Added $sop cell type and "abc -sop"
authorClifford Wolf <clifford@clifford.at>
Fri, 17 Jun 2016 11:46:01 +0000 (13:46 +0200)
committerClifford Wolf <clifford@clifford.at>
Fri, 17 Jun 2016 11:50:09 +0000 (13:50 +0200)
frontends/blif/blifparse.cc
frontends/blif/blifparse.h
kernel/celltypes.h
kernel/rtlil.cc
manual/CHAPTER_CellLib.tex
passes/techmap/abc.cc
techlibs/common/simlib.v

index a901e55f97a159fbbbc95e2e17e90f686e282acd..3b4b6d86f0c71bbd1c31abb840a4dba1ad6200fd 100644 (file)
@@ -49,12 +49,13 @@ static bool read_next_line(char *&buffer, size_t &buffer_size, int &line_count,
        }
 }
 
-void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean)
+void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean, bool sop_mode)
 {
        RTLIL::Module *module = nullptr;
        RTLIL::Const *lutptr = NULL;
+       RTLIL::Cell *sopcell = NULL;
        RTLIL::State lut_default_state = RTLIL::State::Sx;
-       int blif_maxnum = 0;
+       int blif_maxnum = 0, sopmode = -1;
 
        auto blif_wire = [&](const std::string &wire_name) -> Wire*
        {
@@ -116,6 +117,11 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
                                lut_default_state = RTLIL::State::Sx;
                        }
 
+                       if (sopcell) {
+                               sopcell = NULL;
+                               sopmode = -1;
+                       }
+
                        char *cmd = strtok(buffer, " \t\r\n");
 
                        if (!strcmp(cmd, ".model")) {
@@ -344,20 +350,33 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
                                        goto continue_without_read;
                                }
 
-                               RTLIL::Cell *cell = module->addCell(NEW_ID, "$lut");
-                               cell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size());
-                               cell->parameters["\\LUT"] = RTLIL::Const(RTLIL::State::Sx, 1 << input_sig.size());
-                               cell->setPort("\\A", input_sig);
-                               cell->setPort("\\Y", output_sig);
-                               lutptr = &cell->parameters.at("\\LUT");
-                               lut_default_state = RTLIL::State::Sx;
+                               if (sop_mode)
+                               {
+                                       sopcell = module->addCell(NEW_ID, "$sop");
+                                       sopcell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size());
+                                       sopcell->parameters["\\DEPTH"] = 0;
+                                       sopcell->parameters["\\TABLE"] = RTLIL::Const();
+                                       sopcell->setPort("\\A", input_sig);
+                                       sopcell->setPort("\\Y", output_sig);
+                                       sopmode = -1;
+                               }
+                               else
+                               {
+                                       RTLIL::Cell *cell = module->addCell(NEW_ID, "$lut");
+                                       cell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size());
+                                       cell->parameters["\\LUT"] = RTLIL::Const(RTLIL::State::Sx, 1 << input_sig.size());
+                                       cell->setPort("\\A", input_sig);
+                                       cell->setPort("\\Y", output_sig);
+                                       lutptr = &cell->parameters.at("\\LUT");
+                                       lut_default_state = RTLIL::State::Sx;
+                               }
                                continue;
                        }
 
                        goto error;
                }
 
-               if (lutptr == NULL)
+               if (lutptr == NULL && sopcell == NULL)
                        goto error;
 
                char *input = strtok(buffer, " \t\r\n");
@@ -367,23 +386,60 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
                        goto error;
 
                int input_len = strlen(input);
-               if (input_len > 8)
-                       goto error;
 
