Skip to content
Browse files

Detect and elaborate AMS access functions.

Detect function call expressions that turn out to be calls to the
access function of a nature. Elaborate the access function and stub
the emit code. This gets the access function just short of the code
generator.
  • Loading branch information...
1 parent 25a27f9 commit 9f04641fc780e4856fc0faa8ec977970e1b70b88 @steveicarus committed Jul 30, 2008
Showing with 161 additions and 16 deletions.
  1. +1 −0 PExpr.h
  2. +7 −0 design_dump.cc
  3. +2 −0 discipline.h
  4. +9 −0 dup_expr.cc
  5. +29 −2 elab_expr.cc
  6. +6 −2 emit.cc
  7. +14 −0 net_expr.cc
  8. +5 −0 net_nex_input.cc
  9. +21 −0 netlist.h
  10. +17 −1 pform_disciplines.cc
  11. +9 −0 t-dll-expr.cc
  12. +14 −6 t-dll-proc.cc
  13. +2 −1 t-dll.h
  14. +8 −1 target.cc
  15. +2 −1 target.h
  16. +15 −2 tgt-stub/expression.c
View
1 PExpr.h
@@ -731,6 +731,7 @@ class PECallFunction : public PExpr {
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope, int expr_wid) const;
+ NetExpr* elaborate_access_func_(Design*des, NetScope*scope, int expr_wid) const;
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
View
7 design_dump.cc
@@ -27,6 +27,7 @@
# include <iomanip>
# include "netlist.h"
# include "compiler.h"
+# include "discipline.h"
# include "ivl_assert.h"
static ostream& operator<< (ostream&o, NetBlock::Type t)
@@ -1182,6 +1183,12 @@ void NetExpr::dump(ostream&o) const
o << "(?" << typeid(*this).name() << "?)";
}
+void NetEAccess::dump(ostream&o) const
+{
+ o << nature_->name() << "." << nature_->access() << "(";
+ o << ")";
+}
+
void NetEBinary::dump(ostream&o) const
{
if (op_ == 'm' || op_ == 'M') {
View
2 discipline.h
@@ -71,5 +71,7 @@ class discipline_t : public LineInfo {
extern map<perm_string,nature_t*> natures;
extern map<perm_string,discipline_t*> disciplines;
+ // Map access function name to the nature that it accesses.
+extern map<perm_string,nature_t*> access_function_nature;
#endif
View
9 dup_expr.cc
@@ -21,6 +21,15 @@
# include "netlist.h"
# include <cassert>
+# include "ivl_assert.h"
+
+NetEAccess* NetEAccess::dup_expr() const
+{
+ NetEAccess*tmp = new NetEAccess(nature_);
+ ivl_assert(*this, tmp);
+ tmp->set_line(*this);
+ return tmp;
+}
NetEBComp* NetEBComp::dup_expr() const
{
View
31 elab_expr.cc
@@ -25,6 +25,7 @@
# include "pform.h"
# include "netlist.h"
+# include "discipline.h"
# include "netmisc.h"
# include "util.h"
# include "ivl_assert.h"
@@ -601,6 +602,26 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
return fun;
}
+NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
+ int expr_wid) const
+{
+ // Hierarchical names cannot be access functions.
+ if (path_.size() != 1)
+ return 0;
+
+ perm_string access_name = peek_tail_name(path_);
+ nature_t*nature = access_function_nature[access_name];
+
+ // If the name doesn't match any access functions, then give up.
+ if (nature == 0)
+ return 0;
+
+ NetEAccess*tmp = new NetEAccess(nature);
+ tmp->set_line(*this);
+
+ return tmp;
+}
+
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool) const
{
@@ -609,15 +630,21 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
NetFuncDef*def = des->find_function(scope, path_);
if (def == 0) {
+ // Not a user defined function. Maybe it is an access
+ // function for a nature? If so then elaborate it that way.
+ NetExpr*tmp = elaborate_access_func_(des, scope, expr_wid);
+ if (tmp != 0)
+ return tmp;
+
cerr << get_fileline() << ": error: No function " << path_ <<
" in this context (" << scope_path(scope) << ")." << endl;
des->errors += 1;
return 0;
}
- assert(def);
+ ivl_assert(*this, def);
NetScope*dscope = def->scope();
- assert(dscope);
+ ivl_assert(*this, dscope);
if (! check_call_matches_definition_(des, dscope))
return 0;
View
8 emit.cc
@@ -198,8 +198,7 @@ bool NetProc::emit_proc(struct target_t*tgt) const
bool NetAssign::emit_proc(struct target_t*tgt) const
{
- tgt->proc_assign(this);
- return true;
+ return tgt->proc_assign(this);
}
bool NetAssignNB::emit_proc(struct target_t*tgt) const
@@ -461,6 +460,11 @@ int Design::emit(struct target_t*tgt) const
return rc;
}
+void NetEAccess::expr_scan(struct expr_scan_t*tgt) const
+{
+ tgt->expr_access_func(this);
+}
+
void NetEBinary::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_binary(this);
View
14 net_expr.cc
@@ -588,3 +588,17 @@ ivl_variable_type_t NetESFunc::expr_type() const
{
return type_;
}
+
+NetEAccess::NetEAccess(nature_t*nat)
+: nature_(nat)
+{
+}
+
+NetEAccess::~NetEAccess()
+{
+}
+
+ivl_variable_type_t NetEAccess::expr_type() const
+{
+ return IVL_VT_REAL;
+}
View
5 net_nex_input.cc
@@ -62,6 +62,11 @@ NexusSet* NetEConcat::nex_input(bool rem_out)
return result;
}
+NexusSet* NetEAccess::nex_input(bool rem_out)
+{
+ return new NexusSet;
+}
+
/*
* A constant has not inputs, so always return an empty set.
*/
View
21 netlist.h
@@ -68,6 +68,7 @@ class NetTaskDef;
class NetEvTrig;
class NetEvWait;
+class nature_t;
struct target;
struct functor_t;
@@ -2874,6 +2875,26 @@ class NetEUFunc : public NetExpr {
};
/*
+ * A call to a nature access function for a branch.
+ */
+class NetEAccess : public NetExpr {
+
+ public:
+ explicit NetEAccess(nature_t*nat);
+ ~NetEAccess();
+
+ virtual ivl_variable_type_t expr_type() const;
+ virtual void dump(ostream&) const;
+
+ virtual void expr_scan(struct expr_scan_t*) const;
+ virtual NetEAccess*dup_expr() const;
+ virtual NexusSet* nex_input(bool rem_out = true);
+
+ private:
+ nature_t*nature_;
+};
+
+/*
* A call to a user defined task is elaborated into this object. This
* contains a pointer to the elaborated task definition, but is a
* NetProc object so that it can be linked into statements.
View
18 pform_disciplines.cc
@@ -25,6 +25,7 @@
map<perm_string,nature_t*> natures;
map<perm_string,discipline_t*> disciplines;
+map<perm_string,nature_t*> access_function_nature;
static perm_string nature_name = perm_string::perm_string();
static perm_string nature_access = perm_string::perm_string();
@@ -62,9 +63,24 @@ void pform_end_nature(const struct vlltype&loc)
}
nature_t*tmp = new nature_t(nature_name, nature_access);
+ FILE_NAME(tmp, loc);
+
natures[nature_name] = tmp;
- FILE_NAME(tmp, loc);
+ // Make sure the access function is not used by multiple
+ // different natures.
+ if (nature_t*dup_access_nat = access_function_nature[nature_access]) {
+ cerr << tmp->get_fileline() << ": error: "
+ << "Access function name " << nature_access
+ << " is already used by nature " << dup_access_nat->name()
+ << " declared at " << dup_access_nat->get_fileline()
+ << "." << endl;
+ error_count += 1;
+ }
+
+ // Map the access functio back to the nature so that
+ // expressions that use the access function can find it.
+ access_function_nature[nature_access] = tmp;
nature_name = perm_string::perm_string();
nature_access = perm_string::perm_string();
View
9 t-dll-expr.cc
@@ -149,6 +149,15 @@ ivl_expr_t dll_target::expr_from_value_(const verinum&val)
return expr;
}
+void dll_target::expr_access_func(const NetEAccess*net)
+{
+ assert(expr_ == 0);
+
+ cerr << net->get_fileline() << ": internal error: "
+ << "Nature access functions not implemented yet." << endl;
+
+}
+
void dll_target::expr_binary(const NetEBinary*net)
{
assert(expr_ == 0);
View
20 t-dll-proc.cc
@@ -37,6 +37,8 @@
bool dll_target::process(const NetProcTop*net)
{
+ bool rc_flag = true;
+
ivl_process_t obj = (struct ivl_process_s*)
calloc(1, sizeof(struct ivl_process_s));
@@ -70,7 +72,7 @@ bool dll_target::process(const NetProcTop*net)
assert(stmt_cur_ == 0);
stmt_cur_ = (struct ivl_statement_s*)calloc(1, sizeof*stmt_cur_);
assert(stmt_cur_);
- net->statement()->emit_proc(this);
+ rc_flag = net->statement()->emit_proc(this) && rc_flag;
assert(stmt_cur_);
obj->stmt_ = stmt_cur_;
@@ -80,7 +82,7 @@ bool dll_target::process(const NetProcTop*net)
obj->next_ = des_.threads_;
des_.threads_ = obj;
- return true;
+ return rc_flag;
}
void dll_target::task_def(const NetScope*net)
@@ -190,7 +192,7 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
/*
*/
-void dll_target::proc_assign(const NetAssign*net)
+bool dll_target::proc_assign(const NetAssign*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
@@ -214,6 +216,8 @@ void dll_target::proc_assign(const NetAssign*net)
stmt_cur_->u_.assign_.delay = expr_;
expr_ = 0;
}
+
+ return true;
}
@@ -399,6 +403,8 @@ bool dll_target::proc_cassign(const NetCAssign*net)
bool dll_target::proc_condit(const NetCondit*net)
{
+ bool rc_flag = true;
+
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
FILE_NAME(stmt_cur_, net);
@@ -410,18 +416,20 @@ bool dll_target::proc_condit(const NetCondit*net)
assert(expr_ == 0);
net->expr()->expr_scan(this);
stmt_cur_->u_.condit_.cond_ = expr_;
+ if (expr_ == 0)
+ rc_flag = false;
expr_ = 0;
ivl_statement_t save_cur_ = stmt_cur_;
stmt_cur_ = save_cur_->u_.condit_.stmt_+0;
- bool flag = net->emit_recurse_if(this);
+ rc_flag = net->emit_recurse_if(this) && rc_flag;
stmt_cur_ = save_cur_->u_.condit_.stmt_+1;
- flag = flag && net->emit_recurse_else(this);
+ rc_flag = net->emit_recurse_else(this) && rc_flag;
stmt_cur_ = save_cur_;
- return flag;
+ return rc_flag;
}
bool dll_target::proc_deassign(const NetDeassign*net)
View
3 t-dll.h
@@ -111,7 +111,7 @@ struct dll_target : public target_t, public expr_scan_t {
/* These methods and members are used for forming the
statements of a thread. */
struct ivl_statement_s*stmt_cur_;
- void proc_assign(const NetAssign*);
+ bool proc_assign(const NetAssign*);
void proc_assign_nb(const NetAssignNB*);
bool proc_block(const NetBlock*);
void proc_case(const NetCase*);
@@ -134,6 +134,7 @@ struct dll_target : public target_t, public expr_scan_t {
void task_def(const NetScope*);
struct ivl_expr_s*expr_;
+ void expr_access_func(const NetEAccess*);
void expr_binary(const NetEBinary*);
void expr_concat(const NetEConcat*);
void expr_const(const NetEConst*);
View
9 target.cc
@@ -243,10 +243,11 @@ bool target_t::process(const NetProcTop*top)
return top->statement()->emit_proc(this);
}
-void target_t::proc_assign(const NetAssign*)
+bool target_t::proc_assign(const NetAssign*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled procedural assignment." << endl;
+ return false;
}
void target_t::proc_assign_nb(const NetAssignNB*)
@@ -377,6 +378,12 @@ expr_scan_t::~expr_scan_t()
{
}
+void expr_scan_t::expr_access_func(const NetEAccess*)
+{
+ cerr << "expr_scan_t (" << typeid(*this).name() << "): "
+ "unhandled expr_access_func." << endl;
+}
+
void expr_scan_t::expr_const(const NetEConst*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
View
3 target.h
@@ -105,7 +105,7 @@ struct target_t {
virtual bool process(const NetProcTop*);
/* Various kinds of process nodes are dispatched through these. */
- virtual void proc_assign(const NetAssign*);
+ virtual bool proc_assign(const NetAssign*);
virtual void proc_assign_nb(const NetAssignNB*);
virtual bool proc_block(const NetBlock*);
virtual void proc_case(const NetCase*);
@@ -133,6 +133,7 @@ struct target_t {
of expressions. */
struct expr_scan_t {
virtual ~expr_scan_t();
+ virtual void expr_access_func(const NetEAccess*);
virtual void expr_const(const NetEConst*);
virtual void expr_param(const NetEConstParam*);
virtual void expr_rparam(const NetECRealParam*);
View
17 tgt-stub/expression.c
@@ -49,10 +49,23 @@ static void show_binary_expression(ivl_expr_t net, unsigned ind)
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*vt = vt_type_string(net);
+ ivl_expr_t oper1 = ivl_expr_oper1(net);
+ ivl_expr_t oper2 = ivl_expr_oper2(net);
+
fprintf(out, "%*s<\"%c\" width=%u, %s, type=%s>\n", ind, "",
ivl_expr_opcode(net), width, sign, vt);
- show_expression(ivl_expr_oper1(net), ind+3);
- show_expression(ivl_expr_oper2(net), ind+3);
+ if (oper1) {
+ show_expression(oper1, ind+3);
+ } else {
+ fprintf(out, "%*sERROR: Missing operand 1\n", ind+3, "");
+ stub_errors += 1;
+ }
+ if (oper2) {
+ show_expression(oper2, ind+3);
+ } else {
+ fprintf(out, "%*sERROR: Missing operand 2\n", ind+3, "");
+ stub_errors += 1;
+ }
switch (ivl_expr_opcode(net)) {

0 comments on commit 9f04641

Please sign in to comment.
Something went wrong with that request. Please try again.