aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorMarcelina Kościelnicka <mwk@0x04.net>2021-10-06 22:16:55 +0200
committerMarcelina Kościelnicka <mwk@0x04.net>2021-10-07 04:24:06 +0200
commit4e70c3077562e511d6f840c91dd30ade87d66517 (patch)
treee03d632836952baf936c715927f2d6c8a9691e28 /kernel
parent356ec7bb3980f77d737d9fa6e24e2f0b2159e741 (diff)
downloadyosys-4e70c3077562e511d6f840c91dd30ade87d66517.tar.gz
yosys-4e70c3077562e511d6f840c91dd30ade87d66517.tar.bz2
yosys-4e70c3077562e511d6f840c91dd30ade87d66517.zip
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
Diffstat (limited to 'kernel')
-rw-r--r--kernel/ff.cc575
-rw-r--r--kernel/ff.h472
-rw-r--r--kernel/ffmerge.cc2
-rw-r--r--kernel/mem.cc8
4 files changed, 604 insertions, 453 deletions
diff --git a/kernel/ff.cc b/kernel/ff.cc
new file mode 100644
index 000000000..c2f1a75a0
--- /dev/null
+++ b/kernel/ff.cc
@@ -0,0 +1,575 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2020 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/ff.h"
+
+USING_YOSYS_NAMESPACE
+
+FfData::FfData(FfInitVals *initvals, Cell *cell_) : FfData(cell_->module, initvals, cell_->name)
+{
+ cell = cell_;
+ sig_q = cell->getPort(ID::Q);
+ width = GetSize(sig_q);
+ attributes = cell->attributes;
+
+ if (initvals)
+ val_init = (*initvals)(sig_q);
+
+ std::string type_str = cell->type.str();
+
+ if (cell->type.in(ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr))) {
+ if (cell->type == ID($ff)) {
+ has_gclk = true;
+ sig_d = cell->getPort(ID::D);
+ } else if (cell->type == ID($sr)) {
+ // No data input at all.
+ } else if (cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr))) {
+ has_aload = true;
+ sig_aload = cell->getPort(ID::EN);
+ pol_aload = cell->getParam(ID::EN_POLARITY).as_bool();
+ sig_ad = cell->getPort(ID::D);
+ } else {
+ has_clk = true;
+ sig_clk = cell->getPort(ID::CLK);
+ pol_clk = cell->getParam(ID::CLK_POLARITY).as_bool();
+ sig_d = cell->getPort(ID::D);
+ }
+ if (cell->type.in(ID($dffe), ID($dffsre), ID($adffe), ID($aldffe), ID($sdffe), ID($sdffce))) {
+ has_ce = true;
+ sig_ce = cell->getPort(ID::EN);
+ pol_ce = cell->getParam(ID::EN_POLARITY).as_bool();
+ }
+ if (cell->type.in(ID($dffsr), ID($dffsre), ID($dlatchsr), ID($sr))) {
+ has_sr = true;
+ sig_clr = cell->getPort(ID::CLR);
+ sig_set = cell->getPort(ID::SET);
+ pol_clr = cell->getParam(ID::CLR_POLARITY).as_bool();
+ pol_set = cell->getParam(ID::SET_POLARITY).as_bool();
+ }
+ if (cell->type.in(ID($aldff), ID($aldffe))) {
+ has_aload = true;
+ sig_aload = cell->getPort(ID::ALOAD);
+ pol_aload = cell->getParam(ID::ALOAD_POLARITY).as_bool();
+ sig_ad = cell->getPort(ID::AD);
+ }
+ if (cell->type.in(ID($adff), ID($adffe), ID($adlatch))) {
+ has_arst = true;
+ sig_arst = cell->getPort(ID::ARST);
+ pol_arst = cell->getParam(ID::ARST_POLARITY).as_bool();
+ val_arst = cell->getParam(ID::ARST_VALUE);
+ }
+ if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
+ has_srst = true;
+ sig_srst = cell->getPort(ID::SRST);
+ pol_srst = cell->getParam(ID::SRST_POLARITY).as_bool();
+ val_srst = cell->getParam(ID::SRST_VALUE);
+ ce_over_srst = cell->type == ID($sdffce);
+ }
+ } else if (cell->type == ID($_FF_)) {
+ is_fine = true;
+ has_gclk = true;
+ sig_d = cell->getPort(ID::D);
+ } else if (type_str.substr(0, 5) == "$_SR_") {
+ is_fine = true;
+ has_sr = true;
+ pol_set = type_str[5] == 'P';
+ pol_clr = type_str[6] == 'P';
+ sig_set = cell->getPort(ID::S);
+ sig_clr = cell->getPort(ID::R);
+ } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 8) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[6] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 10) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[7] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_ce = true;
+ pol_ce = type_str[8] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 10) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[6] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_arst = true;
+ pol_arst = type_str[7] == 'P';
+ sig_arst = cell->getPort(ID::R);
+ val_arst = type_str[8] == '1' ? State::S1 : State::S0;
+ } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 12) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[7] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_arst = true;
+ pol_arst = type_str[8] == 'P';
+ sig_arst = cell->getPort(ID::R);
+ val_arst = type_str[9] == '1' ? State::S1 : State::S0;
+ has_ce = true;
+ pol_ce = type_str[10] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 8) == "$_ALDFF_" && type_str.size() == 11) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[8] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_aload = true;
+ pol_aload = type_str[9] == 'P';
+ sig_aload = cell->getPort(ID::L);
+ sig_ad = cell->getPort(ID::AD);
+ } else if (type_str.substr(0, 9) == "$_ALDFFE_" && type_str.size() == 13) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[9] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_aload = true;
+ pol_aload = type_str[10] == 'P';
+ sig_aload = cell->getPort(ID::L);
+ sig_ad = cell->getPort(ID::AD);
+ has_ce = true;
+ pol_ce = type_str[11] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 8) == "$_DFFSR_" && type_str.size() == 12) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[8] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_sr = true;
+ pol_set = type_str[9] == 'P';
+ pol_clr = type_str[10] == 'P';
+ sig_set = cell->getPort(ID::S);
+ sig_clr = cell->getPort(ID::R);
+ } else if (type_str.substr(0, 9) == "$_DFFSRE_" && type_str.size() == 14) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[9] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_sr = true;
+ pol_set = type_str[10] == 'P';
+ pol_clr = type_str[11] == 'P';
+ sig_set = cell->getPort(ID::S);
+ sig_clr = cell->getPort(ID::R);
+ has_ce = true;
+ pol_ce = type_str[12] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 7) == "$_SDFF_" && type_str.size() == 11) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[7] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_srst = true;
+ pol_srst = type_str[8] == 'P';
+ sig_srst = cell->getPort(ID::R);
+ val_srst = type_str[9] == '1' ? State::S1 : State::S0;
+ } else if (type_str.substr(0, 8) == "$_SDFFE_" && type_str.size() == 13) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[8] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_srst = true;
+ pol_srst = type_str[9] == 'P';
+ sig_srst = cell->getPort(ID::R);
+ val_srst = type_str[10] == '1' ? State::S1 : State::S0;
+ has_ce = true;
+ pol_ce = type_str[11] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 9) == "$_SDFFCE_" && type_str.size() == 14) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[9] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_srst = true;
+ pol_srst = type_str[10] == 'P';
+ sig_srst = cell->getPort(ID::R);
+ val_srst = type_str[11] == '1' ? State::S1 : State::S0;
+ has_ce = true;
+ pol_ce = type_str[12] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ ce_over_srst = true;
+ } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 11) {
+ is_fine = true;
+ has_aload = true;
+ sig_ad = cell->getPort(ID::D);
+ has_aload = true;
+ pol_aload = type_str[9] == 'P';
+ sig_aload = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 13) {
+ is_fine = true;
+ has_aload = true;
+ sig_ad = cell->getPort(ID::D);
+ has_aload = true;
+ pol_aload = type_str[9] == 'P';
+ sig_aload = cell->getPort(ID::E);
+ has_arst = true;
+ pol_arst = type_str[10] == 'P';
+ sig_arst = cell->getPort(ID::R);
+ val_arst = type_str[11] == '1' ? State::S1 : State::S0;
+ } else if (type_str.substr(0, 11) == "$_DLATCHSR_" && type_str.size() == 15) {
+ is_fine = true;
+ has_aload = true;
+ sig_ad = cell->getPort(ID::D);
+ has_aload = true;
+ pol_aload = type_str[11] == 'P';
+ sig_aload = cell->getPort(ID::E);
+ has_sr = true;
+ pol_set = type_str[12] == 'P';
+ pol_clr = type_str[13] == 'P';
+ sig_set = cell->getPort(ID::S);
+ sig_clr = cell->getPort(ID::R);
+ } else {
+ log_assert(0);
+ }
+ if (has_aload && !has_clk && !has_sr && !has_arst && sig_ad.is_fully_const()) {
+ // Plain D latches with const D treated specially.
+ has_aload = false;
+ has_arst = true;
+ sig_arst = sig_aload;
+ pol_arst = pol_aload;
+ val_arst = sig_ad.as_const();
+ }
+}
+
+FfData FfData::slice(const std::vector<int> &bits) {
+ FfData res(module, initvals, NEW_ID);
+ res.sig_clk = sig_clk;
+ res.sig_ce = sig_ce;
+ res.sig_aload = sig_aload;
+ res.sig_arst = sig_arst;
+ res.sig_srst = sig_srst;
+ res.has_clk = has_clk;
+ res.has_gclk = has_gclk;
+ res.has_ce = has_ce;
+ res.has_aload = has_aload;
+ res.has_arst = has_arst;
+ res.has_srst = has_srst;
+ res.has_sr = has_sr;
+ res.ce_over_srst = ce_over_srst;
+ res.is_fine = is_fine;
+ res.pol_clk = pol_clk;
+ res.pol_ce = pol_ce;
+ res.pol_aload = pol_aload;
+ res.pol_arst = pol_arst;
+ res.pol_srst = pol_srst;
+ res.pol_clr = pol_clr;
+ res.pol_set = pol_set;
+ res.attributes = attributes;
+ for (int i : bits) {
+ res.sig_q.append(sig_q[i]);
+ if (has_clk || has_gclk)
+ res.sig_d.append(sig_d[i]);
+ if (has_aload)
+ res.sig_ad.append(sig_ad[i]);
+ if (has_sr) {
+ res.sig_clr.append(sig_clr[i]);
+ res.sig_set.append(sig_set[i]);
+ }
+ if (has_arst)
+ res.val_arst.bits.push_back(val_arst[i]);
+ if (has_srst)
+ res.val_srst.bits.push_back(val_srst[i]);
+ if (initvals)
+ res.val_init.bits.push_back(val_init[i]);
+ }
+ res.width = GetSize(res.sig_q);
+ return res;
+}
+
+void FfData::unmap_ce() {
+ if (!has_ce)
+ return;
+ log_assert(has_clk);
+ if (has_srst && ce_over_srst)
+ unmap_srst();
+
+ if (!is_fine) {
+ if (pol_ce)
+ sig_d = module->Mux(NEW_ID, sig_q, sig_d, sig_ce);
+ else
+ sig_d = module->Mux(NEW_ID, sig_d, sig_q, sig_ce);
+ } else {
+ if (pol_ce)
+ sig_d = module->MuxGate(NEW_ID, sig_q, sig_d, sig_ce);
+ else
+ sig_d = module->MuxGate(NEW_ID, sig_d, sig_q, sig_ce);
+ }
+ has_ce = false;
+}
+
+void FfData::unmap_srst() {
+ if (!has_srst)
+ return;
+ if (has_ce && !ce_over_srst)
+ unmap_ce();
+
+ if (!is_fine) {
+ if (pol_srst)
+ sig_d = module->Mux(NEW_ID, sig_d, val_srst, sig_srst);
+ else
+ sig_d = module->Mux(NEW_ID, val_srst, sig_d, sig_srst);
+ } else {
+ if (pol_srst)
+ sig_d = module->MuxGate(NEW_ID, sig_d, val_srst[0], sig_srst);
+ else
+ sig_d = module->MuxGate(NEW_ID, val_srst[0], sig_d, sig_srst);
+ }
+ has_srst = false;
+}
+
+Cell *FfData::emit() {
+ remove();
+ if (!width)
+ return nullptr;
+ if (!has_aload && !has_clk && !has_gclk && !has_sr) {
+ if (has_arst) {
+ // Convert this case to a D latch.
+ has_aload = true;
+ has_arst = false;
+ sig_ad = val_arst;
+ sig_aload = sig_arst;
+ pol_aload = pol_arst;
+ } else {
+ // No control inputs left. Turn into a const driver.
+ module->connect(sig_q, val_init);
+ return nullptr;
+ }
+ }
+ if (initvals)
+ initvals->set_init(sig_q, val_init);
+ if (!is_fine) {
+ if (has_gclk) {
+ log_assert(!has_clk);
+ log_assert(!has_ce);
+ log_assert(!has_aload);
+ log_assert(!has_arst);
+ log_assert(!has_srst);
+ log_assert(!has_sr);
+ cell = module->addFf(name, sig_d, sig_q);
+ } else if (!has_aload && !has_clk) {
+ log_assert(has_sr);
+ cell = module->addSr(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
+ } else if (!has_clk) {
+ log_assert(!has_srst);
+ if (has_sr)
+ cell = module->addDlatchsr(name, sig_aload, sig_set, sig_clr, sig_ad, sig_q, pol_aload, pol_set, pol_clr);
+ else if (has_arst)
+ cell = module->addAdlatch(name, sig_aload, sig_arst, sig_ad, sig_q, val_arst, pol_aload, pol_arst);
+ else
+ cell = module->addDlatch(name, sig_aload, sig_ad, sig_q, pol_aload);
+ } else {
+ if (has_sr) {
+ if (has_ce)
+ cell = module->addDffsre(name, sig_clk, sig_ce, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_ce, pol_set, pol_clr);
+ else
+ cell = module->addDffsr(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
+ } else if (has_arst) {
+ if (has_ce)
+ cell = module->addAdffe(name, sig_clk, sig_ce, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_ce, pol_arst);
+ else
+ cell = module->addAdff(name, sig_clk, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_arst);
+ } else if (has_aload) {
+ if (has_ce)
+ cell = module->addAldffe(name, sig_clk, sig_ce, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_ce, pol_aload);
+ else
+ cell = module->addAldff(name, sig_clk, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_aload);
+ } else if (has_srst) {
+ if (has_ce)
+ if (ce_over_srst)
+ cell = module->addSdffce(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_ce, pol_srst);
+ else
+ cell = module->addSdffe(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_ce, pol_srst);
+ else
+ cell = module->addSdff(name, sig_clk, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_srst);
+ } else {
+ if (has_ce)
+ cell = module->addDffe(name, sig_clk, sig_ce, sig_d, sig_q, pol_clk, pol_ce);
+ else
+ cell = module->addDff(name, sig_clk, sig_d, sig_q, pol_clk);
+ }
+ }
+ } else {
+ if (has_gclk) {
+ log_assert(!has_clk);
+ log_assert(!has_ce);
+ log_assert(!has_aload);
+ log_assert(!has_arst);
+ log_assert(!has_srst);
+ log_assert(!has_sr);
+ cell = module->addFfGate(name, sig_d, sig_q);
+ } else if (!has_aload && !has_clk) {
+ log_assert(has_sr);
+ cell = module->addSrGate(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
+ } else if (!has_clk) {
+ log_assert(!has_srst);
+ if (has_sr)
+ cell = module->addDlatchsrGate(name, sig_aload, sig_set, sig_clr, sig_ad, sig_q, pol_aload, pol_set, pol_clr);
+ else if (has_arst)
+ cell = module->addAdlatchGate(name, sig_aload, sig_arst, sig_ad, sig_q, val_arst.as_bool(), pol_aload, pol_arst);
+ else
+ cell = module->addDlatchGate(name, sig_aload, sig_ad, sig_q, pol_aload);
+ } else {
+ if (has_sr) {
+ if (has_ce)
+ cell = module->addDffsreGate(name, sig_clk, sig_ce, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_ce, pol_set, pol_clr);
+ else
+ cell = module->addDffsrGate(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
+ } else if (has_arst) {
+ if (has_ce)
+ cell = module->addAdffeGate(name, sig_clk, sig_ce, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_ce, pol_arst);
+ else
+ cell = module->addAdffGate(name, sig_clk, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_arst);
+ } else if (has_aload) {
+ if (has_ce)
+ cell = module->addAldffeGate(name, sig_clk, sig_ce, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_ce, pol_aload);
+ else
+ cell = module->addAldffGate(name, sig_clk, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_aload);
+ } else if (has_srst) {
+ if (has_ce)
+ if (ce_over_srst)
+ cell = module->addSdffceGate(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_ce, pol_srst);
+ else
+ cell = module->addSdffeGate(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_ce, pol_srst);
+ else
+ cell = module->addSdffGate(name, sig_clk, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_srst);
+ } else {
+ if (has_ce)
+ cell = module->addDffeGate(name, sig_clk, sig_ce, sig_d, sig_q, pol_clk, pol_ce);
+ else
+ cell = module->addDffGate(name, sig_clk, sig_d, sig_q, pol_clk);
+ }
+ }
+ }
+ cell->attributes = attributes;
+ return cell;
+}
+
+void FfData::remove() {
+ if (cell) {
+ remove_init();
+ module->remove(cell);
+ cell = nullptr;
+ }
+}
+
+namespace {
+ State invert(State s) {
+ switch (s) {
+ case State::S0: return State::S1;
+ case State::S1: return State::S0;
+ default: return s;
+ }
+ }
+}
+
+void FfData::flip_bits(const pool<int> &bits) {
+ if (!bits.size())
+ return;
+
+ remove_init();
+
+ Wire *new_q = module->addWire(NEW_ID, width);
+
+ for (auto bit: bits) {
+ if (has_arst)
+ val_arst[bit] = invert(val_arst[bit]);
+ if (has_srst)
+ val_srst[bit] = invert(val_srst[bit]);
+ val_init[bit] = invert(val_init[bit]);
+ }
+
+ if (has_sr && cell) {
+ log_warning("Flipping D/Q/init and inserting priority fixup to legalize %s.%s [%s].", log_id(module->name), log_id(cell->name), log_id(cell->type));
+ }
+
+ if (is_fine) {
+ if (has_sr) {
+ bool new_pol_clr = pol_set;
+ SigSpec new_sig_clr;
+ if (pol_set) {
+ if (pol_clr) {
+ new_sig_clr = module->AndnotGate(NEW_ID, sig_set, sig_clr);
+ } else {
+ new_sig_clr = module->AndGate(NEW_ID, sig_set, sig_clr);
+ }
+ } else {
+ if (pol_clr) {
+ new_sig_clr = module->OrGate(NEW_ID, sig_set, sig_clr);
+ } else {
+ new_sig_clr = module->OrnotGate(NEW_ID, sig_set, sig_clr);
+ }
+ }
+ pol_set = pol_clr;
+ sig_set = sig_clr;
+ pol_clr = new_pol_clr;
+ sig_clr = new_sig_clr;
+ }
+ if (has_clk || has_gclk)
+ sig_d = module->NotGate(NEW_ID, sig_d);
+ if (has_aload)
+ sig_ad = module->NotGate(NEW_ID, sig_ad);
+ module->addNotGate(NEW_ID, new_q, sig_q);
+ }
+ else
+ {
+ if (has_sr) {
+ SigSpec not_clr;
+ if (!pol_clr) {
+ not_clr = sig_clr;
+ sig_clr = module->Not(NEW_ID, sig_clr);
+ pol_clr = true;
+ } else {
+ not_clr = module->Not(NEW_ID, sig_clr);
+ }
+ if (!pol_set) {
+ sig_set = module->Not(NEW_ID, sig_set);
+ pol_set = true;
+ }
+
+ SigSpec masked_set = module->And(NEW_ID, sig_set, not_clr);
+ for (auto bit: bits) {
+ sig_set[bit] = sig_clr[bit];
+ sig_clr[bit] = masked_set[bit];
+ }
+ }
+
+ Const mask = Const(State::S0, width);
+ for (auto bit: bits)
+ mask.bits[bit] = State::S1;
+
+ if (has_clk || has_gclk)
+ sig_d = module->Xor(NEW_ID, sig_d, mask);
+ if (has_aload)
+ sig_ad = module->Xor(NEW_ID, sig_ad, mask);
+ module->addXor(NEW_ID, new_q, mask, sig_q);
+ }
+
+ sig_q = new_q;
+}
diff --git a/kernel/ff.h b/kernel/ff.h
index 7f01b8a36..3125f67c6 100644
--- a/kernel/ff.h
+++ b/kernel/ff.h
@@ -76,7 +76,10 @@ YOSYS_NAMESPACE_BEGIN
// - empty set [not a cell — will be emitted as a simple direct connection]
struct FfData {
+ Module *module;
FfInitVals *initvals;
+ Cell *cell;
+ IdString name;
// The FF output.
SigSpec sig_q;
// The sync data input, present if has_clk or has_gclk.
@@ -142,7 +145,7 @@ struct FfData {
int width;
dict<IdString, Const> attributes;
- FfData(FfInitVals *initvals = nullptr, Cell *cell = nullptr) : initvals(initvals) {
+ FfData(Module *module = nullptr, FfInitVals *initvals = nullptr, IdString name = IdString()) : module(module), initvals(initvals), cell(nullptr), name(name) {
width = 0;
has_clk = false;
has_gclk = false;
@@ -160,464 +163,37 @@ struct FfData {
pol_srst = false;
pol_clr = false;
pol_set = false;
-
- if (!cell)
- return;
-
- sig_q = cell->getPort(ID::Q);
- width = GetSize(sig_q);
- attributes = cell->attributes;
-
- if (initvals)
- val_init = (*initvals)(sig_q);
-
- std::string type_str = cell->type.str();
-
- if (cell->type.in(ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr))) {
- if (cell->type == ID($ff)) {
- has_gclk = true;
- sig_d = cell->getPort(ID::D);
- } else if (cell->type == ID($sr)) {
- // No data input at all.
- } else if (cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr))) {
- has_aload = true;
- sig_aload = cell->getPort(ID::EN);
- pol_aload = cell->getParam(ID::EN_POLARITY).as_bool();
- sig_ad = cell->getPort(ID::D);
- } else {
- has_clk = true;
- sig_clk = cell->getPort(ID::CLK);
- pol_clk = cell->getParam(ID::CLK_POLARITY).as_bool();
- sig_d = cell->getPort(ID::D);
- }
- if (cell->type.in(ID($dffe), ID($dffsre), ID($adffe), ID($aldffe), ID($sdffe), ID($sdffce))) {
- has_ce = true;
- sig_ce = cell->getPort(ID::EN);
- pol_ce = cell->getParam(ID::EN_POLARITY).as_bool();
- }
- if (cell->type.in(ID($dffsr), ID($dffsre), ID($dlatchsr), ID($sr))) {
- has_sr = true;
- sig_clr = cell->getPort(ID::CLR);
- sig_set = cell->getPort(ID::SET);
- pol_clr = cell->getParam(ID::CLR_POLARITY).as_bool();
- pol_set = cell->getParam(ID::SET_POLARITY).as_bool();
- }
- if (cell->type.in(ID($aldff), ID($aldffe))) {
- has_aload = true;
- sig_aload = cell->getPort(ID::ALOAD);
- pol_aload = cell->getParam(ID::ALOAD_POLARITY).as_bool();
- sig_ad = cell->getPort(ID::AD);
- }
- if (cell->type.in(ID($adff), ID($adffe), ID($adlatch))) {
- has_arst = true;
- sig_arst = cell->getPort(ID::ARST);
- pol_arst = cell->getParam(ID::ARST_POLARITY).as_bool();
- val_arst = cell->getParam(ID::ARST_VALUE);
- }
- if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
- has_srst = true;
- sig_srst = cell->getPort(ID::SRST);
- pol_srst = cell->getParam(ID::SRST_POLARITY).as_bool();
- val_srst = cell->getParam(ID::SRST_VALUE);
- ce_over_srst = cell->type == ID($sdffce);
- }
- } else if (cell->type == ID($_FF_)) {
- is_fine = true;
- has_gclk = true;
- sig_d = cell->getPort(ID::D);
- } else if (type_str.substr(0, 5) == "$_SR_") {
- is_fine = true;
- has_sr = true;
- pol_set = type_str[5] == 'P';
- pol_clr = type_str[6] == 'P';
- sig_set = cell->getPort(ID::S);
- sig_clr = cell->getPort(ID::R);
- } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 8) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[6] == 'P';
- sig_clk = cell->getPort(ID::C);
- } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 10) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[7] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_ce = true;
- pol_ce = type_str[8] == 'P';
- sig_ce = cell->getPort(ID::E);
- } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 10) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[6] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_arst = true;
- pol_arst = type_str[7] == 'P';
- sig_arst = cell->getPort(ID::R);
- val_arst = type_str[8] == '1' ? State::S1 : State::S0;
- } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 12) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[7] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_arst = true;
- pol_arst = type_str[8] == 'P';
- sig_arst = cell->getPort(ID::R);
- val_arst = type_str[9] == '1' ? State::S1 : State::S0;
- has_ce = true;
- pol_ce = type_str[10] == 'P';
- sig_ce = cell->getPort(ID::E);
- } else if (type_str.substr(0, 8) == "$_ALDFF_" && type_str.size() == 11) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[8] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_aload = true;
- pol_aload = type_str[9] == 'P';
- sig_aload = cell->getPort(ID::L);
- sig_ad = cell->getPort(ID::AD);
- } else if (type_str.substr(0, 9) == "$_ALDFFE_" && type_str.size() == 13) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[9] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_aload = true;
- pol_aload = type_str[10] == 'P';
- sig_aload = cell->getPort(ID::L);
- sig_ad = cell->getPort(ID::AD);
- has_ce = true;
- pol_ce = type_str[11] == 'P';
- sig_ce = cell->getPort(ID::E);
- } else if (type_str.substr(0, 8) == "$_DFFSR_" && type_str.size() == 12) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[8] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_sr = true;
- pol_set = type_str[9] == 'P';
- pol_clr = type_str[10] == 'P';
- sig_set = cell->getPort(ID::S);
- sig_clr = cell->getPort(ID::R);
- } else if (type_str.substr(0, 9) == "$_DFFSRE_" && type_str.size() == 14) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[9] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_sr = true;
- pol_set = type_str[10] == 'P';
- pol_clr = type_str[11] == 'P';
- sig_set = cell->getPort(ID::S);
- sig_clr = cell->getPort(ID::R);
- has_ce = true;
- pol_ce = type_str[12] == 'P';
- sig_ce = cell->getPort(ID::E);
- } else if (type_str.substr(0, 7) == "$_SDFF_" && type_str.size() == 11) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[7] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_srst = true;
- pol_srst = type_str[8] == 'P';
- sig_srst = cell->getPort(ID::R);
- val_srst = type_str[9] == '1' ? State::S1 : State::S0;
- } else if (type_str.substr(0, 8) == "$_SDFFE_" && type_str.size() == 13) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[8] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_srst = true;
- pol_srst = type_str[9] == 'P';
- sig_srst = cell->getPort(ID::R);
- val_srst = type_str[10] == '1' ? State::S1 : State::S0;
- has_ce = true;
- pol_ce = type_str[11] == 'P';
- sig_ce = cell->getPort(ID::E);
- } else if (type_str.substr(0, 9) == "$_SDFFCE_" && type_str.size() == 14) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[9] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_srst = true;
- pol_srst = type_str[10] == 'P';
- sig_srst = cell->getPort(ID::R);
- val_srst = type_str[11] == '1' ? State::S1 : State::S0;
- has_ce = true;
- pol_ce = type_str[12] == 'P';
- sig_ce = cell->getPort(ID::E);
- ce_over_srst = true;
- } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 11) {
- is_fine = true;
- has_aload = true;
- sig_ad = cell->getPort(ID::D);
- has_aload = true;
- pol_aload = type_str[9] == 'P';
- sig_aload = cell->getPort(ID::E);
- } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 13) {
- is_fine = true;
- has_aload = true;
- sig_ad = cell->getPort(ID::D);
- has_aload = true;
- pol_aload = type_str[9] == 'P';
- sig_aload = cell->getPort(ID::E);
- has_arst = true;
- pol_arst = type_str[10] == 'P';
- sig_arst = cell->getPort(ID::R);
- val_arst = type_str[11] == '1' ? State::S1 : State::S0;
- } else if (type_str.substr(0, 11) == "$_DLATCHSR_" && type_str.size() == 15) {
- is_fine = true;
- has_aload = true;
- sig_ad = cell->getPort(ID::D);
- has_aload = true;
- pol_aload = type_str[11] == 'P';
- sig_aload = cell->getPort(ID::E);
- has_sr = true;
- pol_set = type_str[12] == 'P';
- pol_clr = type_str[13] == 'P';
- sig_set = cell->getPort(ID::S);
- sig_clr = cell->getPort(ID::R);
- } else {
- log_assert(0);
- }
- if (has_aload && !has_clk && !has_sr && !has_arst && sig_ad.is_fully_const()) {
- // Plain D latches with const D treated specially.
- has_aload = false;
- has_arst = true;
- sig_arst = sig_aload;
- pol_arst = pol_aload;
- val_arst = sig_ad.as_const();
- }
}
- // Returns a FF identical to this one, but only keeping bit indices from the argument.
- FfData slice(const std::vector<int> &bits) {
- FfData res(initvals);
- res.sig_clk = sig_clk;
- res.sig_ce = sig_ce;
- res.sig_aload = sig_aload;
- res.sig_arst = sig_arst;
- res.sig_srst = sig_srst;
- res.has_clk = has_clk;
- res.has_gclk = has_gclk;
- res.has_ce = has_ce;
- res.has_aload = has_aload;
- res.has_arst = has_arst;
- res.has_srst = has_srst;
- res.has_sr = has_sr;
- res.ce_over_srst = ce_over_srst;
- res.is_fine = is_fine;
- res.pol_clk = pol_clk;
- res.pol_ce = pol_ce;
- res.pol_aload = pol_aload;
- res.pol_arst = pol_arst;
- res.pol_srst = pol_srst;
- res.pol_clr = pol_clr;
- res.pol_set = pol_set;
- res.attributes = attributes;
- for (int i : bits) {
- res.sig_q.append(sig_q[i]);
- if (has_clk || has_gclk)
- res.sig_d.append(sig_d[i]);
- if (has_aload)
- res.sig_ad.append(sig_ad[i]);
- if (has_sr) {
- res.sig_clr.append(sig_clr[i]);
- res.sig_set.append(sig_set[i]);
- }
- if (has_arst)
- res.val_arst.bits.push_back(val_arst[i]);
- if (has_srst)
- res.val_srst.bits.push_back(val_srst[i]);
- if (initvals)
- res.val_init.bits.push_back(val_init[i]);
- }
- res.width = GetSize(res.sig_q);
- return res;
- }
+ FfData(FfInitVals *initvals, Cell *cell_);
- void unmap_ce(Module *module) {
- if (!has_ce)
- return;
- log_assert(has_clk);
- if (has_srst && ce_over_srst)
- unmap_srst(module);
+ // Returns a FF identical to this one, but only keeping bit indices from the argument.
+ FfData slice(const std::vector<int> &bits);
- if (!is_fine) {
- if (pol_ce)
- sig_d = module->Mux(NEW_ID, sig_q, sig_d, sig_ce);
- else
- sig_d = module->Mux(NEW_ID, sig_d, sig_q, sig_ce);
- } else {
- if (pol_ce)
- sig_d = module->MuxGate(NEW_ID, sig_q, sig_d, sig_ce);
- else
- sig_d = module->MuxGate(NEW_ID, sig_d, sig_q, sig_ce);
- }
- has_ce = false;
- }
+ void unmap_ce();
- void unmap_srst(Module *module) {
- if (!has_srst)
- return;
- if (has_ce && !ce_over_srst)
- unmap_ce(module);
+ void unmap_srst();
- if (!is_fine) {
- if (pol_srst)
- sig_d = module->Mux(NEW_ID, sig_d, val_srst, sig_srst);
- else
- sig_d = module->Mux(NEW_ID, val_srst, sig_d, sig_srst);
- } else {
- if (pol_srst)
- sig_d = module->MuxGate(NEW_ID, sig_d, val_srst[0], sig_srst);
- else
- sig_d = module->MuxGate(NEW_ID, val_srst[0], sig_d, sig_srst);
- }
- has_srst = false;
+ void unmap_ce_srst() {
+ unmap_ce();
+ unmap_srst();
}
- void unmap_ce_srst(Module *module) {
- unmap_ce(module);
- unmap_srst(module);
- }
+ Cell *emit();
- Cell *emit(Module *module, IdString name) {
- if (!width)
- return nullptr;
- if (!has_aload && !has_clk && !has_gclk && !has_sr) {
- if (has_arst) {
- // Convert this case to a D latch.
- has_aload = true;
- has_arst = false;
- sig_ad = val_arst;
- sig_aload = sig_arst;
- pol_aload = pol_arst;
- } else {
- // No control inputs left. Turn into a const driver.
- if (initvals)
- initvals->remove_init(sig_q);
- module->connect(sig_q, val_init);
- return nullptr;
- }
- }
+ // Removes init attribute from the Q output, but keeps val_init unchanged.
+ // It will be automatically reattached on emit. Use this before changing sig_q.
+ void remove_init() {
if (initvals)
- initvals->set_init(sig_q, val_init);
- Cell *cell;
- if (!is_fine) {
- if (has_gclk) {
- log_assert(!has_clk);
- log_assert(!has_ce);
- log_assert(!has_aload);
- log_assert(!has_arst);
- log_assert(!has_srst);
- log_assert(!has_sr);
- cell = module->addFf(name, sig_d, sig_q);
- } else if (!has_aload && !has_clk) {
- log_assert(has_sr);
- cell = module->addSr(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
- } else if (!has_clk) {
- log_assert(!has_srst);
- if (has_sr)
- cell = module->addDlatchsr(name, sig_aload, sig_set, sig_clr, sig_ad, sig_q, pol_aload, pol_set, pol_clr);
- else if (has_arst)
- cell = module->addAdlatch(name, sig_aload, sig_arst, sig_ad, sig_q, val_arst, pol_aload, pol_arst);
- else
- cell = module->addDlatch(name, sig_aload, sig_ad, sig_q, pol_aload);
- } else {
- if (has_sr) {
- if (has_ce)
- cell = module->addDffsre(name, sig_clk, sig_ce, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_ce, pol_set, pol_clr);
- else
- cell = module->addDffsr(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
- } else if (has_arst) {
- if (has_ce)
- cell = module->addAdffe(name, sig_clk, sig_ce, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_ce, pol_arst);
- else
- cell = module->addAdff(name, sig_clk, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_arst);
- } else if (has_aload) {
- if (has_ce)
- cell = module->addAldffe(name, sig_clk, sig_ce, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_ce, pol_aload);
- else
- cell = module->addAldff(name, sig_clk, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_aload);
- } else if (has_srst) {
- if (has_ce)
- if (ce_over_srst)
- cell = module->addSdffce(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_ce, pol_srst);
- else
- cell = module->addSdffe(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_ce, pol_srst);
- else
- cell = module->addSdff(name, sig_clk, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_srst);
- } else {
- if (has_ce)
- cell = module->addDffe(name, sig_clk, sig_ce, sig_d, sig_q, pol_clk, pol_ce);
- else
- cell = module->addDff(name, sig_clk, sig_d, sig_q, pol_clk);
- }
- }
- } else {
- if (has_gclk) {
- log_assert(!has_clk);
- log_assert(!has_ce);
- log_assert(!has_aload);
- log_assert(!has_arst);
- log_assert(!has_srst);
- log_assert(!has_sr);
- cell = module->addFfGate(name, sig_d, sig_q);
- } else if (!has_aload && !has_clk) {
- log_assert(has_sr);
- cell = module->addSrGate(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
- } else if (!has_clk) {
- log_assert(!has_srst);
- if (has_sr)
- cell = module->addDlatchsrGate(name, sig_aload, sig_set, sig_clr, sig_ad, sig_q, pol_aload, pol_set, pol_clr);
- else if (has_arst)
- cell = module->addAdlatchGate(name, sig_aload, sig_arst, sig_ad, sig_q, val_arst.as_bool(), pol_aload, pol_arst);
- else
- cell = module->addDlatchGate(name, sig_aload, sig_ad, sig_q, pol_aload);
- } else {
- if (has_sr) {
- if (has_ce)
- cell = module->addDffsreGate(name, sig_clk, sig_ce, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_ce, pol_set, pol_clr);
- else
- cell = module->addDffsrGate(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
- } else if (has_arst) {
- if (has_ce)
- cell = module->addAdffeGate(name, sig_clk, sig_ce, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_ce, pol_arst);
- else
- cell = module->addAdffGate(name, sig_clk, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_arst);
- } else if (has_aload) {
- if (has_ce)
- cell = module->addAldffeGate(name, sig_clk, sig_ce, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_ce, pol_aload);
- else
- cell = module->addAldffGate(name, sig_clk, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_aload);
- } else if (has_srst) {
- if (has_ce)
- if (ce_over_srst)
- cell = module->addSdffceGate(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_ce, pol_srst);
- else
- cell = module->addSdffeGate(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_ce, pol_srst);
- else
- cell = module->addSdffGate(name, sig_clk, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_srst);
- } else {
- if (has_ce)
- cell = module->addDffeGate(name, sig_clk, sig_ce, sig_d, sig_q, pol_clk, pol_ce);
- else
- cell = module->addDffGate(name, sig_clk, sig_d, sig_q, pol_clk);
- }
- }
- }
- cell->attributes = attributes;
- return cell;
+ initvals->remove_init(sig_q);
}
+
+ void remove();
+
+ // Flip the sense of the given bit slices of the FF: insert inverters on data
+ // inputs and output, flip the corresponding init/reset bits, swap clr/set
+ // inputs with proper priority fix.
+ void flip_bits(const pool<int> &bits);
};
YOSYS_NAMESPACE_END
diff --git a/kernel/ffmerge.cc b/kernel/ffmerge.cc
index 7d62a88cf..4ca5bcbb4 100644
--- a/kernel/ffmerge.cc
+++ b/kernel/ffmerge.cc
@@ -29,7 +29,7 @@ bool FfMergeHelper::is_output_unused(RTLIL::SigSpec sig) {
}
bool FfMergeHelper::find_output_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pair<Cell *, int>> &bits) {
- ff = FfData();
+ ff = FfData(module, initvals, NEW_ID);
sigmap->apply(sig);
bool found = false;
diff --git a/kernel/mem.cc b/kernel/mem.cc
index 40659b15b..746f667ea 100644
--- a/kernel/mem.cc
+++ b/kernel/mem.cc
@@ -955,7 +955,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
}
IdString name = stringf("$%s$rdreg[%d]", memid.c_str(), idx);
- FfData ff(initvals);
+ FfData ff(module, initvals, name);
ff.width = GetSize(port.data);
ff.has_clk = true;
ff.sig_clk = port.clk;
@@ -982,7 +982,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
ff.sig_q = port.data;
ff.val_init = port.init_value;
port.data = async_d;
- c = ff.emit(module, name);
+ c = ff.emit();
}
log("Extracted %s FF from read port %d of %s.%s: %s\n", trans_use_addr ? "addr" : "data",
@@ -1160,7 +1160,7 @@ void Mem::emulate_transparency(int widx, int ridx, FfInitVals *initvals) {
// The FF for storing the bypass enable signal must be carefully
// constructed to preserve the overall init/reset/enable behavior
// of the whole port.
- FfData ff(initvals);
+ FfData ff(module, initvals, NEW_ID);
ff.width = 1;
ff.sig_q = cond_q;
ff.sig_d = cond;
@@ -1189,7 +1189,7 @@ void Mem::emulate_transparency(int widx, int ridx, FfInitVals *initvals) {
ff.val_init = State::S0;
else
ff.val_init = State::Sx;
- ff.emit(module, NEW_ID);
+ ff.emit();
// And the final bypass mux.
SigSpec cur = rdata_a.extract(pos, epos-pos);
SigSpec other = wdata_q.extract(pos + wsub * width, epos-pos);