-               for (int i = 0; i < (1 << input_len); i++) {
-                       for (int j = 0; j < input_len; j++) {
-                               char c1 = input[j];
-                               if (c1 != '-') {
-                                       char c2 = (i & (1 << j)) != 0 ? '1' : '0';
-                                       if (c1 != c2)
-                                               goto try_next_value;
+               if (sopcell)
+               {
+                       log_assert(sopcell->parameters["\\WIDTH"].as_int() == input_len);
+                       sopcell->parameters["\\DEPTH"] = sopcell->parameters["\\DEPTH"].as_int() + 1;
+
+                       for (int i = 0; i < input_len; i++)
+                               switch (input[i]) {
+                                       case '0':
+                                               sopcell->parameters["\\TABLE"].bits.push_back(State::S1);
+                                               sopcell->parameters["\\TABLE"].bits.push_back(State::S0);
+                                               break;
+                                       case '1':
+                                               sopcell->parameters["\\TABLE"].bits.push_back(State::S0);
+                                               sopcell->parameters["\\TABLE"].bits.push_back(State::S1);
+                                               break;
+                                       default:
+                                               sopcell->parameters["\\TABLE"].bits.push_back(State::S0);
+                                               sopcell->parameters["\\TABLE"].bits.push_back(State::S0);
+                                               break;
                                }
-                       }
-                       lutptr->bits.at(i) = !strcmp(output, "0") ? RTLIL::State::S0 : RTLIL::State::S1;
-               try_next_value:;
+
+                       if (sopmode == -1) {
+                               sopmode = (*output == '1');
+                               if (!sopmode) {
+                                       SigSpec outnet = sopcell->getPort("\\Y");
+                                       SigSpec tempnet = module->addWire(NEW_ID);
+                                       module->addNotGate(NEW_ID, tempnet, outnet);
+                                       sopcell->setPort("\\Y", tempnet);
+                               }
+                       } else
+                               log_assert(sopmode == (*output == '1'));
                }
 
-               lut_default_state = !strcmp(output, "0") ? RTLIL::State::S1 : RTLIL::State::S0;
+               if (lutptr)
+               {
+                       if (input_len > 8)
+                               goto error;
+
+                       for (int i = 0; i < (1 << input_len); i++) {
+                               for (int j = 0; j < input_len; j++) {
+                                       char c1 = input[j];
+                                       if (c1 != '-') {
+                                               char c2 = (i & (1 << j)) != 0 ? '1' : '0';
+                                               if (c1 != c2)
+                                                       goto try_next_value;
+                                       }
+                               }
+                               lutptr->bits.at(i) = !strcmp(output, "0") ? RTLIL::State::S0 : RTLIL::State::S1;
+                       try_next_value:;
+                       }
+
+                       lut_default_state = !strcmp(output, "0") ? RTLIL::State::S1 : RTLIL::State::S0;
+               }
        }
 
 error:
index 3c01ed373d75d7eced14c6f6f57bc3ac24b01f0b..058087d814c52ba1889b68d453b55648edc15ba2 100644 (file)
@@ -24,7 +24,7 @@
 
 YOSYS_NAMESPACE_BEGIN
 
-extern void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean = false);
+extern void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean = false, bool sop_mode = false);
 
 YOSYS_NAMESPACE_END
 
index 40fdca36eef0bde52eb40ed8013408a510e1e6f6..41dd51ed8778cae04961bf690e36639f8de0935f 100644 (file)
@@ -85,7 +85,7 @@ struct CellTypes
                std::vector<RTLIL::IdString> unary_ops = {
                        "$not", "$pos", "$neg",
                        "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
-                       "$logic_not", "$slice", "$lut"
+                       "$logic_not", "$slice", "$lut", "$sop"
                };
 
                std::vector<RTLIL::IdString> binary_ops = {
@@ -357,6 +357,32 @@ struct CellTypes
                        return t;
                }
 
