3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-08-08 12:11:24 +00:00

FfData: some refactoring.

- FfData now keeps track of the module and underlying cell, if any (so
  calling emit on FfData created from a cell will replace the existing cell)
- FfData implementation is split off to its own .cc file for faster
  compilation
- the "flip FF data sense by inserting inverters in front and after"
  functionality that zinit uses is moved onto FfData class and beefed up
  to have dffsr support, to support more use cases
This commit is contained in:
Marcelina Kościelnicka 2021-10-06 22:16:55 +02:00
parent 356ec7bb39
commit 4e70c30775
14 changed files with 663 additions and 549 deletions

View file

@ -581,7 +581,7 @@ struct MemoryDffWorker
// Now we're commited to merge it.
merger.mark_input_ff(bits);
// If the address FF has enable and/or sync reset, unmap it.
ff.unmap_ce_srst(module);
ff.unmap_ce_srst();
port.clk = ff.sig_clk;
port.en = State::S1;
port.addr = ff.sig_d;

View file

@ -275,7 +275,7 @@ struct OptDffWorker
bool changed = false;
if (!ff.width) {
module->remove(cell);
ff.remove();
did_something = true;
continue;
}
@ -316,6 +316,7 @@ struct OptDffWorker
continue;
}
ff = ff.slice(keep_bits);
ff.cell = cell;
changed = true;
}
@ -393,8 +394,7 @@ struct OptDffWorker
// Always-active enable. Make a comb circuit, nuke the FF/latch.
log("Handling always-active async load on %s (%s) from module %s (changing to combinatorial circuit).\n",
log_id(cell), log_id(cell->type), log_id(module));
initvals.remove_init(ff.sig_q);
module->remove(cell);
ff.remove();
if (ff.has_sr) {
SigSpec tmp;
if (ff.is_fine) {
@ -456,8 +456,7 @@ struct OptDffWorker
// Always-active async reset — change to const driver.
log("Handling always-active ARST on %s (%s) from module %s (changing to const driver).\n",
log_id(cell), log_id(cell->type), log_id(module));
initvals.remove_init(ff.sig_q);
module->remove(cell);
ff.remove();
module->connect(ff.sig_q, ff.val_arst);
did_something = true;
continue;
@ -660,6 +659,7 @@ struct OptDffWorker
continue;
}
ff = ff.slice(keep_bits);
ff.cell = cell;
changed = true;
}
@ -728,7 +728,7 @@ struct OptDffWorker
new_ff.pol_srst = srst.second;
if (new_ff.has_ce)
new_ff.ce_over_srst = true;
Cell *new_cell = new_ff.emit(module, NEW_ID);
Cell *new_cell = new_ff.emit();
if (new_cell)
dff_cells.push_back(new_cell);
log("Adding SRST signal on %s (%s) from module %s (D = %s, Q = %s, rval = %s).\n",
@ -741,6 +741,7 @@ struct OptDffWorker
continue;
} else if (GetSize(remaining_indices) != ff.width) {
ff = ff.slice(remaining_indices);
ff.cell = cell;
changed = true;
}
}
@ -790,7 +791,7 @@ struct OptDffWorker
new_ff.sig_ce = en.first;
new_ff.pol_ce = en.second;
new_ff.ce_over_srst = false;
Cell *new_cell = new_ff.emit(module, NEW_ID);
Cell *new_cell = new_ff.emit();
if (new_cell)
dff_cells.push_back(new_cell);
log("Adding EN signal on %s (%s) from module %s (D = %s, Q = %s).\n",
@ -803,6 +804,7 @@ struct OptDffWorker
continue;
} else if (GetSize(remaining_indices) != ff.width) {
ff = ff.slice(remaining_indices);
ff.cell = cell;
changed = true;
}
}
@ -810,9 +812,7 @@ struct OptDffWorker
if (changed) {
// Rebuild the FF.
IdString name = cell->name;
module->remove(cell);
ff.emit(module, name);
ff.emit();
did_something = true;
}
}

View file

