Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
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...
commit 9f04641fc780e4856fc0faa8ec977970e1b70b88 1 parent 25a27f9
@steveicarus authored
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)) {
Please sign in to comment.
Something went wrong with that request. Please try again.