+               if (cell->type == "$sop")
+               {
+                       int width = cell->parameters.at("\\WIDTH").as_int();
+                       int depth = cell->parameters.at("\\DEPTH").as_int();
+                       std::vector<RTLIL::State> t = cell->parameters.at("\\TABLE").bits;
+
+                       while (GetSize(t) < width*depth*2)
+                               t.push_back(RTLIL::S0);
+
+                       for (int i = 0; i < depth; i++)
+                       {
+                               bool match = true;
+
+                               for (int j = 0; j < width; j++) {
+                                       RTLIL::State a = arg1.bits.at(j);
+                                       if (t.at(2*width*i + 2*j + 0) == State::S1 && a == State::S1) match = false;
+                                       if (t.at(2*width*i + 2*j + 1) == State::S1 && a == State::S0) match = false;
+                               }
+
+                               if (match)
+                                       return State::S1;
+                       }
+
+                       return State::S0;
+               }
+
                bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
                bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
                int result_len = cell->parameters.count("\\Y_WIDTH") > 0 ? cell->parameters["\\Y_WIDTH"].as_int() : -1;
index a706491e8c8618eb6e7f8bc68b59c5c0e8d93fa5..3b1df440690767d650772e983fd5b74d6aed4772 100644 (file)
@@ -845,6 +845,15 @@ namespace {
                                return;
                        }
 
+                       if (cell->type == "$sop") {
+                               param("\\DEPTH");
+                               param("\\TABLE");
+                               port("\\A", param("\\WIDTH"));
+                               port("\\Y", 1);
+                               check_expected();
+                               return;
+                       }
+
                        if (cell->type == "$sr") {
                                param_bool("\\SET_POLARITY");
                                param_bool("\\CLR_POLARITY");
index c648eb1febea9483a9b54df0064702cf5285b801..f97d4ffa54d9585c4e36607c5ac8566b929a61ff 100644 (file)
@@ -428,6 +428,10 @@ Add information about {\tt \$assert}, {\tt \$assume}, and {\tt \$equiv} cells.
 Add information about {\tt \$slice} and {\tt \$concat} cells.
 \end{fixme}
 
+\begin{fixme}
+Add information about {\tt \$lut} and {\tt \$sop} cells.
+\end{fixme}
+
 \begin{fixme}
 Add information about {\tt \$alu}, {\tt \$macc}, {\tt \$fa}, and {\tt \$lcu} cells.
 \end{fixme}
index 7ddc7a16871b08207313be1108c495a6fa3cfce6..b9a1b65dec1679f12db818120572c44955944bba 100644 (file)
 #define ABC_COMMAND_LIB "strash; scorr; ifraig; retime -o {D}; strash; dch -f; map {D}"
 #define ABC_COMMAND_CTR "strash; scorr; ifraig; retime -o {D}; strash; dch -f; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
 #define ABC_COMMAND_LUT "strash; scorr; ifraig; retime -o; strash; dch -f; if; mfs"
+#define ABC_COMMAND_SOP "strash; scorr; ifraig; retime -o; strash; dch -f; cover"
 #define ABC_COMMAND_DFL "strash; scorr; ifraig; retime -o; strash; dch -f; map"
 
 #define ABC_FAST_COMMAND_LIB "retime -o {D}; map {D}"
 #define ABC_FAST_COMMAND_CTR "retime -o {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
 #define ABC_FAST_COMMAND_LUT "retime -o; if"
+#define ABC_FAST_COMMAND_SOP "retime -o; cover"
 #define ABC_FAST_COMMAND_DFL "retime -o; map"
 
 #include "kernel/register.h"
@@ -593,7 +595,7 @@ struct abc_output_filter
 
 void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
                std::string liberty_file, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
-               bool keepff, std::string delay_target, bool fast_mode, const std::vector<RTLIL::Cell*> &cells, bool show_tempdir)
+               bool keepff, std::string delay_target, bool fast_mode, const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode)
 {
        module = current_module;
        map_autoidx = autoidx++;
@@ -652,6 +654,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                        abc_script += "; lutpack";
        } else if (!liberty_file.empty())
                abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR);
+       else if (sop_mode)
+               abc_script += fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP;
        else
                abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL;
 
@@ -898,9 +902,9 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                if (ifs.fail())
                        log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
 
