From 746aac540b815099c6a63077010555369d7fdd5a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 14 Aug 2014 15:46:51 +0200 Subject: Refactoring of CellType class --- backends/verilog/verilog_backend.cc | 38 ++++-- kernel/celltypes.h | 240 ++++++++++++++++-------------------- kernel/rtlil.cc | 16 +-- 3 files changed, 139 insertions(+), 155 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 605616b3..cafc1f3f 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -40,10 +40,8 @@ namespace { bool norename, noattr, attr2comment, noexpr; int auto_name_counter, auto_name_offset, auto_name_digits; std::map auto_name_map; +std::set reg_wires, reg_ct; -std::set reg_wires; - -CellTypes reg_ct; RTLIL::Module *active_module; void reset_auto_counter_id(RTLIL::IdString id, bool may_rename) @@ -314,7 +312,7 @@ void dump_cell_expr_port(FILE *f, RTLIL::Cell *cell, std::string port, bool gen_ std::string cellname(RTLIL::Cell *cell) { - if (!norename && cell->name[0] == '$' && reg_ct.cell_known(cell->type) && cell->hasPort("\\Q")) + if (!norename && cell->name[0] == '$' && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { RTLIL::SigSpec sig = cell->getPort("\\Q"); if (SIZE(sig) != 1 || sig.is_fully_const()) @@ -696,7 +694,7 @@ bool dump_cell_expr(FILE *f, std::string indent, RTLIL::Cell *cell) return true; } - // FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_ + // FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_, $_DLATCHSR_[PN][PN][PN]_ // FIXME: $sr, $dffsr, $dlatch, $memrd, $memwr, $mem, $fsm return false; @@ -937,7 +935,7 @@ void dump_module(FILE *f, std::string indent, RTLIL::Module *module) for (auto &it : module->cells_) { RTLIL::Cell *cell = it.second; - if (!reg_ct.cell_known(cell->type) || !cell->hasPort("\\Q")) + if (!reg_ct.count(cell->type) || !cell->hasPort("\\Q")) continue; RTLIL::SigSpec sig = cell->getPort("\\Q"); @@ -1047,10 +1045,30 @@ struct VerilogBackend : public Backend { bool selected = false; reg_ct.clear(); - reg_ct.setup_stdcells_mem(); - reg_ct.cell_types.insert("$sr"); - reg_ct.cell_types.insert("$dff"); - reg_ct.cell_types.insert("$adff"); + + reg_ct.insert("$dff"); + reg_ct.insert("$adff"); + + reg_ct.insert("$_DFF_N_"); + reg_ct.insert("$_DFF_P_"); + + reg_ct.insert("$_DFF_NN0_"); + reg_ct.insert("$_DFF_NN1_"); + reg_ct.insert("$_DFF_NP0_"); + reg_ct.insert("$_DFF_NP1_"); + reg_ct.insert("$_DFF_PN0_"); + reg_ct.insert("$_DFF_PN1_"); + reg_ct.insert("$_DFF_PP0_"); + reg_ct.insert("$_DFF_PP1_"); + + reg_ct.insert("$_DFFSR_NNN_"); + reg_ct.insert("$_DFFSR_NNP_"); + reg_ct.insert("$_DFFSR_NPN_"); + reg_ct.insert("$_DFFSR_NPP_"); + reg_ct.insert("$_DFFSR_PNN_"); + reg_ct.insert("$_DFFSR_PNP_"); + reg_ct.insert("$_DFFSR_PPN_"); + reg_ct.insert("$_DFFSR_PPP_"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 23d06f82..6beaa3fe 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -27,195 +27,165 @@ #include #include +struct CellType +{ + RTLIL::IdString type; + std::set inputs, outputs; + bool maybe_has_internal_state; +}; + struct CellTypes { - std::set cell_types; - std::vector designs; + std::map cell_types; CellTypes() { } - CellTypes(const RTLIL::Design *design) + CellTypes(RTLIL::Design *design) { setup(design); } - void setup(const RTLIL::Design *design = NULL) + void setup(RTLIL::Design *design = NULL) { if (design) setup_design(design); + setup_internals(); setup_internals_mem(); setup_stdcells(); setup_stdcells_mem(); } - void setup_design(const RTLIL::Design *design) + void setup_type(RTLIL::IdString type, const std::set &inputs, const std::set &outputs, bool maybe_has_internal_state) + { + CellType ct = {type, inputs, outputs, maybe_has_internal_state}; + cell_types[ct.type] = ct; + } + + void setup_module(RTLIL::Module *module) + { + std::set inputs, outputs; + for (auto wire : module->wires()) { + if (wire->port_input) + inputs.insert(wire->name); + if (wire->port_output) + outputs.insert(wire->name); + } + setup_type(module->name, inputs, outputs, true); + } + + void setup_design(RTLIL::Design *design) { - designs.push_back(design); + for (auto module : design->modules()) + setup_module(module); } void setup_internals() { - cell_types.insert("$not"); - cell_types.insert("$pos"); - cell_types.insert("$bu0"); - cell_types.insert("$neg"); - cell_types.insert("$and"); - cell_types.insert("$or"); - cell_types.insert("$xor"); - cell_types.insert("$xnor"); - cell_types.insert("$reduce_and"); - cell_types.insert("$reduce_or"); - cell_types.insert("$reduce_xor"); - cell_types.insert("$reduce_xnor"); - cell_types.insert("$reduce_bool"); - cell_types.insert("$shl"); - cell_types.insert("$shr"); - cell_types.insert("$sshl"); - cell_types.insert("$sshr"); - cell_types.insert("$shift"); - cell_types.insert("$shiftx"); - cell_types.insert("$lt"); - cell_types.insert("$le"); - cell_types.insert("$eq"); - cell_types.insert("$ne"); - cell_types.insert("$eqx"); - cell_types.insert("$nex"); - cell_types.insert("$ge"); - cell_types.insert("$gt"); - cell_types.insert("$add"); - cell_types.insert("$sub"); - cell_types.insert("$mul"); - cell_types.insert("$div"); - cell_types.insert("$mod"); - cell_types.insert("$pow"); - cell_types.insert("$logic_not"); - cell_types.insert("$logic_and"); - cell_types.insert("$logic_or"); - cell_types.insert("$mux"); - cell_types.insert("$pmux"); - cell_types.insert("$slice"); - cell_types.insert("$concat"); - cell_types.insert("$lut"); - cell_types.insert("$assert"); + std::vector unary_ops = { + "$not", "$pos", "$bu0", "$neg", + "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", + "$logic_not", "$slice" + }; + + std::vector binary_ops = { + "$and", "$or", "$xor", "$xnor", + "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", + "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", + "$add", "$sub", "$mul", "$div", "$mod", "$pow", + "$logic_and", "$logic_or", "$concat" + }; + + for (auto type : unary_ops) + setup_type(type, {"\\A"}, {"\\Y"}, false); + + for (auto type : binary_ops) + setup_type(type, {"\\A", "\\B"}, {"\\Y"}, false); + + for (auto type : std::vector({"$mux", "$pmux"})) + setup_type(type, {"\\A", "\\B", "\\S"}, {"\\Y"}, false); + + setup_type("$lut", {"\\I"}, {"\\O"}, false); + setup_type("$assert", {"\\A", "\\EN"}, {}, false); } void setup_internals_mem() { - cell_types.insert("$sr"); - cell_types.insert("$dff"); - cell_types.insert("$dffsr"); - cell_types.insert("$adff"); - cell_types.insert("$dlatch"); - cell_types.insert("$dlatchsr"); - cell_types.insert("$memrd"); - cell_types.insert("$memwr"); - cell_types.insert("$mem"); - cell_types.insert("$fsm"); + setup_type("$sr", {"\\SET", "\\CLR"}, {"\\Q"}, true); + setup_type("$dff", {"\\CLK", "\\D"}, {"\\Q"}, true); + setup_type("$dffsr", {"\\CLK", "\\SET", "\\CLR", "\\D"}, {"\\Q"}, true); + setup_type("$adff", {"\\CLK", "\\ARST", "\\D"}, {"\\Q"}, true); + setup_type("$dlatch", {"\\EN", "\\D"}, {"\\Q"}, true); + setup_type("$dlatchsr", {"\\EN", "\\SET", "\\CLR", "\\D"}, {"\\Q"}, true); + + setup_type("$memrd", {"\\CLK", "\\ADDR"}, {"\\DATA"}, true); + setup_type("$memwr", {"\\CLK", "\\EN", "\\ADDR", "\\DATA"}, {}, true); + setup_type("$mem", {"\\RD_CLK", "\\RD_ADDR", "\\WR_CLK", "\\WR_EN", "\\WR_ADDR", "\\WR_DATA"}, {"\\RD_DATA"}, true); + + setup_type("$fsm", {"\\CLK", "\\ARST", "\\CTRL_IN"}, {"\\CTRL_OUT"}, true); } void setup_stdcells() { - cell_types.insert("$_INV_"); - cell_types.insert("$_AND_"); - cell_types.insert("$_OR_"); - cell_types.insert("$_XOR_"); - cell_types.insert("$_MUX_"); + setup_type("$_INV_", {"\\A"}, {"\\Y"}, false); + setup_type("$_AND_", {"\\A", "\\B"}, {"\\Y"}, false); + setup_type("$_OR_", {"\\A", "\\B"}, {"\\Y"}, false); + setup_type("$_XOR_", {"\\A", "\\B"}, {"\\Y"}, false); + setup_type("$_MUX_", {"\\A", "\\B", "\\S"}, {"\\Y"}, false); } void setup_stdcells_mem() { - cell_types.insert("$_SR_NN_"); - cell_types.insert("$_SR_NP_"); - cell_types.insert("$_SR_PN_"); - cell_types.insert("$_SR_PP_"); - cell_types.insert("$_DFF_N_"); - cell_types.insert("$_DFF_P_"); - cell_types.insert("$_DFF_NN0_"); - cell_types.insert("$_DFF_NN1_"); - cell_types.insert("$_DFF_NP0_"); - cell_types.insert("$_DFF_NP1_"); - cell_types.insert("$_DFF_PN0_"); - cell_types.insert("$_DFF_PN1_"); - cell_types.insert("$_DFF_PP0_"); - cell_types.insert("$_DFF_PP1_"); - cell_types.insert("$_DFFSR_NNN_"); - cell_types.insert("$_DFFSR_NNP_"); - cell_types.insert("$_DFFSR_NPN_"); - cell_types.insert("$_DFFSR_NPP_"); - cell_types.insert("$_DFFSR_PNN_"); - cell_types.insert("$_DFFSR_PNP_"); - cell_types.insert("$_DFFSR_PPN_"); - cell_types.insert("$_DFFSR_PPP_"); - cell_types.insert("$_DLATCH_N_"); - cell_types.insert("$_DLATCH_P_"); - cell_types.insert("$_DLATCHSR_NNN_"); - cell_types.insert("$_DLATCHSR_NNP_"); - cell_types.insert("$_DLATCHSR_NPN_"); - cell_types.insert("$_DLATCHSR_NPP_"); - cell_types.insert("$_DLATCHSR_PNN_"); - cell_types.insert("$_DLATCHSR_PNP_"); - cell_types.insert("$_DLATCHSR_PPN_"); - cell_types.insert("$_DLATCHSR_PPP_"); + std::vector list_np = {'N', 'P'}, list_01 = {'0', '1'}; + + for (auto c1 : list_np) + for (auto c2 : list_np) + setup_type(stringf("$_SR_%c%c_", c1, c2), {"\\S", "\\R"}, {"\\Q"}, true); + + for (auto c1 : list_np) + setup_type(stringf("$_DFF_%c_", c1), {"\\C", "\\D"}, {"\\Q"}, true); + + 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), {"\\C", "\\R", "\\D"}, {"\\Q"}, true); + + 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), {"\\C", "\\S", "\\R", "\\D"}, {"\\Q"}, true); + + for (auto c1 : list_np) + setup_type(stringf("$_DLATCH_%c_", c1), {"\\E", "\\D"}, {"\\Q"}, true); + + 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), {"\\E", "\\S", "\\R", "\\D"}, {"\\Q"}, true); } void clear() { cell_types.clear(); - designs.clear(); } bool cell_known(RTLIL::IdString type) { - if (cell_types.count(type) > 0) - return true; - for (auto design : designs) - if (design->modules_.count(type) > 0) - return true; - return false; + return cell_types.count(type) != 0; } bool cell_output(RTLIL::IdString type, RTLIL::IdString port) { - if (cell_types.count(type) == 0) { - for (auto design : designs) - if (design->modules_.count(type) > 0) { - if (design->modules_.at(type)->wires_.count(port)) - return design->modules_.at(type)->wires_.at(port)->port_output; - return false; - } - return false; - } - - if (port == "\\Y" || port == "\\Q" || port == "\\RD_DATA") - return true; - if (type == "$memrd" && port == "\\DATA") - return true; - if (type == "$fsm" && port == "\\CTRL_OUT") - return true; - if (type == "$lut" && port == "\\O") - return true; - return false; + auto it = cell_types.find(type); + return it != cell_types.end() && it->second.outputs.count(port) != 0; } bool cell_input(RTLIL::IdString type, RTLIL::IdString port) { - if (cell_types.count(type) == 0) { - for (auto design : designs) - if (design->modules_.count(type) > 0) { - if (design->modules_.at(type)->wires_.count(port)) - return design->modules_.at(type)->wires_.at(port)->port_input; - return false; - } - return false; - } - - if (cell_types.count(type) > 0) - return !cell_output(type, port); - - return false; + auto it = cell_types.find(type); + return it != cell_types.end() && it->second.inputs.count(port) != 0; } static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 201c717e..fdb33ed8 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -503,7 +503,7 @@ namespace { cell->type.substr(0, 9) == "$verific$" || cell->type.substr(0, 7) == "$array:" || cell->type.substr(0, 8) == "$extern:") return; - if (cell->type == "$not" || cell->type == "$pos" || cell->type == "$bu0" || cell->type == "$neg") { + if (cell->type.in("$not", "$pos", "$bu0", "$neg")) { param_bool("\\A_SIGNED"); port("\\A", param("\\A_WIDTH")); port("\\Y", param("\\Y_WIDTH")); @@ -511,7 +511,7 @@ namespace { return; } - if (cell->type == "$and" || cell->type == "$or" || cell->type == "$xor" || cell->type == "$xnor") { + if (cell->type.in("$and", "$or", "$xor", "$xnor")) { param_bool("\\A_SIGNED"); param_bool("\\B_SIGNED"); port("\\A", param("\\A_WIDTH")); @@ -521,8 +521,7 @@ namespace { return; } - if (cell->type == "$reduce_and" || cell->type == "$reduce_or" || cell->type == "$reduce_xor" || - cell->type == "$reduce_xnor" || cell->type == "$reduce_bool") { + if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool")) { param_bool("\\A_SIGNED"); port("\\A", param("\\A_WIDTH")); port("\\Y", param("\\Y_WIDTH")); @@ -530,8 +529,7 @@ namespace { return; } - if (cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr" || - cell->type == "$shift" || cell->type == "$shiftx") { + if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx")) { param_bool("\\A_SIGNED"); param_bool("\\B_SIGNED"); port("\\A", param("\\A_WIDTH")); @@ -541,8 +539,7 @@ namespace { return; } - if (cell->type == "$lt" || cell->type == "$le" || cell->type == "$eq" || cell->type == "$ne" || - cell->type == "$eqx" || cell->type == "$nex" || cell->type == "$ge" || cell->type == "$gt") { + if (cell->type.in("$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt")) { param_bool("\\A_SIGNED"); param_bool("\\B_SIGNED"); port("\\A", param("\\A_WIDTH")); @@ -552,8 +549,7 @@ namespace { return; } - if (cell->type == "$add" || cell->type == "$sub" || cell->type == "$mul" || cell->type == "$div" || - cell->type == "$mod" || cell->type == "$pow") { + if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$pow")) { param_bool("\\A_SIGNED"); param_bool("\\B_SIGNED"); port("\\A", param("\\A_WIDTH")); -- cgit v1.2.3