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.cc b/kernel/rtlil.cc index 5a3a5fb60..e3a1e84b1 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" @@ -951,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) { @@ -959,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) @@ -3106,7 +3112,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); @@ -3129,7 +3135,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); @@ -3181,850 +3187,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 +4172,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 +4249,7 @@ std::string RTLIL::Process::to_rtlil_str() const return f.str(); } -RTLIL::Cell::Cell() : module(nullptr) +RTLIL::Cell::Cell(ConstructToken) : module(nullptr) { static unsigned int hashidx_count = 123456789; hashidx_count = mkhash_xorshift(hashidx_count); @@ -4460,6 +4466,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 +5949,8 @@ std::map *RTLIL::Memory::get_all_memorys(void) return &all_memorys; } #endif + +template class CellAdderMixin; +template class CellAdderMixin; + YOSYS_NAMESPACE_END diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 146a552e6..5698441df 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; @@ -1278,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; @@ -2062,7 +2064,204 @@ 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; + + // 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; } + + // 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; @@ -2072,153 +2271,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 = ""); @@ -2427,6 +2586,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 = ""); @@ -2447,304 +2770,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 -{ - 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_; - -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 -{ - Hasher::hash_t hashidx_; - [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } - -protected: - // use module->addCell() and module->remove() to create or destroy cells - friend struct RTLIL::Module; - Cell(); - ~Cell(); - -public: - // do not simply copy cells - Cell(RTLIL::Cell &other) = delete; - 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/rtlil_bufnorm.cc b/kernel/rtlil_bufnorm.cc index 14eec206b..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; - if (module->sig_norm_index != nullptr && !ignored_cell(type)) { + 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) @@ -1113,125 +1259,32 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) if (!r.second && conn_it->second == signal) 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->name.unescape() : "PATCH", this, portname.unescape(), log_signal(signal), GetSize(signal)); log_backtrace("-X- ", yosys_xtrace-1); } - - if (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 (module && module->sig_norm_index != nullptr && !ignored_cell(type)) { + if (!r.second) + signorm_index_remove(portname, conn_it->second, is_input); + signorm_index_add(portname, signal, is_input); } - if (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/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..5c8e066a3 --- /dev/null +++ b/kernel/unstable/patch.cc @@ -0,0 +1,139 @@ +#include "kernel/unstable/patch.h" +#include "kernel/celltypes.h" +#include "kernel/log.h" +#include "kernel/rtlil.h" + +YOSYS_NAMESPACE_BEGIN + +/** +* 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) { + cells_.push_back(std::make_unique(Cell::ConstructToken{})); + + Cell* cell = cells_.back().get(); + cell->name = name; + cell->type = type; + cell->module = nullptr; + return cell; +} + +Wire* Patch::addWire(IdString name, int width) { + wires_.push_back(std::make_unique(Wire::ConstructToken{})); + + Wire* wire = wires_.back().get(); + wire->name = name; + wire->width = width; + wire->module = nullptr; + 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::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(); + mod->wires_[raw->name] = raw; + } + log("patching:\n"); + 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()) { + auto dir = raw->port_dir(port_name); + log_assert(dir != PD_UNKNOWN); + if (dir == PD_OUTPUT || dir == PD_INOUT) { + if (raw == new_cell) { + // RAUW + 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())); + } + } + } + raw->module = mod; + raw->initIndex(); + raw->fixup_parameters(); + } + log_module(mod, ""); + gc(old_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..badf82cda --- /dev/null +++ b/kernel/unstable/patch.h @@ -0,0 +1,51 @@ +#ifndef PATCH_H +#define PATCH_H + +#include "kernel/rtlil.h" +#include "kernel/sigtools.h" + +YOSYS_NAMESPACE_BEGIN + +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); + void add(RTLIL::Process *process); + +public: + Module *mod; + // SigMap map; + vector> wires_; + vector> cells_; + Cell* root; + pool leaves; + + // vector connections_; + pool src; + + void connect(const RTLIL::SigSig &conn); + void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs); + const std::vector &connections() const; + + 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); + + 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 + +#endif 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..5effac2cc --- /dev/null +++ b/passes/cmds/test_patch.cc @@ -0,0 +1,42 @@ +#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; + design->sigNormalize(); + 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)[0].wire->driverCell(); + log_assert(neg->type == ID($not)); + RTLIL::Patch patcher; + patcher.mod = module; + auto sub = patcher.addSub(NEW_ID, + neg->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); + } + } + } + } +} TestPatchPass; + +PRIVATE_NAMESPACE_END