techmap/shift_shiftx: Remove the "shiftx2mux" special path.

Our techmap rules for $shift and $shiftx cells contained a special path
that aimed to decompose the shift LSB-first instead of MSB-first in
select cases that come up in pmux lowering.  This path was needlessly
overcomplicated and contained bugs.

Instead of doing that, just switch over the main path to iterate
LSB-first (except for the specially-handled MSB for signed shifts
and overflow handling).  This also makes the code consistent with
shl/shr/sshl/sshr cells, which are already decomposed LSB-first.

Fixes #2346.
This commit is contained in:
Marcelina Kościelnicka 2020-08-19 13:59:59 +02:00
parent 93d663be62
commit 50d532f01c
3 changed files with 38 additions and 81 deletions

View File

@ -143,78 +143,46 @@ module _90_shift_shiftx (A, B, Y);
localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx;
wire a_padding = _TECHMAP_CELLTYPE_ == "$shiftx" ? extbit : (A_SIGNED ? A[A_WIDTH-1] : 1'b0);
generate
`ifndef NO_LSB_FIRST_SHIFT_SHIFTX
// If $shift/$shiftx only shifts in units of Y_WIDTH
// (a common pattern created by pmux2shiftx)
// which is checked by ensuring that all that
// the appropriate LSBs of B are constant zero,
// then we can decompose LSB first instead of
// MSB first
localparam CLOG2_Y_WIDTH = $clog2(Y_WIDTH);
if (B_WIDTH > CLOG2_Y_WIDTH+1 &&
_TECHMAP_CONSTMSK_B_[CLOG2_Y_WIDTH-1:0] == {CLOG2_Y_WIDTH{1'b1}} &&
_TECHMAP_CONSTVAL_B_[CLOG2_Y_WIDTH-1:0] == {CLOG2_Y_WIDTH{1'b0}}) begin
// Halve the size of $shift/$shiftx by $mux-ing A according to
// the LSB of B, after discarding the zeroed bits
localparam Y_WIDTH2 = 2**CLOG2_Y_WIDTH;
localparam entries = (A_WIDTH+Y_WIDTH-1)/Y_WIDTH2;
localparam len = Y_WIDTH2 * ((entries+1)/2);
wire [len-1:0] AA;
wire [(A_WIDTH+Y_WIDTH2+Y_WIDTH-1)-1:0] Apad = {{(Y_WIDTH2+Y_WIDTH-1){a_padding}}, A};
genvar i;
for (i = 0; i < A_WIDTH; i=i+Y_WIDTH2*2)
assign AA[i/2 +: Y_WIDTH2] = B[CLOG2_Y_WIDTH] ? Apad[i+Y_WIDTH2 +: Y_WIDTH2] : Apad[i +: Y_WIDTH2];
wire [B_WIDTH-2:0] BB = {B[B_WIDTH-1:CLOG2_Y_WIDTH+1], {CLOG2_Y_WIDTH{1'b0}}};
if (_TECHMAP_CELLTYPE_ == "$shift")
$shift #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(len), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(AA), .B(BB), .Y(Y));
else
$shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(len), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(AA), .B(BB), .Y(Y));
end
else
`endif
begin
localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH);
localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0);
localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH);
localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0);
wire [1023:0] _TECHMAP_DO_00_ = "proc;;";
wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_expr -mux_undef -mux_bool -fine;;;";
wire [1023:0] _TECHMAP_DO_00_ = "proc;;";
wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_expr -mux_undef -mux_bool -fine;;;";
integer i;
(* force_downto *)
reg [WIDTH-1:0] buffer;
reg overflow;
integer i;
(* force_downto *)
reg [WIDTH-1:0] buffer;
reg overflow;
always @* begin
overflow = 0;
always @* begin
overflow = 0;
buffer = {WIDTH{extbit}};
buffer[Y_WIDTH-1:0] = {Y_WIDTH{a_padding}};
buffer[A_WIDTH-1:0] = A;
if (B_WIDTH > BB_WIDTH) begin
if (B_SIGNED) begin
for (i = BB_WIDTH; i < B_WIDTH; i = i+1)
if (B[i] != B[BB_WIDTH-1])
overflow = 1;
end else
overflow = |B[B_WIDTH-1:BB_WIDTH];
if (overflow)
buffer = {WIDTH{extbit}};
buffer[Y_WIDTH-1:0] = {Y_WIDTH{a_padding}};
buffer[A_WIDTH-1:0] = A;
if (B_WIDTH > BB_WIDTH) begin
if (B_SIGNED) begin
for (i = BB_WIDTH; i < B_WIDTH; i = i+1)
if (B[i] != B[BB_WIDTH-1])
overflow = 1;
end else
overflow = |B[B_WIDTH-1:BB_WIDTH];
if (overflow)
buffer = {WIDTH{extbit}};
end
for (i = BB_WIDTH-1; i >= 0; i = i-1)
if (B[i]) begin
if (B_SIGNED && i == BB_WIDTH-1)
buffer = {buffer, {2**i{extbit}}};
else if (2**i < WIDTH)
buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]};
else
buffer = {WIDTH{extbit}};
end
end
assign Y = buffer;
end
endgenerate
if (B_SIGNED && B[BB_WIDTH-1])
buffer = {buffer, {2**(BB_WIDTH-1){extbit}}};
for (i = 0; i < (B_SIGNED ? BB_WIDTH-1 : BB_WIDTH); i = i+1)
if (B[i]) begin
if (2**i < WIDTH)
buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]};
else
buffer = {WIDTH{extbit}};
end
end
assign Y = buffer;
endmodule

View File

@ -70,8 +70,9 @@ equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cycl
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux16 # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_ALUT3
select -assert-count 5 t:MISTRAL_ALUT6
select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT6 %% t:* %D
select -assert-max 2 t:MISTRAL_ALUT5
select -assert-max 5 t:MISTRAL_ALUT6
select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D
design -load read

View File

@ -73,12 +73,6 @@ pmux2shiftx
design -save gold
design -load gold
techmap -D NO_LSB_FIRST_SHIFT_SHIFTX
abc -lut 6
select -assert-min 17 t:$lut
design -load gold
techmap
abc -lut 6
@ -91,12 +85,6 @@ miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter
design -load gold
techmap -D NO_LSB_FIRST_SHIFT_SHIFTX
abc9 -lut 6
select -assert-min 17 t:$lut
design -load gold
techmap
abc9 -lut 6