mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-30 04:15:52 +00:00
Merge pull request #5066 from YosysHQ/george/opt_expr_shr_sign
opt_expr: fix sign extension for shifts
This commit is contained in:
commit
bfe05965f9
3 changed files with 58 additions and 7 deletions
|
@ -247,7 +247,7 @@ void shift_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
db->add_edge(cell, ID::A, a_width - 1, ID::Y, i, -1);
|
db->add_edge(cell, ID::A, a_width - 1, ID::Y, i, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int k = 0; k < b_width; k++) {
|
for (int k = 0; k < b_width_capped; k++) {
|
||||||
// left shifts
|
// left shifts
|
||||||
if (cell->type.in(ID($shl), ID($sshl))) {
|
if (cell->type.in(ID($shl), ID($sshl))) {
|
||||||
if (a_width == 1 && is_signed) {
|
if (a_width == 1 && is_signed) {
|
||||||
|
@ -268,7 +268,7 @@ void shift_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
bool shift_in_bulk = i < a_width - 1;
|
bool shift_in_bulk = i < a_width - 1;
|
||||||
// can we jump into the zero-padding by toggling B[k]?
|
// can we jump into the zero-padding by toggling B[k]?
|
||||||
bool zpad_jump = (((y_width - i) & ((1 << (k + 1)) - 1)) != 0 \
|
bool zpad_jump = (((y_width - i) & ((1 << (k + 1)) - 1)) != 0 \
|
||||||
&& (((y_width - i) & ~(1 << k)) < (1 << b_width)));
|
&& (((y_width - i) & ~(1 << k)) < (1 << b_width_capped)));
|
||||||
|
|
||||||
if (shift_in_bulk || (cell->type.in(ID($shr), ID($shift), ID($shiftx)) && zpad_jump))
|
if (shift_in_bulk || (cell->type.in(ID($shr), ID($shift), ID($shiftx)) && zpad_jump))
|
||||||
db->add_edge(cell, ID::B, k, ID::Y, i, -1);
|
db->add_edge(cell, ID::B, k, ID::Y, i, -1);
|
||||||
|
@ -279,7 +279,7 @@ void shift_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||||
// bidirectional shifts (positive B shifts right, negative left)
|
// bidirectional shifts (positive B shifts right, negative left)
|
||||||
} else if (cell->type.in(ID($shift), ID($shiftx)) && is_b_signed) {
|
} else if (cell->type.in(ID($shift), ID($shiftx)) && is_b_signed) {
|
||||||
if (is_signed) {
|
if (is_signed) {
|
||||||
if (k != b_width - 1) {
|
if (k != b_width_capped - 1) {
|
||||||
bool r_shift_in_bulk = i < a_width - 1;
|
bool r_shift_in_bulk = i < a_width - 1;
|
||||||
// assuming B is positive, can we jump into the upper zero-padding by toggling B[k]?
|
// assuming B is positive, can we jump into the upper zero-padding by toggling B[k]?
|
||||||
bool r_zpad_jump = (((y_width - i) & ((1 << (k + 1)) - 1)) != 0 \
|
bool r_zpad_jump = (((y_width - i) & ((1 << (k + 1)) - 1)) != 0 \
|
||||||
|
|
|
@ -1315,13 +1315,14 @@ skip_fine_alu:
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_y(cell->type == ID($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID::Y_WIDTH).as_int());
|
RTLIL::SigSpec sig_y(cell->type == ID($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID::Y_WIDTH).as_int());
|
||||||
|
|
||||||
// Limit indexing to the size of a, which is behaviourally identical (result is all 0)
|
|
||||||
// and avoids integer overflow of i + shift_bits when e.g. ID::B == INT_MAX
|
|
||||||
shift_bits = min(shift_bits, GetSize(sig_a));
|
|
||||||
|
|
||||||
if (cell->type != ID($shiftx) && GetSize(sig_a) < GetSize(sig_y))
|
if (cell->type != ID($shiftx) && GetSize(sig_a) < GetSize(sig_y))
|
||||||
sig_a.extend_u0(GetSize(sig_y), cell->getParam(ID::A_SIGNED).as_bool());
|
sig_a.extend_u0(GetSize(sig_y), cell->getParam(ID::A_SIGNED).as_bool());
|
||||||
|
|
||||||
|
// Limit indexing to the size of a, which is behaviourally identical (result is all 0)
|
||||||
|
// and avoids integer overflow of i + shift_bits when e.g. ID::B == INT_MAX.
|
||||||
|
// We do this after sign-extending a so this accounts for the output size
|
||||||
|
shift_bits = min(shift_bits, GetSize(sig_a));
|
||||||
|
|
||||||
for (int i = 0; i < GetSize(sig_y); i++) {
|
for (int i = 0; i < GetSize(sig_y); i++) {
|
||||||
int idx = i + shift_bits;
|
int idx = i + shift_bits;
|
||||||
if (0 <= idx && idx < GetSize(sig_a))
|
if (0 <= idx && idx < GetSize(sig_a))
|
||||||
|
|
50
tests/opt/opt_expr_shift.ys
Normal file
50
tests/opt/opt_expr_shift.ys
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# Testing edge cases where ports are signed/have different widths/shift amounts
|
||||||
|
# greater than the size
|
||||||
|
|
||||||
|
read_verilog <<EOT
|
||||||
|
module top (
|
||||||
|
input wire [3:0] in_u,
|
||||||
|
input wire signed [3:0] in_s,
|
||||||
|
output wire [7:0] shl_uu,
|
||||||
|
output wire signed [7:0] shl_us,
|
||||||
|
output wire [7:0] shl_su,
|
||||||
|
output wire signed [7:0] shl_ss,
|
||||||
|
output wire [7:0] shr_uu,
|
||||||
|
output wire signed [7:0] shr_us,
|
||||||
|
output wire [7:0] shr_su,
|
||||||
|
output wire signed [7:0] shr_ss,
|
||||||
|
output wire [7:0] sshl_uu,
|
||||||
|
output wire signed [7:0] sshl_us,
|
||||||
|
output wire [7:0] sshl_su,
|
||||||
|
output wire signed [7:0] sshl_ss,
|
||||||
|
output wire [7:0] sshr_uu,
|
||||||
|
output wire signed [7:0] sshr_us,
|
||||||
|
output wire [7:0] sshr_su,
|
||||||
|
output wire signed [7:0] sshr_ss
|
||||||
|
);
|
||||||
|
assign shl_uu = in_u << 20;
|
||||||
|
assign shl_us = in_u << 20;
|
||||||
|
assign shl_su = in_s << 20;
|
||||||
|
assign shl_ss = in_s << 20;
|
||||||
|
assign shr_uu = in_u >> 20;
|
||||||
|
assign shr_us = in_u >> 20;
|
||||||
|
assign shr_su = in_s >> 20;
|
||||||
|
assign shr_ss = in_s >> 20;
|
||||||
|
assign sshl_uu = in_u <<< 20;
|
||||||
|
assign sshl_us = in_u <<< 20;
|
||||||
|
assign sshl_su = in_s <<< 20;
|
||||||
|
assign sshl_ss = in_s <<< 20;
|
||||||
|
assign sshr_uu = in_u >>> 20;
|
||||||
|
assign sshr_us = in_u >>> 20;
|
||||||
|
assign sshr_su = in_s >>> 20;
|
||||||
|
assign sshr_ss = in_s >>> 20;
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
|
||||||
|
equiv_opt opt_expr
|
||||||
|
|
||||||
|
design -load postopt
|
||||||
|
select -assert-none t:$shl
|
||||||
|
select -assert-none t:$shr
|
||||||
|
select -assert-none t:$sshl
|
||||||
|
select -assert-none t:$sshr
|
Loading…
Add table
Add a link
Reference in a new issue