module->connect(sig, Const(0, GetSize(sig)));
}
}
+
+ if (c->type.in("$div", "$mod", "$pow"))
+ {
+ SigSpec A = c->getPort("\\A");
+ int original_a_width = GetSize(A);
+ if (c->getParam("\\A_SIGNED").as_bool()) {
+ while (GetSize(A) > 1 && A[GetSize(A)-1] == State::S0 && A[GetSize(A)-2] == State::S0)
+ A.remove(GetSize(A)-1, 1);
+ } else {
+ while (GetSize(A) > 0 && A[GetSize(A)-1] == State::S0)
+ A.remove(GetSize(A)-1, 1);
+ }
+ if (original_a_width != GetSize(A)) {
+ log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n",
+ original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type));
+ c->setPort("\\A", A);
+ c->setParam("\\A_WIDTH", GetSize(A));
+ }
+
+ SigSpec B = c->getPort("\\B");
+ int original_b_width = GetSize(B);
+ if (c->getParam("\\B_SIGNED").as_bool()) {
+ while (GetSize(B) > 1 && B[GetSize(B)-1] == State::S0 && B[GetSize(B)-2] == State::S0)
+ B.remove(GetSize(B)-1, 1);
+ } else {
+ while (GetSize(B) > 0 && B[GetSize(B)-1] == State::S0)
+ B.remove(GetSize(B)-1, 1);
+ }
+ if (original_b_width != GetSize(B)) {
+ log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n",
+ original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type));
+ c->setPort("\\B", B);
+ c->setParam("\\B_WIDTH", GetSize(B));
+ }
+ }
+
if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) {
IdString memid = c->getParam("\\MEMID").decode_string();
RTLIL::Memory *mem = module->memories.at(memid);
EXTRA_OBJS += passes/pmgen/peepopt_pm.h
.SECONDARY: passes/pmgen/peepopt_pm.h
-PEEPOPT_PATTERN = passes/pmgen/peepopt_shiftmul.pmg
+PEEPOPT_PATTERN = passes/pmgen/peepopt_shiftmul.pmg
+PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg
passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN)
$(P) mkdir -p passes/pmgen && python3 $< -o $@ -p peepopt $(filter-out $<,$^)
--- /dev/null
+pattern muldiv
+
+state <SigSpec> t x y
+
+match mul
+ select mul->type == $mul
+ select GetSize(port(mul, \A)) + GetSize(port(mul, \B)) <= GetSize(port(mul, \Y))
+endmatch
+
+code t x y
+ t = port(mul, \Y);
+ x = port(mul, \A);
+ y = port(mul, \B);
+ branch;
+ std::swap(x, y);
+endcode
+
+match div
+ select div->type.in($div)
+ index <SigSpec> port(div, \A) === t
+ index <SigSpec> port(div, \B) === x
+endmatch
+
+code
+ SigSpec div_y = port(div, \Y);
+ SigSpec val_y = y;
+
+ if (GetSize(div_y) != GetSize(val_y))
+ val_y.extend_u0(GetSize(div_y), param(div, \A_SIGNED).as_bool());
+
+ did_something = true;
+ log("muldiv pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div));
+ module->connect(div_y, val_y);
+ autoremove(div);
+ reject;
+endcode
print(" blacklist_dirty = false;", file=f)
for index in range(len(blocks)):
block = blocks[index]
+ if block["pattern"] != current_pattern:
+ continue
if block["type"] == "match":
print(" if (st_{}.{} != nullptr && blacklist_cells.count(st_{}.{})) {{".format(current_pattern, block["cell"], current_pattern, block["cell"]), file=f)
print(" rollback = {};".format(index+1), file=f)