-               bool builtin_lib = liberty_file.empty() && script_file.empty() && lut_costs.empty();
+               bool builtin_lib = liberty_file.empty() && script_file.empty() && lut_costs.empty() && !sop_mode;
                RTLIL::Design *mapped_design = new RTLIL::Design;
-               parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_");
+               parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode);
 
                ifs.close();
 
@@ -1202,6 +1206,9 @@ struct AbcPass : public Pass {
                log("        for -lut/-luts (different LUT sizes):\n");
                log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT).c_str());
                log("\n");
+               log("        for -sop:\n");
+               log("%s\n", fold_abc_cmd(ABC_COMMAND_SOP).c_str());
+               log("\n");
                log("        otherwise:\n");
                log("%s\n", fold_abc_cmd(ABC_COMMAND_DFL).c_str());
                log("\n");
@@ -1218,6 +1225,9 @@ struct AbcPass : public Pass {
                log("        for -lut/-luts:\n");
                log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LUT).c_str());
                log("\n");
+               log("        for -sop:\n");
+               log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_SOP).c_str());
+               log("\n");
                log("        otherwise:\n");
                log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_DFL).c_str());
                log("\n");
@@ -1253,6 +1263,9 @@ struct AbcPass : public Pass {
                log("        generate netlist using luts. Use the specified costs for luts with 1,\n");
                log("        2, 3, .. inputs.\n");
                log("\n");
+               log("    -sop\n");
+               log("        map to sum-of-product cells\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");
@@ -1309,7 +1322,7 @@ struct AbcPass : public Pass {
 #endif
                std::string script_file, liberty_file, constr_file, clk_str, delay_target;
                bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
-               bool show_tempdir = false;
+               bool show_tempdir = false, sop_mode = false;
                vector<int> lut_costs;
                markgroups = false;
 
@@ -1393,6 +1406,10 @@ struct AbcPass : public Pass {
                                }
                                continue;
                        }
+                       if (arg == "-sop") {
+                               sop_mode = true;
+                               continue;
+                       }
                        if (arg == "-mux4") {
                                map_mux4 = true;
                                continue;
@@ -1466,7 +1483,7 @@ struct AbcPass : public Pass {
                        if (mod->processes.size() > 0)
                                log("Skipping module %s as it contains processes.\n", log_id(mod));
                        else if (!dff_mode || !clk_str.empty())
-                               abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir);
+                               abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir, sop_mode);
                        else
                        {
                                assign_map.set(mod);
@@ -1611,7 +1628,7 @@ struct AbcPass : public Pass {
                                        en_polarity = std::get<2>(it.first);
                                        en_sig = assign_map(std::get<3>(it.first));
                                        abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs,
-                                                       !clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second, show_tempdir);
+                                                       !clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second, show_tempdir, sop_mode);
                                        assign_map.set(mod);
                                }
                        }
index 00f90bd4a2962bbfad960e488a1fa517a577050e..4932925823edd7bfa3e5c28275b258af981c34c4 100644 (file)
@@ -1229,6 +1229,34 @@ endmodule
 `endif
 // --------------------------------------------------------
 
+module \$sop (A, Y);
+
+parameter WIDTH = 0;
+parameter DEPTH = 0;
+parameter TABLE = 0;
+
+input [WIDTH-1:0] A;
+output reg Y;
+
+integer i, j;
+reg match;
+
+always @* begin
+       Y = 0;
+       for (i = 0; i < DEPTH; i=i+1) begin
+               match = 1;
+               for (j = 0; j < WIDTH; j=j+1) begin
+                       if (TABLE[2*WIDTH*i + 2*j + 0] && A[j]) match = 0;
+                       if (TABLE[2*WIDTH*i + 2*j + 1] && !A[j]) match = 0;
+               end
+               if (match) Y = 1;
+       end
+end
+
+endmodule
+
+// --------------------------------------------------------
+
 module \$tribuf (A, EN, Y);
 
 parameter WIDTH = 0;