diff --git a/design_dump.cc b/design_dump.cc index a86ab1540..edd8b65d9 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -138,9 +138,13 @@ ostream& operator <<(ostream&o, struct __ScopePathManip marg) void NetBranch::dump(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "branch ..."; - o << " island=" << get_island(); + static const char*pin_names[2] = { + "terminal0", + "terminal1" }; + + o << setw(ind) << "" << "branch island=" << get_island(); o << " // " << get_fileline() << endl; + dump_node_pins(o, ind+4, pin_names); } void NetDelaySrc::dump(ostream&o, unsigned ind) const diff --git a/elab_expr.cc b/elab_expr.cc index ca4201869..e34f9ba1d 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1253,8 +1253,12 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope, branch = new NetBranch(dis); branch->set_line(*this); - des->add_branch(branch); connect(branch->pin(0), sig->pin(0)); + + NetNet*gnd = des->find_discipline_reference(dis, scope); + connect(branch->pin(1), gnd->pin(0)); + + des->add_branch(branch); join_island(branch); } else { @@ -3043,3 +3047,24 @@ NetExpr* PEUnary::elaborate_expr_bits_(NetExpr*operand, int expr_wid) const tmp->set_line(*this); return tmp; } + +NetNet* Design::find_discipline_reference(ivl_discipline_t dis, NetScope*scope) +{ + NetNet*gnd = discipline_references_[dis->name()]; + + if (gnd) return gnd; + + string name = string(dis->name()) + "$gnd"; + gnd = new NetNet(scope, lex_strings.make(name), NetNet::WIRE, 1); + gnd->set_discipline(dis); + gnd->data_type(IVL_VT_REAL); + discipline_references_[dis->name()] = gnd; + + if (debug_elaborate) + cerr << gnd->get_fileline() << ": debug: " + << "Create an implicit reference terminal" + << " for discipline=" << dis->name() + << " in scope=" << scope_path(scope) << endl; + + return gnd; +} diff --git a/ivl.def b/ivl.def index 890876bc0..dbdbfde34 100644 --- a/ivl.def +++ b/ivl.def @@ -116,6 +116,7 @@ ivl_nexus_ptrs ivl_nexus_ptr ivl_nexus_set_private +ivl_nexus_ptr_branch ivl_nexus_ptr_con ivl_nexus_ptr_drive0 ivl_nexus_ptr_drive1 diff --git a/ivl_target.h b/ivl_target.h index f39b51d87..1a0df2bd1 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -60,6 +60,9 @@ _BEGIN_DECL * This object represent an array that can be a memory or a net * array. (They are the same from the perspective of ivl_target.h.) * + * ivl_branch_t + * this object represents an analog branch. + * * ivl_design_t * This object represents the entire elaborated design. Various * global properties and methods are available from this. @@ -149,6 +152,7 @@ _BEGIN_DECL * throughout the design. */ typedef struct ivl_array_s *ivl_array_t; +typedef struct ivl_branch_s *ivl_branch_t; typedef struct ivl_delaypath_s*ivl_delaypath_t; typedef struct ivl_design_s *ivl_design_t; typedef struct ivl_discipline_s*ivl_discipline_t; @@ -416,6 +420,12 @@ struct ivl_attribute_s { }; typedef const struct ivl_attribute_s*ivl_attribute_t; +/* BRANCH +*/ +extern ivl_discipline_t ivl_branch_discipline(ivl_branch_t obj); +extern ivl_scope_t ivl_branch_scope(ivl_branch_t obj); +extern ivl_nexus_t ivl_branch_terminal(ivl_branch_t obj, int idx); + /* DELAYPATH * Delaypath objects represent delay paths called out by a specify * block in the Verilog source file. The destination signal references @@ -1383,6 +1393,7 @@ extern void* ivl_nexus_get_private(ivl_nexus_t net); extern ivl_drive_t ivl_nexus_ptr_drive0(ivl_nexus_ptr_t net); extern ivl_drive_t ivl_nexus_ptr_drive1(ivl_nexus_ptr_t net); extern unsigned ivl_nexus_ptr_pin(ivl_nexus_ptr_t net); +extern ivl_branch_t ivl_nexus_ptr_branch(ivl_nexus_ptr_t net); extern ivl_net_const_t ivl_nexus_ptr_con(ivl_nexus_ptr_t net); extern ivl_net_logic_t ivl_nexus_ptr_log(ivl_nexus_ptr_t net); extern ivl_lpm_t ivl_nexus_ptr_lpm(ivl_nexus_ptr_t net); diff --git a/ivl_target_priv.h b/ivl_target_priv.h index eae6f3970..d42e386d7 100644 --- a/ivl_target_priv.h +++ b/ivl_target_priv.h @@ -22,11 +22,20 @@ # include /* -* This deader has declarations related to the ivl_target.h API that +* This header has declarations related to the ivl_target.h API that * are not to be exported outside of the core via the ivl_target.h * interface. +* +* (NOTE: A lot of similar definitions exist in the t-dll.h header +* file. That is a legacy from an earlier time before the +* ivl_target_priv.h header file was started, and those definitions +* should gradually be moved over to this header file.) */ +struct ivl_branch_s { + ivl_nexus_t pins[2]; +}; + /* * Information about islands. Connected branches within a net are * collected into islands. Branches that are purely ddiscrete do not diff --git a/net_design.cc b/net_design.cc index 29835c15f..3d7e2f275 100644 --- a/net_design.cc +++ b/net_design.cc @@ -36,7 +36,7 @@ # include "ivl_assert.h" Design:: Design() - : errors(0), nodes_(0), procs_(0), aprocs_(0), lcounter_(0) + : errors(0), nodes_(0), procs_(0), aprocs_(0) { branches_ = 0; procs_idx_ = 0; @@ -49,15 +49,6 @@ Design::~Design() { } -string Design::local_symbol(const string&path) -{ - ostringstream res; - res << path << "." << "_L" << lcounter_; - lcounter_ += 1; - - return res.str(); -} - void Design::set_precision(int val) { if (val < des_precision_) diff --git a/netlist.h b/netlist.h index 2b2e81cb0..fa6bc34f3 100644 --- a/netlist.h +++ b/netlist.h @@ -3886,6 +3886,8 @@ class Design { void delete_process(NetProcTop*); bool check_always_delay() const; + NetNet* find_discipline_reference(ivl_discipline_t dis, NetScope*scope); + // Iterate over the design... void dump(ostream&) const; void functor(struct functor_t*); @@ -3896,9 +3898,6 @@ class Design { // detected. It prevents code being emitted. unsigned errors; - public: - string local_symbol(const string&path); - private: // Keep a tree of scopes. The NetScope class handles the wide // tree and per-hop searches for me. @@ -3917,14 +3916,17 @@ class Design { NetProcTop*procs_; NetProcTop*procs_idx_; + // List the ANALOG processes in the design. NetAnalogTop*aprocs_; + // Map of discipline take to NetNet for the reference node. + mapdiscipline_references_; + + // Map the design arguments to values. map flags_; int des_precision_; - unsigned lcounter_; - private: // not implemented Design(const Design&); Design& operator= (const Design&); diff --git a/t-dll-api.cc b/t-dll-api.cc index c8f4e9f0e..e088217b7 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1318,14 +1318,14 @@ extern "C" void ivl_nexus_set_private(ivl_nexus_t net, void*data) extern "C" unsigned ivl_nexus_ptrs(ivl_nexus_t net) { assert(net); - return net->nptr_; + return net->ptrs_.size(); } extern "C" ivl_nexus_ptr_t ivl_nexus_ptr(ivl_nexus_t net, unsigned idx) { assert(net); - assert(idx < net->nptr_); - return net->ptrs_ + idx; + assert(idx < net->ptrs_.size()); + return & net->ptrs_[idx]; } extern "C" ivl_drive_t ivl_nexus_ptr_drive0(ivl_nexus_ptr_t net) @@ -1346,6 +1346,15 @@ extern "C" unsigned ivl_nexus_ptr_pin(ivl_nexus_ptr_t net) return net->pin_; } +extern "C" ivl_branch_t ivl_nexus_ptr_branch(ivl_nexus_ptr_t net) +{ + if (net == 0) + return 0; + if (net->type_ != __NEXUS_PTR_BRA) + return 0; + return net->l.bra; +} + extern "C" ivl_net_const_t ivl_nexus_ptr_con(ivl_nexus_ptr_t net) { if (net == 0) diff --git a/t-dll.cc b/t-dll.cc index e0d59eded..e08eb7891 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -128,6 +128,11 @@ void* ivl_nexus_s::operator new(size_t s) return tmp; } +void ivl_nexus_s::operator delete(void*, size_t) +{ + assert(0); +} + inline static const char *basename(ivl_scope_t scope, const char *inst) { inst += strlen(ivl_scope_name(scope)); @@ -281,10 +286,7 @@ ivl_signal_t dll_target::find_signal(ivl_design_s &des, const NetNet*net) static ivl_nexus_t nexus_sig_make(ivl_signal_t net, unsigned pin) { ivl_nexus_t tmp = new struct ivl_nexus_s; - tmp->private_data = 0; - tmp->nptr_ = 1; - tmp->ptrs_ = (struct ivl_nexus_ptr_s*) - malloc(sizeof(struct ivl_nexus_ptr_s)); + tmp->ptrs_.resize(1); tmp->ptrs_[0].pin_ = pin; tmp->ptrs_[0].type_ = __NEXUS_PTR_SIG; tmp->ptrs_[0].l.sig = net; @@ -305,11 +307,8 @@ static ivl_nexus_t nexus_sig_make(ivl_signal_t net, unsigned pin) static void nexus_sig_add(ivl_nexus_t nex, ivl_signal_t net, unsigned pin) { - unsigned top = nex->nptr_ + 1; - nex->ptrs_ = (struct ivl_nexus_ptr_s*) - realloc(nex->ptrs_, top * sizeof(struct ivl_nexus_ptr_s)); - nex->nptr_ = top; - + unsigned top = nex->ptrs_.size(); + nex->ptrs_.resize(top+1); ivl_drive_t drive = IVL_DR_HiZ; switch (ivl_signal_type(net)) { case IVL_SIT_REG: @@ -319,11 +318,22 @@ static void nexus_sig_add(ivl_nexus_t nex, ivl_signal_t net, unsigned pin) break; } - nex->ptrs_[top-1].type_= __NEXUS_PTR_SIG; - nex->ptrs_[top-1].drive0 = drive; - nex->ptrs_[top-1].drive1 = drive; - nex->ptrs_[top-1].pin_ = pin; - nex->ptrs_[top-1].l.sig= net; + nex->ptrs_[top].type_= __NEXUS_PTR_SIG; + nex->ptrs_[top].drive0 = drive; + nex->ptrs_[top].drive1 = drive; + nex->ptrs_[top].pin_ = pin; + nex->ptrs_[top].l.sig= net; +} + +static void nexus_bra_add(ivl_nexus_t nex, ivl_branch_t net, unsigned pin) +{ + unsigned top = nex->ptrs_.size(); + nex->ptrs_.resize(top+1); + nex->ptrs_[top].type_= __NEXUS_PTR_BRA; + nex->ptrs_[top].drive0 = 0; + nex->ptrs_[top].drive1 = 0; + nex->ptrs_[top].pin_ = pin; + nex->ptrs_[top].l.bra= net; } /* @@ -337,62 +347,54 @@ static ivl_nexus_ptr_t nexus_log_add(ivl_nexus_t nex, ivl_net_logic_t net, unsigned pin) { - unsigned top = nex->nptr_ + 1; - nex->ptrs_ = (struct ivl_nexus_ptr_s*) - realloc(nex->ptrs_, top * sizeof(struct ivl_nexus_ptr_s)); - nex->nptr_ = top; + unsigned top = nex->ptrs_.size(); + nex->ptrs_.resize(top+1); - nex->ptrs_[top-1].type_= __NEXUS_PTR_LOG; - nex->ptrs_[top-1].drive0 = (pin == 0)? IVL_DR_STRONG : IVL_DR_HiZ; - nex->ptrs_[top-1].drive1 = (pin == 0)? IVL_DR_STRONG : IVL_DR_HiZ; - nex->ptrs_[top-1].pin_ = pin; - nex->ptrs_[top-1].l.log= net; + nex->ptrs_[top].type_= __NEXUS_PTR_LOG; + nex->ptrs_[top].drive0 = (pin == 0)? IVL_DR_STRONG : IVL_DR_HiZ; + nex->ptrs_[top].drive1 = (pin == 0)? IVL_DR_STRONG : IVL_DR_HiZ; + nex->ptrs_[top].pin_ = pin; + nex->ptrs_[top].l.log= net; - return nex->ptrs_ + top - 1; + return & (nex->ptrs_[top]); } static void nexus_con_add(ivl_nexus_t nex, ivl_net_const_t net, unsigned pin, ivl_drive_t drive0, ivl_drive_t drive1) { - unsigned top = nex->nptr_ + 1; - nex->ptrs_ = (struct ivl_nexus_ptr_s*) - realloc(nex->ptrs_, top * sizeof(struct ivl_nexus_ptr_s)); - nex->nptr_ = top; + unsigned top = nex->ptrs_.size(); + nex->ptrs_.resize(top+1); - nex->ptrs_[top-1].type_= __NEXUS_PTR_CON; - nex->ptrs_[top-1].drive0 = drive0; - nex->ptrs_[top-1].drive1 = drive1; - nex->ptrs_[top-1].pin_ = pin; - nex->ptrs_[top-1].l.con= net; + nex->ptrs_[top].type_= __NEXUS_PTR_CON; + nex->ptrs_[top].drive0 = drive0; + nex->ptrs_[top].drive1 = drive1; + nex->ptrs_[top].pin_ = pin; + nex->ptrs_[top].l.con= net; } static void nexus_lpm_add(ivl_nexus_t nex, ivl_lpm_t net, unsigned pin, ivl_drive_t drive0, ivl_drive_t drive1) { - unsigned top = nex->nptr_ + 1; - nex->ptrs_ = (struct ivl_nexus_ptr_s*) - realloc(nex->ptrs_, top * sizeof(struct ivl_nexus_ptr_s)); - nex->nptr_ = top; + unsigned top = nex->ptrs_.size(); + nex->ptrs_.resize(top+1); - nex->ptrs_[top-1].type_= __NEXUS_PTR_LPM; - nex->ptrs_[top-1].drive0 = drive0; - nex->ptrs_[top-1].drive1 = drive0; - nex->ptrs_[top-1].pin_ = pin; - nex->ptrs_[top-1].l.lpm= net; + nex->ptrs_[top].type_= __NEXUS_PTR_LPM; + nex->ptrs_[top].drive0 = drive0; + nex->ptrs_[top].drive1 = drive0; + nex->ptrs_[top].pin_ = pin; + nex->ptrs_[top].l.lpm= net; } static void nexus_switch_add(ivl_nexus_t nex, ivl_switch_t net, unsigned pin) { - unsigned top = nex->nptr_ + 1; - nex->ptrs_ = (struct ivl_nexus_ptr_s*) - realloc(nex->ptrs_, top*sizeof(struct ivl_nexus_ptr_s)); - nex->nptr_ = top; + unsigned top = nex->ptrs_.size(); + nex->ptrs_.resize(top+1); - nex->ptrs_[top-1].type_= __NEXUS_PTR_SWI; - nex->ptrs_[top-1].drive0 = IVL_DR_HiZ; - nex->ptrs_[top-1].drive1 = IVL_DR_HiZ; - nex->ptrs_[top-1].pin_ = pin; - nex->ptrs_[top-1].l.swi= net; + nex->ptrs_[top].type_= __NEXUS_PTR_SWI; + nex->ptrs_[top].drive0 = IVL_DR_HiZ; + nex->ptrs_[top].drive1 = IVL_DR_HiZ; + nex->ptrs_[top].pin_ = pin; + nex->ptrs_[top].l.swi= net; } void scope_add_logic(ivl_scope_t scope, ivl_net_logic_t net) @@ -776,6 +778,22 @@ void dll_target::make_const_delays_(struct ivl_net_const_s*obj, } } +bool dll_target::branch(const NetBranch*net) +{ + struct ivl_branch_s*obj = new struct ivl_branch_s; + ivl_assert(*net, net->pin_count() == 2); + + assert(net->pin(0).nexus()->t_cookie()); + obj->pins[0] = net->pin(0).nexus()->t_cookie(); + nexus_bra_add(obj->pins[0], obj, 0); + + assert(net->pin(1).nexus()->t_cookie()); + obj->pins[1] = net->pin(1).nexus()->t_cookie(); + nexus_bra_add(obj->pins[1], obj, 1); + + return true; +} + /* * Add a bufz object to the scope that contains it. * @@ -2504,6 +2522,7 @@ void dll_target::signal(const NetNet*net) for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) { const Nexus*nex = net->pin(idx).nexus(); + ivl_assert(*net, nex); if (nex->t_cookie()) { if (obj->array_words > 1) { obj->pins[idx] = nex->t_cookie(); @@ -2522,6 +2541,7 @@ void dll_target::signal(const NetNet*net) else obj->pin = tmp; } + ivl_assert(*net, net->pin(idx).nexus()->t_cookie()); } } diff --git a/t-dll.h b/t-dll.h index 71be25c5d..ec429756a 100644 --- a/t-dll.h +++ b/t-dll.h @@ -71,6 +71,7 @@ struct dll_target : public target_t, public expr_scan_t { int end_design(const Design*); bool bufz(const NetBUFZ*); + bool branch(const NetBranch*); void event(const NetEvent*); void logic(const NetLogic*); bool tran(const NetTran*); @@ -516,6 +517,7 @@ struct ivl_nexus_ptr_s { ivl_net_const_t con; /* type 2 */ ivl_lpm_t lpm; /* type 3 */ ivl_switch_t swi; /* type 4 */ + ivl_branch_t bra; /* type 5 */ } l; }; # define __NEXUS_PTR_SIG 0 @@ -523,13 +525,14 @@ struct ivl_nexus_ptr_s { # define __NEXUS_PTR_CON 2 # define __NEXUS_PTR_LPM 3 # define __NEXUS_PTR_SWI 4 +# define __NEXUS_PTR_BRA 5 /* * NOTE: ONLY allocate ivl_nexus_s objects with the included "new" operator. */ struct ivl_nexus_s { - unsigned nptr_; - struct ivl_nexus_ptr_s*ptrs_; + ivl_nexus_s() : ptrs_(1), nexus_(0), name_(0), private_data(0) { } + vectorptrs_; const Nexus*nexus_; const char*name_; void*private_data; diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index a10154447..25d2b5088 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -1132,6 +1132,7 @@ static void show_nexus_details(ivl_signal_t net, ivl_nexus_t nex) ivl_lpm_t lpm; ivl_signal_t sig; ivl_switch_t swt; + ivl_branch_t bra; ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx); const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)]; @@ -1173,6 +1174,10 @@ static void show_nexus_details(ivl_signal_t net, ivl_nexus_t nex) } else if ((con = ivl_nexus_ptr_con(ptr))) { signal_nexus_const(net, ptr, con); + } else if ((bra = ivl_nexus_ptr_branch(ptr))) { + fprintf(out, " BRANCH %p terminal %u\n", + bra, ivl_nexus_ptr_pin(ptr)); + } else { fprintf(out, " ?[%u] (%s0, %s1)\n", ivl_nexus_ptr_pin(ptr), dr0, dr1);