Improved support for $sop cells
authorClifford Wolf <clifford@clifford.at>
Fri, 17 Jun 2016 14:31:16 +0000 (16:31 +0200)
committerClifford Wolf <clifford@clifford.at>
Fri, 17 Jun 2016 14:31:16 +0000 (16:31 +0200)
kernel/celltypes.h
kernel/rtlil.cc
passes/techmap/simplemap.cc
passes/tests/test_cell.cc
techlibs/common/simlib.v
techlibs/common/techmap.v

index 41dd51ed8778cae04961bf690e36639f8de0935f..cf7bc2dcf13fba1c5016b0fda8dac78a977e8bfe 100644 (file)
@@ -366,21 +366,33 @@ struct CellTypes
                        while (GetSize(t) < width*depth*2)
                                t.push_back(RTLIL::S0);
 
+                       RTLIL::State default_ret = State::S0;
+
                        for (int i = 0; i < depth; i++)
                        {
                                bool match = true;
+                               bool match_x = 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 (t.at(2*width*i + 2*j + 0) == State::S1) {
+                                               if (a == State::S1) match_x = false;
+                                               if (a != State::S0) match = false;
+                                       }
+                                       if (t.at(2*width*i + 2*j + 1) == State::S1) {
+                                               if (a == State::S0) match_x = false;
+                                               if (a != State::S1) match = false;
+                                       }
                                }
 
                                if (match)
                                        return State::S1;
+
+                               if (match_x)
+                                       default_ret = State::Sx;
                        }
 
-                       return State::S0;
+                       return default_ret;
                }
 
                bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
index 3b1df440690767d650772e983fd5b74d6aed4772..bcd87d3fffdecb199bc706689bb2aac140253201 100644 (file)
@@ -2142,7 +2142,7 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
                return;
        }
 
-       if (type == "$lut") {
+       if (type == "$lut" || type == "$sop") {
                parameters["\\WIDTH"] = GetSize(connections_["\\A"]);
                return;
        }
index 777e80142f96cf84677a6cdf2a9dca6f86b0f969..0fb64734407a6204a9b8ea4236b166d7636da87e 100644 (file)
@@ -321,6 +321,36 @@ void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
        module->connect(cell->getPort("\\Y"), lut_data);
 }
 
+void simplemap_sop(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+       SigSpec ctrl = cell->getPort("\\A");
+       SigSpec table = cell->getParam("\\TABLE");
+
+       int width = cell->getParam("\\WIDTH").as_int();
+       int depth = cell->getParam("\\DEPTH").as_int();
+       table.extend_u0(2 * width * depth);
+
+       SigSpec products;
+
+       for (int i = 0; i < depth; i++) {
+               SigSpec in, pat;
+               for (int j = 0; j < width; j++) {
+                       if (table[2*i*width + 2*j + 0] == State::S1) {
+                               in.append(ctrl[j]);
+                               pat.append(State::S0);
+                       }
+                       if (table[2*i*width + 2*j + 1] == State::S1) {
+                               in.append(ctrl[j]);
+                               pat.append(State::S1);
+                       }
+               }
+
+               products.append(GetSize(in) > 0 ? module->Eq(NEW_ID, in, pat) : State::S1);
+       }
+
+       module->connect(cell->getPort("\\Y"), module->ReduceOr(NEW_ID, products));
+}
+
 void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell)
 {
        int offset = cell->parameters.at("\\OFFSET").as_int();
@@ -498,6 +528,7 @@ void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTL
        mappers["$mux"]         = simplemap_mux;
        mappers["$tribuf"]      = simplemap_tribuf;
        mappers["$lut"]         = simplemap_lut;
+       mappers["$sop"]         = simplemap_sop;
        mappers["$slice"]       = simplemap_slice;
        mappers["$concat"]      = simplemap_concat;
        mappers["$sr"]          = simplemap_sr;
index a8fcac9bcd7d6692c0159eacfe5f8d9ad5594ab2..8b800d41493dd44d170dfae3bf8e5a1c90c2b690 100644 (file)
@@ -164,6 +164,41 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
                cell->setParam("\\LUT", config.as_const());
        }
 
+       if (cell_type == "$sop")
+       {
+               int width = 1 + xorshift32(8);
+               int depth = 1 + xorshift32(8);
+
+               wire = module->addWire("\\A");
+               wire->width = width;
+               wire->port_input = true;
+               cell->setPort("\\A", wire);
+
+               wire = module->addWire("\\Y");
+               wire->port_output = true;
+               cell->setPort("\\Y", wire);
+
+               RTLIL::SigSpec config;
+               for (int i = 0; i < width*depth; i++)
+                       switch (xorshift32(3)) {
+                               case 0:
+                                       config.append(RTLIL::S1);
+                                       config.append(RTLIL::S0);
+                                       break;
+                               case 1:
+                                       config.append(RTLIL::S0);
+                                       config.append(RTLIL::S1);
+                                       break;
+                               case 2:
+                                       config.append(RTLIL::S0);
+                                       config.append(RTLIL::S0);
+                                       break;
+                       }
+
+               cell->setParam("\\DEPTH", depth);
+               cell->setParam("\\TABLE", config.as_const());
+       }
+
        if (cell_type_flags.find('A') != std::string::npos) {
                wire = module->addWire("\\A");
                wire->width = 1 + xorshift32(8);
@@ -534,7 +569,7 @@ struct TestCellPass : public Pass {
                log("        pass this option to techmap.\n");
                log("\n");
                log("    -simlib\n");
-               log("        use \"techmap -map +/simlib.v -max_iter 2 -autoproc\"\n");
+               log("        use \"techmap -D SIMLIB_NOCHECKS -map +/simlib.v -max_iter 2 -autoproc\"\n");
                log("\n");
                log("    -aigmap\n");
                log("        instead of calling \"techmap\", call \"aigmap\"\n");
@@ -604,7 +639,7 @@ struct TestCellPass : public Pass {
                                continue;
                        }
                        if (args[argidx] == "-simlib") {
-                               techmap_cmd = "techmap -map +/simlib.v -max_iter 2 -autoproc";
+                               techmap_cmd = "techmap -D SIMLIB_NOCHECKS -map +/simlib.v -max_iter 2 -autoproc";
                                continue;
                        }
                        if (args[argidx] == "-aigmap") {
@@ -697,6 +732,7 @@ struct TestCellPass : public Pass {
                // cell_types["$assert"] = "A";
 
                cell_types["$lut"] = "*";
+               cell_types["$sop"] = "*";
                cell_types["$alu"] = "ABSY";
                cell_types["$lcu"] = "*";
                cell_types["$macc"] = "*";
index 4932925823edd7bfa3e5c28275b258af981c34c4..342555024521c16c047631547b2335534e9fbf4b 100644 (file)
@@ -1340,7 +1340,7 @@ wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
 
 genvar i;
 generate
-       for (i = 0; i < WIDTH; i = i+1) begin:bit
+       for (i = 0; i < WIDTH; i = i+1) begin:bitslices
                always @(posedge pos_set[i], posedge pos_clr[i])
                        if (pos_clr[i])
                                Q[i] <= 0;
@@ -1409,7 +1409,7 @@ wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
 
 genvar i;
 generate
-       for (i = 0; i < WIDTH; i = i+1) begin:bit
+       for (i = 0; i < WIDTH; i = i+1) begin:bitslices
                always @(posedge pos_set[i], posedge pos_clr[i], posedge pos_clk)
                        if (pos_clr[i])
                                Q[i] <= 0;
@@ -1485,7 +1485,7 @@ wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
 
 genvar i;
 generate
-       for (i = 0; i < WIDTH; i = i+1) begin:bit
+       for (i = 0; i < WIDTH; i = i+1) begin:bitslices
                always @*
                        if (pos_clr[i])
                                Q[i] = 0;
index a623bb516712634ff244e4a97455766de376bf54..90c4ed7ebbc366a4d793ed6fa7395f22b2a3a7fa 100644 (file)
@@ -452,7 +452,7 @@ endmodule
 
 `ifndef NOLUT
 (* techmap_simplemap *)
-(* techmap_celltype = "$lut" *)
+(* techmap_celltype = "$lut $sop" *)
 module _90_lut;
 endmodule
 `endif