3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-19 05:35:47 +00:00
This commit is contained in:
Emil J. Tywoniak 2026-06-11 20:02:02 +02:00
parent 8e522b08c0
commit afdae7b87e
49 changed files with 1258 additions and 891 deletions

View file

@ -27,7 +27,7 @@ YOSYS_NAMESPACE_BEGIN
struct CellType
{
RTLIL::IdString type;
TwineRef type;
pool<TwineRef> inputs, outputs;
bool is_evaluable;
bool is_combinatorial;
@ -36,7 +36,7 @@ struct CellType
struct CellTypes
{
dict<RTLIL::IdString, CellType> cell_types;
dict<TwineRef, CellType> cell_types;
CellTypes()
{
@ -59,7 +59,7 @@ struct CellTypes
setup_stdcells_mem();
}
void setup_type(RTLIL::IdString type, const pool<TwineRef> &inputs, const pool<TwineRef> &outputs, bool is_evaluable = false, bool is_combinatorial = false, bool is_synthesizable = false)
void setup_type(TwineRef type, const pool<TwineRef> &inputs, const pool<TwineRef> &outputs, bool is_evaluable = false, bool is_combinatorial = false, bool is_synthesizable = false)
{
CellType ct = {type, inputs, outputs, is_evaluable, is_combinatorial, is_synthesizable};
cell_types[ct.type] = ct;
@ -75,7 +75,7 @@ struct CellTypes
if (wire->port_output)
outputs.insert(wire->meta_->name);
}
setup_type(RTLIL::IdString(module->design->twines.str(module->meta_->name)), inputs, outputs);
setup_type(module->meta_->name, inputs, outputs);
}
void setup_design(RTLIL::Design *design)
@ -88,51 +88,51 @@ struct CellTypes
{
setup_internals_eval();
setup_type(ID($tribuf), {TW::A, TW::EN}, {TW::Y});
setup_type(TW($tribuf), {TW::A, TW::EN}, {TW::Y});
setup_type(ID($assert), {TW::A, TW::EN}, pool<TwineRef>());
setup_type(ID($assume), {TW::A, TW::EN}, pool<TwineRef>());
setup_type(ID($live), {TW::A, TW::EN}, pool<TwineRef>());
setup_type(ID($fair), {TW::A, TW::EN}, pool<TwineRef>());
setup_type(ID($cover), {TW::A, TW::EN}, pool<TwineRef>());
setup_type(ID($initstate), pool<TwineRef>(), {TW::Y});
setup_type(ID($anyconst), pool<TwineRef>(), {TW::Y});
setup_type(ID($anyseq), pool<TwineRef>(), {TW::Y});
setup_type(ID($allconst), pool<TwineRef>(), {TW::Y});
setup_type(ID($allseq), pool<TwineRef>(), {TW::Y});
setup_type(ID($equiv), {TW::A, TW::B}, {TW::Y});
setup_type(ID($specify2), {TW::EN, TW::SRC, TW::DST}, pool<TwineRef>());
setup_type(ID($specify3), {TW::EN, TW::SRC, TW::DST, TW::DAT}, pool<TwineRef>());
setup_type(ID($specrule), {TW::SRC_EN, TW::DST_EN, TW::SRC, TW::DST}, pool<TwineRef>());
setup_type(ID($print), {TW::EN, TW::ARGS, TW::TRG}, pool<TwineRef>());
setup_type(ID($check), {TW::A, TW::EN, TW::ARGS, TW::TRG}, pool<TwineRef>());
setup_type(ID($set_tag), {TW::A, TW::SET, TW::CLR}, {TW::Y});
setup_type(ID($get_tag), {TW::A}, {TW::Y});
setup_type(ID($overwrite_tag), {TW::A, TW::SET, TW::CLR}, pool<TwineRef>());
setup_type(ID($original_tag), {TW::A}, {TW::Y});
setup_type(ID($future_ff), {TW::A}, {TW::Y});
setup_type(ID($scopeinfo), {}, {});
setup_type(ID($input_port), {}, {TW::Y});
setup_type(ID($output_port), {TW::A}, {});
setup_type(ID($public), {TW::A}, {});
setup_type(ID($connect), {TW::A, TW::B}, {});
setup_type(TW($assert), {TW::A, TW::EN}, pool<TwineRef>());
setup_type(TW($assume), {TW::A, TW::EN}, pool<TwineRef>());
setup_type(TW($live), {TW::A, TW::EN}, pool<TwineRef>());
setup_type(TW($fair), {TW::A, TW::EN}, pool<TwineRef>());
setup_type(TW($cover), {TW::A, TW::EN}, pool<TwineRef>());
setup_type(TW($initstate), pool<TwineRef>(), {TW::Y});
setup_type(TW($anyconst), pool<TwineRef>(), {TW::Y});
setup_type(TW($anyseq), pool<TwineRef>(), {TW::Y});
setup_type(TW($allconst), pool<TwineRef>(), {TW::Y});
setup_type(TW($allseq), pool<TwineRef>(), {TW::Y});
setup_type(TW($equiv), {TW::A, TW::B}, {TW::Y});
setup_type(TW($specify2), {TW::EN, TW::SRC, TW::DST}, pool<TwineRef>());
setup_type(TW($specify3), {TW::EN, TW::SRC, TW::DST, TW::DAT}, pool<TwineRef>());
setup_type(TW($specrule), {TW::SRC_EN, TW::DST_EN, TW::SRC, TW::DST}, pool<TwineRef>());
setup_type(TW($print), {TW::EN, TW::ARGS, TW::TRG}, pool<TwineRef>());
setup_type(TW($check), {TW::A, TW::EN, TW::ARGS, TW::TRG}, pool<TwineRef>());
setup_type(TW($set_tag), {TW::A, TW::SET, TW::CLR}, {TW::Y});
setup_type(TW($get_tag), {TW::A}, {TW::Y});
setup_type(TW($overwrite_tag), {TW::A, TW::SET, TW::CLR}, pool<TwineRef>());
setup_type(TW($original_tag), {TW::A}, {TW::Y});
setup_type(TW($future_ff), {TW::A}, {TW::Y});
setup_type(TW($scopeinfo), {}, {});
setup_type(TW($input_port), {}, {TW::Y});
setup_type(TW($output_port), {TW::A}, {});
setup_type(TW($public), {TW::A}, {});
setup_type(TW($connect), {TW::A, TW::B}, {});
}
void setup_internals_eval()
{
std::vector<RTLIL::IdString> 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::vector<TwineRef> unary_ops = {
TW($not), TW($pos), TW($buf), TW($neg),
TW($reduce_and), TW($reduce_or), TW($reduce_xor), TW($reduce_xnor), TW($reduce_bool),
TW($logic_not), TW($slice), TW($lut), TW($sop)
};
std::vector<RTLIL::IdString> 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)
std::vector<TwineRef> binary_ops = {
TW($and), TW($or), TW($xor), TW($xnor),
TW($shl), TW($shr), TW($sshl), TW($sshr), TW($shift), TW($shiftx),
TW($lt), TW($le), TW($eq), TW($ne), TW($eqx), TW($nex), TW($ge), TW($gt),
TW($add), TW($sub), TW($mul), TW($div), TW($mod), TW($divfloor), TW($modfloor), TW($pow),
TW($logic_and), TW($logic_or), TW($concat), TW($macc),
TW($bweqx)
};
for (auto type : unary_ops)
@ -141,87 +141,87 @@ struct CellTypes
for (auto type : binary_ops)
setup_type(type, {TW::A, TW::B}, {TW::Y}, true);
for (auto type : std::vector<RTLIL::IdString>({ID($mux), ID($pmux), ID($bwmux)}))
for (auto type : std::vector<TwineRef>({TW($mux), TW($pmux), TW($bwmux)}))
setup_type(type, {TW::A, TW::B, TW::S}, {TW::Y}, true);
for (auto type : std::vector<RTLIL::IdString>({ID($bmux), ID($demux)}))
for (auto type : std::vector<TwineRef>({TW($bmux), TW($demux)}))
setup_type(type, {TW::A, TW::S}, {TW::Y}, true);
setup_type(ID($lcu), {TW::P, TW::G, TW::CI}, {TW::CO}, true);
setup_type(ID($alu), {TW::A, TW::B, TW::CI, TW::BI}, {TW::X, TW::Y, TW::CO}, true);
setup_type(ID($macc_v2), {TW::A, TW::B, TW::C}, {TW::Y}, true);
setup_type(ID($fa), {TW::A, TW::B, TW::C}, {TW::X, TW::Y}, true);
setup_type(TW($lcu), {TW::P, TW::G, TW::CI}, {TW::CO}, true);
setup_type(TW($alu), {TW::A, TW::B, TW::CI, TW::BI}, {TW::X, TW::Y, TW::CO}, true);
setup_type(TW($macc_v2), {TW::A, TW::B, TW::C}, {TW::Y}, true);
setup_type(TW($fa), {TW::A, TW::B, TW::C}, {TW::X, TW::Y}, true);
}
void setup_internals_ff()
{
setup_type(ID($sr), {TW::SET, TW::CLR}, {TW::Q});
setup_type(ID($ff), {TW::D}, {TW::Q});
setup_type(ID($dff), {TW::CLK, TW::D}, {TW::Q});
setup_type(ID($dffe), {TW::CLK, TW::EN, TW::D}, {TW::Q});
setup_type(ID($dffsr), {TW::CLK, TW::SET, TW::CLR, TW::D}, {TW::Q});
setup_type(ID($dffsre), {TW::CLK, TW::SET, TW::CLR, TW::D, TW::EN}, {TW::Q});
setup_type(ID($adff), {TW::CLK, TW::ARST, TW::D}, {TW::Q});
setup_type(ID($adffe), {TW::CLK, TW::ARST, TW::D, TW::EN}, {TW::Q});
setup_type(ID($aldff), {TW::CLK, TW::ALOAD, TW::AD, TW::D}, {TW::Q});
setup_type(ID($aldffe), {TW::CLK, TW::ALOAD, TW::AD, TW::D, TW::EN}, {TW::Q});
setup_type(ID($sdff), {TW::CLK, TW::SRST, TW::D}, {TW::Q});
setup_type(ID($sdffe), {TW::CLK, TW::SRST, TW::D, TW::EN}, {TW::Q});
setup_type(ID($sdffce), {TW::CLK, TW::SRST, TW::D, TW::EN}, {TW::Q});
setup_type(ID($dlatch), {TW::EN, TW::D}, {TW::Q});
setup_type(ID($adlatch), {TW::EN, TW::D, TW::ARST}, {TW::Q});
setup_type(ID($dlatchsr), {TW::EN, TW::SET, TW::CLR, TW::D}, {TW::Q});
setup_type(TW($sr), {TW::SET, TW::CLR}, {TW::Q});
setup_type(TW($ff), {TW::D}, {TW::Q});
setup_type(TW($dff), {TW::CLK, TW::D}, {TW::Q});
setup_type(TW($dffe), {TW::CLK, TW::EN, TW::D}, {TW::Q});
setup_type(TW($dffsr), {TW::CLK, TW::SET, TW::CLR, TW::D}, {TW::Q});
setup_type(TW($dffsre), {TW::CLK, TW::SET, TW::CLR, TW::D, TW::EN}, {TW::Q});
setup_type(TW($adff), {TW::CLK, TW::ARST, TW::D}, {TW::Q});
setup_type(TW($adffe), {TW::CLK, TW::ARST, TW::D, TW::EN}, {TW::Q});
setup_type(TW($aldff), {TW::CLK, TW::ALOAD, TW::AD, TW::D}, {TW::Q});
setup_type(TW($aldffe), {TW::CLK, TW::ALOAD, TW::AD, TW::D, TW::EN}, {TW::Q});
setup_type(TW($sdff), {TW::CLK, TW::SRST, TW::D}, {TW::Q});
setup_type(TW($sdffe), {TW::CLK, TW::SRST, TW::D, TW::EN}, {TW::Q});
setup_type(TW($sdffce), {TW::CLK, TW::SRST, TW::D, TW::EN}, {TW::Q});
setup_type(TW($dlatch), {TW::EN, TW::D}, {TW::Q});
setup_type(TW($adlatch), {TW::EN, TW::D, TW::ARST}, {TW::Q});
setup_type(TW($dlatchsr), {TW::EN, TW::SET, TW::CLR, TW::D}, {TW::Q});
}
void setup_internals_anyinit()
{
setup_type(ID($anyinit), {TW::D}, {TW::Q});
setup_type(TW($anyinit), {TW::D}, {TW::Q});
}
void setup_internals_mem()
{
setup_internals_ff();
setup_type(ID($memrd), {TW::CLK, TW::EN, TW::ADDR}, {TW::DATA});
setup_type(ID($memrd_v2), {TW::CLK, TW::EN, TW::ARST, TW::SRST, TW::ADDR}, {TW::DATA});
setup_type(ID($memwr), {TW::CLK, TW::EN, TW::ADDR, TW::DATA}, pool<TwineRef>());
setup_type(ID($memwr_v2), {TW::CLK, TW::EN, TW::ADDR, TW::DATA}, pool<TwineRef>());
setup_type(ID($meminit), {TW::ADDR, TW::DATA}, pool<TwineRef>());
setup_type(ID($meminit_v2), {TW::ADDR, TW::DATA, TW::EN}, pool<TwineRef>());
setup_type(ID($mem), {TW::RD_CLK, TW::RD_EN, TW::RD_ADDR, TW::WR_CLK, TW::WR_EN, TW::WR_ADDR, TW::WR_DATA}, {TW::RD_DATA});
setup_type(ID($mem_v2), {TW::RD_CLK, TW::RD_EN, TW::RD_ARST, TW::RD_SRST, TW::RD_ADDR, TW::WR_CLK, TW::WR_EN, TW::WR_ADDR, TW::WR_DATA}, {TW::RD_DATA});
setup_type(TW($memrd), {TW::CLK, TW::EN, TW::ADDR}, {TW::DATA});
setup_type(TW($memrd_v2), {TW::CLK, TW::EN, TW::ARST, TW::SRST, TW::ADDR}, {TW::DATA});
setup_type(TW($memwr), {TW::CLK, TW::EN, TW::ADDR, TW::DATA}, pool<TwineRef>());
setup_type(TW($memwr_v2), {TW::CLK, TW::EN, TW::ADDR, TW::DATA}, pool<TwineRef>());
setup_type(TW($meminit), {TW::ADDR, TW::DATA}, pool<TwineRef>());
setup_type(TW($meminit_v2), {TW::ADDR, TW::DATA, TW::EN}, pool<TwineRef>());
setup_type(TW($mem), {TW::RD_CLK, TW::RD_EN, TW::RD_ADDR, TW::WR_CLK, TW::WR_EN, TW::WR_ADDR, TW::WR_DATA}, {TW::RD_DATA});
setup_type(TW($mem_v2), {TW::RD_CLK, TW::RD_EN, TW::RD_ARST, TW::RD_SRST, TW::RD_ADDR, TW::WR_CLK, TW::WR_EN, TW::WR_ADDR, TW::WR_DATA}, {TW::RD_DATA});
setup_type(ID($fsm), {TW::CLK, TW::ARST, TW::CTRL_IN}, {TW::CTRL_OUT});
setup_type(TW($fsm), {TW::CLK, TW::ARST, TW::CTRL_IN}, {TW::CTRL_OUT});
}
void setup_stdcells()
{
setup_stdcells_eval();
setup_type(ID($_TBUF_), {TW::A, TW::E}, {TW::Y});
setup_type(TW($_TBUF_), {TW::A, TW::E}, {TW::Y});
}
void setup_stdcells_eval()
{
setup_type(ID($_BUF_), {TW::A}, {TW::Y}, true);
setup_type(ID($_NOT_), {TW::A}, {TW::Y}, true);
setup_type(ID($_AND_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(ID($_NAND_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(ID($_OR_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(ID($_NOR_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(ID($_XOR_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(ID($_XNOR_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(ID($_ANDNOT_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(ID($_ORNOT_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(ID($_MUX_), {TW::A, TW::B, TW::S}, {TW::Y}, true);
setup_type(ID($_NMUX_), {TW::A, TW::B, TW::S}, {TW::Y}, true);
setup_type(ID($_MUX4_), {TW::A, TW::B, TW::C, TW::D, TW::S, TW::T}, {TW::Y}, true);
setup_type(ID($_MUX8_), {TW::A, TW::B, TW::C, TW::D, TW::E, TW::F, TW::G, TW::H, TW::S, TW::T, TW::U}, {TW::Y}, true);
setup_type(ID($_MUX16_), {TW::A, TW::B, TW::C, TW::D, TW::E, TW::F, TW::G, TW::H, TW::I, TW::J, TW::K, TW::L, TW::M, TW::N, TW::O, TW::P, TW::S, TW::T, TW::U, TW::V}, {TW::Y}, true);
setup_type(ID($_AOI3_), {TW::A, TW::B, TW::C}, {TW::Y}, true);
setup_type(ID($_OAI3_), {TW::A, TW::B, TW::C}, {TW::Y}, true);
setup_type(ID($_AOI4_), {TW::A, TW::B, TW::C, TW::D}, {TW::Y}, true);
setup_type(ID($_OAI4_), {TW::A, TW::B, TW::C, TW::D}, {TW::Y}, true);
setup_type(TW($_BUF_), {TW::A}, {TW::Y}, true);
setup_type(TW($_NOT_), {TW::A}, {TW::Y}, true);
setup_type(TW($_AND_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(TW($_NAND_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(TW($_OR_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(TW($_NOR_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(TW($_XOR_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(TW($_XNOR_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(TW($_ANDNOT_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(TW($_ORNOT_), {TW::A, TW::B}, {TW::Y}, true);
setup_type(TW($_MUX_), {TW::A, TW::B, TW::S}, {TW::Y}, true);
setup_type(TW($_NMUX_), {TW::A, TW::B, TW::S}, {TW::Y}, true);
setup_type(TW($_MUX4_), {TW::A, TW::B, TW::C, TW::D, TW::S, TW::T}, {TW::Y}, true);
setup_type(TW($_MUX8_), {TW::A, TW::B, TW::C, TW::D, TW::E, TW::F, TW::G, TW::H, TW::S, TW::T, TW::U}, {TW::Y}, true);
setup_type(TW($_MUX16_), {TW::A, TW::B, TW::C, TW::D, TW::E, TW::F, TW::G, TW::H, TW::I, TW::J, TW::K, TW::L, TW::M, TW::N, TW::O, TW::P, TW::S, TW::T, TW::U, TW::V}, {TW::Y}, true);
setup_type(TW($_AOI3_), {TW::A, TW::B, TW::C}, {TW::Y}, true);
setup_type(TW($_OAI3_), {TW::A, TW::B, TW::C}, {TW::Y}, true);
setup_type(TW($_AOI4_), {TW::A, TW::B, TW::C, TW::D}, {TW::Y}, true);
setup_type(TW($_OAI4_), {TW::A, TW::B, TW::C, TW::D}, {TW::Y}, true);
}
void setup_stdcells_mem()
@ -230,77 +230,77 @@ struct CellTypes
for (auto c1 : list_np)
for (auto c2 : list_np)
setup_type(stringf("$_SR_%c%c_", c1, c2), {TW::S, TW::R}, {TW::Q});
setup_type(TW($1), {TW::S, TW::R}, {TW::Q});
setup_type(ID($_FF_), {TW::D}, {TW::Q});
setup_type(TW($_FF_), {TW::D}, {TW::Q});
for (auto c1 : list_np)
setup_type(stringf("$_DFF_%c_", c1), {TW::C, TW::D}, {TW::Q});
setup_type(TW($1), {TW::C, TW::D}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
setup_type(stringf("$_DFFE_%c%c_", c1, c2), {TW::C, TW::D, TW::E}, {TW::Q});
setup_type(TW($1), {TW::C, TW::D, TW::E}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
for (auto c3 : list_01)
setup_type(stringf("$_DFF_%c%c%c_", c1, c2, c3), {TW::C, TW::R, TW::D}, {TW::Q});
setup_type(TW($1), {TW::C, TW::R, TW::D}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
for (auto c3 : list_01)
for (auto c4 : list_np)
setup_type(stringf("$_DFFE_%c%c%c%c_", c1, c2, c3, c4), {TW::C, TW::R, TW::D, TW::E}, {TW::Q});
setup_type(TW($1), {TW::C, TW::R, TW::D, TW::E}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
setup_type(stringf("$_ALDFF_%c%c_", c1, c2), {TW::C, TW::L, TW::AD, TW::D}, {TW::Q});
setup_type(TW($1), {TW::C, TW::L, TW::AD, TW::D}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
for (auto c3 : list_np)
setup_type(stringf("$_ALDFFE_%c%c%c_", c1, c2, c3), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q});
setup_type(TW($1), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
for (auto c3 : list_np)
setup_type(stringf("$_DFFSR_%c%c%c_", c1, c2, c3), {TW::C, TW::S, TW::R, TW::D}, {TW::Q});
setup_type(TW($1), {TW::C, TW::S, TW::R, TW::D}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
for (auto c3 : list_np)
for (auto c4 : list_np)
setup_type(stringf("$_DFFSRE_%c%c%c%c_", c1, c2, c3, c4), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q});
setup_type(TW($1), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
for (auto c3 : list_01)
setup_type(stringf("$_SDFF_%c%c%c_", c1, c2, c3), {TW::C, TW::R, TW::D}, {TW::Q});
setup_type(TW($1), {TW::C, TW::R, TW::D}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
for (auto c3 : list_01)
for (auto c4 : list_np)
setup_type(stringf("$_SDFFE_%c%c%c%c_", c1, c2, c3, c4), {TW::C, TW::R, TW::D, TW::E}, {TW::Q});
setup_type(TW($1), {TW::C, TW::R, TW::D, TW::E}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
for (auto c3 : list_01)
for (auto c4 : list_np)
setup_type(stringf("$_SDFFCE_%c%c%c%c_", c1, c2, c3, c4), {TW::C, TW::R, TW::D, TW::E}, {TW::Q});
setup_type(TW($1), {TW::C, TW::R, TW::D, TW::E}, {TW::Q});
for (auto c1 : list_np)
setup_type(stringf("$_DLATCH_%c_", c1), {TW::E, TW::D}, {TW::Q});
setup_type(TW($1), {TW::E, TW::D}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
for (auto c3 : list_01)
setup_type(stringf("$_DLATCH_%c%c%c_", c1, c2, c3), {TW::E, TW::R, TW::D}, {TW::Q});
setup_type(TW($1), {TW::E, TW::R, TW::D}, {TW::Q});
for (auto c1 : list_np)
for (auto c2 : list_np)
for (auto c3 : list_np)
setup_type(stringf("$_DLATCHSR_%c%c%c_", c1, c2, c3), {TW::E, TW::S, TW::R, TW::D}, {TW::Q});
setup_type(TW($1), {TW::E, TW::S, TW::R, TW::D}, {TW::Q});
}
void clear()
@ -308,24 +308,24 @@ struct CellTypes
cell_types.clear();
}
bool cell_known(RTLIL::IdString type) const
bool cell_known(TwineRef type) const
{
return cell_types.count(type) != 0;
}
bool cell_output(RTLIL::IdString type, TwineRef port) const
bool cell_output(TwineRef type, TwineRef port) const
{
auto it = cell_types.find(type);
return it != cell_types.end() && it->second.outputs.count(port) != 0;
}
bool cell_input(RTLIL::IdString type, TwineRef port) const
bool cell_input(TwineRef type, TwineRef port) const
{
auto it = cell_types.find(type);
return it != cell_types.end() && it->second.inputs.count(port) != 0;
}
RTLIL::PortDir cell_port_dir(RTLIL::IdString type, TwineRef port) const
RTLIL::PortDir cell_port_dir(TwineRef type, TwineRef port) const
{
auto it = cell_types.find(type);
if (it == cell_types.end())
@ -335,7 +335,7 @@ struct CellTypes
return RTLIL::PortDir(is_input + is_output * 2);
}
bool cell_evaluable(RTLIL::IdString type) const
bool cell_evaluable(TwineRef type) const
{
auto it = cell_types.find(type);
return it != cell_types.end() && it->second.is_evaluable;
@ -350,20 +350,20 @@ struct CellTypes
}
// Consider using the ConstEval struct instead if you need named ports and/or multiple outputs
static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len, bool *errp = nullptr)
static RTLIL::Const eval(TwineRef type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len, bool *errp = nullptr)
{
if (type == ID($sshr) && !signed1)
type = ID($shr);
if (type == ID($sshl) && !signed1)
type = ID($shl);
if (type == TW($sshr) && !signed1)
type = TW($shr);
if (type == TW($sshl) && !signed1)
type = TW($shl);
if (type != ID($sshr) && type != ID($sshl) && type != ID($shr) && type != ID($shl) && type != ID($shift) && type != ID($shiftx) &&
type != ID($pos) && type != ID($buf) && type != ID($neg) && type != ID($not)) {
if (type != TW($sshr) && type != TW($sshl) && type != TW($shr) && type != TW($shl) && type != TW($shift) && type != TW($shiftx) &&
type != TW($pos) && type != TW($buf) && type != TW($neg) && type != TW($not)) {
if (!signed1 || !signed2)
signed1 = false, signed2 = false;
}
#define HANDLE_CELL_TYPE(_t) if (type == ID($##_t)) return const_ ## _t(arg1, arg2, signed1, signed2, result_len);
#define HANDLE_CELL_TYPE(_t) if (type == TW($##_t)) return const_ ## _t(arg1, arg2, signed1, signed2, result_len);
HANDLE_CELL_TYPE(not)
HANDLE_CELL_TYPE(and)
HANDLE_CELL_TYPE(or)
@ -403,25 +403,25 @@ struct CellTypes
HANDLE_CELL_TYPE(neg)
#undef HANDLE_CELL_TYPE
if (type.in(ID($_BUF_), ID($buf)))
if (type.in(TW($_BUF_), TW($buf)))
return arg1;
if (type == ID($_NOT_))
if (type == TW($_NOT_))
return eval_not(arg1);
if (type == ID($_AND_))
if (type == TW($_AND_))
return const_and(arg1, arg2, false, false, 1);
if (type == ID($_NAND_))
if (type == TW($_NAND_))
return eval_not(const_and(arg1, arg2, false, false, 1));
if (type == ID($_OR_))
if (type == TW($_OR_))
return const_or(arg1, arg2, false, false, 1);
if (type == ID($_NOR_))
if (type == TW($_NOR_))
return eval_not(const_or(arg1, arg2, false, false, 1));
if (type == ID($_XOR_))
if (type == TW($_XOR_))
return const_xor(arg1, arg2, false, false, 1);
if (type == ID($_XNOR_))
if (type == TW($_XNOR_))
return const_xnor(arg1, arg2, false, false, 1);
if (type == ID($_ANDNOT_))
if (type == TW($_ANDNOT_))
return const_and(arg1, eval_not(arg2), false, false, 1);
if (type == ID($_ORNOT_))
if (type == TW($_ORNOT_))
return const_or(arg1, eval_not(arg2), false, false, 1);
if (errp != nullptr) {
@ -435,34 +435,34 @@ struct CellTypes
// Consider using the ConstEval struct instead if you need named ports and/or multiple outputs
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool *errp = nullptr)
{
if (cell->type == ID($slice)) {
if (cell->type == TW($slice)) {
int width = cell->parameters.at(ID::Y_WIDTH).as_int();
int offset = cell->parameters.at(ID::OFFSET).as_int();
return arg1.extract(offset, width);
}
if (cell->type == ID($concat)) {
if (cell->type == TW($concat)) {
RTLIL::Const ret = arg1;
ret.append(arg2);
return ret;
}
if (cell->type == ID($bmux))
if (cell->type == TW($bmux))
{
return const_bmux(arg1, arg2);
}
if (cell->type == ID($demux))
if (cell->type == TW($demux))
{
return const_demux(arg1, arg2);
}
if (cell->type == ID($bweqx))
if (cell->type == TW($bweqx))
{
return const_bweqx(arg1, arg2);
}
if (cell->type == ID($lut))
if (cell->type == TW($lut))
{
int width = cell->parameters.at(ID::WIDTH).as_int();
@ -474,7 +474,7 @@ struct CellTypes
return const_bmux(t, arg1);
}
if (cell->type == ID($sop))
if (cell->type == TW($sop))
{
int width = cell->parameters.at(ID::WIDTH).as_int();
int depth = cell->parameters.at(ID::DEPTH).as_int();
@ -515,23 +515,23 @@ struct CellTypes
bool signed_a = cell->parameters.count(ID::A_SIGNED) > 0 && cell->parameters[ID::A_SIGNED].as_bool();
bool signed_b = cell->parameters.count(ID::B_SIGNED) > 0 && cell->parameters[ID::B_SIGNED].as_bool();
int result_len = cell->parameters.count(ID::Y_WIDTH) > 0 ? cell->parameters[ID::Y_WIDTH].as_int() : -1;
return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len, errp);
return eval(cell->type_impl, arg1, arg2, signed_a, signed_b, result_len, errp);
}
// Consider using the ConstEval struct instead if you need named ports and/or multiple outputs
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr)
{
if (cell->type.in(ID($mux), ID($_MUX_)))
if (cell->type.in(TW($mux), TW($_MUX_)))
return const_mux(arg1, arg2, arg3);
if (cell->type == ID($_NMUX_))
if (cell->type == TW($_NMUX_))
return eval_not(const_mux(arg1, arg2, arg3));
if (cell->type == ID($bwmux))
if (cell->type == TW($bwmux))
return const_bwmux(arg1, arg2, arg3);
if (cell->type == ID($pmux))
if (cell->type == TW($pmux))
return const_pmux(arg1, arg2, arg3);
if (cell->type == ID($_AOI3_))
if (cell->type == TW($_AOI3_))
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1));
if (cell->type == ID($_OAI3_))
if (cell->type == TW($_OAI3_))
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1));
log_assert(arg3.size() == 0);
@ -541,9 +541,9 @@ struct CellTypes
// Consider using the ConstEval struct instead if you need named ports and/or multiple outputs
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4, bool *errp = nullptr)
{
if (cell->type == ID($_AOI4_))
if (cell->type == TW($_AOI4_))
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
if (cell->type == ID($_OAI4_))
if (cell->type == TW($_OAI4_))
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_or(arg3, arg4, false, false, 1), false, false, 1));
log_assert(arg4.size() == 0);

View file

@ -18,7 +18,7 @@ unsigned int CellCosts::get(RTLIL::Module *mod)
return module_cost;
}
static unsigned int y_coef(RTLIL::IdString type)
static unsigned int y_coef(TwineRef type)
{
if (
// equality
@ -46,7 +46,7 @@ static unsigned int y_coef(RTLIL::IdString type)
return 0;
}
static unsigned int max_inp_coef(RTLIL::IdString type)
static unsigned int max_inp_coef(TwineRef type)
{
if (
// binop reduce
@ -69,7 +69,7 @@ static unsigned int max_inp_coef(RTLIL::IdString type)
return 0;
}
static unsigned int sum_coef(RTLIL::IdString type)
static unsigned int sum_coef(TwineRef type)
{
if (type.in(ID($shr), ID($sshr))) {
// right shift
@ -81,12 +81,12 @@ static unsigned int sum_coef(RTLIL::IdString type)
return 0;
}
static unsigned int is_div_mod(RTLIL::IdString type)
static unsigned int is_div_mod(TwineRef type)
{
return (type == ID($div) || type == ID($divfloor) || type == ID($mod) || type == ID($modfloor));
}
static bool is_free(RTLIL::IdString type)
static bool is_free(TwineRef type)
{
return (
// tags

View file

@ -877,7 +877,7 @@ std::string log_signal(DriveChunkWire const &chunk)
std::string log_signal(DriveChunkPort const &chunk)
{
std::string cell_id = chunk.cell->module->design->twines.str(cell->meta_->name);
std::string cell_id = chunk.cell->module->design->twines.str(chunk.cell->meta_->name);
std::string port_id = chunk.cell->module->design->twines.str(chunk.port);
if (chunk.is_whole())
return stringf("%s <%s>", cell_id, port_id);

View file

@ -661,7 +661,7 @@ Cell *FfData::emit() {
log_assert(!has_srst);
log_assert(!has_sr);
if (is_anyinit) {
cell = module->addAnyinit(name, sig_d, sig_q);
cell = module->addAnyinit(Twine{name.str()}, sig_d, sig_q);
log_assert(val_init.is_fully_undef());
} else {
cell = module->addFf(Twine{name.str()}, sig_d, sig_q);

View file

@ -198,7 +198,7 @@ struct Macc
void to_cell(RTLIL::Cell *cell)
{
cell->type = ID($macc_v2);
cell->type_impl = TW::$macc_v2;
int nproducts = 0, naddends = 0;
Const a_signed, b_signed, a_widths, b_widths, product_negated;

View file

@ -125,7 +125,7 @@ void Mem::emit() {
memid = NEW_ID;
cell = module->addCell(Twine{memid.str()}, ID($mem_v2));
}
cell->type = ID($mem_v2);
cell->type_impl = TW::$mem_v2;
cell->attributes = attributes;
cell->parameters[ID::MEMID] = Const(memid.str());
cell->parameters[ID::WIDTH] = Const(width);
@ -301,7 +301,7 @@ void Mem::emit() {
for (auto &port : rd_ports) {
if (!port.cell)
port.cell = module->addCell(NEW_TWINE, ID($memrd_v2));
port.cell->type = ID($memrd_v2);
port.cell->type_impl = TW::$memrd_v2;
port.cell->attributes = port.attributes;
port.cell->parameters[ID::MEMID] = memid.str();
port.cell->parameters[ID::ABITS] = GetSize(port.addr);
@ -326,7 +326,7 @@ void Mem::emit() {
for (auto &port : wr_ports) {
if (!port.cell)
port.cell = module->addCell(NEW_TWINE, ID($memwr_v2));
port.cell->type = ID($memwr_v2);
port.cell->type_impl = TW::$memwr_v2;
port.cell->attributes = port.attributes;
if (port.cell->parameters.count(ID::PRIORITY))
port.cell->parameters.erase(ID::PRIORITY);
@ -350,7 +350,7 @@ void Mem::emit() {
else {
if (!v2)
init.cell->unsetPort(TW::EN);
init.cell->type = v2 ? ID($meminit_v2) : ID($meminit);
init.cell->type_impl = v2 ? TW::$meminit_v2 : TW::$meminit;
}
init.cell->attributes = init.attributes;
init.cell->parameters[ID::MEMID] = memid.str();

View file

@ -50,67 +50,67 @@ struct CellTableBuilder {
bool is_tristate = false;
};
struct CellInfo {
RTLIL::IdString type;
TwineRef type;
PortList inputs, outputs;
Features features;
};
std::array<CellInfo, MAX_CELLS> cells{};
size_t count = 0;
constexpr void setup_type(RTLIL::IdString type, std::initializer_list<TwineRef> inputs, std::initializer_list<TwineRef> outputs, const Features& features) {
constexpr void setup_type(TwineRef type, std::initializer_list<TwineRef> inputs, std::initializer_list<TwineRef> outputs, const Features& features) {
cells[count++] = {type, PortList(inputs), PortList(outputs), features};
}
constexpr void setup_internals_other()
{
Features features {};
features.is_tristate = true;
setup_type(ID($tribuf), {TW::A, TW::EN}, {TW::Y}, features);
setup_type(TW($tribuf), {TW::A, TW::EN}, {TW::Y}, features);
features = {};
setup_type(ID($assert), {TW::A, TW::EN}, {}, features);
setup_type(ID($assume), {TW::A, TW::EN}, {}, features);
setup_type(ID($live), {TW::A, TW::EN}, {}, features);
setup_type(ID($fair), {TW::A, TW::EN}, {}, features);
setup_type(ID($cover), {TW::A, TW::EN}, {}, features);
setup_type(ID($initstate), {}, {TW::Y}, features);
setup_type(ID($anyconst), {}, {TW::Y}, features);
setup_type(ID($anyseq), {}, {TW::Y}, features);
setup_type(ID($allconst), {}, {TW::Y}, features);
setup_type(ID($allseq), {}, {TW::Y}, features);
setup_type(ID($equiv), {TW::A, TW::B}, {TW::Y}, features);
setup_type(ID($specify2), {TW::EN, TW::SRC, TW::DST}, {}, features);
setup_type(ID($specify3), {TW::EN, TW::SRC, TW::DST, TW::DAT}, {}, features);
setup_type(ID($specrule), {TW::SRC_EN, TW::DST_EN, TW::SRC, TW::DST}, {}, features);
setup_type(ID($print), {TW::EN, TW::ARGS, TW::TRG}, {}, features);
setup_type(ID($check), {TW::A, TW::EN, TW::ARGS, TW::TRG}, {}, features);
setup_type(ID($set_tag), {TW::A, TW::SET, TW::CLR}, {TW::Y}, features);
setup_type(ID($get_tag), {TW::A}, {TW::Y}, features);
setup_type(ID($overwrite_tag), {TW::A, TW::SET, TW::CLR}, {}, features);
setup_type(ID($original_tag), {TW::A}, {TW::Y}, features);
setup_type(ID($future_ff), {TW::A}, {TW::Y}, features);
setup_type(ID($scopeinfo), {}, {}, features);
setup_type(ID($input_port), {}, {TW::Y}, features);
setup_type(ID($output_port), {TW::A}, {}, features);
setup_type(ID($public), {TW::A}, {}, features);
setup_type(ID($connect), {TW::A, TW::B}, {}, features);
setup_type(TW($assert), {TW::A, TW::EN}, {}, features);
setup_type(TW($assume), {TW::A, TW::EN}, {}, features);
setup_type(TW($live), {TW::A, TW::EN}, {}, features);
setup_type(TW($fair), {TW::A, TW::EN}, {}, features);
setup_type(TW($cover), {TW::A, TW::EN}, {}, features);
setup_type(TW($initstate), {}, {TW::Y}, features);
setup_type(TW($anyconst), {}, {TW::Y}, features);
setup_type(TW($anyseq), {}, {TW::Y}, features);
setup_type(TW($allconst), {}, {TW::Y}, features);
setup_type(TW($allseq), {}, {TW::Y}, features);
setup_type(TW($equiv), {TW::A, TW::B}, {TW::Y}, features);
setup_type(TW($specify2), {TW::EN, TW::SRC, TW::DST}, {}, features);
setup_type(TW($specify3), {TW::EN, TW::SRC, TW::DST, TW::DAT}, {}, features);
setup_type(TW($specrule), {TW::SRC_EN, TW::DST_EN, TW::SRC, TW::DST}, {}, features);
setup_type(TW($print), {TW::EN, TW::ARGS, TW::TRG}, {}, features);
setup_type(TW($check), {TW::A, TW::EN, TW::ARGS, TW::TRG}, {}, features);
setup_type(TW($set_tag), {TW::A, TW::SET, TW::CLR}, {TW::Y}, features);
setup_type(TW($get_tag), {TW::A}, {TW::Y}, features);
setup_type(TW($overwrite_tag), {TW::A, TW::SET, TW::CLR}, {}, features);
setup_type(TW($original_tag), {TW::A}, {TW::Y}, features);
setup_type(TW($future_ff), {TW::A}, {TW::Y}, features);
setup_type(TW($scopeinfo), {}, {}, features);
setup_type(TW($input_port), {}, {TW::Y}, features);
setup_type(TW($output_port), {TW::A}, {}, features);
setup_type(TW($public), {TW::A}, {}, features);
setup_type(TW($connect), {TW::A, TW::B}, {}, features);
}
constexpr void setup_internals_eval()
{
Features features {};
features.is_evaluable = true;
std::initializer_list<RTLIL::IdString> 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<TwineRef> unary_ops = {
TW($not), TW($pos), TW($buf), TW($neg),
TW($reduce_and), TW($reduce_or), TW($reduce_xor), TW($reduce_xnor), TW($reduce_bool),
TW($logic_not), TW($slice), TW($lut), TW($sop)
};
std::initializer_list<RTLIL::IdString> 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)
std::initializer_list<TwineRef> binary_ops = {
TW($and), TW($or), TW($xor), TW($xnor),
TW($shl), TW($shr), TW($sshl), TW($sshr), TW($shift), TW($shiftx),
TW($lt), TW($le), TW($eq), TW($ne), TW($eqx), TW($nex), TW($ge), TW($gt),
TW($add), TW($sub), TW($mul), TW($div), TW($mod), TW($divfloor), TW($modfloor), TW($pow),
TW($logic_and), TW($logic_or), TW($concat), TW($macc),
TW($bweqx)
};
for (auto type : unary_ops)
@ -119,43 +119,43 @@ struct CellTableBuilder {
for (auto type : binary_ops)
setup_type(type, {TW::A, TW::B}, {TW::Y}, features);
for (auto type : {ID($mux), ID($pmux), ID($bwmux)})
for (auto type : {TW($mux), TW($pmux), TW($bwmux)})
setup_type(type, {TW::A, TW::B, TW::S}, {TW::Y}, features);
for (auto type : {ID($bmux), ID($demux)})
for (auto type : {TW($bmux), TW($demux)})
setup_type(type, {TW::A, TW::S}, {TW::Y}, features);
setup_type(ID($lcu), {TW::P, TW::G, TW::CI}, {TW::CO}, features);
setup_type(ID($alu), {TW::A, TW::B, TW::CI, TW::BI}, {TW::X, TW::Y, TW::CO}, features);
setup_type(ID($macc_v2), {TW::A, TW::B, TW::C}, {TW::Y}, features);
setup_type(ID($fa), {TW::A, TW::B, TW::C}, {TW::X, TW::Y}, features);
setup_type(TW($lcu), {TW::P, TW::G, TW::CI}, {TW::CO}, features);
setup_type(TW($alu), {TW::A, TW::B, TW::CI, TW::BI}, {TW::X, TW::Y, TW::CO}, features);
setup_type(TW($macc_v2), {TW::A, TW::B, TW::C}, {TW::Y}, features);
setup_type(TW($fa), {TW::A, TW::B, TW::C}, {TW::X, TW::Y}, features);
}
constexpr void setup_internals_ff()
{
Features features {};
features.is_ff = true;
setup_type(ID($sr), {TW::SET, TW::CLR}, {TW::Q}, features);
setup_type(ID($ff), {TW::D}, {TW::Q}, features);
setup_type(ID($dff), {TW::CLK, TW::D}, {TW::Q}, features);
setup_type(ID($dffe), {TW::CLK, TW::EN, TW::D}, {TW::Q}, features);
setup_type(ID($dffsr), {TW::CLK, TW::SET, TW::CLR, TW::D}, {TW::Q}, features);
setup_type(ID($dffsre), {TW::CLK, TW::SET, TW::CLR, TW::D, TW::EN}, {TW::Q}, features);
setup_type(ID($adff), {TW::CLK, TW::ARST, TW::D}, {TW::Q}, features);
setup_type(ID($adffe), {TW::CLK, TW::ARST, TW::D, TW::EN}, {TW::Q}, features);
setup_type(ID($aldff), {TW::CLK, TW::ALOAD, TW::AD, TW::D}, {TW::Q}, features);
setup_type(ID($aldffe), {TW::CLK, TW::ALOAD, TW::AD, TW::D, TW::EN}, {TW::Q}, features);
setup_type(ID($sdff), {TW::CLK, TW::SRST, TW::D}, {TW::Q}, features);
setup_type(ID($sdffe), {TW::CLK, TW::SRST, TW::D, TW::EN}, {TW::Q}, features);
setup_type(ID($sdffce), {TW::CLK, TW::SRST, TW::D, TW::EN}, {TW::Q}, features);
setup_type(ID($dlatch), {TW::EN, TW::D}, {TW::Q}, features);
setup_type(ID($adlatch), {TW::EN, TW::D, TW::ARST}, {TW::Q}, features);
setup_type(ID($dlatchsr), {TW::EN, TW::SET, TW::CLR, TW::D}, {TW::Q}, features);
setup_type(TW($sr), {TW::SET, TW::CLR}, {TW::Q}, features);
setup_type(TW($ff), {TW::D}, {TW::Q}, features);
setup_type(TW($dff), {TW::CLK, TW::D}, {TW::Q}, features);
setup_type(TW($dffe), {TW::CLK, TW::EN, TW::D}, {TW::Q}, features);
setup_type(TW($dffsr), {TW::CLK, TW::SET, TW::CLR, TW::D}, {TW::Q}, features);
setup_type(TW($dffsre), {TW::CLK, TW::SET, TW::CLR, TW::D, TW::EN}, {TW::Q}, features);
setup_type(TW($adff), {TW::CLK, TW::ARST, TW::D}, {TW::Q}, features);
setup_type(TW($adffe), {TW::CLK, TW::ARST, TW::D, TW::EN}, {TW::Q}, features);
setup_type(TW($aldff), {TW::CLK, TW::ALOAD, TW::AD, TW::D}, {TW::Q}, features);
setup_type(TW($aldffe), {TW::CLK, TW::ALOAD, TW::AD, TW::D, TW::EN}, {TW::Q}, features);
setup_type(TW($sdff), {TW::CLK, TW::SRST, TW::D}, {TW::Q}, features);
setup_type(TW($sdffe), {TW::CLK, TW::SRST, TW::D, TW::EN}, {TW::Q}, features);
setup_type(TW($sdffce), {TW::CLK, TW::SRST, TW::D, TW::EN}, {TW::Q}, features);
setup_type(TW($dlatch), {TW::EN, TW::D}, {TW::Q}, features);
setup_type(TW($adlatch), {TW::EN, TW::D, TW::ARST}, {TW::Q}, features);
setup_type(TW($dlatchsr), {TW::EN, TW::SET, TW::CLR, TW::D}, {TW::Q}, features);
}
constexpr void setup_internals_anyinit()
{
Features features {};
features.is_anyinit = true;
setup_type(ID($anyinit), {TW::D}, {TW::Q}, features);
setup_type(TW($anyinit), {TW::D}, {TW::Q}, features);
}
constexpr void setup_internals_mem_noff()
{
@ -163,24 +163,24 @@ struct CellTableBuilder {
features.is_mem_noff = true;
// NOT setup_internals_ff()
setup_type(ID($memrd), {TW::CLK, TW::EN, TW::ADDR}, {TW::DATA}, features);
setup_type(ID($memrd_v2), {TW::CLK, TW::EN, TW::ARST, TW::SRST, TW::ADDR}, {TW::DATA}, features);
setup_type(ID($memwr), {TW::CLK, TW::EN, TW::ADDR, TW::DATA}, {}, features);
setup_type(ID($memwr_v2), {TW::CLK, TW::EN, TW::ADDR, TW::DATA}, {}, features);
setup_type(ID($meminit), {TW::ADDR, TW::DATA}, {}, features);
setup_type(ID($meminit_v2), {TW::ADDR, TW::DATA, TW::EN}, {}, features);
setup_type(ID($mem), {TW::RD_CLK, TW::RD_EN, TW::RD_ADDR, TW::WR_CLK, TW::WR_EN, TW::WR_ADDR, TW::WR_DATA}, {TW::RD_DATA}, features);
setup_type(ID($mem_v2), {TW::RD_CLK, TW::RD_EN, TW::RD_ARST, TW::RD_SRST, TW::RD_ADDR, TW::WR_CLK, TW::WR_EN, TW::WR_ADDR, TW::WR_DATA}, {TW::RD_DATA}, features);
setup_type(TW($memrd), {TW::CLK, TW::EN, TW::ADDR}, {TW::DATA}, features);
setup_type(TW($memrd_v2), {TW::CLK, TW::EN, TW::ARST, TW::SRST, TW::ADDR}, {TW::DATA}, features);
setup_type(TW($memwr), {TW::CLK, TW::EN, TW::ADDR, TW::DATA}, {}, features);
setup_type(TW($memwr_v2), {TW::CLK, TW::EN, TW::ADDR, TW::DATA}, {}, features);
setup_type(TW($meminit), {TW::ADDR, TW::DATA}, {}, features);
setup_type(TW($meminit_v2), {TW::ADDR, TW::DATA, TW::EN}, {}, features);
setup_type(TW($mem), {TW::RD_CLK, TW::RD_EN, TW::RD_ADDR, TW::WR_CLK, TW::WR_EN, TW::WR_ADDR, TW::WR_DATA}, {TW::RD_DATA}, features);
setup_type(TW($mem_v2), {TW::RD_CLK, TW::RD_EN, TW::RD_ARST, TW::RD_SRST, TW::RD_ADDR, TW::WR_CLK, TW::WR_EN, TW::WR_ADDR, TW::WR_DATA}, {TW::RD_DATA}, features);
// What?
setup_type(ID($fsm), {TW::CLK, TW::ARST, TW::CTRL_IN}, {TW::CTRL_OUT}, features);
setup_type(TW($fsm), {TW::CLK, TW::ARST, TW::CTRL_IN}, {TW::CTRL_OUT}, features);
}
constexpr void setup_stdcells_tristate()
{
Features features {};
features.is_stdcell = true;
features.is_tristate = true;
setup_type(ID($_TBUF_), {TW::A, TW::E}, {TW::Y}, features);
setup_type(TW($_TBUF_), {TW::A, TW::E}, {TW::Y}, features);
}
constexpr void setup_stdcells_eval()
@ -188,25 +188,25 @@ struct CellTableBuilder {
Features features {};
features.is_stdcell = true;
features.is_evaluable = true;
setup_type(ID($_BUF_), {TW::A}, {TW::Y}, features);
setup_type(ID($_NOT_), {TW::A}, {TW::Y}, features);
setup_type(ID($_AND_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(ID($_NAND_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(ID($_OR_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(ID($_NOR_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(ID($_XOR_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(ID($_XNOR_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(ID($_ANDNOT_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(ID($_ORNOT_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(ID($_MUX_), {TW::A, TW::B, TW::S}, {TW::Y}, features);
setup_type(ID($_NMUX_), {TW::A, TW::B, TW::S}, {TW::Y}, features);
setup_type(ID($_MUX4_), {TW::A, TW::B, TW::C, TW::D, TW::S, TW::T}, {TW::Y}, features);
setup_type(ID($_MUX8_), {TW::A, TW::B, TW::C, TW::D, TW::E, TW::F, TW::G, TW::H, TW::S, TW::T, TW::U}, {TW::Y}, features);
setup_type(ID($_MUX16_), {TW::A, TW::B, TW::C, TW::D, TW::E, TW::F, TW::G, TW::H, TW::I, TW::J, TW::K, TW::L, TW::M, TW::N, TW::O, TW::P, TW::S, TW::T, TW::U, TW::V}, {TW::Y}, features);
setup_type(ID($_AOI3_), {TW::A, TW::B, TW::C}, {TW::Y}, features);
setup_type(ID($_OAI3_), {TW::A, TW::B, TW::C}, {TW::Y}, features);
setup_type(ID($_AOI4_), {TW::A, TW::B, TW::C, TW::D}, {TW::Y}, features);
setup_type(ID($_OAI4_), {TW::A, TW::B, TW::C, TW::D}, {TW::Y}, features);
setup_type(TW($_BUF_), {TW::A}, {TW::Y}, features);
setup_type(TW($_NOT_), {TW::A}, {TW::Y}, features);
setup_type(TW($_AND_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(TW($_NAND_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(TW($_OR_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(TW($_NOR_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(TW($_XOR_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(TW($_XNOR_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(TW($_ANDNOT_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(TW($_ORNOT_), {TW::A, TW::B}, {TW::Y}, features);
setup_type(TW($_MUX_), {TW::A, TW::B, TW::S}, {TW::Y}, features);
setup_type(TW($_NMUX_), {TW::A, TW::B, TW::S}, {TW::Y}, features);
setup_type(TW($_MUX4_), {TW::A, TW::B, TW::C, TW::D, TW::S, TW::T}, {TW::Y}, features);
setup_type(TW($_MUX8_), {TW::A, TW::B, TW::C, TW::D, TW::E, TW::F, TW::G, TW::H, TW::S, TW::T, TW::U}, {TW::Y}, features);
setup_type(TW($_MUX16_), {TW::A, TW::B, TW::C, TW::D, TW::E, TW::F, TW::G, TW::H, TW::I, TW::J, TW::K, TW::L, TW::M, TW::N, TW::O, TW::P, TW::S, TW::T, TW::U, TW::V}, {TW::Y}, features);
setup_type(TW($_AOI3_), {TW::A, TW::B, TW::C}, {TW::Y}, features);
setup_type(TW($_OAI3_), {TW::A, TW::B, TW::C}, {TW::Y}, features);
setup_type(TW($_AOI4_), {TW::A, TW::B, TW::C, TW::D}, {TW::Y}, features);
setup_type(TW($_OAI4_), {TW::A, TW::B, TW::C, TW::D}, {TW::Y}, features);
}
constexpr void setup_stdcells_ff() {
@ -217,193 +217,193 @@ struct CellTableBuilder {
// for (auto c1 : list_np)
// for (auto c2 : list_np)
// setup_type(std::string("$_SR_") + c1 + c2 + "_", {TW::S, TW::R}, {TW::Q}, features);
setup_type(ID($_SR_NN_), {TW::S, TW::R}, {TW::Q}, features);
setup_type(ID($_SR_NP_), {TW::S, TW::R}, {TW::Q}, features);
setup_type(ID($_SR_PN_), {TW::S, TW::R}, {TW::Q}, features);
setup_type(ID($_SR_PP_), {TW::S, TW::R}, {TW::Q}, features);
setup_type(TW($_SR_NN_), {TW::S, TW::R}, {TW::Q}, features);
setup_type(TW($_SR_NP_), {TW::S, TW::R}, {TW::Q}, features);
setup_type(TW($_SR_PN_), {TW::S, TW::R}, {TW::Q}, features);
setup_type(TW($_SR_PP_), {TW::S, TW::R}, {TW::Q}, features);
setup_type(ID($_FF_), {TW::D}, {TW::Q}, features);
setup_type(TW($_FF_), {TW::D}, {TW::Q}, features);
// for (auto c1 : list_np)
// setup_type(std::string("$_DFF_") + c1 + "_", {TW::C, TW::D}, {TW::Q}, features);
setup_type(ID::$_DFF_N_, {TW::C, TW::D}, {TW::Q}, features);
setup_type(ID::$_DFF_P_, {TW::C, TW::D}, {TW::Q}, features);
setup_type(TW($_DFF_N_), {TW::C, TW::D}, {TW::Q}, features);
setup_type(TW($_DFF_P_), {TW::C, TW::D}, {TW::Q}, features);
// for (auto c1 : list_np)
// for (auto c2 : list_np)
// setup_type(std::string("$_DFFE_") + c1 + c2 + "_", {TW::C, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID::$_DFFE_NN_, {TW::C, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID::$_DFFE_NP_, {TW::C, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID::$_DFFE_PN_, {TW::C, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID::$_DFFE_PP_, {TW::C, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_NN_), {TW::C, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_NP_), {TW::C, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_PN_), {TW::C, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_PP_), {TW::C, TW::D, TW::E}, {TW::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 + "_", {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFF_NN0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFF_NN1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFF_NP0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFF_NP1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFF_PN0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFF_PN1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFF_PP0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFF_PP1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFF_NN0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFF_NN1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFF_NP0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFF_NP1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFF_PN0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFF_PN1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFF_PP0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFF_PP1_), {TW::C, TW::R, TW::D}, {TW::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 + "_", {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_NN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_NN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_NN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_NN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_NP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_NP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_NP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_NP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_PN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_PN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_PN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_PN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_PP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_PP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_PP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFE_PP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_NN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_NN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_NN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_NN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_NP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_NP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_NP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_NP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_PN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_PN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_PN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_PN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_PP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_PP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_PP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFE_PP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
// for (auto c1 : list_np)
// for (auto c2 : list_np)
// setup_type(std::string("$_ALDFF_") + c1 + c2 + "_", {TW::C, TW::L, TW::AD, TW::D}, {TW::Q}, features);
setup_type(ID($_ALDFF_NN_), {TW::C, TW::L, TW::AD, TW::D}, {TW::Q}, features);
setup_type(ID($_ALDFF_NP_), {TW::C, TW::L, TW::AD, TW::D}, {TW::Q}, features);
setup_type(ID($_ALDFF_PN_), {TW::C, TW::L, TW::AD, TW::D}, {TW::Q}, features);
setup_type(ID($_ALDFF_PP_), {TW::C, TW::L, TW::AD, TW::D}, {TW::Q}, features);
setup_type(TW($_ALDFF_NN_), {TW::C, TW::L, TW::AD, TW::D}, {TW::Q}, features);
setup_type(TW($_ALDFF_NP_), {TW::C, TW::L, TW::AD, TW::D}, {TW::Q}, features);
setup_type(TW($_ALDFF_PN_), {TW::C, TW::L, TW::AD, TW::D}, {TW::Q}, features);
setup_type(TW($_ALDFF_PP_), {TW::C, TW::L, TW::AD, TW::D}, {TW::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 + "_", {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_ALDFFE_NNN_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_ALDFFE_NNP_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_ALDFFE_NPN_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_ALDFFE_NPP_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_ALDFFE_PNN_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_ALDFFE_PNP_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_ALDFFE_PPN_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_ALDFFE_PPP_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_ALDFFE_NNN_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_ALDFFE_NNP_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_ALDFFE_NPN_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_ALDFFE_NPP_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_ALDFFE_PNN_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_ALDFFE_PNP_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_ALDFFE_PPN_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_ALDFFE_PPP_), {TW::C, TW::L, TW::AD, TW::D, TW::E}, {TW::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 + "_", {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFFSR_NNN_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFFSR_NNP_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFFSR_NPN_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFFSR_NPP_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFFSR_PNN_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFFSR_PNP_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFFSR_PPN_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DFFSR_PPP_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFFSR_NNN_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFFSR_NNP_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFFSR_NPN_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFFSR_NPP_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFFSR_PNN_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFFSR_PNP_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFFSR_PPN_), {TW::C, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DFFSR_PPP_), {TW::C, TW::S, TW::R, TW::D}, {TW::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 + "_", {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_NNNN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_NNNP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_NNPN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_NNPP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_NPNN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_NPNP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_NPPN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_NPPP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_PNNN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_PNNP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_PNPN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_PNPP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_PPNN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_PPNP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_PPPN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_DFFSRE_PPPP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_NNNN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_NNNP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_NNPN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_NNPP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_NPNN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_NPNP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_NPPN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_NPPP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_PNNN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_PNNP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_PNPN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_PNPP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_PPNN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_PPNP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_PPPN_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_DFFSRE_PPPP_), {TW::C, TW::S, TW::R, TW::D, TW::E}, {TW::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 + "_", {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_SDFF_NN0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_SDFF_NN1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_SDFF_NP0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_SDFF_NP1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_SDFF_PN0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_SDFF_PN1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_SDFF_PP0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_SDFF_PP1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_SDFF_NN0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_SDFF_NN1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_SDFF_NP0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_SDFF_NP1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_SDFF_PN0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_SDFF_PN1_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_SDFF_PP0_), {TW::C, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_SDFF_PP1_), {TW::C, TW::R, TW::D}, {TW::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 + "_", {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_NN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_NN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_NN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_NN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_NP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_NP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_NP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_NP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_PN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_PN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_PN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_PN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_PP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_PP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_PP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFE_PP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_NN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_NN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_NN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_NN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_NP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_NP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_NP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_NP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_PN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_PN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_PN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_PN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_PP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_PP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_PP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFE_PP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::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 + "_", {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_NN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_NN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_NN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_NN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_NP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_NP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_NP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_NP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_PN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_PN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_PN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_PN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_PP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_PP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_PP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(ID($_SDFFCE_PP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_NN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_NN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_NN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_NN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_NP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_NP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_NP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_NP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_PN0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_PN0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_PN1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_PN1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_PP0N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_PP0P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_PP1N_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
setup_type(TW($_SDFFCE_PP1P_), {TW::C, TW::R, TW::D, TW::E}, {TW::Q}, features);
// for (auto c1 : list_np)
// setup_type(std::string("$_DLATCH_") + c1 + "_", {TW::E, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCH_N_), {TW::E, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCH_P_), {TW::E, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCH_N_), {TW::E, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCH_P_), {TW::E, TW::D}, {TW::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 + "_", {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCH_NN0_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCH_NN1_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCH_NP0_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCH_NP1_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCH_PN0_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCH_PN1_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCH_PP0_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCH_PP1_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCH_NN0_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCH_NN1_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCH_NP0_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCH_NP1_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCH_PN0_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCH_PN1_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCH_PP0_), {TW::E, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCH_PP1_), {TW::E, TW::R, TW::D}, {TW::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 + "_", {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCHSR_NNN_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCHSR_NNP_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCHSR_NPN_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCHSR_NPP_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCHSR_PNN_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCHSR_PNP_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCHSR_PPN_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(ID($_DLATCHSR_PPP_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCHSR_NNN_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCHSR_NNP_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCHSR_NPN_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCHSR_NPP_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCHSR_PNN_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCHSR_PNP_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCHSR_PPN_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
setup_type(TW($_DLATCHSR_PPP_), {TW::E, TW::S, TW::R, TW::D}, {TW::Q}, features);
}
constexpr CellTableBuilder() {
setup_internals_other();
@ -423,8 +423,8 @@ constexpr CellTableBuilder builder {};
struct PortInfo {
struct PortLists {
std::array<CellTableBuilder::PortList, MAX_CELLS> data{};
constexpr CellTableBuilder::PortList operator()(IdString type) const {
return data[type.index_];
constexpr CellTableBuilder::PortList operator()(TwineRef type) const {
return data[type];
}
constexpr CellTableBuilder::PortList& operator[](size_t idx) {
return data[idx];
@ -436,7 +436,7 @@ struct PortInfo {
constexpr PortInfo() {
for (size_t i = 0; i < builder.count; ++i) {
auto& cell = builder.cells[i];
size_t idx = cell.type.index_;
size_t idx = cell.type;
inputs[idx] = cell.inputs;
outputs[idx] = cell.outputs;
}
@ -446,8 +446,8 @@ struct PortInfo {
struct Categories {
struct Category {
std::array<bool, MAX_CELLS> data{};
constexpr bool operator()(IdString type) const {
size_t idx = type.index_;
constexpr bool operator()(TwineRef type) const {
size_t idx = type;
if (idx >= MAX_CELLS)
return false;
return data[idx];
@ -479,7 +479,7 @@ struct Categories {
constexpr Categories() {
for (size_t i = 0; i < builder.count; ++i) {
auto& cell = builder.cells[i];
size_t idx = cell.type.index_;
size_t idx = cell.type;
is_known.set(idx);
is_evaluable.set(idx, cell.features.is_evaluable);
is_combinatorial.set(idx, cell.features.is_combinatorial);
@ -537,17 +537,17 @@ namespace Compat {
};
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)));
static_assert(categories.is_evaluable(TW($and)));
static_assert(!categories.is_ff(TW($and)));
static_assert(Categories::join(categories.is_evaluable, categories.is_ff)(TW($and)));
static_assert(Categories::join(categories.is_evaluable, categories.is_ff)(TW($dffsr)));
static_assert(!Categories::join(categories.is_evaluable, categories.is_ff)(TW($anyinit)));
}
};
struct NewCellType {
RTLIL::IdString type;
TwineRef type;
pool<TwineRef> inputs, outputs;
bool is_evaluable;
bool is_combinatorial;
@ -561,7 +561,7 @@ struct NewCellTypes {
}
};
StaticCellTypes::Categories::Category static_cell_types = StaticCellTypes::categories.empty;
std::unordered_map<RTLIL::IdString, NewCellType, IdStringHash> custom_cell_types {};
std::unordered_map<TwineRef, NewCellType, IdStringHash> custom_cell_types {};
NewCellTypes() {
static_cell_types = StaticCellTypes::categories.empty;
@ -590,10 +590,10 @@ struct NewCellTypes {
if (wire->port_output)
outputs.insert(wire->meta_->name);
}
setup_type(RTLIL::IdString(module->design->twines.str(module->meta_->name)), inputs, outputs);
setup_type(module->meta_->name, inputs, outputs);
}
void setup_type(RTLIL::IdString type, const pool<TwineRef> &inputs, const pool<TwineRef> &outputs, bool is_evaluable = false, bool is_combinatorial = false, bool is_synthesizable = false) {
void setup_type(TwineRef type, const pool<TwineRef> &inputs, const pool<TwineRef> &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;
}
@ -603,11 +603,11 @@ struct NewCellTypes {
static_cell_types = StaticCellTypes::categories.empty;
}
bool cell_known(const RTLIL::IdString &type) const {
bool cell_known(TwineRef type) const {
return static_cell_types(type) || custom_cell_types.count(type) != 0;
}
bool cell_output(const RTLIL::IdString &type, TwineRef port) const
bool cell_output(TwineRef type, TwineRef port) const
{
// TODO refactor
if (static_cell_types(type) && StaticCellTypes::port_info.outputs(type).contains(port)) {
@ -617,7 +617,7 @@ struct NewCellTypes {
return it != custom_cell_types.end() && it->second.outputs.count(port) != 0;
}
bool cell_input(const RTLIL::IdString &type, TwineRef port) const
bool cell_input(TwineRef type, TwineRef port) const
{
if (static_cell_types(type) && StaticCellTypes::port_info.inputs(type).contains(port)) {
return true;
@ -626,7 +626,7 @@ struct NewCellTypes {
return it != custom_cell_types.end() && it->second.inputs.count(port) != 0;
}
RTLIL::PortDir cell_port_dir(RTLIL::IdString type, TwineRef port) const
RTLIL::PortDir cell_port_dir(TwineRef type, TwineRef port) const
{
bool is_input, is_output;
if (static_cell_types(type)) {
@ -641,7 +641,7 @@ struct NewCellTypes {
}
return RTLIL::PortDir(is_input + is_output * 2);
}
bool cell_evaluable(const RTLIL::IdString &type) const
bool cell_evaluable(TwineRef type) const
{
return static_cell_types(type) && StaticCellTypes::categories.is_evaluable(type);
}

File diff suppressed because it is too large Load diff

View file

@ -133,6 +133,7 @@ namespace RTLIL
struct ModuleNameMasq;
struct WireNameMasq;
struct CellNameMasq;
struct CellTypeMasq;
typedef std::pair<SigSpec, SigSpec> SigSig;
struct PortBit;
@ -590,6 +591,9 @@ public:
}
};
inline bool operator==(TwineRef a, RTLIL::IdString b) { return a.untag().value == (size_t)(unsigned)b.index_; }
inline bool operator==(RTLIL::IdString a, TwineRef b) { return b == a; }
struct RTLIL::OwningIdString : public RTLIL::IdString {
inline OwningIdString() { }
inline OwningIdString(const OwningIdString &str) : IdString(str) { get_reference(); }
@ -776,7 +780,7 @@ namespace RTLIL {
extern dict<std::string, std::string> constpad;
[[deprecated("use StaticCellTypes::categories.is_ff() instead")]]
const pool<IdString> &builtin_ff_cell_types();
const pool<TwineRef> &builtin_ff_cell_types();
static inline std::string escape_id(const std::string &str) {
if (str.size() > 0 && str[0] != '\\' && str[0] != '$')
@ -1337,11 +1341,16 @@ struct RTLIL::WireNameMasq {
WireNameMasq &operator=(WireNameMasq &&) = delete;
// Materialise → IdString. Slow path; intended for plugin code.
operator RTLIL::IdString() const;
// Tagged name handle (Twine::Null when unnamed).
TwineRef ref() const;
// Escaped form ('\'-prefixed when public) / bare content.
std::string escaped() const;
std::string unescaped() const;
bool isPublic() const { return twine_is_public(ref()); }
bool empty() const { return RTLIL::IdString(*this).empty(); }
std::string str() const { return RTLIL::IdString(*this).str(); }
std::string str() const { return escaped(); }
const char *c_str() const { return RTLIL::IdString(*this).c_str(); }
bool isPublic() const { return RTLIL::IdString(*this).isPublic(); }
std::string unescape() const { return RTLIL::IdString(*this).unescape(); }
std::string unescape() const { return unescaped(); }
bool begins_with(const char *s) const { return RTLIL::IdString(*this).begins_with(s); }
bool ends_with(const char *s) const { return RTLIL::IdString(*this).ends_with(s); }
template <typename... Ts> bool in(Ts &&...args) const {
@ -1376,11 +1385,16 @@ struct RTLIL::CellNameMasq {
CellNameMasq &operator=(const CellNameMasq &) = delete;
CellNameMasq &operator=(CellNameMasq &&) = delete;
operator RTLIL::IdString() const;
// Tagged name handle (Twine::Null when unnamed).
TwineRef ref() const;
// Escaped form ('\'-prefixed when public) / bare content.
std::string escaped() const;
std::string unescaped() const;
bool isPublic() const { return twine_is_public(ref()); }
bool empty() const { return RTLIL::IdString(*this).empty(); }
std::string str() const { return RTLIL::IdString(*this).str(); }
std::string str() const { return escaped(); }
const char *c_str() const { return RTLIL::IdString(*this).c_str(); }
bool isPublic() const { return RTLIL::IdString(*this).isPublic(); }
std::string unescape() const { return RTLIL::IdString(*this).unescape(); }
std::string unescape() const { return unescaped(); }
bool begins_with(const char *s) const { return RTLIL::IdString(*this).begins_with(s); }
bool ends_with(const char *s) const { return RTLIL::IdString(*this).ends_with(s); }
template <typename... Ts> bool in(Ts &&...args) const {
@ -1407,6 +1421,51 @@ struct RTLIL::CellNameMasq {
inline bool operator==(RTLIL::IdString lhs, const RTLIL::CellNameMasq &rhs) { return lhs == RTLIL::IdString(rhs); }
inline bool operator!=(RTLIL::IdString lhs, const RTLIL::CellNameMasq &rhs) { return lhs != RTLIL::IdString(rhs); }
// Read-only masquerade for Cell::type. Backed by Cell::type_impl.
// Write the type via cell->type_impl directly.
struct RTLIL::CellTypeMasq {
CellTypeMasq() = default;
CellTypeMasq(const CellTypeMasq &) = delete;
CellTypeMasq(CellTypeMasq &&) = delete;
CellTypeMasq &operator=(const CellTypeMasq &) = delete;
CellTypeMasq &operator=(CellTypeMasq &&) = delete;
operator RTLIL::IdString() const;
explicit operator TwineRef() const { return ref(); }
TwineRef ref() const;
std::string escaped() const;
std::string unescaped() const;
bool isPublic() const { return twine_is_public(ref()); }
bool empty() const { return ref() == Twine::Null; }
std::string str() const { return escaped(); } // TODO deprecate
const char *c_str() const { return RTLIL::IdString(*this).c_str(); }
std::string unescape() const { return unescaped(); }
bool begins_with(const char *s) const { return RTLIL::IdString(*this).begins_with(s); }
bool ends_with(const char *s) const { return RTLIL::IdString(*this).ends_with(s); }
template <typename... Ts> bool in(Ts &&...args) const {
return ref().in(std::forward<Ts>(args)...);
}
std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
return RTLIL::IdString(*this).substr(pos, len);
}
size_t size() const { return RTLIL::IdString(*this).size(); }
bool contains(const char *p) const { return RTLIL::IdString(*this).contains(p); }
char operator[](int n) const { return RTLIL::IdString(*this).str()[n]; }
bool operator==(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) == rhs; }
bool operator!=(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) != rhs; }
bool operator<(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) < rhs; }
bool operator==(TwineRef rhs) const { return ref() == rhs; }
bool operator!=(TwineRef rhs) const { return ref() != rhs; }
bool operator==(const std::string &rhs) const { return RTLIL::IdString(*this) == rhs; }
bool operator!=(const std::string &rhs) const { return RTLIL::IdString(*this) != rhs; }
bool operator==(const CellTypeMasq &rhs) const { return ref() == rhs.ref(); }
bool operator!=(const CellTypeMasq &rhs) const { return ref() != rhs.ref(); }
[[nodiscard]] Hasher hash_into(Hasher h) const { return RTLIL::IdString(*this).hash_into(h); }
};
inline bool operator==(RTLIL::IdString lhs, const RTLIL::CellTypeMasq &rhs) { return lhs == RTLIL::IdString(rhs); }
inline bool operator!=(RTLIL::IdString lhs, const RTLIL::CellTypeMasq &rhs) { return lhs != RTLIL::IdString(rhs); }
inline bool operator==(TwineRef lhs, const RTLIL::CellTypeMasq &rhs) { return lhs == rhs.ref(); }
inline bool operator!=(TwineRef lhs, const RTLIL::CellTypeMasq &rhs) { return lhs != rhs.ref(); }
struct RTLIL::SigChunk
{
RTLIL::Wire *wire;
@ -2385,7 +2444,8 @@ public:
void operator=(RTLIL::Cell &other) = delete;
RTLIL::Module *module;
IdString type;
TwineRef type_impl;
[[no_unique_address]] RTLIL::CellTypeMasq type;
dict<TwineRef, RTLIL::SigSpec> connections_;
dict<RTLIL::IdString, RTLIL::Const> parameters;
@ -2800,8 +2860,6 @@ public:
RTLIL::Cell* addDlatchsrGate (Twine &&name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr,
RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, TwineRef src = Twine::Null);
RTLIL::Cell* addAnyinit(Twine &&name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, TwineRef src = Twine::Null);
// The methods without the add* prefix create a cell and an output signal. They return the newly created output signal.
RTLIL::SigSpec Not (Twine &&name, const RTLIL::SigSpec &sig_a, bool is_signed = false, TwineRef src = Twine::Null);
@ -2967,8 +3025,8 @@ public:
Module();
virtual ~Module();
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail = false);
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail = false);
virtual TwineRef derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail = false);
virtual TwineRef derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail = false);
virtual size_t count_id(TwineRef id);
virtual void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces);
virtual bool reprocess_if_necessary(RTLIL::Design *design);
@ -3038,7 +3096,7 @@ public:
// As above, but additionally renames the new module to `target_name` in
// `dst`. Used when source and destination designs may contain modules
// with the same name and the new one must take a different identity.
virtual RTLIL::Module *clone(RTLIL::Design *dst, RTLIL::IdString target_name, bool src_id_verbatim = false) const;
virtual RTLIL::Module *clone(RTLIL::Design *dst, TwineRef target_name, bool src_id_verbatim = false) const;
bool has_memories() const;
bool has_processes() const;
@ -3110,10 +3168,11 @@ public:
RTLIL::Wire *addWire(Twine &&name, const RTLIL::Wire *other);
// Primary overloads.
RTLIL::Cell *addCell(TwineRef name, RTLIL::IdString type);
RTLIL::Cell *addCell(TwineRef name, TwineRef type);
RTLIL::Cell *addCell(TwineRef name, const RTLIL::Cell *other);
// Convenience.
RTLIL::Cell *addCell(Twine &&name, RTLIL::IdString type);
RTLIL::Cell *addCell(Twine &&name, TwineRef type);
RTLIL::Cell *addCell(TwineRef name, Twine &&type);
RTLIL::Cell *addCell(Twine &&name, const RTLIL::Cell *other);
// NEW_ID analog for twine names; see NEW_TWINE in yosys_common.h.
@ -3132,7 +3191,8 @@ public:
// The add* methods create a cell and return the created cell. All signals must exist in advance.
RTLIL::Cell* addAnyinit(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, TwineRef src = Twine::Null);
RTLIL::Cell* addAnyinit(TwineRef name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, TwineRef src = Twine::Null);
RTLIL::Cell* addAnyinit(Twine &&name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, TwineRef src = Twine::Null);
// The methods without the add* prefix create a cell and an output signal. They return the newly created output signal.
@ -3141,6 +3201,11 @@ public:
RTLIL::SigSpec Allconst (TwineRef name, int width = 1, TwineRef src = Twine::Null);
RTLIL::SigSpec Allseq (TwineRef name, int width = 1, TwineRef src = Twine::Null);
RTLIL::SigSpec Initstate (TwineRef name, TwineRef src = Twine::Null);
RTLIL::SigSpec Anyconst (Twine &&name, int width = 1, TwineRef src = Twine::Null);
RTLIL::SigSpec Anyseq (Twine &&name, int width = 1, TwineRef src = Twine::Null);
RTLIL::SigSpec Allconst (Twine &&name, int width = 1, TwineRef src = Twine::Null);
RTLIL::SigSpec Allseq (Twine &&name, int width = 1, TwineRef src = Twine::Null);
RTLIL::SigSpec Initstate (Twine &&name, TwineRef src = Twine::Null);
RTLIL::SigSpec SetTag (TwineRef name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, TwineRef src = Twine::Null);
RTLIL::Cell* addSetTag (TwineRef name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
@ -3148,6 +3213,12 @@ public:
RTLIL::Cell* addOverwriteTag (TwineRef name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, TwineRef src = Twine::Null);
RTLIL::SigSpec OriginalTag (TwineRef name, const std::string &tag, const RTLIL::SigSpec &sig_a, TwineRef src = Twine::Null);
RTLIL::SigSpec FutureFF (TwineRef name, const RTLIL::SigSpec &sig_e, TwineRef src = Twine::Null);
RTLIL::SigSpec SetTag (Twine &&name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, TwineRef src = Twine::Null);
RTLIL::Cell* addSetTag (Twine &&name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, const RTLIL::SigSpec &sig_y, TwineRef src = Twine::Null);
RTLIL::SigSpec GetTag (Twine &&name, const std::string &tag, const RTLIL::SigSpec &sig_a, TwineRef src = Twine::Null);
RTLIL::Cell* addOverwriteTag (Twine &&name, const std::string &tag, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_c, TwineRef src = Twine::Null);
RTLIL::SigSpec OriginalTag (Twine &&name, const std::string &tag, const RTLIL::SigSpec &sig_a, TwineRef src = Twine::Null);
RTLIL::SigSpec FutureFF (Twine &&name, const RTLIL::SigSpec &sig_e, TwineRef src = Twine::Null);
std::string to_rtlil_str() const;
#ifdef YOSYS_ENABLE_PYTHON
@ -3278,26 +3349,108 @@ void RTLIL::Process::rewrite_sigspecs2(T &functor)
it->rewrite_sigspecs2(functor);
}
inline RTLIL::WireNameMasq::operator RTLIL::IdString() const {
inline TwineRef RTLIL::WireNameMasq::ref() const {
const RTLIL::Wire *w = reinterpret_cast<const RTLIL::Wire *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Wire, name));
if (!w->module || !w->module->design || !w->meta_)
return RTLIL::IdString{};
TwineRef id = w->meta_->name;
if (id == Twine::Null)
return RTLIL::IdString{};
return RTLIL::IdString(w->module->design->twines.flat_string(id));
return Twine::Null;
return w->meta_->name;
}
inline RTLIL::CellNameMasq::operator RTLIL::IdString() const {
inline std::string RTLIL::WireNameMasq::escaped() const {
const RTLIL::Wire *w = reinterpret_cast<const RTLIL::Wire *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Wire, name));
TwineRef id = ref();
if (id == Twine::Null)
return std::string();
return w->module->design->twines.str(id);
}
inline std::string RTLIL::WireNameMasq::unescaped() const {
const RTLIL::Wire *w = reinterpret_cast<const RTLIL::Wire *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Wire, name));
TwineRef id = ref();
if (id == Twine::Null)
return std::string();
return w->module->design->twines.unescaped_str(id);
}
inline RTLIL::WireNameMasq::operator RTLIL::IdString() const {
std::string s = escaped();
if (s.empty())
return RTLIL::IdString{};
return RTLIL::IdString(s);
}
inline TwineRef RTLIL::CellNameMasq::ref() const {
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, name));
if (!c->module || !c->module->design || !c->meta_)
return RTLIL::IdString{};
TwineRef id = c->meta_->name;
return Twine::Null;
return c->meta_->name;
}
inline std::string RTLIL::CellNameMasq::escaped() const {
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, name));
TwineRef id = ref();
if (id == Twine::Null)
return std::string();
return c->module->design->twines.str(id);
}
inline std::string RTLIL::CellNameMasq::unescaped() const {
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, name));
TwineRef id = ref();
if (id == Twine::Null)
return std::string();
return c->module->design->twines.unescaped_str(id);
}
inline RTLIL::CellNameMasq::operator RTLIL::IdString() const {
std::string s = escaped();
if (s.empty())
return RTLIL::IdString{};
return RTLIL::IdString(c->module->design->twines.flat_string(id));
return RTLIL::IdString(s);
}
inline TwineRef RTLIL::CellTypeMasq::ref() const {
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, type));
return c->type_impl;
}
inline std::string RTLIL::CellTypeMasq::escaped() const {
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, type));
TwineRef id = c->type_impl;
if (id == Twine::Null)
return std::string();
if (c->module && c->module->design)
return c->module->design->twines.str(id);
// Static (TW::) refs are pool-independent; assert non-local ref.
log_assert(twine_untag(id) < STATIC_TWINE_END);
return TwinePool{}.str(id);
}
inline std::string RTLIL::CellTypeMasq::unescaped() const {
const RTLIL::Cell *c = reinterpret_cast<const RTLIL::Cell *>(
reinterpret_cast<const char *>(this) - offsetof(RTLIL::Cell, type));
TwineRef id = c->type_impl;
if (id == Twine::Null)
return std::string();
if (c->module && c->module->design)
return c->module->design->twines.unescaped_str(id);
log_assert(twine_untag(id) < STATIC_TWINE_END);
return TwinePool{}.unescaped_str(id);
}
inline RTLIL::CellTypeMasq::operator RTLIL::IdString() const {
std::string s = escaped();
if (s.empty())
return RTLIL::IdString{};
return RTLIL::IdString(s);
}
// inline RTLIL::ModuleNameMasq& RTLIL::ModuleNameMasq::operator=(RTLIL::IdString id) {

View file

@ -527,7 +527,7 @@ void RTLIL::Module::remove(RTLIL::Cell *cell)
log_assert(refcount_cells_ == 0);
cells_.erase(cell_id);
if (design && design->flagBufferedNormalized && buf_norm_cell_queue.count(cell)) {
cell->type.clear();
cell->type_impl = Twine::Null;
// design->obj_release_name(cell);
pending_deleted_cells.insert(cell);
} else {

View file

@ -6,10 +6,10 @@ YOSYS_NAMESPACE_BEGIN
std::vector<Twine> TwinePool::globals_;
TwineRef twine_populate(std::string name) {
if (name[1] == '$') {
// Skip prepended '\'
name = name.substr(1);
}
// Globals store content only: drop the prepended '\'. Publicity lives
// in TWINE_PUBLIC_BIT on the TW:: handle, not in the stored string.
log_assert(name[0] == '\\');
name = name.substr(1);
TwinePool::globals_.push_back(Twine{std::move(name)});
return TwinePool::globals_.size() - 1;
}

View file

@ -4,6 +4,8 @@
#include "kernel/yosys_common.h"
#include "kernel/hashlib.h"
#include <cassert>
#include "libs/plf_colony/plf_colony.h"
#include <cstdint>
#include <limits>
@ -21,10 +23,49 @@ YOSYS_NAMESPACE_BEGIN
struct Twine;
struct TwinePool;
using TwineRef = size_t;
struct TwineRef {
size_t value;
static constexpr size_t kLocalBit = 1ULL << 63;
static constexpr size_t kPublicBit = 1ULL << 62;
static constexpr size_t kTagMask = kLocalBit | kPublicBit;
static constexpr size_t kNull = ~size_t{0};
constexpr TwineRef() : value(0) {}
constexpr TwineRef(size_t val) : value(val) {}
constexpr operator size_t() const { return value; }
template <typename... Args>
constexpr bool in(const Args&... args) const {
return ((*this == args) || ...);
}
constexpr TwineRef operator|(TwineRef rhs) const { return TwineRef(value | rhs.value); }
constexpr TwineRef operator&(TwineRef rhs) const { return TwineRef(value & rhs.value); }
constexpr TwineRef operator~() const { return TwineRef(~value); }
constexpr TwineRef& operator++() { ++value; return *this; }
constexpr TwineRef operator++(int) { return TwineRef(value++); }
constexpr bool is_public() const { return value != kNull && (value & kPublicBit); }
constexpr bool is_local() const { return value != kNull && (value & kLocalBit); }
constexpr TwineRef untag() const {
return value == kNull ? *this : TwineRef(value & ~kPublicBit);
}
constexpr TwineRef tag(bool pub) const {
return value == kNull ? *this : TwineRef(pub ? (value | kPublicBit) : (value & ~kPublicBit));
}
Hasher hash_into(Hasher h) const { h.hash64(value); return h; }
};
// Tags TwineChildPool-local refs; never set on refs handed out by TwinePool.
constexpr TwineRef TWINE_LOCAL_BIT = TwineRef(1) << 63;
constexpr TwineRef TWINE_LOCAL_BIT = TwineRef(1LLU << 63);
// Publicity tag carried on name handles. Pool nodes store name *content*
// (no '\' escape); whether a name is public lives in this bit of the
// handle, never inside the pool. TwinePool strips it on every entry path.
constexpr TwineRef TWINE_PUBLIC_BIT = TwineRef(1LLU << 62);
constexpr TwineRef TWINE_TAG_MASK = TWINE_LOCAL_BIT | TWINE_PUBLIC_BIT;
enum : short {
STATIC_TWINE_BEGIN = 0,
@ -35,11 +76,26 @@ enum : short {
};
struct TW {
#define X(N) static constexpr TwineRef N = IDX_##N;
// Static ids are name handles: non-'$' constids were '\'-escaped publics,
// so their handles carry TWINE_PUBLIC_BIT baked in at compile time.
#define X(N) static constexpr TwineRef N = (#N)[0] == '$' ? TwineRef(IDX_##N) : (TwineRef(IDX_##N) | TWINE_PUBLIC_BIT);
#include "kernel/constids.inc"
#undef X
static constexpr TwineRef lookup(std::string_view name)
{
#define X(N) \
if (name == #N) return N;
#include "kernel/constids.inc"
#undef X
throw "unknown twine id";
}
};
#define TW(id) (size_t)lookup_well_known_id(#id)
// #define TW(name) TW::lookup(#name)
struct Twine {
static constexpr TwineRef Null = std::numeric_limits<size_t>::max();
@ -62,6 +118,10 @@ struct Twine {
const Suffix &suffix() const { return std::get<Suffix>(data); }
};
constexpr bool twine_is_public(TwineRef ref) { return ref.is_public(); }
constexpr TwineRef twine_untag(TwineRef ref) { return ref.untag(); }
constexpr TwineRef twine_tag(TwineRef ref, bool is_public) { return ref.tag(is_public); }
struct TwineHash {
using is_transparent = void;
@ -94,6 +154,7 @@ struct TwinePool {
std::unordered_set<TwineRef, TwineHash, TwineEq> index;
const Twine& operator[] (TwineRef ref) const {
ref = twine_untag(ref);
if (ref < STATIC_TWINE_END)
return globals_[ref];
else
@ -124,6 +185,10 @@ struct TwinePool {
}, twine.data);
}
void print(TwineRef ref, std::ostream& os = std::cout) const {
if (ref == Twine::Null)
return;
if (twine_is_public(ref))
os << '\\';
std::visit([&](const auto& val) {
using T = std::decay_t<decltype(val)>;
if constexpr (std::is_same_v<T, std::monostate>) {
@ -141,12 +206,18 @@ struct TwinePool {
}
}, (*this)[ref].data);
}
// Escaped form: leading '\' for public name handles, content otherwise.
std::string str(TwineRef ref) const {
std::ostringstream os;
print(ref, os);
return os.str();
}
// Name content without the publicity escape.
std::string unescaped_str(TwineRef ref) const {
return str(twine_untag(ref));
}
TwinePool() : index(0, TwineHash{this}, TwineEq{this}) {
rebuild_index();
}
@ -180,14 +251,28 @@ struct TwinePool {
index.insert(STATIC_TWINE_END + backing.get_index(it));
}
TwineRef find(const Twine& t) const {
TwineRef find(Twine t) const {
if (auto *children = std::get_if<std::vector<TwineRef>>(&t.data)) {
for (TwineRef &c : *children)
c = twine_untag(c);
} else if (auto *sfx = std::get_if<Twine::Suffix>(&t.data)) {
sfx->prefix = twine_untag(sfx->prefix);
}
if (auto it = index.find(t); it != index.end()) {
return *it;
}
return Twine::Null;
}
TwineRef add(Twine t) {
TwineRef add_inner(Twine t) {
// Nodes store content only: strip publicity tags off child handles.
if (auto *children = std::get_if<std::vector<TwineRef>>(&t.data)) {
for (TwineRef &c : *children)
c = twine_untag(c);
} else if (auto *sfx = std::get_if<Twine::Suffix>(&t.data)) {
sfx->prefix = twine_untag(sfx->prefix);
}
if (auto it = index.find(t); it != index.end()) {
return *it;
}
@ -198,6 +283,40 @@ struct TwinePool {
return ref;
}
// Interns an object name and returns a publicity-tagged handle. Leaf
// strings follow the escaped convention: a leading '\' marks a public
// name (stripped from the stored content), '$' a private one. Suffix
// and concat names inherit the prefix/first-child handle's publicity.
TwineRef add(Twine t) {
bool is_public = false;
if (auto *leaf = std::get_if<std::string>(&t.data)) {
assert(!leaf->empty());
if ((*leaf)[0] == '\\') {
is_public = true;
leaf->erase(0, 1);
assert(!leaf->empty());
} else {
assert((*leaf)[0] == '$');
}
} else if (auto *sfx = std::get_if<Twine::Suffix>(&t.data)) {
is_public = twine_is_public(sfx->prefix);
} else if (auto *children = std::get_if<std::vector<TwineRef>>(&t.data)) {
is_public = false;
}
return twine_tag(add_inner(std::move(t)), is_public);
}
TwineRef add(std::string&& s) {
if (s.size()) {
if (s[0] == '\\')
return twine_tag(add(Twine{s.substr(1)}), true);
else
return twine_tag(add(Twine{std::move(s)}), true);
} else {
return Twine::Null;
}
}
size_t size() const { return backing.size(); }
TwineRef concat(std::span<const TwineRef> ids) {
@ -207,31 +326,39 @@ struct TwinePool {
}
TwineRef copy_from(const TwinePool& src, TwineRef ref) {
if (ref == Twine::Null || ref < STATIC_TWINE_END)
if (ref == Twine::Null)
return ref;
const Twine& t = src[ref];
// Statics are shared across pools; preserve the handle's publicity
// tag across the copy in either case.
bool is_public = twine_is_public(ref);
TwineRef untagged = twine_untag(ref);
if (untagged < STATIC_TWINE_END)
return ref;
const Twine& t = src[untagged];
if (t.is_leaf())
return add(Twine{t.leaf()});
return twine_tag(add(Twine{t.leaf()}), is_public);
if (t.is_concat()) {
std::vector<TwineRef> children;
children.reserve(t.children().size());
for (TwineRef c : t.children())
children.push_back(copy_from(src, c));
return add(Twine{std::move(children)});
return twine_tag(add(Twine{std::move(children)}), is_public);
}
if (t.is_suffix())
return add(Twine{Twine::Suffix{copy_from(src, t.suffix().prefix), t.suffix().tail}});
return twine_tag(add(Twine{Twine::Suffix{copy_from(src, t.suffix().prefix), t.suffix().tail}}), is_public);
return Twine::Null;
}
// linear deep scan; only for rare by-string lookups
// linear deep scan; only for rare by-string lookups. Accepts the
// escaped name convention: a leading '\' is stripped and the returned
// handle carries TWINE_PUBLIC_BIT.
TwineRef lookup(std::string_view sv) const;
// Erases every backing node not reachable from `roots`; refs to
// surviving nodes stay valid. Returns the number of erased nodes.
template<typename Pool>
size_t gc(const Pool& roots) {
std::unordered_set<TwineRef> live;
pool<TwineRef> live;
for (TwineRef ref : roots)
mark_live(ref, live);
size_t erased = 0;
@ -248,7 +375,8 @@ struct TwinePool {
return erased;
}
void mark_live(TwineRef ref, std::unordered_set<TwineRef>& live) const {
void mark_live(TwineRef ref, pool<TwineRef>& live) const {
ref = twine_untag(ref);
if (ref == Twine::Null || ref < STATIC_TWINE_END || !live.insert(ref).second)
return;
const Twine& t = (*this)[ref];
@ -441,21 +569,51 @@ struct TwineChildPool {
TwineChildPool(const TwinePool* parent) : parent(parent) {}
static bool is_local(TwineRef ref) {
return ref != Twine::Null && (ref & TWINE_LOCAL_BIT);
}
static bool is_local(TwineRef ref) { return ref.is_local(); }
const Twine& operator[] (TwineRef ref) const {
if (is_local(ref))
return local_[ref & ~TWINE_LOCAL_BIT];
return local_[ref & ~TWINE_TAG_MASK];
return (*parent)[ref];
}
TwineRef add(Twine t) {
TwineRef add_inner(Twine t) {
local_.push_back(std::move(t));
return (local_.size() - 1) | TWINE_LOCAL_BIT;
}
// Local analog of TwinePool::add; see there for the convention.
TwineRef add(Twine t) {
bool is_public = false;
if (auto *leaf = std::get_if<std::string>(&t.data)) {
assert(!leaf->empty());
if ((*leaf)[0] == '\\') {
is_public = true;
leaf->erase(0, 1);
assert(!leaf->empty());
} else {
assert((*leaf)[0] == '$');
}
} else if (auto *sfx = std::get_if<Twine::Suffix>(&t.data)) {
is_public = twine_is_public(sfx->prefix);
} else if (auto *children = std::get_if<std::vector<TwineRef>>(&t.data)) {
is_public = !children->empty() && twine_is_public(children->front());
}
return twine_tag(add_inner(std::move(t)), is_public);
}
// TODO duplicated code
TwineRef add(std::string&& s) {
if (s.size()) {
if (s[0] == '\\')
return twine_tag(add(Twine{s.substr(1)}), true);
else
return twine_tag(add(Twine{std::move(s)}), true);
} else {
return Twine::Null;
}
}
bool empty() const { return local_.empty(); }
// serial phase only; dest must be *parent; resolve() covers refs added since the previous commit
@ -477,19 +635,22 @@ struct TwineChildPool {
TwineRef resolve(TwineRef ref) const {
if (!is_local(ref))
return ref;
return remap_[ref & ~TWINE_LOCAL_BIT];
return twine_tag(remap_[ref & ~TWINE_TAG_MASK], twine_is_public(ref));
}
};
inline TwineRef TwinePool::lookup(std::string_view sv) const {
bool is_public = !sv.empty() && sv[0] == '\\';
if (is_public)
sv.remove_prefix(1);
DeepTwineEq eq{this};
for (TwineRef ref = 0; ref < globals_.size(); ref++)
if (eq(ref, sv))
return ref;
return twine_tag(ref, is_public);
for (auto it = backing.begin(); it != backing.end(); ++it) {
TwineRef ref = STATIC_TWINE_END + backing.get_index(it);
if (eq(ref, sv))
return ref;
return twine_tag(ref, is_public);
}
return Twine::Null;
}
@ -502,9 +663,13 @@ struct TwineSearch {
index.insert(STATIC_TWINE_END + pool->backing.get_index(it));
}
}
// Escaped-name aware, same contract as TwinePool::lookup.
TwineRef find(std::string_view sv) const {
bool is_public = !sv.empty() && sv[0] == '\\';
if (is_public)
sv.remove_prefix(1);
if (auto it = index.find(sv); it != index.end()) {
return *it;
return twine_tag(*it, is_public);
}
return Twine::Null;
}

View file

@ -10,17 +10,28 @@ using namespace RTLIL;
template class CellAdderMixin<Patch>;
Cell* Patch::addCell(TwineRef name, IdString type) {
Cell* Patch::addCell(TwineRef name, TwineRef type) {
cells_.push_back(std::make_unique<Cell>(Cell::ConstructToken{}));
Cell* cell = cells_.back().get();
cell->type = type;
cell->type_impl = type;
cell->module = nullptr;
staged_cell_names_[cell] = name;
return cell;
}
Cell* Patch::addCell(Twine &&name, IdString type) {
// Cell* Patch::addCell(TwineRef name, IdString type) {
// static TwinePool s_pool;
// TwineRef tref = s_pool.lookup(type.str());
// log_assert(tref != Twine::Null);
// return addCell(name, tref);
// }
Cell* Patch::addCell(TwineRef name, Twine &&type) {
return addCell(name, twine_staging.add(std::move(type)));
}
Cell* Patch::addCell(Twine &&name, TwineRef type) {
return addCell(twine_staging.add(std::move(name)), type);
}

View file

@ -74,9 +74,10 @@ public:
RTLIL::Wire *addWire(Twine &&name, int width = 1);
RTLIL::Wire *addWire(Twine &&name, const RTLIL::Wire *other);
RTLIL::Cell *addCell(TwineRef name, RTLIL::IdString type);
RTLIL::Cell *addCell(TwineRef name, TwineRef type);
RTLIL::Cell *addCell(TwineRef name, const RTLIL::Cell *other);
RTLIL::Cell *addCell(Twine &&name, RTLIL::IdString type);
RTLIL::Cell *addCell(Twine &&name, TwineRef type);
RTLIL::Cell *addCell(TwineRef name, Twine &&type);
RTLIL::Cell *addCell(Twine &&name, const RTLIL::Cell *other);
// NEW_ID analog for twine names; see NEW_TWINE in yosys_common.h.