@ -78,7 +78,7 @@ struct Async2syncPass : public Pass {
if (ff.has_clk)
{
if (ff.has_sr) {
ff.unmap_ce_srst(module);
ff.unmap_ce_srst();
log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
@ -124,7 +124,7 @@ struct Async2syncPass : public Pass {
ff.sig_q = new_q;
ff.has_sr = false;
} else if (ff.has_aload) {
ff.unmap_ce_srst(module);
ff.unmap_ce_srst();
log("Replacing %s.%s (%s): ALOAD=%s, AD=%s, D=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
@ -157,7 +157,7 @@ struct Async2syncPass : public Pass {
ff.sig_q = new_q;
ff.has_aload = false;
} else if (ff.has_arst) {
ff.unmap_srst(module);
ff.unmap_srst();
log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
@ -267,10 +267,7 @@ struct Async2syncPass : public Pass {
ff.has_sr = false;
ff.has_gclk = true;
}
IdString name = cell->name;
module->remove(cell);
ff.emit(module, name);
ff.emit();
}
}
}

View file

@ -153,6 +153,23 @@ struct Clk2fflogicPass : public Pass {
continue;
}
if (ff.has_clk) {
log("Replacing %s.%s (%s): CLK=%s, D=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
log_signal(ff.sig_clk), log_signal(ff.sig_d), log_signal(ff.sig_q));
} else if (ff.has_aload) {
log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q));
} else {
// $sr.
log("Replacing %s.%s (%s): SET=%s, CLR=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_q));
}
ff.remove();
Wire *past_q = module->addWire(NEW_ID, ff.width);
if (!ff.is_fine) {
module->addFf(NEW_ID, ff.sig_q, past_q);
@ -163,7 +180,7 @@ struct Clk2fflogicPass : public Pass {
initvals.set_init(past_q, ff.val_init);
if (ff.has_clk) {
ff.unmap_ce_srst(module);
ff.unmap_ce_srst();
Wire *past_clk = module->addWire(NEW_ID);
initvals.set_init(past_clk, ff.pol_clk ? State::S1 : State::S0);
@ -173,10 +190,6 @@ struct Clk2fflogicPass : public Pass {
else
module->addFfGate(NEW_ID, ff.sig_clk, past_clk);
log("Replacing %s.%s (%s): CLK=%s, D=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
log_signal(ff.sig_clk), log_signal(ff.sig_d), log_signal(ff.sig_q));
SigSpec clock_edge_pattern;
if (ff.pol_clk) {
@ -203,16 +216,6 @@ struct Clk2fflogicPass : public Pass {
else
qval = module->MuxGate(NEW_ID, past_q, past_d, clock_edge);
} else {
if (ff.has_aload) {
log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q));
} else {
// $sr.
log("Replacing %s.%s (%s): SET=%s, CLR=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_q));
}
qval = past_q;
}
@ -246,10 +249,6 @@ struct Clk2fflogicPass : public Pass {
} else {
module->connect(ff.sig_q, qval);
}
initvals.remove_init(ff.sig_q);
module->remove(cell);
continue;
}
}
}

View file

@ -86,19 +86,18 @@ struct DffunmapPass : public Pass {
if (ce_only) {
if (!ff.has_ce)
continue;
ff.unmap_ce(mod);
ff.unmap_ce();
} else if (srst_only) {
if (!ff.has_srst)
continue;
ff.unmap_srst(mod);
ff.unmap_srst();
} else {
if (!ff.has_ce && !ff.has_srst)
continue;
ff.unmap_ce_srst(mod);
ff.unmap_ce_srst();
}
mod->remove(cell);
ff.emit(mod, name);
ff.emit();
}
}
}

View file

@ -368,13 +368,13 @@ void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell)
module->connect(RTLIL::SigSig(sig_y, sig_ab));
}
void simplemap_ff(RTLIL::Module *module, RTLIL::Cell *cell)
void simplemap_ff(RTLIL::Module *, RTLIL::Cell *cell)
{
FfData ff(nullptr, cell);
for (int i = 0; i < ff.width; i++) {
FfData fff = ff.slice({i});
fff.is_fine = true;
fff.emit(module, NEW_ID);
fff.emit();
}
}

View file

@ -25,14 +25,6 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
State invert(State s) {
switch (s) {
case State::S0: return State::S1;
case State::S1: return State::S0;
default: return s;
}
}
struct ZinitPass : public Pass {
ZinitPass() : Pass("zinit", "add inverters so all FF are zero-initialized") { }
void help() override
@ -75,45 +67,19 @@ struct ZinitPass : public Pass {
continue;
FfData ff(&initvals, cell);
if (!ff.width)
continue;
// Supporting those would require a new cell type where S has priority over R.
if (ff.has_sr)
continue;
Wire *new_q = module->addWire(NEW_ID, ff.width);
log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
log_signal(ff.sig_q), log_signal(ff.val_init));
IdString name = cell->name;
module->remove(cell);
initvals.remove_init(ff.sig_q);
for (int i = 0; i < ff.width; i++)
if (ff.val_init[i] == State::S1)
{
if (ff.has_clk || ff.has_gclk)
ff.sig_d[i] = module->NotGate(NEW_ID, ff.sig_d[i]);
if (ff.has_aload)
ff.sig_ad[i] = module->NotGate(NEW_ID, ff.sig_ad[i]);
if (ff.has_arst)
ff.val_arst[i] = invert(ff.val_arst[i]);
if (ff.has_srst)
ff.val_srst[i] = invert(ff.val_srst[i]);
module->addNotGate(NEW_ID, SigSpec(new_q, i), ff.sig_q[i]);
ff.val_init[i] = State::S0;
}
else
{
module->connect(ff.sig_q[i], SigSpec(new_q, i));
if (all_mode)
ff.val_init[i] = State::S0;
}
ff.sig_q = new_q;
ff.emit(module, name);
pool<int> bits;
for (int i = 0; i < ff.width; i++) {
if (ff.val_init.bits[i] == State::S1)
bits.insert(i);
else if (ff.val_init.bits[i] != State::S0 && all_mode)
ff.val_init.bits[i] = State::S0;
}
ff.flip_bits(bits);
ff.emit();
}
}
}