mirror of https://github.com/YosysHQ/yosys.git
opt_shift
This commit is contained in:
parent
72db8885aa
commit
5082625d71
|
|
@ -28,6 +28,17 @@ PEEPOPT_PATTERN = passes/silimate/peepopt_expand.pmg
|
|||
passes/silimate/peepopt_expand.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN)
|
||||
$(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^)
|
||||
|
||||
OBJS += passes/silimate/opt_shift.o
|
||||
GENFILES += passes/silimate/peepopt_shift.h
|
||||
passes/silimate/opt_shift.o: passes/silimate/peepopt_shift.h
|
||||
$(eval $(call add_extra_objs,passes/silimate/peepopt_shift.h))
|
||||
|
||||
PEEPOPT_PATTERN = passes/silimate/peepopt_combine_shifts.pmg
|
||||
PEEPOPT_PATTERN += passes/silimate/peepopt_expand_shifts.pmg
|
||||
|
||||
passes/silimate/peepopt_shift.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN)
|
||||
$(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^)
|
||||
|
||||
OBJS += passes/silimate/muxmode.o
|
||||
GENFILES += passes/silimate/peepopt_muxmode.h
|
||||
passes/silimate/muxmode.o: passes/silimate/peepopt_muxmode.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
|
||||
* Akash Levy <akash@silimate.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
bool did_something;
|
||||
|
||||
#include "passes/silimate/peepopt_shift.h"
|
||||
|
||||
struct OptShiftPass : public Pass {
|
||||
OptShiftPass() : Pass("opt_shift", "shift optimizations: combine and expand") { }
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" opt_shift [options] [selection]\n");
|
||||
log("\n");
|
||||
log("This pass performs shift optimizations.\n");
|
||||
log("\n");
|
||||
log(" -combine\n");
|
||||
log(" Combine nested shift operations (works with all\n");
|
||||
log(" combinations of $shl/$sshl and $shr/$sshr):\n");
|
||||
log(" (a <</<< b) <</<< c ===> a <</<< (b + c)\n");
|
||||
log(" (a >>>/>> b) >>>/>> c ===> a >>>/>> (b + c)\n");
|
||||
log(" (a <</<< b) >>>/>> c ===> a <</<< (b - c)\n");
|
||||
log(" (a >>>/>> b) <</<< c ===> a >>>/>> (b - c)\n");
|
||||
log(" Result uses the inner shift's type.\n");
|
||||
log("\n");
|
||||
log(" -expand\n");
|
||||
log(" Expand shifts across binary operations:\n");
|
||||
log(" (a OP b) << c ===> (a << c) OP (b << c)\n");
|
||||
log(" (a OP b) >> c ===> (a >> c) OP (b >> c)\n");
|
||||
log(" where OP in {$and, $or, $xor, $add, $sub}\n");
|
||||
log("\n");
|
||||
log(" -max_iters n\n");
|
||||
log(" max number of pass iterations to run.\n");
|
||||
log("\n");
|
||||
log("If neither -combine nor -expand is given, both are run.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
log_header(design, "Executing OPT_SHIFT pass (shift optimizations).\n");
|
||||
|
||||
bool run_combine = false;
|
||||
bool run_expand = false;
|
||||
int max_iters = 10000;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
if (args[argidx] == "-combine") {
|
||||
run_combine = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-expand") {
|
||||
run_expand = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-max_iters" && argidx + 1 < args.size()) {
|
||||
max_iters = std::stoi(args[++argidx]);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
if (!run_combine && !run_expand) {
|
||||
run_combine = true;
|
||||
run_expand = true;
|
||||
}
|
||||
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
did_something = true;
|
||||
for (int i = 0; did_something && i < max_iters; i++)
|
||||
{
|
||||
did_something = false;
|
||||
peepopt_pm pm(module);
|
||||
pm.setup(module->selected_cells());
|
||||
if (run_combine)
|
||||
pm.run_combine_shifts();
|
||||
if (run_expand)
|
||||
pm.run_expand_shifts();
|
||||
}
|
||||
}
|
||||
}
|
||||
} OptShiftPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
pattern combine_shifts
|
||||
//
|
||||
// Authored by Akash Levy of Silimate, Inc. under ISC license.
|
||||
//
|
||||
// Combine nested shift operations
|
||||
//
|
||||
// Same direction:
|
||||
// (a << b) << c ===> a << (b + c)
|
||||
// (a >> b) >> c ===> a >> (b + c)
|
||||
// (a <<< b) <<< c ===> a <<< (b + c)
|
||||
// (a >>> b) >>> c ===> a >>> (b + c)
|
||||
// (a << b) <<< c ===> a << (b + c)
|
||||
// (a <<< b) << c ===> a <<< (b + c)
|
||||
// (a >> b) >>> c ===> a >> (b + c)
|
||||
// (a >>> b) >> c ===> a >>> (b + c)
|
||||
//
|
||||
// Mixed direction:
|
||||
// (a <</<< b) >>>/>> c ===> a <</<< (b - c)
|
||||
// (a >>>/>> b) <</<< c ===> a >>>/>> (b - c)
|
||||
//
|
||||
|
||||
state <SigSpec> inner_a inner_b inner_y outer_b outer_y
|
||||
|
||||
match inner_shift
|
||||
select inner_shift->type.in($shl, $shr, $sshl, $sshr)
|
||||
set inner_a port(inner_shift, \A)
|
||||
set inner_b port(inner_shift, \B)
|
||||
set inner_y port(inner_shift, \Y)
|
||||
endmatch
|
||||
|
||||
code
|
||||
if (nusers(inner_y) != 2)
|
||||
reject;
|
||||
endcode
|
||||
|
||||
match outer_shift
|
||||
select outer_shift->type.in($shl, $shr, $sshl, $sshr)
|
||||
index <SigSpec> port(outer_shift, \A) === inner_y
|
||||
set outer_b port(outer_shift, \B)
|
||||
set outer_y port(outer_shift, \Y)
|
||||
endmatch
|
||||
|
||||
code inner_a inner_b inner_y outer_b outer_y
|
||||
bool inner_is_left = inner_shift->type.in($shl, $sshl);
|
||||
bool outer_is_left = outer_shift->type.in($shl, $sshl);
|
||||
bool same_direction = (inner_is_left == outer_is_left);
|
||||
|
||||
// Unset all ports
|
||||
inner_shift->unsetPort(\A);
|
||||
inner_shift->unsetPort(\B);
|
||||
inner_shift->unsetPort(\Y);
|
||||
outer_shift->unsetPort(\A);
|
||||
outer_shift->unsetPort(\B);
|
||||
outer_shift->unsetPort(\Y);
|
||||
|
||||
Cell *cell = outer_shift;
|
||||
|
||||
// Create combined shift amount
|
||||
int combined_width = max(GetSize(inner_b), GetSize(outer_b)) + 1;
|
||||
Wire *combined_amt = module->addWire(NEW_ID2, combined_width);
|
||||
|
||||
if (same_direction) {
|
||||
// Same direction: b + c
|
||||
module->addAdd(NEW_ID2, inner_b, outer_b, combined_amt,
|
||||
false, cell->get_src_attribute());
|
||||
} else {
|
||||
// Mixed direction: b - c
|
||||
module->addSub(NEW_ID2, inner_b, outer_b, combined_amt,
|
||||
false, cell->get_src_attribute());
|
||||
}
|
||||
|
||||
// Reuse outer shift with inner shift's type, original data, and combined amount
|
||||
outer_shift->type = inner_shift->type;
|
||||
outer_shift->setPort(\A, inner_a);
|
||||
outer_shift->setPort(\B, combined_amt);
|
||||
outer_shift->setPort(\Y, outer_y);
|
||||
outer_shift->setParam(\A_SIGNED, inner_shift->getParam(\A_SIGNED));
|
||||
outer_shift->fixup_parameters();
|
||||
|
||||
// Rename for formal
|
||||
module->rename(outer_shift, NEW_ID2);
|
||||
|
||||
// Remove inner shift
|
||||
autoremove(inner_shift);
|
||||
|
||||
log("combine_shifts pattern in %s: inner=%s (%s), outer=%s (%s)\n",
|
||||
log_id(module), log_id(inner_shift), log_id(inner_shift->type),
|
||||
log_id(outer_shift), log_id(outer_shift->type));
|
||||
did_something = true;
|
||||
accept;
|
||||
endcode
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
pattern expand_shifts
|
||||
//
|
||||
// Authored by Akash Levy of Silimate, Inc. under ISC license.
|
||||
//
|
||||
// Expand shifts across binary operations
|
||||
//
|
||||
// y = (a OP b) << c ===> y = (a << c) OP (b << c)
|
||||
// y = (a OP b) >> c ===> y = (a >> c) OP (b >> c)
|
||||
// y = (a OP b) <<< c ===> y = (a <<< c) OP (b <<< c)
|
||||
// y = (a OP b) >>> c ===> y = (a >>> c) OP (b >>> c)
|
||||
//
|
||||
// where OP in {$and, $or, $xor, $add, $sub}
|
||||
//
|
||||
|
||||
state <SigSpec> op_a op_b op_y shift_amt shift_y
|
||||
|
||||
match op_gate
|
||||
// Select inner binary operation gate
|
||||
select op_gate->type.in($and, $or, $xor, $add, $sub)
|
||||
set op_a port(op_gate, \A)
|
||||
set op_b port(op_gate, \B)
|
||||
set op_y port(op_gate, \Y)
|
||||
endmatch
|
||||
|
||||
code
|
||||
// Fanout of each OP gate Y bit should be 1 (no bit-split)
|
||||
if (nusers(op_y) != 2)
|
||||
reject;
|
||||
endcode
|
||||
|
||||
match shift_gate
|
||||
// Select shift gate consuming the OP gate's output
|
||||
select shift_gate->type.in($shl, $shr, $sshl, $sshr)
|
||||
|
||||
// Connection: shift gate's A input is the OP gate's output
|
||||
index <SigSpec> port(shift_gate, \A) === op_y
|
||||
|
||||
set shift_amt port(shift_gate, \B)
|
||||
set shift_y port(shift_gate, \Y)
|
||||
endmatch
|
||||
|
||||
code op_a op_b op_y shift_amt shift_y
|
||||
// Unset all ports
|
||||
shift_gate->unsetPort(\A);
|
||||
shift_gate->unsetPort(\B);
|
||||
shift_gate->unsetPort(\Y);
|
||||
op_gate->unsetPort(\A);
|
||||
op_gate->unsetPort(\B);
|
||||
op_gate->unsetPort(\Y);
|
||||
|
||||
Cell *cell = shift_gate;
|
||||
|
||||
// Create new intermediate wires
|
||||
Wire *new_op_a = module->addWire(NEW_ID2, GetSize(shift_y));
|
||||
Wire *new_op_b = module->addWire(NEW_ID2, GetSize(shift_y));
|
||||
|
||||
// Create new shift gates: (a SHIFT c) and (b SHIFT c)
|
||||
Cell *new_shift_a = module->addCell(NEW_ID2, shift_gate->type);
|
||||
new_shift_a->setPort(\A, op_a);
|
||||
new_shift_a->setPort(\B, shift_amt);
|
||||
new_shift_a->setPort(\Y, new_op_a);
|
||||
new_shift_a->setParam(\A_SIGNED, shift_gate->getParam(\A_SIGNED));
|
||||
new_shift_a->setParam(\B_SIGNED, shift_gate->getParam(\B_SIGNED));
|
||||
new_shift_a->fixup_parameters();
|
||||
new_shift_a->set_src_attribute(cell->get_src_attribute());
|
||||
|
||||
Cell *new_shift_b = module->addCell(NEW_ID2, shift_gate->type);
|
||||
new_shift_b->setPort(\A, op_b);
|
||||
new_shift_b->setPort(\B, shift_amt);
|
||||
new_shift_b->setPort(\Y, new_op_b);
|
||||
new_shift_b->setParam(\A_SIGNED, shift_gate->getParam(\A_SIGNED));
|
||||
new_shift_b->setParam(\B_SIGNED, shift_gate->getParam(\B_SIGNED));
|
||||
new_shift_b->fixup_parameters();
|
||||
new_shift_b->set_src_attribute(cell->get_src_attribute());
|
||||
|
||||
// Update OP gate to take shifted inputs and produce final output
|
||||
op_gate->setPort(\A, new_op_a);
|
||||
op_gate->setPort(\B, new_op_b);
|
||||
op_gate->setPort(\Y, shift_y);
|
||||
op_gate->fixup_parameters();
|
||||
|
||||
// Rename OP gate for formal
|
||||
cell = op_gate;
|
||||
module->rename(op_gate, NEW_ID2);
|
||||
|
||||
// Remove original shift gate
|
||||
autoremove(shift_gate);
|
||||
|
||||
// Log, fixup, accept
|
||||
log("expand_shifts pattern in %s: op=%s (%s), shift=%s (%s)\n", log_id(module), log_id(op_gate), log_id(op_gate->type), log_id(shift_gate), log_id(shift_gate->type));
|
||||
did_something = true;
|
||||
accept;
|
||||
endcode
|
||||
|
|
@ -0,0 +1,377 @@
|
|||
log -header "Same direction SHL: (a << b) << c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [2:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a << b) << c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -combine
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$shl
|
||||
select -assert-count 1 t:$add
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Same direction SHR: (a >> b) >> c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [2:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a >> b) >> c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -combine
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$shr
|
||||
select -assert-count 1 t:$add
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Same direction SSHR: (a >>> b) >>> c (signed arithmetic)"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire signed [7:0] a,
|
||||
input wire [2:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire signed [7:0] x
|
||||
);
|
||||
assign x = (a >>> b) >>> c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -combine
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$sshr
|
||||
select -assert-count 1 t:$add
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Negative case: fanout from intermediate wire prevents combining"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [2:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] m,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign m = a << b;
|
||||
assign x = m << c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -combine
|
||||
design -load postopt
|
||||
select -assert-count 2 t:$shl
|
||||
select -assert-count 0 t:$add
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Triple chain: ((a << b) << c) << d"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [2:0] b,
|
||||
input wire [2:0] c,
|
||||
input wire [2:0] d,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = ((a << b) << c) << d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -combine
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$shl
|
||||
select -assert-count 2 t:$add
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Mixed direction: (a << b) >> c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [2:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a << b) >> c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
opt_shift -combine
|
||||
select -assert-count 1 t:$shl
|
||||
select -assert-count 0 t:$shr
|
||||
select -assert-count 1 t:$sub
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Mixed direction: (a >> b) << c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [2:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a >> b) << c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
opt_shift -combine
|
||||
select -assert-count 0 t:$shl
|
||||
select -assert-count 1 t:$shr
|
||||
select -assert-count 1 t:$sub
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Cross-type same direction: $shr then $sshr"
|
||||
log -push
|
||||
design -reset
|
||||
read_rtlil <<EOF
|
||||
autoidx 1
|
||||
module \top
|
||||
wire width 8 input 1 \a
|
||||
wire width 3 input 2 \b
|
||||
wire width 3 input 3 \c
|
||||
wire width 8 output 4 \x
|
||||
wire width 8 \t
|
||||
cell $shr \shr_cell
|
||||
parameter \A_SIGNED 0
|
||||
parameter \B_SIGNED 0
|
||||
parameter \A_WIDTH 8
|
||||
parameter \B_WIDTH 3
|
||||
parameter \Y_WIDTH 8
|
||||
connect \A \a
|
||||
connect \B \b
|
||||
connect \Y \t
|
||||
end
|
||||
cell $sshr \sshr_cell
|
||||
parameter \A_SIGNED 1
|
||||
parameter \B_SIGNED 0
|
||||
parameter \A_WIDTH 8
|
||||
parameter \B_WIDTH 3
|
||||
parameter \Y_WIDTH 8
|
||||
connect \A \t
|
||||
connect \B \c
|
||||
connect \Y \x
|
||||
end
|
||||
end
|
||||
EOF
|
||||
check -assert
|
||||
opt_shift -combine
|
||||
select -assert-count 1 t:$shr
|
||||
select -assert-count 0 t:$sshr
|
||||
select -assert-count 1 t:$add
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Cross-type same direction: $sshr then $shr"
|
||||
log -push
|
||||
design -reset
|
||||
read_rtlil <<EOF
|
||||
autoidx 1
|
||||
module \top
|
||||
wire width 8 input 1 \a
|
||||
wire width 3 input 2 \b
|
||||
wire width 3 input 3 \c
|
||||
wire width 8 output 4 \x
|
||||
wire width 8 \t
|
||||
cell $sshr \sshr_cell
|
||||
parameter \A_SIGNED 1
|
||||
parameter \B_SIGNED 0
|
||||
parameter \A_WIDTH 8
|
||||
parameter \B_WIDTH 3
|
||||
parameter \Y_WIDTH 8
|
||||
connect \A \a
|
||||
connect \B \b
|
||||
connect \Y \t
|
||||
end
|
||||
cell $shr \shr_cell
|
||||
parameter \A_SIGNED 0
|
||||
parameter \B_SIGNED 0
|
||||
parameter \A_WIDTH 8
|
||||
parameter \B_WIDTH 3
|
||||
parameter \Y_WIDTH 8
|
||||
connect \A \t
|
||||
connect \B \c
|
||||
connect \Y \x
|
||||
end
|
||||
end
|
||||
EOF
|
||||
check -assert
|
||||
opt_shift -combine
|
||||
select -assert-count 0 t:$shr
|
||||
select -assert-count 1 t:$sshr
|
||||
select -assert-count 1 t:$add
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Cross-type mixed direction: $sshr then $shl"
|
||||
log -push
|
||||
design -reset
|
||||
read_rtlil <<EOF
|
||||
autoidx 1
|
||||
module \top
|
||||
wire width 8 input 1 \a
|
||||
wire width 3 input 2 \b
|
||||
wire width 3 input 3 \c
|
||||
wire width 8 output 4 \x
|
||||
wire width 8 \t
|
||||
cell $sshr \sshr_cell
|
||||
parameter \A_SIGNED 1
|
||||
parameter \B_SIGNED 0
|
||||
parameter \A_WIDTH 8
|
||||
parameter \B_WIDTH 3
|
||||
parameter \Y_WIDTH 8
|
||||
connect \A \a
|
||||
connect \B \b
|
||||
connect \Y \t
|
||||
end
|
||||
cell $shl \shl_cell
|
||||
parameter \A_SIGNED 0
|
||||
parameter \B_SIGNED 0
|
||||
parameter \A_WIDTH 8
|
||||
parameter \B_WIDTH 3
|
||||
parameter \Y_WIDTH 8
|
||||
connect \A \t
|
||||
connect \B \c
|
||||
connect \Y \x
|
||||
end
|
||||
end
|
||||
EOF
|
||||
check -assert
|
||||
opt_shift -combine
|
||||
select -assert-count 0 t:$shl
|
||||
select -assert-count 1 t:$sshr
|
||||
select -assert-count 1 t:$sub
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Cross-type mixed direction: $shl then $sshr"
|
||||
log -push
|
||||
design -reset
|
||||
read_rtlil <<EOF
|
||||
autoidx 1
|
||||
module \top
|
||||
wire width 8 input 1 \a
|
||||
wire width 3 input 2 \b
|
||||
wire width 3 input 3 \c
|
||||
wire width 8 output 4 \x
|
||||
wire width 8 \t
|
||||
cell $shl \shl_cell
|
||||
parameter \A_SIGNED 0
|
||||
parameter \B_SIGNED 0
|
||||
parameter \A_WIDTH 8
|
||||
parameter \B_WIDTH 3
|
||||
parameter \Y_WIDTH 8
|
||||
connect \A \a
|
||||
connect \B \b
|
||||
connect \Y \t
|
||||
end
|
||||
cell $sshr \sshr_cell
|
||||
parameter \A_SIGNED 1
|
||||
parameter \B_SIGNED 0
|
||||
parameter \A_WIDTH 8
|
||||
parameter \B_WIDTH 3
|
||||
parameter \Y_WIDTH 8
|
||||
connect \A \t
|
||||
connect \B \c
|
||||
connect \Y \x
|
||||
end
|
||||
end
|
||||
EOF
|
||||
check -assert
|
||||
opt_shift -combine
|
||||
select -assert-count 1 t:$shl
|
||||
select -assert-count 0 t:$sshr
|
||||
select -assert-count 1 t:$sub
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "1-bit operands: (a << b) << c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire a,
|
||||
input wire [2:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a << b) << c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -combine
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$shl
|
||||
select -assert-count 1 t:$add
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Constant shift amounts: (a << 3) << 2"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a << 3) << 2;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -combine
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$shl
|
||||
select -assert-count 1 t:$add
|
||||
design -reset
|
||||
log -pop
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
log -header "SHL across AND: (a & b) << c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a & b) << c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$and
|
||||
select -assert-count 2 t:$shl
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "SHL across OR: (a | b) << c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a | b) << c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$or
|
||||
select -assert-count 2 t:$shl
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "SHL across XOR: (a ^ b) << c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a ^ b) << c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$xor
|
||||
select -assert-count 2 t:$shl
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "SHL across ADD: (a + b) << c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a + b) << c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$add
|
||||
select -assert-count 2 t:$shl
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "SHL across SUB: (a - b) << c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a - b) << c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$sub
|
||||
select -assert-count 2 t:$shl
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "SHR across AND: (a & b) >> c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a & b) >> c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$and
|
||||
select -assert-count 2 t:$shr
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "SHR across XOR: (a ^ b) >> c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a ^ b) >> c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$xor
|
||||
select -assert-count 2 t:$shr
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "SSHR (arithmetic right shift) across AND: signed (a & b) >>> c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire signed [7:0] a,
|
||||
input wire signed [7:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire signed [7:0] x
|
||||
);
|
||||
assign x = (a & b) >>> c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$and
|
||||
select -assert-count 2 t:$sshr
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Negative case: fanout from intermediate wire prevents expansion"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] m,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign m = a & b;
|
||||
assign x = m << c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$and
|
||||
select -assert-count 1 t:$shl
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "1-bit operands: (a & b) << c"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire a,
|
||||
input wire b,
|
||||
input wire [2:0] c,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = (a & b) << c;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$and
|
||||
select -assert-count 2 t:$shl
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Nested: ((a | b) << c) ^ d"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [2:0] c,
|
||||
input wire [7:0] d,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = ((a | b) << c) ^ d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$xor
|
||||
select -assert-count 1 t:$or
|
||||
select -assert-count 2 t:$shl
|
||||
design -reset
|
||||
log -pop
|
||||
|
||||
|
||||
|
||||
log -header "Chained shifts: ((a + b) << c) << d"
|
||||
log -push
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top (
|
||||
input wire [7:0] a,
|
||||
input wire [7:0] b,
|
||||
input wire [2:0] c,
|
||||
input wire [2:0] d,
|
||||
output wire [7:0] x
|
||||
);
|
||||
assign x = ((a + b) << c) << d;
|
||||
endmodule
|
||||
EOF
|
||||
check -assert
|
||||
equiv_opt -assert opt_shift -expand
|
||||
design -load postopt
|
||||
select -assert-count 1 t:$add
|
||||
select -assert-count 4 t:$shl
|
||||
design -reset
|
||||
log -pop
|
||||
Loading…
Reference in New Issue