Rework synchronous statement synthesis.
This changes the flow of the NetProc::synth_sync method, and implements the NetBlock::synth_sync better.
This commit is contained in:
parent
a47447610f
commit
1abf4f1aa1
13
netlist.cc
13
netlist.cc
|
|
@ -288,6 +288,19 @@ NetBus::~NetBus()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned NetBus::find_link(const Link&that) const
|
||||||
|
{
|
||||||
|
unsigned ptr = 0;
|
||||||
|
|
||||||
|
while (ptr < pin_count()) {
|
||||||
|
if (pin(ptr).is_linked(that))
|
||||||
|
return ptr;
|
||||||
|
|
||||||
|
ptr += 1;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins,
|
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins,
|
||||||
bool condit_src, bool conditional)
|
bool condit_src, bool conditional)
|
||||||
: NetObj(s, n, npins + (condit_src?1:0))
|
: NetObj(s, n, npins + (condit_src?1:0))
|
||||||
|
|
|
||||||
23
netlist.h
23
netlist.h
|
|
@ -449,6 +449,8 @@ class NetBus : public NetObj {
|
||||||
NetBus(NetScope*scope, unsigned pin_count);
|
NetBus(NetScope*scope, unsigned pin_count);
|
||||||
~NetBus();
|
~NetBus();
|
||||||
|
|
||||||
|
unsigned find_link(const Link&that) const;
|
||||||
|
|
||||||
private: // not implemented
|
private: // not implemented
|
||||||
NetBus(const NetBus&);
|
NetBus(const NetBus&);
|
||||||
NetBus& operator= (const NetBus&);
|
NetBus& operator= (const NetBus&);
|
||||||
|
|
@ -2392,7 +2394,20 @@ class NetProc : public virtual LineInfo {
|
||||||
virtual bool synth_async(Design*des, NetScope*scope,
|
virtual bool synth_async(Design*des, NetScope*scope,
|
||||||
const NetBus&nex_map, NetBus&nex_out);
|
const NetBus&nex_map, NetBus&nex_out);
|
||||||
|
|
||||||
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
// Synthesize as synchronous logic, and return true. That
|
||||||
|
// means binding the outputs to the data port of a FF, and the
|
||||||
|
// event inputs to a FF clock. Only some key NetProc sub-types
|
||||||
|
// that have specific meaning in synchronous statements. The
|
||||||
|
// remainder reduce to a call to synth_async that connects the
|
||||||
|
// output to the Data input of the FF.
|
||||||
|
//
|
||||||
|
// The events argument is filled in be the NetEvWait
|
||||||
|
// implementation of this method with the probes that it does
|
||||||
|
// not itself pick off as a clock. These events should be
|
||||||
|
// picked off by e.g. condit statements as set/reset inputs to
|
||||||
|
// the flipflop being generated.
|
||||||
|
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||||
|
NetNet*clock,
|
||||||
const NetBus&nex_map, NetBus&nex_out,
|
const NetBus&nex_map, NetBus&nex_out,
|
||||||
const std::vector<NetEvProbe*>&events);
|
const std::vector<NetEvProbe*>&events);
|
||||||
|
|
||||||
|
|
@ -2650,7 +2665,7 @@ class NetBlock : public NetProc {
|
||||||
bool synth_async(Design*des, NetScope*scope,
|
bool synth_async(Design*des, NetScope*scope,
|
||||||
const NetBus&nex_map, NetBus&nex_out);
|
const NetBus&nex_map, NetBus&nex_out);
|
||||||
|
|
||||||
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
bool synth_sync(Design*des, NetScope*scope, NetNet*clock,
|
||||||
const NetBus&nex_map, NetBus&nex_out,
|
const NetBus&nex_map, NetBus&nex_out,
|
||||||
const std::vector<NetEvProbe*>&events);
|
const std::vector<NetEvProbe*>&events);
|
||||||
|
|
||||||
|
|
@ -2781,7 +2796,7 @@ class NetCondit : public NetProc {
|
||||||
bool synth_async(Design*des, NetScope*scope,
|
bool synth_async(Design*des, NetScope*scope,
|
||||||
const NetBus&nex_map, NetBus&nex_out);
|
const NetBus&nex_map, NetBus&nex_out);
|
||||||
|
|
||||||
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
bool synth_sync(Design*des, NetScope*scope, NetNet*clock,
|
||||||
const NetBus&nex_map, NetBus&nex_out,
|
const NetBus&nex_map, NetBus&nex_out,
|
||||||
const std::vector<NetEvProbe*>&events);
|
const std::vector<NetEvProbe*>&events);
|
||||||
|
|
||||||
|
|
@ -3027,7 +3042,7 @@ class NetEvWait : public NetProc {
|
||||||
virtual bool synth_async(Design*des, NetScope*scope,
|
virtual bool synth_async(Design*des, NetScope*scope,
|
||||||
const NetBus&nex_map, NetBus&nex_out);
|
const NetBus&nex_map, NetBus&nex_out);
|
||||||
|
|
||||||
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
virtual bool synth_sync(Design*des, NetScope*scope, NetNet*clock,
|
||||||
const NetBus&nex_map, NetBus&nex_out,
|
const NetBus&nex_map, NetBus&nex_out,
|
||||||
const std::vector<NetEvProbe*>&events);
|
const std::vector<NetEvProbe*>&events);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,9 @@ netvector_t netvector_t::atom2u16 (IVL_VT_BOOL, 15, 0, false);
|
||||||
netvector_t netvector_t::atom2s8 (IVL_VT_BOOL, 7, 0, true);
|
netvector_t netvector_t::atom2s8 (IVL_VT_BOOL, 7, 0, true);
|
||||||
netvector_t netvector_t::atom2u8 (IVL_VT_BOOL, 7, 0, false);
|
netvector_t netvector_t::atom2u8 (IVL_VT_BOOL, 7, 0, false);
|
||||||
|
|
||||||
|
//netvector_t netvector_t::scalar_bool (IVL_VT_BOOL);
|
||||||
|
netvector_t netvector_t::scalar_logic (IVL_VT_LOGIC);
|
||||||
|
|
||||||
netvector_t::netvector_t(ivl_variable_type_t type, long msb, long lsb, bool flag)
|
netvector_t::netvector_t(ivl_variable_type_t type, long msb, long lsb, bool flag)
|
||||||
: type_(type), signed_(flag), isint_(false), is_scalar_(false)
|
: type_(type), signed_(flag), isint_(false), is_scalar_(false)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,8 @@ class netvector_t : public ivl_type_s {
|
||||||
static netvector_t atom2u16;
|
static netvector_t atom2u16;
|
||||||
static netvector_t atom2s8;
|
static netvector_t atom2s8;
|
||||||
static netvector_t atom2u8;
|
static netvector_t atom2u8;
|
||||||
|
static netvector_t scalar_bool;
|
||||||
|
static netvector_t scalar_logic;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<netrange_t> packed_dims_;
|
std::vector<netrange_t> packed_dims_;
|
||||||
|
|
|
||||||
185
synth2.cc
185
synth2.cc
|
|
@ -33,7 +33,7 @@ bool NetProc::synth_async(Design*, NetScope*, const NetBus&, NetBus&)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF* /*ff*/,
|
bool NetProc::synth_sync(Design*des, NetScope*scope, NetNet* /* clock */,
|
||||||
const NetBus&nex_map, NetBus&nex_out,
|
const NetBus&nex_map, NetBus&nex_out,
|
||||||
const vector<NetEvProbe*>&events)
|
const vector<NetEvProbe*>&events)
|
||||||
{
|
{
|
||||||
|
|
@ -138,11 +138,7 @@ bool NetBlock::synth_async(Design*des, NetScope*scope,
|
||||||
to the tmp_map.pin(idx) pin, and link that to the
|
to the tmp_map.pin(idx) pin, and link that to the
|
||||||
tmp_out.pin(idx) output link. */
|
tmp_out.pin(idx) output link. */
|
||||||
for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) {
|
||||||
unsigned ptr = 0;
|
unsigned ptr = nex_map.find_link(tmp_map.pin(idx));
|
||||||
while (ptr < nex_map.pin_count()
|
|
||||||
&& ! nex_map.pin(ptr).is_linked(tmp_map.pin(idx)))
|
|
||||||
ptr += 1;
|
|
||||||
|
|
||||||
assert(ptr < nex_out.pin_count());
|
assert(ptr < nex_out.pin_count());
|
||||||
connect(nex_out.pin(ptr), tmp_out.pin(idx));
|
connect(nex_out.pin(ptr), tmp_out.pin(idx));
|
||||||
}
|
}
|
||||||
|
|
@ -395,30 +391,12 @@ bool NetProcTop::synth_async(Design*des)
|
||||||
* This needs to be split into a DFF bank for each statement, because
|
* This needs to be split into a DFF bank for each statement, because
|
||||||
* the statements may each infer different reset and enable signals.
|
* the statements may each infer different reset and enable signals.
|
||||||
*/
|
*/
|
||||||
bool NetBlock::synth_sync(Design*des, NetScope* /*scope*/, NetFF* /*ff*/,
|
bool NetBlock::synth_sync(Design*des, NetScope*scope, NetNet*clk,
|
||||||
const NetBus& /*nex_map*/, NetBus& /*nex_out*/,
|
const NetBus&nex_map, NetBus&nex_out,
|
||||||
const vector<NetEvProbe*>& /*events_in*/)
|
const vector<NetEvProbe*>&events_in)
|
||||||
{
|
{
|
||||||
if (last_ == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
cerr << get_fileline() << ": sorry: "
|
|
||||||
<< "Forgot to implement NetBlock::synth_sync" << endl;
|
|
||||||
des->errors += 1;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
bool flag = true;
|
bool flag = true;
|
||||||
|
|
||||||
const perm_string tmp1 = perm_string::literal("tmp1");
|
|
||||||
const perm_string tmp2 = perm_string::literal("tmp2");
|
|
||||||
|
|
||||||
/* Keep an accounting of which statement accounts for which
|
|
||||||
bit slice of the FF bank. This is used for error checking. */
|
|
||||||
NetProc**pin_accounting = new NetProc* [ff->pin_count()];
|
|
||||||
for (unsigned idx = 0 ; idx < ff->pin_count() ; idx += 1)
|
|
||||||
pin_accounting[idx] = 0;
|
|
||||||
|
|
||||||
NetProc*cur = last_;
|
NetProc*cur = last_;
|
||||||
do {
|
do {
|
||||||
cur = cur->next_;
|
cur = cur->next_;
|
||||||
|
|
@ -426,10 +404,9 @@ bool NetBlock::synth_sync(Design*des, NetScope* /*scope*/, NetFF* /*ff*/,
|
||||||
/* Create a temporary nex_map for the substatement. */
|
/* Create a temporary nex_map for the substatement. */
|
||||||
NexusSet tmp_set;
|
NexusSet tmp_set;
|
||||||
cur->nex_output(tmp_set);
|
cur->nex_output(tmp_set);
|
||||||
NetNet*tmp_map = new NetNet(scope, tmp1, NetNet::WIRE,
|
NetBus tmp_map (scope, tmp_set.count());
|
||||||
tmp_set.count());
|
for (unsigned idx = 0 ; idx < tmp_map.pin_count() ; idx += 1)
|
||||||
for (unsigned idx = 0 ; idx < tmp_map->pin_count() ; idx += 1)
|
connect(tmp_set[idx], tmp_map.pin(idx));
|
||||||
connect(tmp_set[idx], tmp_map->pin(idx));
|
|
||||||
|
|
||||||
/* NOTE: After this point, tmp_set should not be used as
|
/* NOTE: After this point, tmp_set should not be used as
|
||||||
the various functions I call do a lot of connecting,
|
the various functions I call do a lot of connecting,
|
||||||
|
|
@ -440,85 +417,13 @@ bool NetBlock::synth_sync(Design*des, NetScope* /*scope*/, NetFF* /*ff*/,
|
||||||
output. The tmp1 and tmp2 map and out sets together
|
output. The tmp1 and tmp2 map and out sets together
|
||||||
are used to collect the outputs from the substatement
|
are used to collect the outputs from the substatement
|
||||||
for the inputs of the FF bank. */
|
for the inputs of the FF bank. */
|
||||||
NetNet*tmp_out = new NetNet(scope, tmp2, NetNet::WIRE,
|
NetBus tmp_out (scope, tmp_set.count());
|
||||||
tmp_map->pin_count());
|
|
||||||
|
|
||||||
verinum tmp_aset = ff->aset_value();
|
|
||||||
verinum tmp_sset = ff->sset_value();
|
|
||||||
|
|
||||||
/* Create a new DFF to handle this part of the begin-end
|
|
||||||
block. Connect this NetFF to the associated pins of
|
|
||||||
the existing wide NetFF device. While I'm at it, also
|
|
||||||
copy the aset_value bits for the new ff device. */
|
|
||||||
NetFF*ff2 = new NetFF(scope, scope->local_symbol(),
|
|
||||||
tmp_out->pin_count());
|
|
||||||
des->add_node(ff2);
|
|
||||||
|
|
||||||
verinum aset_value2 (verinum::V1, ff2->width());
|
|
||||||
verinum sset_value2 (verinum::V1, ff2->width());
|
|
||||||
for (unsigned idx = 0 ; idx < ff2->width() ; idx += 1) {
|
|
||||||
unsigned ptr = find_nexus_in_set(nex_map,
|
|
||||||
tmp_map->pin(idx).nexus());
|
|
||||||
|
|
||||||
/* Connect Data and Q bits to the new FF. */
|
|
||||||
connect(ff->pin_Data(ptr), ff2->pin_Data(idx));
|
|
||||||
connect(ff->pin_Q(ptr), ff2->pin_Q(idx));
|
|
||||||
|
|
||||||
/* Copy the asynch set bit to the new device. */
|
|
||||||
if (ptr < tmp_aset.len())
|
|
||||||
aset_value2.set(idx, tmp_aset[ptr]);
|
|
||||||
|
|
||||||
/* Copy the synch set bit to the new device. */
|
|
||||||
if (ptr < tmp_sset.len())
|
|
||||||
sset_value2.set(idx, tmp_sset[ptr]);
|
|
||||||
|
|
||||||
if (pin_accounting[ptr] != 0) {
|
|
||||||
cerr << cur->get_line() << ": error: "
|
|
||||||
<< "Synchronous output conflicts with "
|
|
||||||
<< pin_accounting[ptr]->get_line()
|
|
||||||
<< "." << endl;
|
|
||||||
flag = false;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
pin_accounting[ptr] = cur;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ff->pin_Aclr().is_linked())
|
|
||||||
connect(ff->pin_Aclr(), ff2->pin_Aclr());
|
|
||||||
if (ff->pin_Aset().is_linked())
|
|
||||||
connect(ff->pin_Aset(), ff2->pin_Aset());
|
|
||||||
if (ff->pin_Sclr().is_linked())
|
|
||||||
connect(ff->pin_Sclr(), ff2->pin_Sclr());
|
|
||||||
if (ff->pin_Sset().is_linked())
|
|
||||||
connect(ff->pin_Sset(), ff2->pin_Sset());
|
|
||||||
if (ff->pin_Clock().is_linked())
|
|
||||||
connect(ff->pin_Clock(), ff2->pin_Clock());
|
|
||||||
if (ff->pin_Enable().is_linked())
|
|
||||||
connect(ff->pin_Enable(),ff2->pin_Enable());
|
|
||||||
|
|
||||||
/* Remember to store the aset value into the new FF. If
|
|
||||||
this leads to an Aset value of 0 (and Aclr is not
|
|
||||||
otherwise used) then move the Aset input to Aclr. */
|
|
||||||
if (tmp_aset.len() == ff->width()) {
|
|
||||||
|
|
||||||
if (aset_value2.is_zero()
|
|
||||||
&& ff2->pin_Aset().is_linked()
|
|
||||||
&& !ff2->pin_Aclr().is_linked()) {
|
|
||||||
|
|
||||||
connect(ff2->pin_Aclr(), ff2->pin_Aset());
|
|
||||||
ff2->pin_Aset().unlink();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ff2->aset_value(aset_value2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now go on with the synchronous synthesis for this
|
/* Now go on with the synchronous synthesis for this
|
||||||
subset of the statement. The tmp_map is the output
|
subset of the statement. The tmp_map is the output
|
||||||
nexa that we expect, and the tmp_out is where we want
|
nexa that we expect, and the tmp_out is where we want
|
||||||
those outputs connected. */
|
those outputs connected. */
|
||||||
bool ok_flag = cur->synth_sync(des, scope, ff2, tmp_map,
|
bool ok_flag = cur->synth_sync(des, scope, clk, tmp_map,
|
||||||
tmp_out, events_in);
|
tmp_out, events_in);
|
||||||
flag = flag && ok_flag;
|
flag = flag && ok_flag;
|
||||||
|
|
||||||
|
|
@ -530,28 +435,15 @@ bool NetBlock::synth_sync(Design*des, NetScope* /*scope*/, NetFF* /*ff*/,
|
||||||
whole. It is occasionally possible to have outputs
|
whole. It is occasionally possible to have outputs
|
||||||
beyond the input set, for example when the l-value of
|
beyond the input set, for example when the l-value of
|
||||||
an assignment is smaller than the r-value. */
|
an assignment is smaller than the r-value. */
|
||||||
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) {
|
||||||
unsigned ptr = find_nexus_in_set(nex_map,
|
unsigned ptr = nex_map.find_link(tmp_map.pin(idx));
|
||||||
tmp_map->pin(idx).nexus());
|
assert(ptr < nex_out.pin_count());
|
||||||
|
connect(nex_out.pin(ptr), tmp_out.pin(idx));
|
||||||
if (ptr < nex_out->pin_count())
|
|
||||||
connect(nex_out->pin(ptr), tmp_out->pin(idx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete tmp_map;
|
|
||||||
delete tmp_out;
|
|
||||||
|
|
||||||
} while (cur != last_);
|
} while (cur != last_);
|
||||||
|
|
||||||
delete[]pin_accounting;
|
|
||||||
|
|
||||||
/* Done. The large NetFF is no longer needed, as it has been
|
|
||||||
taken up by the smaller NetFF devices. */
|
|
||||||
delete ff;
|
|
||||||
|
|
||||||
return flag;
|
return flag;
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -560,7 +452,7 @@ bool NetBlock::synth_sync(Design*des, NetScope* /*scope*/, NetFF* /*ff*/,
|
||||||
* asynchronous set/reset, depending on whether the pin of the
|
* asynchronous set/reset, depending on whether the pin of the
|
||||||
* expression is connected to an event, or not.
|
* expression is connected to an event, or not.
|
||||||
*/
|
*/
|
||||||
bool NetCondit::synth_sync(Design*des, NetScope* /*scope*/, NetFF* /*ff*/,
|
bool NetCondit::synth_sync(Design*des, NetScope* /*scope*/, NetNet* /*clk*/,
|
||||||
const NetBus& /*nex_map*/, NetBus& /*nex_out*/,
|
const NetBus& /*nex_map*/, NetBus& /*nex_out*/,
|
||||||
const vector<NetEvProbe*>& /*events_in*/)
|
const vector<NetEvProbe*>& /*events_in*/)
|
||||||
{
|
{
|
||||||
|
|
@ -775,7 +667,7 @@ bool NetCondit::synth_sync(Design*des, NetScope* /*scope*/, NetFF* /*ff*/,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetNet*clk,
|
||||||
const NetBus&nex_map, NetBus&nex_out,
|
const NetBus&nex_map, NetBus&nex_out,
|
||||||
const vector<NetEvProbe*>&events_in)
|
const vector<NetEvProbe*>&events_in)
|
||||||
{
|
{
|
||||||
|
|
@ -833,10 +725,10 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(ff->pin_Clock(), pclk->pin(0));
|
connect(clk->pin(0), pclk->pin(0));
|
||||||
if (pclk->edge() == NetEvProbe::NEGEDGE) {
|
if (pclk->edge() == NetEvProbe::NEGEDGE) {
|
||||||
perm_string polarity = perm_string::literal("Clock:LPM_Polarity");
|
perm_string polarity = perm_string::literal("Clock:LPM_Polarity");
|
||||||
ff->attribute(polarity, verinum("INVERT"));
|
clk->attribute(polarity, verinum("INVERT"));
|
||||||
|
|
||||||
if (debug_synth2) {
|
if (debug_synth2) {
|
||||||
cerr << get_fileline() << ": debug: "
|
cerr << get_fileline() << ": debug: "
|
||||||
|
|
@ -846,7 +738,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Synthesize the input to the DFF. */
|
/* Synthesize the input to the DFF. */
|
||||||
bool flag = statement_->synth_sync(des, scope, ff,
|
bool flag = statement_->synth_sync(des, scope, clk,
|
||||||
nex_map, nex_out, events);
|
nex_map, nex_out, events);
|
||||||
|
|
||||||
return flag;
|
return flag;
|
||||||
|
|
@ -872,17 +764,10 @@ bool NetProcTop::synth_sync(Design*des)
|
||||||
set, and will also take the initial connection of clocks
|
set, and will also take the initial connection of clocks
|
||||||
and resets. */
|
and resets. */
|
||||||
|
|
||||||
if (debug_synth2) {
|
// Create a net to carry the clock for the synthesized FFs.
|
||||||
cerr << get_fileline() << ": debug: "
|
NetNet*clock = new NetNet(scope(), scope()->local_symbol(),
|
||||||
<< "Top level making a "
|
NetNet::TRI, &netvector_t::scalar_logic);
|
||||||
<< nex_set[0]->vector_width() << "-wide "
|
clock->local_flag(true);
|
||||||
<< "NetFF device." << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetFF*ff = new NetFF(scope(), scope()->local_symbol(),
|
|
||||||
nex_set[0]->vector_width());
|
|
||||||
des->add_node(ff);
|
|
||||||
ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF"));
|
|
||||||
|
|
||||||
NetBus nex_d (scope(), nex_set.count());
|
NetBus nex_d (scope(), nex_set.count());
|
||||||
NetBus nex_q (scope(), nex_set.count());
|
NetBus nex_q (scope(), nex_set.count());
|
||||||
|
|
@ -898,28 +783,28 @@ bool NetProcTop::synth_sync(Design*des)
|
||||||
// Connect the input later.
|
// Connect the input later.
|
||||||
|
|
||||||
/* Synthesize the input to the DFF. */
|
/* Synthesize the input to the DFF. */
|
||||||
bool flag = statement_->synth_sync(des, scope(), ff,
|
bool flag = statement_->synth_sync(des, scope(), clock,
|
||||||
nex_q, nex_d,
|
nex_q, nex_d,
|
||||||
vector<NetEvProbe*>());
|
vector<NetEvProbe*>());
|
||||||
if (! flag) {
|
if (! flag) {
|
||||||
delete ff;
|
delete clock;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
|
||||||
|
|
||||||
NetNet*tmp = nex_d.pin(0).nexus()->pick_any_net();
|
if (debug_synth2) {
|
||||||
assert(tmp);
|
cerr << get_fileline() << ": debug: "
|
||||||
|
<< "Top level making a "
|
||||||
|
<< nex_set[idx]->vector_width() << "-wide "
|
||||||
|
<< "NetFF device." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
tmp = crop_to_width(des, tmp, ff->width());
|
|
||||||
connect(tmp->pin(0), ff->pin_Data());
|
|
||||||
connect(nex_q.pin(0), ff->pin_Q());
|
|
||||||
|
|
||||||
for (unsigned idx = 1 ; idx < nex_set.count() ; idx += 1) {
|
|
||||||
NetFF*ff2 = new NetFF(scope(), scope()->local_symbol(),
|
NetFF*ff2 = new NetFF(scope(), scope()->local_symbol(),
|
||||||
nex_set[idx]->vector_width());
|
nex_set[idx]->vector_width());
|
||||||
des->add_node(ff2);
|
des->add_node(ff2);
|
||||||
|
|
||||||
tmp = nex_d.pin(idx).nexus()->pick_any_net();
|
NetNet*tmp = nex_d.pin(idx).nexus()->pick_any_net();
|
||||||
assert(tmp);
|
assert(tmp);
|
||||||
|
|
||||||
tmp = crop_to_width(des, tmp, ff2->width());
|
tmp = crop_to_width(des, tmp, ff2->width());
|
||||||
|
|
@ -927,7 +812,8 @@ bool NetProcTop::synth_sync(Design*des)
|
||||||
connect(nex_q.pin(idx), ff2->pin_Q());
|
connect(nex_q.pin(idx), ff2->pin_Q());
|
||||||
connect(tmp->pin(0), ff2->pin_Data());
|
connect(tmp->pin(0), ff2->pin_Data());
|
||||||
|
|
||||||
connect(ff->pin_Clock(), ff2->pin_Clock());
|
connect(clock->pin(0), ff2->pin_Clock());
|
||||||
|
#if 0
|
||||||
if (ff->pin_Enable().is_linked())
|
if (ff->pin_Enable().is_linked())
|
||||||
connect(ff->pin_Enable(), ff2->pin_Enable());
|
connect(ff->pin_Enable(), ff2->pin_Enable());
|
||||||
if (ff->pin_Aset().is_linked())
|
if (ff->pin_Aset().is_linked())
|
||||||
|
|
@ -938,6 +824,7 @@ bool NetProcTop::synth_sync(Design*des)
|
||||||
connect(ff->pin_Sset(), ff2->pin_Sset());
|
connect(ff->pin_Sset(), ff2->pin_Sset());
|
||||||
if (ff->pin_Sclr().is_linked())
|
if (ff->pin_Sclr().is_linked())
|
||||||
connect(ff->pin_Sclr(), ff2->pin_Sclr());
|
connect(ff->pin_Sclr(), ff2->pin_Sclr());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue