aboutsummaryrefslogtreecommitdiffstats
path: root/passes/pmgen/test_pmgen.cc
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2019-08-16 13:26:36 +0200
committerClifford Wolf <clifford@clifford.at>2019-08-16 13:26:36 +0200
commitc710df181c2e9931ce464ea60568c864b7195e8b (patch)
tree5f7ae08ea90c374688f46e36e692db665a21b475 /passes/pmgen/test_pmgen.cc
parent4a57b7e1abe148b36827a393fd7fe62e46c2b1a7 (diff)
downloadyosys-c710df181c2e9931ce464ea60568c864b7195e8b.tar.gz
yosys-c710df181c2e9931ce464ea60568c864b7195e8b.tar.bz2
yosys-c710df181c2e9931ce464ea60568c864b7195e8b.zip
Add pmgen "generate" feature
Signed-off-by: Clifford Wolf <clifford@clifford.at>
Diffstat (limited to 'passes/pmgen/test_pmgen.cc')
-rw-r--r--passes/pmgen/test_pmgen.cc142
1 files changed, 142 insertions, 0 deletions
diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc
index 3bff9ae12..48d58b263 100644
--- a/passes/pmgen/test_pmgen.cc
+++ b/passes/pmgen/test_pmgen.cc
@@ -23,7 +23,12 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
+// for peepopt_pm
+bool did_something;
+
#include "passes/pmgen/test_pmgen_pm.h"
+#include "passes/pmgen/ice40_dsp_pm.h"
+#include "passes/pmgen/peepopt_pm.h"
void reduce_chain(test_pmgen_pm &pm)
{
@@ -94,6 +99,100 @@ void reduce_tree(test_pmgen_pm &pm)
log(" -> %s (%s)\n", log_id(c), log_id(c->type));
}
+#define GENERATE_PATTERN(pmclass, pattern) \
+ generate_pattern<pmclass>([](pmclass &pm, std::function<void()> f){ return pm.run_ ## pattern(f); }, #pmclass, #pattern, design)
+
+void pmtest_addports(Module *module)
+{
+ pool<SigBit> driven_bits, used_bits;
+ SigMap sigmap(module);
+ int icnt = 0, ocnt = 0;
+
+ for (auto cell : module->cells())
+ for (auto conn : cell->connections())
+ {
+ if (cell->input(conn.first))
+ for (auto bit : sigmap(conn.second))
+ used_bits.insert(bit);
+ if (cell->output(conn.first))
+ for (auto bit : sigmap(conn.second))
+ driven_bits.insert(bit);
+ }
+
+ for (auto wire : vector<Wire*>(module->wires()))
+ {
+ SigSpec ibits, obits;
+ for (auto bit : sigmap(wire)) {
+ if (!used_bits.count(bit))
+ obits.append(bit);
+ if (!driven_bits.count(bit))
+ ibits.append(bit);
+ }
+ if (!ibits.empty()) {
+ Wire *w = module->addWire(stringf("\\i%d", icnt++), GetSize(ibits));
+ w->port_input = true;
+ module->connect(ibits, w);
+ }
+ if (!obits.empty()) {
+ Wire *w = module->addWire(stringf("\\o%d", ocnt++), GetSize(obits));
+ w->port_output = true;
+ module->connect(w, obits);
+ }
+ }
+
+ module->fixup_ports();
+}
+
+template <class pm>
+void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const char *pmclass, const char *pattern, Design *design)
+{
+ log("Generating \"%s\" patterns for pattern matcher \"%s\".\n", pattern, pmclass);
+
+ int modcnt = 0;
+
+ while (modcnt < 100)
+ {
+ int submodcnt = 0, itercnt = 0, cellcnt = 0;
+ Module *mod = design->addModule(NEW_ID);
+
+ while (submodcnt < 10 && itercnt++ < 1000)
+ {
+ pm matcher(mod, mod->cells());
+
+ matcher.rng(1);
+ matcher.rngseed += modcnt;
+ matcher.rng(1);
+ matcher.rngseed += submodcnt;
+ matcher.rng(1);
+ matcher.rngseed += itercnt;
+ matcher.rng(1);
+ matcher.rngseed += cellcnt;
+ matcher.rng(1);
+
+ if (GetSize(mod->cells()) != cellcnt)
+ {
+ bool found_match = false;
+ run(matcher, [&](){ found_match = true; });
+
+ if (found_match) {
+ Module *m = design->addModule(stringf("\\pmtest_%s_%s_%05d",
+ pmclass, pattern, modcnt++));
+ mod->cloneInto(m);
+ pmtest_addports(m);
+ submodcnt++;
+ }
+
+ cellcnt = GetSize(mod->cells());
+ }
+
+ matcher.generate_mode = true;
+ run(matcher, [](){});
+ }
+
+ design->remove(mod);
+ }
+}
+
struct TestPmgenPass : public Pass {
TestPmgenPass() : Pass("test_pmgen", "test pass for pmgen") { }
void help() YS_OVERRIDE
@@ -104,11 +203,18 @@ struct TestPmgenPass : public Pass {
log("\n");
log("Demo for recursive pmgen patterns. Map chains of AND/OR/XOR to $reduce_*.\n");
log("\n");
+
log("\n");
log(" test_pmgen -reduce_tree [options] [selection]\n");
log("\n");
log("Demo for recursive pmgen patterns. Map trees of AND/OR/XOR to $reduce_*.\n");
log("\n");
+
+ log("\n");
+ log(" test_pmgen -generate [options] <pattern_name>\n");
+ log("\n");
+ log("Create modules that match the specified pattern.\n");
+ log("\n");
}
void execute_reduce_chain(std::vector<std::string> args, RTLIL::Design *design)
@@ -149,6 +255,40 @@ struct TestPmgenPass : public Pass {
test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_tree);
}
+ void execute_generate(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ log_header(design, "Executing TEST_PMGEN pass (-generate).\n");
+
+ size_t argidx;
+ for (argidx = 2; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-singleton") {
+ // singleton_mode = true;
+ // continue;
+ // }
+ break;
+ }
+
+ if (argidx+1 != args.size())
+ log_cmd_error("Expected exactly one pattern.\n");
+
+ string pattern = args[argidx];
+
+ if (pattern == "reduce")
+ return GENERATE_PATTERN(test_pmgen_pm, reduce);
+
+ if (pattern == "ice40_dsp")
+ return GENERATE_PATTERN(ice40_dsp_pm, ice40_dsp);
+
+ if (pattern == "peepopt-muldiv")
+ return GENERATE_PATTERN(peepopt_pm, muldiv);
+
+ if (pattern == "peepopt-shiftmul")
+ return GENERATE_PATTERN(peepopt_pm, shiftmul);
+
+ log_cmd_error("Unkown pattern: %s\n", pattern.c_str());
+ }
+
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
if (GetSize(args) > 1)
@@ -157,6 +297,8 @@ struct TestPmgenPass : public Pass {
return execute_reduce_chain(args, design);
if (args[1] == "-reduce_tree")
return execute_reduce_tree(args, design);
+ if (args[1] == "-generate")
+ return execute_generate(args, design);
}
log_cmd_error("Missing or unsupported mode parameter.\n");
}