From a61455645d524df256661ee1278f8f9f40270253 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 15:06:36 +0100 Subject: [PATCH 01/34] 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 0a15c2b23..f6c37d613 100644 --- a/Makefile +++ b/Makefile @@ -613,6 +613,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 000000000..1c0a2c2db --- /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 3671d577a0c9e2fc01c0eae53112c05eb0ef9093 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 15:07:17 +0100 Subject: [PATCH 02/34] 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 f1d21435c..bea514878 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) @@ -310,10 +314,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()) @@ -517,14 +521,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); @@ -697,10 +699,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; @@ -783,7 +776,6 @@ struct CleanPass : public Pass { design->check(); keep_cache.reset(); - ct_reg.clear(); ct_all.clear(); request_garbage_collection(); From 6adc08b0e5a48358de5a2577924da4f7872fa12f Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 15:15:16 +0100 Subject: [PATCH 03/34] 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 1c0a2c2db..df1c13960 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 7131053c9..f7e43beca 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; @@ -407,9 +408,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)) { @@ -433,7 +431,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); @@ -2294,7 +2292,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 35ccaa60d710c1ccdb442386bcbc85a221017bab Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 16:11:05 +0100 Subject: [PATCH 04/34] 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 df1c13960..92c947439 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 bea514878..3afb77512 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::mem_ff, + StaticCellTypes::categories.is_anyinit); CellTypes ct_all; int count_rm_cells, count_rm_wires; @@ -526,7 +526,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 f7e43beca..2c040b09d 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -431,7 +431,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 9e59f05c258fbe95a8342dda4716124b775a32d9 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 18:41:26 +0100 Subject: [PATCH 05/34] newcelltypes: wrap design celltypes support --- kernel/newcelltypes.h | 184 ++++++++++++++++++++++++++++++++++++---- passes/opt/opt_clean.cc | 2 +- 2 files changed, 168 insertions(+), 18 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index 92c947439..0379eda05 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 3afb77512..72d22ddd3 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::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 7e9e88c2ec49fbdd91e12a625c01476336ed3b57 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 19:06:46 +0100 Subject: [PATCH 06/34] 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 0379eda05..b25a690ca 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 2d7d6ca10b3d47797e4bff017d37aaec9853f02c Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 20:08:26 +0100 Subject: [PATCH 07/34] 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 000000000..1743ef7a0 --- /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 3212dfaf1f98d92111ccd5b58bfe752f412b209b Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 20:08:41 +0100 Subject: [PATCH 08/34] 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 b25a690ca..b537139e7 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 eef1c319d..c59c0b1f7 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -288,6 +288,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 07ec8708e41d0b6ca42f6948cac7ae24387a6726 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 20:17:27 +0100 Subject: [PATCH 09/34] share: use newcelltypes --- kernel/newcelltypes.h | 9 ++++ passes/opt/share.cc | 114 ++++++++++++++++++------------------------ 2 files changed, 59 insertions(+), 64 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index b537139e7..6f520d891 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 307cd299b..f7843cc08 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_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.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_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.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.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.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_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.insert(ID($add)); - config.generic_cbin_ops.insert(ID($mul)); + config.generic_cbin_ops.set_id(ID($add)); + config.generic_cbin_ops.set_id(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_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.insert(ID($logic_not)); - config.generic_cbin_ops.insert(ID($logic_and)); - config.generic_cbin_ops.insert(ID($logic_or)); + 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.insert(ID($alu)); - config.generic_other_ops.insert(ID($macc)); + 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 e3f9911e33766b261d1be523986350e67bcf519e Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 20:21:33 +0100 Subject: [PATCH 10/34] newcelltypes: refactor --- kernel/newcelltypes.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index 6f520d891..e5c1bc76a 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 a9463d1aee122b2ebd04545a044aec4756a8e636 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 22:41:12 +0100 Subject: [PATCH 11/34] 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 e5c1bc76a..005b4c117 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 a0f87dc2d1d18e751aa83566211c130713e1365c Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 23:36:40 +0100 Subject: [PATCH 12/34] 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 5cd8e3cb2..193269687 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 @@ -357,7 +358,7 @@ struct ModWalker RTLIL::Design *design; RTLIL::Module *module; - CellTypes ct; + NewCellTypes ct; SigMap sigmap; dict> signal_drivers; From 8e17fb02661a7ae91c9a6b4d171973aa9c3b88fa Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 23:47:56 +0100 Subject: [PATCH 13/34] 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 ca04d722f..d00ae8f33 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 @@ -44,9 +45,8 @@ struct ConstEval ConstEval(RTLIL::Module *module, RTLIL::State defaultval = RTLIL::State::Sm) : module(module), assign_map(module), defaultval(defaultval) { - CellTypes ct; - ct.setup_internals(); - ct.setup_stdcells(); + auto ct = NewCellTypes(); + ct.static_cell_types = StaticCellTypes::Compat::nomem_noff; for (auto &it : module->cells_) { if (!ct.cell_known(it.second->type)) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index 005b4c117..28584b1f1 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 31b86ebc2ea3b177b3aefdb256f5b308ea096de6 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 25 Nov 2025 23:52:30 +0100 Subject: [PATCH 14/34] newcelltypes: comment --- kernel/newcelltypes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index 28584b1f1..be661fc4f 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 d91e1c8607038132df0767e1107084653fe239a1 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:03:43 +0100 Subject: [PATCH 15/34] 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 1743ef7a0..0383d831d 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 4ab22cbb9724cbb3f213329ed1ba53eb4fb9eb2f Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:03:53 +0100 Subject: [PATCH 16/34] 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 6e5b1fba8..a072bf022 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" @@ -2455,7 +2455,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 665b6eeb4a1325f242882d173a3b31a12dc62c51 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:14:12 +0100 Subject: [PATCH 17/34] 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 babc29826..5f7e71a3a 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -45,6 +45,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 c3ed884bc4ce5d8b9a135a1d14a58de057fb7466 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:16:07 +0100 Subject: [PATCH 18/34] 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 ba7b2aa84..28d3be91e 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 @@ private: 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 7a5c303ccd0dde31fe121b130e295a97aeb12eea Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:32:11 +0100 Subject: [PATCH 19/34] 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 85db8679e..cc339bcbc 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 @@ -61,7 +61,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 61d6ee254..145477b6b 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 78eab17da..ad16d50ab 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 d80622029..9d0ebc2aa 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 a6ccbf27f..acefad060 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 5216d32d1b70d095a776c3bd2cb2ac187e4b4bba Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:47:30 +0100 Subject: [PATCH 20/34] 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 34b013dd9..91e0e7070 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 be661fc4f..868b54c8f 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 4264cb772..29fcd48d8 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -18,8 +18,8 @@ */ #include "kernel/yosys.h" -#include "kernel/celltypes.h" #include "kernel/log.h" +#include "kernel/newcelltypes.h" #ifdef YOSYS_ENABLE_READLINE # include @@ -92,7 +92,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; @@ -262,7 +262,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(); } @@ -291,8 +291,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 ecb8b20f6231bf27b7500728a07b710ae812d48a Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:50:41 +0100 Subject: [PATCH 21/34] 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.h | 1 + passes/sat/sim.cc | 1 + passes/techmap/abc9_ops.cc | 2 +- 8 files changed, 10 insertions(+), 8 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index e55349aa7..9931ef78f 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 c59c0b1f7..61dac3313 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 b7a5feb57..1019c2955 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 0df47664f..2359efe03 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 537b6793d..52c00072f 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.h b/passes/equiv/equiv.h index 95d4b25e9..055dc440b 100644 --- a/passes/equiv/equiv.h +++ b/passes/equiv/equiv.h @@ -5,6 +5,7 @@ #include "kernel/yosys_common.h" #include "kernel/sigtools.h" #include "kernel/satgen.h" +#include "kernel/newcelltypes.h" YOSYS_NAMESPACE_BEGIN diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 27d6d12c1..d78da892f 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 8d3869ece..75efd230a 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 12412d1fa59d9bcd3f7d62131968b4200b1c9a36 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 00:53:01 +0100 Subject: [PATCH 22/34] register: use newcelltypes --- kernel/register.cc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/kernel/register.cc b/kernel/register.cc index abde8f47e..cba6d5f99 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -22,6 +22,7 @@ #include "kernel/json.h" #include "kernel/gzip.h" #include "kernel/log_help.h" +#include "kernel/newcelltypes.h" #include #include @@ -975,16 +976,18 @@ struct HelpPass : public Pass { json.entry("generator", yosys_maybe_version()); dict> groups; - dict> cells; + dict> cells; // iterate over cells bool raise_error = false; - for (auto &it : yosys_celltypes.cell_types) { - auto name = it.first.str(); + for (auto it : StaticCellTypes::builder.cells) { + if (!StaticCellTypes::categories.is_known(it.type)) + continue; + auto name = it.type.str(); if (cell_help_messages.contains(name)) { auto cell_help = cell_help_messages.get(name); groups[cell_help.group].emplace_back(name); - auto cell_pair = pair(cell_help, it.second); + auto cell_pair = pair(cell_help, it); cells.emplace(name, cell_pair); } else { log("ERROR: Missing cell help for cell '%s'.\n", name); @@ -1025,9 +1028,9 @@ struct HelpPass : public Pass { json.name("outputs"); json.value(outputs); vector properties; // CellType properties - if (ct.is_evaluable) properties.push_back("is_evaluable"); - if (ct.is_combinatorial) properties.push_back("is_combinatorial"); - if (ct.is_synthesizable) properties.push_back("is_synthesizable"); + if (ct.features.is_evaluable) properties.push_back("is_evaluable"); + if (ct.features.is_combinatorial) properties.push_back("is_combinatorial"); + if (ct.features.is_synthesizable) properties.push_back("is_synthesizable"); // SimHelper properties size_t last = 0; size_t next = 0; while ((next = ch.tags.find(", ", last)) != string::npos) { From f594014befd4aa0611603b7613e13f3c18e3a1db Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 13:15:02 +0100 Subject: [PATCH 23/34] 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 0383d831d..1df8ba3ad 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 661fcb24cb62b0eb4146268f679ce117b87a2f2a Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 26 Nov 2025 13:17:24 +0100 Subject: [PATCH 24/34] 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 868b54c8f..e26de0569 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 ae10e9e9551689e4a76215118eacecca1579e8fe Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 27 Nov 2025 01:58:06 +0100 Subject: [PATCH 25/34] 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 717fed8ea..57d4dc82f 100644 --- a/tests/pyosys/test_dict.py +++ b/tests/pyosys/test_dict.py @@ -35,10 +35,4 @@ print(repr_test.popitem()) 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 793a3513c60dea5c7c323d353701a8da36b96479 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 27 Nov 2025 02:53:29 +0100 Subject: [PATCH 26/34] 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 e26de0569..c4a4ea329 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 0284595e9ca79392fa406671acb0823a253a1aae Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 27 Nov 2025 03:32:31 +0100 Subject: [PATCH 27/34] celltypes: fix absurd eval declarations --- kernel/celltypes.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 91e0e7070..c03cbdcc3 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($tribuf), {ID::A, ID::EN}, {ID::Y}); - 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($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 6d4736269b2611a4f4d6fa4c53a5180af58d28ad Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 27 Nov 2025 03:32:41 +0100 Subject: [PATCH 28/34] 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 1df8ba3ad..aec8b05fc 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(); From cae54a4c7bd8fcade1242cb0a7a6384c1de1697d Mon Sep 17 00:00:00 2001 From: nella Date: Sat, 28 Feb 2026 18:09:34 +0100 Subject: [PATCH 29/34] Aiger use newcelltypes. --- backends/aiger2/aiger.cc | 129 ++++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 50 deletions(-) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index 5f7e71a3a..1831fdb03 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -23,7 +23,7 @@ // - zero-width operands #include "kernel/register.h" -#include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/rtlil.h" USING_YOSYS_NAMESPACE @@ -45,10 +45,30 @@ 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*/ +static constexpr auto known_ops = []() constexpr { + StaticCellTypes::Categories::Category c{}; + // bitwise + for (auto id : {ID($buf), ID($not), ID($mux), ID($and), ID($or), ID($xor), ID($xnor), ID($fa), ID($bwmux)}) + c.set_id(id); + // reduce + for (auto id : {ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool)}) + c.set_id(id); + // logic + for (auto id : {ID($logic_and), ID($logic_or), ID($logic_not)}) + c.set_id(id); + // gates + for (auto id : {ID($_BUF_), ID($_NOT_), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), + ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($_MUX_), ID($_NMUX_), + ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_)}) + c.set_id(id); + // compare + for (auto id : {ID($eq), ID($ne), ID($lt), ID($le), ID($ge), ID($gt)}) + c.set_id(id); + // other + for (auto id : {ID($pos), ID($pmux), ID($bmux)}) + c.set_id(id); + return c; +}(); template struct Index { @@ -94,7 +114,7 @@ struct Index { int pos = index_wires(info, m); for (auto cell : m->cells()) { - if (cell->type.in(KNOWN_OPS) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port))) + if (known_ops(cell->type) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port))) continue; Module *submodule = m->design->module(cell->type); @@ -106,7 +126,7 @@ struct Index { pos += index_module(submodule); } else { if (allow_blackboxes) { - info.found_blackboxes.insert(cell); + info.found_blackboxes.insert(cell); } else { // Even if we don't allow blackboxes these might still be // present outside of any traversed input cones, so we @@ -271,7 +291,7 @@ struct Index { } else if (cell->type.in(ID($lt), ID($le), ID($gt), ID($ge))) { if (cell->type.in(ID($gt), ID($ge))) std::swap(aport, bport); - int carry = cell->type.in(ID($le), ID($ge)) ? CFALSE : CTRUE; + int carry = cell->type.in(ID($le), ID($ge)) ? CFALSE : CTRUE; Lit a = Writer::EMPTY_LIT; Lit b = Writer::EMPTY_LIT; // TODO: this might not be the most economic structure; revisit at a later date @@ -581,7 +601,7 @@ struct Index { // an output of a cell Cell *driver = bit.wire->driverCell(); - if (driver->type.in(KNOWN_OPS)) { + if (known_ops(driver->type)) { ret = impl_op(cursor, driver, bit.wire->driverPort(), bit.offset); } else { Module *def = cursor.enter(*this, driver); @@ -918,15 +938,15 @@ struct XAigerWriter : AigerWriter { std::vector pos; std::vector pis; - // * The aiger output port sequence is COs (inputs to modeled boxes), - // inputs to opaque boxes, then module outputs. COs going first is - // required by abc. - // * proper_pos_counter counts ports which follow after COs - // * The mapping file `pseudopo` and `po` statements use indexing relative - // to the first port following COs. - // * If a module output is directly driven by an opaque box, the emission - // of the po statement in the mapping file is skipped. This is done to - // aid re-integration of the mapped result. + // * The aiger output port sequence is COs (inputs to modeled boxes), + // inputs to opaque boxes, then module outputs. COs going first is + // required by abc. + // * proper_pos_counter counts ports which follow after COs + // * The mapping file `pseudopo` and `po` statements use indexing relative + // to the first port following COs. + // * If a module output is directly driven by an opaque box, the emission + // of the po statement in the mapping file is skipped. This is done to + // aid re-integration of the mapped result. int proper_pos_counter = 0; pool driven_by_opaque_box; @@ -1333,41 +1353,50 @@ struct Aiger2Backend : Backend { log(" perform structural hashing while writing\n"); log("\n"); log(" -flatten\n"); - log(" allow descending into submodules and write a flattened view of the design\n"); - log(" hierarchy starting at the selected top\n"); - log("\n"); + log(" allow descending into submodules and write a flattened view of the design\n"); + log(" hierarchy starting at the selected top\n"); + log("\n"); log("This command is able to ingest all combinational cells except for:\n"); log("\n"); - pool supported = {KNOWN_OPS}; - CellTypes ct; - ct.setup_internals_eval(); log(" "); int col = 0; - for (auto pair : ct.cell_types) - if (!supported.count(pair.first)) { - if (col + pair.first.size() + 2 > 72) { + for (size_t i = 0; i < StaticCellTypes::builder.count; i++) { + auto &cell = StaticCellTypes::builder.cells[i]; + if (!cell.features.is_evaluable) + continue; + if (cell.features.is_stdcell) + continue; + if (known_ops(cell.type)) + continue; + std::string name = log_id(cell.type); + if (col + name.size() + 2 > 72) { log("\n "); col = 0; } - col += pair.first.size() + 2; - log("%s, ", log_id(pair.first)); + col += name.size() + 2; + log("%s, ", name.c_str()); } log("\n"); log("\n"); log("And all combinational gates except for:\n"); log("\n"); - CellTypes ct2; - ct2.setup_stdcells(); log(" "); col = 0; - for (auto pair : ct2.cell_types) - if (!supported.count(pair.first)) { - if (col + pair.first.size() + 2 > 72) { + for (size_t i = 0; i < StaticCellTypes::builder.count; i++) { + auto &cell = StaticCellTypes::builder.cells[i]; + if (!cell.features.is_evaluable) + continue; + if (!cell.features.is_stdcell) + continue; + if (known_ops(cell.type)) + continue; + std::string name = log_id(cell.type); + if (col + name.size() + 2 > 72) { log("\n "); col = 0; } - col += pair.first.size() + 2; - log("%s, ", log_id(pair.first)); + col += name.size() + 2; + log("%s, ", name.c_str()); } log("\n"); } @@ -1425,20 +1454,20 @@ struct XAiger2Backend : Backend { log(" perform structural hashing while writing\n"); log("\n"); log(" -flatten\n"); - log(" allow descending into submodules and write a flattened view of the design\n"); - log(" hierarchy starting at the selected top\n"); - log("\n"); - log(" -mapping_prep\n"); - log(" after the file is written, prepare the module for reintegration of\n"); - log(" a mapping in a subsequent command. all cells which are not blackboxed nor\n"); - log(" whiteboxed are removed from the design as well as all wires which only\n"); - log(" connect to removed cells\n"); - log(" (conflicts with -flatten)\n"); - log("\n"); - log(" -map2 \n"); - log(" write a map2 file which 'read_xaiger2 -sc_mapping' can read to\n"); - log(" reintegrate a mapping\n"); - log(" (conflicts with -flatten)\n"); + log(" allow descending into submodules and write a flattened view of the design\n"); + log(" hierarchy starting at the selected top\n"); + log("\n"); + log(" -mapping_prep\n"); + log(" after the file is written, prepare the module for reintegration of\n"); + log(" a mapping in a subsequent command. all cells which are not blackboxed nor\n"); + log(" whiteboxed are removed from the design as well as all wires which only\n"); + log(" connect to removed cells\n"); + log(" (conflicts with -flatten)\n"); + log("\n"); + log(" -map2 \n"); + log(" write a map2 file which 'read_xaiger2 -sc_mapping' can read to\n"); + log(" reintegrate a mapping\n"); + log(" (conflicts with -flatten)\n"); log("\n"); } From 66bd4716cf31423dcd0174229aed2065de44dad7 Mon Sep 17 00:00:00 2001 From: nella Date: Sat, 28 Feb 2026 18:30:37 +0100 Subject: [PATCH 30/34] rtlil use newcelltypes. --- kernel/rtlil.cc | 158 +---------------------------- kernel/rtlil.h | 2 - passes/cmds/icell_liberty.cc | 3 +- tests/unit/kernel/cellTypesTest.cc | 47 ++++++++- 4 files changed, 47 insertions(+), 163 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 61dac3313..339450c6a 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -288,162 +288,6 @@ 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), - ID($ff), - ID($dff), - ID($dffe), - ID($dffsr), - ID($dffsre), - ID($adff), - ID($adffe), - ID($aldff), - ID($aldffe), - ID($sdff), - ID($sdffe), - ID($sdffce), - ID($dlatch), - ID($adlatch), - ID($dlatchsr), - ID($_DFFE_NN_), - ID($_DFFE_NP_), - ID($_DFFE_PN_), - ID($_DFFE_PP_), - ID($_DFFSR_NNN_), - ID($_DFFSR_NNP_), - ID($_DFFSR_NPN_), - ID($_DFFSR_NPP_), - ID($_DFFSR_PNN_), - ID($_DFFSR_PNP_), - ID($_DFFSR_PPN_), - ID($_DFFSR_PPP_), - ID($_DFFSRE_NNNN_), - ID($_DFFSRE_NNNP_), - ID($_DFFSRE_NNPN_), - ID($_DFFSRE_NNPP_), - ID($_DFFSRE_NPNN_), - ID($_DFFSRE_NPNP_), - ID($_DFFSRE_NPPN_), - ID($_DFFSRE_NPPP_), - ID($_DFFSRE_PNNN_), - ID($_DFFSRE_PNNP_), - ID($_DFFSRE_PNPN_), - ID($_DFFSRE_PNPP_), - ID($_DFFSRE_PPNN_), - ID($_DFFSRE_PPNP_), - ID($_DFFSRE_PPPN_), - ID($_DFFSRE_PPPP_), - ID($_DFF_N_), - ID($_DFF_P_), - ID($_DFF_NN0_), - ID($_DFF_NN1_), - ID($_DFF_NP0_), - ID($_DFF_NP1_), - ID($_DFF_PN0_), - ID($_DFF_PN1_), - ID($_DFF_PP0_), - ID($_DFF_PP1_), - ID($_DFFE_NN0N_), - ID($_DFFE_NN0P_), - ID($_DFFE_NN1N_), - ID($_DFFE_NN1P_), - ID($_DFFE_NP0N_), - ID($_DFFE_NP0P_), - ID($_DFFE_NP1N_), - ID($_DFFE_NP1P_), - ID($_DFFE_PN0N_), - ID($_DFFE_PN0P_), - ID($_DFFE_PN1N_), - ID($_DFFE_PN1P_), - ID($_DFFE_PP0N_), - ID($_DFFE_PP0P_), - ID($_DFFE_PP1N_), - ID($_DFFE_PP1P_), - ID($_ALDFF_NN_), - ID($_ALDFF_NP_), - ID($_ALDFF_PN_), - ID($_ALDFF_PP_), - ID($_ALDFFE_NNN_), - ID($_ALDFFE_NNP_), - ID($_ALDFFE_NPN_), - ID($_ALDFFE_NPP_), - ID($_ALDFFE_PNN_), - ID($_ALDFFE_PNP_), - ID($_ALDFFE_PPN_), - ID($_ALDFFE_PPP_), - ID($_SDFF_NN0_), - ID($_SDFF_NN1_), - ID($_SDFF_NP0_), - ID($_SDFF_NP1_), - ID($_SDFF_PN0_), - ID($_SDFF_PN1_), - ID($_SDFF_PP0_), - ID($_SDFF_PP1_), - ID($_SDFFE_NN0N_), - ID($_SDFFE_NN0P_), - ID($_SDFFE_NN1N_), - ID($_SDFFE_NN1P_), - ID($_SDFFE_NP0N_), - ID($_SDFFE_NP0P_), - ID($_SDFFE_NP1N_), - ID($_SDFFE_NP1P_), - ID($_SDFFE_PN0N_), - ID($_SDFFE_PN0P_), - ID($_SDFFE_PN1N_), - ID($_SDFFE_PN1P_), - ID($_SDFFE_PP0N_), - ID($_SDFFE_PP0P_), - ID($_SDFFE_PP1N_), - ID($_SDFFE_PP1P_), - ID($_SDFFCE_NN0N_), - ID($_SDFFCE_NN0P_), - ID($_SDFFCE_NN1N_), - ID($_SDFFCE_NN1P_), - ID($_SDFFCE_NP0N_), - ID($_SDFFCE_NP0P_), - ID($_SDFFCE_NP1N_), - ID($_SDFFCE_NP1P_), - ID($_SDFFCE_PN0N_), - ID($_SDFFCE_PN0P_), - ID($_SDFFCE_PN1N_), - ID($_SDFFCE_PN1P_), - ID($_SDFFCE_PP0N_), - ID($_SDFFCE_PP0P_), - ID($_SDFFCE_PP1N_), - ID($_SDFFCE_PP1P_), - ID($_SR_NN_), - ID($_SR_NP_), - ID($_SR_PN_), - ID($_SR_PP_), - ID($_DLATCH_N_), - ID($_DLATCH_P_), - ID($_DLATCH_NN0_), - ID($_DLATCH_NN1_), - ID($_DLATCH_NP0_), - ID($_DLATCH_NP1_), - ID($_DLATCH_PN0_), - ID($_DLATCH_PN1_), - ID($_DLATCH_PP0_), - ID($_DLATCH_PP1_), - ID($_DLATCHSR_NNN_), - ID($_DLATCHSR_NNP_), - ID($_DLATCHSR_NPN_), - ID($_DLATCHSR_NPP_), - ID($_DLATCHSR_PNN_), - ID($_DLATCHSR_PNP_), - ID($_DLATCHSR_PPN_), - ID($_DLATCHSR_PPP_), - ID($_FF_), - }; - return res; -} - -const pool &RTLIL::builtin_ff_cell_types() { - return builtin_ff_cell_types_internal(); -} - #define check(condition) log_assert(condition && "malformed Const union") const Const::bitvectype& Const::get_bits() const { @@ -4611,7 +4455,7 @@ bool RTLIL::Cell::is_mem_cell() const } bool RTLIL::Cell::is_builtin_ff() const { - return builtin_ff_cell_types_internal().count(type) > 0; + return StaticCellTypes::categories.is_ff(type); } RTLIL::SigChunk::SigChunk(const RTLIL::SigBit &bit) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index fea53081e..18bac5e6a 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -737,8 +737,6 @@ template <> struct IDMacroHelper<-1> { namespace RTLIL { extern dict constpad; - const pool &builtin_ff_cell_types(); - static inline std::string escape_id(const std::string &str) { if (str.size() > 0 && str[0] != '\\' && str[0] != '$') return "\\" + str; diff --git a/passes/cmds/icell_liberty.cc b/passes/cmds/icell_liberty.cc index a928e5d58..1d3628f1f 100644 --- a/passes/cmds/icell_liberty.cc +++ b/passes/cmds/icell_liberty.cc @@ -1,5 +1,6 @@ #include "kernel/yosys.h" #include "kernel/celltypes.h" +#include "kernel/newcelltypes.h" #include "kernel/ff.h" USING_YOSYS_NAMESPACE @@ -123,7 +124,7 @@ struct LibertyStubber { return; } - if (RTLIL::builtin_ff_cell_types().count(base_name)) + if (StaticCellTypes::categories.is_ff(base_name)) return liberty_flop(base, derived, f); auto& base_type = ct.cell_types[base_name]; diff --git a/tests/unit/kernel/cellTypesTest.cc b/tests/unit/kernel/cellTypesTest.cc index aec8b05fc..f2c044df4 100644 --- a/tests/unit/kernel/cellTypesTest.cc +++ b/tests/unit/kernel/cellTypesTest.cc @@ -18,7 +18,6 @@ TEST(CellTypesTest, basic) newer.setup(nullptr); older.setup_type(ID(bleh), {ID::G}, {ID::H, ID::I}, false, true); newer.setup_type(ID(bleh), {ID::G}, {ID::H, ID::I}, false, true); - EXPECT_EQ(older.cell_known(ID(aaaaa)), newer.cell_known(ID(aaaaa))); EXPECT_EQ(older.cell_known(ID($and)), newer.cell_known(ID($and))); auto check_port = [&](auto type, auto port) { @@ -26,6 +25,49 @@ TEST(CellTypesTest, basic) EXPECT_EQ(older.cell_input(type, port), newer.cell_input(type, port)); EXPECT_EQ(older.cell_output(type, port), newer.cell_output(type, port)); }; + + // ground truth + const pool expected_ff_types = { + ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), + ID($adff), ID($adffe), ID($aldff), ID($aldffe), + ID($sdff), ID($sdffe), ID($sdffce), + ID($dlatch), ID($adlatch), ID($dlatchsr), + ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), + ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), + ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_), + ID($_DFFSRE_NNNN_), ID($_DFFSRE_NNNP_), ID($_DFFSRE_NNPN_), ID($_DFFSRE_NNPP_), + ID($_DFFSRE_NPNN_), ID($_DFFSRE_NPNP_), ID($_DFFSRE_NPPN_), ID($_DFFSRE_NPPP_), + ID($_DFFSRE_PNNN_), ID($_DFFSRE_PNNP_), ID($_DFFSRE_PNPN_), ID($_DFFSRE_PNPP_), + ID($_DFFSRE_PPNN_), ID($_DFFSRE_PPNP_), ID($_DFFSRE_PPPN_), ID($_DFFSRE_PPPP_), + ID($_DFF_N_), ID($_DFF_P_), + ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), + ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_), + ID($_DFFE_NN0N_), ID($_DFFE_NN0P_), ID($_DFFE_NN1N_), ID($_DFFE_NN1P_), + ID($_DFFE_NP0N_), ID($_DFFE_NP0P_), ID($_DFFE_NP1N_), ID($_DFFE_NP1P_), + ID($_DFFE_PN0N_), ID($_DFFE_PN0P_), ID($_DFFE_PN1N_), ID($_DFFE_PN1P_), + ID($_DFFE_PP0N_), ID($_DFFE_PP0P_), ID($_DFFE_PP1N_), ID($_DFFE_PP1P_), + ID($_ALDFF_NN_), ID($_ALDFF_NP_), ID($_ALDFF_PN_), ID($_ALDFF_PP_), + ID($_ALDFFE_NNN_), ID($_ALDFFE_NNP_), ID($_ALDFFE_NPN_), ID($_ALDFFE_NPP_), + ID($_ALDFFE_PNN_), ID($_ALDFFE_PNP_), ID($_ALDFFE_PPN_), ID($_ALDFFE_PPP_), + ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_), + ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_), + ID($_SDFFE_NN0N_), ID($_SDFFE_NN0P_), ID($_SDFFE_NN1N_), ID($_SDFFE_NN1P_), + ID($_SDFFE_NP0N_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1N_), ID($_SDFFE_NP1P_), + ID($_SDFFE_PN0N_), ID($_SDFFE_PN0P_), ID($_SDFFE_PN1N_), ID($_SDFFE_PN1P_), + ID($_SDFFE_PP0N_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1N_), ID($_SDFFE_PP1P_), + ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NN1P_), + ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1N_), ID($_SDFFCE_NP1P_), + ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PN1P_), + ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1N_), ID($_SDFFCE_PP1P_), + ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_), + ID($_DLATCH_N_), ID($_DLATCH_P_), + ID($_DLATCH_NN0_), ID($_DLATCH_NN1_), ID($_DLATCH_NP0_), ID($_DLATCH_NP1_), + ID($_DLATCH_PN0_), ID($_DLATCH_PN1_), ID($_DLATCH_PP0_), ID($_DLATCH_PP1_), + ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_), + ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), + ID($_FF_), + }; + for (size_t i = 0; i < static_cast(RTLIL::StaticId::STATIC_ID_END); i++) { IdString type; type.index_ = i; @@ -37,8 +79,7 @@ TEST(CellTypesTest, basic) check_port(type, port); for (auto port : StaticCellTypes::builder.cells.data()->outputs.ports) check_port(type, port); - - EXPECT_EQ(RTLIL::builtin_ff_cell_types().count(type), StaticCellTypes::categories.is_ff(type)); + EXPECT_EQ(expected_ff_types.count(type) > 0, StaticCellTypes::categories.is_ff(type)); } yosys_shutdown(); } From b8ee0803abd9deab49e067f0586fcd97dbef13cb Mon Sep 17 00:00:00 2001 From: nella Date: Sat, 28 Feb 2026 18:39:16 +0100 Subject: [PATCH 31/34] Remove todo. --- tests/pyosys/test_dict.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/pyosys/test_dict.py b/tests/pyosys/test_dict.py index 57d4dc82f..59342391c 100644 --- a/tests/pyosys/test_dict.py +++ b/tests/pyosys/test_dict.py @@ -33,6 +33,3 @@ assert repr_test == {'tomato': 'tomato', 'first': 'second', 'key': 'value', 'im before = len(repr_test) print(repr_test.popitem()) assert before - 1 == len(repr_test) - -# test noncomparable -# TODO newcelltypes? From 04822c66600eef91f5b495233350abd15454348b Mon Sep 17 00:00:00 2001 From: nella Date: Mon, 2 Mar 2026 12:11:25 +0100 Subject: [PATCH 32/34] Readd builtin_ff_cell_types for plugin parity. --- kernel/rtlil.cc | 13 +++++++++++++ kernel/rtlil.h | 3 +++ 2 files changed, 16 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 339450c6a..66bf3b9f7 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -288,6 +288,19 @@ void RTLIL::OwningIdString::collect_garbage() dict RTLIL::constpad; +const pool &RTLIL::builtin_ff_cell_types() { + static const pool res = []() { + pool r; + for (size_t i = 0; i < StaticCellTypes::builder.count; i++) { + auto &cell = StaticCellTypes::builder.cells[i]; + if (cell.features.is_ff) + r.insert(cell.type); + } + return r; + }(); + return res; +} + #define check(condition) log_assert(condition && "malformed Const union") const Const::bitvectype& Const::get_bits() const { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 18bac5e6a..6f26d0d39 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -737,6 +737,9 @@ template <> struct IDMacroHelper<-1> { namespace RTLIL { extern dict constpad; + [[deprecated("use StaticCellTypes::categories.is_ff() instead")]] + const pool &builtin_ff_cell_types(); + static inline std::string escape_id(const std::string &str) { if (str.size() > 0 && str[0] != '\\' && str[0] != '$') return "\\" + str; From 16b1a914f1f131337726440415221e0ed424c228 Mon Sep 17 00:00:00 2001 From: nella Date: Mon, 2 Mar 2026 12:24:41 +0100 Subject: [PATCH 33/34] Aiger use defines for known ops. --- backends/aiger2/aiger.cc | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index 1831fdb03..6f32d05de 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -47,24 +47,16 @@ PRIVATE_NAMESPACE_BEGIN static constexpr auto known_ops = []() constexpr { StaticCellTypes::Categories::Category c{}; - // bitwise - for (auto id : {ID($buf), ID($not), ID($mux), ID($and), ID($or), ID($xor), ID($xnor), ID($fa), ID($bwmux)}) + for (auto id : {BITWISE_OPS}) c.set_id(id); - // reduce - for (auto id : {ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool)}) + for (auto id : {REDUCE_OPS}) c.set_id(id); - // logic - for (auto id : {ID($logic_and), ID($logic_or), ID($logic_not)}) + for (auto id : {LOGIC_OPS}) c.set_id(id); - // gates - for (auto id : {ID($_BUF_), ID($_NOT_), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), - ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($_MUX_), ID($_NMUX_), - ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_)}) + for (auto id : {GATE_OPS}) c.set_id(id); - // compare - for (auto id : {ID($eq), ID($ne), ID($lt), ID($le), ID($ge), ID($gt)}) + for (auto id : {CMP_OPS}) c.set_id(id); - // other for (auto id : {ID($pos), ID($pmux), ID($bmux)}) c.set_id(id); return c; From 6485a13809df455a7a6c658147f8542d6907d7d8 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 4 Mar 2026 15:17:26 +0100 Subject: [PATCH 34/34] newcelltypes: mark header unstable --- kernel/newcelltypes.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index c4a4ea329..bb14293a3 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -6,6 +6,11 @@ YOSYS_NAMESPACE_BEGIN +/** + * This API is unstable. + * It may change or be removed in future versions and break dependent code. + */ + namespace StaticCellTypes { // Given by last internal cell type IdString constids.inc, compilation error if too low