Merge pull request #3778 from jix/yw_clk2fflogic

This commit is contained in:
N. Engelhardt 2023-06-05 16:15:04 +02:00 committed by GitHub
commit 6f5d984bdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 70 additions and 17 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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