Added $div and $mod technology mapping
authorClifford Wolf <clifford@clifford.at>
Fri, 9 Aug 2013 15:09:24 +0000 (17:09 +0200)
committerClifford Wolf <clifford@clifford.at>
Fri, 9 Aug 2013 15:09:24 +0000 (17:09 +0200)
frontends/ast/genrtlil.cc
techlibs/stdcells.v
tests/simple/operators.v
tests/tools/autotest.sh

index e7ceec5f9d277372cc38ef0765dece1d4c358ed1..9c027878aa379a8ddf5d1f25895b19a3afcec3ff 100644 (file)
@@ -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;
index 304280bf6d288c869ec95897f9def91391d14b21..c411ba35bb1bb82df10abe7c6a7b5f645f6f4df5 100644 (file)
@@ -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);
index b9bbc13c83efa088f630e04b05117fa0cb12e71e..6ca6ca7a8ee5539c1f1ec725d39986136e4e445b 100644 (file)
@@ -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
 
index e599db3a1ba54e38929b85a1d5baf5b2a7b23937..cb1e3a96d11decd42c855b6f0ec6089fb5d8dcd3 100755 (executable)
@@ -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
        }