aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2019-04-30 11:25:15 +0200
committerClifford Wolf <clifford@clifford.at>2019-04-30 11:25:15 +0200
commitb515fd2d25851c90c9a0b08414c5ea5edeb916a0 (patch)
tree18e75d1f0b5ad39801b3cfcb72905ca048847ab7
parent4306bebe586dc3a6a954a6630b9f0292c1b1b1dd (diff)
downloadyosys-b515fd2d25851c90c9a0b08414c5ea5edeb916a0.tar.gz
yosys-b515fd2d25851c90c9a0b08414c5ea5edeb916a0.tar.bz2
yosys-b515fd2d25851c90c9a0b08414c5ea5edeb916a0.zip
Add peepopt_muldiv, fixes #930
Signed-off-by: Clifford Wolf <clifford@clifford.at>
-rw-r--r--passes/opt/wreduce.cc36
-rw-r--r--passes/pmgen/Makefile.inc3
-rw-r--r--passes/pmgen/peepopt.cc1
-rw-r--r--passes/pmgen/peepopt_muldiv.pmg36
-rw-r--r--passes/pmgen/pmgen.py2
-rw-r--r--tests/simple/peepopt.v9
6 files changed, 86 insertions, 1 deletions
diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc
index 68e077cf9..bbb1f4c48 100644
--- a/passes/opt/wreduce.cc
+++ b/passes/opt/wreduce.cc
@@ -529,6 +529,42 @@ struct WreducePass : public Pass {
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);
diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc
index a8cac7ea4..7911132db 100644
--- a/passes/pmgen/Makefile.inc
+++ b/passes/pmgen/Makefile.inc
@@ -16,7 +16,8 @@ passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h
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 $<,$^)
diff --git a/passes/pmgen/peepopt.cc b/passes/pmgen/peepopt.cc
index 0584878c3..78eb68c7a 100644
--- a/passes/pmgen/peepopt.cc
+++ b/passes/pmgen/peepopt.cc
@@ -59,6 +59,7 @@ struct PeepoptPass : public Pass {
did_something = false;
peepopt_pm pm(module, module->selected_cells());
pm.run_shiftmul();
+ pm.run_muldiv();
}
}
}
diff --git a/passes/pmgen/peepopt_muldiv.pmg b/passes/pmgen/peepopt_muldiv.pmg
new file mode 100644
index 000000000..06c275834
--- /dev/null
+++ b/passes/pmgen/peepopt_muldiv.pmg
@@ -0,0 +1,36 @@
+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
diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py
index 95a0a5f5d..81052afce 100644
--- a/passes/pmgen/pmgen.py
+++ b/passes/pmgen/pmgen.py
@@ -335,6 +335,8 @@ with open(outfile, "w") as f:
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)
diff --git a/tests/simple/peepopt.v b/tests/simple/peepopt.v
new file mode 100644
index 000000000..b27b9fe57
--- /dev/null
+++ b/tests/simple/peepopt.v
@@ -0,0 +1,9 @@
+module peepopt_shiftmul_0 #(parameter N=3, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output [W-1:0] o);
+assign o = i[s*W+:W];
+endmodule
+
+module peepopt_muldiv_0(input [1:0] i, output [1:0] o);
+wire [3:0] t;
+assign t = i * 3;
+assign o = t / 3;
+endmodule