From b292a5fc0526e7b5afc10a4ae992f05f1261712e Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 4 Aug 2008 20:54:05 -0700 Subject: [PATCH] Create a branch object to be the argument to the access function. The NetBranch object is connected, but not like an object, so the NetPins object base class is factored out from NetObj to handle the connectivity, and the NetBranch class uses the NetPins to connect a branch. Also, account for the fact that nets with a discipline are by default real-valued. --- cprop.cc | 4 +-- design_dump.cc | 12 +++++++- dup_expr.cc | 2 +- elab_expr.cc | 31 ++++++++++++++++++- elab_sig.cc | 4 +++ ivl_target.h | 1 + link_const.cc | 5 +-- net_event.cc | 2 +- net_expr.cc | 4 +-- net_link.cc | 15 +++++---- net_tran.cc | 8 +++-- netlist.cc | 71 +++++++++++++++++++++++++++++++------------ netlist.h | 69 +++++++++++++++++++++++++++++++---------- pform_disciplines.cc | 1 + t-dll-expr.cc | 12 +++++--- tgt-stub/expression.c | 15 +++++++++ 16 files changed, 199 insertions(+), 57 deletions(-) diff --git a/cprop.cc b/cprop.cc index 9345b9ea8..56e3a7bf7 100644 --- a/cprop.cc +++ b/cprop.cc @@ -897,7 +897,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj) for (Link*clnk = nex->first_nlink() ; clnk ; clnk = clnk->next_nlink()) { - NetObj*cur; + NetPins*cur; unsigned pin; clnk->cur_link(cur, pin); @@ -923,7 +923,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj) for (Link*clnk = nex->first_nlink() ; clnk ; clnk = clnk->next_nlink()) { - NetObj*cur; + NetPins*cur; unsigned pin; clnk->cur_link(cur, pin); diff --git a/design_dump.cc b/design_dump.cc index 98378628f..17c0af847 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -188,6 +188,10 @@ void NetNet::dump_net(ostream&o, unsigned ind) const o << " inout"; break; } + + if (discipline_t*dis = get_discipline()) + o << " discipline=" << dis->name(); + o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")"; if (scope()) o << " scope=" << scope_path(scope()); @@ -237,7 +241,7 @@ void NetNode::dump_node(ostream&o, unsigned ind) const /* This is the generic dumping of all the signals connected to each pin of the object. The "this" object is not printed, only the signals connected to this. */ -void NetObj::dump_node_pins(ostream&o, unsigned ind) const +void NetPins::dump_node_pins(ostream&o, unsigned ind) const { for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { o << setw(ind) << "" << idx << " " << pin(idx).get_name() @@ -1186,6 +1190,12 @@ void NetExpr::dump(ostream&o) const void NetEAccess::dump(ostream&o) const { o << nature_->name() << "." << nature_->access() << "("; + assert(branch_); + if (branch_->pin(0).is_linked()) + o << branch_->pin(0).nexus()->name(); + o << ", "; + if (branch_->pin(1).is_linked()) + o << branch_->pin(1).nexus()->name(); o << ")"; } diff --git a/dup_expr.cc b/dup_expr.cc index 96a721543..ad4bb7b0a 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -25,7 +25,7 @@ NetEAccess* NetEAccess::dup_expr() const { - NetEAccess*tmp = new NetEAccess(nature_); + NetEAccess*tmp = new NetEAccess(branch_, nature_); ivl_assert(*this, tmp); tmp->set_line(*this); return tmp; diff --git a/elab_expr.cc b/elab_expr.cc index 9f3cc228b..b4160e5d8 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -616,7 +616,36 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope, if (nature == 0) return 0; - NetEAccess*tmp = new NetEAccess(nature); + // An access function must have 1 or 2 arguments. + ivl_assert(*this, parms_.size()==2 || parms_.size()==1); + + NetBranch*branch = 0; + + if (parms_.size() == 1) { + PExpr*arg1 = parms_[0]; + PEIdent*arg_ident = dynamic_cast (arg1); + ivl_assert(*this, arg_ident); + + const pform_name_t&path = arg_ident->path(); + ivl_assert(*this, path.size()==1); + perm_string name = peek_tail_name(path); + + NetNet*sig = scope->find_signal(name); + ivl_assert(*this, sig); + + discipline_t*dis = sig->get_discipline(); + ivl_assert(*this, dis); + ivl_assert(*this, nature == dis->potential() || nature == dis->flow()); + + branch = new NetBranch(dis); + branch->set_line(*this); + connect(branch->pin(0), sig->pin(0)); + + } else { + ivl_assert(*this, 0); + } + + NetEAccess*tmp = new NetEAccess(branch, nature); tmp->set_line(*this); return tmp; diff --git a/elab_sig.cc b/elab_sig.cc index 8faa7f2c9..c01fdd81e 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -1029,6 +1029,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const sig->set_signed(get_signed()); sig->set_isint(get_isint()); + if (discipline_t*dis = get_discipline()) { + sig->set_discipline(dis); + } + if (pull) connect(sig->pin(0), pull->pin(0)); diff --git a/ivl_target.h b/ivl_target.h index 7535bd0d4..c019acf04 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -193,6 +193,7 @@ typedef enum ivl_drive_e { typedef enum ivl_expr_type_e { IVL_EX_NONE = 0, IVL_EX_ARRAY = 18, + IVL_EX_BACCESS= 19, IVL_EX_BINARY = 2, IVL_EX_CONCAT = 3, IVL_EX_EVENT = 17, diff --git a/link_const.cc b/link_const.cc index 60b68afa6..212fbf9e7 100644 --- a/link_const.cc +++ b/link_const.cc @@ -60,8 +60,9 @@ bool Nexus::drivers_constant() const if (cur_dir == Link::PASSIVE) { - const NetObj*obj = cur->get_obj(); - if (obj->scope()->parent() != 0) + const NetPins*obj = cur->get_obj(); + const NetObj*as_obj = dynamic_cast(obj); + if (as_obj == 0 || as_obj->scope()->parent() != 0) continue; sig = dynamic_cast(cur->get_obj()); diff --git a/net_event.cc b/net_event.cc index a214cdd48..3535e7ea9 100644 --- a/net_event.cc +++ b/net_event.cc @@ -299,7 +299,7 @@ void NetEvProbe::find_similar_probes(list&plist) Nexus*nex = pin(0).nexus(); for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) { - NetObj*obj = lcur->get_obj(); + NetPins*obj = lcur->get_obj(); if (obj->pin_count() != pin_count()) continue; diff --git a/net_expr.cc b/net_expr.cc index 4d3818099..e749cdca1 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -589,8 +589,8 @@ ivl_variable_type_t NetESFunc::expr_type() const return type_; } -NetEAccess::NetEAccess(nature_t*nat) -: nature_(nat) +NetEAccess::NetEAccess(NetBranch*br, nature_t*nat) +: branch_(br), nature_(nat) { } diff --git a/net_link.cc b/net_link.cc index 228add8c0..9b892a152 100644 --- a/net_link.cc +++ b/net_link.cc @@ -134,13 +134,13 @@ verinum::V Link::get_init() const } -void Link::cur_link(NetObj*&net, unsigned &pin) +void Link::cur_link(NetPins*&net, unsigned &pin) { net = node_; pin = pin_; } -void Link::cur_link(const NetObj*&net, unsigned &pin) const +void Link::cur_link(const NetPins*&net, unsigned &pin) const { net = node_; pin = pin_; @@ -186,12 +186,12 @@ const Link* Link::next_nlink() const return next_; } -const NetObj*Link::get_obj() const +const NetPins*Link::get_obj() const { return node_; } -NetObj*Link::get_obj() +NetPins*Link::get_obj() { return node_; } @@ -253,7 +253,10 @@ void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay) if (cur->get_dir() != Link::OUTPUT) continue; - NetObj*obj = cur->get_obj(); + NetObj*obj = dynamic_cast(cur->get_obj()); + if (obj == 0) + continue; + obj->rise_time(rise); obj->fall_time(fall); obj->decay_time(decay); @@ -397,7 +400,7 @@ const char* Nexus::name() const if (sig == 0) { const Link*lnk = first_nlink(); - const NetObj*obj = lnk->get_obj(); + const NetObj*obj = dynamic_cast(lnk->get_obj()); pin = lnk->get_pin(); cerr << "internal error: No signal for nexus of " << obj->name() << " pin " << pin << "(" << diff --git a/net_tran.cc b/net_tran.cc index b28a28753..42b726307 100644 --- a/net_tran.cc +++ b/net_tran.cc @@ -100,8 +100,12 @@ void join_island(NetObj*obj) Nexus*nex = obj->pin(idx).nexus(); for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) { unsigned pin; - NetObj*tmp; - cur->cur_link(tmp, pin); + NetPins*tmp_pins; + cur->cur_link(tmp_pins, pin); + + NetObj*tmp = dynamic_cast (tmp_pins); + if (tmp == 0) + continue; // Skip self. if (tmp == obj) diff --git a/netlist.cc b/netlist.cc index 51cf898f6..ece7adf45 100644 --- a/netlist.cc +++ b/netlist.cc @@ -91,7 +91,7 @@ unsigned count_inputs(const Link&pin) const Nexus*nex = pin.nexus(); for (const Link*clnk = nex->first_nlink() ; clnk ; clnk = clnk->next_nlink()) { - const NetObj*cur; + const NetPins*cur; unsigned cpin; clnk->cur_link(cur, cpin); if (cur->pin(cpin).get_dir() == Link::INPUT) @@ -108,7 +108,7 @@ unsigned count_outputs(const Link&pin) const Nexus*nex = pin.nexus(); for (const Link*clnk = nex->first_nlink() ; clnk ; clnk = clnk->next_nlink()) { - const NetObj*cur; + const NetPins*cur; unsigned cpin; clnk->cur_link(cur, cpin); if (cur->pin(cpin).get_dir() == Link::OUTPUT) @@ -125,7 +125,7 @@ unsigned count_signals(const Link&pin) const Nexus*nex = pin.nexus(); for (const Link*clnk = nex->first_nlink() ; clnk ; clnk = clnk->next_nlink()) { - const NetObj*cur; + const NetPins*cur; unsigned cpin; clnk->cur_link(cur, cpin); if (dynamic_cast(cur)) @@ -142,7 +142,7 @@ const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx) for (const Link*clnk = nex->first_nlink() ; clnk ; clnk = clnk->next_nlink()) { - const NetObj*cur; + const NetPins*cur; unsigned cpin; clnk->cur_link(cur, cpin); @@ -171,8 +171,8 @@ Link* find_next_output(Link*lnk) return 0; } -NetObj::NetObj(NetScope*s, perm_string n, unsigned np) -: scope_(s), name_(n), npins_(np), delay1_(0), delay2_(0), delay3_(0) +NetPins::NetPins(unsigned npins) +: npins_(npins) { pins_ = new Link[npins_]; for (unsigned idx = 0 ; idx < npins_ ; idx += 1) { @@ -181,22 +181,12 @@ NetObj::NetObj(NetScope*s, perm_string n, unsigned np) } } -NetObj::~NetObj() +NetPins::~NetPins() { delete[]pins_; } -NetScope* NetObj::scope() -{ - return scope_; -} - -const NetScope* NetObj::scope() const -{ - return scope_; -} - -Link& NetObj::pin(unsigned idx) +Link& NetPins::pin(unsigned idx) { if (idx >= npins_) { cerr << get_fileline() << ": internal error: pin("<del_node(this); } +NetBranch::NetBranch(discipline_t*dis) +: NetPins(2), discipline_(dis) +{ + pin(0).set_name(perm_string::literal("A"), 0); + pin(0).set_dir(Link::PASSIVE); + pin(1).set_name(perm_string::literal("B"), 0); + pin(1).set_dir(Link::PASSIVE); +} + +NetBranch::~NetBranch() +{ +} + NetBus::NetBus(NetScope*s, unsigned pin_count) : NetObj(s, perm_string::literal(""), pin_count) { @@ -622,6 +644,17 @@ void NetNet::set_isint(bool flag) isint_ = flag; } +discipline_t* NetNet::get_discipline() const +{ + return discipline_; +} + +void NetNet::set_discipline(discipline_t*dis) +{ + ivl_assert(*this, discipline_ == 0); + discipline_ = dis; +} + long NetNet::lsb() const { return lsb_; diff --git a/netlist.h b/netlist.h index d3af7febd..6a3488b46 100644 --- a/netlist.h +++ b/netlist.h @@ -69,6 +69,7 @@ class NetEvTrig; class NetEvWait; class nature_t; +class discipline_t; struct target; struct functor_t; @@ -77,6 +78,24 @@ ostream& operator << (ostream&o, ivl_variable_type_t val); extern void join_island(NetObj*obj); +class NetPins : public LineInfo { + + public: + explicit NetPins(unsigned npins); + virtual ~NetPins(); + + unsigned pin_count() const { return npins_; } + + Link&pin(unsigned idx); + const Link&pin(unsigned idx) const; + + void dump_node_pins(ostream&, unsigned) const; + + private: + Link*pins_; + const unsigned npins_; +}; + /* ========= * A NetObj is anything that has any kind of behavior in the * netlist. Nodes can be gates, registers, etc. and are linked @@ -97,7 +116,7 @@ extern void join_island(NetObj*obj); * interpretation of the rise/fall/decay times is typically left to * the target to properly interpret. */ -class NetObj : public Attrib, public virtual LineInfo { +class NetObj : public NetPins, public Attrib { public: public: @@ -111,8 +130,6 @@ class NetObj : public Attrib, public virtual LineInfo { perm_string name() const { return name_; } - unsigned pin_count() const { return npins_; } - const NetExpr* rise_time() const { return delay1_; } const NetExpr* fall_time() const { return delay2_; } const NetExpr* decay_time() const { return delay3_; } @@ -121,17 +138,11 @@ class NetObj : public Attrib, public virtual LineInfo { void fall_time(const NetExpr* d) { delay2_ = d; } void decay_time(const NetExpr* d) { delay3_ = d; } - Link&pin(unsigned idx); - const Link&pin(unsigned idx) const; - - void dump_node_pins(ostream&, unsigned) const; void dump_obj_attr(ostream&, unsigned) const; private: NetScope*scope_; perm_string name_; - Link*pins_; - const unsigned npins_; const NetExpr* delay1_; const NetExpr* delay2_; const NetExpr* delay3_; @@ -151,11 +162,31 @@ class IslandBranch { struct ivl_island_s* island; }; +/* + * A NetBranch is a construct of Verilog-A that is a branch between + * two nodes. The branch has exactly 2 pins and a discipline. + * + * pin(0) is the source of flow through a branch and the plus side of + * potential. Pin(1) is the sink of flow and the minus (or ground) of + * potential. + */ +class NetBranch : public NetPins { + + public: + explicit NetBranch(discipline_t*dis); + explicit NetBranch(discipline_t*dis, perm_string name); + ~NetBranch(); + + private: + discipline_t*discipline_; + perm_string name_; +}; + class Link { friend void connect(Link&, Link&); friend void connect(Nexus*, Link&); - friend class NetObj; + friend class NetPins; friend class Nexus; public: @@ -189,8 +220,8 @@ class Link { void set_init(verinum::V val); verinum::V get_init() const; - void cur_link(NetObj*&net, unsigned &pin); - void cur_link(const NetObj*&net, unsigned &pin) const; + void cur_link(NetPins*&net, unsigned &pin); + void cur_link(const NetPins*&net, unsigned &pin) const; // Get a pointer to the nexus that represents all the links // connected to me. @@ -217,8 +248,8 @@ class Link { // Return information about the object that this link is // a part of. - const NetObj*get_obj() const; - NetObj*get_obj(); + const NetPins*get_obj() const; + NetPins*get_obj(); unsigned get_pin() const; // A link of an object (sometimes called a "pin") has a @@ -231,7 +262,7 @@ class Link { private: // The NetNode manages these. They point back to the // NetNode so that following the links can get me here. - NetObj *node_; + NetPins *node_; unsigned pin_; DIR dir_; @@ -521,6 +552,10 @@ class NetNet : public NetObj { bool get_isint() const; void set_isint(bool); + /* Attach a discipline to the net. */ + discipline_t* get_discipline() const; + void set_discipline(discipline_t*dis); + /* These methods return the msb and lsb indices for the most significant and least significant bits. These are signed longs, and may be different from pin numbers. For example, @@ -588,6 +623,7 @@ class NetNet : public NetObj { ivl_variable_type_t data_type_; bool signed_; bool isint_; // original type of integer + discipline_t*discipline_; long msb_, lsb_; const unsigned dimensions_; @@ -2880,7 +2916,7 @@ class NetEUFunc : public NetExpr { class NetEAccess : public NetExpr { public: - explicit NetEAccess(nature_t*nat); + explicit NetEAccess(NetBranch*br, nature_t*nat); ~NetEAccess(); virtual ivl_variable_type_t expr_type() const; @@ -2891,6 +2927,7 @@ class NetEAccess : public NetExpr { virtual NexusSet* nex_input(bool rem_out = true); private: + NetBranch*branch_; nature_t*nature_; }; diff --git a/pform_disciplines.cc b/pform_disciplines.cc index cca4cc0ac..2ce7aeedd 100644 --- a/pform_disciplines.cc +++ b/pform_disciplines.cc @@ -205,6 +205,7 @@ void pform_attach_discipline(const struct vlltype&loc, error_count += 1; } else { + cur_net->set_data_type(IVL_VT_REAL); cur_net->set_discipline(discipline); } } diff --git a/t-dll-expr.cc b/t-dll-expr.cc index 51f9d4ea9..cbba20ded 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -152,10 +152,14 @@ ivl_expr_t dll_target::expr_from_value_(const verinum&val) 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; - + // Make a stub Branch Access Function expression node. + expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); + expr_->type_ = IVL_EX_BACCESS; + expr_->value_ = IVL_VT_REAL; + expr_->file = net->get_file(); + expr_->lineno = net->get_lineno(); + expr_->width_ = 1; + expr_->signed_= 1; } void dll_target::expr_binary(const NetEBinary*net) diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index 791b14b75..98092d127 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -43,6 +43,17 @@ static void show_array_expression(ivl_expr_t net, unsigned ind) ivl_signal_dimensions(sig), width, vt); } +static void show_branch_access_expression(ivl_expr_t net, unsigned ind) +{ + fprintf(out, "%*s\n", ind, ""); + + if (ivl_expr_value(net) != IVL_VT_REAL) { + fprintf(out, "%*sERROR: Expecting type IVL_VT_REAL, got %s\n", + ind, "", vt_type_string(net)); + stub_errors += 1; + } +} + static void show_binary_expression(ivl_expr_t net, unsigned ind) { unsigned width = ivl_expr_width(net); @@ -216,6 +227,10 @@ void show_expression(ivl_expr_t net, unsigned ind) show_array_expression(net, ind); break; + case IVL_EX_BACCESS: + show_branch_access_expression(net, ind); + break; + case IVL_EX_BINARY: show_binary_expression(net, ind); break;