From 56461158b46212c429f88f9cb78640c1b216f525 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 31 Mar 2026 15:00:26 +0200 Subject: [PATCH 01/17] tests: use memory -bram-register in tests/bram --- tests/bram/run-single.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 tests/bram/run-single.sh diff --git a/tests/bram/run-single.sh b/tests/bram/run-single.sh old mode 100644 new mode 100755 index f7ce6f644..b10e36da6 --- a/tests/bram/run-single.sh +++ b/tests/bram/run-single.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -e -${YOSYS} -qq -f verilog -p "proc; opt; memory -nomap -bram temp/brams_${2}.txt; opt -fast -full" \ +${YOSYS} -qq -f verilog -p "proc; opt; memory -nomap -bram-register temp/brams_${2}.txt; opt -fast -full" \ -l temp/synth_${1}_${2}.log -o temp/synth_${1}_${2}.v temp/brams_${1}.v iverilog -Dvcd_file=\"temp/tb_${1}_${2}.vcd\" -DSIMLIB_MEMDELAY=1 -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v \ temp/brams_${1}_ref.v temp/synth_${1}_${2}.v temp/brams_${2}.v ../../techlibs/common/simlib.v From 25344b3947924b9e7c2435dbb0ff79831d4f4384 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 16 Apr 2026 15:50:05 +0200 Subject: [PATCH 02/17] Revert "tests: use memory -bram-register in tests/bram" This reverts commit 24488a7011474080bcb99a91d38ae27b2c2d813c. --- tests/bram/run-single.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 tests/bram/run-single.sh diff --git a/tests/bram/run-single.sh b/tests/bram/run-single.sh old mode 100755 new mode 100644 index b10e36da6..f7ce6f644 --- a/tests/bram/run-single.sh +++ b/tests/bram/run-single.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -e -${YOSYS} -qq -f verilog -p "proc; opt; memory -nomap -bram-register temp/brams_${2}.txt; opt -fast -full" \ +${YOSYS} -qq -f verilog -p "proc; opt; memory -nomap -bram temp/brams_${2}.txt; opt -fast -full" \ -l temp/synth_${1}_${2}.log -o temp/synth_${1}_${2}.v temp/brams_${1}.v iverilog -Dvcd_file=\"temp/tb_${1}_${2}.vcd\" -DSIMLIB_MEMDELAY=1 -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v \ temp/brams_${1}_ref.v temp/synth_${1}_${2}.v temp/brams_${2}.v ../../techlibs/common/simlib.v From b3f605e0d2c16757012c9f49cf594fe758d4485d Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 19 Dec 2025 19:14:33 +0100 Subject: [PATCH 03/17] patcher: start --- Makefile | 2 ++ kernel/rtlil.h | 5 +++-- kernel/unstable/Makefile.inc | 2 ++ kernel/unstable/patch.cc | 21 +++++++++++++++++++ kernel/unstable/patch.h | 39 ++++++++++++++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 kernel/unstable/Makefile.inc create mode 100644 kernel/unstable/patch.cc create mode 100644 kernel/unstable/patch.h diff --git a/Makefile b/Makefile index 6ee34070d..ab399ef2e 100644 --- a/Makefile +++ b/Makefile @@ -718,6 +718,8 @@ ifneq ($(SMALL),1) OBJS += libs/subcircuit/subcircuit.o +include $(YOSYS_SRC)/kernel/unstable/Makefile.inc + include $(YOSYS_SRC)/frontends/*/Makefile.inc include $(YOSYS_SRC)/passes/*/Makefile.inc include $(YOSYS_SRC)/backends/*/Makefile.inc diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 146a552e6..cf43df7f0 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -106,6 +106,7 @@ namespace RTLIL struct Monitor; struct Design; struct Module; + struct Patch; struct Wire; struct Memory; struct Cell; @@ -2527,13 +2528,13 @@ struct RTLIL::Cell : public RTLIL::NamedObject Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } -protected: +public: // use module->addCell() and module->remove() to create or destroy cells friend struct RTLIL::Module; + friend struct RTLIL::Patch; Cell(); ~Cell(); -public: // do not simply copy cells Cell(RTLIL::Cell &other) = delete; void operator=(RTLIL::Cell &other) = delete; diff --git a/kernel/unstable/Makefile.inc b/kernel/unstable/Makefile.inc new file mode 100644 index 000000000..35735eef2 --- /dev/null +++ b/kernel/unstable/Makefile.inc @@ -0,0 +1,2 @@ +OBJS += kernel/unstable/patch.o +$(eval $(call add_include_file,kernel/unstable/patch.h)) diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc new file mode 100644 index 000000000..18d761384 --- /dev/null +++ b/kernel/unstable/patch.cc @@ -0,0 +1,21 @@ +#include "kernel/unstable/patch.h" + +YOSYS_NAMESPACE_BEGIN + +using namespace RTLIL; +Cell* Patch::addCell(IdString name, IdString type) { + auto& cell = cells_.emplace_back(); + cell.name = std::move(name); + cell.type = type; + return &cell; +} +// RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, RTLIL::IdString type) +// { +// RTLIL::Cell *cell = new RTLIL::Cell; +// cell->name = std::move(name); +// cell->type = type; +// add(cell); +// return cell; +// } + +YOSYS_NAMESPACE_END \ No newline at end of file diff --git a/kernel/unstable/patch.h b/kernel/unstable/patch.h new file mode 100644 index 000000000..ede8b57cb --- /dev/null +++ b/kernel/unstable/patch.h @@ -0,0 +1,39 @@ +#ifndef PATCH_H +#define PATCH_H + +#include "kernel/rtlil.h" + +YOSYS_NAMESPACE_BEGIN + +struct RTLIL::Patch +{ + Hasher::hash_t hashidx_; + [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } + +protected: + void add(RTLIL::Wire *wire); + void add(RTLIL::Cell *cell); + void add(RTLIL::Process *process); + +public: + // RTLIL::Design *design; + vector wires_; + vector cells_; + + vector connections_; + + void connect(const RTLIL::SigSig &conn); + void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs); + const std::vector &connections() const; + + void patch(RTLIL::Module *mod); + RTLIL::Wire *addWire(RTLIL::IdString name, int width = 1); + RTLIL::Wire *addWire(RTLIL::IdString name, const RTLIL::Wire *other); + + RTLIL::Cell *addCell(RTLIL::IdString name, RTLIL::IdString type); + RTLIL::Cell *addCell(RTLIL::IdString name, const RTLIL::Cell *other); +}; + +YOSYS_NAMESPACE_END + +#endif From 3e6b74043020d0838f739f144fac4f14828ae429 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Sun, 21 Dec 2025 16:56:14 +0100 Subject: [PATCH 04/17] rtlil: allow friends to use Cell constructors with a factory token pattern --- kernel/rtlil.cc | 4 ++-- kernel/rtlil.h | 8 +++++--- kernel/unstable/patch.cc | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 5a3a5fb60..ac970e2f1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3129,7 +3129,7 @@ RTLIL::Wire *RTLIL::Module::addWire(RTLIL::IdString name, const RTLIL::Wire *oth RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, RTLIL::IdString type) { - RTLIL::Cell *cell = new RTLIL::Cell; + RTLIL::Cell *cell = new RTLIL::Cell(Cell::ConstructToken{}); cell->name = std::move(name); cell->type = type; add(cell); @@ -4243,7 +4243,7 @@ std::string RTLIL::Process::to_rtlil_str() const return f.str(); } -RTLIL::Cell::Cell() : module(nullptr) +RTLIL::Cell::Cell(RTLIL::Cell::ConstructToken) : module(nullptr) { static unsigned int hashidx_count = 123456789; hashidx_count = mkhash_xorshift(hashidx_count); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index cf43df7f0..6c22efcd5 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -2525,18 +2525,20 @@ struct RTLIL::Memory : public RTLIL::NamedObject struct RTLIL::Cell : public RTLIL::NamedObject { +private: + struct ConstructToken { explicit ConstructToken() = default; }; +public: Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } -public: // use module->addCell() and module->remove() to create or destroy cells friend struct RTLIL::Module; friend struct RTLIL::Patch; - Cell(); + Cell(ConstructToken); ~Cell(); // do not simply copy cells - Cell(RTLIL::Cell &other) = delete; + Cell(ConstructToken, RTLIL::Cell &other); void operator=(RTLIL::Cell &other) = delete; RTLIL::Module *module; diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index 18d761384..53632114d 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -4,7 +4,7 @@ YOSYS_NAMESPACE_BEGIN using namespace RTLIL; Cell* Patch::addCell(IdString name, IdString type) { - auto& cell = cells_.emplace_back(); + auto& cell = cells_.emplace_back(Cell::ConstructToken{}); cell.name = std::move(name); cell.type = type; return &cell; From 6f0be1b4e9f636809f761c03289021313cf85e4a Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 23 Dec 2025 16:58:16 +0100 Subject: [PATCH 05/17] rtlil: allow friends to use Wire constructors with a factory token pattern --- kernel/rtlil.h | 16 +++++++++------- kernel/unstable/patch.cc | 10 ++-------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 6c22efcd5..d21e0cd56 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -2454,18 +2454,20 @@ void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire); struct RTLIL::Wire : public RTLIL::NamedObject { +private: + struct ConstructToken { explicit ConstructToken() = default; }; + friend struct RTLIL::Design; + friend struct RTLIL::Cell; + friend struct RTLIL::Module; + friend struct RTLIL::Patch; +public: Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } - -protected: // use module->addWire() and module->remove() to create or destroy wires - friend struct RTLIL::Module; friend struct RTLIL::SigNormIndex; Wire(); ~Wire(); - friend struct RTLIL::Design; - friend struct RTLIL::Cell; friend void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire); RTLIL::Cell *driverCell_ = nullptr; RTLIL::IdString driverPort_; @@ -2527,13 +2529,13 @@ struct RTLIL::Cell : public RTLIL::NamedObject { private: struct ConstructToken { explicit ConstructToken() = default; }; + friend struct RTLIL::Module; + friend struct RTLIL::Patch; public: Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } // use module->addCell() and module->remove() to create or destroy cells - friend struct RTLIL::Module; - friend struct RTLIL::Patch; Cell(ConstructToken); ~Cell(); diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index 53632114d..8f01daaee 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -9,13 +9,7 @@ Cell* Patch::addCell(IdString name, IdString type) { cell.type = type; return &cell; } -// RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, RTLIL::IdString type) -// { -// RTLIL::Cell *cell = new RTLIL::Cell; -// cell->name = std::move(name); -// cell->type = type; -// add(cell); -// return cell; -// } + + YOSYS_NAMESPACE_END \ No newline at end of file From 89e5c4cccac6e8e904727301102f014a41efb04f Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 31 Dec 2025 17:46:27 +0100 Subject: [PATCH 06/17] test_patch total basics --- kernel/unstable/patch.cc | 20 ++++++++++++++++++++ kernel/unstable/patch.h | 8 +++++--- passes/cmds/Makefile.inc | 1 + passes/cmds/test_patch.cc | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 passes/cmds/test_patch.cc diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index 8f01daaee..976a769fe 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -1,4 +1,6 @@ #include "kernel/unstable/patch.h" +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" YOSYS_NAMESPACE_BEGIN @@ -10,6 +12,24 @@ Cell* Patch::addCell(IdString name, IdString type) { return &cell; } +void Patch::patch() { + for (auto& cell: cells_) { + Cell* new_cell = mod->addCell(cell.name, &cell); + for (auto [port_name, sig] : new_cell->connections()) { + log_assert(yosys_celltypes.cell_known(cell.type)); + auto dir = cell.port_dir(port_name); + if (dir == PD_OUTPUT || dir == PD_INOUT) { + for (auto chunk : sig.chunks()) { + log_assert(chunk.is_wire()); + auto* wire = chunk.wire; + wire->driverCell_->setPort(wire->driverPort_, SigSpec()); + wire->driverCell_ = new_cell; + wire->driverPort_ = port_name; + } + } + } + } +} YOSYS_NAMESPACE_END \ No newline at end of file diff --git a/kernel/unstable/patch.h b/kernel/unstable/patch.h index ede8b57cb..150ca379a 100644 --- a/kernel/unstable/patch.h +++ b/kernel/unstable/patch.h @@ -2,6 +2,7 @@ #define PATCH_H #include "kernel/rtlil.h" +#include "kernel/sigtools.h" YOSYS_NAMESPACE_BEGIN @@ -16,17 +17,18 @@ protected: void add(RTLIL::Process *process); public: - // RTLIL::Design *design; + Module *mod; + SigMap map; vector wires_; vector cells_; - vector connections_; + vector connections_; void connect(const RTLIL::SigSig &conn); void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs); const std::vector &connections() const; - void patch(RTLIL::Module *mod); + void patch(); RTLIL::Wire *addWire(RTLIL::IdString name, int width = 1); RTLIL::Wire *addWire(RTLIL::IdString name, const RTLIL::Wire *other); diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc index 5e2994a53..587963095 100644 --- a/passes/cmds/Makefile.inc +++ b/passes/cmds/Makefile.inc @@ -60,5 +60,6 @@ OBJS += passes/cmds/timeest.o OBJS += passes/cmds/linecoverage.o OBJS += passes/cmds/sort.o OBJS += passes/cmds/icell_liberty.o +OBJS += passes/cmds/test_patch.o include $(YOSYS_SRC)/passes/cmds/sdc/Makefile.inc diff --git a/passes/cmds/test_patch.cc b/passes/cmds/test_patch.cc new file mode 100644 index 000000000..ba7ad851f --- /dev/null +++ b/passes/cmds/test_patch.cc @@ -0,0 +1,36 @@ +#include "kernel/rtlil.h" +#include "kernel/yosys.h" +#include "kernel/unstable/patch.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct TestPatchPass : public Pass { + TestPatchPass() : Pass("test_patch", "test patcher") { } + void help() override + { + } + void execute(std::vector args, RTLIL::Design *design) override + { + (void) args; + RTLIL::Patch patcher; + design->bufNormalize(); + for (auto module : design->selected_modules()) { + patcher.mod = module; + patcher.map = SigMap(module); + for (auto cell : module->selected_cells()) { + if (cell->type == ID($add)) { + RTLIL::Cell* sub = patcher.addCell(NEW_ID, ID($sub)); + sub->connections_ = cell->connections(); + sub->parameters = cell->parameters; + sub->setPort(ID::A, cell->getPort(ID::A)); + sub->setPort(ID::B, cell->getPort(ID::B)); + sub->setPort(ID::Y, cell->getPort(ID::Y)); + patcher.patch(); + } + } + } + } +} TestPatchPass; + +PRIVATE_NAMESPACE_END From 770d74cc9b51d6b8ef0e3c4d3dee0a63ca83c02e Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 31 Dec 2025 17:59:24 +0100 Subject: [PATCH 07/17] patch: GC comment --- kernel/unstable/patch.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index 976a769fe..33bbb9777 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -4,6 +4,14 @@ YOSYS_NAMESPACE_BEGIN +/** + * Notes + * + * If we want GC, we need more indices + * namely user count (and users?). This should be optional + * + * +*/ using namespace RTLIL; Cell* Patch::addCell(IdString name, IdString type) { auto& cell = cells_.emplace_back(Cell::ConstructToken{}); @@ -22,7 +30,9 @@ void Patch::patch() { for (auto chunk : sig.chunks()) { log_assert(chunk.is_wire()); auto* wire = chunk.wire; + // Unwire old driver wire->driverCell_->setPort(wire->driverPort_, SigSpec()); + // Maintain bufnorm wire->driverCell_ = new_cell; wire->driverPort_ = port_name; } From dbc7e3390820bda93bab3cabdffdd9af03604a1a Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 1 Jan 2026 17:06:38 +0100 Subject: [PATCH 08/17] rtlil: add CellAdderMixin for shared Cell adder interface between Module and Patch --- kernel/rtlil.cc | 1598 +++++++++++++++++++------------------- kernel/rtlil.h | 870 +++++++++++---------- kernel/unstable/patch.cc | 62 +- kernel/unstable/patch.h | 5 +- 4 files changed, 1283 insertions(+), 1252 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index ac970e2f1..134082585 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3106,7 +3106,7 @@ void RTLIL::Module::fixup_ports() RTLIL::Wire *RTLIL::Module::addWire(RTLIL::IdString name, int width) { - RTLIL::Wire *wire = new RTLIL::Wire; + RTLIL::Wire *wire = new RTLIL::Wire(Wire::ConstructToken{}); wire->name = std::move(name); wire->width = width; add(wire); @@ -3181,850 +3181,850 @@ RTLIL::Process *RTLIL::Module::addProcess(RTLIL::IdString name, const RTLIL::Pro return proc; } -#define DEF_METHOD(_func, _y_size, _type) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::A_SIGNED] = is_signed; \ - cell->parameters[ID::A_WIDTH] = sig_a.size(); \ - cell->parameters[ID::Y_WIDTH] = sig_y.size(); \ - cell->setPort(ID::A, sig_a); \ - cell->setPort(ID::Y, sig_y); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed, const std::string &src) { \ - RTLIL::SigSpec sig_y = addWire(NEW_ID, _y_size); \ - add ## _func(name, sig_a, sig_y, is_signed, src); \ - return sig_y; \ + #define DEF_METHOD(_func, _y_size, _type) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->parameters[ID::A_SIGNED] = is_signed; \ + cell->parameters[ID::A_WIDTH] = sig_a.size(); \ + cell->parameters[ID::Y_WIDTH] = sig_y.size(); \ + cell->setPort(ID::A, sig_a); \ + cell->setPort(ID::Y, sig_y); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigSpec CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed, const std::string &src) { \ + RTLIL::SigSpec sig_y = static_cast(this)->addWire(NEW_ID, _y_size); \ + add ## _func(name, sig_a, sig_y, is_signed, src); \ + return sig_y; \ + } + DEF_METHOD(Not, sig_a.size(), ID($not)) + DEF_METHOD(Pos, sig_a.size(), ID($pos)) + DEF_METHOD(Neg, sig_a.size(), ID($neg)) + DEF_METHOD(ReduceAnd, 1, ID($reduce_and)) + DEF_METHOD(ReduceOr, 1, ID($reduce_or)) + DEF_METHOD(ReduceXor, 1, ID($reduce_xor)) + DEF_METHOD(ReduceXnor, 1, ID($reduce_xnor)) + DEF_METHOD(ReduceBool, 1, ID($reduce_bool)) + DEF_METHOD(LogicNot, 1, ID($logic_not)) + #undef DEF_METHOD + + #define DEF_METHOD(_func, _y_size, _type) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool /* is_signed */, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->parameters[ID::WIDTH] = sig_a.size(); \ + cell->setPort(ID::A, sig_a); \ + cell->setPort(ID::Y, sig_y); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigSpec CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed, const std::string &src) { \ + RTLIL::SigSpec sig_y = static_cast(this)->addWire(NEW_ID, _y_size); \ + add ## _func(name, sig_a, sig_y, is_signed, src); \ + return sig_y; \ + } + DEF_METHOD(Buf, sig_a.size(), ID($buf)) + #undef DEF_METHOD + + #define DEF_METHOD(_func, _y_size, _type) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->parameters[ID::A_SIGNED] = is_signed; \ + cell->parameters[ID::B_SIGNED] = is_signed; \ + cell->parameters[ID::A_WIDTH] = sig_a.size(); \ + cell->parameters[ID::B_WIDTH] = sig_b.size(); \ + cell->parameters[ID::Y_WIDTH] = sig_y.size(); \ + cell->setPort(ID::A, sig_a); \ + cell->setPort(ID::B, sig_b); \ + cell->setPort(ID::Y, sig_y); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigSpec CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed, const std::string &src) { \ + RTLIL::SigSpec sig_y = static_cast(this)->addWire(NEW_ID, _y_size); \ + add ## _func(name, sig_a, sig_b, sig_y, is_signed, src); \ + return sig_y; \ + } + DEF_METHOD(And, max(sig_a.size(), sig_b.size()), ID($and)) + DEF_METHOD(Or, max(sig_a.size(), sig_b.size()), ID($or)) + DEF_METHOD(Xor, max(sig_a.size(), sig_b.size()), ID($xor)) + DEF_METHOD(Xnor, max(sig_a.size(), sig_b.size()), ID($xnor)) + DEF_METHOD(Shift, sig_a.size(), ID($shift)) + DEF_METHOD(Lt, 1, ID($lt)) + DEF_METHOD(Le, 1, ID($le)) + DEF_METHOD(Eq, 1, ID($eq)) + DEF_METHOD(Ne, 1, ID($ne)) + DEF_METHOD(Eqx, 1, ID($eqx)) + DEF_METHOD(Nex, 1, ID($nex)) + DEF_METHOD(Ge, 1, ID($ge)) + DEF_METHOD(Gt, 1, ID($gt)) + DEF_METHOD(Add, max(sig_a.size(), sig_b.size()), ID($add)) + DEF_METHOD(Sub, max(sig_a.size(), sig_b.size()), ID($sub)) + DEF_METHOD(Mul, max(sig_a.size(), sig_b.size()), ID($mul)) + DEF_METHOD(Div, max(sig_a.size(), sig_b.size()), ID($div)) + DEF_METHOD(Mod, max(sig_a.size(), sig_b.size()), ID($mod)) + DEF_METHOD(DivFloor, max(sig_a.size(), sig_b.size()), ID($divfloor)) + DEF_METHOD(ModFloor, max(sig_a.size(), sig_b.size()), ID($modfloor)) + DEF_METHOD(LogicAnd, 1, ID($logic_and)) + DEF_METHOD(LogicOr, 1, ID($logic_or)) + #undef DEF_METHOD + + #define DEF_METHOD(_func, _y_size, _type) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->parameters[ID::A_SIGNED] = is_signed; \ + cell->parameters[ID::B_SIGNED] = false; \ + cell->parameters[ID::A_WIDTH] = sig_a.size(); \ + cell->parameters[ID::B_WIDTH] = sig_b.size(); \ + cell->parameters[ID::Y_WIDTH] = sig_y.size(); \ + cell->setPort(ID::A, sig_a); \ + cell->setPort(ID::B, sig_b); \ + cell->setPort(ID::Y, sig_y); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigSpec CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed, const std::string &src) { \ + RTLIL::SigSpec sig_y = static_cast(this)->addWire(NEW_ID, _y_size); \ + add ## _func(name, sig_a, sig_b, sig_y, is_signed, src); \ + return sig_y; \ + } + DEF_METHOD(Shl, sig_a.size(), ID($shl)) + DEF_METHOD(Shr, sig_a.size(), ID($shr)) + DEF_METHOD(Sshl, sig_a.size(), ID($sshl)) + DEF_METHOD(Sshr, sig_a.size(), ID($sshr)) + #undef DEF_METHOD + + #define DEF_METHOD(_func, _y_size, _type) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->parameters[ID::A_SIGNED] = false; \ + cell->parameters[ID::B_SIGNED] = is_signed; \ + cell->parameters[ID::A_WIDTH] = sig_a.size(); \ + cell->parameters[ID::B_WIDTH] = sig_b.size(); \ + cell->parameters[ID::Y_WIDTH] = sig_y.size(); \ + cell->setPort(ID::A, sig_a); \ + cell->setPort(ID::B, sig_b); \ + cell->setPort(ID::Y, sig_y); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigSpec CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed, const std::string &src) { \ + RTLIL::SigSpec sig_y = static_cast(this)->addWire(NEW_ID, _y_size); \ + add ## _func(name, sig_a, sig_b, sig_y, is_signed, src); \ + return sig_y; \ + } + DEF_METHOD(Shiftx, sig_a.size(), ID($shiftx)) + #undef DEF_METHOD + + #define DEF_METHOD(_func, _type, _pmux) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->parameters[ID::WIDTH] = sig_a.size(); \ + if (_pmux) cell->parameters[ID::S_WIDTH] = sig_s.size(); \ + cell->setPort(ID::A, sig_a); \ + cell->setPort(ID::B, sig_b); \ + cell->setPort(ID::S, sig_s); \ + cell->setPort(ID::Y, sig_y); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigSpec CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src) { \ + RTLIL::SigSpec sig_y = static_cast(this)->addWire(NEW_ID, sig_a.size()); \ + add ## _func(name, sig_a, sig_b, sig_s, sig_y, src); \ + return sig_y; \ + } + DEF_METHOD(Mux, ID($mux), 0) + DEF_METHOD(Bwmux, ID($bwmux), 0) + DEF_METHOD(Pmux, ID($pmux), 1) + #undef DEF_METHOD + + #define DEF_METHOD(_func, _type, _demux) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->parameters[ID::WIDTH] = _demux ? sig_a.size() : sig_y.size(); \ + cell->parameters[ID::S_WIDTH] = sig_s.size(); \ + cell->setPort(ID::A, sig_a); \ + cell->setPort(ID::S, sig_s); \ + cell->setPort(ID::Y, sig_y); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigSpec CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src) { \ + RTLIL::SigSpec sig_y = static_cast(this)->addWire(NEW_ID, _demux ? sig_a.size() << sig_s.size() : sig_a.size() >> sig_s.size()); \ + add ## _func(name, sig_a, sig_s, sig_y, src); \ + return sig_y; \ + } + DEF_METHOD(Bmux, ID($bmux), 0) + DEF_METHOD(Demux, ID($demux), 1) + #undef DEF_METHOD + + #define DEF_METHOD(_func, _type) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->parameters[ID::WIDTH] = sig_a.size(); \ + cell->setPort(ID::A, sig_a); \ + cell->setPort(ID::B, sig_b); \ + cell->setPort(ID::Y, sig_y); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigSpec CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src) { \ + RTLIL::SigSpec sig_y = static_cast(this)->addWire(NEW_ID, sig_a.size()); \ + add ## _func(name, sig_a, sig_s, sig_y, src); \ + return sig_y; \ + } + DEF_METHOD(Bweqx, ID($bweqx)) + #undef DEF_METHOD + + #define DEF_METHOD_2(_func, _type, _P1, _P2) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->setPort("\\" #_P1, sig1); \ + cell->setPort("\\" #_P2, sig2); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigBit CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const std::string &src) { \ + RTLIL::SigBit sig2 = static_cast(this)->addWire(NEW_ID); \ + add ## _func(name, sig1, sig2, src); \ + return sig2; \ + } + #define DEF_METHOD_3(_func, _type, _P1, _P2, _P3) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->setPort("\\" #_P1, sig1); \ + cell->setPort("\\" #_P2, sig2); \ + cell->setPort("\\" #_P3, sig3); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigBit CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const std::string &src) { \ + RTLIL::SigBit sig3 = static_cast(this)->addWire(NEW_ID); \ + add ## _func(name, sig1, sig2, sig3, src); \ + return sig3; \ + } + #define DEF_METHOD_4(_func, _type, _P1, _P2, _P3, _P4) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const RTLIL::SigBit &sig4, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->setPort("\\" #_P1, sig1); \ + cell->setPort("\\" #_P2, sig2); \ + cell->setPort("\\" #_P3, sig3); \ + cell->setPort("\\" #_P4, sig4); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigBit CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const std::string &src) { \ + RTLIL::SigBit sig4 = static_cast(this)->addWire(NEW_ID); \ + add ## _func(name, sig1, sig2, sig3, sig4, src); \ + return sig4; \ + } + #define DEF_METHOD_5(_func, _type, _P1, _P2, _P3, _P4, _P5) \ + template RTLIL::Cell* CellAdderMixin::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const RTLIL::SigBit &sig4, const RTLIL::SigBit &sig5, const std::string &src) { \ + RTLIL::Cell *cell = static_cast(this)->addCell(name, _type); \ + cell->setPort("\\" #_P1, sig1); \ + cell->setPort("\\" #_P2, sig2); \ + cell->setPort("\\" #_P3, sig3); \ + cell->setPort("\\" #_P4, sig4); \ + cell->setPort("\\" #_P5, sig5); \ + cell->set_src_attribute(src); \ + return cell; \ + } \ + template RTLIL::SigBit CellAdderMixin::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const RTLIL::SigBit &sig4, const std::string &src) { \ + RTLIL::SigBit sig5 = static_cast(this)->addWire(NEW_ID); \ + add ## _func(name, sig1, sig2, sig3, sig4, sig5, src); \ + return sig5; \ + } + DEF_METHOD_2(BufGate, ID($_BUF_), A, Y) + DEF_METHOD_2(NotGate, ID($_NOT_), A, Y) + DEF_METHOD_3(AndGate, ID($_AND_), A, B, Y) + DEF_METHOD_3(NandGate, ID($_NAND_), A, B, Y) + DEF_METHOD_3(OrGate, ID($_OR_), A, B, Y) + DEF_METHOD_3(NorGate, ID($_NOR_), A, B, Y) + DEF_METHOD_3(XorGate, ID($_XOR_), A, B, Y) + DEF_METHOD_3(XnorGate, ID($_XNOR_), A, B, Y) + DEF_METHOD_3(AndnotGate, ID($_ANDNOT_), A, B, Y) + DEF_METHOD_3(OrnotGate, ID($_ORNOT_), A, B, Y) + DEF_METHOD_4(MuxGate, ID($_MUX_), A, B, S, Y) + DEF_METHOD_4(NmuxGate, ID($_NMUX_), A, B, S, Y) + DEF_METHOD_4(Aoi3Gate, ID($_AOI3_), A, B, C, Y) + DEF_METHOD_4(Oai3Gate, ID($_OAI3_), A, B, C, Y) + DEF_METHOD_5(Aoi4Gate, ID($_AOI4_), A, B, C, D, Y) + DEF_METHOD_5(Oai4Gate, ID($_OAI4_), A, B, C, D, Y) + #undef DEF_METHOD_2 + #undef DEF_METHOD_3 + #undef DEF_METHOD_4 + #undef DEF_METHOD_5 + + template RTLIL::Cell* CellAdderMixin::addPow(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool a_signed, bool b_signed, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($pow)); + cell->parameters[ID::A_SIGNED] = a_signed; + cell->parameters[ID::B_SIGNED] = b_signed; + cell->parameters[ID::A_WIDTH] = sig_a.size(); + cell->parameters[ID::B_WIDTH] = sig_b.size(); + cell->parameters[ID::Y_WIDTH] = sig_y.size(); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::B, sig_b); + cell->setPort(ID::Y, sig_y); + cell->set_src_attribute(src); + return cell; } -DEF_METHOD(Not, sig_a.size(), ID($not)) -DEF_METHOD(Pos, sig_a.size(), ID($pos)) -DEF_METHOD(Neg, sig_a.size(), ID($neg)) -DEF_METHOD(ReduceAnd, 1, ID($reduce_and)) -DEF_METHOD(ReduceOr, 1, ID($reduce_or)) -DEF_METHOD(ReduceXor, 1, ID($reduce_xor)) -DEF_METHOD(ReduceXnor, 1, ID($reduce_xnor)) -DEF_METHOD(ReduceBool, 1, ID($reduce_bool)) -DEF_METHOD(LogicNot, 1, ID($logic_not)) -#undef DEF_METHOD -#define DEF_METHOD(_func, _y_size, _type) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool /* is_signed */, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::WIDTH] = sig_a.size(); \ - cell->setPort(ID::A, sig_a); \ - cell->setPort(ID::Y, sig_y); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed, const std::string &src) { \ - RTLIL::SigSpec sig_y = addWire(NEW_ID, _y_size); \ - add ## _func(name, sig_a, sig_y, is_signed, src); \ - return sig_y; \ + template RTLIL::Cell* CellAdderMixin::addFa(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_c, const RTLIL::SigSpec &sig_x, const RTLIL::SigSpec &sig_y, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($fa)); + cell->parameters[ID::WIDTH] = sig_a.size(); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::B, sig_b); + cell->setPort(ID::C, sig_c); + cell->setPort(ID::X, sig_x); + cell->setPort(ID::Y, sig_y); + cell->set_src_attribute(src); + return cell; } -DEF_METHOD(Buf, sig_a.size(), ID($buf)) -#undef DEF_METHOD -#define DEF_METHOD(_func, _y_size, _type) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::A_SIGNED] = is_signed; \ - cell->parameters[ID::B_SIGNED] = is_signed; \ - cell->parameters[ID::A_WIDTH] = sig_a.size(); \ - cell->parameters[ID::B_WIDTH] = sig_b.size(); \ - cell->parameters[ID::Y_WIDTH] = sig_y.size(); \ - cell->setPort(ID::A, sig_a); \ - cell->setPort(ID::B, sig_b); \ - cell->setPort(ID::Y, sig_y); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed, const std::string &src) { \ - RTLIL::SigSpec sig_y = addWire(NEW_ID, _y_size); \ - add ## _func(name, sig_a, sig_b, sig_y, is_signed, src); \ - return sig_y; \ + template RTLIL::Cell* CellAdderMixin::addSlice(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const offset, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($slice)); + cell->parameters[ID::A_WIDTH] = sig_a.size(); + cell->parameters[ID::Y_WIDTH] = sig_y.size(); + cell->parameters[ID::OFFSET] = offset; + cell->setPort(ID::A, sig_a); + cell->setPort(ID::Y, sig_y); + cell->set_src_attribute(src); + return cell; } -DEF_METHOD(And, max(sig_a.size(), sig_b.size()), ID($and)) -DEF_METHOD(Or, max(sig_a.size(), sig_b.size()), ID($or)) -DEF_METHOD(Xor, max(sig_a.size(), sig_b.size()), ID($xor)) -DEF_METHOD(Xnor, max(sig_a.size(), sig_b.size()), ID($xnor)) -DEF_METHOD(Shift, sig_a.size(), ID($shift)) -DEF_METHOD(Lt, 1, ID($lt)) -DEF_METHOD(Le, 1, ID($le)) -DEF_METHOD(Eq, 1, ID($eq)) -DEF_METHOD(Ne, 1, ID($ne)) -DEF_METHOD(Eqx, 1, ID($eqx)) -DEF_METHOD(Nex, 1, ID($nex)) -DEF_METHOD(Ge, 1, ID($ge)) -DEF_METHOD(Gt, 1, ID($gt)) -DEF_METHOD(Add, max(sig_a.size(), sig_b.size()), ID($add)) -DEF_METHOD(Sub, max(sig_a.size(), sig_b.size()), ID($sub)) -DEF_METHOD(Mul, max(sig_a.size(), sig_b.size()), ID($mul)) -DEF_METHOD(Div, max(sig_a.size(), sig_b.size()), ID($div)) -DEF_METHOD(Mod, max(sig_a.size(), sig_b.size()), ID($mod)) -DEF_METHOD(DivFloor, max(sig_a.size(), sig_b.size()), ID($divfloor)) -DEF_METHOD(ModFloor, max(sig_a.size(), sig_b.size()), ID($modfloor)) -DEF_METHOD(LogicAnd, 1, ID($logic_and)) -DEF_METHOD(LogicOr, 1, ID($logic_or)) -#undef DEF_METHOD -#define DEF_METHOD(_func, _y_size, _type) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::A_SIGNED] = is_signed; \ - cell->parameters[ID::B_SIGNED] = false; \ - cell->parameters[ID::A_WIDTH] = sig_a.size(); \ - cell->parameters[ID::B_WIDTH] = sig_b.size(); \ - cell->parameters[ID::Y_WIDTH] = sig_y.size(); \ - cell->setPort(ID::A, sig_a); \ - cell->setPort(ID::B, sig_b); \ - cell->setPort(ID::Y, sig_y); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed, const std::string &src) { \ - RTLIL::SigSpec sig_y = addWire(NEW_ID, _y_size); \ - add ## _func(name, sig_a, sig_b, sig_y, is_signed, src); \ - return sig_y; \ + template RTLIL::Cell* CellAdderMixin::addConcat(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($concat)); + cell->parameters[ID::A_WIDTH] = sig_a.size(); + cell->parameters[ID::B_WIDTH] = sig_b.size(); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::B, sig_b); + cell->setPort(ID::Y, sig_y); + cell->set_src_attribute(src); + return cell; } -DEF_METHOD(Shl, sig_a.size(), ID($shl)) -DEF_METHOD(Shr, sig_a.size(), ID($shr)) -DEF_METHOD(Sshl, sig_a.size(), ID($sshl)) -DEF_METHOD(Sshr, sig_a.size(), ID($sshr)) -#undef DEF_METHOD -#define DEF_METHOD(_func, _y_size, _type) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::A_SIGNED] = false; \ - cell->parameters[ID::B_SIGNED] = is_signed; \ - cell->parameters[ID::A_WIDTH] = sig_a.size(); \ - cell->parameters[ID::B_WIDTH] = sig_b.size(); \ - cell->parameters[ID::Y_WIDTH] = sig_y.size(); \ - cell->setPort(ID::A, sig_a); \ - cell->setPort(ID::B, sig_b); \ - cell->setPort(ID::Y, sig_y); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed, const std::string &src) { \ - RTLIL::SigSpec sig_y = addWire(NEW_ID, _y_size); \ - add ## _func(name, sig_a, sig_b, sig_y, is_signed, src); \ - return sig_y; \ + template RTLIL::Cell* CellAdderMixin::addLut(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const lut, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($lut)); + cell->parameters[ID::LUT] = lut; + cell->parameters[ID::WIDTH] = sig_a.size(); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::Y, sig_y); + cell->set_src_attribute(src); + return cell; } -DEF_METHOD(Shiftx, sig_a.size(), ID($shiftx)) -#undef DEF_METHOD -#define DEF_METHOD(_func, _type, _pmux) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::WIDTH] = sig_a.size(); \ - if (_pmux) cell->parameters[ID::S_WIDTH] = sig_s.size(); \ - cell->setPort(ID::A, sig_a); \ - cell->setPort(ID::B, sig_b); \ - cell->setPort(ID::S, sig_s); \ - cell->setPort(ID::Y, sig_y); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src) { \ - RTLIL::SigSpec sig_y = addWire(NEW_ID, sig_a.size()); \ - add ## _func(name, sig_a, sig_b, sig_s, sig_y, src); \ - return sig_y; \ + template RTLIL::Cell* CellAdderMixin::addTribuf(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_y, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($tribuf)); + cell->parameters[ID::WIDTH] = sig_a.size(); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::EN, sig_en); + cell->setPort(ID::Y, sig_y); + cell->set_src_attribute(src); + return cell; } -DEF_METHOD(Mux, ID($mux), 0) -DEF_METHOD(Bwmux, ID($bwmux), 0) -DEF_METHOD(Pmux, ID($pmux), 1) -#undef DEF_METHOD -#define DEF_METHOD(_func, _type, _demux) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::WIDTH] = _demux ? sig_a.size() : sig_y.size(); \ - cell->parameters[ID::S_WIDTH] = sig_s.size(); \ - cell->setPort(ID::A, sig_a); \ - cell->setPort(ID::S, sig_s); \ - cell->setPort(ID::Y, sig_y); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src) { \ - RTLIL::SigSpec sig_y = addWire(NEW_ID, _demux ? sig_a.size() << sig_s.size() : sig_a.size() >> sig_s.size()); \ - add ## _func(name, sig_a, sig_s, sig_y, src); \ - return sig_y; \ + template RTLIL::Cell* CellAdderMixin::addAssert(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($assert)); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::EN, sig_en); + cell->set_src_attribute(src); + return cell; } -DEF_METHOD(Bmux, ID($bmux), 0) -DEF_METHOD(Demux, ID($demux), 1) -#undef DEF_METHOD -#define DEF_METHOD(_func, _type) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->parameters[ID::WIDTH] = sig_a.size(); \ - cell->setPort(ID::A, sig_a); \ - cell->setPort(ID::B, sig_b); \ - cell->setPort(ID::Y, sig_y); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src) { \ - RTLIL::SigSpec sig_y = addWire(NEW_ID, sig_a.size()); \ - add ## _func(name, sig_a, sig_s, sig_y, src); \ - return sig_y; \ + template RTLIL::Cell* CellAdderMixin::addAssume(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($assume)); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::EN, sig_en); + cell->set_src_attribute(src); + return cell; } -DEF_METHOD(Bweqx, ID($bweqx)) -#undef DEF_METHOD -#define DEF_METHOD_2(_func, _type, _P1, _P2) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->setPort("\\" #_P1, sig1); \ - cell->setPort("\\" #_P2, sig2); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const std::string &src) { \ - RTLIL::SigBit sig2 = addWire(NEW_ID); \ - add ## _func(name, sig1, sig2, src); \ - return sig2; \ + template RTLIL::Cell* CellAdderMixin::addLive(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($live)); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::EN, sig_en); + cell->set_src_attribute(src); + return cell; } -#define DEF_METHOD_3(_func, _type, _P1, _P2, _P3) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->setPort("\\" #_P1, sig1); \ - cell->setPort("\\" #_P2, sig2); \ - cell->setPort("\\" #_P3, sig3); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const std::string &src) { \ - RTLIL::SigBit sig3 = addWire(NEW_ID); \ - add ## _func(name, sig1, sig2, sig3, src); \ - return sig3; \ + + template RTLIL::Cell* CellAdderMixin::addFair(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($fair)); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::EN, sig_en); + cell->set_src_attribute(src); + return cell; } -#define DEF_METHOD_4(_func, _type, _P1, _P2, _P3, _P4) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const RTLIL::SigBit &sig4, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->setPort("\\" #_P1, sig1); \ - cell->setPort("\\" #_P2, sig2); \ - cell->setPort("\\" #_P3, sig3); \ - cell->setPort("\\" #_P4, sig4); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const std::string &src) { \ - RTLIL::SigBit sig4 = addWire(NEW_ID); \ - add ## _func(name, sig1, sig2, sig3, sig4, src); \ - return sig4; \ + + template RTLIL::Cell* CellAdderMixin::addCover(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($cover)); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::EN, sig_en); + cell->set_src_attribute(src); + return cell; } -#define DEF_METHOD_5(_func, _type, _P1, _P2, _P3, _P4, _P5) \ - RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const RTLIL::SigBit &sig4, const RTLIL::SigBit &sig5, const std::string &src) { \ - RTLIL::Cell *cell = addCell(name, _type); \ - cell->setPort("\\" #_P1, sig1); \ - cell->setPort("\\" #_P2, sig2); \ - cell->setPort("\\" #_P3, sig3); \ - cell->setPort("\\" #_P4, sig4); \ - cell->setPort("\\" #_P5, sig5); \ - cell->set_src_attribute(src); \ - return cell; \ - } \ - RTLIL::SigBit RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const RTLIL::SigBit &sig3, const RTLIL::SigBit &sig4, const std::string &src) { \ - RTLIL::SigBit sig5 = addWire(NEW_ID); \ - add ## _func(name, sig1, sig2, sig3, sig4, sig5, src); \ - return sig5; \ + + template RTLIL::Cell* CellAdderMixin::addEquiv(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($equiv)); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::B, sig_b); + cell->setPort(ID::Y, sig_y); + cell->set_src_attribute(src); + return cell; } -DEF_METHOD_2(BufGate, ID($_BUF_), A, Y) -DEF_METHOD_2(NotGate, ID($_NOT_), A, Y) -DEF_METHOD_3(AndGate, ID($_AND_), A, B, Y) -DEF_METHOD_3(NandGate, ID($_NAND_), A, B, Y) -DEF_METHOD_3(OrGate, ID($_OR_), A, B, Y) -DEF_METHOD_3(NorGate, ID($_NOR_), A, B, Y) -DEF_METHOD_3(XorGate, ID($_XOR_), A, B, Y) -DEF_METHOD_3(XnorGate, ID($_XNOR_), A, B, Y) -DEF_METHOD_3(AndnotGate, ID($_ANDNOT_), A, B, Y) -DEF_METHOD_3(OrnotGate, ID($_ORNOT_), A, B, Y) -DEF_METHOD_4(MuxGate, ID($_MUX_), A, B, S, Y) -DEF_METHOD_4(NmuxGate, ID($_NMUX_), A, B, S, Y) -DEF_METHOD_4(Aoi3Gate, ID($_AOI3_), A, B, C, Y) -DEF_METHOD_4(Oai3Gate, ID($_OAI3_), A, B, C, Y) -DEF_METHOD_5(Aoi4Gate, ID($_AOI4_), A, B, C, D, Y) -DEF_METHOD_5(Oai4Gate, ID($_OAI4_), A, B, C, D, Y) -#undef DEF_METHOD_2 -#undef DEF_METHOD_3 -#undef DEF_METHOD_4 -#undef DEF_METHOD_5 -RTLIL::Cell* RTLIL::Module::addPow(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool a_signed, bool b_signed, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($pow)); - cell->parameters[ID::A_SIGNED] = a_signed; - cell->parameters[ID::B_SIGNED] = b_signed; - cell->parameters[ID::A_WIDTH] = sig_a.size(); - cell->parameters[ID::B_WIDTH] = sig_b.size(); - cell->parameters[ID::Y_WIDTH] = sig_y.size(); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::B, sig_b); - cell->setPort(ID::Y, sig_y); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addSr(RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, const RTLIL::SigSpec &sig_q, bool set_polarity, bool clr_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($sr)); + cell->parameters[ID::SET_POLARITY] = set_polarity; + cell->parameters[ID::CLR_POLARITY] = clr_polarity; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::SET, sig_set); + cell->setPort(ID::CLR, sig_clr); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addFa(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_c, const RTLIL::SigSpec &sig_x, const RTLIL::SigSpec &sig_y, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($fa)); - cell->parameters[ID::WIDTH] = sig_a.size(); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::B, sig_b); - cell->setPort(ID::C, sig_c); - cell->setPort(ID::X, sig_x); - cell->setPort(ID::Y, sig_y); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addFf(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($ff)); + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addSlice(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const offset, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($slice)); - cell->parameters[ID::A_WIDTH] = sig_a.size(); - cell->parameters[ID::Y_WIDTH] = sig_y.size(); - cell->parameters[ID::OFFSET] = offset; - cell->setPort(ID::A, sig_a); - cell->setPort(ID::Y, sig_y); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($dff)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addConcat(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($concat)); - cell->parameters[ID::A_WIDTH] = sig_a.size(); - cell->parameters[ID::B_WIDTH] = sig_b.size(); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::B, sig_b); - cell->setPort(ID::Y, sig_y); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($dffe)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::EN_POLARITY] = en_polarity; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::EN, sig_en); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addLut(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const lut, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($lut)); - cell->parameters[ID::LUT] = lut; - cell->parameters[ID::WIDTH] = sig_a.size(); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::Y, sig_y); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDffsr(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, + RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($dffsr)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::SET_POLARITY] = set_polarity; + cell->parameters[ID::CLR_POLARITY] = clr_polarity; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::SET, sig_set); + cell->setPort(ID::CLR, sig_clr); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addTribuf(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_y, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($tribuf)); - cell->parameters[ID::WIDTH] = sig_a.size(); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::Y, sig_y); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDffsre(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, + RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($dffsre)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::EN_POLARITY] = en_polarity; + cell->parameters[ID::SET_POLARITY] = set_polarity; + cell->parameters[ID::CLR_POLARITY] = clr_polarity; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::EN, sig_en); + cell->setPort(ID::SET, sig_set); + cell->setPort(ID::CLR, sig_clr); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addAssert(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($assert)); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addAdff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + RTLIL::Const arst_value, bool clk_polarity, bool arst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($adff)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::ARST_POLARITY] = arst_polarity; + cell->parameters[ID::ARST_VALUE] = arst_value; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::ARST, sig_arst); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addAssume(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($assume)); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addAdffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + RTLIL::Const arst_value, bool clk_polarity, bool en_polarity, bool arst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($adffe)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::EN_POLARITY] = en_polarity; + cell->parameters[ID::ARST_POLARITY] = arst_polarity; + cell->parameters[ID::ARST_VALUE] = arst_value; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::EN, sig_en); + cell->setPort(ID::ARST, sig_arst); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addLive(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($live)); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addAldff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool aload_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($aldff)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::ALOAD_POLARITY] = aload_polarity; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::ALOAD, sig_aload); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::AD, sig_ad); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addFair(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($fair)); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addAldffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool en_polarity, bool aload_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($aldffe)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::EN_POLARITY] = en_polarity; + cell->parameters[ID::ALOAD_POLARITY] = aload_polarity; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::EN, sig_en); + cell->setPort(ID::ALOAD, sig_aload); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::AD, sig_ad); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addCover(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_en, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($cover)); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::EN, sig_en); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addSdff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + RTLIL::Const srst_value, bool clk_polarity, bool srst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($sdff)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::SRST_POLARITY] = srst_polarity; + cell->parameters[ID::SRST_VALUE] = srst_value; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::SRST, sig_srst); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addEquiv(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($equiv)); - cell->setPort(ID::A, sig_a); - cell->setPort(ID::B, sig_b); - cell->setPort(ID::Y, sig_y); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addSdffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + RTLIL::Const srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($sdffe)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::EN_POLARITY] = en_polarity; + cell->parameters[ID::SRST_POLARITY] = srst_polarity; + cell->parameters[ID::SRST_VALUE] = srst_value; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::EN, sig_en); + cell->setPort(ID::SRST, sig_srst); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addSr(RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, const RTLIL::SigSpec &sig_q, bool set_polarity, bool clr_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($sr)); - cell->parameters[ID::SET_POLARITY] = set_polarity; - cell->parameters[ID::CLR_POLARITY] = clr_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::SET, sig_set); - cell->setPort(ID::CLR, sig_clr); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addSdffce(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + RTLIL::Const srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($sdffce)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::EN_POLARITY] = en_polarity; + cell->parameters[ID::SRST_POLARITY] = srst_polarity; + cell->parameters[ID::SRST_VALUE] = srst_value; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::EN, sig_en); + cell->setPort(ID::SRST, sig_srst); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addFf(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($ff)); - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDlatch(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($dlatch)); + cell->parameters[ID::EN_POLARITY] = en_polarity; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::EN, sig_en); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addDff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($dff)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addAdlatch(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + RTLIL::Const arst_value, bool en_polarity, bool arst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($adlatch)); + cell->parameters[ID::EN_POLARITY] = en_polarity; + cell->parameters[ID::ARST_POLARITY] = arst_polarity; + cell->parameters[ID::ARST_VALUE] = arst_value; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::EN, sig_en); + cell->setPort(ID::ARST, sig_arst); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addDffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($dffe)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDlatchsr(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, + RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($dlatchsr)); + cell->parameters[ID::EN_POLARITY] = en_polarity; + cell->parameters[ID::SET_POLARITY] = set_polarity; + cell->parameters[ID::CLR_POLARITY] = clr_polarity; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::EN, sig_en); + cell->setPort(ID::SET, sig_set); + cell->setPort(ID::CLR, sig_clr); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addDffsr(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($dffsr)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::SET_POLARITY] = set_polarity; - cell->parameters[ID::CLR_POLARITY] = clr_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::SET, sig_set); - cell->setPort(ID::CLR, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addSrGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, + const RTLIL::SigSpec &sig_q, bool set_polarity, bool clr_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_SR_%c%c_", set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N')); + cell->setPort(ID::S, sig_set); + cell->setPort(ID::R, sig_clr); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addDffsre(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($dffsre)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::SET_POLARITY] = set_polarity; - cell->parameters[ID::CLR_POLARITY] = clr_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::SET, sig_set); - cell->setPort(ID::CLR, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addFfGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, ID($_FF_)); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addAdff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const arst_value, bool clk_polarity, bool arst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($adff)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::ARST_POLARITY] = arst_polarity; - cell->parameters[ID::ARST_VALUE] = arst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::ARST, sig_arst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_DFF_%c_", clk_polarity ? 'P' : 'N')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addAdffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const arst_value, bool clk_polarity, bool en_polarity, bool arst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($adffe)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::ARST_POLARITY] = arst_polarity; - cell->parameters[ID::ARST_VALUE] = arst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::ARST, sig_arst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::E, sig_en); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addAldff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool aload_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($aldff)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::ALOAD_POLARITY] = aload_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::ALOAD, sig_aload); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::AD, sig_ad); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDffsrGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, + RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_DFFSR_%c%c%c_", clk_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::S, sig_set); + cell->setPort(ID::R, sig_clr); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addAldffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool en_polarity, bool aload_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($aldffe)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::ALOAD_POLARITY] = aload_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::ALOAD, sig_aload); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::AD, sig_ad); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDffsreGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, + RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_DFFSRE_%c%c%c%c_", clk_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::S, sig_set); + cell->setPort(ID::R, sig_clr); + cell->setPort(ID::E, sig_en); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addSdff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const srst_value, bool clk_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($sdff)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::SRST_POLARITY] = srst_polarity; - cell->parameters[ID::SRST_VALUE] = srst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::SRST, sig_srst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addAdffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + bool arst_value, bool clk_polarity, bool arst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_DFF_%c%c%c_", clk_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::R, sig_arst); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addSdffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($sdffe)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::SRST_POLARITY] = srst_polarity; - cell->parameters[ID::SRST_VALUE] = srst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::SRST, sig_srst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addAdffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + bool arst_value, bool clk_polarity, bool en_polarity, bool arst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_DFFE_%c%c%c%c_", clk_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0', en_polarity ? 'P' : 'N')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::R, sig_arst); + cell->setPort(ID::E, sig_en); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addSdffce(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($sdffce)); - cell->parameters[ID::CLK_POLARITY] = clk_polarity; - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::SRST_POLARITY] = srst_polarity; - cell->parameters[ID::SRST_VALUE] = srst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::CLK, sig_clk); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::SRST, sig_srst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addAldffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool aload_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_ALDFF_%c%c_", clk_polarity ? 'P' : 'N', aload_polarity ? 'P' : 'N')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::L, sig_aload); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::AD, sig_ad); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addDlatch(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($dlatch)); - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addAldffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool en_polarity, bool aload_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_ALDFFE_%c%c%c_", clk_polarity ? 'P' : 'N', aload_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::L, sig_aload); + cell->setPort(ID::E, sig_en); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::AD, sig_ad); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addAdlatch(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const arst_value, bool en_polarity, bool arst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($adlatch)); - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::ARST_POLARITY] = arst_polarity; - cell->parameters[ID::ARST_VALUE] = arst_value; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::ARST, sig_arst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addSdffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + bool srst_value, bool clk_polarity, bool srst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_SDFF_%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::R, sig_srst); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addDlatchsr(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($dlatchsr)); - cell->parameters[ID::EN_POLARITY] = en_polarity; - cell->parameters[ID::SET_POLARITY] = set_polarity; - cell->parameters[ID::CLR_POLARITY] = clr_polarity; - cell->parameters[ID::WIDTH] = sig_q.size(); - cell->setPort(ID::EN, sig_en); - cell->setPort(ID::SET, sig_set); - cell->setPort(ID::CLR, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addSdffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + bool srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_SDFFE_%c%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0', en_polarity ? 'P' : 'N')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::R, sig_srst); + cell->setPort(ID::E, sig_en); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addSrGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - const RTLIL::SigSpec &sig_q, bool set_polarity, bool clr_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_SR_%c%c_", set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N')); - cell->setPort(ID::S, sig_set); - cell->setPort(ID::R, sig_clr); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addSdffceGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + bool srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_SDFFCE_%c%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0', en_polarity ? 'P' : 'N')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::R, sig_srst); + cell->setPort(ID::E, sig_en); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addFfGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, ID($_FF_)); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDlatchGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_DLATCH_%c_", en_polarity ? 'P' : 'N')); + cell->setPort(ID::E, sig_en); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addDffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DFF_%c_", clk_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addAdlatchGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + bool arst_value, bool en_polarity, bool arst_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_DLATCH_%c%c%c_", en_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0')); + cell->setPort(ID::E, sig_en); + cell->setPort(ID::R, sig_arst); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } -RTLIL::Cell* RTLIL::Module::addDffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addDffsrGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DFFSR_%c%c%c_", clk_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::S, sig_set); - cell->setPort(ID::R, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addDffsreGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DFFSRE_%c%c%c%c_", clk_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::S, sig_set); - cell->setPort(ID::R, sig_clr); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addAdffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool arst_value, bool clk_polarity, bool arst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DFF_%c%c%c_", clk_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::R, sig_arst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addAdffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool arst_value, bool clk_polarity, bool en_polarity, bool arst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DFFE_%c%c%c%c_", clk_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0', en_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::R, sig_arst); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addAldffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool aload_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_ALDFF_%c%c_", clk_polarity ? 'P' : 'N', aload_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::L, sig_aload); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::AD, sig_ad); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addAldffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool en_polarity, bool aload_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_ALDFFE_%c%c%c_", clk_polarity ? 'P' : 'N', aload_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::L, sig_aload); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::AD, sig_ad); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addSdffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool srst_value, bool clk_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_SDFF_%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::R, sig_srst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addSdffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_SDFFE_%c%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0', en_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::R, sig_srst); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addSdffceGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_SDFFCE_%c%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0', en_polarity ? 'P' : 'N')); - cell->setPort(ID::C, sig_clk); - cell->setPort(ID::R, sig_srst); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addDlatchGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DLATCH_%c_", en_polarity ? 'P' : 'N')); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addAdlatchGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - bool arst_value, bool en_polarity, bool arst_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DLATCH_%c%c%c_", en_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0')); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::R, sig_arst); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} - -RTLIL::Cell* RTLIL::Module::addDlatchsrGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) -{ - RTLIL::Cell *cell = addCell(name, stringf("$_DLATCHSR_%c%c%c_", en_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N')); - cell->setPort(ID::E, sig_en); - cell->setPort(ID::S, sig_set); - cell->setPort(ID::R, sig_clr); - cell->setPort(ID::D, sig_d); - cell->setPort(ID::Q, sig_q); - cell->set_src_attribute(src); - return cell; -} + template RTLIL::Cell* CellAdderMixin::addDlatchsrGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, + RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src) + { + RTLIL::Cell *cell = static_cast(this)->addCell(name, stringf("$_DLATCHSR_%c%c%c_", en_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N')); + cell->setPort(ID::E, sig_en); + cell->setPort(ID::S, sig_set); + cell->setPort(ID::R, sig_clr); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; + } RTLIL::Cell* RTLIL::Module::addAnyinit(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src) { @@ -4166,7 +4166,7 @@ std::string RTLIL::Module::to_rtlil_str() const return f.str(); } -RTLIL::Wire::Wire() +RTLIL::Wire::Wire(ConstructToken) { static unsigned int hashidx_count = 123456789; hashidx_count = mkhash_xorshift(hashidx_count); @@ -4243,7 +4243,7 @@ std::string RTLIL::Process::to_rtlil_str() const return f.str(); } -RTLIL::Cell::Cell(RTLIL::Cell::ConstructToken) : module(nullptr) +RTLIL::Cell::Cell(ConstructToken) : module(nullptr) { static unsigned int hashidx_count = 123456789; hashidx_count = mkhash_xorshift(hashidx_count); @@ -4460,6 +4460,11 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) check(); } +bool RTLIL::Cell::has_keep_attr() const { + return get_bool_attribute(ID::keep) || (module && module->design && module->design->module(type) && + module->design->module(type)->get_bool_attribute(ID::keep)); +} + bool RTLIL::Cell::has_memid() const { return type.in(ID($memwr), ID($memwr_v2), ID($memrd), ID($memrd_v2), ID($meminit), ID($meminit_v2)); @@ -5938,4 +5943,7 @@ std::map *RTLIL::Memory::get_all_memorys(void) return &all_memorys; } #endif + +template class CellAdderMixin; + YOSYS_NAMESPACE_END diff --git a/kernel/rtlil.h b/kernel/rtlil.h index d21e0cd56..413a8477c 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -2063,7 +2063,195 @@ struct RTLIL::Design std::string to_rtlil_str(bool only_selected = true) const; }; -struct RTLIL::Module : public RTLIL::NamedObject +namespace RTLIL_BACKEND { +void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire); +} + +struct RTLIL::Wire : public RTLIL::NamedObject +{ +private: + struct ConstructToken { explicit ConstructToken() = default; }; + friend struct RTLIL::Design; + friend struct RTLIL::Cell; + friend struct RTLIL::Module; + friend struct RTLIL::Patch; +public: + Hasher::hash_t hashidx_; + [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } + // use module->addWire() and module->remove() to create or destroy wires + Wire(ConstructToken); + ~Wire(); + + friend void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire); + RTLIL::Cell *driverCell_ = nullptr; + RTLIL::IdString driverPort_; + + // do not simply copy wires + Wire(ConstructToken, RTLIL::Wire &other); + void operator=(RTLIL::Wire &other) = delete; + + RTLIL::Module *module; + int width, start_offset, port_id; + bool port_input, port_output, upto, is_signed; + + bool known_driver() const { return driverCell_ != nullptr; } + + RTLIL::Cell *driverCell() const { log_assert(driverCell_); return driverCell_; }; + RTLIL::IdString driverPort() const { log_assert(driverCell_); return driverPort_; }; + + int from_hdl_index(int hdl_index) { + int zero_index = hdl_index - start_offset; + int rtlil_index = upto ? width - 1 - zero_index : zero_index; + return rtlil_index >= 0 && rtlil_index < width ? rtlil_index : INT_MIN; + } + + int to_hdl_index(int rtlil_index) { + if (rtlil_index < 0 || rtlil_index >= width) + return INT_MIN; + int zero_index = upto ? width - 1 - rtlil_index : rtlil_index; + return zero_index + start_offset; + } + + std::string to_rtlil_str() const; + +#ifdef YOSYS_ENABLE_PYTHON + static std::map *get_all_wires(void); +#endif +}; + +inline int GetSize(RTLIL::Wire *wire) { + return wire->width; +} + +struct RTLIL::Memory : public RTLIL::NamedObject +{ + Hasher::hash_t hashidx_; + [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } + + Memory(); + + int width, start_offset, size; +#ifdef YOSYS_ENABLE_PYTHON + ~Memory(); + static std::map *get_all_memorys(void); +#endif + + std::string to_rtlil_str() const; +}; + +struct RTLIL::Cell : public RTLIL::NamedObject +{ +private: + struct ConstructToken { explicit ConstructToken() = default; }; + friend struct RTLIL::Module; + friend struct RTLIL::Patch; +public: + Hasher::hash_t hashidx_; + [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } + + // use module->addCell() and module->remove() to create or destroy cells + Cell(ConstructToken); + ~Cell(); + + // do not simply copy cells + Cell(ConstructToken, RTLIL::Cell &other); + void operator=(RTLIL::Cell &other) = delete; + + RTLIL::Module *module; + RTLIL::IdString type; + dict connections_; + dict parameters; + + // access cell ports + bool hasPort(RTLIL::IdString portname) const; + void unsetPort(RTLIL::IdString portname); + void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal); + const RTLIL::SigSpec &getPort(RTLIL::IdString portname) const; + const dict &connections() const; + + // information about cell ports + bool known() const; + bool input(RTLIL::IdString portname) const; + bool output(RTLIL::IdString portname) const; + PortDir port_dir(RTLIL::IdString portname) const; + + // access cell parameters + bool hasParam(RTLIL::IdString paramname) const; + void unsetParam(RTLIL::IdString paramname); + void setParam(RTLIL::IdString paramname, RTLIL::Const value); + const RTLIL::Const &getParam(RTLIL::IdString paramname) const; + + void sort(); + void check(); + void fixup_parameters(bool set_a_signed = false, bool set_b_signed = false); + + bool has_keep_attr() const; + + template void rewrite_sigspecs(T &functor); + template void rewrite_sigspecs2(T &functor); + +#ifdef YOSYS_ENABLE_PYTHON + static std::map *get_all_cells(void); +#endif + + bool has_memid() const; + bool is_mem_cell() const; + bool is_builtin_ff() const; + + std::string to_rtlil_str() const; +}; + +struct RTLIL::CaseRule : public RTLIL::AttrObject +{ + std::vector compare; + std::vector actions; + std::vector switches; + + ~CaseRule(); + + bool empty() const; + + template void rewrite_sigspecs(T &functor); + template void rewrite_sigspecs2(T &functor); + RTLIL::CaseRule *clone() const; +}; + +struct RTLIL::SwitchRule : public RTLIL::AttrObject +{ + RTLIL::SigSpec signal; + std::vector cases; + + ~SwitchRule(); + + bool empty() const; + + template void rewrite_sigspecs(T &functor); + template void rewrite_sigspecs2(T &functor); + RTLIL::SwitchRule *clone() const; +}; + +struct RTLIL::MemWriteAction : RTLIL::AttrObject +{ + RTLIL::IdString memid; + RTLIL::SigSpec address; + RTLIL::SigSpec data; + RTLIL::SigSpec enable; + RTLIL::Const priority_mask; +}; + +struct RTLIL::SyncRule +{ + RTLIL::SyncType type; + RTLIL::SigSpec signal; + std::vector actions; + std::vector mem_write_actions; + + template void rewrite_sigspecs(T &functor); + template void rewrite_sigspecs2(T &functor); + RTLIL::SyncRule *clone() const; +}; + +struct RTLIL::Process : public RTLIL::NamedObject { friend struct RTLIL::SigNormIndex; friend struct RTLIL::Cell; @@ -2073,153 +2261,113 @@ struct RTLIL::Module : public RTLIL::NamedObject [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } protected: - void add(RTLIL::Wire *wire); - void add(RTLIL::Cell *cell); - void add(RTLIL::Process *process); + // use module->addProcess() and module->remove() to create or destroy processes + friend struct RTLIL::Module; + Process(); + ~Process(); public: - RTLIL::Design *design; - pool monitors; - - int refcount_wires_; - int refcount_cells_; - - dict wires_; - dict cells_; - - std::vector connections_; - std::vector bindings_; - - idict avail_parameters; - dict parameter_default_values; - dict memories; - dict processes; - - Module(); - virtual ~Module(); - virtual RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, bool mayfail = false); - virtual RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, const dict &interfaces, const dict &modports, bool mayfail = false); - virtual size_t count_id(RTLIL::IdString id); - virtual void expand_interfaces(RTLIL::Design *design, const dict &local_interfaces); - virtual bool reprocess_if_necessary(RTLIL::Design *design); - - virtual void sort(); - virtual void check(); - virtual void optimize(); - virtual void makeblackbox(); - - bool get_blackbox_attribute(bool ignore_wb=false) const { - return get_bool_attribute(ID::blackbox) || (!ignore_wb && get_bool_attribute(ID::whitebox)); - } - - void connect(const RTLIL::SigSig &conn); - void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs); - void new_connections(const std::vector &new_conn); - const std::vector &connections() const; - - std::vector ports; - void fixup_ports(); - - pool buf_norm_cell_queue; - pool> buf_norm_cell_port_queue; - pool buf_norm_wire_queue; - pool pending_deleted_cells; - dict> buf_norm_connect_index; - void bufNormalize(); - void dump_sigmap(); - -protected: - SigNormIndex *sig_norm_index = nullptr; - void clear_sig_norm_index(); - int timestamp_ = 0; -public: - void sigNormalize(); - - int timestamp() const { return timestamp_; } - int next_timestamp(); - std::vector dirty_cells(int starting_from); - const pool &fanout(SigBit bit); - const dict> &signorm_fanout() const; + RTLIL::Module *module; + RTLIL::CaseRule root_case; + std::vector syncs; template void rewrite_sigspecs(T &functor); template void rewrite_sigspecs2(T &functor); - void cloneInto(RTLIL::Module *new_mod) const; - virtual RTLIL::Module *clone() const; + RTLIL::Process *clone() const; - bool has_memories() const; - bool has_processes() const; + std::string to_rtlil_str() const; +}; - bool has_memories_warn() const; - bool has_processes_warn() const; +struct RTLIL::PortBit +{ + RTLIL::Cell *cell; + RTLIL::IdString port; + int offset; + PortBit(Cell* c, IdString p, int o) : cell(c), port(p), offset(o) {} - bool is_selected() const; - bool is_selected_whole() const; - - std::vector selected_wires() const; - std::vector selected_cells() const; - std::vector selected_memories() const; - std::vector selected_processes() const; - std::vector selected_members() const; - - template bool selected(T *member) const { - return design->selected_member(name, member->name); + bool operator<(const PortBit &other) const { + if (cell != other.cell) + return cell < other.cell; + if (port != other.port) + return port < other.port; + return offset < other.offset; } - RTLIL::Wire* wire(RTLIL::IdString id) { - auto it = wires_.find(id); - return it == wires_.end() ? nullptr : it->second; - } - RTLIL::Cell* cell(RTLIL::IdString id) { - auto it = cells_.find(id); - return it == cells_.end() ? nullptr : it->second; + bool operator==(const PortBit &other) const { + return cell == other.cell && port == other.port && offset == other.offset; } - const RTLIL::Wire* wire(RTLIL::IdString id) const{ - auto it = wires_.find(id); - return it == wires_.end() ? nullptr : it->second; + [[nodiscard]] Hasher hash_into(Hasher h) const { + h.eat(cell->name); + h.eat(port); + h.eat(offset); + return h; } - const RTLIL::Cell* cell(RTLIL::IdString id) const { - auto it = cells_.find(id); - return it == cells_.end() ? nullptr : it->second; +}; + +inline RTLIL::SigBit::SigBit() : wire(NULL), data(RTLIL::State::S0) { } +inline RTLIL::SigBit::SigBit(RTLIL::State bit) : wire(NULL), data(bit) { } +inline RTLIL::SigBit::SigBit(bool bit) : wire(NULL), data(bit ? State::S1 : State::S0) { } +inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire) : wire(wire), offset(0) { log_assert(wire && wire->width == 1); } +inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire, int offset) : wire(wire), offset(offset) { log_assert(wire != nullptr); } +inline RTLIL::SigBit::SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire) { log_assert(chunk.width == 1); if (wire) offset = chunk.offset; else data = chunk.data[0]; } +inline RTLIL::SigBit::SigBit(const RTLIL::SigChunk &chunk, int index) : wire(chunk.wire) { if (wire) offset = chunk.offset + index; else data = chunk.data[index]; } + +inline bool RTLIL::SigBit::operator<(const RTLIL::SigBit &other) const { + if (wire == other.wire) + return wire ? (offset < other.offset) : (data < other.data); + if (wire != nullptr && other.wire != nullptr) + return wire->name < other.wire->name; + return (wire != nullptr) < (other.wire != nullptr); +} + +inline bool RTLIL::SigBit::operator==(const RTLIL::SigBit &other) const { + return (wire == other.wire) && (wire ? (offset == other.offset) : (data == other.data)); +} + +inline bool RTLIL::SigBit::operator!=(const RTLIL::SigBit &other) const { + return (wire != other.wire) || (wire ? (offset != other.offset) : (data != other.data)); +} + +inline Hasher RTLIL::SigBit::hash_into(Hasher h) const { + if (wire) { + h.eat(offset); + h.eat(wire->name); + return h; } + h.eat(data); + return h; +} - RTLIL::ObjRange wires() { return RTLIL::ObjRange(&wires_, &refcount_wires_); } - int wires_size() const { return wires_.size(); } - RTLIL::Wire* wire_at(int index) const { return wires_.element(index)->second; } - RTLIL::ObjRange cells() { return RTLIL::ObjRange(&cells_, &refcount_cells_); } - int cells_size() const { return cells_.size(); } - RTLIL::Cell* cell_at(int index) const { return cells_.element(index)->second; } - void add(RTLIL::Binding *binding); +inline Hasher RTLIL::SigBit::hash_top() const { + Hasher h; + if (wire) { + h.force(hashlib::legacy::djb2_add(wire->name.index_, offset)); + return h; + } + h.force(data); + return h; +} - // Removing wires is expensive. If you have to remove wires, remove them all at once. - void remove(const pool &wires); - void remove(RTLIL::Cell *cell); - void remove(RTLIL::Memory *memory); - void remove(RTLIL::Process *process); +inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const { + return (*sig_p)[index]; +} - void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); - void rename(RTLIL::Cell *cell, RTLIL::IdString new_name); - void rename(RTLIL::IdString old_name, RTLIL::IdString new_name); +inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() { + bit = (*sig_p)[index]; + return bit; +} - void swap_names(RTLIL::Wire *w1, RTLIL::Wire *w2); - void swap_names(RTLIL::Cell *c1, RTLIL::Cell *c2); - - RTLIL::IdString uniquify(RTLIL::IdString name); - RTLIL::IdString uniquify(RTLIL::IdString name, int &index); - - RTLIL::Wire *addWire(RTLIL::IdString name, int width = 1); - RTLIL::Wire *addWire(RTLIL::IdString name, const RTLIL::Wire *other); - - RTLIL::Cell *addCell(RTLIL::IdString name, RTLIL::IdString type); - RTLIL::Cell *addCell(RTLIL::IdString name, const RTLIL::Cell *other); - - RTLIL::Memory *addMemory(RTLIL::IdString name); - RTLIL::Memory *addMemory(RTLIL::IdString name, const RTLIL::Memory *other); - - RTLIL::Process *addProcess(RTLIL::IdString name); - RTLIL::Process *addProcess(RTLIL::IdString name, const RTLIL::Process *other); +inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) { + log_assert(sig.size() == 1); + auto it = sig.chunks().begin(); + *this = SigBit(*it); +} +template +class CellAdderMixin { +public: // The add* methods create a cell and return the created cell. All signals must exist in advance. RTLIL::Cell* addNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); @@ -2428,6 +2576,170 @@ public: RTLIL::SigBit Oai3Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const std::string &src = ""); RTLIL::SigBit Aoi4Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const std::string &src = ""); RTLIL::SigBit Oai4Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const std::string &src = ""); +}; + +struct RTLIL::Module : public RTLIL::NamedObject, public CellAdderMixin +{ + friend struct RTLIL::SigNormIndex; + friend struct RTLIL::Cell; + friend struct RTLIL::Design; + + Hasher::hash_t hashidx_; + [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } + +protected: + void add(RTLIL::Wire *wire); + void add(RTLIL::Cell *cell); + void add(RTLIL::Process *process); + +public: + RTLIL::Design *design; + pool monitors; + + int refcount_wires_; + int refcount_cells_; + + dict wires_; + dict cells_; + + std::vector connections_; + std::vector bindings_; + + idict avail_parameters; + dict parameter_default_values; + dict memories; + dict processes; + + Module(); + virtual ~Module(); + virtual RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, bool mayfail = false); + virtual RTLIL::IdString derive(RTLIL::Design *design, const dict ¶meters, const dict &interfaces, const dict &modports, bool mayfail = false); + virtual size_t count_id(RTLIL::IdString id); + virtual void expand_interfaces(RTLIL::Design *design, const dict &local_interfaces); + virtual bool reprocess_if_necessary(RTLIL::Design *design); + + virtual void sort(); + virtual void check(); + virtual void optimize(); + virtual void makeblackbox(); + + bool get_blackbox_attribute(bool ignore_wb=false) const { + return get_bool_attribute(ID::blackbox) || (!ignore_wb && get_bool_attribute(ID::whitebox)); + } + + void connect(const RTLIL::SigSig &conn); + void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs); + void new_connections(const std::vector &new_conn); + const std::vector &connections() const; + + std::vector ports; + void fixup_ports(); + + pool buf_norm_cell_queue; + pool> buf_norm_cell_port_queue; + pool buf_norm_wire_queue; + pool pending_deleted_cells; + dict> buf_norm_connect_index; + void bufNormalize(); + void dump_sigmap(); + +protected: + SigNormIndex *sig_norm_index = nullptr; + void clear_sig_norm_index(); + int timestamp_ = 0; +public: + void sigNormalize(); + + int timestamp() const { return timestamp_; } + int next_timestamp(); + std::vector dirty_cells(int starting_from); + const pool &fanout(SigBit bit); + const dict> &signorm_fanout() const; + + template void rewrite_sigspecs(T &functor); + template void rewrite_sigspecs2(T &functor); + void cloneInto(RTLIL::Module *new_mod) const; + virtual RTLIL::Module *clone() const; + + bool has_memories() const; + bool has_processes() const; + + bool has_memories_warn() const; + bool has_processes_warn() const; + + bool is_selected() const; + bool is_selected_whole() const; + + std::vector selected_wires() const; + std::vector selected_cells() const; + std::vector selected_memories() const; + std::vector selected_processes() const; + std::vector selected_members() const; + + template bool selected(T *member) const { + return design->selected_member(name, member->name); + } + + RTLIL::Wire* wire(const RTLIL::IdString &id) { + auto it = wires_.find(id); + return it == wires_.end() ? nullptr : it->second; + } + RTLIL::Cell* cell(const RTLIL::IdString &id) { + auto it = cells_.find(id); + return it == cells_.end() ? nullptr : it->second; + } + + const RTLIL::Wire* wire(const RTLIL::IdString &id) const{ + auto it = wires_.find(id); + return it == wires_.end() ? nullptr : it->second; + } + const RTLIL::Cell* cell(const RTLIL::IdString &id) const { + auto it = cells_.find(id); + return it == cells_.end() ? nullptr : it->second; + } + + RTLIL::ObjRange wires() { return RTLIL::ObjRange(&wires_, &refcount_wires_); } + int wires_size() const { return wires_.size(); } + RTLIL::Wire* wire_at(int index) const { return wires_.element(index)->second; } + RTLIL::ObjRange cells() { return RTLIL::ObjRange(&cells_, &refcount_cells_); } + int cells_size() const { return cells_.size(); } + RTLIL::Cell* cell_at(int index) const { return cells_.element(index)->second; } + + void add(RTLIL::Binding *binding); + + // Removing wires is expensive. If you have to remove wires, remove them all at once. + void remove(const pool &wires); + void remove(RTLIL::Cell *cell); + void remove(RTLIL::Memory *memory); + void remove(RTLIL::Process *process); + + void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); + void rename(RTLIL::Cell *cell, RTLIL::IdString new_name); + void rename(RTLIL::IdString old_name, RTLIL::IdString new_name); + + void swap_names(RTLIL::Wire *w1, RTLIL::Wire *w2); + void swap_names(RTLIL::Cell *c1, RTLIL::Cell *c2); + + RTLIL::IdString uniquify(RTLIL::IdString name); + RTLIL::IdString uniquify(RTLIL::IdString name, int &index); + + RTLIL::Wire *addWire(RTLIL::IdString name, int width = 1); + RTLIL::Wire *addWire(RTLIL::IdString name, const RTLIL::Wire *other); + + RTLIL::Cell *addCell(RTLIL::IdString name, RTLIL::IdString type); + RTLIL::Cell *addCell(RTLIL::IdString name, const RTLIL::Cell *other); + + RTLIL::Memory *addMemory(RTLIL::IdString name); + RTLIL::Memory *addMemory(RTLIL::IdString name, const RTLIL::Memory *other); + + RTLIL::Process *addProcess(RTLIL::IdString name); + RTLIL::Process *addProcess(RTLIL::IdString name, const RTLIL::Process *other); + + // The add* methods create a cell and return the created cell. All signals must exist in advance. + + RTLIL::Cell* addAnyinit(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src = ""); + + // The methods without the add* prefix create a cell and an output signal. They return the newly created output signal. RTLIL::SigSpec Anyconst (RTLIL::IdString name, int width = 1, const std::string &src = ""); RTLIL::SigSpec Anyseq (RTLIL::IdString name, int width = 1, const std::string &src = ""); @@ -2448,308 +2760,6 @@ public: #endif }; -namespace RTLIL_BACKEND { -void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire); -} - -struct RTLIL::Wire : public RTLIL::NamedObject -{ -private: - struct ConstructToken { explicit ConstructToken() = default; }; - friend struct RTLIL::Design; - friend struct RTLIL::Cell; - friend struct RTLIL::Module; - friend struct RTLIL::Patch; -public: - Hasher::hash_t hashidx_; - [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } - // use module->addWire() and module->remove() to create or destroy wires - friend struct RTLIL::SigNormIndex; - Wire(); - ~Wire(); - - friend void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire); - RTLIL::Cell *driverCell_ = nullptr; - RTLIL::IdString driverPort_; - -public: - // do not simply copy wires - Wire(RTLIL::Wire &other) = delete; - void operator=(RTLIL::Wire &other) = delete; - - RTLIL::Module *module; - int width, start_offset, port_id; - bool port_input, port_output, upto, is_signed; - - bool known_driver() const { return driverCell_ != nullptr; } - - RTLIL::Cell *driverCell() const { log_assert(driverCell_); return driverCell_; }; - RTLIL::IdString driverPort() const { log_assert(driverCell_); return driverPort_; }; - - int from_hdl_index(int hdl_index) { - int zero_index = hdl_index - start_offset; - int rtlil_index = upto ? width - 1 - zero_index : zero_index; - return rtlil_index >= 0 && rtlil_index < width ? rtlil_index : INT_MIN; - } - - int to_hdl_index(int rtlil_index) { - if (rtlil_index < 0 || rtlil_index >= width) - return INT_MIN; - int zero_index = upto ? width - 1 - rtlil_index : rtlil_index; - return zero_index + start_offset; - } - - std::string to_rtlil_str() const; -#ifdef YOSYS_ENABLE_PYTHON - static std::map *get_all_wires(void); -#endif -}; - -inline int GetSize(RTLIL::Wire *wire) { - return wire->width; -} - -struct RTLIL::Memory : public RTLIL::NamedObject -{ - Hasher::hash_t hashidx_; - [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } - - Memory(); - - int width, start_offset, size; - - std::string to_rtlil_str() const; -#ifdef YOSYS_ENABLE_PYTHON - ~Memory(); - static std::map *get_all_memorys(void); -#endif -}; - -struct RTLIL::Cell : public RTLIL::NamedObject -{ -private: - struct ConstructToken { explicit ConstructToken() = default; }; - friend struct RTLIL::Module; - friend struct RTLIL::Patch; -public: - Hasher::hash_t hashidx_; - [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } - - // use module->addCell() and module->remove() to create or destroy cells - Cell(ConstructToken); - ~Cell(); - - // do not simply copy cells - Cell(ConstructToken, RTLIL::Cell &other); - void operator=(RTLIL::Cell &other) = delete; - - RTLIL::Module *module; - RTLIL::IdString type; - dict connections_; - dict parameters; - - // access cell ports - bool hasPort(RTLIL::IdString portname) const; - void unsetPort(RTLIL::IdString portname); - void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal); - const RTLIL::SigSpec &getPort(RTLIL::IdString portname) const; - const dict &connections() const; - - // information about cell ports - bool known() const; - bool input(RTLIL::IdString portname) const; - bool output(RTLIL::IdString portname) const; - PortDir port_dir(RTLIL::IdString portname) const; - - // access cell parameters - bool hasParam(RTLIL::IdString paramname) const; - void unsetParam(RTLIL::IdString paramname); - void setParam(RTLIL::IdString paramname, RTLIL::Const value); - const RTLIL::Const &getParam(RTLIL::IdString paramname) const; - - void sort(); - void check(); - void fixup_parameters(bool set_a_signed = false, bool set_b_signed = false); - - bool has_keep_attr() const { - return get_bool_attribute(ID::keep) || (module && module->design && module->design->module(type) && - module->design->module(type)->get_bool_attribute(ID::keep)); - } - - template void rewrite_sigspecs(T &functor); - template void rewrite_sigspecs2(T &functor); - - std::string to_rtlil_str() const; - -#ifdef YOSYS_ENABLE_PYTHON - static std::map *get_all_cells(void); -#endif - - bool has_memid() const; - bool is_mem_cell() const; - bool is_builtin_ff() const; -}; - -struct RTLIL::CaseRule : public RTLIL::AttrObject -{ - std::vector compare; - std::vector actions; - std::vector switches; - - ~CaseRule(); - - bool empty() const; - - template void rewrite_sigspecs(T &functor); - template void rewrite_sigspecs2(T &functor); - RTLIL::CaseRule *clone() const; -}; - -struct RTLIL::SwitchRule : public RTLIL::AttrObject -{ - RTLIL::SigSpec signal; - std::vector cases; - - ~SwitchRule(); - - bool empty() const; - - template void rewrite_sigspecs(T &functor); - template void rewrite_sigspecs2(T &functor); - RTLIL::SwitchRule *clone() const; -}; - -struct RTLIL::MemWriteAction : RTLIL::AttrObject -{ - RTLIL::IdString memid; - RTLIL::SigSpec address; - RTLIL::SigSpec data; - RTLIL::SigSpec enable; - RTLIL::Const priority_mask; -}; - -struct RTLIL::SyncRule -{ - RTLIL::SyncType type; - RTLIL::SigSpec signal; - std::vector actions; - std::vector mem_write_actions; - - template void rewrite_sigspecs(T &functor); - template void rewrite_sigspecs2(T &functor); - RTLIL::SyncRule *clone() const; -}; - -struct RTLIL::Process : public RTLIL::NamedObject -{ - Hasher::hash_t hashidx_; - [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } - -protected: - // use module->addProcess() and module->remove() to create or destroy processes - friend struct RTLIL::Module; - Process(); - ~Process(); - -public: - RTLIL::Module *module; - RTLIL::CaseRule root_case; - std::vector syncs; - - template void rewrite_sigspecs(T &functor); - template void rewrite_sigspecs2(T &functor); - RTLIL::Process *clone() const; - std::string to_rtlil_str() const; -}; - -struct RTLIL::PortBit -{ - RTLIL::Cell *cell; - RTLIL::IdString port; - int offset; - PortBit(Cell* c, IdString p, int o) : cell(c), port(p), offset(o) {} - - bool operator<(const PortBit &other) const { - if (cell != other.cell) - return cell < other.cell; - if (port != other.port) - return port < other.port; - return offset < other.offset; - } - - bool operator==(const PortBit &other) const { - return cell == other.cell && port == other.port && offset == other.offset; - } - - [[nodiscard]] Hasher hash_into(Hasher h) const { - h.eat(cell->name); - h.eat(port); - h.eat(offset); - return h; - } -}; - - -inline RTLIL::SigBit::SigBit() : wire(NULL), data(RTLIL::State::S0) { } -inline RTLIL::SigBit::SigBit(RTLIL::State bit) : wire(NULL), data(bit) { } -inline RTLIL::SigBit::SigBit(bool bit) : wire(NULL), data(bit ? State::S1 : State::S0) { } -inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire) : wire(wire), offset(0) { log_assert(wire && wire->width == 1); } -inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire, int offset) : wire(wire), offset(offset) { log_assert(wire != nullptr); } -inline RTLIL::SigBit::SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire) { log_assert(chunk.width == 1); if (wire) offset = chunk.offset; else data = chunk.data[0]; } -inline RTLIL::SigBit::SigBit(const RTLIL::SigChunk &chunk, int index) : wire(chunk.wire) { if (wire) offset = chunk.offset + index; else data = chunk.data[index]; } - -inline bool RTLIL::SigBit::operator<(const RTLIL::SigBit &other) const { - if (wire == other.wire) - return wire ? (offset < other.offset) : (data < other.data); - if (wire != nullptr && other.wire != nullptr) - return wire->name < other.wire->name; - return (wire != nullptr) < (other.wire != nullptr); -} - -inline bool RTLIL::SigBit::operator==(const RTLIL::SigBit &other) const { - return (wire == other.wire) && (wire ? (offset == other.offset) : (data == other.data)); -} - -inline bool RTLIL::SigBit::operator!=(const RTLIL::SigBit &other) const { - return (wire != other.wire) || (wire ? (offset != other.offset) : (data != other.data)); -} - -inline Hasher RTLIL::SigBit::hash_into(Hasher h) const { - if (wire) { - h.eat(offset); - h.eat(wire->name); - return h; - } - h.eat(data); - return h; -} - - -inline Hasher RTLIL::SigBit::hash_top() const { - Hasher h; - if (wire) { - h.force(hashlib::legacy::djb2_add(wire->name.index_, offset)); - return h; - } - h.force(data); - return h; -} - -inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const { - return (*sig_p)[index]; -} - -inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() { - bit = (*sig_p)[index]; - return bit; -} - -inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) { - log_assert(sig.size() == 1); - auto it = sig.chunks().begin(); - *this = SigBit(*it); -} - template void RTLIL::Module::rewrite_sigspecs(T &functor) { diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index 33bbb9777..e1ca2aa96 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -5,40 +5,50 @@ YOSYS_NAMESPACE_BEGIN /** - * Notes - * - * If we want GC, we need more indices - * namely user count (and users?). This should be optional - * - * +* Notes +* +* If we want GC, we need more indices +* namely user count (and users?). This should be optional +* +* */ using namespace RTLIL; + +template class CellAdderMixin; + Cell* Patch::addCell(IdString name, IdString type) { - auto& cell = cells_.emplace_back(Cell::ConstructToken{}); + auto& cell = cells_.emplace_back(Cell::ConstructToken{}); cell.name = std::move(name); cell.type = type; - return &cell; + return &cell; +} + +Wire* Patch::addWire(IdString name, int width) { + (void)name; + (void)width; + log_assert(false); + return nullptr; } void Patch::patch() { - for (auto& cell: cells_) { - Cell* new_cell = mod->addCell(cell.name, &cell); - for (auto [port_name, sig] : new_cell->connections()) { - log_assert(yosys_celltypes.cell_known(cell.type)); - auto dir = cell.port_dir(port_name); - if (dir == PD_OUTPUT || dir == PD_INOUT) { - for (auto chunk : sig.chunks()) { - log_assert(chunk.is_wire()); - auto* wire = chunk.wire; - // Unwire old driver - wire->driverCell_->setPort(wire->driverPort_, SigSpec()); - // Maintain bufnorm - wire->driverCell_ = new_cell; - wire->driverPort_ = port_name; - } - } - } - } + for (auto& cell: cells_) { + Cell* new_cell = mod->addCell(cell.name, &cell); + for (auto [port_name, sig] : new_cell->connections()) { + log_assert(yosys_celltypes.cell_known(cell.type)); + auto dir = cell.port_dir(port_name); + if (dir == PD_OUTPUT || dir == PD_INOUT) { + for (auto chunk : sig.chunks()) { + log_assert(chunk.is_wire()); + auto* wire = chunk.wire; + // Unwire old driver + wire->driverCell_->setPort(wire->driverPort_, SigSpec()); + // Maintain bufnorm + wire->driverCell_ = new_cell; + wire->driverPort_ = port_name; + } + } + } + } } diff --git a/kernel/unstable/patch.h b/kernel/unstable/patch.h index 150ca379a..287a739d6 100644 --- a/kernel/unstable/patch.h +++ b/kernel/unstable/patch.h @@ -6,7 +6,7 @@ YOSYS_NAMESPACE_BEGIN -struct RTLIL::Patch +struct RTLIL::Patch final : public CellAdderMixin { Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } @@ -34,6 +34,9 @@ public: RTLIL::Cell *addCell(RTLIL::IdString name, RTLIL::IdString type); RTLIL::Cell *addCell(RTLIL::IdString name, const RTLIL::Cell *other); + + RTLIL::Cell* addDffsr(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, + RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity, const std::string &src); }; YOSYS_NAMESPACE_END From b7ea32dbee41ae59dcea74dd2a06175450f11e6f Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 14 May 2026 17:43:46 +0200 Subject: [PATCH 09/17] patch: unique heap --- kernel/unstable/patch.cc | 16 +++++++++------- kernel/unstable/patch.h | 5 +++-- passes/cmds/test_patch.cc | 6 +++--- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index e1ca2aa96..8ef567db7 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -17,10 +17,12 @@ using namespace RTLIL; template class CellAdderMixin; Cell* Patch::addCell(IdString name, IdString type) { - auto& cell = cells_.emplace_back(Cell::ConstructToken{}); - cell.name = std::move(name); - cell.type = type; - return &cell; + cells_.emplace(cells_.end(), std::make_unique(Cell::ConstructToken{})); + + Cell* cell = cells_.back().get(); + cell->name = std::move(name); + cell->type = type; + return cell; } Wire* Patch::addWire(IdString name, int width) { @@ -32,10 +34,10 @@ Wire* Patch::addWire(IdString name, int width) { void Patch::patch() { for (auto& cell: cells_) { - Cell* new_cell = mod->addCell(cell.name, &cell); + Cell* new_cell = mod->addCell(cell->name, cell->type); for (auto [port_name, sig] : new_cell->connections()) { - log_assert(yosys_celltypes.cell_known(cell.type)); - auto dir = cell.port_dir(port_name); + log_assert(yosys_celltypes.cell_known(cell->type)); + auto dir = cell->port_dir(port_name); if (dir == PD_OUTPUT || dir == PD_INOUT) { for (auto chunk : sig.chunks()) { log_assert(chunk.is_wire()); diff --git a/kernel/unstable/patch.h b/kernel/unstable/patch.h index 287a739d6..bc902c2ee 100644 --- a/kernel/unstable/patch.h +++ b/kernel/unstable/patch.h @@ -19,8 +19,9 @@ protected: public: Module *mod; SigMap map; - vector wires_; - vector cells_; + vector> wires_; + vector> cells_; + Cell* root; vector connections_; diff --git a/passes/cmds/test_patch.cc b/passes/cmds/test_patch.cc index ba7ad851f..dc5270b3e 100644 --- a/passes/cmds/test_patch.cc +++ b/passes/cmds/test_patch.cc @@ -13,13 +13,13 @@ struct TestPatchPass : public Pass { void execute(std::vector args, RTLIL::Design *design) override { (void) args; - RTLIL::Patch patcher; design->bufNormalize(); for (auto module : design->selected_modules()) { - patcher.mod = module; - patcher.map = SigMap(module); for (auto cell : module->selected_cells()) { if (cell->type == ID($add)) { + RTLIL::Patch patcher; + patcher.mod = module; + patcher.map = SigMap(module); RTLIL::Cell* sub = patcher.addCell(NEW_ID, ID($sub)); sub->connections_ = cell->connections(); sub->parameters = cell->parameters; From d2ae9b48e429a37728c8dca1eac090888e98e41a Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 19 May 2026 12:36:41 +0200 Subject: [PATCH 10/17] patch: signorm, move --- kernel/unstable/patch.cc | 58 +++++++++++++++++++++++++++++---------- kernel/unstable/patch.h | 2 +- passes/cmds/test_patch.cc | 13 +++++---- 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index 8ef567db7..c7a0bdbac 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -1,5 +1,6 @@ #include "kernel/unstable/patch.h" #include "kernel/celltypes.h" +#include "kernel/log.h" #include "kernel/rtlil.h" YOSYS_NAMESPACE_BEGIN @@ -17,10 +18,10 @@ using namespace RTLIL; template class CellAdderMixin; Cell* Patch::addCell(IdString name, IdString type) { - cells_.emplace(cells_.end(), std::make_unique(Cell::ConstructToken{})); + cells_.push_back(std::make_unique(Cell::ConstructToken{})); Cell* cell = cells_.back().get(); - cell->name = std::move(name); + cell->name = name; cell->type = type; return cell; } @@ -32,25 +33,52 @@ Wire* Patch::addWire(IdString name, int width) { return nullptr; } -void Patch::patch() { +void Patch::patch(Cell* old_cell, Cell* new_cell) { + pool patch_cells; for (auto& cell: cells_) { - Cell* new_cell = mod->addCell(cell->name, cell->type); - for (auto [port_name, sig] : new_cell->connections()) { - log_assert(yosys_celltypes.cell_known(cell->type)); - auto dir = cell->port_dir(port_name); - if (dir == PD_OUTPUT || dir == PD_INOUT) { - for (auto chunk : sig.chunks()) { - log_assert(chunk.is_wire()); - auto* wire = chunk.wire; - // Unwire old driver - wire->driverCell_->setPort(wire->driverPort_, SigSpec()); - // Maintain bufnorm + patch_cells.insert(cell.get()); + } + log("patching:\n"); + log_cell(old_cell); + for (auto& cell: cells_) { + log("with:\n"); + log_cell(cell.get()); + log("ptr %p\n", cell.get()); + Cell* raw = cell.release(); + log("ptr2 %p\n", raw); + mod->cells_[raw->name] = raw; + raw->module = mod; + for (auto [port_name, sig] : raw->connections()) { + auto dir = raw->port_dir(port_name); + log_assert(dir != PD_UNKNOWN); + if (raw == new_cell) + if (dir == PD_OUTPUT || dir == PD_INOUT) { + // RAUW + old_cell->setPort(port_name, mod->addWire(NEW_ID, sig.size())); + new_cell->setPort(port_name, sig); + auto* wire = sig.as_wire(); wire->driverCell_ = new_cell; wire->driverPort_ = port_name; } - } + // } else { + // new_cell->setPort(port_name, sig); // map? + // for (auto chunk : map(sig).chunks()) { + // if (chunk.size() == 0) + // continue; + // log_assert(chunk.is_wire()); + // auto* wire = chunk.wire; + // // TODO Use roots instead? + // if (patch_cells.count(wire->driverCell_)) { + // // How do we handle this? + // log_assert(false); + // } else { + // // mod->sig_norm_index + + // } + // } } } + log_module(mod, ""); } diff --git a/kernel/unstable/patch.h b/kernel/unstable/patch.h index bc902c2ee..10f096403 100644 --- a/kernel/unstable/patch.h +++ b/kernel/unstable/patch.h @@ -29,7 +29,7 @@ public: void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs); const std::vector &connections() const; - void patch(); + void patch(Cell* old_cell, Cell* new_cell); RTLIL::Wire *addWire(RTLIL::IdString name, int width = 1); RTLIL::Wire *addWire(RTLIL::IdString name, const RTLIL::Wire *other); diff --git a/passes/cmds/test_patch.cc b/passes/cmds/test_patch.cc index dc5270b3e..3081034fc 100644 --- a/passes/cmds/test_patch.cc +++ b/passes/cmds/test_patch.cc @@ -13,7 +13,7 @@ struct TestPatchPass : public Pass { void execute(std::vector args, RTLIL::Design *design) override { (void) args; - design->bufNormalize(); + design->sigNormalize(); for (auto module : design->selected_modules()) { for (auto cell : module->selected_cells()) { if (cell->type == ID($add)) { @@ -21,12 +21,13 @@ struct TestPatchPass : public Pass { patcher.mod = module; patcher.map = SigMap(module); RTLIL::Cell* sub = patcher.addCell(NEW_ID, ID($sub)); - sub->connections_ = cell->connections(); + // sub->connections_ = cell->connections(); sub->parameters = cell->parameters; - sub->setPort(ID::A, cell->getPort(ID::A)); - sub->setPort(ID::B, cell->getPort(ID::B)); - sub->setPort(ID::Y, cell->getPort(ID::Y)); - patcher.patch(); + sub->connections_[ID::A] = cell->getPort(ID::A); + sub->connections_[ID::B] = cell->getPort(ID::B); + sub->connections_[ID::Y] = cell->getPort(ID::Y); + log_cell(sub); + patcher.patch(cell, sub); } } } From 6b16a0cac800bb4b0bd7a60a95128e40b710a27e Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 19 May 2026 15:33:41 +0200 Subject: [PATCH 11/17] patch: wires --- kernel/unstable/patch.cc | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index c7a0bdbac..2438229f0 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -27,13 +27,35 @@ Cell* Patch::addCell(IdString name, IdString type) { } Wire* Patch::addWire(IdString name, int width) { - (void)name; - (void)width; - log_assert(false); - return nullptr; + wires_.push_back(std::make_unique(Wire::ConstructToken{})); + + Wire* wire = wires_.back().get(); + wire->name = name; + wire->width = width; + return wire; +} + +// TODO code golf + +RTLIL::Wire *RTLIL::Patch::addWire(RTLIL::IdString name, const RTLIL::Wire *other) +{ + RTLIL::Wire *wire = addWire(std::move(name)); + wire->width = other->width; + wire->start_offset = other->start_offset; + wire->port_id = other->port_id; + wire->port_input = other->port_input; + wire->port_output = other->port_output; + wire->upto = other->upto; + wire->is_signed = other->is_signed; + wire->attributes = other->attributes; + return wire; } void Patch::patch(Cell* old_cell, Cell* new_cell) { + for (auto& wire: wires_) { + Wire* raw = wire.release(); + mod->wires_[raw->name] = raw; + } pool patch_cells; for (auto& cell: cells_) { patch_cells.insert(cell.get()); From 8c26ecd2a6c4ecd4989944b3788860afb4067881 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 19 May 2026 15:57:10 +0200 Subject: [PATCH 12/17] patch: WIP multicell patch test --- kernel/rtlil_bufnorm.cc | 5 ++++- kernel/unstable/patch.cc | 2 ++ passes/cmds/test_patch.cc | 23 +++++++++++++++-------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/kernel/rtlil_bufnorm.cc b/kernel/rtlil_bufnorm.cc index 14eec206b..7b5c1df18 100644 --- a/kernel/rtlil_bufnorm.cc +++ b/kernel/rtlil_bufnorm.cc @@ -1090,7 +1090,7 @@ static bool ignored_cell(const RTLIL::IdString& type) void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) { bool is_input_port = false; - if (module->sig_norm_index != nullptr && !ignored_cell(type)) { + if (module && module->sig_norm_index != nullptr && !ignored_cell(type)) { module->sig_norm_index->sigmap.apply(signal); auto dir = port_dir(portname); @@ -1113,6 +1113,9 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) if (!r.second && conn_it->second == signal) return; + if (!module) + return; + for (auto mon : module->monitors) mon->notify_connect(this, conn_it->first, conn_it->second, signal); diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index 2438229f0..01286c1d3 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -37,6 +37,7 @@ Wire* Patch::addWire(IdString name, int width) { // TODO code golf + RTLIL::Wire *RTLIL::Patch::addWire(RTLIL::IdString name, const RTLIL::Wire *other) { RTLIL::Wire *wire = addWire(std::move(name)); @@ -76,6 +77,7 @@ void Patch::patch(Cell* old_cell, Cell* new_cell) { if (raw == new_cell) if (dir == PD_OUTPUT || dir == PD_INOUT) { // RAUW + // TODO optimized implementation for signorm fanout transfer? old_cell->setPort(port_name, mod->addWire(NEW_ID, sig.size())); new_cell->setPort(port_name, sig); auto* wire = sig.as_wire(); diff --git a/passes/cmds/test_patch.cc b/passes/cmds/test_patch.cc index 3081034fc..727099a15 100644 --- a/passes/cmds/test_patch.cc +++ b/passes/cmds/test_patch.cc @@ -17,17 +17,24 @@ struct TestPatchPass : public Pass { for (auto module : design->selected_modules()) { for (auto cell : module->selected_cells()) { if (cell->type == ID($add)) { + Cell* add = cell; + log_assert(add->getPort(ID::B).is_wire()); + log_assert(add->getPort(ID::B).known_driver()); + auto neg = add->getPort(ID::B).as_wire()->driverCell(); + log_assert(neg->type == ID($not)); + + RTLIL::Patch patcher; patcher.mod = module; patcher.map = SigMap(module); - RTLIL::Cell* sub = patcher.addCell(NEW_ID, ID($sub)); - // sub->connections_ = cell->connections(); - sub->parameters = cell->parameters; - sub->connections_[ID::A] = cell->getPort(ID::A); - sub->connections_[ID::B] = cell->getPort(ID::B); - sub->connections_[ID::Y] = cell->getPort(ID::Y); - log_cell(sub); - patcher.patch(cell, sub); + auto new_cell = patcher.addNeg(NEW_ID, patcher.Sub(NEW_ID, neg->getPort(ID::A), cell->getPort(ID::A)), SigSpec()); + // // sub->connections_ = cell->connections(); + // sub->parameters = add->parameters; + // sub->connections_[ID::A] = add->getPort(ID::A); + // sub->connections_[ID::B] = add->getPort(ID::B); + // sub->connections_[ID::Y] = add->getPort(ID::Y); + log_cell(new_cell); + patcher.patch(add, new_cell); } } } From e78e19acfe39c3f7cd188df1d8a9728d1dad21e5 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 19 May 2026 16:21:00 +0200 Subject: [PATCH 13/17] patch: fix patch mixins --- kernel/rtlil.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 134082585..aa8852586 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -22,6 +22,7 @@ #include "kernel/newcelltypes.h" #include "kernel/binding.h" #include "kernel/sigtools.h" +#include "kernel/unstable/patch.h" #include "kernel/threading.h" #include "frontends/verilog/verilog_frontend.h" #include "frontends/verilog/preproc.h" @@ -5945,5 +5946,6 @@ std::map *RTLIL::Memory::get_all_memorys(void) #endif template class CellAdderMixin; +template class CellAdderMixin; YOSYS_NAMESPACE_END From db1c1d4359402adfb24e9bb30c6f458b7278d06d Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 19 May 2026 18:48:43 +0200 Subject: [PATCH 14/17] patch: working multi-cell signorm invariant --- kernel/rtlil_bufnorm.cc | 22 ++++++++--------- kernel/unstable/patch.cc | 50 +++++++++++++++------------------------ passes/cmds/test_patch.cc | 15 +++++------- 3 files changed, 35 insertions(+), 52 deletions(-) diff --git a/kernel/rtlil_bufnorm.cc b/kernel/rtlil_bufnorm.cc index 7b5c1df18..55bf9cccb 100644 --- a/kernel/rtlil_bufnorm.cc +++ b/kernel/rtlil_bufnorm.cc @@ -1113,23 +1113,21 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) if (!r.second && conn_it->second == signal) return; - if (!module) - return; - - for (auto mon : module->monitors) - mon->notify_connect(this, conn_it->first, conn_it->second, signal); - - if (module->design) - for (auto mon : module->design->monitors) + if (module) { + for (auto mon : module->monitors) mon->notify_connect(this, conn_it->first, conn_it->second, signal); + if (module->design) + for (auto mon : module->design->monitors) + mon->notify_connect(this, conn_it->first, conn_it->second, signal); + } + if (yosys_xtrace) { - log("#X# Connect %s.%s.%s = %s (%d)\n", this->module, this, portname.unescape(), log_signal(signal), GetSize(signal)); + log("#X# Connect %s.%s.%s = %s (%d)\n", this->module ? this->module : "PATCH", this, portname.unescape(), log_signal(signal), GetSize(signal)); log_backtrace("-X- ", yosys_xtrace-1); } - - if (module->sig_norm_index != nullptr && !ignored_cell(type)) { + if (module && module->sig_norm_index != nullptr && !ignored_cell(type)) { module->sig_norm_index->dirty.insert(this); if (!r.second) { if (is_input_port) { @@ -1172,7 +1170,7 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) } } - if (module->design && module->design->flagBufferedNormalized) + if (module && module->design && module->design->flagBufferedNormalized) { // We eagerly clear a driver that got disconnected by changing this port connection if (conn_it->second.is_wire()) { diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index 01286c1d3..ab0549e0d 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -23,6 +23,7 @@ Cell* Patch::addCell(IdString name, IdString type) { Cell* cell = cells_.back().get(); cell->name = name; cell->type = type; + cell->module = nullptr; return cell; } @@ -32,6 +33,7 @@ Wire* Patch::addWire(IdString name, int width) { Wire* wire = wires_.back().get(); wire->name = name; wire->width = width; + wire->module = nullptr; return wire; } @@ -54,53 +56,39 @@ RTLIL::Wire *RTLIL::Patch::addWire(RTLIL::IdString name, const RTLIL::Wire *othe void Patch::patch(Cell* old_cell, Cell* new_cell) { for (auto& wire: wires_) { + wire->module = mod; Wire* raw = wire.release(); mod->wires_[raw->name] = raw; } - pool patch_cells; - for (auto& cell: cells_) { - patch_cells.insert(cell.get()); - } log("patching:\n"); log_cell(old_cell); for (auto& cell: cells_) { - log("with:\n"); log_cell(cell.get()); - log("ptr %p\n", cell.get()); Cell* raw = cell.release(); - log("ptr2 %p\n", raw); mod->cells_[raw->name] = raw; - raw->module = mod; for (auto [port_name, sig] : raw->connections()) { auto dir = raw->port_dir(port_name); log_assert(dir != PD_UNKNOWN); - if (raw == new_cell) - if (dir == PD_OUTPUT || dir == PD_INOUT) { + if (dir == PD_OUTPUT || dir == PD_INOUT) { + SigSpec sig_to_fix = sig; + if (raw == new_cell) { // RAUW - // TODO optimized implementation for signorm fanout transfer? - old_cell->setPort(port_name, mod->addWire(NEW_ID, sig.size())); - new_cell->setPort(port_name, sig); - auto* wire = sig.as_wire(); - wire->driverCell_ = new_cell; + // TODO optimized implementation for signorm fanout transfer that avoids expensive(?) setPort? + auto yoink = old_cell->getPort(port_name); + log(">>>> RAUW %s to %s\n", port_name, log_signal(yoink)); + new_cell->setPort(port_name, yoink); + old_cell->setPort(port_name, mod->addWire(NEW_ID, yoink.size())); + sig_to_fix = yoink; + } + if (sig_to_fix.size()) { + auto* wire = sig_to_fix.as_wire(); + wire->driverCell_ = raw; wire->driverPort_ = port_name; } - // } else { - // new_cell->setPort(port_name, sig); // map? - // for (auto chunk : map(sig).chunks()) { - // if (chunk.size() == 0) - // continue; - // log_assert(chunk.is_wire()); - // auto* wire = chunk.wire; - // // TODO Use roots instead? - // if (patch_cells.count(wire->driverCell_)) { - // // How do we handle this? - // log_assert(false); - // } else { - // // mod->sig_norm_index - - // } - // } + } } + raw->module = mod; + raw->fixup_parameters(); } log_module(mod, ""); } diff --git a/passes/cmds/test_patch.cc b/passes/cmds/test_patch.cc index 727099a15..b03dcfe14 100644 --- a/passes/cmds/test_patch.cc +++ b/passes/cmds/test_patch.cc @@ -20,19 +20,16 @@ struct TestPatchPass : public Pass { Cell* add = cell; log_assert(add->getPort(ID::B).is_wire()); log_assert(add->getPort(ID::B).known_driver()); - auto neg = add->getPort(ID::B).as_wire()->driverCell(); + auto neg = add->getPort(ID::B)[0].wire->driverCell(); log_assert(neg->type == ID($not)); - - RTLIL::Patch patcher; patcher.mod = module; patcher.map = SigMap(module); - auto new_cell = patcher.addNeg(NEW_ID, patcher.Sub(NEW_ID, neg->getPort(ID::A), cell->getPort(ID::A)), SigSpec()); - // // sub->connections_ = cell->connections(); - // sub->parameters = add->parameters; - // sub->connections_[ID::A] = add->getPort(ID::A); - // sub->connections_[ID::B] = add->getPort(ID::B); - // sub->connections_[ID::Y] = add->getPort(ID::Y); + auto sub = patcher.addSub(NEW_ID, + neg->getPort(ID::A), + cell->getPort(ID::A), + patcher.addWire(NEW_ID, cell->getPort(ID::A).size())); + auto new_cell = patcher.addNeg(NEW_ID, sub->getPort(ID::Y), SigSpec()); log_cell(new_cell); patcher.patch(add, new_cell); } From 9f22b9d2a02068d5b39764517df68e44d24acb35 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 19 May 2026 19:31:16 +0200 Subject: [PATCH 15/17] patch: source transfer --- kernel/rtlil.cc | 9 +++++-- kernel/rtlil.h | 1 + kernel/unstable/patch.cc | 49 +++++++++++++++++++++++++++++++++++++++ kernel/unstable/patch.h | 10 ++++++-- passes/cmds/test_patch.cc | 5 ++-- 5 files changed, 68 insertions(+), 6 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index aa8852586..e3a1e84b1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -952,7 +952,7 @@ string RTLIL::AttrObject::get_string_attribute(RTLIL::IdString id) const return value; } -void RTLIL::AttrObject::set_strpool_attribute(RTLIL::IdString id, const pool &data) +std::string RTLIL::AttrObject::strpool_attribute_to_str(const pool &data) { string attrval; for (const auto &s : data) { @@ -960,7 +960,12 @@ void RTLIL::AttrObject::set_strpool_attribute(RTLIL::IdString id, const pool &data) +{ + set_string_attribute(id, strpool_attribute_to_str(data)); } void RTLIL::AttrObject::add_strpool_attribute(RTLIL::IdString id, const pool &data) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 413a8477c..2951122d4 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1279,6 +1279,7 @@ struct RTLIL::AttrObject void set_string_attribute(RTLIL::IdString id, string value); string get_string_attribute(RTLIL::IdString id) const; + static std::string strpool_attribute_to_str(const pool &data); void set_strpool_attribute(RTLIL::IdString id, const pool &data); void add_strpool_attribute(RTLIL::IdString id, const pool &data); pool get_strpool_attribute(RTLIL::IdString id) const; diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index ab0549e0d..0ee521fd0 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -54,7 +54,54 @@ RTLIL::Wire *RTLIL::Patch::addWire(RTLIL::IdString name, const RTLIL::Wire *othe return wire; } +void Patch::collect_src(Cell* old_cell) { + src.insert(old_cell->get_src_attribute()); + log("collect %s\n", old_cell->name); + std::vector inputs = {}; + for (auto [port_name, sig] : old_cell->connections()) { + auto dir = old_cell->port_dir(port_name); + log_assert(dir != PD_UNKNOWN); + log_assert(!sig.size() || sig.is_wire()); + if (dir == PD_INPUT || dir == PD_INOUT) { + Wire* in_wire = sig.as_wire(); + if (!leaves.count(in_wire)) + inputs.push_back(in_wire->driverCell()); + } + } + for (auto input : inputs) + collect_src(input); +} + +void Patch::gc(Cell* old_cell) { + log("gc %s\n", old_cell->name); + std::vector inputs = {}; + for (auto [port_name, sig] : old_cell->connections()) { + auto dir = old_cell->port_dir(port_name); + log_assert(dir != PD_UNKNOWN); + log_assert(!sig.size() || sig.is_wire()); + if (dir == PD_OUTPUT || dir == PD_INOUT) { + if (sig.size()) { + for (auto bit : sig) { + // Reject GC if used + if (!mod->fanout(bit).empty()) + return; + } + } + } + if (dir == PD_INPUT || dir == PD_INOUT) { + Wire* in_wire = sig.as_wire(); + if (!leaves.count(in_wire)) + inputs.push_back(in_wire->driverCell()); + } + } + for (auto input : inputs) + gc(input); +} + void Patch::patch(Cell* old_cell, Cell* new_cell) { + log_assert(!leaves.empty()); + collect_src(old_cell); + std::string src_str = AttrObject::strpool_attribute_to_str(src); for (auto& wire: wires_) { wire->module = mod; Wire* raw = wire.release(); @@ -64,6 +111,7 @@ void Patch::patch(Cell* old_cell, Cell* new_cell) { log_cell(old_cell); for (auto& cell: cells_) { log_cell(cell.get()); + cell->set_src_attribute(src_str); Cell* raw = cell.release(); mod->cells_[raw->name] = raw; for (auto [port_name, sig] : raw->connections()) { @@ -91,6 +139,7 @@ void Patch::patch(Cell* old_cell, Cell* new_cell) { raw->fixup_parameters(); } log_module(mod, ""); + gc(old_cell); } diff --git a/kernel/unstable/patch.h b/kernel/unstable/patch.h index 10f096403..badf82cda 100644 --- a/kernel/unstable/patch.h +++ b/kernel/unstable/patch.h @@ -11,6 +11,10 @@ struct RTLIL::Patch final : public CellAdderMixin Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } +private: + void collect_src(Cell* old_cell); + void gc(Cell* old_cell); + protected: void add(RTLIL::Wire *wire); void add(RTLIL::Cell *cell); @@ -18,12 +22,14 @@ protected: public: Module *mod; - SigMap map; + // SigMap map; vector> wires_; vector> cells_; Cell* root; + pool leaves; - vector connections_; + // vector connections_; + pool src; void connect(const RTLIL::SigSig &conn); void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs); diff --git a/passes/cmds/test_patch.cc b/passes/cmds/test_patch.cc index b03dcfe14..5effac2cc 100644 --- a/passes/cmds/test_patch.cc +++ b/passes/cmds/test_patch.cc @@ -24,13 +24,14 @@ struct TestPatchPass : public Pass { log_assert(neg->type == ID($not)); RTLIL::Patch patcher; patcher.mod = module; - patcher.map = SigMap(module); auto sub = patcher.addSub(NEW_ID, neg->getPort(ID::A), - cell->getPort(ID::A), + add->getPort(ID::A), patcher.addWire(NEW_ID, cell->getPort(ID::A).size())); auto new_cell = patcher.addNeg(NEW_ID, sub->getPort(ID::Y), SigSpec()); log_cell(new_cell); + patcher.leaves.insert(neg->getPort(ID::A).as_wire()); + patcher.leaves.insert(add->getPort(ID::A).as_wire()); patcher.patch(add, new_cell); } } From b0eb50be1b9036418bb43f086225f9a72bc2c0f3 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Sat, 23 May 2026 00:11:16 +0200 Subject: [PATCH 16/17] fixup! patch: working multi-cell signorm invariant --- kernel/rtlil_bufnorm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rtlil_bufnorm.cc b/kernel/rtlil_bufnorm.cc index 55bf9cccb..93f800f4f 100644 --- a/kernel/rtlil_bufnorm.cc +++ b/kernel/rtlil_bufnorm.cc @@ -1123,7 +1123,7 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) } if (yosys_xtrace) { - log("#X# Connect %s.%s.%s = %s (%d)\n", this->module ? this->module : "PATCH", this, portname.unescape(), log_signal(signal), GetSize(signal)); + log("#X# Connect %s.%s.%s = %s (%d)\n", this->module ? this->module->name.unescape() : "PATCH", this, portname.unescape(), log_signal(signal), GetSize(signal)); log_backtrace("-X- ", yosys_xtrace-1); } From 5a6568edbeb8bf8bd07a9c5ed1cd8dd0ab977c65 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Sat, 23 May 2026 01:09:26 +0200 Subject: [PATCH 17/17] rtlil, patch: update signorm index and driver fields when committing Cell from Patch to Design --- kernel/rtlil.h | 9 ++ kernel/rtlil_bufnorm.cc | 256 +++++++++++++++++++++++---------------- kernel/unstable/patch.cc | 9 +- 3 files changed, 164 insertions(+), 110 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 2951122d4..5698441df 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -2146,6 +2146,15 @@ private: struct ConstructToken { explicit ConstructToken() = default; }; friend struct RTLIL::Module; friend struct RTLIL::Patch; + + // Push existing port connections into signorm/bufnorm indices after module assignment. + // Assumes signals are already in normalized form. + void initIndex(); + + // Signorm index helpers (used by setPort/unsetPort/initIndex) + void signorm_index_remove(RTLIL::IdString portname, const RTLIL::SigSpec &old_signal, bool is_input); + void signorm_index_add(RTLIL::IdString portname, const RTLIL::SigSpec &new_signal, bool is_input); + bool bufnorm_handle_setPort(RTLIL::IdString portname, RTLIL::SigSpec &signal, dict::iterator conn_it); public: Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } diff --git a/kernel/rtlil_bufnorm.cc b/kernel/rtlil_bufnorm.cc index 93f800f4f..3d5b86064 100644 --- a/kernel/rtlil_bufnorm.cc +++ b/kernel/rtlil_bufnorm.cc @@ -1087,15 +1087,161 @@ static bool ignored_cell(const RTLIL::IdString& type) return type == ID($specify2) || type == ID($specify3) || type == ID($specrule); } +void RTLIL::Cell::signorm_index_remove(IdString portname, const SigSpec &old_signal, bool is_input) +{ + auto &index = *module->sig_norm_index; + index.dirty.insert(this); + if (is_input) { + int i = 0; + for (auto bit : old_signal) { + if (bit.is_wire()) { + auto found = index.fanout.find(bit); + log_assert(found != index.fanout.end()); + int erased = found->second.erase(PortBit(this, portname, i)); + log_assert(erased); + if (found->second.empty()) + index.fanout.erase(found); + } + i++; + } + } else { + Wire *w = old_signal.as_wire(); + log_assert(w->driverCell_ == this); + log_assert(w->driverPort_ == portname); + w->driverCell_ = nullptr; + w->driverPort_ = IdString(); + } +} + +void RTLIL::Cell::signorm_index_add(IdString portname, const SigSpec &new_signal, bool is_input) +{ + auto &index = *module->sig_norm_index; + index.dirty.insert(this); + if (is_input) { + int i = 0; + for (auto bit : new_signal) { + if (bit.is_wire()) + index.fanout[bit].insert(PortBit(this, portname, i)); + i++; + } + } else if (GetSize(new_signal)) { + Wire *w = new_signal.as_wire(); + log_assert(w->driverCell_ == nullptr); + log_assert(w->driverPort_.empty()); + w->driverCell_ = this; + w->driverPort_ = portname; + } +} + +// Handles the bufnorm part of setPort. Updates conn_it->second and returns true if the +// connection was stored (fast path or $connect cell). If false, caller must store signal. +bool RTLIL::Cell::bufnorm_handle_setPort(IdString portname, SigSpec &signal, dict::iterator conn_it) +{ + // Eagerly clear a driver that got disconnected by changing this port connection + if (conn_it->second.is_wire()) { + Wire *w = conn_it->second.as_wire(); + if (w->driverCell_ == this && w->driverPort_ == portname) { + w->driverCell_ = nullptr; + w->driverPort_ = IdString(); + module->buf_norm_wire_queue.insert(w); + } + } + + auto dir = port_dir(portname); + // Fast path: connecting a full driverless wire to an output port — everything else + // goes through the bufnorm queues and is handled during the next bufNormalize call + if ((dir == RTLIL::PD_OUTPUT || dir == RTLIL::PD_INOUT) && signal.is_wire()) { + Wire *w = signal.as_wire(); + if (w->driverCell_ == nullptr && + (w->port_input && !w->port_output) == (type == ID($input_port))) { + w->driverCell_ = this; + w->driverPort_ = portname; + conn_it->second = std::move(signal); + return true; + } + } + + if (dir == RTLIL::PD_OUTPUT || dir == RTLIL::PD_INOUT) { + module->buf_norm_cell_queue.insert(this); + module->buf_norm_cell_port_queue.emplace(this, portname); + } else { + for (auto &chunk : signal.chunks()) + if (chunk.wire != nullptr && chunk.wire->driverCell_ == nullptr) + module->buf_norm_wire_queue.insert(chunk.wire); + } + + if (type == ID($connect)) { + for (auto &[port, sig] : connections_) { + for (auto &chunk : sig.chunks()) { + if (!chunk.wire) continue; + auto it = module->buf_norm_connect_index.find(chunk.wire); + if (it == module->buf_norm_connect_index.end()) continue; + it->second.erase(this); + if (it->second.empty()) + module->buf_norm_connect_index.erase(it); + } + } + conn_it->second = std::move(signal); + for (auto &[port, sig] : connections_) { + for (auto &chunk : sig.chunks()) { + if (!chunk.wire) continue; + module->buf_norm_connect_index[chunk.wire].insert(this); + } + } + return true; + } + + return false; +} + +// Called after the cell's module pointer has been set to push all existing port connections +// into the signorm and bufnorm indices. Assumes signals are already in normalized form. +void RTLIL::Cell::initIndex() +{ + log_assert(module != nullptr); + if (ignored_cell(type)) + return; + + if (module->sig_norm_index != nullptr) { + for (auto &[portname, signal] : connections_) { + bool is_input = port_dir(portname) == RTLIL::PD_INPUT; + signorm_index_add(portname, signal, is_input); + } + } + + if (module->design && module->design->flagBufferedNormalized) { + for (auto &[portname, signal] : connections_) { + auto dir = port_dir(portname); + if ((dir == RTLIL::PD_OUTPUT || dir == RTLIL::PD_INOUT) && signal.is_wire()) { + Wire *w = signal.as_wire(); + if (w->driverCell_ == nullptr && + (w->port_input && !w->port_output) == (type == ID($input_port))) { + w->driverCell_ = this; + w->driverPort_ = portname; + continue; + } + } + if (dir == RTLIL::PD_OUTPUT || dir == RTLIL::PD_INOUT) { + module->buf_norm_cell_queue.insert(this); + module->buf_norm_cell_port_queue.emplace(this, portname); + } else { + for (auto &chunk : signal.chunks()) + if (chunk.wire != nullptr && chunk.wire->driverCell_ == nullptr) + module->buf_norm_wire_queue.insert(chunk.wire); + } + } + } +} + void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) { - bool is_input_port = false; + bool is_input = false; if (module && module->sig_norm_index != nullptr && !ignored_cell(type)) { module->sig_norm_index->sigmap.apply(signal); auto dir = port_dir(portname); if (dir == RTLIL::PD_INPUT) { - is_input_port = true; + is_input = true; } else { Wire *wire = nullptr; if (signal.is_wire() && (wire = signal.as_wire())->driverCell_ != nullptr) @@ -1128,111 +1274,17 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) } if (module && module->sig_norm_index != nullptr && !ignored_cell(type)) { - module->sig_norm_index->dirty.insert(this); - if (!r.second) { - if (is_input_port) { - auto &fanout = module->sig_norm_index->fanout; - int i = 0; - for (auto bit : conn_it->second) { - if (bit.is_wire()) { - auto found = fanout.find(bit); - log_assert(found != fanout.end()); - int erased = found->second.erase(PortBit(this, portname, i)); - log_assert(erased); - if (found->second.empty()) - fanout.erase(found); - } - i++; - } - } else { - Wire *w = conn_it->second.as_wire(); - log_assert(w->driverCell_ == this); - log_assert(w->driverPort_ == portname); - w->driverCell_ = nullptr; - w->driverPort_ = IdString(); - } - } - - if (is_input_port) { - auto &fanout = module->sig_norm_index->fanout; - int i = 0; - for (auto bit : signal) { - if (bit.is_wire()) - fanout[bit].insert(PortBit(this, portname, i)); - i++; - } - } else if (GetSize(signal)) { - Wire *w = signal.as_wire(); - log_assert(w->driverCell_ == nullptr); - log_assert(w->driverPort_.empty()); - w->driverCell_ = this; - w->driverPort_ = portname; - } + if (!r.second) + signorm_index_remove(portname, conn_it->second, is_input); + signorm_index_add(portname, signal, is_input); } - if (module && module->design && module->design->flagBufferedNormalized) - { - // We eagerly clear a driver that got disconnected by changing this port connection - if (conn_it->second.is_wire()) { - Wire *w = conn_it->second.as_wire(); - if (w->driverCell_ == this && w->driverPort_ == portname) { - w->driverCell_ = nullptr; - w->driverPort_ = IdString(); - module->buf_norm_wire_queue.insert(w); - } - } - - auto dir = port_dir(portname); - // This is a fast path that handles connecting a full driverless wire to an output port, - // everything else is goes through the bufnorm queues and is handled during the next - // bufNormalize call - if ((dir == RTLIL::PD_OUTPUT || dir == RTLIL::PD_INOUT) && signal.is_wire()) { - Wire *w = signal.as_wire(); - if (w->driverCell_ == nullptr && ( - (w->port_input && !w->port_output) == (type == ID($input_port)))) { - w->driverCell_ = this; - w->driverPort_ = portname; - - conn_it->second = std::move(signal); - return; - } - } - - if (dir == RTLIL::PD_OUTPUT || dir == RTLIL::PD_INOUT) { - module->buf_norm_cell_queue.insert(this); - module->buf_norm_cell_port_queue.emplace(this, portname); - } else { - for (auto &chunk : signal.chunks()) - if (chunk.wire != nullptr && chunk.wire->driverCell_ == nullptr) - module->buf_norm_wire_queue.insert(chunk.wire); - } - - if (type == ID($connect)) { - for (auto &[port, sig] : connections_) { - for (auto &chunk : sig.chunks()) { - if (!chunk.wire) - continue; - auto it = module->buf_norm_connect_index.find(chunk.wire); - if (it == module->buf_norm_connect_index.end()) - continue; - it->second.erase(this); - if (it->second.empty()) - module->buf_norm_connect_index.erase(it); - } - } - conn_it->second = std::move(signal); - for (auto &[port, sig] : connections_) { - for (auto &chunk : sig.chunks()) { - if (!chunk.wire) - continue; - module->buf_norm_connect_index[chunk.wire].insert(this); - } - } + if (module && module->design && module->design->flagBufferedNormalized) { + if (bufnorm_handle_setPort(portname, signal, conn_it)) return; - } } - conn_it->second = std::move(signal); + conn_it->second = std::move(signal); } void RTLIL::Design::add(RTLIL::Module *module) diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index 0ee521fd0..5c8e066a3 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -118,24 +118,17 @@ void Patch::patch(Cell* old_cell, Cell* new_cell) { auto dir = raw->port_dir(port_name); log_assert(dir != PD_UNKNOWN); if (dir == PD_OUTPUT || dir == PD_INOUT) { - SigSpec sig_to_fix = sig; if (raw == new_cell) { // RAUW - // TODO optimized implementation for signorm fanout transfer that avoids expensive(?) setPort? auto yoink = old_cell->getPort(port_name); log(">>>> RAUW %s to %s\n", port_name, log_signal(yoink)); new_cell->setPort(port_name, yoink); old_cell->setPort(port_name, mod->addWire(NEW_ID, yoink.size())); - sig_to_fix = yoink; - } - if (sig_to_fix.size()) { - auto* wire = sig_to_fix.as_wire(); - wire->driverCell_ = raw; - wire->driverPort_ = port_name; } } } raw->module = mod; + raw->initIndex(); raw->fixup_parameters(); } log_module(mod, "");