From c8763301b436d05c1040adb1615e75ccbfde93e8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 9 Aug 2013 17:09:24 +0200 Subject: Added $div and $mod technology mapping --- frontends/ast/genrtlil.cc | 2 +- techlibs/stdcells.v | 102 ++++++++++++++++++++++++++++++++++++++++++---- tests/simple/operators.v | 61 +++++++++++++++++---------- tests/tools/autotest.sh | 6 +-- 4 files changed, 137 insertions(+), 34 deletions(-) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index e7ceec5f..9c027878 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -968,7 +968,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (width > width_hint && width_hint > 0) width = width_hint; if (width < width_hint) { - if (type == AST_ADD || type == AST_SUB) + if (type == AST_ADD || type == AST_SUB || type == AST_DIV) width++; if (type == AST_SUB && (!children[0]->is_signed || !children[1]->is_signed)) width = width_hint; diff --git a/techlibs/stdcells.v b/techlibs/stdcells.v index 304280bf..c411ba35 100644 --- a/techlibs/stdcells.v +++ b/techlibs/stdcells.v @@ -993,7 +993,76 @@ wire [Y_WIDTH-1:0] A_buf, B_buf; endmodule -/**** +// -------------------------------------------------------- + +module \$div_mod_u (A, B, Y, R); + +parameter WIDTH = 1; + +input [WIDTH-1:0] A, B; +output [WIDTH-1:0] Y, R; + +wire [WIDTH*WIDTH-1:0] chaindata; +assign R = chaindata[WIDTH*WIDTH-1:WIDTH*(WIDTH-1)]; + +genvar i; +generate begin + for (i = 0; i < WIDTH; i=i+1) begin:stage + wire [WIDTH-1:0] stage_in; + + if (i == 0) begin:cp + assign stage_in = A; + end else begin:cp + assign stage_in = chaindata[i*WIDTH-1:(i-1)*WIDTH]; + end + + assign Y[WIDTH-(i+1)] = stage_in >= {B, {WIDTH-(i+1){1'b0}}}; + assign chaindata[(i+1)*WIDTH-1:i*WIDTH] = Y[WIDTH-(i+1)] ? stage_in - {B, {WIDTH-(i+1){1'b0}}} : stage_in; + end +end endgenerate + +endmodule + +// -------------------------------------------------------- + +module \$div_mod (A, B, Y, R); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 1; +parameter B_WIDTH = 1; +parameter Y_WIDTH = 1; + +localparam WIDTH = + A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : + B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y, R; + +wire [WIDTH-1:0] A_buf, B_buf; +\$pos #(.A_SIGNED(A_SIGNED && B_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); +\$pos #(.A_SIGNED(A_SIGNED && B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + +wire [WIDTH-1:0] A_buf_u, B_buf_u, Y_u, R_u; +assign A_buf_u = A_SIGNED && B_SIGNED && A_buf[WIDTH-1] ? -A_buf : A_buf; +assign B_buf_u = A_SIGNED && B_SIGNED && B_buf[WIDTH-1] ? -B_buf : B_buf; + +\$div_mod_u #( + .WIDTH(WIDTH) +) div_mod_u ( + .A(A_buf_u), + .B(B_buf_u), + .Y(Y_u), + .R(R_u), +); + +assign Y = A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? -Y_u : Y_u; +assign R = A_SIGNED && B_SIGNED && A_buf[WIDTH-1] ? -R_u : R_u; + +endmodule + // -------------------------------------------------------- module \$div (A, B, Y); @@ -1008,10 +1077,17 @@ input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; -wire signed [A_WIDTH:0] buffer_a = A_SIGNED ? $signed(A) : A; -wire signed [B_WIDTH:0] buffer_b = B_SIGNED ? $signed(B) : B; - -assign Y = buffer_a / buffer_b; +\$div_mod #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) +) div_mod ( + .A(A), + .B(B), + .Y(Y) +); endmodule @@ -1029,13 +1105,21 @@ input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; -wire signed [A_WIDTH:0] buffer_a = A_SIGNED ? $signed(A) : A; -wire signed [B_WIDTH:0] buffer_b = B_SIGNED ? $signed(B) : B; - -assign Y = buffer_a % buffer_b; +\$div_mod #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) +) div_mod ( + .A(A), + .B(B), + .R(Y) +); endmodule +/**** // -------------------------------------------------------- module \$pow (A, B, Y); diff --git a/tests/simple/operators.v b/tests/simple/operators.v index b9bbc13c..6ca6ca7a 100644 --- a/tests/simple/operators.v +++ b/tests/simple/operators.v @@ -1,8 +1,7 @@ - module test(clk, mode, u1, s1, u2, s2, y); input clk; -input [5:0] mode; +input [6:0] mode; input [3:0] u1, u2; input signed [3:0] s1, s2; @@ -72,25 +71,45 @@ always @(posedge clk) begin 46: y <= s1 - u2; 47: y <= s1 - s2; - 48: y <= +u1; - 49: y <= -u1; - 50: y <= +s1; - 51: y <= -s1; - - 52: y <= { &u1, ~&u1, |u1, ~|u1, ^u1, ~^u1, ^~u1 }; - 53: y <= { &s1, ~&s1, |s1, ~|s1, ^s1, ~^s1, ^~s1 }; - 54: y <= { &u1[1:0], ~&u1[1:0], |u1[1:0], ~|u1[1:0], ^u1[1:0], ~^u1[1:0], ^~u1[1:0] }; - 55: y <= { &s1[1:0], ~&s1[1:0], |s1[1:0], ~|s1[1:0], ^s1[1:0], ~^s1[1:0], ^~s1[1:0] }; - - 56: y <= { u1[1:0] && u2[1:0], u1[1:0] && u2[1:0], !u1[1:0] }; - 57: y <= {4{u1[1:0]}}; - 58: y <= {u1, u2} ^ {s1, s2}; - 59: y <= {u1, u2} & {s1, s2}; - - 60: y <= u1[0] ? u1 : u2; - 61: y <= u1[0] ? u1 : s2; - 62: y <= u1[0] ? s1 : u2; - 63: y <= u1[0] ? s1 : s2; + 48: y <= u1 * u2; + 49: y <= u1 * s2; + 50: y <= s1 * u2; + 51: y <= s1 * s2; + + 52: y <= u1 / u2; + 53: y <= u1 / s2; + 54: y <= s1 / u2; + 55: y <= s1 / s2; + + 56: y <= u1 % u2; + 57: y <= u1 % s2; + 58: y <= s1 % u2; + 59: y <= s1 % s2; + + 60: y <= +u1; + 61: y <= -u1; + 62: y <= ~u1; + 63: y <= !u1; + + 64: y <= +s1; + 65: y <= -s1; + 66: y <= ~s1; + 67: y <= !s1; + + 68: y <= { &u1, ~&u1, |u1, ~|u1, ^u1, ~^u1, ^~u1 }; + 69: y <= { &s1, ~&s1, |s1, ~|s1, ^s1, ~^s1, ^~s1 }; + 70: y <= { &u1[1:0], ~&u1[1:0], |u1[1:0], ~|u1[1:0], ^u1[1:0], ~^u1[1:0], ^~u1[1:0] }; + 71: y <= { &s1[1:0], ~&s1[1:0], |s1[1:0], ~|s1[1:0], ^s1[1:0], ~^s1[1:0], ^~s1[1:0] }; + + 72: y <= { u1[1:0] && u2[1:0], u1[1:0] && u2[1:0], !u1[1:0] }; + 73: y <= {4{u1[1:0]}}; + 74: y <= {u1, u2} ^ {s1, s2}; + 75: y <= {u1, u2} & {s1, s2}; + + 76: y <= u1[0] ? u1 : u2; + 77: y <= u1[0] ? u1 : s2; + 78: y <= u1[0] ? s1 : u2; + 79: y <= u1[0] ? s1 : s2; endcase end diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index e599db3a..cb1e3a96 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -140,9 +140,9 @@ do if [ -n "$scriptfiles" ]; then test_passes else - test_passes -p hierarchy -p proc -p memory -p opt -p fsm -p opt - test_passes -p hierarchy -p proc -p memory -p opt -p fsm -p opt -p techmap -p opt - # test_passes -p hierarchy -p proc -p memory -p opt -p techmap -p opt -p abc -p opt + test_passes -p "hierarchy; proc; memory; opt; fsm; opt" + test_passes -p "hierarchy; proc; memory; opt; fsm; opt; techmap; opt" + # test_passes -p "hierarchy; proc; memory; opt; fsm; opt; techmap -opt; opt; abc; opt" fi touch ../${bn}.log } -- cgit v1.2.3