aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--backends/verilog/verilog_backend.cc38
-rw-r--r--kernel/celltypes.h240
-rw-r--r--kernel/rtlil.cc16
3 files changed, 139 insertions, 155 deletions
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index 605616b31..cafc1f3f0 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<RTLIL::IdString, int> auto_name_map;
+std::set<RTLIL::IdString> reg_wires, reg_ct;
-std::set<RTLIL::IdString> 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 23d06f820..6beaa3fed 100644
--- a/kernel/celltypes.h
+++ b/kernel/celltypes.h
@@ -27,195 +27,165 @@
#include <kernel/rtlil.h>
#include <kernel/log.h>
+struct CellType
+{
+ RTLIL::IdString type;
+ std::set<RTLIL::IdString> inputs, outputs;
+ bool maybe_has_internal_state;
+};
+
struct CellTypes
{
- std::set<RTLIL::IdString> cell_types;
- std::vector<const RTLIL::Design*> designs;
+ std::map<RTLIL::IdString, CellType> 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<RTLIL::IdString> &inputs, const std::set<RTLIL::IdString> &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<RTLIL::IdString> 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<RTLIL::IdString> unary_ops = {
+ "$not", "$pos", "$bu0", "$neg",
+ "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
+ "$logic_not", "$slice"
+ };
+
+ std::vector<RTLIL::IdString> 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<RTLIL::IdString>({"$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<char> 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 201c717e4..fdb33ed82 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"));