More flexible synthesis of DFF with asynchronous set/reset.

This commit is contained in:
Stephen Williams 2014-06-15 19:10:09 -07:00
parent 0f85bf0b9a
commit 3c0a982ab3
2 changed files with 54 additions and 51 deletions

View File

@ -2557,7 +2557,7 @@ class NetProc : public virtual LineInfo {
// the flipflop being generated. // the flipflop being generated.
virtual bool synth_sync(Design*des, NetScope*scope, virtual bool synth_sync(Design*des, NetScope*scope,
NetNet*ff_clock, NetNet*ff_ce, NetNet*ff_clock, NetNet*ff_ce,
NetNet*ff_aclr, NetNet*ff_aset, NetBus&ff_aclr, NetBus&ff_aset,
NexusSet&nex_map, NetBus&nex_out, NexusSet&nex_map, NetBus&nex_out,
const std::vector<NetEvProbe*>&events); const std::vector<NetEvProbe*>&events);
@ -2838,7 +2838,7 @@ class NetBlock : public NetProc {
bool synth_sync(Design*des, NetScope*scope, bool synth_sync(Design*des, NetScope*scope,
NetNet*ff_clk, NetNet*ff_ce, NetNet*ff_clk, NetNet*ff_ce,
NetNet*ff_aclr,NetNet*ff_aset, NetBus&ff_aclr,NetBus&ff_aset,
NexusSet&nex_map, NetBus&nex_out, NexusSet&nex_map, NetBus&nex_out,
const std::vector<NetEvProbe*>&events); const std::vector<NetEvProbe*>&events);
@ -2977,7 +2977,7 @@ class NetCondit : public NetProc {
bool synth_sync(Design*des, NetScope*scope, bool synth_sync(Design*des, NetScope*scope,
NetNet*ff_clk, NetNet*ff_ce, NetNet*ff_clk, NetNet*ff_ce,
NetNet*ff_aclr,NetNet*ff_aset, NetBus&ff_aclr,NetBus&ff_aset,
NexusSet&nex_map, NetBus&nex_out, NexusSet&nex_map, NetBus&nex_out,
const std::vector<NetEvProbe*>&events); const std::vector<NetEvProbe*>&events);
@ -3254,7 +3254,7 @@ class NetEvWait : public NetProc {
virtual bool synth_sync(Design*des, NetScope*scope, virtual bool synth_sync(Design*des, NetScope*scope,
NetNet*ff_clk, NetNet*ff_ce, NetNet*ff_clk, NetNet*ff_ce,
NetNet*ff_aclr,NetNet*ff_aset, NetBus&ff_aclr,NetBus&ff_aset,
NexusSet&nex_map, NetBus&nex_out, NexusSet&nex_map, NetBus&nex_out,
const std::vector<NetEvProbe*>&events); const std::vector<NetEvProbe*>&events);

View File

@ -35,7 +35,7 @@ bool NetProc::synth_async(Design*, NetScope*, NexusSet&, NetBus&, NetBus&)
bool NetProc::synth_sync(Design*des, NetScope*scope, bool NetProc::synth_sync(Design*des, NetScope*scope,
NetNet* /* ff_clk */, NetNet* /* ff_ce */, NetNet* /* ff_clk */, NetNet* /* ff_ce */,
NetNet* /* ff_aclr*/, NetNet* /* ff_aset*/, NetBus& /* ff_aclr*/, NetBus& /* ff_aset*/,
NexusSet&nex_map, NetBus&nex_out, NexusSet&nex_map, NetBus&nex_out,
const vector<NetEvProbe*>&events) const vector<NetEvProbe*>&events)
{ {
@ -1036,7 +1036,7 @@ bool NetProcTop::synth_async(Design*des)
*/ */
bool NetBlock::synth_sync(Design*des, NetScope*scope, bool NetBlock::synth_sync(Design*des, NetScope*scope,
NetNet*ff_clk, NetNet*ff_ce, NetNet*ff_clk, NetNet*ff_ce,
NetNet*ff_aclr,NetNet*ff_aset, NetBus&ff_aclr,NetBus&ff_aset,
NexusSet&nex_map, NetBus&nex_out, NexusSet&nex_map, NetBus&nex_out,
const vector<NetEvProbe*>&events_in) const vector<NetEvProbe*>&events_in)
{ {
@ -1102,7 +1102,7 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope,
*/ */
bool NetCondit::synth_sync(Design*des, NetScope*scope, bool NetCondit::synth_sync(Design*des, NetScope*scope,
NetNet*ff_clk, NetNet*ff_ce, NetNet*ff_clk, NetNet*ff_ce,
NetNet*ff_aclr,NetNet*ff_aset, NetBus&ff_aclr,NetBus&ff_aset,
NexusSet&nex_map, NetBus&nex_out, NexusSet&nex_map, NetBus&nex_out,
const vector<NetEvProbe*>&events_in) const vector<NetEvProbe*>&events_in)
{ {
@ -1143,45 +1143,54 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
flag = if_->synth_async(des, scope, nex_map, tmp_out, accumulated_tmp_out); flag = if_->synth_async(des, scope, nex_map, tmp_out, accumulated_tmp_out);
ivl_assert(*this, flag); ivl_assert(*this, flag);
ivl_assert(*this, tmp_out.pin_count()==1); ivl_assert(*this, tmp_out.pin_count() == ff_aclr.pin_count());
Nexus*rst_nex = tmp_out.pin(0).nexus(); ivl_assert(*this, tmp_out.pin_count() == ff_aset.pin_count());
vector<bool> rst_mask = rst_nex->driven_mask(); for (unsigned pin = 0 ; pin < tmp_out.pin_count() ; pin += 1) {
cerr << get_fileline() << ": NetCondit::synth_sync: " Nexus*rst_nex = tmp_out.pin(pin).nexus();
<< "rst_mask.size()==" << rst_mask.size()
<< ", rst_nex->vector_width()=" << rst_nex->vector_width()
<< endl;
ivl_assert(*this, rst_mask.size()==1); vector<bool> rst_mask = rst_nex->driven_mask();
if (rst_mask[0]==false) { if (debug_synth2) {
cerr << get_fileline() << ": sorry: " cerr << get_fileline() << ": NetCondit::synth_sync: "
<< "Asynchronous LOAD not implemented." << endl; << "nex_out pin=" << pin
return false; << ", rst_mask.size()==" << rst_mask.size()
} << ", rst_nex->vector_width()=" << rst_nex->vector_width()
<< endl;
}
verinum rst_drv = rst_nex->driven_vector(); for (size_t bit = 0 ; bit < rst_mask.size() ; bit += 1) {
ivl_assert(*this, rst_drv.len()==1); if (rst_mask[bit]==false) {
cerr << get_fileline() << ": sorry: "
<< "Asynchronous LOAD not implemented." << endl;
return false;
}
}
if (rst_drv[0]==verinum::V0) { verinum rst_drv = rst_nex->driven_vector();
ivl_assert(*this, ff_aclr && ff_aclr->pin_count()==1); ivl_assert(*this, rst_drv.len()==rst_mask.size());
// Don't yet support multiple asynchronous reset inputs.
ivl_assert(*this, ! ff_aclr->pin(0).is_linked());
ivl_assert(*this, rst->pin_count()==1); verinum zero (verinum::V0, rst_drv.len());
connect(ff_aclr->pin(0), rst->pin(0)); verinum ones (verinum::V1, rst_drv.len());
} else if (rst_drv[0]==verinum::V1) { if (rst_drv==zero) {
ivl_assert(*this, ff_aset && ff_aset->pin_count()==1); // Don't yet support multiple asynchronous reset inputs.
// Don't yet support multiple asynchronous set inputs. ivl_assert(*this, ! ff_aclr.pin(pin).is_linked());
ivl_assert(*this, ! ff_aset->pin(0).is_linked());
ivl_assert(*this, rst->pin_count()==1); ivl_assert(*this, rst->pin_count()==1);
connect(ff_aset->pin(0), rst->pin(0)); connect(ff_aclr.pin(pin), rst->pin(0));
} else { } else if (rst_drv==ones) {
cerr << get_fileline() << ": sorry: " // Don't yet support multiple asynchronous set inputs.
<< "Forgot how to implement asynchronous scramble (set to x/z)." << endl; ivl_assert(*this, ! ff_aset.pin(pin).is_linked());
return false;
ivl_assert(*this, rst->pin_count()==1);
connect(ff_aset.pin(pin), rst->pin(0));
} else {
cerr << get_fileline() << ": sorry: "
<< "Forgot how to implement asynchronous scramble (set to x/z)." << endl;
return false;
}
} }
return else_->synth_sync(des, scope, ff_clk, ff_ce, return else_->synth_sync(des, scope, ff_clk, ff_ce,
@ -1319,7 +1328,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
bool NetEvWait::synth_sync(Design*des, NetScope*scope, bool NetEvWait::synth_sync(Design*des, NetScope*scope,
NetNet*ff_clk, NetNet*ff_ce, NetNet*ff_clk, NetNet*ff_ce,
NetNet*ff_aclr,NetNet*ff_aset, NetBus&ff_aclr,NetBus&ff_aset,
NexusSet&nex_map, NetBus&nex_out, NexusSet&nex_map, NetBus&nex_out,
const vector<NetEvProbe*>&events_in) const vector<NetEvProbe*>&events_in)
{ {
@ -1436,16 +1445,10 @@ bool NetProcTop::synth_sync(Design*des)
NetNet::TRI, &netvector_t::scalar_logic); NetNet::TRI, &netvector_t::scalar_logic);
ce->local_flag(true); ce->local_flag(true);
NetNet*aclr = new NetNet(scope(), scope()->local_symbol(),
NetNet::TRI, &netvector_t::scalar_logic);
aclr->local_flag(true);
NetNet*aset = new NetNet(scope(), scope()->local_symbol(),
NetNet::TRI, &netvector_t::scalar_logic);
aset->local_flag(true);
NetBus nex_d (scope(), nex_set.size()); NetBus nex_d (scope(), nex_set.size());
NetBus nex_q (scope(), nex_set.size()); NetBus nex_q (scope(), nex_set.size());
NetBus aclr (scope(), nex_set.size());
NetBus aset (scope(), nex_set.size());
/* The Q of the NetFF devices is connected to the output that /* 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 we are. The nex_q is a bundle of the outputs. We will also
@ -1493,10 +1496,10 @@ bool NetProcTop::synth_sync(Design*des)
connect(clock->pin(0), ff2->pin_Clock()); connect(clock->pin(0), ff2->pin_Clock());
if (ce->is_linked()) if (ce->is_linked())
connect(ce->pin(0), ff2->pin_Enable()); connect(ce->pin(0), ff2->pin_Enable());
if (aclr->is_linked()) if (aclr.pin(idx).is_linked())
connect(aclr->pin(0), ff2->pin_Aclr()); connect(aclr.pin(idx), ff2->pin_Aclr());
if (aset->is_linked()) if (aset.pin(idx).is_linked())
connect(aset->pin(0), ff2->pin_Aset()); connect(aset.pin(idx), ff2->pin_Aset());
#if 0 #if 0
if (ff->pin_Sset().is_linked()) if (ff->pin_Sset().is_linked())
connect(ff->pin_Sset(), ff2->pin_Sset()); connect(ff->pin_Sset(), ff2->pin_Sset());