Added $_MUX4_, $_MUX8_, and $_MUX16_ cell types
authorClifford Wolf <clifford@clifford.at>
Sun, 5 Apr 2015 07:45:14 +0000 (09:45 +0200)
committerClifford Wolf <clifford@clifford.at>
Sun, 5 Apr 2015 07:45:14 +0000 (09:45 +0200)
kernel/celltypes.h
kernel/rtlil.cc
passes/abc/abc.cc
techlibs/common/simcells.v

index 533c370fe24313d3beacf300e47c0cedc4d314e2..afdbda5d7e8d922e392b3257a077eb4c5a6e1f54 100644 (file)
@@ -95,7 +95,6 @@ struct CellTypes
                        "$add", "$sub", "$mul", "$div", "$mod", "$pow",
                        "$logic_and", "$logic_or", "$concat", "$macc"
                };
-
                IdString A = "\\A", B = "\\B", S = "\\S", Y = "\\Y";
                IdString P = "\\P", G = "\\G", C = "\\C", X = "\\X";
                IdString BI = "\\BI", CI = "\\CI", CO = "\\CO", EN = "\\EN";
@@ -144,7 +143,13 @@ struct CellTypes
 
        void setup_stdcells()
        {
-               IdString A = "\\A", B = "\\B", C = "\\C", D = "\\D", S = "\\S", Y = "\\Y";
+               IdString A = "\\A", B = "\\B", C = "\\C", D = "\\D";
+               IdString E = "\\E", F = "\\F", G = "\\G", H = "\\H";
+               IdString I = "\\I", J = "\\J", K = "\\K", L = "\\L";
+               IdString M = "\\I", N = "\\N", O = "\\O", P = "\\P";
+               IdString S = "\\S", T = "\\T", U = "\\U", V = "\\V";
+               IdString Y = "\\Y";
+
                setup_type("$_BUF_", {A}, {Y}, true);
                setup_type("$_NOT_", {A}, {Y}, true);
                setup_type("$_AND_", {A, B}, {Y}, true);
@@ -154,6 +159,9 @@ struct CellTypes
                setup_type("$_XOR_", {A, B}, {Y}, true);
                setup_type("$_XNOR_", {A, B}, {Y}, true);
                setup_type("$_MUX_", {A, B, S}, {Y}, true);
+               setup_type("$_MUX4_", {A, B, C, D, S, T}, {Y}, true);
+               setup_type("$_MUX8_", {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true);
+               setup_type("$_MUX16_", {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true);
                setup_type("$_AOI3_", {A, B, C}, {Y}, true);
                setup_type("$_OAI3_", {A, B, C}, {Y}, true);
                setup_type("$_AOI4_", {A, B, C, D}, {Y}, true);
index adf89a24510518464ac34dd8e79ffd6f6cd64f11..6de5846f93ae2fb23d590cf7d68455717681ecc0 100644 (file)
@@ -970,6 +970,10 @@ namespace {
                        if (cell->type == "$_AOI4_") { check_gate("ABCDY"); return; }
                        if (cell->type == "$_OAI4_") { check_gate("ABCDY"); return; }
 
+                       if (cell->type == "$_MUX4_")  { check_gate("ABCDSTY"); return; }
+                       if (cell->type == "$_MUX8_")  { check_gate("ABCDEFGHSTUY"); return; }
+                       if (cell->type == "$_MUX16_") { check_gate("ABCDEFGHIJKLMNOPSTUVY"); return; }
+
                        if (cell->type == "$_SR_NN_") { check_gate("SRQ"); return; }
                        if (cell->type == "$_SR_NP_") { check_gate("SRQ"); return; }
                        if (cell->type == "$_SR_PN_") { check_gate("SRQ"); return; }
index 8cd0211c109b36bd5732b2c07a50febcc98a629d..81cf2bd4cf3958f44a21f156b9d8bb01beac45de 100644 (file)
@@ -90,6 +90,10 @@ struct gate_t
        RTLIL::SigBit bit;
 };
 
+bool map_mux4;
+bool map_mux8;
+bool map_mux16;
+
 bool markgroups;
 int map_autoidx;
 SigMap assign_map;
@@ -844,6 +848,12 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D));     PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_AOI4_"));
                fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D));     PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_OAI4_"));
                fprintf(f, "GATE MUX  %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_MUX_"));
+               if (map_mux4)
+                       fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*get_cell_cost("$_MUX_"));
+               if (map_mux8)
+                       fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*get_cell_cost("$_MUX_"));
+               if (map_mux16)
+                       fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_"));
                fclose(f);
 
                if (lut_mode) {
@@ -934,6 +944,64 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                                        design->select(module, cell);
                                        continue;
                                }
