mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	abc9_ops: add 'dff' label for auto handling of (* abc9_flop *) boxes
This commit is contained in:
		
							parent
							
								
									accfc70fc2
								
							
						
					
					
						commit
						95763c8d18
					
				
					 9 changed files with 403 additions and 640 deletions
				
			
		|  | @ -1,6 +1,3 @@ | |||
| module \$__ABC9_FF_ (input D, output Q); | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box *) | ||||
| module \$__ABC9_DELAY (input I, output O); | ||||
|   parameter DELAY = 0; | ||||
|  |  | |||
|  | @ -22,360 +22,6 @@ | |||
| //   before invoking the `abc9` pass in order to transform the design into | ||||
| //   a format that it understands. | ||||
| 
 | ||||
| `ifdef DFF_MODE | ||||
| // For example, (complex) flip-flops are expected to be described as an | ||||
| //   combinatorial box (containing all control logic such as clock enable | ||||
| //   or synchronous resets) followed by a basic D-Q flop. | ||||
| // Yosys will automatically analyse the simulation model (described in | ||||
| //   cells_sim.v) and detach any $_DFF_P_ or $_DFF_N_ cells present in | ||||
| //   order to extract the combinatorial control logic left behind. | ||||
| //   Specifically, a simulation model similar to the one below: | ||||
| // | ||||
| //                ++===================================++ | ||||
| //                ||                        Sim model  || | ||||
| //                ||      /\/\/\/\                     || | ||||
| //            D -->>-----<        >     +------+       || | ||||
| //            R -->>-----<  Comb. >     |$_DFF_|       || | ||||
| //           CE -->>-----<  logic >-----| [NP]_|---+---->>-- Q | ||||
| //                ||  +--<        >     +------+   |   || | ||||
| //                ||  |   \/\/\/\/                 |   || | ||||
| //                ||  |                            |   || | ||||
| //                ||  +----------------------------+   || | ||||
| //                ||                                   || | ||||
| //                ++===================================++ | ||||
| // | ||||
| //   is transformed into: | ||||
| // | ||||
| //                ++==================++ | ||||
| //                ||         Comb box || | ||||
| //                ||                  || | ||||
| //                ||      /\/\/\/\    || | ||||
| //           D  -->>-----<        >   || | ||||
| //           R  -->>-----<  Comb. >   ||        +-----------+ | ||||
| //          CE  -->>-----<  logic >--->>-- $Q --|$__ABC9_FF_|--+-->> Q | ||||
| //   abc9_ff.Q +-->>-----<        >   ||        +-----------+  | | ||||
| //             |  ||      \/\/\/\/    ||                       | | ||||
| //             |  ||                  ||                       | | ||||
| //             |  ++==================++                       | | ||||
| //             |                                               | | ||||
| //             +-----------------------------------------------+ | ||||
| // | ||||
| // The purpose of the following FD* rules are to wrap the flop with: | ||||
| // (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9 | ||||
| //     the connectivity of its basic D-Q flop | ||||
| // (b) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to | ||||
| //     capture asynchronous behaviour | ||||
| // (c) a special abc9_ff.clock wire to capture its clock domain and polarity | ||||
| //     (indicated to `abc9' so that it only performs sequential synthesis | ||||
| //     (with reachability analysis) correctly on one domain at a time) | ||||
| // (d) an (* abc9_init *) attribute on the $__ABC9_FF_ cell capturing its | ||||
| //     initial state | ||||
| //     NOTE: in order to perform sequential synthesis, `abc9' requires that | ||||
| //     the initial value of all flops be zero | ||||
| // (e) a special _TECHMAP_REPLACE_.abc9_ff.Q wire that will be used for feedback | ||||
| //     into the (combinatorial) FD* cell to facilitate clock-enable behaviour | ||||
| 
 | ||||
| module FDRE (output Q, (* techmap_autopurge *) input C, CE, D, R); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   parameter [0:0] IS_C_INVERTED = 1'b0; | ||||
|   parameter [0:0] IS_D_INVERTED = 1'b0; | ||||
|   parameter [0:0] IS_R_INVERTED = 1'b0; | ||||
|   wire QQ, $Q; | ||||
|   generate if (INIT == 1'b1) begin | ||||
|     assign Q = ~QQ; | ||||
|     FDSE #( | ||||
|       .INIT(1'b0), | ||||
|       .IS_C_INVERTED(IS_C_INVERTED), | ||||
|       .IS_D_INVERTED(IS_D_INVERTED), | ||||
|       .IS_S_INVERTED(IS_R_INVERTED) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .S(R) | ||||
|     ); | ||||
|   end | ||||
|   else begin | ||||
|     assign Q = QQ; | ||||
|     FDRE #( | ||||
|       .INIT(1'b0), | ||||
|       .IS_C_INVERTED(IS_C_INVERTED), | ||||
|       .IS_D_INVERTED(IS_D_INVERTED), | ||||
|       .IS_R_INVERTED(IS_R_INVERTED) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .R(R) | ||||
|     ); | ||||
|   end | ||||
|   endgenerate | ||||
|   (* abc9_init = 1'b0 *) | ||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); | ||||
| 
 | ||||
|   // Special signals | ||||
|   wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; | ||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; | ||||
| endmodule | ||||
| module FDRE_1 (output Q, (* techmap_autopurge *) input C, CE, D, R); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   wire QQ, $Q; | ||||
|   generate if (INIT == 1'b1) begin | ||||
|     assign Q = ~QQ; | ||||
|     FDSE_1 #( | ||||
|       .INIT(1'b0) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .S(R) | ||||
|     ); | ||||
|   end | ||||
|   else begin | ||||
|     assign Q = QQ; | ||||
|     FDRE_1 #( | ||||
|       .INIT(1'b0) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .R(R) | ||||
|     ); | ||||
|   end | ||||
|   endgenerate | ||||
|   (* abc9_init = 1'b0 *) | ||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); | ||||
| 
 | ||||
|   // Special signals | ||||
|   wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; | ||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; | ||||
| endmodule | ||||
| 
 | ||||
| module FDSE (output Q, (* techmap_autopurge *) input C, CE, D, S); | ||||
|   parameter [0:0] INIT = 1'b1; | ||||
|   parameter [0:0] IS_C_INVERTED = 1'b0; | ||||
|   parameter [0:0] IS_D_INVERTED = 1'b0; | ||||
|   parameter [0:0] IS_S_INVERTED = 1'b0; | ||||
|   wire QQ, $Q; | ||||
|   generate if (INIT == 1'b1) begin | ||||
|     assign Q = ~QQ; | ||||
|     FDRE #( | ||||
|       .INIT(1'b0), | ||||
|       .IS_C_INVERTED(IS_C_INVERTED), | ||||
|       .IS_D_INVERTED(IS_D_INVERTED), | ||||
|       .IS_R_INVERTED(IS_S_INVERTED) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) | ||||
|     ); | ||||
|   end | ||||
|   else begin | ||||
|     assign Q = QQ; | ||||
|     FDSE #( | ||||
|       .INIT(1'b0), | ||||
|       .IS_C_INVERTED(IS_C_INVERTED), | ||||
|       .IS_D_INVERTED(IS_D_INVERTED), | ||||
|       .IS_S_INVERTED(IS_S_INVERTED) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .S(S) | ||||
|     ); | ||||
|   end endgenerate | ||||
|   (* abc9_init = 1'b0 *) | ||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); | ||||
| 
 | ||||
|   // Special signals | ||||
|   wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; | ||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; | ||||
| endmodule | ||||
| module FDSE_1 (output Q, (* techmap_autopurge *) input C, CE, D, S); | ||||
|   parameter [0:0] INIT = 1'b1; | ||||
|   wire QQ, $Q; | ||||
|   generate if (INIT == 1'b1) begin | ||||
|     assign Q = ~QQ; | ||||
|     FDRE_1 #( | ||||
|       .INIT(1'b0) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) | ||||
|     ); | ||||
|   end | ||||
|   else begin | ||||
|     assign Q = QQ; | ||||
|     FDSE_1 #( | ||||
|       .INIT(1'b0) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .S(S) | ||||
|     ); | ||||
|   end endgenerate | ||||
|   (* abc9_init = 1'b0 *) | ||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); | ||||
| 
 | ||||
|   // Special signals | ||||
|   wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; | ||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; | ||||
| endmodule | ||||
| 
 | ||||
| module FDCE (output Q, (* techmap_autopurge *) input C, CE, D, CLR); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   parameter [0:0] IS_C_INVERTED = 1'b0; | ||||
|   parameter [0:0] IS_D_INVERTED = 1'b0; | ||||
|   parameter [0:0] IS_CLR_INVERTED = 1'b0; | ||||
|   wire QQ, $Q, $QQ; | ||||
|   generate if (INIT == 1'b1) begin | ||||
|     assign Q = ~QQ; | ||||
|     FDPE #( | ||||
|       .INIT(1'b0), | ||||
|       .IS_C_INVERTED(IS_C_INVERTED), | ||||
|       .IS_D_INVERTED(IS_D_INVERTED), | ||||
|       .IS_PRE_INVERTED(IS_CLR_INVERTED) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR) | ||||
|                                         // ^^^ Note that async | ||||
|                                         //     control is not directly | ||||
|                                         //     supported by abc9 but its | ||||
|                                         //     behaviour is captured by | ||||
|                                         //     $__ABC9_ASYNC1 below | ||||
|     ); | ||||
|     // Since this is an async flop, async behaviour is dealt with here | ||||
|     $__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); | ||||
|   end | ||||
|   else begin | ||||
|     assign Q = QQ; | ||||
|     FDCE #( | ||||
|       .INIT(1'b0), | ||||
|       .IS_C_INVERTED(IS_C_INVERTED), | ||||
|       .IS_D_INVERTED(IS_D_INVERTED), | ||||
|       .IS_CLR_INVERTED(IS_CLR_INVERTED) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR) | ||||
|                                        // ^^^ Note that async | ||||
|                                        //     control is not directly | ||||
|                                        //     supported by abc9 but its | ||||
|                                        //     behaviour is captured by | ||||
|                                        //     $__ABC9_ASYNC0 below | ||||
|     ); | ||||
|     // Since this is an async flop, async behaviour is dealt with here | ||||
|     $__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); | ||||
|   end endgenerate | ||||
|   (* abc9_init = 1'b0 *) | ||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); | ||||
| 
 | ||||
|   // Special signals | ||||
|   wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; | ||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; | ||||
| endmodule | ||||
| module FDCE_1 (output Q, (* techmap_autopurge *) input C, CE, D, CLR); | ||||
|   parameter [0:0] INIT = 1'b0; | ||||
|   wire QQ, $Q, $QQ; | ||||
|   generate if (INIT == 1'b1) begin | ||||
|     assign Q = ~QQ; | ||||
|     FDPE_1 #( | ||||
|       .INIT(1'b0) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR) | ||||
|                                         // ^^^ Note that async | ||||
|                                         //     control is not directly | ||||
|                                         //     supported by abc9 but its | ||||
|                                         //     behaviour is captured by | ||||
|                                         //     $__ABC9_ASYNC1 below | ||||
|     ); | ||||
|     $__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR), .Y(QQ)); | ||||
|   end | ||||
|   else begin | ||||
|     assign Q = QQ; | ||||
|     FDCE_1 #( | ||||
|       .INIT(1'b0) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR) | ||||
|                                        // ^^^ Note that async | ||||
|                                        //     control is not directly | ||||
|                                        //     supported by abc9 but its | ||||
|                                        //     behaviour is captured by | ||||
|                                        //     $__ABC9_ASYNC0 below | ||||
|     ); | ||||
|     $__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR), .Y(QQ)); | ||||
|   end endgenerate | ||||
|   (* abc9_init = 1'b0 *) | ||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); | ||||
| 
 | ||||
|   // Special signals | ||||
|   wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; | ||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; | ||||
| endmodule | ||||
| 
 | ||||
| module FDPE (output Q, (* techmap_autopurge *) input C, CE, D, PRE); | ||||
|   parameter [0:0] INIT = 1'b1; | ||||
|   parameter [0:0] IS_C_INVERTED = 1'b0; | ||||
|   parameter [0:0] IS_D_INVERTED = 1'b0; | ||||
|   parameter [0:0] IS_PRE_INVERTED = 1'b0; | ||||
|   wire QQ, $Q, $QQ; | ||||
|   generate if (INIT == 1'b1) begin | ||||
|     assign Q = ~QQ; | ||||
|     FDCE #( | ||||
|       .INIT(1'b0), | ||||
|       .IS_C_INVERTED(IS_C_INVERTED), | ||||
|       .IS_D_INVERTED(IS_D_INVERTED), | ||||
|       .IS_CLR_INVERTED(IS_PRE_INVERTED), | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE) | ||||
|                                         // ^^^ Note that async | ||||
|                                         //     control is not directly | ||||
|                                         //     supported by abc9 but its | ||||
|                                         //     behaviour is captured by | ||||
|                                         //     $__ABC9_ASYNC0 below | ||||
|     ); | ||||
|     $__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); | ||||
|   end | ||||
|   else begin | ||||
|     assign Q = QQ; | ||||
|     FDPE #( | ||||
|       .INIT(1'b0), | ||||
|       .IS_C_INVERTED(IS_C_INVERTED), | ||||
|       .IS_D_INVERTED(IS_D_INVERTED), | ||||
|       .IS_PRE_INVERTED(IS_PRE_INVERTED), | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE) | ||||
|                                        // ^^^ Note that async | ||||
|                                        //     control is not directly | ||||
|                                        //     supported by abc9 but its | ||||
|                                        //     behaviour is captured by | ||||
|                                        //     $__ABC9_ASYNC1 below | ||||
|     ); | ||||
|     $__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); | ||||
|   end endgenerate | ||||
|   (* abc9_init = 1'b0 *) | ||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); | ||||
| 
 | ||||
|   // Special signals | ||||
|   wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; | ||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; | ||||
| endmodule | ||||
| module FDPE_1 (output Q, (* techmap_autopurge *) input C, CE, D, PRE); | ||||
|   parameter [0:0] INIT = 1'b1; | ||||
|   wire QQ, $Q, $QQ; | ||||
|   generate if (INIT == 1'b1) begin | ||||
|     assign Q = ~QQ; | ||||
|     FDCE_1 #( | ||||
|       .INIT(1'b0) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE) | ||||
|                                         // ^^^ Note that async | ||||
|                                         //     control is not directly | ||||
|                                         //     supported by abc9 but its | ||||
|                                         //     behaviour is captured by | ||||
|                                         //     $__ABC9_ASYNC0 below | ||||
|     ); | ||||
|     $__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE), .Y(QQ)); | ||||
|   end | ||||
|   else begin | ||||
|     assign Q = QQ; | ||||
|     FDPE_1 #( | ||||
|       .INIT(1'b0) | ||||
|     ) _TECHMAP_REPLACE_ ( | ||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE) | ||||
|                                        // ^^^ Note that async | ||||
|                                        //     control is not directly | ||||
|                                        //     supported by abc9 but its | ||||
|                                        //     behaviour is captured by | ||||
|                                        //     $__ABC9_ASYNC1 below | ||||
|     ); | ||||
|     $__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE), .Y(QQ)); | ||||
|   end endgenerate | ||||
|   (* abc9_init = 1'b0 *) | ||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); | ||||
| 
 | ||||
|   // Special signals | ||||
|   wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; | ||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; | ||||
| endmodule | ||||
| `endif | ||||
| 
 | ||||
| // Attach a (combinatorial) black-box onto the output | ||||
| //   of thes LUTRAM primitives to capture their | ||||
| //   asynchronous read behaviour | ||||
|  |  | |||
|  | @ -25,10 +25,6 @@ module $__ABC9_ASYNC01(input A, S, output Y); | |||
|   assign Y = A; | ||||
| endmodule | ||||
| 
 | ||||
| module $__ABC9_FF_(input D, output Q); | ||||
|   assign Q = D; | ||||
| endmodule | ||||
| 
 | ||||
| module $__ABC9_RAM6(input A, input [5:0] S, output Y); | ||||
|   assign Y = A; | ||||
| endmodule | ||||
|  |  | |||
|  | @ -640,7 +640,7 @@ module FDRSE ( | |||
|       Q <= d; | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| (* lib_whitebox *) | ||||
| module FDCE ( | ||||
|   output reg Q, | ||||
|   (* clkbuf_sink *) | ||||
|  | @ -683,7 +683,7 @@ module FDCE ( | |||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| (* lib_whitebox *) | ||||
| module FDCE_1 ( | ||||
|   output reg Q, | ||||
|   (* clkbuf_sink *) | ||||
|  | @ -708,7 +708,7 @@ module FDCE_1 ( | |||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| (* lib_whitebox *) | ||||
| module FDPE ( | ||||
|   output reg Q, | ||||
|   (* clkbuf_sink *) | ||||
|  | @ -750,7 +750,7 @@ module FDPE ( | |||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| (* lib_whitebox *) | ||||
| module FDPE_1 ( | ||||
|   output reg Q, | ||||
|   (* clkbuf_sink *) | ||||
|  |  | |||
|  | @ -613,10 +613,7 @@ struct SynthXilinxPass : public ScriptPass | |||
| 				if (family != "xc7") | ||||
| 					log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, " | ||||
| 							"will use timing for 'xc7' instead.\n", family.c_str()); | ||||
| 				std::string techmap_args = "-map +/xilinx/abc9_map.v -max_iter 1"; | ||||
| 				if (dff_mode) | ||||
| 					techmap_args += " -D DFF_MODE"; | ||||
| 				run("techmap " + techmap_args); | ||||
| 				run("techmap -map +/xilinx/abc9_map.v -max_iter 1"); | ||||
| 				run("read_verilog -icells -lib -specify +/abc9_model.v +/xilinx/abc9_model.v"); | ||||
| 				std::string abc9_opts; | ||||
| 				std::string k = "synth_xilinx.abc9.W"; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue