Refactoring of CellType class
authorClifford Wolf <clifford@clifford.at>
Thu, 14 Aug 2014 13:46:51 +0000 (15:46 +0200)
committerClifford Wolf <clifford@clifford.at>
Thu, 14 Aug 2014 13:46:51 +0000 (15:46 +0200)
backends/verilog/verilog_backend.cc
kernel/celltypes.h
kernel/rtlil.cc

index 605616b31bc3cf2c1ced359e43cfde30b5354240..cafc1f3f058506ee9913e77b704d7b569185b3d0 100644 (file)
@@ -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++) {
index 23d06f8209b33529c601e0bd7c58538be5d93fd4..6beaa3fed329d08165cf2357a7480e00566e1e4e 100644 (file)
 #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)
index 201c717e45225e59eabef37e4015b0af07d4a75c..fdb33ed82b2106912ae2028b69fb8a622910a26a 100644 (file)
@@ -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"));