Handle synthesis l-values that are part selects.
This commit is contained in:
parent
64b2345cf2
commit
7d6d93e4e2
16
elaborate.cc
16
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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
118
net_link.cc
118
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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
64
netlist.h
64
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<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
150
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<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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue