Skip to content

Commit

Permalink
Detect and elaborate AMS access functions.
Browse files Browse the repository at this point in the history
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
steveicarus committed Jul 31, 2008
1 parent 25a27f9 commit 9f04641
Show file tree
Hide file tree
Showing 16 changed files with 161 additions and 16 deletions.
1 change: 1 addition & 0 deletions PExpr.h
Expand Up @@ -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,
Expand Down
7 changes: 7 additions & 0 deletions design_dump.cc
Expand Up @@ -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)
Expand Down Expand Up @@ -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') {
Expand Down
2 changes: 2 additions & 0 deletions discipline.h
Expand Up @@ -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
9 changes: 9 additions & 0 deletions dup_expr.cc
Expand Up @@ -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
{
Expand Down
31 changes: 29 additions & 2 deletions elab_expr.cc
Expand Up @@ -25,6 +25,7 @@

# include "pform.h"
# include "netlist.h"
# include "discipline.h"
# include "netmisc.h"
# include "util.h"
# include "ivl_assert.h"
Expand Down Expand Up @@ -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
{
Expand All @@ -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;
Expand Down
8 changes: 6 additions & 2 deletions emit.cc
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions net_expr.cc
Expand Up @@ -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;
}
5 changes: 5 additions & 0 deletions net_nex_input.cc
Expand Up @@ -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.
*/
Expand Down
21 changes: 21 additions & 0 deletions netlist.h
Expand Up @@ -68,6 +68,7 @@ class NetTaskDef;
class NetEvTrig;
class NetEvWait;

class nature_t;

struct target;
struct functor_t;
Expand Down Expand Up @@ -2873,6 +2874,26 @@ class NetEUFunc : public NetExpr {
NetEUFunc& operator= (const NetEUFunc&);
};

/*
* 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
Expand Down
18 changes: 17 additions & 1 deletion pform_disciplines.cc
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
9 changes: 9 additions & 0 deletions t-dll-expr.cc
Expand Up @@ -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);
Expand Down
20 changes: 14 additions & 6 deletions t-dll-proc.cc
Expand Up @@ -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));

Expand Down Expand Up @@ -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_;
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -214,6 +216,8 @@ void dll_target::proc_assign(const NetAssign*net)
stmt_cur_->u_.assign_.delay = expr_;
expr_ = 0;
}

return true;
}


Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion t-dll.h
Expand Up @@ -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*);
Expand All @@ -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*);
Expand Down
9 changes: 8 additions & 1 deletion target.cc
Expand Up @@ -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*)
Expand Down Expand Up @@ -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() << "): "
Expand Down
3 changes: 2 additions & 1 deletion target.h
Expand Up @@ -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*);
Expand Down Expand Up @@ -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*);
Expand Down

0 comments on commit 9f04641

Please sign in to comment.