diff --git a/elaborate.cc b/elaborate.cc index 084d627aa..48b016172 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3850,7 +3850,7 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope, return enet; } - if (nset->count() == 0) { + if (nset->size() == 0) { cerr << get_fileline() << ": warning: @* found no " "sensitivities so it will never trigger." << endl; @@ -3869,9 +3869,9 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope, NetEvProbe*pr = new NetEvProbe(scope, scope->local_symbol(), ev, NetEvProbe::ANYEDGE, - nset->count()); - for (unsigned idx = 0 ; idx < nset->count() ; idx += 1) - connect(nset[0][idx], pr->pin(idx)); + nset->size()); + for (unsigned idx = 0 ; idx < nset->size() ; idx += 1) + connect(nset->at(idx).nex, pr->pin(idx)); delete nset; des->add_node(pr); @@ -4134,7 +4134,7 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope, return 0; } - if (wait_set->count() == 0) { + if (wait_set->size() == 0) { cerr << get_fileline() << ": internal error: Empty NexusSet" << " from wait expression." << endl; des->errors += 1; @@ -4143,9 +4143,9 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope, NetEvProbe*wait_pr = new NetEvProbe(scope, scope->local_symbol(), wait_event, NetEvProbe::ANYEDGE, - wait_set->count()); - for (unsigned idx = 0; idx < wait_set->count() ; idx += 1) - connect(wait_set[0][idx], wait_pr->pin(idx)); + wait_set->size()); + for (unsigned idx = 0; idx < wait_set->size() ; idx += 1) + connect(wait_set->at(idx).nex, wait_pr->pin(idx)); delete wait_set; des->add_node(wait_pr); diff --git a/expr_synth.cc b/expr_synth.cc index c6de2ea8f..6b4085de4 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -1310,16 +1310,16 @@ static NetEvWait* make_func_trigger(Design*des, NetScope*scope, NetExpr*root) NetEvWait*trigger = 0; NexusSet*nset = root->nex_input(false); - if (nset && (nset->count() > 0)) { + if (nset && (nset->size() > 0)) { NetEvent*ev = new NetEvent(scope->local_symbol()); ev->set_line(*root); NetEvProbe*pr = new NetEvProbe(scope, scope->local_symbol(), ev, NetEvProbe::ANYEDGE, - nset->count()); + nset->size()); pr->set_line(*root); - for (unsigned idx = 0 ; idx < nset->count() ; idx += 1) - connect(nset[0][idx], pr->pin(idx)); + for (unsigned idx = 0 ; idx < nset->size() ; idx += 1) + connect(nset->at(idx).nex, pr->pin(idx)); des->add_node(pr); diff --git a/net_event.cc b/net_event.cc index 3c31521d4..e9c7de8ae 100644 --- a/net_event.cc +++ b/net_event.cc @@ -225,9 +225,10 @@ NexusSet* NetEvent::nex_async_() return 0; } - for (unsigned idx = 0 ; idx < cur->pin_count() ; idx += 1) - tmp->add(cur->pin(idx).nexus()); - + for (unsigned idx = 0 ; idx < cur->pin_count() ; idx += 1) { + Nexus*nex = cur->pin(idx).nexus(); + tmp->add(nex, 0, nex->vector_width()); + } } return tmp; diff --git a/net_link.cc b/net_link.cc index 0bd45a9ce..1883e261e 100644 --- a/net_link.cc +++ b/net_link.cc @@ -523,109 +523,117 @@ const char* Nexus::name() const NexusSet::NexusSet() { - items_ = 0; - nitems_ = 0; } NexusSet::~NexusSet() { - if (nitems_ > 0) { - assert(items_ != 0); - free(items_); - } else { - assert(items_ == 0); - } } -unsigned NexusSet::count() const +size_t NexusSet::size() const { - return nitems_; + return items_.size(); } -void NexusSet::add(Nexus*that) +void NexusSet::add(Nexus*that, unsigned base, unsigned wid) { assert(that); - if (nitems_ == 0) { - assert(items_ == 0); - items_ = (Nexus**)malloc(sizeof(Nexus*)); - items_[0] = that; - nitems_ = 1; + elem_t cur (that, base, wid); + + if (items_.size() == 0) { + items_.resize(1); + items_[0] = cur; return; } - unsigned ptr = bsearch_(that); - if (ptr < nitems_) { - assert(items_[ptr] == that); + unsigned ptr = bsearch_(cur); + if (ptr < items_.size()) { return; } - assert(ptr == nitems_); + assert(ptr == items_.size()); - items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*)); - items_[ptr] = that; - nitems_ += 1; + items_.push_back(cur); } void NexusSet::add(const NexusSet&that) { - for (unsigned idx = 0 ; idx < that.nitems_ ; idx += 1) - add(that.items_[idx]); + for (size_t idx = 0 ; idx < that.items_.size() ; idx += 1) + add(that.items_[idx].nex, that.items_[idx].base, that.items_[idx].wid); } -void NexusSet::rem(Nexus*that) +void NexusSet::rem_(const NexusSet::elem_t&that) { - assert(that); - if (nitems_ == 0) + if (items_.empty()) return; unsigned ptr = bsearch_(that); - if (ptr >= nitems_) + if (ptr >= items_.size()) return; - if (nitems_ == 1) { - free(items_); - items_ = 0; - nitems_ = 0; + if (items_.size() == 1) { + items_.clear(); return; } - for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1) + for (unsigned idx = ptr ; idx < (items_.size()-1) ; idx += 1) items_[idx] = items_[idx+1]; - items_ = (Nexus**)realloc(items_, (nitems_-1) * sizeof(Nexus*)); - nitems_ -= 1; + items_.pop_back(); } void NexusSet::rem(const NexusSet&that) { - for (unsigned idx = 0 ; idx < that.nitems_ ; idx += 1) - rem(that.items_[idx]); + for (size_t idx = 0 ; idx < that.items_.size() ; idx += 1) + rem_(that.items_[idx]); } -Nexus* NexusSet::operator[] (unsigned idx) const +unsigned NexusSet::find_nexus(const NexusSet::elem_t&that) const { - assert(idx < nitems_); + return bsearch_(that); +} + +const NexusSet::elem_t& NexusSet::at (unsigned idx) const +{ + assert(idx < items_.size()); return items_[idx]; } -unsigned NexusSet::bsearch_(Nexus*that) const +size_t NexusSet::bsearch_(const NexusSet::elem_t&that) const { - for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { - if (items_[idx] == that) + for (unsigned idx = 0 ; idx < items_.size() ; idx += 1) { + if (items_[idx]==that) return idx; } - return nitems_; + return items_.size(); +} + +bool NexusSet::elem_t::contains(const struct elem_t&that) const +{ + if (nex != that.nex) + return false; + if (that.base < base) + return false; + if ((that.base+that.wid) > (base+wid)) + return false; + + return true; +} + +bool NexusSet::contains_(const NexusSet::elem_t&that) const +{ + for (unsigned idx = 0 ; idx < items_.size() ; idx += 1) { + if (items_[idx].contains(that)) + return true; + } + return false; } bool NexusSet::contains(const NexusSet&that) const { - for (unsigned idx = 0 ; idx < that.nitems_ ; idx += 1) { - unsigned where = bsearch_(that[idx]); - if (where == nitems_) - return false; - if (items_[where] != that[idx]) - return false; + for (size_t idx = 0 ; idx < that.items_.size() ; idx += 1) { + if (! contains_(that.items_[idx])) + return false; } return true; @@ -633,12 +641,12 @@ bool NexusSet::contains(const NexusSet&that) const bool NexusSet::intersect(const NexusSet&that) const { - for (unsigned idx = 0 ; idx < that.nitems_ ; idx += 1) { - unsigned where = bsearch_(that[idx]); - if (where == nitems_) + for (size_t idx = 0 ; idx < that.items_.size() ; idx += 1) { + size_t where = bsearch_(that.items_[idx]); + if (where == items_.size()) continue; - if (items_[where] == that[idx]) - return true; + + return true; } return false; diff --git a/net_nex_input.cc b/net_nex_input.cc index b0a3e61e2..1a1a1a179 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -184,7 +184,7 @@ NexusSet* NetESignal::nex_input(bool rem_out) } } for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1) - result->add(net_->pin(idx).nexus()); + result->add(net_->pin(idx).nexus(), 0, net_->vector_width()); return result; } diff --git a/net_nex_output.cc b/net_nex_output.cc index 9a61a54ae..534fe0441 100644 --- a/net_nex_output.cc +++ b/net_nex_output.cc @@ -36,6 +36,42 @@ void NetProc::nex_output(NexusSet&) << endl; } +void NetAssign_::nex_output(NexusSet&out) +{ + if (sig_ && !word_) { + Nexus*nex = sig_->pin(0).nexus(); + unsigned use_base = 0; + unsigned use_wid = lwidth(); + if (base_) { + long tmp = 0; + bool flag = eval_as_long(tmp, base_); + if (!flag) { + // Unable to evaluate the bit/part select of + // the l-value, so this is a mux. Pretty + // sure I don't know how to handle this yet + // in synthesis, so punt for now. + use_base = 0; + use_wid = nex->vector_width(); + + } else { + use_base = tmp; + } + } + + out.add(nex, use_base, use_wid); + + } else { + /* Quoting from netlist.h comments for class NetMemory: + * "This is not a node because memory objects can only be + * accessed by behavioral code." + */ + cerr << "?:?" << ": internal error: " + << "NetAssignBase::nex_output on unsupported lval "; + dump_lval(cerr); + cerr << endl; + } +} + /* * Assignments have as output all the bits of the concatenated signals * of the l-value. @@ -43,18 +79,7 @@ void NetProc::nex_output(NexusSet&) void NetAssignBase::nex_output(NexusSet&out) { for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) { - if (NetNet*lsig = cur->sig()) { - out.add(lsig->pin(0).nexus()); - } else { - /* Quoting from netlist.h comments for class NetMemory: - * "This is not a node because memory objects can only be - * accessed by behavioral code." - */ - cerr << get_fileline() << ": internal error: " - << "NetAssignBase::nex_output on unsupported lval "; - dump_lval(cerr); - cerr << endl; - } + cur->nex_output(out); } } diff --git a/netlist.h b/netlist.h index 9d47e43f4..6c337958b 100644 --- a/netlist.h +++ b/netlist.h @@ -405,33 +405,55 @@ inline void connect(Nexus*l, Link&r) { l->connect(r); } class NexusSet { + public: + struct elem_t { + inline elem_t(Nexus*n, unsigned b, unsigned w) + : nex(n), base(b), wid(w) + { } + inline elem_t() : nex(0), base(0), wid(0) { } + inline bool operator == (const struct elem_t&that) const + { return nex==that.nex && base==that.base && wid==that.wid; } + + bool contains(const struct elem_t&that) const; + + Nexus*nex; + unsigned base; + unsigned wid; + }; + public: ~NexusSet(); NexusSet(); - unsigned count() const; + size_t size() const; - // Add the nexus to the set, if it is not already present. - void add(Nexus*that); + // Add the nexus/part to the set, if it is not already present. + void add(Nexus*that, unsigned base, unsigned wid); void add(const NexusSet&that); // Remove the nexus from the set, if it is present. - void rem(Nexus*that); void rem(const NexusSet&that); - Nexus* operator[] (unsigned idx) const; + unsigned find_nexus(const elem_t&that) const; - // Return true if this set contains every nexus in that set. + const elem_t& at(unsigned idx) const; + inline const elem_t& operator[] (unsigned idx) const { return at(idx); } + + // Return true if this set contains every nexus/part in that + // set. That means that every bit of that set is accounted for + // this set. bool contains(const NexusSet&that) const; // Return true if this set contains any nexus in that set. bool intersect(const NexusSet&that) const; private: - Nexus**items_; - unsigned nitems_; + // NexSet items are canonical part selects of vectors. + std::vector items_; - unsigned bsearch_(Nexus*that) const; + size_t bsearch_(const struct elem_t&that) const; + void rem_(const struct elem_t&that); + bool contains_(const elem_t&htat) const; private: // not implemented NexusSet(const NexusSet&); @@ -2392,7 +2414,7 @@ class NetProc : public virtual LineInfo { // Synthesize as asynchronous logic, and return true. virtual bool synth_async(Design*des, NetScope*scope, - const NetBus&nex_map, NetBus&nex_out); + const NexusSet&nex_map, NetBus&nex_out); // Synthesize as synchronous logic, and return true. That // means binding the outputs to the data port of a FF, and the @@ -2408,7 +2430,7 @@ class NetProc : public virtual LineInfo { // the flipflop being generated. virtual bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clock, NetNet*ff_ce, - const NetBus&nex_map, NetBus&nex_out, + const NexusSet&nex_map, NetBus&nex_out, const std::vector&events); virtual void dump(ostream&, unsigned ind) const; @@ -2530,6 +2552,10 @@ class NetAssign_ { // expression idx. NexusSet* nex_input(bool rem_out = true); + // Figuring out nex_output to proces ultimately comes down to + // this method. + void nex_output(NexusSet&); + // This pointer is for keeping simple lists. NetAssign_* more; @@ -2578,7 +2604,7 @@ class NetAssignBase : public NetProc { unsigned lwidth() const; bool synth_async(Design*des, NetScope*scope, - const NetBus&nex_map, NetBus&nex_out); + const NexusSet&nex_map, NetBus&nex_out); // This dumps all the lval structures. void dump_lval(ostream&) const; @@ -2663,11 +2689,11 @@ class NetBlock : public NetProc { // synthesize as asynchronous logic, and return true. bool synth_async(Design*des, NetScope*scope, - const NetBus&nex_map, NetBus&nex_out); + const NexusSet&nex_map, NetBus&nex_out); bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, - const NetBus&nex_map, NetBus&nex_out, + const NexusSet&nex_map, NetBus&nex_out, const std::vector&events); // This version of emit_recurse scans all the statements of @@ -2720,7 +2746,7 @@ class NetCase : public NetProc { virtual void nex_output(NexusSet&out); bool synth_async(Design*des, NetScope*scope, - const NetBus&nex_map, NetBus&nex_out); + const NexusSet&nex_map, NetBus&nex_out); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -2795,11 +2821,11 @@ class NetCondit : public NetProc { bool is_asynchronous(); bool synth_async(Design*des, NetScope*scope, - const NetBus&nex_map, NetBus&nex_out); + const NexusSet&nex_map, NetBus&nex_out); bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, - const NetBus&nex_map, NetBus&nex_out, + const NexusSet&nex_map, NetBus&nex_out, const std::vector&events); virtual bool emit_proc(struct target_t*) const; @@ -3042,11 +3068,11 @@ class NetEvWait : public NetProc { virtual void nex_output(NexusSet&out); virtual bool synth_async(Design*des, NetScope*scope, - const NetBus&nex_map, NetBus&nex_out); + const NexusSet&nex_map, NetBus&nex_out); virtual bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, - const NetBus&nex_map, NetBus&nex_out, + const NexusSet&nex_map, NetBus&nex_out, const std::vector&events); virtual void dump(ostream&, unsigned ind) const; diff --git a/synth2.cc b/synth2.cc index 310c09e1e..2f5081087 100644 --- a/synth2.cc +++ b/synth2.cc @@ -28,14 +28,14 @@ using namespace std; -bool NetProc::synth_async(Design*, NetScope*, const NetBus&, NetBus&) +bool NetProc::synth_async(Design*, NetScope*, const NexusSet&, NetBus&) { return false; } bool NetProc::synth_sync(Design*des, NetScope*scope, NetNet* /* ff_clk */, NetNet* /* ff_ce */, - const NetBus&nex_map, NetBus&nex_out, + const NexusSet&nex_map, NetBus&nex_out, const vector&events) { if (events.size() > 0) { @@ -60,7 +60,7 @@ bool NetProc::synth_sync(Design*des, NetScope*scope, * r-value. */ bool NetAssignBase::synth_async(Design*des, NetScope*scope, - const NetBus& /*nex_map*/, NetBus&nex_out) + const NexusSet&nex_map, NetBus&nex_out) { NetNet*rsig = rval_->synthesize(des, scope, rval_); assert(rsig); @@ -77,14 +77,48 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, assert(lval_->more == 0); if (debug_synth2) { - cerr << get_fileline() << ": debug: l-value signal is " - << lsig->vector_width() << " bits, r-value signal is " - << rsig->vector_width() << " bits." << endl; + cerr << get_fileline() << ": NetAssignBase::synth_async: " + << "l-value signal is " << lsig->vector_width() << " bits, " + << "r-value signal is " << rsig->vector_width() << " bits." << endl; + cerr << get_fileline() << ": NetAssignBase::synth_async: " + << "lval_->lwidth()=" << lval_->lwidth() << endl; + if (const NetExpr*base = lval_->get_base()) { + cerr << get_fileline() << ": NetAssignBase::synth_async: " + << "base_=" << *base << endl; + } + cerr << get_fileline() << ": NetAssignBase::synth_async: " + << "nex_map.size()==" << nex_map.size() + << ", nex_out.pin_count()==" << nex_out.pin_count() << endl; } /* For now, assume there is exactly one output. */ - assert(nex_out.pin_count() == 1); + ivl_assert(*this, nex_out.pin_count() == 1); +#if 0 + if (lval_->lwidth() != lsig->vector_width()) { + ivl_assert(*this, lval_->lwidth() < lsig->vector_width()); + long base_off = 0; + if (! eval_as_long(base_off, lval_->get_base())) { + assert(0); + } + ivl_assert(*this, base_off >= 0); + + ivl_variable_type_t tmp_data_type = rsig->data_type(); + listnot_an_array; + netvector_t*tmp_type = new netvector_t(tmp_data_type, lsig->vector_width()-1,0); + + NetNet*tmp = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, not_an_array, tmp_type); + tmp->local_flag(true); + + NetPartSelect*ps = new NetPartSelect(tmp, base_off, lval_->lwidth(), NetPartSelect::PV); + ps->set_line(*this); + des->add_node(ps); + + connect(ps->pin(0), rsig->pin(0)); + rsig = tmp; + } +#endif connect(nex_out.pin(0), rsig->pin(0)); /* This lval_ represents a reg that is a WIRE in the @@ -104,7 +138,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, * substatements. */ bool NetBlock::synth_async(Design*des, NetScope*scope, - const NetBus&nex_map, NetBus&nex_out) + const NexusSet&nex_map, NetBus&nex_out) { if (last_ == 0) { return true; @@ -117,15 +151,12 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, /* Create a temporary map of the output only from this statement. */ - NexusSet tmp_set; - cur->nex_output(tmp_set); - NetBus tmp_map (scope, tmp_set.count()); - for (unsigned idx = 0 ; idx < tmp_set.count() ; idx += 1) - connect(tmp_set[idx], tmp_map.pin(idx)); + NexusSet tmp_map; + cur->nex_output(tmp_map); /* Create also a temporary NetBus to collect the output from the synthesis. */ - NetBus tmp_out (scope, tmp_set.count()); + NetBus tmp_out (scope, tmp_map.size()); bool ok_flag = cur->synth_async(des, scope, tmp_map, tmp_out); @@ -139,8 +170,8 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, to the tmp_map.pin(idx) pin, and link that to the tmp_out.pin(idx) output link. */ for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) { - unsigned ptr = nex_map.find_link(tmp_map.pin(idx)); - assert(ptr < nex_out.pin_count()); + unsigned ptr = nex_map.find_nexus(tmp_map[idx]); + ivl_assert(*this, ptr < nex_out.pin_count()); connect(nex_out.pin(ptr), tmp_out.pin(idx)); } @@ -150,7 +181,7 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, } bool NetCase::synth_async(Design*des, NetScope*scope, - const NetBus&nex_map, NetBus&nex_out) + const NexusSet&nex_map, NetBus&nex_out) { /* Synthesize the select expression. */ NetNet*esig = expr_->synthesize(des, scope, expr_); @@ -163,8 +194,8 @@ bool NetCase::synth_async(Design*des, NetScope*scope, mux_width += nex_out.pin(idx).nexus()->vector_width(); unsigned map_width = 0; - for (unsigned idx = 0 ; idx < nex_map.pin_count() ; idx += 1) - map_width += nex_map.pin(idx).nexus()->vector_width(); + for (unsigned idx = 0 ; idx < nex_map.size() ; idx += 1) + map_width += nex_map[idx].wid; /* Calculate the mux width from the map, the mex_map values are from the top level and are more reliable. */ @@ -217,7 +248,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope, connect(mux->pin_Sel(), esig->pin(0)); /* For now, assume that the output is only 1 signal. */ - assert(nex_out.pin_count() == 1); + ivl_assert(*this, nex_out.pin_count() == 1); connect(mux->pin_Result(), nex_out.pin(0)); /* Make sure the output is already connected to a net. */ @@ -236,11 +267,12 @@ bool NetCase::synth_async(Design*des, NetScope*scope, NetNet*default_sig = 0; if (statement_default) { - NetBus tmp (scope, 1); - statement_default->synth_async(des, scope, tmp, tmp); + NetBus tmp (scope, nex_map.size()); + statement_default->synth_async(des, scope, nex_map, tmp); // Get the signal from the synthesized statement. This // will be hooked to all the default cases. + ivl_assert(*this, tmp.pin_count()==1); default_sig = tmp.pin(0).nexus()->pick_any_net(); ivl_assert(*this, default_sig); } @@ -259,9 +291,10 @@ bool NetCase::synth_async(Design*des, NetScope*scope, continue; } - NetBus tmp (scope, 1); - stmt->synth_async(des, scope, tmp, tmp); + NetBus tmp (scope, nex_map.size()); + stmt->synth_async(des, scope, nex_map, tmp); + ivl_assert(*this, tmp.pin_count()==1); connect(mux->pin_Data(idx), tmp.pin(0)); ivl_assert(*this, mux->pin_Data(idx).nexus()->pick_any_net()); } @@ -270,7 +303,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope, } bool NetCondit::synth_async(Design*des, NetScope*scope, - const NetBus&nex_map, NetBus&nex_out) + const NexusSet&nex_map, NetBus&nex_out) { if (if_ == 0) { return false; @@ -345,7 +378,7 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, } bool NetEvWait::synth_async(Design*des, NetScope*scope, - const NetBus&nex_map, NetBus&nex_out) + const NexusSet&nex_map, NetBus&nex_out) { bool flag = statement_->synth_async(des, scope, nex_map, nex_out); return flag; @@ -365,16 +398,34 @@ bool NetProcTop::synth_async(Design*des) statement_->nex_output(nex_set); if (debug_synth2) { - cerr << get_fileline() << ": debug: Process has " - << nex_set.count() << " outputs." << endl; + cerr << get_fileline() << ": NetProcTop::synth_async: " + << "Process has " << nex_set.size() << " outputs." << endl; } - NetBus nex_q (scope(), nex_set.count()); - for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) { - connect(nex_set[idx], nex_q.pin(idx)); + NetBus nex_q (scope(), nex_set.size()); + for (unsigned idx = 0 ; idx < nex_set.size() ; idx += 1) { + const NexusSet::elem_t&item = nex_set[idx]; + if (item.base != 0 || item.wid!=item.nex->vector_width()) { + ivl_variable_type_t tmp_data_type = IVL_VT_LOGIC; + listnot_an_array; + netvector_t*tmp_type = new netvector_t(tmp_data_type, item.nex->vector_width()-1,0); + NetNet*tmp_sig = new NetNet(scope(), scope()->local_symbol(), + NetNet::WIRE, not_an_array, tmp_type); + tmp_sig->local_flag(true); + + NetPartSelect*tmp = new NetPartSelect(tmp_sig, item.base, + item.wid, NetPartSelect::PV); + des->add_node(tmp); + tmp->set_line(*this); + connect(tmp->pin(0), nex_q.pin(idx)); + connect(item.nex, tmp_sig->pin(0)); + + } else { + connect(item.nex, nex_q.pin(idx)); + } } - bool flag = statement_->synth_async(des, scope(), nex_q, nex_q); + bool flag = statement_->synth_async(des, scope(), nex_set, nex_q); return flag; } @@ -394,7 +445,7 @@ bool NetProcTop::synth_async(Design*des) */ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, - const NetBus&nex_map, NetBus&nex_out, + const NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { bool flag = true; @@ -406,9 +457,6 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, /* Create a temporary nex_map for the substatement. */ NexusSet tmp_set; cur->nex_output(tmp_set); - NetBus tmp_map (scope, tmp_set.count()); - for (unsigned idx = 0 ; idx < tmp_map.pin_count() ; idx += 1) - connect(tmp_set[idx], tmp_map.pin(idx)); /* NOTE: After this point, tmp_set should not be used as the various functions I call do a lot of connecting, @@ -419,14 +467,14 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, output. The tmp1 and tmp2 map and out sets together are used to collect the outputs from the substatement for the inputs of the FF bank. */ - NetBus tmp_out (scope, tmp_set.count()); + NetBus tmp_out (scope, tmp_set.size()); /* Now go on with the synchronous synthesis for this subset of the statement. The tmp_map is the output nexa that we expect, and the tmp_out is where we want those outputs connected. */ bool ok_flag = cur->synth_sync(des, scope, ff_clk, ff_ce, - tmp_map, tmp_out, events_in); + tmp_set, tmp_out, events_in); flag = flag && ok_flag; if (ok_flag == false) @@ -438,7 +486,7 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, beyond the input set, for example when the l-value of an assignment is smaller than the r-value. */ for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) { - unsigned ptr = nex_map.find_link(tmp_map.pin(idx)); + unsigned ptr = nex_map.find_nexus(tmp_set[idx]); assert(ptr < nex_out.pin_count()); connect(nex_out.pin(ptr), tmp_out.pin(idx)); } @@ -456,7 +504,7 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, */ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, - const NetBus&nex_map, NetBus&nex_out, + const NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { /* First try to turn the condition expression into an @@ -470,7 +518,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetEvProbe*ev = events_in[idx]; NexusSet pin_set; - pin_set.add(ev->pin(0).nexus()); + pin_set.add(ev->pin(0).nexus(), 0, 0); if (! expr_input->contains(pin_set)) continue; @@ -665,7 +713,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, - const NetBus&nex_map, NetBus&nex_out, + const NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { if (events_in.size() > 0) { @@ -697,7 +745,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, assert(tmp->pin_count() == 1); NexusSet tmp_nex; - tmp_nex .add( tmp->pin(0).nexus() ); + tmp_nex .add( tmp->pin(0).nexus(), 0, 0 ); if (! statement_input ->contains(tmp_nex)) { if (pclk != 0) { @@ -770,39 +818,39 @@ bool NetProcTop::synth_sync(Design*des) NetNet::TRI, &netvector_t::scalar_logic); ce->local_flag(true); - NetBus nex_d (scope(), nex_set.count()); - NetBus nex_q (scope(), nex_set.count()); + NetBus nex_d (scope(), nex_set.size()); + NetBus nex_q (scope(), nex_set.size()); /* The Q of the NetFF devices is connected to the output that we are. The nex_q is a bundle of the outputs. We will also pass the nex_q as a map to the statement's synth_sync method to map it to the correct nex_d pin. */ - for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) { - connect(nex_set[idx], nex_q.pin(idx)); + for (unsigned idx = 0 ; idx < nex_set.size() ; idx += 1) { + connect(nex_set[idx].nex, nex_q.pin(idx)); } // Connect the input later. /* Synthesize the input to the DFF. */ bool flag = statement_->synth_sync(des, scope(), clock, ce, - nex_q, nex_d, + nex_set, nex_d, vector()); if (! flag) { delete clock; return false; } - for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) { + for (unsigned idx = 0 ; idx < nex_set.size() ; idx += 1) { if (debug_synth2) { cerr << get_fileline() << ": debug: " << "Top level making a " - << nex_set[idx]->vector_width() << "-wide " + << nex_set[idx].nex->vector_width() << "-wide " << "NetFF device." << endl; } NetFF*ff2 = new NetFF(scope(), scope()->local_symbol(), - nex_set[idx]->vector_width()); + nex_set[idx].nex->vector_width()); des->add_node(ff2); ff2->set_line(*this);