diff options
Diffstat (limited to 'passes/pmgen/test_pmgen.pmg')
-rw-r--r-- | passes/pmgen/test_pmgen.pmg | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/passes/pmgen/test_pmgen.pmg b/passes/pmgen/test_pmgen.pmg new file mode 100644 index 000000000..211477a62 --- /dev/null +++ b/passes/pmgen/test_pmgen.pmg @@ -0,0 +1,106 @@ +pattern reduce + +state <IdString> portname +udata <vector<pair<Cell*, IdString>>> chain longest_chain +udata <pool<Cell*>> non_first_cells +udata <SigSpec> leaves + +code + non_first_cells.clear(); + subpattern(setup); +endcode + +match first + select first->type.in($_AND_, $_OR_, $_XOR_) + filter !non_first_cells.count(first) +generate + SigSpec A = module->addWire(NEW_ID); + SigSpec B = module->addWire(NEW_ID); + SigSpec Y = module->addWire(NEW_ID); + switch (rng(3)) + { + case 0: + module->addAndGate(NEW_ID, A, B, Y); + break; + case 1: + module->addOrGate(NEW_ID, A, B, Y); + break; + case 2: + module->addXorGate(NEW_ID, A, B, Y); + break; + } +endmatch + +code + leaves = SigSpec(); + longest_chain.clear(); + chain.push_back(make_pair(first, \A)); + subpattern(tail); + chain.back().second = \B; + subpattern(tail); +finally + chain.pop_back(); + log_assert(chain.empty()); + if (GetSize(longest_chain) > 1) + accept; +endcode + +// ------------------------------------------------------------------ + +subpattern setup + +match first + select first->type.in($_AND_, $_OR_, $_XOR_) +endmatch + +code portname + portname = \A; + branch; + portname = \B; +endcode + +match next + select nusers(port(next, \Y)) == 2 + select next->type.in($_AND_, $_OR_, $_XOR_) + index <IdString> next->type === first->type + index <SigSpec> port(next, \Y) === port(first, portname) +endmatch + +code + non_first_cells.insert(next); +endcode + +// ------------------------------------------------------------------ + +subpattern tail +arg first + +match next + semioptional + select nusers(port(next, \Y)) == 2 + select next->type.in($_AND_, $_OR_, $_XOR_) + index <IdString> next->type === chain.back().first->type + index <SigSpec> port(next, \Y) === port(chain.back().first, chain.back().second) +generate 10 + SigSpec A = module->addWire(NEW_ID); + SigSpec B = module->addWire(NEW_ID); + SigSpec Y = port(chain.back().first, chain.back().second); + Cell *c = module->addAndGate(NEW_ID, A, B, Y); + c->type = chain.back().first->type; +endmatch + +code + if (next) { + chain.push_back(make_pair(next, \A)); + subpattern(tail); + chain.back().second = \B; + subpattern(tail); + } else { + if (GetSize(chain) > GetSize(longest_chain)) + longest_chain = chain; + leaves.append(port(chain.back().first, chain.back().second)); + } +finally + if (next) + chain.pop_back(); +endcode |