kernel/yosys.h: undef CONST on WIN32
[yosys.git] / kernel / rtlil.cc
index 1091133708e521996bdcf6043065faf91ba7c7a7..1faf376e7fd67fc1c3822c4afcdd5924b96dd3c8 100644 (file)
@@ -22,7 +22,7 @@
 #include "kernel/celltypes.h"
 #include "frontends/verilog/verilog_frontend.h"
 #include "frontends/verilog/preproc.h"
-#include "backends/ilang/ilang_backend.h"
+#include "backends/rtlil/rtlil_backend.h"
 
 #include <string.h>
 #include <algorithm>
@@ -54,8 +54,14 @@ const pool<IdString> &RTLIL::builtin_ff_cell_types() {
                ID($dff),
                ID($dffe),
                ID($dffsr),
+               ID($dffsre),
                ID($adff),
+               ID($adffe),
+               ID($sdff),
+               ID($sdffe),
+               ID($sdffce),
                ID($dlatch),
+               ID($adlatch),
                ID($dlatchsr),
                ID($_DFFE_NN_),
                ID($_DFFE_NP_),
@@ -69,16 +75,102 @@ const pool<IdString> &RTLIL::builtin_ff_cell_types() {
                ID($_DFFSR_PNP_),
                ID($_DFFSR_PPN_),
                ID($_DFFSR_PPP_),
+               ID($_DFFSRE_NNNN_),
+               ID($_DFFSRE_NNNP_),
+               ID($_DFFSRE_NNPN_),
+               ID($_DFFSRE_NNPP_),
+               ID($_DFFSRE_NPNN_),
+               ID($_DFFSRE_NPNP_),
+               ID($_DFFSRE_NPPN_),
+               ID($_DFFSRE_NPPP_),
+               ID($_DFFSRE_PNNN_),
+               ID($_DFFSRE_PNNP_),
+               ID($_DFFSRE_PNPN_),
+               ID($_DFFSRE_PNPP_),
+               ID($_DFFSRE_PPNN_),
+               ID($_DFFSRE_PPNP_),
+               ID($_DFFSRE_PPPN_),
+               ID($_DFFSRE_PPPP_),
+               ID($_DFF_N_),
+               ID($_DFF_P_),
                ID($_DFF_NN0_),
                ID($_DFF_NN1_),
                ID($_DFF_NP0_),
                ID($_DFF_NP1_),
-               ID($_DFF_N_),
                ID($_DFF_PN0_),
                ID($_DFF_PN1_),
                ID($_DFF_PP0_),
                ID($_DFF_PP1_),
-               ID($_DFF_P_),
+               ID($_DFFE_NN0N_),
+               ID($_DFFE_NN0P_),
+               ID($_DFFE_NN1N_),
+               ID($_DFFE_NN1P_),
+               ID($_DFFE_NP0N_),
+               ID($_DFFE_NP0P_),
+               ID($_DFFE_NP1N_),
+               ID($_DFFE_NP1P_),
+               ID($_DFFE_PN0N_),
+               ID($_DFFE_PN0P_),
+               ID($_DFFE_PN1N_),
+               ID($_DFFE_PN1P_),
+               ID($_DFFE_PP0N_),
+               ID($_DFFE_PP0P_),
+               ID($_DFFE_PP1N_),
+               ID($_DFFE_PP1P_),
+               ID($_SDFF_NN0_),
+               ID($_SDFF_NN1_),
+               ID($_SDFF_NP0_),
+               ID($_SDFF_NP1_),
+               ID($_SDFF_PN0_),
+               ID($_SDFF_PN1_),
+               ID($_SDFF_PP0_),
+               ID($_SDFF_PP1_),
+               ID($_SDFFE_NN0N_),
+               ID($_SDFFE_NN0P_),
+               ID($_SDFFE_NN1N_),
+               ID($_SDFFE_NN1P_),
+               ID($_SDFFE_NP0N_),
+               ID($_SDFFE_NP0P_),
+               ID($_SDFFE_NP1N_),
+               ID($_SDFFE_NP1P_),
+               ID($_SDFFE_PN0N_),
+               ID($_SDFFE_PN0P_),
+               ID($_SDFFE_PN1N_),
+               ID($_SDFFE_PN1P_),
+               ID($_SDFFE_PP0N_),
+               ID($_SDFFE_PP0P_),
+               ID($_SDFFE_PP1N_),
+               ID($_SDFFE_PP1P_),
+               ID($_SDFFCE_NN0N_),
+               ID($_SDFFCE_NN0P_),
+               ID($_SDFFCE_NN1N_),
+               ID($_SDFFCE_NN1P_),
+               ID($_SDFFCE_NP0N_),
+               ID($_SDFFCE_NP0P_),
+               ID($_SDFFCE_NP1N_),
+               ID($_SDFFCE_NP1P_),
+               ID($_SDFFCE_PN0N_),
+               ID($_SDFFCE_PN0P_),
+               ID($_SDFFCE_PN1N_),
+               ID($_SDFFCE_PN1P_),
+               ID($_SDFFCE_PP0N_),
+               ID($_SDFFCE_PP0P_),
+               ID($_SDFFCE_PP1N_),
+               ID($_SDFFCE_PP1P_),
+               ID($_SR_NN_),
+               ID($_SR_NP_),
+               ID($_SR_PN_),
+               ID($_SR_PP_),
+               ID($_DLATCH_N_),
+               ID($_DLATCH_P_),
+               ID($_DLATCH_NN0_),
+               ID($_DLATCH_NN1_),
+               ID($_DLATCH_NP0_),
+               ID($_DLATCH_NP1_),
+               ID($_DLATCH_PN0_),
+               ID($_DLATCH_PN1_),
+               ID($_DLATCH_PP0_),
+               ID($_DLATCH_PP1_),
                ID($_DLATCHSR_NNN_),
                ID($_DLATCHSR_NNP_),
                ID($_DLATCHSR_NPN_),
@@ -87,8 +179,6 @@ const pool<IdString> &RTLIL::builtin_ff_cell_types() {
                ID($_DLATCHSR_PNP_),
                ID($_DLATCHSR_PPN_),
                ID($_DLATCHSR_PPP_),
-               ID($_DLATCH_N_),
-               ID($_DLATCH_P_),
                ID($_FF_),
        };
        return res;
@@ -319,7 +409,7 @@ void RTLIL::AttrObject::set_strpool_attribute(RTLIL::IdString id, const pool<str
                        attrval += "|";
                attrval += s;
        }
-       attributes[id] = RTLIL::Const(attrval);
+       set_string_attribute(id, attrval);
 }
 
 void RTLIL::AttrObject::add_strpool_attribute(RTLIL::IdString id, const pool<string> &data)
@@ -334,11 +424,27 @@ pool<string> RTLIL::AttrObject::get_strpool_attribute(RTLIL::IdString id) const
 {
        pool<string> data;
        if (attributes.count(id) != 0)
-               for (auto s : split_tokens(attributes.at(id).decode_string(), "|"))
+               for (auto s : split_tokens(get_string_attribute(id), "|"))
                        data.insert(s);
        return data;
 }
 
+void RTLIL::AttrObject::set_hdlname_attribute(const vector<string> &hierarchy)
+{
+       string attrval;
+       for (const auto &ident : hierarchy) {
+               if (!attrval.empty())
+                       attrval += " ";
+               attrval += ident;
+       }
+       set_string_attribute(ID::hdlname, attrval);
+}
+
+vector<string> RTLIL::AttrObject::get_hdlname_attribute() const
+{
+       return split_tokens(get_string_attribute(ID::hdlname), " ");
+}
+
 bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name) const
 {
        if (full_selection)
@@ -817,7 +923,7 @@ namespace {
                void error(int linenr)
                {
                        std::stringstream buf;
-                       ILANG_BACKEND::dump_cell(buf, "  ", cell);
+                       RTLIL_BACKEND::dump_cell(buf, "  ", cell);
 
                        log_error("Found error in internal cell %s%s%s (%s) at %s:%d:\n%s",
                                        module ? module->name.c_str() : "", module ? "." : "",
@@ -929,7 +1035,11 @@ namespace {
                        }
 
                        if (cell->type.in(ID($shift), ID($shiftx))) {
-                               param_bool(ID::A_SIGNED);
+                               if (cell->type == ID($shiftx)) {
+                                       param_bool(ID::A_SIGNED, /*expected=*/false);
+                               } else {
+                                       param_bool(ID::A_SIGNED);
+                               }
                                param_bool(ID::B_SIGNED);
                                port(ID::A, param(ID::A_WIDTH));
                                port(ID::B, param(ID::B_WIDTH));
@@ -1123,6 +1233,21 @@ namespace {
                                return;
                        }
 
+                       if (cell->type == ID($dffsre)) {
+                               param_bool(ID::CLK_POLARITY);
+                               param_bool(ID::SET_POLARITY);
+                               param_bool(ID::CLR_POLARITY);
+                               param_bool(ID::EN_POLARITY);
+                               port(ID::CLK, 1);
+                               port(ID::EN, 1);
+                               port(ID::SET, param(ID::WIDTH));
+                               port(ID::CLR, param(ID::WIDTH));
+                               port(ID::D, param(ID::WIDTH));
+                               port(ID::Q, param(ID::WIDTH));
+                               check_expected();
+                               return;
+                       }
+
                        if (cell->type == ID($adff)) {
                                param_bool(ID::CLK_POLARITY);
                                param_bool(ID::ARST_POLARITY);
@@ -1135,6 +1260,46 @@ namespace {
                                return;
                        }
 
+                       if (cell->type == ID($sdff)) {
+                               param_bool(ID::CLK_POLARITY);
+                               param_bool(ID::SRST_POLARITY);
+                               param_bits(ID::SRST_VALUE, param(ID::WIDTH));
+                               port(ID::CLK, 1);
+                               port(ID::SRST, 1);
+                               port(ID::D, param(ID::WIDTH));
+                               port(ID::Q, param(ID::WIDTH));
+                               check_expected();
+                               return;
+                       }
+
+                       if (cell->type.in(ID($sdffe), ID($sdffce))) {
+                               param_bool(ID::CLK_POLARITY);
+                               param_bool(ID::EN_POLARITY);
+                               param_bool(ID::SRST_POLARITY);
+                               param_bits(ID::SRST_VALUE, param(ID::WIDTH));
+                               port(ID::CLK, 1);
+                               port(ID::EN, 1);
+                               port(ID::SRST, 1);
+                               port(ID::D, param(ID::WIDTH));
+                               port(ID::Q, param(ID::WIDTH));
+                               check_expected();
+                               return;
+                       }
+
+                       if (cell->type == ID($adffe)) {
+                               param_bool(ID::CLK_POLARITY);
+                               param_bool(ID::EN_POLARITY);
+                               param_bool(ID::ARST_POLARITY);
+                               param_bits(ID::ARST_VALUE, param(ID::WIDTH));
+                               port(ID::CLK, 1);
+                               port(ID::EN, 1);
+                               port(ID::ARST, 1);
+                               port(ID::D, param(ID::WIDTH));
+                               port(ID::Q, param(ID::WIDTH));
+                               check_expected();
+                               return;
+                       }
+
                        if (cell->type == ID($dlatch)) {
                                param_bool(ID::EN_POLARITY);
                                port(ID::EN, 1);
@@ -1144,6 +1309,18 @@ namespace {
                                return;
                        }
 
+                       if (cell->type == ID($adlatch)) {
+                               param_bool(ID::EN_POLARITY);
+                               param_bool(ID::ARST_POLARITY);
+                               param_bits(ID::ARST_VALUE, param(ID::WIDTH));
+                               port(ID::EN, 1);
+                               port(ID::ARST, 1);
+                               port(ID::D, param(ID::WIDTH));
+                               port(ID::Q, param(ID::WIDTH));
+                               check_expected();
+                               return;
+                       }
+
                        if (cell->type == ID($dlatchsr)) {
                                param_bool(ID::EN_POLARITY);
                                param_bool(ID::SET_POLARITY);
@@ -1335,49 +1512,69 @@ namespace {
                        if (cell->type == ID($_MUX8_))  { port(ID::A,1); port(ID::B,1); port(ID::C,1); port(ID::D,1); port(ID::E,1); port(ID::F,1); port(ID::G,1); port(ID::H,1); port(ID::S,1); port(ID::T,1); port(ID::U,1); port(ID::Y,1); check_expected(); return; }
                        if (cell->type == ID($_MUX16_)) { port(ID::A,1); port(ID::B,1); port(ID::C,1); port(ID::D,1); port(ID::E,1); port(ID::F,1); port(ID::G,1); port(ID::H,1); port(ID::I,1); port(ID::J,1); port(ID::K,1); port(ID::L,1); port(ID::M,1); port(ID::N,1); port(ID::O,1); port(ID::P,1); port(ID::S,1); port(ID::T,1); port(ID::U,1); port(ID::V,1); port(ID::Y,1); check_expected(); return; }
 
-                       if (cell->type == ID($_SR_NN_)) { port(ID::S,1); port(ID::R,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_SR_NP_)) { port(ID::S,1); port(ID::R,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_SR_PN_)) { port(ID::S,1); port(ID::R,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_SR_PP_)) { port(ID::S,1); port(ID::R,1); port(ID::Q,1); check_expected(); return; }
-
-                       if (cell->type == ID($_FF_))    { port(ID::D,1); port(ID::Q,1); check_expected();  return; }
-                       if (cell->type == ID($_DFF_N_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); check_expected(); return; }
-                       if (cell->type == ID($_DFF_P_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); check_expected(); return; }
-
-                       if (cell->type == ID($_DFFE_NN_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::E,1); check_expected(); return; }
-                       if (cell->type == ID($_DFFE_NP_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::E,1); check_expected(); return; }
-                       if (cell->type == ID($_DFFE_PN_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::E,1); check_expected(); return; }
-                       if (cell->type == ID($_DFFE_PP_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::E,1); check_expected(); return; }
-
-                       if (cell->type == ID($_DFF_NN0_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; }
-                       if (cell->type == ID($_DFF_NN1_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; }
-                       if (cell->type == ID($_DFF_NP0_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; }
-                       if (cell->type == ID($_DFF_NP1_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; }
-                       if (cell->type == ID($_DFF_PN0_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; }
-                       if (cell->type == ID($_DFF_PN1_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; }
-                       if (cell->type == ID($_DFF_PP0_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; }
-                       if (cell->type == ID($_DFF_PP1_)) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; }
-
-                       if (cell->type == ID($_DFFSR_NNN_)) { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DFFSR_NNP_)) { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DFFSR_NPN_)) { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DFFSR_NPP_)) { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DFFSR_PNN_)) { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DFFSR_PNP_)) { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DFFSR_PPN_)) { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DFFSR_PPP_)) { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-
-                       if (cell->type == ID($_DLATCH_N_)) { port(ID::E,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DLATCH_P_)) { port(ID::E,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-
-                       if (cell->type == ID($_DLATCHSR_NNN_)) { port(ID::E,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DLATCHSR_NNP_)) { port(ID::E,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DLATCHSR_NPN_)) { port(ID::E,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DLATCHSR_NPP_)) { port(ID::E,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DLATCHSR_PNN_)) { port(ID::E,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DLATCHSR_PNP_)) { port(ID::E,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DLATCHSR_PPN_)) { port(ID::E,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
-                       if (cell->type == ID($_DLATCHSR_PPP_)) { port(ID::E,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
+                       if (cell->type.in(ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_)))
+                               { port(ID::S,1); port(ID::R,1); port(ID::Q,1); check_expected(); return; }
+
+                       if (cell->type == ID($_FF_)) { port(ID::D,1); port(ID::Q,1); check_expected();  return; }
+
+                       if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
+                               { port(ID::D,1); port(ID::Q,1); port(ID::C,1); check_expected(); return; }
+
+                       if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
+                               { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::E,1); check_expected(); return; }
+
+                       if (cell->type.in(
+                                       ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
+                                       ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
+                               { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; }
+
+                       if (cell->type.in(
+                                       ID($_DFFE_NN0N_), ID($_DFFE_NN0P_), ID($_DFFE_NN1N_), ID($_DFFE_NN1P_),
+                                       ID($_DFFE_NP0N_), ID($_DFFE_NP0P_), ID($_DFFE_NP1N_), ID($_DFFE_NP1P_),
+                                       ID($_DFFE_PN0N_), ID($_DFFE_PN0P_), ID($_DFFE_PN1N_), ID($_DFFE_PN1P_),
+                                       ID($_DFFE_PP0N_), ID($_DFFE_PP0P_), ID($_DFFE_PP1N_), ID($_DFFE_PP1P_)))
+                               { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); port(ID::E,1); check_expected(); return; }
+
+                       if (cell->type.in(
+                                       ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
+                                       ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_)))
+                               { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
+
+                       if (cell->type.in(
+                                       ID($_DFFSRE_NNNN_), ID($_DFFSRE_NNNP_), ID($_DFFSRE_NNPN_), ID($_DFFSRE_NNPP_),
+                                       ID($_DFFSRE_NPNN_), ID($_DFFSRE_NPNP_), ID($_DFFSRE_NPPN_), ID($_DFFSRE_NPPP_),
+                                       ID($_DFFSRE_PNNN_), ID($_DFFSRE_PNNP_), ID($_DFFSRE_PNPN_), ID($_DFFSRE_PNPP_),
+                                       ID($_DFFSRE_PPNN_), ID($_DFFSRE_PPNP_), ID($_DFFSRE_PPPN_), ID($_DFFSRE_PPPP_)))
+                               { port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::E,1); port(ID::Q,1); check_expected(); return; }
+
+                       if (cell->type.in(
+                                       ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_),
+                                       ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_)))
+                               { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); check_expected(); return; }
+
+                       if (cell->type.in(
+                                       ID($_SDFFE_NN0N_), ID($_SDFFE_NN0P_), ID($_SDFFE_NN1N_), ID($_SDFFE_NN1P_),
+                                       ID($_SDFFE_NP0N_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1N_), ID($_SDFFE_NP1P_),
+                                       ID($_SDFFE_PN0N_), ID($_SDFFE_PN0P_), ID($_SDFFE_PN1N_), ID($_SDFFE_PN1P_),
+                                       ID($_SDFFE_PP0N_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1N_), ID($_SDFFE_PP1P_),
+                                       ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NN1P_),
+                                       ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1N_), ID($_SDFFCE_NP1P_),
+                                       ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PN1P_),
+                                       ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1N_), ID($_SDFFCE_PP1P_)))
+                               { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); port(ID::E,1); check_expected(); return; }
+
+                       if (cell->type.in(ID($_DLATCH_N_), ID($_DLATCH_P_)))
+                               { port(ID::E,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
+
+                       if (cell->type.in(
+                                       ID($_DLATCH_NN0_), ID($_DLATCH_NN1_), ID($_DLATCH_NP0_), ID($_DLATCH_NP1_),
+                                       ID($_DLATCH_PN0_), ID($_DLATCH_PN1_), ID($_DLATCH_PP0_), ID($_DLATCH_PP1_)))
+                               { port(ID::E,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
+
+                       if (cell->type.in(
+                                       ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
+                                       ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_)))
+                               { port(ID::E,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
 
                        error(__LINE__);
                }
@@ -1520,13 +1717,13 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod) const
                new_mod->addWire(it.first, it.second);
 
        for (auto &it : memories)
-               new_mod->memories[it.first] = new RTLIL::Memory(*it.second);
+               new_mod->addMemory(it.first, it.second);
 
        for (auto &it : cells_)
                new_mod->addCell(it.first, it.second);
 
        for (auto &it : processes)
-               new_mod->processes[it.first] = it.second->clone();
+               new_mod->addProcess(it.first, it.second);
 
        struct RewriteSigSpecWorker
        {
@@ -1629,7 +1826,7 @@ void RTLIL::Module::remove(const pool<RTLIL::Wire*> &wires)
                        sig.pack();
                        for (auto &c : sig.chunks_)
                                if (c.wire != NULL && wires_p->count(c.wire)) {
-                                       c.wire = module->addWire(NEW_ID, c.width);
+                                       c.wire = module->addWire(stringf("$delete_wire$%d", autoidx++), c.width);
                                        c.offset = 0;
                                }
                }
@@ -1897,6 +2094,14 @@ RTLIL::Memory *RTLIL::Module::addMemory(RTLIL::IdString name, const RTLIL::Memor
        return mem;
 }
 
+RTLIL::Process *RTLIL::Module::addProcess(RTLIL::IdString name, const RTLIL::Process *other)
+{
+       RTLIL::Process *proc = other->clone();
+       proc->name = name;
+       processes[name] = proc;
+       return proc;
+}
+
 #define DEF_METHOD(_func, _y_size, _type) \
        RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \
                RTLIL::Cell *cell = addCell(name, _type);           \
@@ -2275,6 +2480,25 @@ RTLIL::Cell* RTLIL::Module::addDffsr(RTLIL::IdString name, const RTLIL::SigSpec
        return cell;
 }
 
+RTLIL::Cell* RTLIL::Module::addDffsre(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, 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 clk_polarity, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, ID($dffsre));
+       cell->parameters[ID::CLK_POLARITY] = clk_polarity;
+       cell->parameters[ID::EN_POLARITY] = en_polarity;
+       cell->parameters[ID::SET_POLARITY] = set_polarity;
+       cell->parameters[ID::CLR_POLARITY] = clr_polarity;
+       cell->parameters[ID::WIDTH] = sig_q.size();
+       cell->setPort(ID::CLK, sig_clk);
+       cell->setPort(ID::EN, sig_en);
+       cell->setPort(ID::SET, sig_set);
+       cell->setPort(ID::CLR, sig_clr);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
 RTLIL::Cell* RTLIL::Module::addAdff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
                RTLIL::Const arst_value, bool clk_polarity, bool arst_polarity, const std::string &src)
 {
@@ -2291,6 +2515,76 @@ RTLIL::Cell* RTLIL::Module::addAdff(RTLIL::IdString name, const RTLIL::SigSpec &
        return cell;
 }
 
+RTLIL::Cell* RTLIL::Module::addAdffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+               RTLIL::Const arst_value, bool clk_polarity, bool en_polarity, bool arst_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, ID($adffe));
+       cell->parameters[ID::CLK_POLARITY] = clk_polarity;
+       cell->parameters[ID::EN_POLARITY] = en_polarity;
+       cell->parameters[ID::ARST_POLARITY] = arst_polarity;
+       cell->parameters[ID::ARST_VALUE] = arst_value;
+       cell->parameters[ID::WIDTH] = sig_q.size();
+       cell->setPort(ID::CLK, sig_clk);
+       cell->setPort(ID::EN, sig_en);
+       cell->setPort(ID::ARST, sig_arst);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
+RTLIL::Cell* RTLIL::Module::addSdff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+               RTLIL::Const srst_value, bool clk_polarity, bool srst_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, ID($sdff));
+       cell->parameters[ID::CLK_POLARITY] = clk_polarity;
+       cell->parameters[ID::SRST_POLARITY] = srst_polarity;
+       cell->parameters[ID::SRST_VALUE] = srst_value;
+       cell->parameters[ID::WIDTH] = sig_q.size();
+       cell->setPort(ID::CLK, sig_clk);
+       cell->setPort(ID::SRST, sig_srst);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
+RTLIL::Cell* RTLIL::Module::addSdffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+               RTLIL::Const srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, ID($sdffe));
+       cell->parameters[ID::CLK_POLARITY] = clk_polarity;
+       cell->parameters[ID::EN_POLARITY] = en_polarity;
+       cell->parameters[ID::SRST_POLARITY] = srst_polarity;
+       cell->parameters[ID::SRST_VALUE] = srst_value;
+       cell->parameters[ID::WIDTH] = sig_q.size();
+       cell->setPort(ID::CLK, sig_clk);
+       cell->setPort(ID::EN, sig_en);
+       cell->setPort(ID::SRST, sig_srst);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
+RTLIL::Cell* RTLIL::Module::addSdffce(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+               RTLIL::Const srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, ID($sdffce));
+       cell->parameters[ID::CLK_POLARITY] = clk_polarity;
+       cell->parameters[ID::EN_POLARITY] = en_polarity;
+       cell->parameters[ID::SRST_POLARITY] = srst_polarity;
+       cell->parameters[ID::SRST_VALUE] = srst_value;
+       cell->parameters[ID::WIDTH] = sig_q.size();
+       cell->setPort(ID::CLK, sig_clk);
+       cell->setPort(ID::EN, sig_en);
+       cell->setPort(ID::SRST, sig_srst);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
 RTLIL::Cell* RTLIL::Module::addDlatch(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, const std::string &src)
 {
        RTLIL::Cell *cell = addCell(name, ID($dlatch));
@@ -2303,6 +2597,22 @@ RTLIL::Cell* RTLIL::Module::addDlatch(RTLIL::IdString name, const RTLIL::SigSpec
        return cell;
 }
 
+RTLIL::Cell* RTLIL::Module::addAdlatch(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+               RTLIL::Const arst_value, bool en_polarity, bool arst_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, ID($adlatch));
+       cell->parameters[ID::EN_POLARITY] = en_polarity;
+       cell->parameters[ID::ARST_POLARITY] = arst_polarity;
+       cell->parameters[ID::ARST_VALUE] = arst_value;
+       cell->parameters[ID::WIDTH] = sig_q.size();
+       cell->setPort(ID::EN, sig_en);
+       cell->setPort(ID::ARST, sig_arst);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
 RTLIL::Cell* RTLIL::Module::addDlatchsr(RTLIL::IdString 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, bool set_polarity, bool clr_polarity, const std::string &src)
 {
@@ -2320,6 +2630,17 @@ RTLIL::Cell* RTLIL::Module::addDlatchsr(RTLIL::IdString name, const RTLIL::SigSp
        return cell;
 }
 
+RTLIL::Cell* RTLIL::Module::addSrGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr,
+               const RTLIL::SigSpec &sig_q, bool set_polarity, bool clr_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, stringf("$_SR_%c%c_", set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N'));
+       cell->setPort(ID::S, sig_set);
+       cell->setPort(ID::R, sig_clr);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
 RTLIL::Cell* RTLIL::Module::addFfGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src)
 {
        RTLIL::Cell *cell = addCell(name, ID($_FF_));
@@ -2363,6 +2684,20 @@ RTLIL::Cell* RTLIL::Module::addDffsrGate(RTLIL::IdString name, const RTLIL::SigS
        return cell;
 }
 
+RTLIL::Cell* RTLIL::Module::addDffsreGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, 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 clk_polarity, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, stringf("$_DFFSRE_%c%c%c%c_", clk_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
+       cell->setPort(ID::C, sig_clk);
+       cell->setPort(ID::S, sig_set);
+       cell->setPort(ID::R, sig_clr);
+       cell->setPort(ID::E, sig_en);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
 RTLIL::Cell* RTLIL::Module::addAdffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
                bool arst_value, bool clk_polarity, bool arst_polarity, const std::string &src)
 {
@@ -2375,6 +2710,57 @@ RTLIL::Cell* RTLIL::Module::addAdffGate(RTLIL::IdString name, const RTLIL::SigSp
        return cell;
 }
 
+RTLIL::Cell* RTLIL::Module::addAdffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+               bool arst_value, bool clk_polarity, bool en_polarity, bool arst_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, stringf("$_DFFE_%c%c%c%c_", clk_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0', en_polarity ? 'P' : 'N'));
+       cell->setPort(ID::C, sig_clk);
+       cell->setPort(ID::R, sig_arst);
+       cell->setPort(ID::E, sig_en);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
+RTLIL::Cell* RTLIL::Module::addSdffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+               bool srst_value, bool clk_polarity, bool srst_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, stringf("$_SDFF_%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0'));
+       cell->setPort(ID::C, sig_clk);
+       cell->setPort(ID::R, sig_srst);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
+RTLIL::Cell* RTLIL::Module::addSdffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+               bool srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, stringf("$_SDFFE_%c%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0', en_polarity ? 'P' : 'N'));
+       cell->setPort(ID::C, sig_clk);
+       cell->setPort(ID::R, sig_srst);
+       cell->setPort(ID::E, sig_en);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
+RTLIL::Cell* RTLIL::Module::addSdffceGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+               bool srst_value, bool clk_polarity, bool en_polarity, bool srst_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, stringf("$_SDFFCE_%c%c%c%c_", clk_polarity ? 'P' : 'N', srst_polarity ? 'P' : 'N', srst_value ? '1' : '0', en_polarity ? 'P' : 'N'));
+       cell->setPort(ID::C, sig_clk);
+       cell->setPort(ID::R, sig_srst);
+       cell->setPort(ID::E, sig_en);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
 RTLIL::Cell* RTLIL::Module::addDlatchGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity, const std::string &src)
 {
        RTLIL::Cell *cell = addCell(name, stringf("$_DLATCH_%c_", en_polarity ? 'P' : 'N'));
@@ -2385,6 +2771,18 @@ RTLIL::Cell* RTLIL::Module::addDlatchGate(RTLIL::IdString name, const RTLIL::Sig
        return cell;
 }
 
+RTLIL::Cell* RTLIL::Module::addAdlatchGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+               bool arst_value, bool en_polarity, bool arst_polarity, const std::string &src)
+{
+       RTLIL::Cell *cell = addCell(name, stringf("$_DLATCH_%c%c%c_", en_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0'));
+       cell->setPort(ID::E, sig_en);
+       cell->setPort(ID::R, sig_arst);
+       cell->setPort(ID::D, sig_d);
+       cell->setPort(ID::Q, sig_q);
+       cell->set_src_attribute(src);
+       return cell;
+}
+
 RTLIL::Cell* RTLIL::Module::addDlatchsrGate(RTLIL::IdString 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, bool set_polarity, bool clr_polarity, const std::string &src)
 {