diff --git a/Makefile b/Makefile index 0c673cdf8f4..f34b435636f 100644 --- a/Makefile +++ b/Makefile @@ -603,6 +603,7 @@ $(eval $(call add_include_file,kernel/bitpattern.h)) $(eval $(call add_include_file,kernel/cellaigs.h)) $(eval $(call add_include_file,kernel/celledges.h)) $(eval $(call add_include_file,kernel/celltypes.h)) +$(eval $(call add_include_file,kernel/newcelltypes.h)) $(eval $(call add_include_file,kernel/consteval.h)) $(eval $(call add_include_file,kernel/constids.inc)) $(eval $(call add_include_file,kernel/cost.h)) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index 41e1b91c1c6..0b2f069595a 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -44,6 +44,8 @@ PRIVATE_NAMESPACE_BEGIN // TODO //#define ARITH_OPS ID($add), ID($sub), ID($neg) +// TODO convert to newcelltypes + #define KNOWN_OPS BITWISE_OPS, REDUCE_OPS, LOGIC_OPS, GATE_OPS, ID($pos), CMP_OPS, \ ID($pmux), ID($bmux) /*, ARITH_OPS*/ diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index ab7861802c6..be7287917a1 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -24,7 +24,7 @@ #include "kernel/rtlil.h" #include "kernel/register.h" #include "kernel/sigtools.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/log.h" #include @@ -60,7 +60,7 @@ struct BlifDumper RTLIL::Module *module; RTLIL::Design *design; BlifDumperConfig *config; - CellTypes ct; + NewCellTypes ct; SigMap sigmap; dict init_bits; diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 61d6ee254b8..145477b6bf1 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -23,7 +23,7 @@ #include "kernel/rtlil.h" #include "kernel/register.h" #include "kernel/sigtools.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/log.h" #include @@ -138,7 +138,7 @@ struct EdifBackend : public Backend { bool lsbidx = false; std::map> lib_cell_ports; bool nogndvcc = false, gndvccy = false, keepmode = false; - CellTypes ct(design); + NewCellTypes ct(design); EdifNames edif_names; size_t argidx; diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index 78eab17da83..ad16d50abc1 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -20,7 +20,7 @@ #include "kernel/rtlil.h" #include "kernel/register.h" #include "kernel/sigtools.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/log.h" #include @@ -117,7 +117,7 @@ struct IntersynthBackend : public Backend { std::set conntypes_code, celltypes_code; std::string netlists_code; - CellTypes ct(design); + NewCellTypes ct(design); for (auto lib : libs) ct.setup_design(lib); diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index d80622029a6..9d0ebc2aa65 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -20,7 +20,7 @@ #include "kernel/rtlil.h" #include "kernel/register.h" #include "kernel/sigtools.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/log.h" #include "kernel/mem.h" #include "libs/json11/json11.hpp" @@ -32,7 +32,7 @@ PRIVATE_NAMESPACE_BEGIN struct Smt2Worker { - CellTypes ct; + NewCellTypes ct; SigMap sigmap; RTLIL::Module *module; bool bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode; diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index a6ccbf27f0a..acefad0605b 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -20,7 +20,7 @@ #include "kernel/rtlil.h" #include "kernel/register.h" #include "kernel/sigtools.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/log.h" #include @@ -29,7 +29,7 @@ PRIVATE_NAMESPACE_BEGIN struct SmvWorker { - CellTypes ct; + NewCellTypes ct; SigMap sigmap; RTLIL::Module *module; std::ostream &f; diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4df37c0cda9..2c7780420b8 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -37,7 +37,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "aigerparse.h" YOSYS_NAMESPACE_BEGIN diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 2c3535eac61..2d53f5a8742 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -87,22 +87,22 @@ struct CellTypes { setup_internals_eval(); - setup_type(ID($tribuf), {ID::A, ID::EN}, {ID::Y}, true); - - setup_type(ID($assert), {ID::A, ID::EN}, pool(), true); - setup_type(ID($assume), {ID::A, ID::EN}, pool(), true); - setup_type(ID($live), {ID::A, ID::EN}, pool(), true); - setup_type(ID($fair), {ID::A, ID::EN}, pool(), true); - setup_type(ID($cover), {ID::A, ID::EN}, pool(), true); - setup_type(ID($initstate), pool(), {ID::Y}, true); - setup_type(ID($anyconst), pool(), {ID::Y}, true); - setup_type(ID($anyseq), pool(), {ID::Y}, true); - setup_type(ID($allconst), pool(), {ID::Y}, true); - setup_type(ID($allseq), pool(), {ID::Y}, true); - setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y}, true); - setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, pool(), true); - setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, pool(), true); - setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, pool(), true); + setup_type(ID($tribuf), {ID::A, ID::EN}, {ID::Y}); + + setup_type(ID($assert), {ID::A, ID::EN}, pool()); + setup_type(ID($assume), {ID::A, ID::EN}, pool()); + setup_type(ID($live), {ID::A, ID::EN}, pool()); + setup_type(ID($fair), {ID::A, ID::EN}, pool()); + setup_type(ID($cover), {ID::A, ID::EN}, pool()); + setup_type(ID($initstate), pool(), {ID::Y}); + setup_type(ID($anyconst), pool(), {ID::Y}); + setup_type(ID($anyseq), pool(), {ID::Y}); + setup_type(ID($allconst), pool(), {ID::Y}); + setup_type(ID($allseq), pool(), {ID::Y}); + setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y}); + setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, pool()); + setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, pool()); + setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, pool()); setup_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, pool()); setup_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, pool()); setup_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y}); @@ -195,7 +195,7 @@ struct CellTypes { setup_stdcells_eval(); - setup_type(ID($_TBUF_), {ID::A, ID::E}, {ID::Y}, true); + setup_type(ID($_TBUF_), {ID::A, ID::E}, {ID::Y}); } void setup_stdcells_eval() @@ -548,9 +548,6 @@ struct CellTypes } }; -// initialized by yosys_setup() -extern CellTypes yosys_celltypes; - YOSYS_NAMESPACE_END #endif diff --git a/kernel/consteval.h b/kernel/consteval.h index b13c7ea5c5b..82169f31efd 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -24,6 +24,7 @@ #include "kernel/sigtools.h" #include "kernel/celltypes.h" #include "kernel/macc.h" +#include "kernel/newcelltypes.h" YOSYS_NAMESPACE_BEGIN @@ -40,9 +41,8 @@ struct ConstEval ConstEval(RTLIL::Module *module, RTLIL::State defaultval = RTLIL::State::Sm) : module(module), assign_map(module), defaultval(defaultval) { - CellTypes ct; - ct.setup_internals(); - ct.setup_stdcells(); + auto ct = NewCellTypes(); + ct.static_cell_types = StaticCellTypes::Compat::nomem_noff; for (auto &it : module->cells_) { if (!ct.cell_known(it.second->type)) diff --git a/kernel/drivertools.h b/kernel/drivertools.h index ba7b2aa8485..28d3be91eb0 100644 --- a/kernel/drivertools.h +++ b/kernel/drivertools.h @@ -25,7 +25,7 @@ #include "kernel/rtlil.h" #include "kernel/sigtools.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" YOSYS_NAMESPACE_BEGIN @@ -1093,10 +1093,10 @@ struct DriveSpec struct DriverMap { - CellTypes celltypes; + NewCellTypes celltypes; DriverMap() { celltypes.setup(); } - DriverMap(Design *design) { celltypes.setup(); celltypes.setup_design(design); } + DriverMap(Design *design) { celltypes.setup(design); } private: diff --git a/kernel/modtools.h b/kernel/modtools.h index 27ba98d7d7a..4be32a80672 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -23,6 +23,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" YOSYS_NAMESPACE_BEGIN @@ -332,7 +333,7 @@ struct ModWalker RTLIL::Design *design; RTLIL::Module *module; - CellTypes ct; + NewCellTypes ct; SigMap sigmap; dict> signal_drivers; diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h new file mode 100644 index 00000000000..c4a4ea3292c --- /dev/null +++ b/kernel/newcelltypes.h @@ -0,0 +1,646 @@ +#ifndef NEWCELLTYPES_H +#define NEWCELLTYPES_H + +#include "kernel/rtlil.h" +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN + +namespace StaticCellTypes { + +// Given by last internal cell type IdString constids.inc, compilation error if too low +constexpr int MAX_CELLS = 300; +// Currently given by _MUX16_, compilation error if too low +constexpr int MAX_PORTS = 20; +struct CellTableBuilder { + struct PortList { + std::array ports{}; + size_t count = 0; + constexpr PortList() = default; + constexpr PortList(std::initializer_list init) { + for (auto p : init) { + ports[count++] = p; + } + } + constexpr auto begin() const { return ports.begin(); } + constexpr auto end() const { return ports.begin() + count; } + constexpr bool contains(RTLIL::IdString port) const { + for (size_t i = 0; i < count; i++) { + if (port == ports[i]) + return true; + } + + return false; + } + constexpr size_t size() const { return count; } + }; + struct Features { + bool is_evaluable = false; + bool is_combinatorial = false; + bool is_synthesizable = false; + bool is_stdcell = false; + bool is_ff = false; + bool is_mem_noff = false; + bool is_anyinit = false; + bool is_tristate = false; + }; + struct CellInfo { + RTLIL::IdString type; + PortList inputs, outputs; + Features features; + }; + std::array cells{}; + size_t count = 0; + + constexpr void setup_type(RTLIL::IdString type, std::initializer_list inputs, std::initializer_list outputs, const Features& features) { + cells[count++] = {type, PortList(inputs), PortList(outputs), features}; + } + constexpr void setup_internals_other() + { + Features features {}; + features.is_tristate = true; + setup_type(ID($tribuf), {ID::A, ID::EN}, {ID::Y}, features); + + features = {}; + setup_type(ID($assert), {ID::A, ID::EN}, {}, features); + setup_type(ID($assume), {ID::A, ID::EN}, {}, features); + setup_type(ID($live), {ID::A, ID::EN}, {}, features); + setup_type(ID($fair), {ID::A, ID::EN}, {}, features); + setup_type(ID($cover), {ID::A, ID::EN}, {}, features); + setup_type(ID($initstate), {}, {ID::Y}, features); + setup_type(ID($anyconst), {}, {ID::Y}, features); + setup_type(ID($anyseq), {}, {ID::Y}, features); + setup_type(ID($allconst), {}, {ID::Y}, features); + setup_type(ID($allseq), {}, {ID::Y}, features); + setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y}, features); + setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, {}, features); + setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, {}, features); + setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, {}, features); + setup_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, {}, features); + setup_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, {}, features); + setup_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y}, features); + setup_type(ID($get_tag), {ID::A}, {ID::Y}, features); + setup_type(ID($overwrite_tag), {ID::A, ID::SET, ID::CLR}, {}, features); + setup_type(ID($original_tag), {ID::A}, {ID::Y}, features); + setup_type(ID($future_ff), {ID::A}, {ID::Y}, features); + setup_type(ID($scopeinfo), {}, {}, features); + setup_type(ID($input_port), {}, {ID::Y}, features); + setup_type(ID($connect), {ID::A, ID::B}, {}, features); + } + constexpr void setup_internals_eval() + { + Features features {}; + features.is_evaluable = true; + std::initializer_list unary_ops = { + ID($not), ID($pos), ID($buf), ID($neg), + ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), + ID($logic_not), ID($slice), ID($lut), ID($sop) + }; + + std::initializer_list binary_ops = { + ID($and), ID($or), ID($xor), ID($xnor), + ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx), + ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), + ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow), + ID($logic_and), ID($logic_or), ID($concat), ID($macc), + ID($bweqx) + }; + + for (auto type : unary_ops) + setup_type(type, {ID::A}, {ID::Y}, features); + + for (auto type : binary_ops) + setup_type(type, {ID::A, ID::B}, {ID::Y}, features); + + for (auto type : {ID($mux), ID($pmux), ID($bwmux)}) + setup_type(type, {ID::A, ID::B, ID::S}, {ID::Y}, features); + + for (auto type : {ID($bmux), ID($demux)}) + setup_type(type, {ID::A, ID::S}, {ID::Y}, features); + + setup_type(ID($lcu), {ID::P, ID::G, ID::CI}, {ID::CO}, features); + setup_type(ID($alu), {ID::A, ID::B, ID::CI, ID::BI}, {ID::X, ID::Y, ID::CO}, features); + setup_type(ID($macc_v2), {ID::A, ID::B, ID::C}, {ID::Y}, features); + setup_type(ID($fa), {ID::A, ID::B, ID::C}, {ID::X, ID::Y}, features); + } + constexpr void setup_internals_ff() + { + Features features {}; + features.is_ff = true; + setup_type(ID($sr), {ID::SET, ID::CLR}, {ID::Q}, features); + setup_type(ID($ff), {ID::D}, {ID::Q}, features); + setup_type(ID($dff), {ID::CLK, ID::D}, {ID::Q}, features); + setup_type(ID($dffe), {ID::CLK, ID::EN, ID::D}, {ID::Q}, features); + setup_type(ID($dffsr), {ID::CLK, ID::SET, ID::CLR, ID::D}, {ID::Q}, features); + setup_type(ID($dffsre), {ID::CLK, ID::SET, ID::CLR, ID::D, ID::EN}, {ID::Q}, features); + setup_type(ID($adff), {ID::CLK, ID::ARST, ID::D}, {ID::Q}, features); + setup_type(ID($adffe), {ID::CLK, ID::ARST, ID::D, ID::EN}, {ID::Q}, features); + setup_type(ID($aldff), {ID::CLK, ID::ALOAD, ID::AD, ID::D}, {ID::Q}, features); + setup_type(ID($aldffe), {ID::CLK, ID::ALOAD, ID::AD, ID::D, ID::EN}, {ID::Q}, features); + setup_type(ID($sdff), {ID::CLK, ID::SRST, ID::D}, {ID::Q}, features); + setup_type(ID($sdffe), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q}, features); + setup_type(ID($sdffce), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q}, features); + setup_type(ID($dlatch), {ID::EN, ID::D}, {ID::Q}, features); + setup_type(ID($adlatch), {ID::EN, ID::D, ID::ARST}, {ID::Q}, features); + setup_type(ID($dlatchsr), {ID::EN, ID::SET, ID::CLR, ID::D}, {ID::Q}, features); + } + constexpr void setup_internals_anyinit() + { + Features features {}; + features.is_anyinit = true; + setup_type(ID($anyinit), {ID::D}, {ID::Q}, features); + } + constexpr void setup_internals_mem_noff() + { + Features features {}; + features.is_mem_noff = true; + // NOT setup_internals_ff() + + setup_type(ID($memrd), {ID::CLK, ID::EN, ID::ADDR}, {ID::DATA}, features); + setup_type(ID($memrd_v2), {ID::CLK, ID::EN, ID::ARST, ID::SRST, ID::ADDR}, {ID::DATA}, features); + setup_type(ID($memwr), {ID::CLK, ID::EN, ID::ADDR, ID::DATA}, {}, features); + setup_type(ID($memwr_v2), {ID::CLK, ID::EN, ID::ADDR, ID::DATA}, {}, features); + setup_type(ID($meminit), {ID::ADDR, ID::DATA}, {}, features); + setup_type(ID($meminit_v2), {ID::ADDR, ID::DATA, ID::EN}, {}, features); + setup_type(ID($mem), {ID::RD_CLK, ID::RD_EN, ID::RD_ADDR, ID::WR_CLK, ID::WR_EN, ID::WR_ADDR, ID::WR_DATA}, {ID::RD_DATA}, features); + setup_type(ID($mem_v2), {ID::RD_CLK, ID::RD_EN, ID::RD_ARST, ID::RD_SRST, ID::RD_ADDR, ID::WR_CLK, ID::WR_EN, ID::WR_ADDR, ID::WR_DATA}, {ID::RD_DATA}, features); + + // What? + setup_type(ID($fsm), {ID::CLK, ID::ARST, ID::CTRL_IN}, {ID::CTRL_OUT}, features); + } + constexpr void setup_stdcells_tristate() + { + Features features {}; + features.is_stdcell = true; + features.is_tristate = true; + setup_type(ID($_TBUF_), {ID::A, ID::E}, {ID::Y}, features); + } + + constexpr void setup_stdcells_eval() + { + Features features {}; + features.is_stdcell = true; + features.is_evaluable = true; + setup_type(ID($_BUF_), {ID::A}, {ID::Y}, features); + setup_type(ID($_NOT_), {ID::A}, {ID::Y}, features); + setup_type(ID($_AND_), {ID::A, ID::B}, {ID::Y}, features); + setup_type(ID($_NAND_), {ID::A, ID::B}, {ID::Y}, features); + setup_type(ID($_OR_), {ID::A, ID::B}, {ID::Y}, features); + setup_type(ID($_NOR_), {ID::A, ID::B}, {ID::Y}, features); + setup_type(ID($_XOR_), {ID::A, ID::B}, {ID::Y}, features); + setup_type(ID($_XNOR_), {ID::A, ID::B}, {ID::Y}, features); + setup_type(ID($_ANDNOT_), {ID::A, ID::B}, {ID::Y}, features); + setup_type(ID($_ORNOT_), {ID::A, ID::B}, {ID::Y}, features); + setup_type(ID($_MUX_), {ID::A, ID::B, ID::S}, {ID::Y}, features); + setup_type(ID($_NMUX_), {ID::A, ID::B, ID::S}, {ID::Y}, features); + setup_type(ID($_MUX4_), {ID::A, ID::B, ID::C, ID::D, ID::S, ID::T}, {ID::Y}, features); + setup_type(ID($_MUX8_), {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::S, ID::T, ID::U}, {ID::Y}, features); + setup_type(ID($_MUX16_), {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::I, ID::J, ID::K, ID::L, ID::M, ID::N, ID::O, ID::P, ID::S, ID::T, ID::U, ID::V}, {ID::Y}, features); + setup_type(ID($_AOI3_), {ID::A, ID::B, ID::C}, {ID::Y}, features); + setup_type(ID($_OAI3_), {ID::A, ID::B, ID::C}, {ID::Y}, features); + setup_type(ID($_AOI4_), {ID::A, ID::B, ID::C, ID::D}, {ID::Y}, features); + setup_type(ID($_OAI4_), {ID::A, ID::B, ID::C, ID::D}, {ID::Y}, features); + } + + constexpr void setup_stdcells_ff() { + Features features {}; + features.is_stdcell = true; + features.is_ff = true; + + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // setup_type(std::string("$_SR_") + c1 + c2 + "_", {ID::S, ID::R}, {ID::Q}, features); + setup_type(ID($_SR_NN_), {ID::S, ID::R}, {ID::Q}, features); + setup_type(ID($_SR_NP_), {ID::S, ID::R}, {ID::Q}, features); + setup_type(ID($_SR_PN_), {ID::S, ID::R}, {ID::Q}, features); + setup_type(ID($_SR_PP_), {ID::S, ID::R}, {ID::Q}, features); + + setup_type(ID($_FF_), {ID::D}, {ID::Q}, features); + + // for (auto c1 : list_np) + // setup_type(std::string("$_DFF_") + c1 + "_", {ID::C, ID::D}, {ID::Q}, features); + setup_type(ID::$_DFF_N_, {ID::C, ID::D}, {ID::Q}, features); + setup_type(ID::$_DFF_P_, {ID::C, ID::D}, {ID::Q}, features); + + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // setup_type(std::string("$_DFFE_") + c1 + c2 + "_", {ID::C, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID::$_DFFE_NN_, {ID::C, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID::$_DFFE_NP_, {ID::C, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID::$_DFFE_PN_, {ID::C, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID::$_DFFE_PP_, {ID::C, ID::D, ID::E}, {ID::Q}, features); + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // for (auto c3 : list_01) + // setup_type(std::string("$_DFF_") + c1 + c2 + c3 + "_", {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFF_NN0_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFF_NN1_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFF_NP0_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFF_NP1_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFF_PN0_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFF_PN1_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFF_PP0_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFF_PP1_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // for (auto c3 : list_01) + // for (auto c4 : list_np) + // setup_type(std::string("$_DFFE_") + c1 + c2 + c3 + c4 + "_", {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_NN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_NN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_NN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_NN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_NP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_NP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_NP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_NP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_PN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_PN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_PN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_PN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_PP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_PP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_PP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFE_PP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // setup_type(std::string("$_ALDFF_") + c1 + c2 + "_", {ID::C, ID::L, ID::AD, ID::D}, {ID::Q}, features); + setup_type(ID($_ALDFF_NN_), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q}, features); + setup_type(ID($_ALDFF_NP_), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q}, features); + setup_type(ID($_ALDFF_PN_), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q}, features); + setup_type(ID($_ALDFF_PP_), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q}, features); + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // for (auto c3 : list_np) + // setup_type(std::string("$_ALDFFE_") + c1 + c2 + c3 + "_", {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_ALDFFE_NNN_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_ALDFFE_NNP_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_ALDFFE_NPN_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_ALDFFE_NPP_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_ALDFFE_PNN_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_ALDFFE_PNP_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_ALDFFE_PPN_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_ALDFFE_PPP_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features); + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // for (auto c3 : list_np) + // setup_type(std::string("$_DFFSR_") + c1 + c2 + c3 + "_", {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFFSR_NNN_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFFSR_NNP_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFFSR_NPN_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFFSR_NPP_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFFSR_PNN_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFFSR_PNP_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFFSR_PPN_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DFFSR_PPP_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features); + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // for (auto c3 : list_np) + // for (auto c4 : list_np) + // setup_type(std::string("$_DFFSRE_") + c1 + c2 + c3 + c4 + "_", {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_NNNN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_NNNP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_NNPN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_NNPP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_NPNN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_NPNP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_NPPN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_NPPP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_PNNN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_PNNP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_PNPN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_PNPP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_PPNN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_PPNP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_PPPN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_DFFSRE_PPPP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features); + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // for (auto c3 : list_01) + // setup_type(std::string("$_SDFF_") + c1 + c2 + c3 + "_", {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_SDFF_NN0_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_SDFF_NN1_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_SDFF_NP0_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_SDFF_NP1_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_SDFF_PN0_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_SDFF_PN1_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_SDFF_PP0_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_SDFF_PP1_), {ID::C, ID::R, ID::D}, {ID::Q}, features); + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // for (auto c3 : list_01) + // for (auto c4 : list_np) + // setup_type(std::string("$_SDFFE_") + c1 + c2 + c3 + c4 + "_", {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_NN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_NN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_NN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_NN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_NP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_NP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_NP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_NP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_PN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_PN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_PN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_PN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_PP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_PP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_PP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFE_PP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // for (auto c3 : list_01) + // for (auto c4 : list_np) + // setup_type(std::string("$_SDFFCE_") + c1 + c2 + c3 + c4 + "_", {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_NN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_NN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_NN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_NN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_NP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_NP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_NP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_NP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_PN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_PN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_PN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_PN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_PP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_PP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_PP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + setup_type(ID($_SDFFCE_PP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features); + // for (auto c1 : list_np) + // setup_type(std::string("$_DLATCH_") + c1 + "_", {ID::E, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCH_N_), {ID::E, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCH_P_), {ID::E, ID::D}, {ID::Q}, features); + + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // for (auto c3 : list_01) + // setup_type(std::string("$_DLATCH_") + c1 + c2 + c3 + "_", {ID::E, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCH_NN0_), {ID::E, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCH_NN1_), {ID::E, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCH_NP0_), {ID::E, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCH_NP1_), {ID::E, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCH_PN0_), {ID::E, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCH_PN1_), {ID::E, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCH_PP0_), {ID::E, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCH_PP1_), {ID::E, ID::R, ID::D}, {ID::Q}, features); + // for (auto c1 : list_np) + // for (auto c2 : list_np) + // for (auto c3 : list_np) + // setup_type(std::string("$_DLATCHSR_") + c1 + c2 + c3 + "_", {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCHSR_NNN_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCHSR_NNP_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCHSR_NPN_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCHSR_NPP_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCHSR_PNN_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCHSR_PNP_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCHSR_PPN_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features); + setup_type(ID($_DLATCHSR_PPP_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features); + } + constexpr CellTableBuilder() { + setup_internals_other(); + setup_internals_eval(); + setup_internals_ff(); + setup_internals_anyinit(); + setup_internals_mem_noff(); + setup_stdcells_tristate(); + setup_stdcells_eval(); + setup_stdcells_ff(); + } + +}; + +constexpr CellTableBuilder builder{}; + +struct PortInfo { + struct PortLists { + std::array data{}; + constexpr CellTableBuilder::PortList operator()(IdString type) const { + return data[type.index_]; + } + constexpr CellTableBuilder::PortList& operator[](size_t idx) { + return data[idx]; + } + constexpr size_t size() const { return data.size(); } + }; + PortLists inputs {}; + PortLists outputs {}; + constexpr PortInfo() { + for (size_t i = 0; i < builder.count; ++i) { + auto& cell = builder.cells[i]; + size_t idx = cell.type.index_; + inputs[idx] = cell.inputs; + outputs[idx] = cell.outputs; + } + } +}; + +struct Categories { + struct Category { + std::array data{}; + constexpr bool operator()(IdString type) const { + size_t idx = type.index_; + if (idx >= MAX_CELLS) + return false; + return data[idx]; + } + constexpr bool operator[](size_t idx) { + return data[idx]; + } + constexpr void set_id(IdString type, bool val = true) { + size_t idx = type.index_; + if (idx >= MAX_CELLS) + return; // TODO should be an assert but then it's not constexpr + data[idx] = val; + } + constexpr void set(size_t idx, bool val = true) { + data[idx] = val; + } + constexpr size_t size() const { return data.size(); } + }; + Category empty {}; + Category is_known {}; + Category is_evaluable {}; + Category is_combinatorial {}; + Category is_synthesizable {}; + Category is_stdcell {}; + Category is_ff {}; + Category is_mem_noff {}; + Category is_anyinit {}; + Category is_tristate {}; + constexpr Categories() { + for (size_t i = 0; i < builder.count; ++i) { + auto& cell = builder.cells[i]; + size_t idx = cell.type.index_; + is_known.set(idx); + is_evaluable.set(idx, cell.features.is_evaluable); + is_combinatorial.set(idx, cell.features.is_combinatorial); + is_synthesizable.set(idx, cell.features.is_synthesizable); + is_stdcell.set(idx, cell.features.is_stdcell); + is_ff.set(idx, cell.features.is_ff); + is_mem_noff.set(idx, cell.features.is_mem_noff); + is_anyinit.set(idx, cell.features.is_anyinit); + is_tristate.set(idx, cell.features.is_tristate); + } + } + constexpr static Category join(Category left, Category right) { + Category c {}; + for (size_t i = 0; i < MAX_CELLS; ++i) { + c.set(i, left[i] || right[i]); + } + return c; + } + constexpr static Category meet(Category left, Category right) { + Category c {}; + for (size_t i = 0; i < MAX_CELLS; ++i) { + c.set(i, left[i] && right[i]); + } + return c; + } + // Sketchy! Make sure to always meet with only the known universe. + // In other words, no modus tollens allowed + constexpr static Category complement(Category arg) { + Category c {}; + for (size_t i = 0; i < MAX_CELLS; ++i) { + c.set(i, !arg[i]); + } + return c; + } +}; + +// Pure +static constexpr PortInfo port_info; +static constexpr Categories categories; + +// Legacy +namespace Compat { + static constexpr auto internals_all = Categories::meet(categories.is_known, Categories::complement(categories.is_stdcell)); + static constexpr auto mem_ff = Categories::join(categories.is_ff, categories.is_mem_noff); + // old setup_internals + setup_stdcells + static constexpr auto nomem_noff = Categories::meet(categories.is_known, Categories::complement(mem_ff)); + static constexpr auto internals_mem_ff = Categories::meet(internals_all, mem_ff); + // old setup_internals + static constexpr auto internals_nomem_noff = Categories::meet(internals_all, nomem_noff); + // old setup_stdcells + static constexpr auto stdcells_nomem_noff = Categories::meet(categories.is_stdcell, nomem_noff); + static constexpr auto stdcells_mem = Categories::meet(categories.is_stdcell, categories.is_mem_noff); + // old setup_internals_eval + // static constexpr auto internals_eval = Categories::meet(internals_all, categories.is_evaluable); +}; + +namespace { + static_assert(categories.is_evaluable(ID($and))); + static_assert(!categories.is_ff(ID($and))); + static_assert(Categories::join(categories.is_evaluable, categories.is_ff)(ID($and))); + static_assert(Categories::join(categories.is_evaluable, categories.is_ff)(ID($dffsr))); + static_assert(!Categories::join(categories.is_evaluable, categories.is_ff)(ID($anyinit))); +} + +}; + +struct NewCellType { + RTLIL::IdString type; + pool inputs, outputs; + bool is_evaluable; + bool is_combinatorial; + bool is_synthesizable; +}; + +struct NewCellTypes { + struct IdStringHash { + std::size_t operator()(const IdString id) const { + return static_cast(id.hash_top().yield()); + } + }; + StaticCellTypes::Categories::Category static_cell_types = StaticCellTypes::categories.empty; + std::unordered_map custom_cell_types {}; + + NewCellTypes() { + static_cell_types = StaticCellTypes::categories.empty; + } + + NewCellTypes(RTLIL::Design *design) { + static_cell_types = StaticCellTypes::categories.empty; + setup(design); + } + void setup(RTLIL::Design *design = NULL) { + if (design) + setup_design(design); + static_cell_types = StaticCellTypes::categories.is_known; + } + void setup_design(RTLIL::Design *design) { + for (auto module : design->modules()) + setup_module(module); + } + + void setup_module(RTLIL::Module *module) { + pool inputs, outputs; + for (RTLIL::IdString wire_name : module->ports) { + RTLIL::Wire *wire = module->wire(wire_name); + if (wire->port_input) + inputs.insert(wire->name); + if (wire->port_output) + outputs.insert(wire->name); + } + setup_type(module->name, inputs, outputs); + } + + void setup_type(RTLIL::IdString type, const pool &inputs, const pool &outputs, bool is_evaluable = false, bool is_combinatorial = false, bool is_synthesizable = false) { + NewCellType ct = {type, inputs, outputs, is_evaluable, is_combinatorial, is_synthesizable}; + custom_cell_types[ct.type] = ct; + } + + void clear() { + custom_cell_types.clear(); + static_cell_types = StaticCellTypes::categories.empty; + } + + bool cell_known(const RTLIL::IdString &type) const { + return static_cell_types(type) || custom_cell_types.count(type) != 0; + } + + bool cell_output(const RTLIL::IdString &type, const RTLIL::IdString &port) const + { + if (static_cell_types(type) && StaticCellTypes::port_info.outputs(type).contains(port)) { + return true; + } + auto it = custom_cell_types.find(type); + return it != custom_cell_types.end() && it->second.outputs.count(port) != 0; + } + + bool cell_input(const RTLIL::IdString &type, const RTLIL::IdString &port) const + { + if (static_cell_types(type) && StaticCellTypes::port_info.inputs(type).contains(port)) { + return true; + } + auto it = custom_cell_types.find(type); + return it != custom_cell_types.end() && it->second.inputs.count(port) != 0; + } + + RTLIL::PortDir cell_port_dir(RTLIL::IdString type, RTLIL::IdString port) const + { + bool is_input, is_output; + if (static_cell_types(type)) { + is_input = StaticCellTypes::port_info.inputs(type).contains(port); + is_output = StaticCellTypes::port_info.outputs(type).contains(port); + } else { + auto it = custom_cell_types.find(type); + if (it == custom_cell_types.end()) + return RTLIL::PD_UNKNOWN; + is_input = it->second.inputs.count(port); + is_output = it->second.outputs.count(port); + } + return RTLIL::PortDir(is_input + is_output * 2); + } + bool cell_evaluable(const RTLIL::IdString &type) const + { + return static_cell_types(type) && StaticCellTypes::categories.is_evaluable(type); + } +}; + +extern NewCellTypes yosys_celltypes; + +YOSYS_NAMESPACE_END + +#endif diff --git a/kernel/register.cc b/kernel/register.cc index 3f5aa49ca56..00cd273834b 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -22,6 +22,7 @@ #include "kernel/json.h" #include "kernel/gzip.h" #include "kernel/log_help.h" +#include "kernel/newcelltypes.h" #include #include @@ -975,16 +976,18 @@ struct HelpPass : public Pass { json.entry("generator", yosys_maybe_version()); dict> groups; - dict> cells; + dict> cells; // iterate over cells bool raise_error = false; - for (auto &it : yosys_celltypes.cell_types) { - auto name = it.first.str(); + for (auto it : StaticCellTypes::builder.cells) { + if (!StaticCellTypes::categories.is_known(it.type)) + continue; + auto name = it.type.str(); if (cell_help_messages.contains(name)) { auto cell_help = cell_help_messages.get(name); groups[cell_help.group].emplace_back(name); - auto cell_pair = pair(cell_help, it.second); + auto cell_pair = pair(cell_help, it); cells.emplace(name, cell_pair); } else { log("ERROR: Missing cell help for cell '%s'.\n", name); @@ -1025,9 +1028,9 @@ struct HelpPass : public Pass { json.name("outputs"); json.value(outputs); vector properties; // CellType properties - if (ct.is_evaluable) properties.push_back("is_evaluable"); - if (ct.is_combinatorial) properties.push_back("is_combinatorial"); - if (ct.is_synthesizable) properties.push_back("is_synthesizable"); + if (ct.features.is_evaluable) properties.push_back("is_evaluable"); + if (ct.features.is_combinatorial) properties.push_back("is_combinatorial"); + if (ct.features.is_synthesizable) properties.push_back("is_synthesizable"); // SimHelper properties size_t last = 0; size_t next = 0; while ((next = ch.tags.find(", ", last)) != string::npos) { diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index d18a709c94d..54fff829c67 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -19,7 +19,7 @@ #include "kernel/yosys.h" #include "kernel/macc.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/binding.h" #include "kernel/sigtools.h" #include "frontends/verilog/verilog_frontend.h" @@ -300,6 +300,7 @@ void RTLIL::OwningIdString::collect_garbage() dict RTLIL::constpad; +// TODO take a look static const pool &builtin_ff_cell_types_internal() { static const pool res = { ID($sr), diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 009da56b984..adfd8d808c3 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -18,7 +18,7 @@ */ #include "kernel/yosys.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #ifdef YOSYS_ENABLE_READLINE # include @@ -91,7 +91,7 @@ const char* yosys_maybe_version() { } RTLIL::Design *yosys_design = NULL; -CellTypes yosys_celltypes; +NewCellTypes yosys_celltypes; #ifdef YOSYS_ENABLE_TCL Tcl_Interp *yosys_tcl_interp = NULL; @@ -240,7 +240,7 @@ void yosys_setup() Pass::init_register(); yosys_design = new RTLIL::Design; - yosys_celltypes.setup(); + yosys_celltypes.static_cell_types = StaticCellTypes::categories.is_known; log_push(); } @@ -269,8 +269,6 @@ void yosys_shutdown() log_errfile = NULL; log_files.clear(); - yosys_celltypes.clear(); - #ifdef YOSYS_ENABLE_TCL if (yosys_tcl_interp != NULL) { if (!Tcl_InterpDeleted(yosys_tcl_interp)) { diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc index b7a5feb57a4..1019c2955ee 100644 --- a/passes/cmds/check.cc +++ b/passes/cmds/check.cc @@ -20,7 +20,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/celledges.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/utils.h" #include "kernel/log_help.h" diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 6da15c19a38..539a2f651c7 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -18,7 +18,7 @@ */ #include "kernel/yosys.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/sigtools.h" #include "kernel/log_help.h" @@ -488,7 +488,7 @@ static int parse_comma_list(std::set &tokens, const std::string } } -static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::vector &rules, std::set &limits, int max_objects, char mode, CellTypes &ct, bool eval_only) +static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::vector &rules, std::set &limits, int max_objects, char mode, NewCellTypes &ct, bool eval_only) { int sel_objects = 0; bool is_input, is_output; @@ -564,7 +564,7 @@ static void select_op_expand(RTLIL::Design *design, const std::string &arg, char std::vector rules; std::set limits; - CellTypes ct; + NewCellTypes ct; if (mode != 'x') ct.setup(design); diff --git a/passes/cmds/torder.cc b/passes/cmds/torder.cc index 537b6793de6..52c00072f29 100644 --- a/passes/cmds/torder.cc +++ b/passes/cmds/torder.cc @@ -18,7 +18,7 @@ */ #include "kernel/yosys.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/sigtools.h" #include "kernel/utils.h" #include "kernel/log_help.h" diff --git a/passes/equiv/equiv_induct.cc b/passes/equiv/equiv_induct.cc index e1a3a7990de..dad27ef4d9c 100644 --- a/passes/equiv/equiv_induct.cc +++ b/passes/equiv/equiv_induct.cc @@ -20,6 +20,7 @@ #include "kernel/yosys.h" #include "kernel/satgen.h" #include "kernel/sigtools.h" +#include "kernel/newcelltypes.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN diff --git a/passes/equiv/equiv_simple.cc b/passes/equiv/equiv_simple.cc index 97f95ac63fe..844a979ac78 100644 --- a/passes/equiv/equiv_simple.cc +++ b/passes/equiv/equiv_simple.cc @@ -19,6 +19,7 @@ #include "kernel/yosys.h" #include "kernel/satgen.h" +#include "kernel/newcelltypes.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 3892c7581cc..d824fd2dbc2 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -21,6 +21,7 @@ #include "kernel/sigtools.h" #include "kernel/log.h" #include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/ffinit.h" #include #include @@ -101,7 +102,10 @@ struct keep_cache_t }; keep_cache_t keep_cache; -CellTypes ct_reg, ct_all; +static constexpr auto ct_reg = StaticCellTypes::Categories::join( + StaticCellTypes::Compat::mem_ff, + StaticCellTypes::categories.is_anyinit); +NewCellTypes ct_all; int count_rm_cells, count_rm_wires; void rmunused_module_cells(Module *module, bool verbose) @@ -307,10 +311,10 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (!purge_mode) for (auto &it : module->cells_) { RTLIL::Cell *cell = it.second; - if (ct_reg.cell_known(cell->type)) { + if (ct_reg(cell->type)) { bool clk2fflogic = cell->get_bool_attribute(ID(clk2fflogic)); for (auto &it2 : cell->connections()) - if (clk2fflogic ? it2.first == ID::D : ct_reg.cell_output(cell->type, it2.first)) + if (clk2fflogic ? it2.first == ID::D : ct_all.cell_output(cell->type, it2.first)) register_signals.add(it2.second); } for (auto &it2 : cell->connections()) @@ -516,14 +520,12 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos bool rmunused_module_init(RTLIL::Module *module, bool verbose) { bool did_something = false; - CellTypes fftypes; - fftypes.setup_internals_mem(); SigMap sigmap(module); dict qbits; for (auto cell : module->cells()) - if (fftypes.cell_known(cell->type) && cell->hasPort(ID::Q)) + if (StaticCellTypes::Compat::internals_mem_ff(cell->type) && cell->hasPort(ID::Q)) { SigSpec sig = cell->getPort(ID::Q); @@ -696,10 +698,6 @@ struct OptCleanPass : public Pass { keep_cache.reset(design, purge_mode); - ct_reg.setup_internals_mem(); - ct_reg.setup_internals_anyinit(); - ct_reg.setup_stdcells_mem(); - ct_all.setup(design); count_rm_cells = 0; @@ -719,7 +717,6 @@ struct OptCleanPass : public Pass { design->check(); keep_cache.reset(); - ct_reg.clear(); ct_all.clear(); log_pop(); @@ -760,10 +757,6 @@ struct CleanPass : public Pass { keep_cache.reset(design); - ct_reg.setup_internals_mem(); - ct_reg.setup_internals_anyinit(); - ct_reg.setup_stdcells_mem(); - ct_all.setup(design); count_rm_cells = 0; @@ -784,7 +777,6 @@ struct CleanPass : public Pass { design->check(); keep_cache.reset(); - ct_reg.clear(); ct_all.clear(); request_garbage_collection(); diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 86d96ea7a70..e8be360a8ff 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -20,6 +20,7 @@ #include "kernel/register.h" #include "kernel/sigtools.h" #include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/utils.h" #include "kernel/log.h" #include @@ -31,7 +32,7 @@ PRIVATE_NAMESPACE_BEGIN bool did_something; -void replace_undriven(RTLIL::Module *module, const CellTypes &ct) +void replace_undriven(RTLIL::Module *module, const NewCellTypes &ct) { SigMap sigmap(module); SigPool driven_signals; @@ -409,9 +410,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - CellTypes ct_memcells; - ct_memcells.setup_stdcells_mem(); - if (!noclkinv) for (auto cell : module->cells()) if (design->selected(module, cell)) { @@ -435,7 +433,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($dffe), ID($adffe), ID($aldffe), ID($sdffe), ID($sdffce), ID($dffsre), ID($dlatch), ID($adlatch), ID($dlatchsr))) handle_polarity_inv(cell, ID::EN, ID::EN_POLARITY, assign_map, invert_map); - if (!ct_memcells.cell_known(cell->type)) + if (!StaticCellTypes::Compat::stdcells_mem(cell->type)) continue; handle_clkpol_celltype_swap(cell, "$_SR_N?_", "$_SR_P?_", ID::S, assign_map, invert_map); @@ -2358,7 +2356,7 @@ struct OptExprPass : public Pass { } extra_args(args, argidx, design); - CellTypes ct(design); + NewCellTypes ct(design); for (auto module : design->selected_modules()) { log("Optimizing module %s.\n", log_id(module)); diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 307cd299bd5..f7843cc0809 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -23,6 +23,7 @@ #include "kernel/modtools.h" #include "kernel/utils.h" #include "kernel/macc.h" +#include "kernel/newcelltypes.h" #include USING_YOSYS_NAMESPACE @@ -38,19 +39,18 @@ struct ShareWorkerConfig bool opt_force; bool opt_aggressive; bool opt_fast; - pool generic_uni_ops, generic_bin_ops, generic_cbin_ops, generic_other_ops; + StaticCellTypes::Categories::Category generic_uni_ops, generic_bin_ops, generic_cbin_ops, generic_other_ops; }; struct ShareWorker { const ShareWorkerConfig config; int limit; - pool generic_ops; + StaticCellTypes::Categories::Category generic_ops; RTLIL::Design *design; RTLIL::Module *module; - CellTypes fwd_ct, cone_ct; ModWalker modwalker; pool cells_to_remove; @@ -75,7 +75,7 @@ struct ShareWorker queue_bits.insert(modwalker.signal_outputs.begin(), modwalker.signal_outputs.end()); for (auto &it : module->cells_) - if (!fwd_ct.cell_known(it.second->type)) { + if (!StaticCellTypes::Compat::internals_nomem_noff(it.second->type)) { pool &bits = modwalker.cell_inputs[it.second]; queue_bits.insert(bits.begin(), bits.end()); } @@ -95,7 +95,7 @@ struct ShareWorker queue_bits.insert(bits.begin(), bits.end()); visited_cells.insert(pbit.cell); } - if (fwd_ct.cell_known(pbit.cell->type) && visited_cells.count(pbit.cell) == 0) { + if (StaticCellTypes::Compat::internals_nomem_noff(pbit.cell->type) && visited_cells.count(pbit.cell) == 0) { pool &bits = modwalker.cell_inputs[pbit.cell]; terminal_bits.insert(bits.begin(), bits.end()); queue_bits.insert(bits.begin(), bits.end()); @@ -388,7 +388,7 @@ struct ShareWorker continue; } - if (generic_ops.count(cell->type)) { + if (generic_ops(cell->type)) { if (config.opt_aggressive) shareable_cells.insert(cell); continue; @@ -412,7 +412,7 @@ struct ShareWorker return true; } - if (config.generic_uni_ops.count(c1->type)) + if (config.generic_uni_ops(c1->type)) { if (!config.opt_aggressive) { @@ -429,7 +429,7 @@ struct ShareWorker return true; } - if (config.generic_bin_ops.count(c1->type) || c1->type == ID($alu)) + if (config.generic_bin_ops(c1->type) || c1->type == ID($alu)) { if (!config.opt_aggressive) { @@ -449,7 +449,7 @@ struct ShareWorker return true; } - if (config.generic_cbin_ops.count(c1->type)) + if (config.generic_cbin_ops(c1->type)) { if (!config.opt_aggressive) { @@ -511,7 +511,7 @@ struct ShareWorker { log_assert(c1->type == c2->type); - if (config.generic_uni_ops.count(c1->type)) + if (config.generic_uni_ops(c1->type)) { if (c1->parameters.at(ID::A_SIGNED).as_bool() != c2->parameters.at(ID::A_SIGNED).as_bool()) { @@ -560,11 +560,11 @@ struct ShareWorker return supercell; } - if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == ID($alu)) + if (config.generic_bin_ops(c1->type) || config.generic_cbin_ops(c1->type) || c1->type == ID($alu)) { bool modified_src_cells = false; - if (config.generic_cbin_ops.count(c1->type)) + if (config.generic_cbin_ops(c1->type)) { int score_unflipped = max(c1->parameters.at(ID::A_WIDTH).as_int(), c2->parameters.at(ID::A_WIDTH).as_int()) + max(c1->parameters.at(ID::B_WIDTH).as_int(), c2->parameters.at(ID::B_WIDTH).as_int()); @@ -758,7 +758,7 @@ struct ShareWorker recursion_state.insert(cell); for (auto c : consumer_cells) - if (fwd_ct.cell_known(c->type)) { + if (StaticCellTypes::Compat::internals_nomem_noff(c->type)) { const pool &bits = find_forbidden_controls(c); forbidden_controls_cache[cell].insert(bits.begin(), bits.end()); } @@ -897,7 +897,7 @@ struct ShareWorker return activation_patterns_cache.at(cell); } for (auto &pbit : modwalker.signal_consumers[bit]) { - log_assert(fwd_ct.cell_known(pbit.cell->type)); + log_assert(StaticCellTypes::Compat::internals_nomem_noff(pbit.cell->type)); if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && (pbit.port == ID::A || pbit.port == ID::B)) driven_data_muxes.insert(pbit.cell); else @@ -1214,24 +1214,10 @@ struct ShareWorker ShareWorker(ShareWorkerConfig config, RTLIL::Design* design) : config(config), design(design), modwalker(design) { - generic_ops.insert(config.generic_uni_ops.begin(), config.generic_uni_ops.end()); - generic_ops.insert(config.generic_bin_ops.begin(), config.generic_bin_ops.end()); - generic_ops.insert(config.generic_cbin_ops.begin(), config.generic_cbin_ops.end()); - generic_ops.insert(config.generic_other_ops.begin(), config.generic_other_ops.end()); - - fwd_ct.setup_internals(); - - cone_ct.setup_internals(); - cone_ct.cell_types.erase(ID($mul)); - cone_ct.cell_types.erase(ID($mod)); - cone_ct.cell_types.erase(ID($div)); - cone_ct.cell_types.erase(ID($modfloor)); - cone_ct.cell_types.erase(ID($divfloor)); - cone_ct.cell_types.erase(ID($pow)); - cone_ct.cell_types.erase(ID($shl)); - cone_ct.cell_types.erase(ID($shr)); - cone_ct.cell_types.erase(ID($sshl)); - cone_ct.cell_types.erase(ID($sshr)); + generic_ops = StaticCellTypes::Categories::join(generic_ops, config.generic_uni_ops); + generic_ops = StaticCellTypes::Categories::join(generic_ops, config.generic_bin_ops); + generic_ops = StaticCellTypes::Categories::join(generic_ops, config.generic_cbin_ops); + generic_ops = StaticCellTypes::Categories::join(generic_ops, config.generic_other_ops); } void operator()(RTLIL::Module *module) { @@ -1561,45 +1547,45 @@ struct SharePass : public Pass { config.opt_aggressive = false; config.opt_fast = false; - config.generic_uni_ops.insert(ID($not)); - // config.generic_uni_ops.insert(ID($pos)); - config.generic_uni_ops.insert(ID($neg)); - - config.generic_cbin_ops.insert(ID($and)); - config.generic_cbin_ops.insert(ID($or)); - config.generic_cbin_ops.insert(ID($xor)); - config.generic_cbin_ops.insert(ID($xnor)); - - config.generic_bin_ops.insert(ID($shl)); - config.generic_bin_ops.insert(ID($shr)); - config.generic_bin_ops.insert(ID($sshl)); - config.generic_bin_ops.insert(ID($sshr)); - - config.generic_bin_ops.insert(ID($lt)); - config.generic_bin_ops.insert(ID($le)); - config.generic_bin_ops.insert(ID($eq)); - config.generic_bin_ops.insert(ID($ne)); - config.generic_bin_ops.insert(ID($eqx)); - config.generic_bin_ops.insert(ID($nex)); - config.generic_bin_ops.insert(ID($ge)); - config.generic_bin_ops.insert(ID($gt)); - - config.generic_cbin_ops.insert(ID($add)); - config.generic_cbin_ops.insert(ID($mul)); - - config.generic_bin_ops.insert(ID($sub)); - config.generic_bin_ops.insert(ID($div)); - config.generic_bin_ops.insert(ID($mod)); - config.generic_bin_ops.insert(ID($divfloor)); - config.generic_bin_ops.insert(ID($modfloor)); - // config.generic_bin_ops.insert(ID($pow)); - - config.generic_uni_ops.insert(ID($logic_not)); - config.generic_cbin_ops.insert(ID($logic_and)); - config.generic_cbin_ops.insert(ID($logic_or)); - - config.generic_other_ops.insert(ID($alu)); - config.generic_other_ops.insert(ID($macc)); + config.generic_uni_ops.set_id(ID($not)); + // config.generic_uni_ops.set_id(ID($pos)); + config.generic_uni_ops.set_id(ID($neg)); + + config.generic_cbin_ops.set_id(ID($and)); + config.generic_cbin_ops.set_id(ID($or)); + config.generic_cbin_ops.set_id(ID($xor)); + config.generic_cbin_ops.set_id(ID($xnor)); + + config.generic_bin_ops.set_id(ID($shl)); + config.generic_bin_ops.set_id(ID($shr)); + config.generic_bin_ops.set_id(ID($sshl)); + config.generic_bin_ops.set_id(ID($sshr)); + + config.generic_bin_ops.set_id(ID($lt)); + config.generic_bin_ops.set_id(ID($le)); + config.generic_bin_ops.set_id(ID($eq)); + config.generic_bin_ops.set_id(ID($ne)); + config.generic_bin_ops.set_id(ID($eqx)); + config.generic_bin_ops.set_id(ID($nex)); + config.generic_bin_ops.set_id(ID($ge)); + config.generic_bin_ops.set_id(ID($gt)); + + config.generic_cbin_ops.set_id(ID($add)); + config.generic_cbin_ops.set_id(ID($mul)); + + config.generic_bin_ops.set_id(ID($sub)); + config.generic_bin_ops.set_id(ID($div)); + config.generic_bin_ops.set_id(ID($mod)); + config.generic_bin_ops.set_id(ID($divfloor)); + config.generic_bin_ops.set_id(ID($modfloor)); + // config.generic_bin_ops.set_id(ID($pow)); + + config.generic_uni_ops.set_id(ID($logic_not)); + config.generic_cbin_ops.set_id(ID($logic_and)); + config.generic_cbin_ops.set_id(ID($logic_or)); + + config.generic_other_ops.set_id(ID($alu)); + config.generic_other_ops.set_id(ID($macc)); log_header(design, "Executing SHARE pass (SAT-based resource sharing).\n"); diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index a29651653a8..7ea193ac6fd 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -20,6 +20,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/mem.h" #include "kernel/fstdata.h" #include "kernel/ff.h" diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 3a814d0b71c..85e177fd418 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -43,7 +43,7 @@ #include "kernel/register.h" #include "kernel/sigtools.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/ffinit.h" #include "kernel/ff.h" #include "kernel/cost.h" @@ -2382,7 +2382,7 @@ struct AbcPass : public Pass { continue; } - CellTypes ct(design); + NewCellTypes ct(design); std::vector all_cells = mod->selected_cells(); pool unassigned_cells(all_cells.begin(), all_cells.end()); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 8d3869ececc..75efd230a7e 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -21,7 +21,7 @@ #include "kernel/register.h" #include "kernel/sigtools.h" #include "kernel/utils.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/timinginfo.h" USING_YOSYS_NAMESPACE diff --git a/tests/pyosys/test_dict.py b/tests/pyosys/test_dict.py index 717fed8eafb..57d4dc82f87 100644 --- a/tests/pyosys/test_dict.py +++ b/tests/pyosys/test_dict.py @@ -35,10 +35,4 @@ assert before - 1 == len(repr_test) # test noncomparable -## if ys.CellType ever gets an == operator just disable this section -uncomparable_value = ys.Globals.yosys_celltypes.cell_types[ys.IdString("$not")] - -x = ys.IdstringToCelltypeDict({ ys.IdString("\\a"): uncomparable_value}) -y = ys.IdstringToCelltypeDict({ ys.IdString("\\a"): uncomparable_value}) - -assert x != y # not comparable +# TODO newcelltypes? diff --git a/tests/unit/kernel/cellTypesTest.cc b/tests/unit/kernel/cellTypesTest.cc new file mode 100644 index 00000000000..aec8b05fc90 --- /dev/null +++ b/tests/unit/kernel/cellTypesTest.cc @@ -0,0 +1,46 @@ +#include +#include "kernel/yosys.h" +#include "kernel/yosys_common.h" +#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" + +#include + +YOSYS_NAMESPACE_BEGIN + +TEST(CellTypesTest, basic) +{ + yosys_setup(); + log_files.push_back(stdout); + CellTypes older; + NewCellTypes newer; + older.setup(nullptr); + newer.setup(nullptr); + older.setup_type(ID(bleh), {ID::G}, {ID::H, ID::I}, false, true); + newer.setup_type(ID(bleh), {ID::G}, {ID::H, ID::I}, false, true); + + EXPECT_EQ(older.cell_known(ID(aaaaa)), newer.cell_known(ID(aaaaa))); + EXPECT_EQ(older.cell_known(ID($and)), newer.cell_known(ID($and))); + auto check_port = [&](auto type, auto port) { + EXPECT_EQ(older.cell_port_dir(type, port), newer.cell_port_dir(type, port)); + EXPECT_EQ(older.cell_input(type, port), newer.cell_input(type, port)); + EXPECT_EQ(older.cell_output(type, port), newer.cell_output(type, port)); + }; + for (size_t i = 0; i < static_cast(RTLIL::StaticId::STATIC_ID_END); i++) { + IdString type; + type.index_ = i; + EXPECT_EQ(older.cell_known(type), newer.cell_known(type)); + if (older.cell_evaluable(type) != newer.cell_evaluable(type)) + std::cout << type.str() << "\n"; + EXPECT_EQ(older.cell_evaluable(type), newer.cell_evaluable(type)); + for (auto port : StaticCellTypes::builder.cells.data()->inputs.ports) + check_port(type, port); + for (auto port : StaticCellTypes::builder.cells.data()->outputs.ports) + check_port(type, port); + + EXPECT_EQ(RTLIL::builtin_ff_cell_types().count(type), StaticCellTypes::categories.is_ff(type)); + } + yosys_shutdown(); +} + +YOSYS_NAMESPACE_END