From b474ce0c67b996acf44e8828ad7bee71bf71d346 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 15:06:36 +0100 Subject: [PATCH 01/31] newcelltypes: init --- Makefile | 1 + kernel/newcelltypes.h | 435 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 436 insertions(+) create mode 100644 kernel/newcelltypes.h 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/kernel/newcelltypes.h b/kernel/newcelltypes.h new file mode 100644 index 00000000000..1c0a2c2db10 --- /dev/null +++ b/kernel/newcelltypes.h @@ -0,0 +1,435 @@ +#ifndef NEWCELLTYPES_H +#define NEWCELLTYPES_H + +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN + +namespace TurboCellTypes { + +constexpr int MAX_CELLS = 300; +constexpr int MAX_PORTS = 10; +template +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 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_eval() + { + 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 { + .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 { + .is_anyinit = true, + }; + setup_type(ID($anyinit), {ID::D}, {ID::Q}, features); + } + constexpr void setup_internals_mem_noff() + { + 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 { + .is_stdcell = true, + .is_tristate = true, + }; + setup_type(ID($_TBUF_), {ID::A, ID::E}, {ID::Y}, features); + } + // TODO check correctness in unit test + constexpr void setup_stdcells_ff() { + Features features { + .is_stdcell = true, + .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_eval(); + setup_internals_ff(); + setup_internals_anyinit(); + setup_internals_mem_noff(); + setup_stdcells_tristate(); + setup_stdcells_ff(); + // TODO + } + +}; + + +constexpr CellTableBuilder turbo_builder{}; + +struct Categories { + struct Category { + std::array data{}; + constexpr bool operator()(IdString type) const { + return data[type.index_]; + } + constexpr bool& operator[](size_t idx) { + return data[idx]; + } + // Optional: Helper to expose size + constexpr size_t size() const { return data.size(); } + }; + 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 < turbo_builder.count; ++i) { + auto& c = turbo_builder.cells[i]; + size_t idx = c.type.index_; + is_evaluable[idx] = c.features.is_evaluable; + is_combinatorial[idx] = c.features.is_combinatorial; + is_synthesizable[idx] = c.features.is_synthesizable; + is_stdcell[idx] = c.features.is_stdcell; + is_ff[idx] = c.features.is_ff; + is_mem_noff[idx] = c.features.is_mem_noff; + is_anyinit[idx] = c.features.is_anyinit; + is_tristate[idx] = c.features.is_tristate; + } + } + constexpr static Category join(Category left, Category right) { + Category c {}; + for (size_t i = 0; i < MAX_CELLS; ++i) { + c[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[i] = left[i] && right[i]; + } + return c; + } + constexpr static Category complement(Category old) { + Category c {}; + for (size_t i = 0; i < MAX_CELLS; ++i) { + c[i] = !old[i]; + } + return c; + } +}; + +// Pure +static constexpr Categories categories; + +// Legacy +namespace Compat { + static constexpr auto internals_all = Categories::complement(categories.is_stdcell); + static constexpr auto internals_mem_ff = Categories::meet(categories.is_ff, categories.is_mem_noff); + // auto stdcells_mem = Categories::meet(internals_all, categories.is_mem_noff); +}; + +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))); + +} + + + +}; +YOSYS_NAMESPACE_END + +#endif From 2e2f9e2469afa427646990db36be697839e7d325 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 15:07:17 +0100 Subject: [PATCH 02/31] opt_clean: use newcelltypes --- passes/opt/opt_clean.cc | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 3892c7581cc..e631c46557c 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 = TurboCellTypes::Categories::join( + TurboCellTypes::Compat::internals_mem_ff, + TurboCellTypes::categories.is_anyinit); +CellTypes 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 (TurboCellTypes::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(); From d1ade0128625c2692ea0f9ef0fe4422bef09d1d0 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 15:15:16 +0100 Subject: [PATCH 03/31] opt_expr: use newcelltypes --- kernel/newcelltypes.h | 2 +- passes/opt/opt_expr.cc | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index 1c0a2c2db10..df1c1396061 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -415,7 +415,7 @@ static constexpr Categories categories; namespace Compat { static constexpr auto internals_all = Categories::complement(categories.is_stdcell); static constexpr auto internals_mem_ff = Categories::meet(categories.is_ff, categories.is_mem_noff); - // auto stdcells_mem = Categories::meet(internals_all, categories.is_mem_noff); + static constexpr auto stdcells_mem = Categories::meet(categories.is_stdcell, categories.is_mem_noff); }; namespace { diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 86d96ea7a70..97079cecae9 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 (!TurboCellTypes::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)); From bea80c06b997865dfbb6ed9c2876488bea45e62a Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 16:11:05 +0100 Subject: [PATCH 04/31] newcelltypes: TurboCellTypes -> StaticCellTypes --- kernel/newcelltypes.h | 2 +- passes/opt/opt_clean.cc | 8 ++++---- passes/opt/opt_expr.cc | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index df1c1396061..92c947439cc 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -5,7 +5,7 @@ YOSYS_NAMESPACE_BEGIN -namespace TurboCellTypes { +namespace StaticCellTypes { constexpr int MAX_CELLS = 300; constexpr int MAX_PORTS = 10; diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index e631c46557c..d9ca996ac7f 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -102,9 +102,9 @@ struct keep_cache_t }; keep_cache_t keep_cache; -static constexpr auto ct_reg = TurboCellTypes::Categories::join( - TurboCellTypes::Compat::internals_mem_ff, - TurboCellTypes::categories.is_anyinit); +static constexpr auto ct_reg = StaticCellTypes::Categories::join( + StaticCellTypes::Compat::internals_mem_ff, + StaticCellTypes::categories.is_anyinit); CellTypes ct_all; int count_rm_cells, count_rm_wires; @@ -525,7 +525,7 @@ bool rmunused_module_init(RTLIL::Module *module, bool verbose) dict qbits; for (auto cell : module->cells()) - if (TurboCellTypes::Compat::internals_mem_ff(cell->type) && cell->hasPort(ID::Q)) + if (StaticCellTypes::Compat::internals_mem_ff(cell->type) && cell->hasPort(ID::Q)) { SigSpec sig = cell->getPort(ID::Q); diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 97079cecae9..e8be360a8ff 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -433,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 (!TurboCellTypes::Compat::stdcells_mem(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); From 29453aa05369de0f44942a08c94b0a9640ab9dfb Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 18:41:26 +0100 Subject: [PATCH 05/31] newcelltypes: wrap design celltypes support --- kernel/newcelltypes.h | 180 ++++++++++++++++++++++++++++++++++++---- passes/opt/opt_clean.cc | 2 +- 2 files changed, 166 insertions(+), 16 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index 92c947439cc..0379eda0518 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -1,6 +1,7 @@ #ifndef NEWCELLTYPES_H #define NEWCELLTYPES_H +#include "kernel/rtlil.h" #include "kernel/yosys.h" YOSYS_NAMESPACE_BEGIN @@ -9,7 +10,6 @@ namespace StaticCellTypes { constexpr int MAX_CELLS = 300; constexpr int MAX_PORTS = 10; -template struct CellTableBuilder { struct PortList { std::array ports{}; @@ -22,6 +22,14 @@ struct CellTableBuilder { } 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 { @@ -349,7 +357,54 @@ struct CellTableBuilder { }; -constexpr CellTableBuilder turbo_builder{}; +constexpr CellTableBuilder turbo_builder{}; + +// template +// struct Worlds { +// struct World { +// std::array data{}; +// constexpr T operator()(IdString type) const { +// return data[type.index_]; +// } +// constexpr T& operator[](size_t idx) { +// return data[idx]; +// } +// constexpr size_t size() const { return data.size(); } +// }; +// World is_known {}; +// World is_evaluable {}; +// World is_combinatorial {}; +// World is_synthesizable {}; +// World is_stdcell {}; +// World is_ff {}; +// World is_mem_noff {}; +// World is_anyinit {}; +// World is_tristate {}; +// virtual constexpr Categories(); +// }; + +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 < turbo_builder.count; ++i) { + auto& cell = turbo_builder.cells[i]; + size_t idx = cell.type.index_; + inputs[idx] = cell.inputs; + outputs[idx] = cell.outputs; + } + } +}; struct Categories { struct Category { @@ -360,9 +415,10 @@ struct Categories { constexpr bool& operator[](size_t idx) { return data[idx]; } - // Optional: Helper to expose size constexpr size_t size() const { return data.size(); } }; + Category empty {}; + Category is_known {}; Category is_evaluable {}; Category is_combinatorial {}; Category is_synthesizable {}; @@ -373,16 +429,17 @@ struct Categories { Category is_tristate {}; constexpr Categories() { for (size_t i = 0; i < turbo_builder.count; ++i) { - auto& c = turbo_builder.cells[i]; - size_t idx = c.type.index_; - is_evaluable[idx] = c.features.is_evaluable; - is_combinatorial[idx] = c.features.is_combinatorial; - is_synthesizable[idx] = c.features.is_synthesizable; - is_stdcell[idx] = c.features.is_stdcell; - is_ff[idx] = c.features.is_ff; - is_mem_noff[idx] = c.features.is_mem_noff; - is_anyinit[idx] = c.features.is_anyinit; - is_tristate[idx] = c.features.is_tristate; + auto& cell = turbo_builder.cells[i]; + size_t idx = cell.type.index_; + is_known[idx] = true; + is_evaluable[idx] = cell.features.is_evaluable; + is_combinatorial[idx] = cell.features.is_combinatorial; + is_synthesizable[idx] = cell.features.is_synthesizable; + is_stdcell[idx] = cell.features.is_stdcell; + is_ff[idx] = cell.features.is_ff; + is_mem_noff[idx] = cell.features.is_mem_noff; + is_anyinit[idx] = cell.features.is_anyinit; + is_tristate[idx] = cell.features.is_tristate; } } constexpr static Category join(Category left, Category right) { @@ -409,12 +466,13 @@ struct Categories { }; // Pure +static constexpr PortInfo port_info; static constexpr Categories categories; // Legacy namespace Compat { static constexpr auto internals_all = Categories::complement(categories.is_stdcell); - static constexpr auto internals_mem_ff = Categories::meet(categories.is_ff, categories.is_mem_noff); + static constexpr auto internals_mem_ff = Categories::join(categories.is_ff, categories.is_mem_noff); static constexpr auto stdcells_mem = Categories::meet(categories.is_stdcell, categories.is_mem_noff); }; @@ -424,12 +482,104 @@ namespace { 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 { + StaticCellTypes::Categories::Category static_cell_types = StaticCellTypes::categories.empty; + dict custom_cell_types; + + NewCellTypes() { + } + NewCellTypes(RTLIL::Design *design) { + setup(design); + } + void setup(RTLIL::Design *design = NULL) { + if (design) + setup_design(design); + } + void setup_design(RTLIL::Design *design) { + for (auto module : design->modules()) + setup_module(module); + static_cell_types = StaticCellTypes::categories.is_known; + } + + 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); + } }; + YOSYS_NAMESPACE_END #endif diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index d9ca996ac7f..b22dfad3a51 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -105,7 +105,7 @@ keep_cache_t keep_cache; static constexpr auto ct_reg = StaticCellTypes::Categories::join( StaticCellTypes::Compat::internals_mem_ff, StaticCellTypes::categories.is_anyinit); -CellTypes ct_all; +NewCellTypes ct_all; int count_rm_cells, count_rm_wires; void rmunused_module_cells(Module *module, bool verbose) From f6e5ea302766e080881c24b0ac19dcf3a46b4e65 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 19:06:46 +0100 Subject: [PATCH 06/31] newcelltypes: bounds check --- kernel/newcelltypes.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index 0379eda0518..b25a690ca3a 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -410,7 +410,10 @@ struct Categories { struct Category { std::array data{}; constexpr bool operator()(IdString type) const { - return data[type.index_]; + size_t idx = type.index_; + if (idx >= MAX_CELLS) + return false; + return data[idx]; } constexpr bool& operator[](size_t idx) { return data[idx]; @@ -496,12 +499,14 @@ struct NewCellType { struct NewCellTypes { StaticCellTypes::Categories::Category static_cell_types = StaticCellTypes::categories.empty; - dict custom_cell_types; + dict 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) { From 79619a75e501ab8a8a6a264a9c3962bb4e8f0bd7 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 20:08:26 +0100 Subject: [PATCH 07/31] newcelltypes: unit test --- tests/unit/kernel/cellTypesTest.cc | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/unit/kernel/cellTypesTest.cc diff --git a/tests/unit/kernel/cellTypesTest.cc b/tests/unit/kernel/cellTypesTest.cc new file mode 100644 index 00000000000..1743ef7a099 --- /dev/null +++ b/tests/unit/kernel/cellTypesTest.cc @@ -0,0 +1,37 @@ +#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; + log("setup nullptr\n"); + older.setup(nullptr); + newer.setup(nullptr); + log("setup type bleh\n"); + 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))); + for (size_t i = 0; i < 1000; i++) { + IdString type; + type.index_ = i; + if (older.cell_known(type) != newer.cell_known(type)) + std::cout << i << " " << type.str() << "\n"; + EXPECT_EQ(older.cell_known(type), newer.cell_known(type)); + + } + yosys_shutdown(); +} + +YOSYS_NAMESPACE_END From f4975f27eecc9c33326c123528821c11b0e916e3 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 20:08:41 +0100 Subject: [PATCH 08/31] newcelltypes: fix unit test --- kernel/newcelltypes.h | 316 +++++++++++++++++++++++++----------------- kernel/rtlil.cc | 1 + 2 files changed, 190 insertions(+), 127 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index b25a690ca3a..b537139e71b 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -8,8 +8,10 @@ YOSYS_NAMESPACE_BEGIN namespace StaticCellTypes { +// Given by last internal cell type IdString constids.inc, compilation error if too low constexpr int MAX_CELLS = 300; -constexpr int MAX_PORTS = 10; +// Currently given by _MUX16_, compilation error if too low +constexpr int MAX_PORTS = 20; struct CellTableBuilder { struct PortList { std::array ports{}; @@ -53,6 +55,39 @@ struct CellTableBuilder { 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 { + .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 { @@ -146,7 +181,34 @@ struct CellTableBuilder { }; setup_type(ID($_TBUF_), {ID::A, ID::E}, {ID::Y}, features); } - // TODO check correctness in unit test + + constexpr void setup_stdcells_eval() + { + Features features { + .is_evaluable = true, + .is_stdcell = 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 { .is_stdcell = true, @@ -156,10 +218,10 @@ struct CellTableBuilder { // 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($_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); @@ -179,179 +241,180 @@ struct CellTableBuilder { // 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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(); - // TODO } }; @@ -512,12 +575,11 @@ struct NewCellTypes { 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); - static_cell_types = StaticCellTypes::categories.is_known; } void setup_module(RTLIL::Module *module) { diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index d18a709c94d..a1bee6db60b 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -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), From e2e7e5ef6aea6a8fcb1faf53532f20de55afd1e0 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 20:17:27 +0100 Subject: [PATCH 09/31] share: use newcelltypes --- kernel/newcelltypes.h | 9 +++ passes/opt/share.cc | 128 +++++++++++++++++++----------------------- 2 files changed, 66 insertions(+), 71 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index b537139e71b..6f520d891e2 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -481,6 +481,15 @@ struct Categories { 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 {}; 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"); From 746e9f6bcd6aef7837f8c9a81b69de11813e05d9 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 20:21:33 +0100 Subject: [PATCH 10/31] newcelltypes: refactor --- kernel/newcelltypes.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index 6f520d891e2..e5c1bc76a5b 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -478,7 +478,7 @@ struct Categories { return false; return data[idx]; } - constexpr bool& operator[](size_t idx) { + constexpr bool operator[](size_t idx) { return data[idx]; } constexpr void set_id(IdString type, bool val = true) { @@ -506,35 +506,35 @@ struct Categories { for (size_t i = 0; i < turbo_builder.count; ++i) { auto& cell = turbo_builder.cells[i]; size_t idx = cell.type.index_; - is_known[idx] = true; - is_evaluable[idx] = cell.features.is_evaluable; - is_combinatorial[idx] = cell.features.is_combinatorial; - is_synthesizable[idx] = cell.features.is_synthesizable; - is_stdcell[idx] = cell.features.is_stdcell; - is_ff[idx] = cell.features.is_ff; - is_mem_noff[idx] = cell.features.is_mem_noff; - is_anyinit[idx] = cell.features.is_anyinit; - is_tristate[idx] = cell.features.is_tristate; + 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[i] = left[i] || right[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[i] = left[i] && right[i]; + c.set(i, left[i] && right[i]); } return c; } - constexpr static Category complement(Category old) { + constexpr static Category complement(Category arg) { Category c {}; for (size_t i = 0; i < MAX_CELLS; ++i) { - c[i] = !old[i]; + c.set(i, !arg[i]); } return c; } From 4b55e5ff5f5cef551e4db5c093419e486219d5f3 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 22:41:12 +0100 Subject: [PATCH 11/31] newcelltypes: fix non-cells --- kernel/newcelltypes.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index e5c1bc76a5b..005b4c117bc 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -531,6 +531,8 @@ struct Categories { } 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) { @@ -546,8 +548,12 @@ static constexpr Categories categories; // Legacy namespace Compat { - static constexpr auto internals_all = Categories::complement(categories.is_stdcell); - static constexpr auto internals_mem_ff = Categories::join(categories.is_ff, categories.is_mem_noff); + 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); + 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); static constexpr auto stdcells_mem = Categories::meet(categories.is_stdcell, categories.is_mem_noff); }; From 8c53b706f00a69d6dba2f56188ba33a7f7d19ed2 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 23:19:26 +0100 Subject: [PATCH 12/31] fixup! opt_clean: use newcelltypes --- passes/opt/opt_clean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index b22dfad3a51..d824fd2dbc2 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -103,7 +103,7 @@ struct keep_cache_t keep_cache_t keep_cache; static constexpr auto ct_reg = StaticCellTypes::Categories::join( - StaticCellTypes::Compat::internals_mem_ff, + StaticCellTypes::Compat::mem_ff, StaticCellTypes::categories.is_anyinit); NewCellTypes ct_all; int count_rm_cells, count_rm_wires; From 9877d189ce6f13b1958cfd5228404f32ca03b0fd Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 23:36:40 +0100 Subject: [PATCH 13/31] modtools: use newcelltypes --- kernel/modtools.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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; From ce3c23f969ecb41253e8fe482affb3a92b1e5615 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 23:47:56 +0100 Subject: [PATCH 14/31] consteval: use newcelltypes --- kernel/consteval.h | 6 +++--- kernel/newcelltypes.h | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel/consteval.h b/kernel/consteval.h index b13c7ea5c5b..7450661b2ed 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::stdcells_nomem_noff; for (auto &it : module->cells_) { if (!ct.cell_known(it.second->type)) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index 005b4c117bc..28584b1f11b 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -554,6 +554,8 @@ namespace Compat { 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); }; From a8509aee48ab2a2212bb771bf19eea5eb5d8f97c Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 23:51:09 +0100 Subject: [PATCH 15/31] fixup! consteval: use newcelltypes --- kernel/consteval.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/consteval.h b/kernel/consteval.h index 7450661b2ed..82169f31efd 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -42,7 +42,7 @@ struct ConstEval ConstEval(RTLIL::Module *module, RTLIL::State defaultval = RTLIL::State::Sm) : module(module), assign_map(module), defaultval(defaultval) { auto ct = NewCellTypes(); - ct.static_cell_types = StaticCellTypes::Compat::stdcells_nomem_noff; + ct.static_cell_types = StaticCellTypes::Compat::nomem_noff; for (auto &it : module->cells_) { if (!ct.cell_known(it.second->type)) From 299d64ad9fee77eda9e5e273e17a8f67cc217c3c Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 23:52:30 +0100 Subject: [PATCH 16/31] newcelltypes: comment --- kernel/newcelltypes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index 28584b1f11b..be661fc4f14 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -550,6 +550,7 @@ static constexpr Categories categories; 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 From 92543c5bfef173b41dcfd07fac4c5f884b524926 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:03:43 +0100 Subject: [PATCH 17/31] newcelltypes: test against builtin_ff_cell_types --- tests/unit/kernel/cellTypesTest.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/unit/kernel/cellTypesTest.cc b/tests/unit/kernel/cellTypesTest.cc index 1743ef7a099..0383d831d08 100644 --- a/tests/unit/kernel/cellTypesTest.cc +++ b/tests/unit/kernel/cellTypesTest.cc @@ -30,6 +30,9 @@ TEST(CellTypesTest, basic) std::cout << i << " " << type.str() << "\n"; EXPECT_EQ(older.cell_known(type), newer.cell_known(type)); + if (RTLIL::builtin_ff_cell_types().count(type) != StaticCellTypes::categories.is_ff(type)) + std::cout << i << " " << type.str() << "\n"; + EXPECT_EQ(RTLIL::builtin_ff_cell_types().count(type), StaticCellTypes::categories.is_ff(type)); } yosys_shutdown(); } From 52d8a3e0cd6060eb8cc2946dde4149c2642c0c78 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:03:53 +0100 Subject: [PATCH 18/31] abc: use newcelltypes --- passes/techmap/abc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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()); From 6cd7c5131a74f2beae1459792a88983ee82b6ef9 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:14:12 +0100 Subject: [PATCH 19/31] aiger2: add TODO --- backends/aiger2/aiger.cc | 2 ++ 1 file changed, 2 insertions(+) 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*/ From ab4fd8c623ba19147409dba3599d79e90e38e92d Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:16:07 +0100 Subject: [PATCH 20/31] drivertools: use newcelltypes --- kernel/drivertools.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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: From 99cb0483b8197254a2ea1cd03c647602339f7b98 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:32:11 +0100 Subject: [PATCH 21/31] backends: use newcelltypes --- backends/blif/blif.cc | 4 ++-- backends/edif/edif.cc | 4 ++-- backends/intersynth/intersynth.cc | 4 ++-- backends/smt2/smt2.cc | 4 ++-- backends/smv/smv.cc | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) 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; From 46f9e70dcef0840b06362e97c3fb082bd53d2eb3 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:47:30 +0100 Subject: [PATCH 22/31] yosys: use newcelltypes for yosys_celltypes --- kernel/celltypes.h | 3 --- kernel/newcelltypes.h | 39 +++++++++------------------------------ kernel/yosys.cc | 8 +++----- 3 files changed, 12 insertions(+), 38 deletions(-) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 2c3535eac61..bf17883b92d 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -548,9 +548,6 @@ struct CellTypes } }; -// initialized by yosys_setup() -extern CellTypes yosys_celltypes; - YOSYS_NAMESPACE_END #endif diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index be661fc4f14..868b54c8f59 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -419,32 +419,7 @@ struct CellTableBuilder { }; - -constexpr CellTableBuilder turbo_builder{}; - -// template -// struct Worlds { -// struct World { -// std::array data{}; -// constexpr T operator()(IdString type) const { -// return data[type.index_]; -// } -// constexpr T& operator[](size_t idx) { -// return data[idx]; -// } -// constexpr size_t size() const { return data.size(); } -// }; -// World is_known {}; -// World is_evaluable {}; -// World is_combinatorial {}; -// World is_synthesizable {}; -// World is_stdcell {}; -// World is_ff {}; -// World is_mem_noff {}; -// World is_anyinit {}; -// World is_tristate {}; -// virtual constexpr Categories(); -// }; +constexpr CellTableBuilder builder{}; struct PortInfo { struct PortLists { @@ -460,8 +435,8 @@ struct PortInfo { PortLists inputs {}; PortLists outputs {}; constexpr PortInfo() { - for (size_t i = 0; i < turbo_builder.count; ++i) { - auto& cell = turbo_builder.cells[i]; + 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; @@ -503,8 +478,8 @@ struct Categories { Category is_anyinit {}; Category is_tristate {}; constexpr Categories() { - for (size_t i = 0; i < turbo_builder.count; ++i) { - auto& cell = turbo_builder.cells[i]; + 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); @@ -558,6 +533,8 @@ namespace Compat { // 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 { @@ -665,6 +642,8 @@ struct NewCellTypes { } }; +extern NewCellTypes yosys_celltypes; + YOSYS_NAMESPACE_END #endif 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)) { From 4dddd6fe4bf8b78b1a004643539337f8fb2aebee Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:50:41 +0100 Subject: [PATCH 23/31] yosys: use newcelltypes for yosys_celltypes users --- frontends/aiger/aigerparse.cc | 2 +- kernel/rtlil.cc | 2 +- passes/cmds/check.cc | 2 +- passes/cmds/select.cc | 6 +++--- passes/cmds/torder.cc | 2 +- passes/equiv/equiv_induct.cc | 1 + passes/equiv/equiv_simple.cc | 1 + passes/sat/sim.cc | 1 + passes/techmap/abc9_ops.cc | 2 +- 9 files changed, 11 insertions(+), 8 deletions(-) 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/rtlil.cc b/kernel/rtlil.cc index a1bee6db60b..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" 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/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/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 From e8f7845c5b2a80616a53c44500bb92a2f30a4502 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:53:01 +0100 Subject: [PATCH 24/31] register: use newcelltypes --- kernel/register.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/kernel/register.cc b/kernel/register.cc index 3f5aa49ca56..58cfdcdc7fe 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,16 @@ 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) { + 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 +1026,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) { From 7f436ecc076f73fe265a794250b375aa4bc82229 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 13:15:02 +0100 Subject: [PATCH 25/31] newcelltypes: proper bounds for unit test --- tests/unit/kernel/cellTypesTest.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/kernel/cellTypesTest.cc b/tests/unit/kernel/cellTypesTest.cc index 0383d831d08..1df8ba3adb3 100644 --- a/tests/unit/kernel/cellTypesTest.cc +++ b/tests/unit/kernel/cellTypesTest.cc @@ -23,7 +23,7 @@ TEST(CellTypesTest, basic) EXPECT_EQ(older.cell_known(ID(aaaaa)), newer.cell_known(ID(aaaaa))); EXPECT_EQ(older.cell_known(ID($and)), newer.cell_known(ID($and))); - for (size_t i = 0; i < 1000; i++) { + for (size_t i = 0; i < static_cast(RTLIL::StaticId::STATIC_ID_END); i++) { IdString type; type.index_ = i; if (older.cell_known(type) != newer.cell_known(type)) From ce6cd32065d5f33c23ab449bf4e43e8c6d3ace6f Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 13:17:24 +0100 Subject: [PATCH 26/31] newcelltypes: fix MSVC build --- kernel/newcelltypes.h | 46 ++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index 868b54c8f59..e26de056933 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -57,9 +57,8 @@ struct CellTableBuilder { } constexpr void setup_internals_other() { - Features features { - .is_tristate = true, - }; + Features features {}; + features.is_tristate = true; setup_type(ID($tribuf), {ID::A, ID::EN}, {ID::Y}, features); features = {}; @@ -90,9 +89,8 @@ struct CellTableBuilder { } constexpr void setup_internals_eval() { - Features features { - .is_evaluable = true, - }; + 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), @@ -127,9 +125,8 @@ struct CellTableBuilder { } constexpr void setup_internals_ff() { - Features features { - .is_ff = true, - }; + 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); @@ -149,16 +146,14 @@ struct CellTableBuilder { } constexpr void setup_internals_anyinit() { - Features features { - .is_anyinit = true, - }; + Features features {}; + features.is_anyinit = true; setup_type(ID($anyinit), {ID::D}, {ID::Q}, features); } constexpr void setup_internals_mem_noff() { - Features features { - .is_mem_noff = true, - }; + Features features {}; + features.is_mem_noff = true; // NOT setup_internals_ff() setup_type(ID($memrd), {ID::CLK, ID::EN, ID::ADDR}, {ID::DATA}, features); @@ -175,19 +170,17 @@ struct CellTableBuilder { } constexpr void setup_stdcells_tristate() { - Features features { - .is_stdcell = true, - .is_tristate = true, - }; + 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 { - .is_evaluable = true, - .is_stdcell = true, - }; + 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); @@ -210,10 +203,9 @@ struct CellTableBuilder { } constexpr void setup_stdcells_ff() { - Features features { - .is_stdcell = true, - .is_ff = true, - }; + Features features {}; + features.is_stdcell = true; + features.is_ff = true; // for (auto c1 : list_np) // for (auto c2 : list_np) From 0d13de95959e89bd39ed0088f6a37a351c57e407 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 27 Nov 2025 01:20:52 +0100 Subject: [PATCH 27/31] fixup! register: use newcelltypes --- kernel/register.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/register.cc b/kernel/register.cc index 58cfdcdc7fe..00cd273834b 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -981,6 +981,8 @@ struct HelpPass : public Pass { // iterate over cells bool raise_error = false; 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); From 43ca5254b8c0fcb11fd804559cc2ff2c81c63cd9 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 27 Nov 2025 01:58:06 +0100 Subject: [PATCH 28/31] pyosys: disable test --- tests/pyosys/test_dict.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) 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? From 105c591bbe04c84d809ef6025a14000cc74b096b Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 27 Nov 2025 02:53:29 +0100 Subject: [PATCH 29/31] newcelltypes: use unordered_map --- kernel/newcelltypes.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index e26de056933..c4a4ea3292c 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -548,8 +548,13 @@ struct NewCellType { }; 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; - dict custom_cell_types = {}; + std::unordered_map custom_cell_types {}; NewCellTypes() { static_cell_types = StaticCellTypes::categories.empty; From b3405377960c2debec0023cd68bbf4aaf5305d15 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 27 Nov 2025 03:32:31 +0100 Subject: [PATCH 30/31] celltypes: fix absurd eval declarations --- kernel/celltypes.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index bf17883b92d..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() From 8f627d43fc70ce4685385a920ecdfdedc3cabf15 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 27 Nov 2025 03:32:41 +0100 Subject: [PATCH 31/31] newcelltypes: extend testing --- tests/unit/kernel/cellTypesTest.cc | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/unit/kernel/cellTypesTest.cc b/tests/unit/kernel/cellTypesTest.cc index 1df8ba3adb3..aec8b05fc90 100644 --- a/tests/unit/kernel/cellTypesTest.cc +++ b/tests/unit/kernel/cellTypesTest.cc @@ -14,24 +14,30 @@ TEST(CellTypesTest, basic) log_files.push_back(stdout); CellTypes older; NewCellTypes newer; - log("setup nullptr\n"); older.setup(nullptr); newer.setup(nullptr); - log("setup type bleh\n"); 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; - if (older.cell_known(type) != newer.cell_known(type)) - std::cout << i << " " << type.str() << "\n"; 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); - if (RTLIL::builtin_ff_cell_types().count(type) != StaticCellTypes::categories.is_ff(type)) - std::cout << i << " " << type.str() << "\n"; EXPECT_EQ(RTLIL::builtin_ff_cell_types().count(type), StaticCellTypes::categories.is_ff(type)); } yosys_shutdown();