More progress on Firrtl backend.
authorAdam Izraelevitz <azidar@gmail.com>
Tue, 22 Nov 2016 01:28:17 +0000 (17:28 -0800)
committerAdam Izraelevitz <azidar@gmail.com>
Mon, 13 Feb 2017 19:17:53 +0000 (11:17 -0800)
Chisel -> Firrtl -> Verilog -> Firrtl -> Verilog is successful for a
simple rocket-chip design.

backends/firrtl/firrtl.cc
backends/firrtl/test.sh
backends/firrtl/test.v

index 0d1c1889d56c97e0b8a78fe95173b2f85976f2d9..06cbc9b2b3da8746c12c43a0177e116051ea2bd9 100644 (file)
@@ -157,7 +157,53 @@ struct FirrtlWorker
 
                for (auto cell : module->cells())
                {
-                       if (cell->type.in("$add", "$sub", "$xor"))
+                       if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor"))
+                       {
+                               string y_id = make_id(cell->name);
+                               bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
+                               int y_width =  cell->parameters.at("\\Y_WIDTH").as_int();
+                               string a_expr = make_expr(cell->getPort("\\A"));
+                               wire_decls.push_back(stringf("    wire %s: UInt<%d>\n", y_id.c_str(), y_width));
+
+                               if (cell->parameters.at("\\A_SIGNED").as_bool()) {
+                                       a_expr = "asSInt(" + a_expr + ")";
+                               }
+
+                               a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
+
+                               string primop;
+                                bool always_uint = false;
+                               if (cell->type == "$not") primop = "not";
+                               if (cell->type == "$neg") primop = "neg";
+                               if (cell->type == "$logic_not") {
+                                        primop = "eq";
+                                        a_expr = stringf("%s, UInt(0)", a_expr.c_str());
+                                }
+                               if (cell->type == "$reduce_and") primop = "andr";
+                               if (cell->type == "$reduce_or") primop = "orr";
+                               if (cell->type == "$reduce_xor") primop = "xorr";
+                               if (cell->type == "$reduce_xnor") {
+                                        primop = "not";
+                                        a_expr = stringf("xorr(%s)", a_expr.c_str());
+                                }
+                               if (cell->type == "$reduce_bool") {
+                                        primop = "neq";
+                                        a_expr = stringf("%s, UInt(0)", a_expr.c_str());
+                                }
+
+                               string expr = stringf("%s(%s)", primop.c_str(), a_expr.c_str());
+
+                               if ((is_signed && !always_uint))
+                                       expr = stringf("asUInt(%s)", expr.c_str());
+
+                               cell_exprs.push_back(stringf("    %s <= %s\n", y_id.c_str(), expr.c_str()));
+                               register_reverse_wire_map(y_id, cell->getPort("\\Y"));
+
+                               continue;
+                       }
+                       if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$and", "$or", "$eq", "$eqx",
+                                        "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl",
+                                        "$logic_and", "$logic_or"))
                        {
                                string y_id = make_id(cell->name);
                                bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
@@ -166,22 +212,88 @@ struct FirrtlWorker
                                string b_expr = make_expr(cell->getPort("\\B"));
                                wire_decls.push_back(stringf("    wire %s: UInt<%d>\n", y_id.c_str(), y_width));
 
-                               if (is_signed) {
+                               if (cell->parameters.at("\\A_SIGNED").as_bool()) {
                                        a_expr = "asSInt(" + a_expr + ")";
+                               }
+                               if (cell->parameters.at("\\A_SIGNED").as_bool()  & (cell->type != "$shr")) {
                                        b_expr = "asSInt(" + b_expr + ")";
                                }
 
                                a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
-                               b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
+
+                               if ((cell->type != "$shl") && (cell->type != "$sshl")) {
+                                       b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
+                                }
+
+                               if (cell->parameters.at("\\A_SIGNED").as_bool()  & (cell->type == "$shr")) {
+                                       a_expr = "asUInt(" + a_expr + ")";
+                               }
 
                                string primop;
+                                bool always_uint = false;
                                if (cell->type == "$add") primop = "add";
                                if (cell->type == "$sub") primop = "sub";
-                               if (cell->type == "$xor") primop = "xor";
+                               if (cell->type == "$mul") primop = "mul";
+                               if (cell->type == "$div") primop = "div";
+                               if (cell->type == "$mod") primop = "rem";
+                               if (cell->type == "$and") {
+                                        primop = "and";
+                                        always_uint = true;
+                                }
+                               if (cell->type == "$or" ) {
+                                        primop =  "or";
+                                        always_uint = true;
+                                }
+                               if (cell->type == "$xor") {
+                                        primop = "xor";
+                                        always_uint = true;
+                                }
+                               if ((cell->type == "$eq") | (cell->type == "$eqx")) {
+                                        primop = "eq";
+                                        always_uint = true;
+                                }
+                               if ((cell->type == "$ne") | (cell->type == "$nex")) {
+                                        primop = "neq";
+                                        always_uint = true;
+                                }
+                               if (cell->type == "$gt") {
+                                        primop = "gt";
+                                        always_uint = true;
+                                }
+                               if (cell->type == "$ge") {
+                                        primop = "geq";
+                                        always_uint = true;
+                                }
+                               if (cell->type == "$lt") {
+                                        primop = "lt";
+                                        always_uint = true;
+                                }
+                               if (cell->type == "$le") {
+                                        primop = "leq";
+                                        always_uint = true;
+                                }
+                               if ((cell->type == "$shl") | (cell->type == "$sshl")) primop = "dshl";
+                               if ((cell->type == "$shr") | (cell->type == "$sshr")) primop = "dshr";
+                               if ((cell->type == "$logic_and")) {
+                                        primop = "and";
+                                        a_expr = "neq(" + a_expr + ", UInt(0))";
+                                        b_expr = "neq(" + b_expr + ", UInt(0))";
+                                        always_uint = true;
+                                }
+                               if ((cell->type == "$logic_or")) {
+                                        primop = "or";
+                                        a_expr = "neq(" + a_expr + ", UInt(0))";
+                                        b_expr = "neq(" + b_expr + ", UInt(0))";
+                                        always_uint = true;
+                                }
+
+                               if (!cell->parameters.at("\\B_SIGNED").as_bool()) {
+                                       b_expr = "asUInt(" + b_expr + ")";
+                               }
 
                                string expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str());
 
-                               if ((is_signed && !cell->type.in("$xor")) || cell->type.in("$sub"))
+                               if ((is_signed && !always_uint) || cell->type.in("$sub"))
                                        expr = stringf("asUInt(%s)", expr.c_str());
 
                                cell_exprs.push_back(stringf("    %s <= %s\n", y_id.c_str(), expr.c_str()));
index 0a7151afa6fe6c0cbb0fa1afaa610f40f9dc2f16..fe7e3a329127b850115c3d111d1c93ff3fe2e43e 100644 (file)
@@ -1,16 +1,20 @@
 #!/bin/bash
 set -ex
 
-../../yosys -p 'prep -nordff; write_firrtl test.fir' test.v
+cd ../../
+make
+cd backends/firrtl
 
-firrtl -i test.fir -o test_out.v
+../../yosys -q -p 'prep -nordff; write_firrtl test.fir' $1
 
-../../yosys -p '
-       read_verilog test.v
-       rename test gold
+firrtl -i test.fir -o test_out.v -ll Info
+
+../../yosys -p "
+       read_verilog $1
+       rename Top gold
 
        read_verilog test_out.v
-       rename test gate
+       rename Top gate
 
        prep
        memory_map
@@ -18,5 +22,4 @@ firrtl -i test.fir -o test_out.v
        hierarchy -top miter
 
        sat -verify -prove trigger 0 -set-init-zero -seq 10 miter
-'
-
+"
index 1c7088ab8573b9362d0ac2f75ec39e93e7a5aded..c6d62a847260ad1ce74ec8a53a12fe5c224e8f78 100644 (file)
@@ -1,24 +1,63 @@
 module test(
        input clk, wen,
-       input [4:0] waddr, raddr,
-       input [31:0] wdata,
-       output reg [31:0] rdata,
-       signed input [7:0] a, b, x,
-       output [15:0] s, d, y, z, u, q
+       input [7:0] uns,
+       input signed [7:0] a, b,
+       input signed [23:0] c,
+       input signed [2:0] sel,
+       output [15:0] s, d, y, z, u, q, p, mul, div, mod, mux, And, Or, Xor, eq, neq, gt, lt, geq, leq, eqx, shr, sshr, shl, sshl, Land, Lor, Lnot, Not, Neg, pos, Andr, Orr, Xorr, Xnorr, Reduce_bool,
+        output [7:0] PMux
 );
-       reg [31:0] memory [0:31];
-
-       always @(posedge clk) begin
-               rdata <= memory[raddr];
-               if (wen) memory[waddr] <= wdata;
-       end
-
+        //initial begin
+          //$display("shr = %b", shr);
+        //end
        assign s = a+{b[6:2], 2'b1};
        assign d = a-b;
        assign y = x;
        assign z[7:0] = s+d;
        assign z[15:8] = s-d;
+        assign p = a & b | x;
+        assign mul = a * b;
+        assign div = a / b;
+        assign mod = a % b;
+        assign mux = x[0] ? a : b;
+        assign And = a & b;
+        assign Or = a | b;
+        assign Xor = a ^ b;
+        assign Not = ~a;
+        assign Neg = -a;
+        assign eq = a == b;
+        assign neq = a != b;
+        assign gt = a > b;
+        assign lt = a < b;
+        assign geq = a >= b;
+        assign leq = a <= b;
+        assign eqx = a === b;
+        assign shr = a >> b; //0111111111000000
+        assign sshr = a >>> b;
+        assign shl = a << b;
+        assign sshl = a <<< b;
+        assign Land = a && b;
+        assign Lor = a || b;
+        assign Lnot = !a;
+        assign pos = $signed(uns);
+        assign Andr = &a;
+        assign Orr = |a;
+        assign Xorr = ^a;
+        assign Xnorr = ~^a;
+        always @*
+          if(!a) begin
+             Reduce_bool = a;
+          end else begin
+             Reduce_bool = b;
+          end
+        //always @(sel or c or a)
+        //  begin
+        //    case (sel)
+        //      3'b000: PMux = a;
+        //      3'b001: PMux = c[7:0];
+        //      3'b010: PMux = c[15:8];
+        //      3'b100: PMux = c[23:16];
+        //    endcase
+        //  end
 
-       always @(posedge clk)
-               q <= s ^ d ^ x;
 endmodule