mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #3778 from jix/yw_clk2fflogic
This commit is contained in:
commit
6f5d984bdb
|
@ -736,6 +736,9 @@ struct AigerWriter
|
|||
auto sig_qy = cell->getPort(cell->type.in(ID($anyconst), ID($anyseq)) ? ID::Y : ID::Q);
|
||||
SigSpec sig = sigmap(sig_qy);
|
||||
|
||||
if (cell->get_bool_attribute(ID(clk2fflogic)))
|
||||
sig_qy = cell->getPort(ID::D); // For a clk2fflogic $_FF_ the named signal is the D input not the Q output
|
||||
|
||||
for (int i = 0; i < GetSize(sig_qy); i++) {
|
||||
if (sig_qy[i].wire == nullptr || sig[i].wire == nullptr)
|
||||
continue;
|
||||
|
|
|
@ -728,7 +728,10 @@ struct BtorWorker
|
|||
else
|
||||
btorf("%d state %d %s\n", nid, sid, log_id(symbol));
|
||||
|
||||
ywmap_state(sig_q);
|
||||
if (cell->get_bool_attribute(ID(clk2fflogic)))
|
||||
ywmap_state(cell->getPort(ID::D)); // For a clk2fflogic FF the named signal is the D input not the Q output
|
||||
else
|
||||
ywmap_state(sig_q);
|
||||
|
||||
if (nid_init_val >= 0) {
|
||||
int nid_init = next_nid++;
|
||||
|
|
|
@ -626,8 +626,9 @@ struct Smt2Worker
|
|||
}
|
||||
|
||||
bool init_only = cell->type.in(ID($anyconst), ID($anyinit), ID($allconst));
|
||||
bool clk2fflogic = cell->type == ID($anyinit) && cell->get_bool_attribute(ID(clk2fflogic));
|
||||
int smtoffset = 0;
|
||||
for (auto chunk : cell->getPort(QY).chunks()) {
|
||||
for (auto chunk : cell->getPort(clk2fflogic ? ID::D : QY).chunks()) {
|
||||
if (chunk.is_wire())
|
||||
decls.push_back(witness_signal(init_only ? "init" : "seq", chunk.width, chunk.offset, "", idcounter, chunk.wire, smtoffset));
|
||||
smtoffset += chunk.width;
|
||||
|
|
|
@ -139,7 +139,12 @@ static bool rename_witness(RTLIL::Design *design, dict<RTLIL::Module *, int> &ca
|
|||
|
||||
if (cell->type.in(ID($anyconst), ID($anyseq), ID($anyinit), ID($allconst), ID($allseq))) {
|
||||
has_witness_signals = true;
|
||||
auto QY = cell->type == ID($anyinit) ? ID::Q : ID::Y;
|
||||
IdString QY;
|
||||
bool clk2fflogic = false;
|
||||
if (cell->type == ID($anyinit))
|
||||
QY = (clk2fflogic = cell->get_bool_attribute(ID(clk2fflogic))) ? ID::D : ID::Q;
|
||||
else
|
||||
QY = ID::Y;
|
||||
auto sig_out = cell->getPort(QY);
|
||||
|
||||
for (auto chunk : sig_out.chunks()) {
|
||||
|
@ -151,7 +156,10 @@ static bool rename_witness(RTLIL::Design *design, dict<RTLIL::Module *, int> &ca
|
|||
auto new_id = module->uniquify("\\_witness_." + name);
|
||||
auto new_wire = module->addWire(new_id, GetSize(sig_out));
|
||||
new_wire->set_hdlname_attribute({ "_witness_", strstr(new_id.c_str(), ".") + 1 });
|
||||
module->connect({sig_out, new_wire});
|
||||
if (clk2fflogic)
|
||||
module->connect({new_wire, sig_out});
|
||||
else
|
||||
module->connect({sig_out, new_wire});
|
||||
cell->setPort(QY, new_wire);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -292,10 +292,12 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
|
|||
if (!purge_mode)
|
||||
for (auto &it : module->cells_) {
|
||||
RTLIL::Cell *cell = it.second;
|
||||
if (ct_reg.cell_known(cell->type))
|
||||
if (ct_reg.cell_known(cell->type)) {
|
||||
bool clk2fflogic = cell->get_bool_attribute(ID(clk2fflogic));
|
||||
for (auto &it2 : cell->connections())
|
||||
if (ct_reg.cell_output(cell->type, it2.first))
|
||||
if (clk2fflogic ? it2.first == ID::D : ct_reg.cell_output(cell->type, it2.first))
|
||||
register_signals.add(it2.second);
|
||||
}
|
||||
for (auto &it2 : cell->connections())
|
||||
connected_signals.add(it2.second);
|
||||
}
|
||||
|
|
|
@ -80,15 +80,27 @@ struct Clk2fflogicPass : public Pass {
|
|||
return module->Eqx(NEW_ID, {sampled_sig, sig}, polarity ? SigSpec {State::S0, State::S1} : SigSpec {State::S1, State::S0});
|
||||
}
|
||||
// Sampled and current value of a data signal.
|
||||
SampledSig sample_data(Module *module, SigSpec sig, RTLIL::Const init, bool is_fine) {
|
||||
SampledSig sample_data(Module *module, SigSpec sig, RTLIL::Const init, bool is_fine, bool set_attribute = false) {
|
||||
std::string sig_str = log_signal(sig);
|
||||
sig_str.erase(std::remove(sig_str.begin(), sig_str.end(), ' '), sig_str.end());
|
||||
|
||||
|
||||
Wire *sampled_sig = module->addWire(NEW_ID_SUFFIX(stringf("%s#sampled", sig_str.c_str())), GetSize(sig));
|
||||
sampled_sig->attributes[ID::init] = init;
|
||||
|
||||
Cell *cell;
|
||||
if (is_fine)
|
||||
module->addFfGate(NEW_ID, sig, sampled_sig);
|
||||
cell = module->addFfGate(NEW_ID, sig, sampled_sig);
|
||||
else
|
||||
module->addFf(NEW_ID, sig, sampled_sig);
|
||||
cell = module->addFf(NEW_ID, sig, sampled_sig);
|
||||
|
||||
if (set_attribute) {
|
||||
for (auto &chunk : sig.chunks())
|
||||
if (chunk.wire != nullptr)
|
||||
chunk.wire->set_bool_attribute(ID::keep);
|
||||
cell->set_bool_attribute(ID(clk2fflogic));
|
||||
}
|
||||
|
||||
return {sampled_sig, sig};
|
||||
}
|
||||
SigSpec mux(Module *module, SigSpec a, SigSpec b, SigSpec s, bool is_fine) {
|
||||
|
@ -213,7 +225,7 @@ struct Clk2fflogicPass : public Pass {
|
|||
if (ff.has_clk)
|
||||
ff.unmap_ce_srst();
|
||||
|
||||
auto next_q = sample_data(module, ff.sig_q, ff.val_init, ff.is_fine).sampled;
|
||||
auto next_q = sample_data(module, ff.sig_q, ff.val_init, ff.is_fine, true).sampled;
|
||||
|
||||
if (ff.has_clk) {
|
||||
// The init value for the sampled d is never used, so we can set it to fixed zero, reducing uninit'd FFs
|
||||
|
|
|
@ -140,6 +140,7 @@ struct SimInstance
|
|||
dict<SigBit, pool<Wire*>> upd_outports;
|
||||
|
||||
dict<SigBit, SigBit> in_parent_drivers;
|
||||
dict<SigBit, SigBit> clk2fflogic_drivers;
|
||||
|
||||
pool<SigBit> dirty_bits;
|
||||
pool<Cell*> dirty_cells;
|
||||
|
@ -270,6 +271,11 @@ struct SimInstance
|
|||
ff.past_srst = State::Sx;
|
||||
ff.data = ff_data;
|
||||
ff_database[cell] = ff;
|
||||
|
||||
if (cell->get_bool_attribute(ID(clk2fflogic))) {
|
||||
for (int i = 0; i < ff_data.width; i++)
|
||||
clk2fflogic_drivers.emplace(sigmap(ff_data.sig_d[i]), sigmap(ff_data.sig_q[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (cell->is_mem_cell())
|
||||
|
@ -389,6 +395,10 @@ struct SimInstance
|
|||
auto sigbit = sig[i];
|
||||
auto sigval = value[i];
|
||||
|
||||
auto clk2fflogic_driver = clk2fflogic_drivers.find(sigbit);
|
||||
if (clk2fflogic_driver != clk2fflogic_drivers.end())
|
||||
sigbit = clk2fflogic_driver->second;
|
||||
|
||||
auto in_parent_driver = in_parent_drivers.find(sigbit);
|
||||
if (in_parent_driver == in_parent_drivers.end())
|
||||
set_state(sigbit, sigval);
|
||||
|
@ -589,7 +599,7 @@ struct SimInstance
|
|||
}
|
||||
}
|
||||
|
||||
bool update_ph2(bool gclk)
|
||||
bool update_ph2(bool gclk, bool stable_past_update = false)
|
||||
{
|
||||
bool did_something = false;
|
||||
|
||||
|
@ -600,7 +610,7 @@ struct SimInstance
|
|||
|
||||
Const current_q = get_state(ff.data.sig_q);
|
||||
|
||||
if (ff_data.has_clk) {
|
||||
if (ff_data.has_clk && !stable_past_update) {
|
||||
// flip-flops
|
||||
State current_clk = get_state(ff_data.sig_clk)[0];
|
||||
if (ff_data.pol_clk ? (ff.past_clk == State::S0 && current_clk != State::S0) :
|
||||
|
@ -621,7 +631,7 @@ struct SimInstance
|
|||
if (ff_data.has_aload) {
|
||||
State current_aload = get_state(ff_data.sig_aload)[0];
|
||||
if (current_aload == (ff_data.pol_aload ? State::S1 : State::S0)) {
|
||||
current_q = ff_data.has_clk ? ff.past_ad : get_state(ff.data.sig_ad);
|
||||
current_q = ff_data.has_clk && !stable_past_update ? ff.past_ad : get_state(ff.data.sig_ad);
|
||||
}
|
||||
}
|
||||
// async reset
|
||||
|
@ -672,6 +682,8 @@ struct SimInstance
|
|||
}
|
||||
else
|
||||
{
|
||||
if (stable_past_update)
|
||||
continue;
|
||||
if (port.clk_polarity ?
|
||||
(mdb.past_wr_clk[port_idx] == State::S1 || get_state(port.clk) != State::S1) :
|
||||
(mdb.past_wr_clk[port_idx] == State::S0 || get_state(port.clk) != State::S0))
|
||||
|
@ -701,7 +713,7 @@ struct SimInstance
|
|||
}
|
||||
|
||||
for (auto it : children)
|
||||
if (it.second->update_ph2(gclk)) {
|
||||
if (it.second->update_ph2(gclk, stable_past_update)) {
|
||||
dirty_children.insert(it.second);
|
||||
did_something = true;
|
||||
}
|
||||
|
@ -1197,9 +1209,21 @@ struct SimWorker : SimShared
|
|||
|
||||
void initialize_stable_past()
|
||||
{
|
||||
if (debug)
|
||||
log("\n-- ph1 (initialize) --\n");
|
||||
top->update_ph1();
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (debug)
|
||||
log("\n-- ph1 (initialize) --\n");
|
||||
|
||||
top->update_ph1();
|
||||
|
||||
if (debug)
|
||||
log("\n-- ph2 (initialize) --\n");
|
||||
|
||||
if (!top->update_ph2(false, true))
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
log("\n-- ph3 (initialize) --\n");
|
||||
top->update_ph3(true);
|
||||
|
|
Loading…
Reference in New Issue