+                               if (c->type == "\\MUX4") {
+                                       RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX4_");
+                                       if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
+                                       cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
+                                       cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
+                                       cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
+                                       cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
+                                       cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
+                                       cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
+                                       cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
+                                       design->select(module, cell);
+                                       continue;
+                               }
+                               if (c->type == "\\MUX8") {
+                                       RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX8_");
+                                       if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
+                                       cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
+                                       cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
+                                       cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
+                                       cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
+                                       cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)]));
+                                       cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)]));
+                                       cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)]));
+                                       cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)]));
+                                       cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
+                                       cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
+                                       cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)]));
+                                       cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
+                                       design->select(module, cell);
+                                       continue;
+                               }
+                               if (c->type == "\\MUX16") {
+                                       RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX16_");
+                                       if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
+                                       cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
+                                       cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
+                                       cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
+                                       cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
+                                       cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)]));
+                                       cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)]));
+                                       cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)]));
+                                       cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)]));
+                                       cell->setPort("\\I", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\I").as_wire()->name)]));
+                                       cell->setPort("\\J", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\J").as_wire()->name)]));
+                                       cell->setPort("\\K", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\K").as_wire()->name)]));
+                                       cell->setPort("\\L", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\L").as_wire()->name)]));
+                                       cell->setPort("\\M", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\M").as_wire()->name)]));
+                                       cell->setPort("\\N", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\N").as_wire()->name)]));
+                                       cell->setPort("\\O", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\O").as_wire()->name)]));
+                                       cell->setPort("\\P", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\P").as_wire()->name)]));
+                                       cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
+                                       cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
+                                       cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)]));
+                                       cell->setPort("\\V", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\V").as_wire()->name)]));
+                                       cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
+                                       design->select(module, cell);
+                                       continue;
+                               }
                                if (c->type == "\\AOI3" || c->type == "\\OAI3") {
                                        RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
                                        if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
@@ -1150,6 +1218,10 @@ struct AbcPass : public Pass {
                log("        the area cost doubles with each additional input bit. the delay cost\n");
                log("        is still constant for all lut widths.\n");
                log("\n");
+               // log("    -mux4, -mux8, -mux16\n");
+               // log("        try to extract 4-input, 8-input, and/or 16-input muxes\n");
+               // log("        (ignored when used with -liberty or -lut)\n");
+               // log("\n");
                log("    -dff\n");
                log("        also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n");
                log("        clock domains are automatically partitioned in clock domains and each\n");
@@ -1197,6 +1269,10 @@ struct AbcPass : public Pass {
                int lut_mode = 0, lut_mode2 = 0;
                markgroups = false;
 
+               map_mux4 = false;
+               map_mux8 = false;
+               map_mux16 = false;
+
 #ifdef _WIN32
                if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe"))
                        exe_file = proc_self_dirname() + "..\\yosys-abc";
@@ -1248,6 +1324,18 @@ struct AbcPass : public Pass {
                                }
                                continue;
                        }
+                       if (arg == "-mux4") {
+                               map_mux4 = true;
+                               continue;
+                       }
+                       if (arg == "-mux8") {
+                               map_mux8 = true;
+                               continue;
+                       }
+                       if (arg == "-mux16") {
+                               map_mux16 = true;
+                               continue;
+                       }
                        if (arg == "-fast") {
                                fast_mode = true;
                                continue;
index eb62d7830786bc441bab4d5d75945c88b8778cb1..d85cf5adc5acef8b45ee280266bf5bd7b5a6df1d 100644 (file)
@@ -79,6 +79,35 @@ output Y;
 assign Y = S ? B : A;
 endmodule
 
+module \$_MUX4_ (A, B, C, D, S, T, Y);
+input A, B, C, D, S, T;
+output Y;
+assign Y = T ? (S ? D : C) :
+               (S ? B : A);
+endmodule
+
+module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y);
+input A, B, C, D, E, F, G, H, S, T, U;
+output Y;
+assign Y = U ? T ? (S ? H : G) :
+                   (S ? F : E) :
+               T ? (S ? D : C) :
+                   (S ? B : A);
+endmodule
+
+module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y);
+input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V;
+output Y;
+assign Y = V ? U ? T ? (S ? P : O) :
+                       (S ? N : M) :
+                   T ? (S ? L : K) :
+                       (S ? J : I) :
+               U ? T ? (S ? H : G) :
+                       (S ? F : E) :
+                   T ? (S ? D : C) :
+                       (S ? B : A);
+endmodule
+
 module  \$_AOI3_ (A, B, C, Y);
 input A, B, C;
 output Y;