diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 0d1c1889d..06cbc9b2b 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -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())); diff --git a/backends/firrtl/test.sh b/backends/firrtl/test.sh index 0a7151afa..fe7e3a329 100644 --- a/backends/firrtl/test.sh +++ b/backends/firrtl/test.sh @@ -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 -' - +" diff --git a/backends/firrtl/test.v b/backends/firrtl/test.v index 1c7088ab8..c6d62a847 100644 --- a/backends/firrtl/test.v +++ b/backends/firrtl/test.v @@ -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