mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	More progress on Firrtl backend.
Chisel -> Firrtl -> Verilog -> Firrtl -> Verilog is successful for a simple rocket-chip design.
This commit is contained in:
		
							parent
							
								
									69468d5a16
								
							
						
					
					
						commit
						794cec0016
					
				
					 3 changed files with 181 additions and 27 deletions
				
			
		|  | @ -157,7 +157,53 @@ struct FirrtlWorker | ||||||
| 
 | 
 | ||||||
| 		for (auto cell : module->cells()) | 		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); | 				string y_id = make_id(cell->name); | ||||||
| 				bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool(); | 				bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool(); | ||||||
|  | @ -166,22 +212,88 @@ struct FirrtlWorker | ||||||
| 				string b_expr = make_expr(cell->getPort("\\B")); | 				string b_expr = make_expr(cell->getPort("\\B")); | ||||||
| 				wire_decls.push_back(stringf("    wire %s: UInt<%d>\n", y_id.c_str(), y_width)); | 				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 + ")"; | 					a_expr = "asSInt(" + a_expr + ")"; | ||||||
|  | 				} | ||||||
|  | 				if (cell->parameters.at("\\A_SIGNED").as_bool()  & (cell->type != "$shr")) { | ||||||
| 					b_expr = "asSInt(" + b_expr + ")"; | 					b_expr = "asSInt(" + b_expr + ")"; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); | 				a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); | ||||||
|  | 
 | ||||||
|  | 				if ((cell->type != "$shl") && (cell->type != "$sshl")) { | ||||||
| 				        b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width); | 				        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; | 				string primop; | ||||||
|  |                                 bool always_uint = false; | ||||||
| 				if (cell->type == "$add") primop = "add"; | 				if (cell->type == "$add") primop = "add"; | ||||||
| 				if (cell->type == "$sub") primop = "sub"; | 				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()); | 				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()); | 					expr = stringf("asUInt(%s)", expr.c_str()); | ||||||
| 
 | 
 | ||||||
| 				cell_exprs.push_back(stringf("    %s <= %s\n", y_id.c_str(), expr.c_str())); | 				cell_exprs.push_back(stringf("    %s <= %s\n", y_id.c_str(), expr.c_str())); | ||||||
|  |  | ||||||
|  | @ -1,16 +1,20 @@ | ||||||
| #!/bin/bash | #!/bin/bash | ||||||
| set -ex | 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 ' | firrtl -i test.fir -o test_out.v -ll Info | ||||||
| 	read_verilog test.v | 
 | ||||||
| 	rename test gold | ../../yosys -p " | ||||||
|  | 	read_verilog $1 | ||||||
|  | 	rename Top gold | ||||||
| 
 | 
 | ||||||
| 	read_verilog test_out.v | 	read_verilog test_out.v | ||||||
| 	rename test gate | 	rename Top gate | ||||||
| 
 | 
 | ||||||
| 	prep | 	prep | ||||||
| 	memory_map | 	memory_map | ||||||
|  | @ -18,5 +22,4 @@ firrtl -i test.fir -o test_out.v | ||||||
| 	hierarchy -top miter | 	hierarchy -top miter | ||||||
| 
 | 
 | ||||||
| 	sat -verify -prove trigger 0 -set-init-zero -seq 10 miter | 	sat -verify -prove trigger 0 -set-init-zero -seq 10 miter | ||||||
| ' | " | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -1,24 +1,63 @@ | ||||||
| module test( | module test( | ||||||
| 	input clk, wen, | 	input clk, wen, | ||||||
| 	input [4:0] waddr, raddr, | 	input [7:0] uns, | ||||||
| 	input [31:0] wdata, | 	input signed [7:0] a, b, | ||||||
| 	output reg [31:0] rdata, | 	input signed [23:0] c, | ||||||
| 	signed input [7:0] a, b, x, | 	input signed [2:0] sel, | ||||||
| 	output [15:0] s, d, y, z, u, q | 	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]; |         //initial begin | ||||||
| 
 |           //$display("shr = %b", shr); | ||||||
| 	always @(posedge clk) begin |         //end | ||||||
| 		rdata <= memory[raddr]; |  | ||||||
| 		if (wen) memory[waddr] <= wdata; |  | ||||||
| 	end |  | ||||||
| 
 |  | ||||||
| 	assign s = a+{b[6:2], 2'b1}; | 	assign s = a+{b[6:2], 2'b1}; | ||||||
| 	assign d = a-b; | 	assign d = a-b; | ||||||
| 	assign y = x; | 	assign y = x; | ||||||
| 	assign z[7:0] = s+d; | 	assign z[7:0] = s+d; | ||||||
| 	assign z[15:8] = 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 | endmodule | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue