diff options
Diffstat (limited to 'passes/tests/test_cell.cc')
-rw-r--r-- | passes/tests/test_cell.cc | 171 |
1 files changed, 167 insertions, 4 deletions
diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index a8fcac9b..049c2053 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -21,6 +21,7 @@ #include "kernel/yosys.h" #include "kernel/satgen.h" #include "kernel/consteval.h" +#include "kernel/celledges.h" #include "kernel/macc.h" #include <algorithm> @@ -42,6 +43,32 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, RTLIL::Cell *cell = module->addCell("\\UUT", cell_type); RTLIL::Wire *wire; + if (cell_type == "$mux" || cell_type == "$pmux") + { + int width = 1 + xorshift32(8); + int swidth = cell_type == "$mux" ? 1 : 1 + xorshift32(8); + + wire = module->addWire("\\A"); + wire->width = width; + wire->port_input = true; + cell->setPort("\\A", wire); + + wire = module->addWire("\\B"); + wire->width = width * swidth; + wire->port_input = true; + cell->setPort("\\B", wire); + + wire = module->addWire("\\S"); + wire->width = swidth; + wire->port_input = true; + cell->setPort("\\S", wire); + + wire = module->addWire("\\Y"); + wire->width = width; + wire->port_output = true; + cell->setPort("\\Y", wire); + } + if (cell_type == "$fa") { int width = 1 + xorshift32(8); @@ -164,6 +191,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); @@ -270,6 +332,91 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, cell->check(); } +static void run_edges_test(RTLIL::Design *design, bool verbose) +{ + Module *module = *design->modules().begin(); + Cell *cell = *module->cells().begin(); + + ezSatPtr ezptr; + ezSAT &ez = *ezptr.get(); + + SigMap sigmap(module); + SatGen satgen(&ez, &sigmap); + + FwdCellEdgesDatabase edges_db(sigmap); + if (!edges_db.add_edges_from_cell(cell)) + log_error("Creating edge database failed for this cell!\n"); + + dict<SigBit, pool<SigBit>> satgen_db; + + satgen.setContext(&sigmap, "X:"); + satgen.importCell(cell); + + satgen.setContext(&sigmap, "Y:"); + satgen.importCell(cell); + + vector<tuple<SigBit, int, int>> input_db, output_db; + + for (auto &conn : cell->connections()) + { + SigSpec bits = sigmap(conn.second); + + satgen.setContext(&sigmap, "X:"); + std::vector<int> xbits = satgen.importSigSpec(bits); + + satgen.setContext(&sigmap, "Y:"); + std::vector<int> ybits = satgen.importSigSpec(bits); + + for (int i = 0; i < GetSize(bits); i++) + if (cell->input(conn.first)) + input_db.emplace_back(bits[i], xbits[i], ybits[i]); + else + output_db.emplace_back(bits[i], xbits[i], ybits[i]); + } + + if (verbose) + log("\nSAT solving for all edges:\n"); + + for (int i = 0; i < GetSize(input_db); i++) + { + SigBit inbit = std::get<0>(input_db[i]); + + if (verbose) + log(" Testing input signal %s:\n", log_signal(inbit)); + + vector<int> xinbits, yinbits; + for (int k = 0; k < GetSize(input_db); k++) + if (k != i) { + xinbits.push_back(std::get<1>(input_db[k])); + yinbits.push_back(std::get<2>(input_db[k])); + } + + int xyinbit_ok = ez.vec_eq(xinbits, yinbits); + + for (int k = 0; k < GetSize(output_db); k++) + { + SigBit outbit = std::get<0>(output_db[k]); + int xoutbit = std::get<1>(output_db[k]); + int youtbit = std::get<2>(output_db[k]); + + bool is_edge = ez.solve(xyinbit_ok, ez.XOR(xoutbit, youtbit)); + + if (is_edge) + satgen_db[inbit].insert(outbit); + + if (verbose) { + bool is_ref_edge = edges_db.db.count(inbit) && edges_db.db.at(inbit).count(outbit); + log(" %c %s %s\n", is_edge ? 'x' : 'o', log_signal(outbit), is_edge == is_ref_edge ? "OK" : "ERROR"); + } + } + } + + if (satgen_db == edges_db.db) + log("PASS.\n"); + else + log_error("SAT-based edge table does not match the database!\n"); +} + static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std::string uut_name, std::ofstream &vlog_file) { log("Eval testing:%c", verbose ? '\n' : ' '); @@ -534,7 +681,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"); @@ -555,6 +702,9 @@ struct TestCellPass : public Pass { log(" -noeval\n"); log(" do not check const-eval models\n"); log("\n"); + log(" -edges\n"); + log(" test cell edges db creator against sat-based implementation\n"); + log("\n"); log(" -v\n"); log(" print additional debug information to the console\n"); log("\n"); @@ -574,6 +724,7 @@ struct TestCellPass : public Pass { bool constmode = false; bool nosat = false; bool noeval = false; + bool edges = false; int argidx; for (argidx = 1; argidx < GetSize(args); argidx++) @@ -604,7 +755,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") { @@ -627,6 +778,10 @@ struct TestCellPass : public Pass { noeval = true; continue; } + if (args[argidx] == "-edges") { + edges = true; + continue; + } if (args[argidx] == "-v") { verbose = true; continue; @@ -690,13 +845,18 @@ struct TestCellPass : public Pass { cell_types["$logic_and"] = "ABSY"; cell_types["$logic_or"] = "ABSY"; - // cell_types["$mux"] = "A"; - // cell_types["$pmux"] = "A"; + if (edges) { + cell_types["$mux"] = "*"; + cell_types["$pmux"] = "*"; + } + // cell_types["$slice"] = "A"; // cell_types["$concat"] = "A"; // cell_types["$assert"] = "A"; + // cell_types["$assume"] = "A"; cell_types["$lut"] = "*"; + cell_types["$sop"] = "*"; cell_types["$alu"] = "ABSY"; cell_types["$lcu"] = "*"; cell_types["$macc"] = "*"; @@ -763,6 +923,9 @@ struct TestCellPass : public Pass { create_gold_module(design, cell_type, cell_types.at(cell_type), constmode, muxdiv); if (!write_prefix.empty()) { Pass::call(design, stringf("write_ilang %s_%s_%05d.il", write_prefix.c_str(), cell_type.c_str()+1, i)); + } else if (edges) { + Pass::call(design, "dump gold"); + run_edges_test(design, verbose); } else { Pass::call(design, stringf("copy gold gate; cd gate; %s; cd ..; opt -fast gate", techmap_cmd.c_str())); if (!nosat) |