Handle synthesis l-values that are part selects.

This commit is contained in:
Stephen Williams 2013-09-08 18:18:31 -07:00
parent 64b2345cf2
commit 7d6d93e4e2
8 changed files with 261 additions and 153 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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<struct elem_t> 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<NetEvProbe*>&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<NetEvProbe*>&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<NetEvProbe*>&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<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const;

150
synth2.cc
View File

@ -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<NetEvProbe*>&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();
list<netrange_t>not_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;
list<netrange_t>not_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<NetEvProbe*>&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<NetEvProbe*>&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<NetEvProbe*>&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<NetEvProbe*>());
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);