From 4eaa45091cebb57db32fa30c37e80e113ae10451 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 14:47:50 -0800 Subject: [PATCH 01/25] Update some abc9_arrival times, add abc9_required times --- techlibs/xilinx/cells_sim.v | 188 +++++++++++++++++++++++++++++----- techlibs/xilinx/cells_xtra.py | 40 ++++++++ techlibs/xilinx/cells_xtra.v | 16 +++ 3 files changed, 220 insertions(+), 24 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 3bcbfc9aa..ed602fa6e 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -1112,15 +1112,33 @@ module RAM16X1D_1 ( endmodule module RAM32X1D ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 (* abc9_arrival=1153 *) output DPO, SPO, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986 + (* abc9_required=453 *) input D, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) input WCLK, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 + (* abc9_required=654 *) input WE, - input A0, A1, A2, A3, A4, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L800 + (* abc9_required=245 *) + input A0, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/clBLM_R.sdf#L798 + (* abc9_required=208 *) + input A1, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L796 + (* abc9_required=147 *) + input A2, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L794 + (* abc9_required=68 *) + input A3, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L792 + (* abc9_required=66 *) + input A4, input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 ); parameter INIT = 32'h0; @@ -1135,15 +1153,33 @@ module RAM32X1D ( endmodule module RAM32X1D_1 ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 (* abc9_arrival=1153 *) output DPO, SPO, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986 + (* abc9_required=453 *) input D, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) input WCLK, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 + (* abc9_required=654 *) input WE, - input A0, A1, A2, A3, A4, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L800 + (* abc9_required=245 *) + input A0, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/clBLM_R.sdf#L798 + (* abc9_required=208 *) + input A1, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L796 + (* abc9_required=147 *) + input A2, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L794 + (* abc9_required=68 *) + input A3, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L792 + (* abc9_required=66 *) + input A4, input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 ); parameter INIT = 32'h0; @@ -1158,15 +1194,36 @@ module RAM32X1D_1 ( endmodule module RAM64X1D ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 (* abc9_arrival=1153 *) output DPO, SPO, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986 + (* abc9_required=453 *) input D, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) input WCLK, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 + (* abc9_required=654 *) input WE, - input A0, A1, A2, A3, A4, A5, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L828 + (* abc9_required=362 *) + input A0, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L826 + (* abc9_required=245 *) + input A1, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L824 + (* abc9_required=208 *) + input A2, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L822 + (* abc9_required=147 *) + input A3, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L820 + (* abc9_required=68 *) + input A4, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L818 + (* abc9_required=66 *) + input A5, input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 ); parameter INIT = 64'h0; @@ -1181,15 +1238,36 @@ module RAM64X1D ( endmodule module RAM64X1D_1 ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 (* abc9_arrival=1153 *) output DPO, SPO, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986 + (* abc9_required=453 *) input D, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) input WCLK, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 + (* abc9_required=654 *) input WE, - input A0, A1, A2, A3, A4, A5, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L828 + (* abc9_required=362 *) + input A0, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L826 + (* abc9_required=245 *) + input A1, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L824 + (* abc9_required=208 *) + input A2, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L822 + (* abc9_required=147 *) + input A3, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L820 + (* abc9_required=68 *) + input A4, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L818 + (* abc9_required=66 *) + input A5, input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 ); parameter INIT = 64'h0; @@ -1204,15 +1282,23 @@ module RAM64X1D_1 ( endmodule module RAM128X1D ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 - (* abc9_arrival=1153 *) - output DPO, SPO, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 + // plus 208ps to cross MUXF7 + (* abc9_arrival=1359 *) + output DPO, SPO, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986 + (* abc9_required=453 *) input D, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) input WCLK, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 + (* abc9_required=654 *) input WE, - input [6:0] A, DPRA + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L818-830 + (* abc9_required="616 362 245 208 147 68 66" *) + input [6:0] A, + input [6:0] DPRA ); parameter INIT = 128'h0; parameter IS_WCLK_INVERTED = 1'b0; @@ -1244,15 +1330,44 @@ endmodule // Multi port. module RAM32M ( + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L889 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L857 + (* abc9_arrival="1153 1188" *) + output [1:0] DOA, // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 - (* abc9_arrival=1153 *) - output [1:0] DOA, DOB, DOC, DOD, - input [4:0] ADDRA, ADDRB, ADDRC, ADDRD, - input [1:0] DIA, DIB, DIC, DID, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L925 + (* abc9_arrival="1161 1187" *) + output [1:0] DOB, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1025 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L993 + (* abc9_arrival="1158 1180" *) + output [1:0] DOC, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1093 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1061 + (* abc9_arrival="1163 1190" *) + output [1:0] DOD, + input [4:0] ADDRA, ADDRB, ADDRC, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L792-L802 + (* abc9_required="245 208 147 68 66" *) + input [4:0] ADDRD, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986-L988 + (* abc9_required="453 384" *) + input [1:0] DIA, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1054-L1056 + (* abc9_required="461 354" *) + input [1:0] DIB, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1122-L1124 + (* abc9_required="457 375" *) + input [1:0] DIC, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1190-L1192 + (* abc9_required="310 334" *) + input [1:0] DID, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) - input WCLK, - input WE + input WCLK, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 + (* abc9_required=654 *) + input WE ); parameter [63:0] INIT_A = 64'h0000000000000000; parameter [63:0] INIT_B = 64'h0000000000000000; @@ -1347,15 +1462,40 @@ module RAM32M16 ( endmodule module RAM64M ( - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L889 (* abc9_arrival=1153 *) - output DOA, DOB, DOC, DOD, - input [5:0] ADDRA, ADDRB, ADDRC, ADDRD, - input DIA, DIB, DIC, DID, + output DOA, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + (* abc9_arrival=1161 *) + output DOB, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1025 + (* abc9_arrival=1158 *) + output DOC, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1093 + (* abc9_arrival=1163 *) + output DOD, + input [5:0] ADDRA, ADDRB, ADDRC, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L818-L830 + (* abc9_required="362 245 208 147 68 66" *) + input [5:0] ADDRD, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L986-L988 + (* abc9_required=384 *) + input DIA, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1054-L1056 + (* abc9_required=354 *) + input DIB, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1122-L1124 + (* abc9_required=375 *) + input DIC, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L1190-L1192 + (* abc9_required=310 *) + input DID, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) - input WCLK, - input WE + input WCLK, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L834 + (* abc9_required=654 *) + input WE ); parameter [63:0] INIT_A = 64'h0000000000000000; parameter [63:0] INIT_B = 64'h0000000000000000; diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py index d5c58c5d7..cb873a044 100644 --- a/techlibs/xilinx/cells_xtra.py +++ b/techlibs/xilinx/cells_xtra.py @@ -180,18 +180,58 @@ CELLS = [ Cell('RAMB18E1', port_attrs={ 'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L143 'DOADO': ['abc9_arrival=2454'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L163 'DOBDO': ['abc9_arrival=2454'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L144 'DOPADOP': ['abc9_arrival=2454'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L164 'DOPBDOP': ['abc9_arrival=2454'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L13 + 'ADDRARDADDR': ['abc9_required=566'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L17 + 'ADDRBWRADDR': ['abc9_required=566'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L19 + 'WEA': ['abc9_required=532'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L21 + 'WEBWE': ['abc9_required=532'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L123 + 'DIADI': ['abc9_required=737'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L133 + 'DIBDI': ['abc9_required=737'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L125 + 'DIPADIP': ['abc9_required=737'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L135 + 'DIPBDIP': ['abc9_required=737'], }), Cell('RAMB36E1', port_attrs={ 'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L143 'DOADO': ['abc9_arrival=2454'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L163 'DOBDO': ['abc9_arrival=2454'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L144 'DOPADOP': ['abc9_arrival=2454'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L164 'DOPBDOP': ['abc9_arrival=2454'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L13 + 'ADDRARDADDR': ['abc9_required=566'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L17 + 'ADDRBWRADDR': ['abc9_required=566'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L19 + 'WEA': ['abc9_required=532'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L21 + 'WEBWE': ['abc9_required=532'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L123 + 'DIADI': ['abc9_required=737'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L133 + 'DIBDI': ['abc9_required=737'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L125 + 'DIPADIP': ['abc9_required=737'], + # https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/BRAM_L.sdf#L135 + 'DIPBDIP': ['abc9_required=737'], }), # Ultrascale. Cell('FIFO18E2', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index c3e5c72f9..beed07e0a 100644 --- a/techlibs/xilinx/cells_xtra.v +++ b/techlibs/xilinx/cells_xtra.v @@ -4518,13 +4518,21 @@ module RAMB18E1 (...); input RSTREGARSTREG; (* invertible_pin = "IS_RSTREGB_INVERTED" *) input RSTREGB; + (* abc9_required=566 *) input [13:0] ADDRARDADDR; + (* abc9_required=566 *) input [13:0] ADDRBWRADDR; + (* abc9_required=737 *) input [15:0] DIADI; + (* abc9_required=737 *) input [15:0] DIBDI; + (* abc9_required=737 *) input [1:0] DIPADIP; + (* abc9_required=737 *) input [1:0] DIPBDIP; + (* abc9_required=532 *) input [1:0] WEA; + (* abc9_required=532 *) input [3:0] WEBWE; endmodule @@ -4742,13 +4750,21 @@ module RAMB36E1 (...); input REGCEB; input INJECTDBITERR; input INJECTSBITERR; + (* abc9_required=566 *) input [15:0] ADDRARDADDR; + (* abc9_required=566 *) input [15:0] ADDRBWRADDR; + (* abc9_required=737 *) input [31:0] DIADI; + (* abc9_required=737 *) input [31:0] DIBDI; + (* abc9_required=737 *) input [3:0] DIPADIP; + (* abc9_required=737 *) input [3:0] DIPBDIP; + (* abc9_required=532 *) input [3:0] WEA; + (* abc9_required=532 *) input [7:0] WEBWE; endmodule From 5017be6445fdf3729eb8781e1692be1099039a90 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 14:49:09 -0800 Subject: [PATCH 02/25] Cope with abc9_arrival as string --- backends/aiger/xaiger.cc | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 5729f045a..96263f576 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -199,6 +199,7 @@ struct XAigerWriter dict> bit_drivers, bit_users; TopoSort toposort; bool abc9_box_seen = false; + std::vector arrivals; for (auto cell : module->selected_cells()) { if (cell->type == "$_NOT_") @@ -284,16 +285,20 @@ struct XAigerWriter } } if (is_output) { - int arrival = 0; + arrivals.clear(); if (port_wire) { auto it = port_wire->attributes.find("\\abc9_arrival"); if (it != port_wire->attributes.end()) { - if (it->second.flags != 0) - log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type)); - arrival = it->second.as_int(); + if (it->second.flags == 0) + arrivals.push_back(it->second.as_int()); + else + for (const auto &tok : split_tokens(it->second.decode_string())) + arrivals.push_back(atoi(tok.c_str())); } } + log_assert(GetSize(arrivals) <= 1 || GetSize(arrivals) == GetSize(c.second)); + auto it = arrivals.begin(); for (auto b : c.second) { Wire *w = b.wire; if (!w) continue; @@ -303,8 +308,12 @@ struct XAigerWriter alias_map[O] = b; undriven_bits.erase(O); - if (arrival) - arrival_times[b] = arrival; + if (!arrivals.empty()) { + if (arrivals.size() == 1) + arrival_times[b] = *it; + else + arrival_times[b] = *it++; + } } } } From b7afafde22c195f381168677407a2abc93c5fae0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 14:52:26 -0800 Subject: [PATCH 03/25] Consistency --- techlibs/xilinx/abc9_xc7.box | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box index 774388d49..c6df54667 100644 --- a/techlibs/xilinx/abc9_xc7.box +++ b/techlibs/xilinx/abc9_xc7.box @@ -21,7 +21,7 @@ MUXF8 2 1 3 1 # and expect to save on its delay # Inputs: I0 I1 I2 I3 S0 S1 # Outputs: O -$__MUXF78 3 1 6 1 +$__XILINX_MUXF78 3 1 6 1 294 297 311 317 390 273 # CARRY4 + CARRY4_[ABCD]X From 36d79c80d05f93cd4cb565fe7a92d7cb88683852 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 27 Dec 2019 15:35:19 -0800 Subject: [PATCH 04/25] write_xaiger: simplify c{i,o}_bits --- backends/aiger/xaiger.cc | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 96263f576..db38f2017 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -81,8 +81,7 @@ struct XAigerWriter pool input_bits, output_bits; dict not_map, alias_map; dict> and_map; - vector> ci_bits; - vector> co_bits; + vector ci_bits, co_bits; dict arrival_times; vector> aig_gates; @@ -376,7 +375,6 @@ struct XAigerWriter cell->setPort(port_name, rhs); } - int offset = 0; for (auto b : rhs.bits()) { SigBit I = sigmap(b); if (b == RTLIL::Sx) @@ -387,7 +385,7 @@ struct XAigerWriter else alias_map[b] = I; } - co_bits.emplace_back(b, cell, port_name, offset++, 0); + co_bits.emplace_back(b); unused_bits.erase(b); } } @@ -407,9 +405,8 @@ struct XAigerWriter cell->setPort(port_name, rhs); } - int offset = 0; for (const auto &b : rhs.bits()) { - ci_bits.emplace_back(b, cell, port_name, offset++); + ci_bits.emplace_back(b); SigBit O = sigmap(b); if (O != b) alias_map[O] = b; @@ -496,15 +493,13 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (auto &c : ci_bits) { - RTLIL::SigBit bit = std::get<0>(c); + for (auto bit : ci_bits) { aig_m++, aig_i++; aig_map[bit] = 2*aig_m; } - for (auto &c : co_bits) { - RTLIL::SigBit bit = std::get<0>(c); - std::get<4>(c) = ordered_outputs[bit] = aig_o++; + for (auto bit : co_bits) { + ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -517,7 +512,6 @@ struct XAigerWriter ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } - } void write_aiger(std::ostream &f, bool ascii_mode) From 3177437224b1264e429df34683c3369227657446 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 9 Jan 2020 10:05:03 -0800 Subject: [PATCH 05/25] write_xaiger: cope with abc9_arrival as string of ints --- backends/aiger/xaiger.cc | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index beaed696d..1956422bc 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -185,6 +185,7 @@ struct XAigerWriter } } + std::vector arrivals; for (auto cell : module->cells()) { if (cell->type == "$_NOT_") { @@ -224,13 +225,15 @@ struct XAigerWriter } RTLIL::Module* inst_module = module->design->module(cell->type); - if (inst_module) { + if (inst_module && inst_module->get_blackbox_attribute()) { auto it = cell->attributes.find("\\abc9_box_seq"); if (it != cell->attributes.end()) { int abc9_box_seq = it->second.as_int(); if (GetSize(box_list) <= abc9_box_seq) box_list.resize(abc9_box_seq+1); box_list[abc9_box_seq] = cell; + // Only flop boxes may have arrival times + // (all others are combinatorial) if (!inst_module->get_bool_attribute("\\abc9_flop")) continue; } @@ -238,16 +241,26 @@ struct XAigerWriter for (const auto &conn : cell->connections()) { auto port_wire = inst_module->wire(conn.first); if (port_wire->port_output) { - int arrival = 0; + arrivals.clear(); auto it = port_wire->attributes.find("\\abc9_arrival"); if (it != port_wire->attributes.end()) { - if (it->second.flags != 0) - log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(port_wire), log_id(cell->type)); - arrival = it->second.as_int(); + if (it->second.flags == 0) + arrivals.emplace_back(it->second.as_int()); + else + for (const auto &tok : split_tokens(it->second.decode_string())) + arrivals.push_back(atoi(tok.c_str())); + } + if (!arrivals.empty()) { + if (GetSize(arrivals) > 1 && GetSize(arrivals) != GetSize(port_wire)) + log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first), + GetSize(port_wire), log_signal(it->second), GetSize(arrivals)); + auto jt = arrivals.begin(); + for (auto bit : sigmap(conn.second)) { + arrival_times[bit] = *jt; + if (arrivals.size() > 1) + jt++; + } } - if (arrival) - for (auto bit : sigmap(conn.second)) - arrival_times[bit] = arrival; } } } From ceabd5bc3984a0ff088d697ac8ba7061b4f552fb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 9 Jan 2020 14:03:43 -0800 Subject: [PATCH 06/25] write_xaiger: cleanup --- backends/aiger/xaiger.cc | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1956422bc..cde53ff63 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -243,23 +243,21 @@ struct XAigerWriter if (port_wire->port_output) { arrivals.clear(); auto it = port_wire->attributes.find("\\abc9_arrival"); - if (it != port_wire->attributes.end()) { - if (it->second.flags == 0) - arrivals.emplace_back(it->second.as_int()); - else - for (const auto &tok : split_tokens(it->second.decode_string())) - arrivals.push_back(atoi(tok.c_str())); - } - if (!arrivals.empty()) { - if (GetSize(arrivals) > 1 && GetSize(arrivals) != GetSize(port_wire)) - log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first), - GetSize(port_wire), log_signal(it->second), GetSize(arrivals)); - auto jt = arrivals.begin(); - for (auto bit : sigmap(conn.second)) { - arrival_times[bit] = *jt; - if (arrivals.size() > 1) - jt++; - } + if (it == port_wire->attributes.end()) + continue; + if (it->second.flags == 0) + arrivals.emplace_back(it->second.as_int()); + else + for (const auto &tok : split_tokens(it->second.decode_string())) + arrivals.push_back(atoi(tok.c_str())); + if (GetSize(arrivals) > 1 && GetSize(arrivals) != GetSize(port_wire)) + log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first), + GetSize(port_wire), log_signal(it->second), GetSize(arrivals)); + auto jt = arrivals.begin(); + for (auto bit : sigmap(conn.second)) { + arrival_times[bit] = *jt; + if (arrivals.size() > 1) + jt++; } } } From 5e280a3b591d3d8b556992b0708fcaaf6a6a3e0d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 9 Jan 2020 14:04:10 -0800 Subject: [PATCH 07/25] abc9_exe: -box to not require -lut --- passes/techmap/abc9_exe.cc | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index f7dafda96..b3afaebe6 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -188,20 +188,15 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe std::string abc9_script; - if (!lut_costs.empty()) { + if (!lut_costs.empty()) abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); - if (!box_file.empty()) - abc9_script += stringf("read_box %s; ", box_file.c_str()); - } else - if (!lut_file.empty()) { + if (!lut_file.empty()) abc9_script += stringf("read_lut %s; ", lut_file.c_str()); - if (!box_file.empty()) - abc9_script += stringf("read_box %s; ", box_file.c_str()); - } else log_abort(); + abc9_script += stringf("read_box %s; ", box_file.c_str()); abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); if (!script_file.empty()) { @@ -355,7 +350,7 @@ struct Abc9ExePass : public Pass { log(" command output is identical across runs.\n"); log("\n"); log(" -box \n"); - log(" pass this file with box library to ABC. Use with -lut.\n"); + log(" pass this file with box library to ABC.\n"); log("\n"); log(" -cwd \n"); log(" use this as the current working directory, inside which the 'input.xaig'\n"); From b2259a920165930261050065d870d03fc7573346 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 10 Jan 2020 11:45:41 -0800 Subject: [PATCH 08/25] Add abc9_ops -check, -prep_times, -write_box for required times --- passes/techmap/abc9.cc | 26 ++- passes/techmap/abc9_ops.cc | 300 +++++++++++++++++++++++++++-------- techlibs/xilinx/abc9_model.v | 5 + 3 files changed, 256 insertions(+), 75 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f6627602b..41cfdeece 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -131,6 +131,7 @@ struct Abc9Pass : public ScriptPass std::stringstream exe_cmd; bool dff_mode, cleanup; + std::string box_file; void clear_flags() YS_OVERRIDE { @@ -138,6 +139,7 @@ struct Abc9Pass : public ScriptPass exe_cmd << "abc9_exe"; dff_mode = false; cleanup = true; + box_file.clear(); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -154,7 +156,7 @@ struct Abc9Pass : public ScriptPass std::string arg = args[argidx]; if ((arg == "-exe" || arg == "-script" || arg == "-D" || /* arg == "-S" || */ arg == "-lut" || arg == "-luts" || - arg == "-box" || arg == "-W") && + /*arg == "-box" ||*/ arg == "-W") && argidx+1 < args.size()) { exe_cmd << " " << arg << " " << args[++argidx]; continue; @@ -173,6 +175,10 @@ struct Abc9Pass : public ScriptPass cleanup = false; continue; } + if (arg == "-box" && argidx+1 < args.size()) { + box_file = args[++argidx]; + continue; + } break; } extra_args(args, argidx, design); @@ -185,11 +191,12 @@ struct Abc9Pass : public ScriptPass void script() YS_OVERRIDE { if (check_label("pre")) { + run("abc9_ops -check"); run("scc -set_attr abc9_scc_id {}"); if (help_mode) - run("abc9_ops -break_scc -prep_holes [-dff]", "(option for -dff)"); + run("abc9_ops -break_scc -prep_times -prep_holes [-dff]", "(option for -dff)"); else - run("abc9_ops -break_scc -prep_holes" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)"); + run("abc9_ops -break_scc -prep_times -prep_holes" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)"); run("select -set abc9_holes A:abc9_holes"); run("flatten -wb @abc9_holes"); run("techmap @abc9_holes"); @@ -203,8 +210,9 @@ struct Abc9Pass : public ScriptPass if (check_label("map")) { if (help_mode) { run("foreach module in selection"); + run(" abc9_ops -write_box [(-box value)|(null)] /input.box"); run(" write_xaiger -map /input.sym /input.xaig"); - run(" abc9_exe [options] -cwd "); + run(" abc9_exe [options] -cwd -box /input.box"); run(" read_aiger -xaiger -wideports -module_name $abc9 -map /input.sym /output.aig"); run(" abc9_ops -reintegrate"); } @@ -229,6 +237,10 @@ struct Abc9Pass : public ScriptPass tempdir_name[0] = tempdir_name[4] = '_'; tempdir_name = make_temp_dir(tempdir_name); + if (box_file.empty()) + run(stringf("abc9_ops -write_box (null) %s/input.box", tempdir_name.c_str())); + else + run(stringf("abc9_ops -write_box %s %s/input.box", box_file.c_str(), tempdir_name.c_str())); run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs"); @@ -238,10 +250,8 @@ struct Abc9Pass : public ScriptPass active_design->scratchpad_get_int("write_xaiger.num_inputs"), num_outputs); if (num_outputs) { - run(stringf("%s -cwd %s", exe_cmd.str().c_str(), tempdir_name.c_str()), - "abc9_exe [options] -cwd "); - run(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod->name), tempdir_name.c_str(), tempdir_name.c_str()), - "read_aiger -xaiger -wideports -module_name $abc9 -map /input.sym /output.aig"); + run(stringf("%s -cwd %s -box %s/input.box", exe_cmd.str().c_str(), tempdir_name.c_str(), tempdir_name.c_str())); + run(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod->name), tempdir_name.c_str(), tempdir_name.c_str())); run("abc9_ops -reintegrate"); } else diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 7c7208711..4d49bb4d2 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -23,6 +23,8 @@ #include "kernel/utils.h" #include "kernel/celltypes.h" +#define ABC9_DELAY_BASE_ID 9000 + USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -33,6 +35,48 @@ inline std::string remap_name(RTLIL::IdString abc9_name) return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1); } +void check(RTLIL::Design *design) +{ + dict box_lookup; + for (auto m : design->modules()) { + auto it = m->attributes.find(ID(abc9_box_id)); + if (it == m->attributes.end()) + continue; + if (m->name.begins_with("$paramod")) + continue; + auto id = it->second.as_int(); + auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); + if (!r.second) + log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", + log_id(m), id, log_id(r.first->second)); + + // Make carry in the last PI, and carry out the last PO + // since ABC requires it this way + IdString carry_in, carry_out; + for (const auto &port_name : m->ports) { + auto w = m->wire(port_name); + log_assert(w); + if (w->get_bool_attribute("\\abc9_carry")) { + if (w->port_input) { + if (carry_in != IdString()) + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); + carry_in = port_name; + } + if (w->port_output) { + if (carry_out != IdString()) + log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(m)); + carry_out = port_name; + } + } + } + + if (carry_in != IdString() && carry_out == IdString()) + log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); + if (carry_in == IdString() && carry_out != IdString()) + log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); + } +} + void break_scc(RTLIL::Module *module) { // For every unique SCC found, (arbitrarily) find the first @@ -301,6 +345,7 @@ void prep_holes(RTLIL::Module *module, bool dff) } cell->attributes["\\abc9_box_seq"] = box_list.size(); + //log_debug("%s.%s is box %d\n", log_id(module), log_id(cell), box_list.size()); box_list.emplace_back(cell); } log_assert(!box_list.empty()); @@ -318,8 +363,8 @@ void prep_holes(RTLIL::Module *module, bool dff) log_assert(orig_box_module); IdString derived_name = orig_box_module->derive(design, cell->parameters); RTLIL::Module* box_module = design->module(derived_name); - if (box_module->has_processes()) - Pass::call_on_module(design, box_module, "proc"); + cell->type = derived_name; + cell->parameters.clear(); int box_inputs = 0; auto r = cell_cache.insert(std::make_pair(derived_name, nullptr)); @@ -328,6 +373,9 @@ void prep_holes(RTLIL::Module *module, bool dff) holes_cell = holes_module->addCell(cell->name, cell->type); holes_cell->parameters = cell->parameters; r.first->second = holes_cell; + + if (box_module->has_processes()) + Pass::call_on_module(design, box_module, "proc"); } auto r2 = box_ports.insert(cell->type); @@ -339,25 +387,15 @@ void prep_holes(RTLIL::Module *module, bool dff) auto w = box_module->wire(port_name); log_assert(w); if (w->get_bool_attribute("\\abc9_carry")) { - if (w->port_input) { - if (carry_in != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(box_module)); + if (w->port_input) carry_in = port_name; - } - if (w->port_output) { - if (carry_out != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(box_module)); + if (w->port_output) carry_out = port_name; - } } else r2.first->second.push_back(port_name); } - if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(box_module)); - if (carry_in == IdString() && carry_out != IdString()) - log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(box_module)); if (carry_in != IdString()) { r2.first->second.push_back(carry_in); r2.first->second.push_back(carry_out); @@ -423,6 +461,116 @@ void prep_holes(RTLIL::Module *module, bool dff) } } +void prep_times(RTLIL::Design *design) +{ + std::set delays; + std::vector boxes; + std::map> requireds; + for (auto module : design->selected_modules()) { + if (module->get_bool_attribute("\\abc9_holes")) + continue; + + if (module->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(module)); + continue; + } + + boxes.clear(); + for (auto cell : module->cells()) { + if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_), ID($__ABC9_DELAY))) + continue; + + RTLIL::Module* inst_module = module->design->module(cell->type); + if (!inst_module) + continue; + if (!inst_module->get_blackbox_attribute()) + continue; + // Flop inputs cannot have required times + // (required time should be captured by flop box) + // TODO: enforce this + if (cell->attributes.count(ID(abc9_box_id))) + continue; + boxes.emplace_back(cell); + } + + delays.clear(); + requireds.clear(); + for (auto cell : boxes) { + RTLIL::Module* inst_module = module->design->module(cell->type); + + for (auto &conn : cell->connections_) { + auto port_wire = inst_module->wire(conn.first); + if (!port_wire->port_input) + continue; + + auto it = port_wire->attributes.find("\\abc9_required"); + if (it == port_wire->attributes.end()) + continue; + + int count = 0; + requireds.clear(); + if (it->second.flags == 0) { + count = 1; + requireds[it->second.as_int()].push_back(0); + } + else + for (const auto &tok : split_tokens(it->second.decode_string())) + requireds[atoi(tok.c_str())].push_back(count++); + if (count > 1 && count != GetSize(port_wire)) + log_error("%s.%s is %d bits wide but abc9_required = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first), + GetSize(port_wire), log_signal(it->second), count); + + SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); + for (const auto &i : requireds) { + delays.insert(i.first); + for (auto offset : i.second) { + auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); + box->setPort(ID(I), conn.second[offset]); + box->setPort(ID(O), O[offset]); + box->setParam(ID(DELAY), i.first); + conn.second[offset] = O[offset]; + } + } + } + } + + std::stringstream ss; + bool first = true; + for (auto d : delays) + if (first) { + first = false; + ss << d; + } + else + ss << " " << d; + module->attributes[ID(abc9_delays)] = ss.str(); + } +} + +void write_box(RTLIL::Module *module, const std::string &src, const std::string &dst) { + std::ofstream ofs(dst); + log_assert(ofs.is_open()); + + // Since ABC can only accept one box file, we have to copy + // over the existing box file + if (src != "(null)") { + std::ifstream ifs(src); + ofs << ifs.rdbuf() << std::endl; + ifs.close(); + } + + auto it = module->attributes.find(ID(abc9_delays)); + if (it != module->attributes.end()) { + for (const auto &tok : split_tokens(it->second.decode_string())) { + int d = atoi(tok.c_str()); + ofs << "$__ABC9_DELAY@" << d << " " << ABC9_DELAY_BASE_ID + d << " 0 1 1" << std::endl; + ofs << d << std::endl; + } + } + + ofs.close(); +} + void reintegrate(RTLIL::Module *module) { auto design = module->design; @@ -438,8 +586,6 @@ void reintegrate(RTLIL::Module *module) module->addWire(remap_name(w->name), GetSize(w)); dict box_lookup; - dict> box_ports; - for (auto m : design->modules()) { auto it = m->attributes.find(ID(abc9_box_id)); if (it == m->attributes.end()) @@ -447,51 +593,19 @@ void reintegrate(RTLIL::Module *module) if (m->name.begins_with("$paramod")) continue; auto id = it->second.as_int(); - auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); - if (!r.second) - log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", - log_id(m), id, log_id(r.first->second)); + auto r YS_ATTRIBUTE(unused) = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); log_assert(r.second); - - auto r2 = box_ports.insert(m->name); - if (r2.second) { - // Make carry in the last PI, and carry out the last PO - // since ABC requires it this way - IdString carry_in, carry_out; - for (const auto &port_name : m->ports) { - auto w = m->wire(port_name); - log_assert(w); - if (w->get_bool_attribute("\\abc9_carry")) { - if (w->port_input) { - if (carry_in != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); - carry_in = port_name; - } - if (w->port_output) { - if (carry_out != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(m)); - carry_out = port_name; - } - } - else - r2.first->second.push_back(port_name); - } - - if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); - if (carry_in == IdString() && carry_out != IdString()) - log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); - if (carry_in != IdString()) { - r2.first->second.push_back(carry_in); - r2.first->second.push_back(carry_out); - } - } } + pool delay_boxes; std::vector boxes; for (auto cell : module->cells().to_vector()) { if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) module->remove(cell); + else if (cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) { + delay_boxes.insert(cell->name); + module->remove(cell); + } else if (cell->attributes.erase("\\abc9_box_seq")) boxes.emplace_back(cell); } @@ -501,6 +615,7 @@ void reintegrate(RTLIL::Module *module) dict not2drivers; dict> bit2sinks; + dict> box_ports; std::map cell_stats; for (auto mapped_cell : mapped_mod->cells()) { @@ -551,16 +666,6 @@ void reintegrate(RTLIL::Module *module) } if (mapped_cell->type.in(ID($lut), ID($__ABC9_FF_))) { - // Convert buffer into direct connection - if (mapped_cell->type == ID($lut) && - GetSize(mapped_cell->getPort(ID::A)) == 1 && - mapped_cell->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) { - SigSpec my_a = module->wires_.at(remap_name(mapped_cell->getPort(ID::A).as_wire()->name)); - SigSpec my_y = module->wires_.at(remap_name(mapped_cell->getPort(ID::Y).as_wire()->name)); - module->connect(my_y, my_a); - log_abort(); - continue; - } RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); cell->parameters = mapped_cell->parameters; cell->attributes = mapped_cell->attributes; @@ -588,6 +693,16 @@ void reintegrate(RTLIL::Module *module) bit_drivers[i].insert(mapped_cell->name); } } + else if (delay_boxes.count(mapped_cell->name)) { + SigBit I = mapped_cell->getPort(ID(i)); + SigBit O = mapped_cell->getPort(ID(o)); + if (I.wire) + I.wire = module->wires_.at(remap_name(I.wire->name)); + log_assert(O.wire); + O.wire = module->wires_.at(remap_name(O.wire->name)); + module->connect(O, I); + continue; + } else { RTLIL::Cell *existing_cell = module->cell(mapped_cell->name); log_assert(existing_cell); @@ -621,6 +736,30 @@ void reintegrate(RTLIL::Module *module) bit_drivers[i].insert(mapped_cell->name); } + auto r2 = box_ports.insert(cell->type); + if (r2.second) { + // Make carry in the last PI, and carry out the last PO + // since ABC requires it this way + IdString carry_in, carry_out; + for (const auto &port_name : box_module->ports) { + auto w = box_module->wire(port_name); + log_assert(w); + if (w->get_bool_attribute("\\abc9_carry")) { + if (w->port_input) + carry_in = port_name; + if (w->port_output) + carry_out = port_name; + } + else + r2.first->second.push_back(port_name); + } + + if (carry_in != IdString()) { + r2.first->second.push_back(carry_in); + r2.first->second.push_back(carry_out); + } + } + int input_count = 0, output_count = 0; for (const auto &port_name : box_ports.at(cell->type)) { RTLIL::Wire *w = box_module->wire(port_name); @@ -807,16 +946,23 @@ struct Abc9OpsPass : public Pass { { log_header(design, "Executing ABC9_OPS pass (helper functions for ABC9).\n"); + bool check_mode = false; + bool prep_times_mode = false; bool break_scc_mode = false; bool unbreak_scc_mode = false; - bool prep_dff_mode = false; bool prep_holes_mode = false; + bool prep_dff_mode = false; + std::string write_box_src, write_box_dst; bool reintegrate_mode = false; bool dff_mode = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; + if (arg == "-check") { + check_mode = true; + continue; + } if (arg == "-break_scc") { break_scc_mode = true; continue; @@ -833,6 +979,17 @@ struct Abc9OpsPass : public Pass { prep_holes_mode = true; continue; } + if (arg == "-prep_times") { + prep_times_mode = true; + continue; + } + if (arg == "-write_box" && argidx+2 < args.size()) { + write_box_src = args[++argidx]; + write_box_dst = args[++argidx]; + rewrite_filename(write_box_src); + rewrite_filename(write_box_dst); + continue; + } if (arg == "-reintegrate") { reintegrate_mode = true; continue; @@ -845,6 +1002,13 @@ struct Abc9OpsPass : public Pass { } extra_args(args, argidx, design); + // TODO: Check at least one mode given + + if (check_mode) + check(design); + if (prep_times_mode) + prep_times(design); + for (auto mod : design->selected_modules()) { if (mod->get_bool_attribute("\\abc9_holes")) continue; @@ -858,10 +1022,12 @@ struct Abc9OpsPass : public Pass { break_scc(mod); if (unbreak_scc_mode) unbreak_scc(mod); - if (prep_dff_mode) - prep_dff(mod); if (prep_holes_mode) prep_holes(mod, dff_mode); + if (prep_dff_mode) + prep_dff(mod); + if (!write_box_src.empty()) + write_box(mod, write_box_src, write_box_dst); if (reintegrate_mode) reintegrate(mod); } diff --git a/techlibs/xilinx/abc9_model.v b/techlibs/xilinx/abc9_model.v index 204fa883f..25530acf8 100644 --- a/techlibs/xilinx/abc9_model.v +++ b/techlibs/xilinx/abc9_model.v @@ -33,6 +33,11 @@ endmodule module \$__ABC9_FF_ (input D, output Q); endmodule +(* abc9_box_id = (9000+DELAY) *) +module \$__ABC9_DELAY (input I, output O); + parameter DELAY = 0; +endmodule + // Box to emulate async behaviour of FDC* (* abc9_box_id = 1000, lib_whitebox *) module \$__ABC9_ASYNC0 (input A, S, output Y); From e0af812180528c45e79291209e2e3726c98b80ae Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 10 Jan 2020 12:38:49 -0800 Subject: [PATCH 09/25] abc9_ops -prep_times: update comment --- passes/techmap/abc9_ops.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 4d49bb4d2..14b3f6c43 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -485,9 +485,9 @@ void prep_times(RTLIL::Design *design) continue; if (!inst_module->get_blackbox_attribute()) continue; - // Flop inputs cannot have required times - // (required time should be captured by flop box) - // TODO: enforce this + // Only flop boxes are not combinatorial and may have required times, + // however those times are captured by this flop box, no need to + // add delay boxes if (cell->attributes.count(ID(abc9_box_id))) continue; boxes.emplace_back(cell); @@ -566,6 +566,7 @@ void write_box(RTLIL::Module *module, const std::string &src, const std::string ofs << "$__ABC9_DELAY@" << d << " " << ABC9_DELAY_BASE_ID + d << " 0 1 1" << std::endl; ofs << d << std::endl; } + module->attributes.erase(it); } ofs.close(); From 475d983676a42e57a104aaf5e72462d704c0c3aa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 10 Jan 2020 14:49:52 -0800 Subject: [PATCH 10/25] abc9_ops -prep_times: generate flop boxes from abc9_required attr --- passes/techmap/abc9_ops.cc | 84 ++++++++++++++++++++++++++++-------- techlibs/xilinx/abc9_xc7.box | 61 -------------------------- 2 files changed, 67 insertions(+), 78 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 14b3f6c43..918afd284 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -39,9 +39,13 @@ void check(RTLIL::Design *design) { dict box_lookup; for (auto m : design->modules()) { + auto flop = m->get_bool_attribute(ID(abc9_flop)); auto it = m->attributes.find(ID(abc9_box_id)); - if (it == m->attributes.end()) + if (it == m->attributes.end()) { + if (flop) + log_error("Module '%s' contains (* abc9_flop *) but not (* abc9_box_id= *).\n", log_id(m)); continue; + } if (m->name.begins_with("$paramod")) continue; auto id = it->second.as_int(); @@ -59,21 +63,31 @@ void check(RTLIL::Design *design) if (w->get_bool_attribute("\\abc9_carry")) { if (w->port_input) { if (carry_in != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); + log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", log_id(m)); carry_in = port_name; } if (w->port_output) { if (carry_out != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(m)); + log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", log_id(m)); carry_out = port_name; } } } if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); + log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", log_id(m)); if (carry_in == IdString() && carry_out != IdString()) - log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); + log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", log_id(m)); + + if (flop) { + int num_outputs = 0; + for (auto port_name : m->ports) { + auto wire = m->wire(port_name); + if (wire->port_output) num_outputs++; + } + if (num_outputs != 1) + log_error("Module '%s' with (* abc_flop *) has %d outputs (expect 1).\n", log_id(m), num_outputs); + } } } @@ -464,12 +478,10 @@ void prep_holes(RTLIL::Module *module, bool dff) void prep_times(RTLIL::Design *design) { std::set delays; + pool flops; std::vector boxes; std::map> requireds; for (auto module : design->selected_modules()) { - if (module->get_bool_attribute("\\abc9_holes")) - continue; - if (module->processes.size() > 0) { log("Skipping module %s as it contains processes.\n", log_id(module)); continue; @@ -485,10 +497,13 @@ void prep_times(RTLIL::Design *design) continue; if (!inst_module->get_blackbox_attribute()) continue; - // Only flop boxes are not combinatorial and may have required times, - // however those times are captured by this flop box, no need to - // add delay boxes - if (cell->attributes.count(ID(abc9_box_id))) + if (inst_module->get_bool_attribute(ID(abc9_flop))) { + flops.insert(inst_module); + continue; + } + // All remaining boxes are combinatorial and cannot + // contain a required time + if (inst_module->attributes.count(ID(abc9_box_id))) continue; boxes.emplace_back(cell); } @@ -536,15 +551,48 @@ void prep_times(RTLIL::Design *design) std::stringstream ss; bool first = true; - for (auto d : delays) - if (first) { + for (auto d : delays) { + if (first) first = false; - ss << d; - } else - ss << " " << d; + ss << " "; + ss << d; + } module->attributes[ID(abc9_delays)] = ss.str(); } + + std::stringstream ss; + for (auto flop_module : flops) { + // Skip parameterised flop_modules for now (since we do not + // dynamically generate the abc9_box_id) + if (flop_module->name.begins_with("$paramod")) + continue; + + int num_inputs = 0, num_outputs = 0; + for (auto port_name : flop_module->ports) { + auto wire = flop_module->wire(port_name); + if (wire->port_input) num_inputs++; + if (wire->port_output) num_outputs++; + } + log_assert(num_outputs == 1); + + ss << log_id(flop_module) << " " << flop_module->attributes.at(ID(abc9_box_id)).as_int(); + ss << " 1 " << num_inputs+1 << " " << num_outputs << std::endl; + bool first = true; + for (auto port_name : flop_module->ports) { + auto wire = flop_module->wire(port_name); + if (!wire->port_input) + continue; + if (first) + first = false; + else + ss << " "; + ss << wire->attributes.at("\\abc9_required", 0).as_int(); + } + // Last input is 'abc9_ff.Q' + ss << " 0" << std::endl << std::endl; + } + design->scratchpad_set_string("abc9_ops.box.flops", ss.str()); } void write_box(RTLIL::Module *module, const std::string &src, const std::string &dst) { @@ -559,6 +607,8 @@ void write_box(RTLIL::Module *module, const std::string &src, const std::string ifs.close(); } + ofs << module->design->scratchpad_get_string("abc9_ops.box.flops"); + auto it = module->attributes.find(ID(abc9_delays)); if (it != module->attributes.end()) { for (const auto &tok : split_tokens(it->second.decode_string())) { diff --git a/techlibs/xilinx/abc9_xc7.box b/techlibs/xilinx/abc9_xc7.box index 13f4f0e61..48d492801 100644 --- a/techlibs/xilinx/abc9_xc7.box +++ b/techlibs/xilinx/abc9_xc7.box @@ -62,67 +62,6 @@ $__ABC9_ASYNC1 1001 1 2 1 #A S 0 764 # Y -# Flop boxes: -# * Max delays from https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L237-L251 -# https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L265-L277 -# * Exception: $abc9_currQ is a special input (located last) necessary for clock-enable functionality - -# Box 1100 : FDRE -# name ID w/b ins outs -FDRE 1100 1 5 1 -#C CE D R $abc9_currQ -#0 109 -46 404 0 -0 109 0 404 0 # Q (-46ps Tsu clamped to 0) - -# Box 1101 : FDRE_1 -# name ID w/b ins outs -FDRE_1 1101 1 5 1 -#C CE D R $abc9_currQ -#0 109 -46 404 0 -0 109 0 404 0 # Q (-46ps Tsu clamped to 0) - -# Box 1102 : FDSE -# name ID w/b ins outs -FDSE 1102 1 5 1 -#C CE D R $abc9_currQ -#0 109 -46 404 0 -0 109 0 404 0 # Q (-46ps Tsu clamped to 0) - -# Box 1103 : FDSE_1 -# name ID w/b ins outs -FDSE_1 1103 1 5 1 -#C CE D R $abc9_currQ -#0 109 -46 404 0 -0 109 0 404 0 # Q (-46ps Tsu clamped to 0) - -# Box 1104 : FDCE -# name ID w/b ins outs -FDCE 1104 1 5 1 -#C CE CLR D $abc9_currQ -#0 109 764 -46 0 -0 109 764 0 0 # Q (-46ps Tsu clamped to 0) - -# Box 1105 : FDCE_1 -# name ID w/b ins outs -FDCE_1 1105 1 5 1 -#C CE CLR D $abc9_currQ -#0 109 764 -46 0 -0 109 764 0 0 # Q (-46ps Tsu clamped to 0) - -# Box 1106 : FDPE -# name ID w/b ins outs -FDPE 1106 1 5 1 -#C CE D PRE $abc9_currQ -#0 109 -46 764 0 -0 109 0 764 0 # Q (-46ps Tsu clamped to 0) - -# Box 1107 : FDPE_1 -# name ID w/b ins outs -FDPE_1 1107 1 5 1 -#C CE D PRE $abc9_currQ -#0 109 -46 764 0 -0 109 0 764 0 # Q (-46ps Tsu clamped to 0) - # Box 2000 : $__ABC9_LUT6 # (private cell to emulate async behaviour of LUTRAMs) # SLICEM/A6LUT From 28f814ee59e36230200108381a9c674c5275e3e4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 10 Jan 2020 17:12:31 -0800 Subject: [PATCH 11/25] Add abc9_required to DSP48E1.{A,B,C,D,PCIN} --- techlibs/xilinx/cells_sim.v | 165 ++++++++++++++++++++++++++---------- 1 file changed, 122 insertions(+), 43 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index aa6a5ed52..08380ddca 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -2290,21 +2290,30 @@ module DSP48E1 ( output reg MULTSIGNOUT, output OVERFLOW, `ifdef YOSYS - (* abc9_arrival = \DSP48E1.P_arrival () *) + (* abc9_arrival = \P.abc9_arrival () *) `endif output reg signed [47:0] P, output reg PATTERNBDETECT, output reg PATTERNDETECT, `ifdef YOSYS - (* abc9_arrival = \DSP48E1.PCOUT_arrival () *) + (* abc9_arrival = \PCOUT.abc9_arrival () *) `endif output [47:0] PCOUT, output UNDERFLOW, +`ifdef YOSYS + (* abc9_required = \A.abc9_required () *) +`endif input signed [29:0] A, input [29:0] ACIN, input [3:0] ALUMODE, +`ifdef YOSYS + (* abc9_required = \B.abc9_required () *) +`endif input signed [17:0] B, input [17:0] BCIN, +`ifdef YOSYS + (* abc9_required = \C.abc9_required () *) +`endif input [47:0] C, input CARRYCASCIN, input CARRYIN, @@ -2323,10 +2332,16 @@ module DSP48E1 ( input CEM, input CEP, (* clkbuf_sink *) input CLK, +`ifdef YOSYS + (* abc9_required = \D.abc9_required () *) +`endif input [24:0] D, input [4:0] INMODE, input MULTSIGNIN, input [6:0] OPMODE, +`ifdef YOSYS + (* abc9_required = \PCIN.abc9_required () *) +`endif input [47:0] PCIN, input RSTA, input RSTALLCARRYIN, @@ -2371,69 +2386,133 @@ module DSP48E1 ( parameter [6:0] IS_OPMODE_INVERTED = 7'b0; `ifdef YOSYS - function integer \DSP48E1.P_arrival ; + function integer \A.abc9_required ; begin - \DSP48E1.P_arrival = 0; - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin - if (PREG != 0) \DSP48E1.P_arrival = 329; - // Worst-case from CREG and MREG - else if (CREG != 0) \DSP48E1.P_arrival = 1687; - else if (MREG != 0) \DSP48E1.P_arrival = 1671; - // Worst-case from AREG and BREG - else if (AREG != 0) \DSP48E1.P_arrival = 2952; - else if (BREG != 0) \DSP48E1.P_arrival = 2813; + \A.abc9_required = 0; + if (AREG != 0) \A.abc9_required = 254; + else if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin + if (MREG != 0) \A.abc9_required = 1416; + else if (PREG != 0) \A.abc9_required = (USE_PATTERN_DETECT != "NO_PATDET" ? 3030 : 2739) ; end else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin - if (PREG != 0) \DSP48E1.P_arrival = 329; - // Worst-case from CREG and MREG - else if (CREG != 0) \DSP48E1.P_arrival = 1687; - else if (MREG != 0) \DSP48E1.P_arrival = 1671; - // Worst-case from AREG, ADREG, BREG, DREG - else if (AREG != 0) \DSP48E1.P_arrival = 3935; - else if (DREG != 0) \DSP48E1.P_arrival = 3908; - else if (ADREG != 0) \DSP48E1.P_arrival = 2958; - else if (BREG != 0) \DSP48E1.P_arrival = 2813; + // Worst-case from ADREG and MREG + if (MREG != 0) \A.abc9_required = 2400; + else if (ADREG != 0) \A.abc9_required = 1283; + else if (PREG != 0) \A.abc9_required = 3723; + else if (PREG != 0) \A.abc9_required = (USE_PATTERN_DETECT != "NO_PATDET" ? 4014 : 3723) ; end else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin - if (PREG != 0) \DSP48E1.P_arrival = 329; + if (PREG != 0) \A.abc9_required = (USE_PATTERN_DETECT != "NO_PATDET" ? 1730 : 1441) ; + end + end + endfunction + function integer \B.abc9_required ; + begin + \B.abc9_required = 0; + if (BREG != 0) \B.abc9_required = 324; + else if (MREG != 0) \B.abc9_required = 1285; + else if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin + if (PREG != 0) \B.abc9_required = (USE_PATTERN_DETECT != "NO_PATDET" ? 2898 : 2608) ; + end + else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin + if (PREG != 0) \B.abc9_required = (USE_PATTERN_DETECT != "NO_PATDET" ? 2898 : 2608) ; + end + else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin + if (PREG != 0) \B.abc9_required = (USE_PATTERN_DETECT != "NO_PATDET" ? 1718 : 1428) ; + end + end + endfunction + function integer \C.abc9_required ; + begin + \C.abc9_required = 0; + if (CREG != 0) \C.abc9_required = 168; + else if (PREG != 0) \C.abc9_required = (USE_PATTERN_DETECT != "NO_PATDET" ? 1534 : 1244) ; + end + endfunction + function integer \D.abc9_required ; + begin + \D.abc9_required = 0; + if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin + end + else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin + if (DREG != 0) \D.abc9_required = 248; + else if (ADREG != 0) \D.abc9_required = 1195; + else if (MREG != 0) \D.abc9_required = 2310; + else if (PREG != 0) \D.abc9_required = (USE_PATTERN_DETECT != "NO_PATDET" ? 3925 : 3635) ; + end + else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin + end + end + endfunction + function integer \PCIN.abc9_required ; + begin + \PCIN.abc9_required = 0; + if (PREG != 0) \PCIN.abc9_required = (USE_PATTERN_DETECT != "NO_PATDET" ? 1315 : 1025) ; + end + endfunction + function integer \P.abc9_arrival ; + begin + \P.abc9_arrival = 0; + if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin + if (PREG != 0) \P.abc9_arrival = 329; + // Worst-case from CREG and MREG + else if (CREG != 0) \P.abc9_arrival = 1687; + else if (MREG != 0) \P.abc9_arrival = 1671; + // Worst-case from AREG and BREG + else if (AREG != 0) \P.abc9_arrival = 2952; + else if (BREG != 0) \P.abc9_arrival = 2813; + end + else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin + if (PREG != 0) \P.abc9_arrival = 329; + // Worst-case from CREG and MREG + else if (CREG != 0) \P.abc9_arrival = 1687; + else if (MREG != 0) \P.abc9_arrival = 1671; + // Worst-case from AREG, ADREG, BREG, DREG + else if (AREG != 0) \P.abc9_arrival = 3935; + else if (DREG != 0) \P.abc9_arrival = 3908; + else if (ADREG != 0) \P.abc9_arrival = 2958; + else if (BREG != 0) \P.abc9_arrival = 2813; + end + else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin + if (PREG != 0) \P.abc9_arrival = 329; // Worst-case from AREG, BREG, CREG - else if (CREG != 0) \DSP48E1.P_arrival = 1687; - else if (AREG != 0) \DSP48E1.P_arrival = 1632; - else if (BREG != 0) \DSP48E1.P_arrival = 1616; + else if (CREG != 0) \P.abc9_arrival = 1687; + else if (AREG != 0) \P.abc9_arrival = 1632; + else if (BREG != 0) \P.abc9_arrival = 1616; end //else // $error("Invalid DSP48E1 configuration"); end endfunction - function integer \DSP48E1.PCOUT_arrival ; + function integer \PCOUT.abc9_arrival ; begin - \DSP48E1.PCOUT_arrival = 0; + \PCOUT.abc9_arrival = 0; if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin - if (PREG != 0) \DSP48E1.PCOUT_arrival = 435; + if (PREG != 0) \PCOUT.abc9_arrival = 435; // Worst-case from CREG and MREG - else if (CREG != 0) \DSP48E1.PCOUT_arrival = 1835; - else if (MREG != 0) \DSP48E1.PCOUT_arrival = 1819; + else if (CREG != 0) \PCOUT.abc9_arrival = 1835; + else if (MREG != 0) \PCOUT.abc9_arrival = 1819; // Worst-case from AREG and BREG - else if (AREG != 0) \DSP48E1.PCOUT_arrival = 3098; - else if (BREG != 0) \DSP48E1.PCOUT_arrival = 2960; + else if (AREG != 0) \PCOUT.abc9_arrival = 3098; + else if (BREG != 0) \PCOUT.abc9_arrival = 2960; end else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin - if (PREG != 0) \DSP48E1.PCOUT_arrival = 435; + if (PREG != 0) \PCOUT.abc9_arrival = 435; // Worst-case from CREG and MREG - else if (CREG != 0) \DSP48E1.PCOUT_arrival = 1835; - else if (MREG != 0) \DSP48E1.PCOUT_arrival = 1819; + else if (CREG != 0) \PCOUT.abc9_arrival = 1835; + else if (MREG != 0) \PCOUT.abc9_arrival = 1819; // Worst-case from AREG, ADREG, BREG, DREG - else if (AREG != 0) \DSP48E1.PCOUT_arrival = 4083; - else if (DREG != 0) \DSP48E1.PCOUT_arrival = 4056; - else if (BREG != 0) \DSP48E1.PCOUT_arrival = 2960; - else if (ADREG != 0) \DSP48E1.PCOUT_arrival = 2859; + else if (AREG != 0) \PCOUT.abc9_arrival = 4083; + else if (DREG != 0) \PCOUT.abc9_arrival = 4056; + else if (BREG != 0) \PCOUT.abc9_arrival = 2960; + else if (ADREG != 0) \PCOUT.abc9_arrival = 2859; end else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin - if (PREG != 0) \DSP48E1.PCOUT_arrival = 435; + if (PREG != 0) \PCOUT.abc9_arrival = 435; // Worst-case from AREG, BREG, CREG - else if (CREG != 0) \DSP48E1.PCOUT_arrival = 1835; - else if (AREG != 0) \DSP48E1.PCOUT_arrival = 1780; - else if (BREG != 0) \DSP48E1.PCOUT_arrival = 1765; + else if (CREG != 0) \PCOUT.abc9_arrival = 1835; + else if (AREG != 0) \PCOUT.abc9_arrival = 1780; + else if (BREG != 0) \PCOUT.abc9_arrival = 1765; end //else // $error("Invalid DSP48E1 configuration"); From f24de88f385a3eeaadd9b9c8c200a7c338f37448 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 10 Jan 2020 17:13:27 -0800 Subject: [PATCH 12/25] log_debug() for abc9_{arrival,required} times --- backends/aiger/xaiger.cc | 8 ++++++++ passes/techmap/abc9_ops.cc | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index cde53ff63..359d951b9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -254,6 +254,14 @@ struct XAigerWriter log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first), GetSize(port_wire), log_signal(it->second), GetSize(arrivals)); auto jt = arrivals.begin(); + +#ifndef NDEBUG + if (ys_debug(1)) { + static std::set> seen; + if (seen.emplace(cell->type, conn.first).second) log("%s.%s abc9_arrival = %d\n", log_id(cell->type), log_id(conn.first), *jt); + } +#endif + for (auto bit : sigmap(conn.second)) { arrival_times[bit] = *jt; if (arrivals.size() > 1) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 918afd284..eac1ff2b6 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -512,7 +512,7 @@ void prep_times(RTLIL::Design *design) requireds.clear(); for (auto cell : boxes) { RTLIL::Module* inst_module = module->design->module(cell->type); - + log_assert(inst_module); for (auto &conn : cell->connections_) { auto port_wire = inst_module->wire(conn.first); if (!port_wire->port_input) @@ -537,6 +537,12 @@ void prep_times(RTLIL::Design *design) SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); for (const auto &i : requireds) { +#ifndef NDEBUG + if (ys_debug(1)) { + static std::set> seen; + if (seen.emplace(cell->type, conn.first).second) log("%s.%s abc9_required = %d\n", log_id(cell->type), log_id(conn.first), i.first); + } +#endif delays.insert(i.first); for (auto offset : i.second) { auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); From aaafd784a54603af44fe7424c8d39be2443368e5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 13:05:39 -0800 Subject: [PATCH 13/25] write_xaiger: skip if no arrival times --- backends/aiger/xaiger.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d3415e45d..b424eca2c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -257,6 +257,9 @@ struct XAigerWriter arrivals.push_back(atoi(tok.c_str())); } + if (arrivals.empty()) + continue; + if (GetSize(arrivals) > 1 && GetSize(arrivals) != GetSize(port_wire)) log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first), GetSize(port_wire), log_signal(it->second), GetSize(arrivals)); From 300003cb7854650cab9dd063a864f8f1df052d6d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 13:09:54 -0800 Subject: [PATCH 14/25] abc9_ops: discard $__ABC9_DELAY boxes --- passes/techmap/abc9_ops.cc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 04a54fd63..e1f6252f2 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -572,17 +572,12 @@ void reintegrate(RTLIL::Module *module) log_assert(r.second); } - pool delay_boxes; std::vector boxes; for (auto cell : module->cells().to_vector()) { if (cell->has_keep_attr()) continue; - if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) + if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_), ID($__ABC9_DELAY))) module->remove(cell); - else if (cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) { - delay_boxes.insert(cell->name); - module->remove(cell); - } else if (cell->attributes.erase("\\abc9_box_seq")) boxes.emplace_back(cell); } @@ -674,7 +669,7 @@ void reintegrate(RTLIL::Module *module) bit_drivers[i].insert(mapped_cell->name); } } - else if (delay_boxes.count(mapped_cell->name)) { + else if (mapped_cell->type == ID($__ABC9_DELAY)) { SigBit I = mapped_cell->getPort(ID(i)); SigBit O = mapped_cell->getPort(ID(o)); if (I.wire) From 593897ffc0b7bedfd65cdddf68dee6b89295b70b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 13:13:15 -0800 Subject: [PATCH 15/25] abc9_ops: cleanup --- passes/techmap/abc9_ops.cc | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index e1f6252f2..9b7901ffb 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -233,25 +233,15 @@ void prep_xaiger(RTLIL::Module *module, bool dff) auto w = inst_module->wire(port_name); log_assert(w); if (w->get_bool_attribute("\\abc9_carry")) { - if (w->port_input) { - if (carry_in != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(inst_module)); + log_assert(w->port_input != w->port_output); + if (w->port_input) carry_in = port_name; - } - if (w->port_output) { - if (carry_out != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(inst_module)); + else if (w->port_output) carry_out = port_name; - } } else r.first->second.push_back(port_name); } - - if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(inst_module)); - if (carry_in == IdString() && carry_out != IdString()) - log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(inst_module)); if (carry_in != IdString()) { r.first->second.push_back(carry_in); r.first->second.push_back(carry_out); @@ -723,9 +713,10 @@ void reintegrate(RTLIL::Module *module) auto w = box_module->wire(port_name); log_assert(w); if (w->get_bool_attribute("\\abc9_carry")) { + log_assert(w->port_input != w->port_output); if (w->port_input) carry_in = port_name; - if (w->port_output) + else if (w->port_output) carry_out = port_name; } else From ec95fbb273872ed41e2baadb644a311d31c3ee79 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 13:21:58 -0800 Subject: [PATCH 16/25] abc9_ops: -prep_times -> -prep_delays; add doc --- passes/techmap/abc9.cc | 6 +++--- passes/techmap/abc9_ops.cc | 28 ++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5ba87fa88..dde0a11d4 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -251,9 +251,9 @@ struct Abc9Pass : public ScriptPass run("abc9_ops -check"); run("scc -set_attr abc9_scc_id {}"); if (help_mode) - run("abc9_ops -mark_scc -prep_times -prep_xaiger [-dff]", "(option for -dff)"); + run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)"); else - run("abc9_ops -mark_scc -prep_times -prep_xaiger" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)"); + run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)"); run("select -set abc9_holes A:abc9_holes"); run("flatten -wb @abc9_holes"); run("techmap @abc9_holes"); @@ -267,7 +267,7 @@ struct Abc9Pass : public ScriptPass if (check_label("map")) { if (help_mode) { run("foreach module in selection"); - run(" abc9_ops -write_box [(-box )|(null)] /input.box"); + run(" abc9_ops -write_box [|(null)] /input.box"); run(" write_xaiger -map /input.sym /input.xaig"); run(" abc9_exe [options] -cwd -box /input.box"); run(" read_aiger -xaiger -wideports -module_name $abc9 -map /input.sym /output.aig"); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 9b7901ffb..af4073594 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -383,7 +383,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) } } -void prep_times(RTLIL::Design *design) +void prep_delays(RTLIL::Design *design) { std::set delays; pool flops; @@ -918,6 +918,14 @@ struct Abc9OpsPass : public Pass { log("mapping, and is expected to be called in conjunction with other operations from\n"); log("the `abc9' script pass. Only fully-selected modules are supported.\n"); log("\n"); + log(" -check\n"); + log(" check that the design is valid, e.g. (* abc9_box_id *) values are unique,\n"); + log(" (* abc9_carry *) is only given for one input/output port, etc.\n"); + log("\n"); + log(" -prep_delays\n"); + log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n"); + log(" certain delays, e.g. (* abc9_required *) values.\n"); + log("\n"); log(" -mark_scc\n"); log(" for an arbitrarily chosen cell in each unique SCC of each selected module\n"); log(" (tagged with an (* abc9_scc_id = *) attribute), temporarily mark all\n"); @@ -938,6 +946,10 @@ struct Abc9OpsPass : public Pass { log(" compute the clock domain and initial value of each flop in the design.\n"); log(" process the '$holes' module to support clock-enable functionality.\n"); log("\n"); + log(" -write_box (|(null)) \n"); + log(" copy the existing box file from (skip if '(null)') and append any\n"); + log(" new box definitions.\n"); + log("\n"); log(" -reintegrate\n"); log(" for each selected module, re-intergrate the module '$abc9'\n"); log(" by first recovering ABC9 boxes, and then stitching in the remaining primary\n"); @@ -949,7 +961,7 @@ struct Abc9OpsPass : public Pass { log_header(design, "Executing ABC9_OPS pass (helper functions for ABC9).\n"); bool check_mode = false; - bool prep_times_mode = false; + bool prep_delays_mode = false; bool mark_scc_mode = false; bool prep_dff_mode = false; bool prep_xaiger_mode = false; @@ -976,8 +988,8 @@ struct Abc9OpsPass : public Pass { prep_xaiger_mode = true; continue; } - if (arg == "-prep_times") { - prep_times_mode = true; + if (arg == "-prep_delays") { + prep_delays_mode = true; continue; } if (arg == "-write_box" && argidx+2 < args.size()) { @@ -999,16 +1011,16 @@ struct Abc9OpsPass : public Pass { } extra_args(args, argidx, design); - if (!(check_mode || mark_scc_mode || prep_times_mode || prep_xaiger_mode || prep_dff_mode || !write_box_src.empty() || reintegrate_mode)) - log_cmd_error("At least one of -check, -mark_scc, -prep_{times,xaiger,dff}, -write_box, -reintegrate must be specified.\n"); + if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || !write_box_src.empty() || reintegrate_mode)) + log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff}, -write_box, -reintegrate must be specified.\n"); if (dff_mode && !prep_xaiger_mode) log_cmd_error("'-dff' option is only relevant for -prep_xaiger.\n"); if (check_mode) check(design); - if (prep_times_mode) - prep_times(design); + if (prep_delays_mode) + prep_delays(design); for (auto mod : design->selected_modules()) { if (mod->get_bool_attribute("\\abc9_holes")) From b951ca9e1c25b0c9c021419c3e537c743dca6216 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 14:06:02 -0800 Subject: [PATCH 17/25] abc9_ops: fix -reintegrate handling of $__ABC9_DELAY --- passes/techmap/abc9_ops.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index af4073594..816c0276a 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -659,7 +659,7 @@ void reintegrate(RTLIL::Module *module) bit_drivers[i].insert(mapped_cell->name); } } - else if (mapped_cell->type == ID($__ABC9_DELAY)) { + else if (box_lookup.at(mapped_cell->type, IdString()) == ID($__ABC9_DELAY)) { SigBit I = mapped_cell->getPort(ID(i)); SigBit O = mapped_cell->getPort(ID(o)); if (I.wire) @@ -671,7 +671,8 @@ void reintegrate(RTLIL::Module *module) } else { RTLIL::Cell *existing_cell = module->cell(mapped_cell->name); - log_assert(existing_cell); + if (!existing_cell) + log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell)); log_assert(mapped_cell->type.begins_with("$__boxid")); auto type = box_lookup.at(mapped_cell->type, IdString()); From 0e4285ca0d92397490768e649626cfdb5a0c9d95 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 15:05:49 -0800 Subject: [PATCH 18/25] abc9_ops: generate flop box ids, add abc9_required to FD* cells --- backends/aiger/xaiger.cc | 6 +- passes/techmap/abc9_ops.cc | 121 +++++++++++++++++------------------- techlibs/xilinx/cells_sim.v | 57 +++++++++++++---- 3 files changed, 106 insertions(+), 78 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 20f2385f6..268be432a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -596,7 +596,11 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); log_assert(box_module); - auto r = cell_cache.insert(cell->type); + IdString derived_type = box_module->derive(box_module->design, cell->parameters); + box_module = box_module->design->module(derived_type); + log_assert(box_module); + + auto r = cell_cache.insert(derived_type); auto &v = r.first->second; if (r.second) { int box_inputs = 0, box_outputs = 0; diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index a686bbd32..0c95f7ff6 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -23,6 +23,7 @@ #include "kernel/utils.h" #include "kernel/celltypes.h" +#define ABC9_FLOPS_BASE_ID 8000 #define ABC9_DELAY_BASE_ID 9000 USING_YOSYS_NAMESPACE @@ -39,20 +40,20 @@ void check(RTLIL::Design *design) { dict box_lookup; for (auto m : design->modules()) { - auto flop = m->get_bool_attribute(ID(abc9_flop)); - auto it = m->attributes.find(ID(abc9_box_id)); - if (it == m->attributes.end()) { - if (flop) - log_error("Module '%s' contains (* abc9_flop *) but not (* abc9_box_id= *).\n", log_id(m)); - continue; - } if (m->name.begins_with("$paramod")) continue; - auto id = it->second.as_int(); - auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); - if (!r.second) - log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", - log_id(m), id, log_id(r.first->second)); + + auto flop = m->get_bool_attribute(ID(abc9_flop)); + auto it = m->attributes.find(ID(abc9_box_id)); + if (!flop) { + if (it == m->attributes.end()) + continue; + auto id = it->second.as_int(); + auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); + if (!r.second) + log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", + log_id(m), id, log_id(r.first->second)); + } // Make carry in the last PI, and carry out the last PO // since ABC requires it this way @@ -217,13 +218,11 @@ void prep_xaiger(RTLIL::Module *module, bool dff) continue; auto inst_module = module->design->module(cell->type); - bool abc9_box = inst_module && inst_module->attributes.count("\\abc9_box_id"); - bool abc9_flop = false; - if (abc9_box) { - abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); - if (abc9_flop && !dff) - continue; + bool abc9_flop = inst_module && inst_module->get_bool_attribute("\\abc9_flop"); + if (abc9_flop && !dff) + continue; + if ((inst_module && inst_module->attributes.count("\\abc9_box_id")) || abc9_flop) { auto r = box_ports.insert(cell->type); if (r.second) { // Make carry in the last PI, and carry out the last PO @@ -309,17 +308,17 @@ void prep_xaiger(RTLIL::Module *module, bool dff) cell->attributes["\\abc9_box_seq"] = box_count++; - IdString derived_name = box_module->derive(design, cell->parameters); - box_module = design->module(derived_name); + IdString derived_type = box_module->derive(design, cell->parameters); + box_module = design->module(derived_type); - auto r = cell_cache.insert(derived_name); + auto r = cell_cache.insert(derived_type); auto &holes_cell = r.first->second; if (r.second) { if (box_module->has_processes()) Pass::call_on_module(design, box_module, "proc"); if (box_module->get_bool_attribute("\\whitebox")) { - holes_cell = holes_module->addCell(cell->name, derived_name); + holes_cell = holes_module->addCell(cell->name, derived_type); if (box_module->has_processes()) Pass::call_on_module(design, box_module, "proc"); @@ -344,7 +343,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) } } else if (w->port_output) - conn = holes_module->addWire(stringf("%s.%s", derived_name.c_str(), log_id(port_name)), GetSize(w)); + conn = holes_module->addWire(stringf("%s.%s", derived_type.c_str(), log_id(port_name)), GetSize(w)); } // For flops only, create an extra 1-bit input that drives a new wire @@ -387,7 +386,7 @@ void prep_delays(RTLIL::Design *design) { std::set delays; pool flops; - std::vector boxes; + std::vector cells; std::map> requireds; for (auto module : design->selected_modules()) { if (module->processes.size() > 0) { @@ -395,7 +394,7 @@ void prep_delays(RTLIL::Design *design) continue; } - boxes.clear(); + cells.clear(); for (auto cell : module->cells()) { if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_), ID($__ABC9_DELAY))) continue; @@ -406,19 +405,21 @@ void prep_delays(RTLIL::Design *design) if (!inst_module->get_blackbox_attribute()) continue; if (inst_module->get_bool_attribute(ID(abc9_flop))) { + IdString derived_type = inst_module->derive(design, cell->parameters); + inst_module = design->module(derived_type); + log_assert(inst_module); flops.insert(inst_module); - continue; + continue; // because all flop required times + // will be captured in the flop box } - // All remaining boxes are combinatorial and cannot - // contain a required time if (inst_module->attributes.count(ID(abc9_box_id))) continue; - boxes.emplace_back(cell); + cells.emplace_back(cell); } delays.clear(); requireds.clear(); - for (auto cell : boxes) { + for (auto cell : cells) { RTLIL::Module* inst_module = module->design->module(cell->type); log_assert(inst_module); for (auto &conn : cell->connections_) { @@ -475,13 +476,9 @@ void prep_delays(RTLIL::Design *design) module->attributes[ID(abc9_delays)] = ss.str(); } + int flops_id = ABC9_FLOPS_BASE_ID; std::stringstream ss; for (auto flop_module : flops) { - // Skip parameterised flop_modules for now (since we do not - // dynamically generate the abc9_box_id) - if (flop_module->name.begins_with("$paramod")) - continue; - int num_inputs = 0, num_outputs = 0; for (auto port_name : flop_module->ports) { auto wire = flop_module->wire(port_name); @@ -490,7 +487,11 @@ void prep_delays(RTLIL::Design *design) } log_assert(num_outputs == 1); - ss << log_id(flop_module) << " " << flop_module->attributes.at(ID(abc9_box_id)).as_int(); + auto r = flop_module->attributes.insert(ID(abc9_box_id)); + if (r.second) + r.first->second = flops_id++; + + ss << log_id(flop_module) << " " << r.first->second.as_int(); ss << " 1 " << num_inputs+1 << " " << num_outputs << std::endl; bool first = true; for (auto port_name : flop_module->ports) { @@ -550,23 +551,11 @@ void reintegrate(RTLIL::Module *module) for (auto w : mapped_mod->wires()) module->addWire(remap_name(w->name), GetSize(w)); - dict box_lookup; - for (auto m : design->modules()) { - auto it = m->attributes.find(ID(abc9_box_id)); - if (it == m->attributes.end()) - continue; - if (m->name.begins_with("$paramod")) - continue; - auto id = it->second.as_int(); - auto r YS_ATTRIBUTE(unused) = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); - log_assert(r.second); - } - std::vector boxes; for (auto cell : module->cells().to_vector()) { if (cell->has_keep_attr()) continue; - if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_), ID($__ABC9_DELAY))) + if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) module->remove(cell); else if (cell->attributes.erase("\\abc9_box_seq")) boxes.emplace_back(cell); @@ -659,26 +648,29 @@ void reintegrate(RTLIL::Module *module) bit_drivers[i].insert(mapped_cell->name); } } - else if (box_lookup.at(mapped_cell->type, IdString()) == ID($__ABC9_DELAY)) { - SigBit I = mapped_cell->getPort(ID(i)); - SigBit O = mapped_cell->getPort(ID(o)); - if (I.wire) - I.wire = module->wires_.at(remap_name(I.wire->name)); - log_assert(O.wire); - O.wire = module->wires_.at(remap_name(O.wire->name)); - module->connect(O, I); - continue; - } else { RTLIL::Cell *existing_cell = module->cell(mapped_cell->name); if (!existing_cell) log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell)); - log_assert(mapped_cell->type.begins_with("$__boxid")); +#ifndef NDEBUG + RTLIL::Module* box_module = design->module(existing_cell->type); + IdString derived_type = box_module->derive(design, existing_cell->parameters); + RTLIL::Module* derived_module = design->module(derived_type); + log_assert(derived_module); + log_assert(mapped_cell->type == stringf("$__boxid%d", derived_module->attributes.at("\\abc9_box_id").as_int())); +#endif + mapped_cell->type = existing_cell->type; - auto type = box_lookup.at(mapped_cell->type, IdString()); - if (type == IdString()) - log_error("No module with abc9_box_id = %s found.\n", mapped_cell->type.c_str() + strlen("$__boxid")); - mapped_cell->type = type; + if (mapped_cell->type == ID($__ABC9_DELAY)) { + SigBit I = mapped_cell->getPort(ID(i)); + SigBit O = mapped_cell->getPort(ID(o)); + if (I.wire) + I.wire = module->wires_.at(remap_name(I.wire->name)); + log_assert(O.wire); + O.wire = module->wires_.at(remap_name(O.wire->name)); + module->connect(O, I); + continue; + } RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); cell->parameters = existing_cell->parameters; @@ -694,7 +686,6 @@ void reintegrate(RTLIL::Module *module) SigSpec outputs = std::move(it->second); mapped_cell->connections_.erase(it); - RTLIL::Module* box_module = design->module(mapped_cell->type); auto abc9_flop = box_module->attributes.count("\\abc9_flop"); if (!abc9_flop) { for (const auto &i : inputs) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 08380ddca..c8cbf8522 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -325,17 +325,20 @@ endmodule // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L238-L250 -(* abc9_box_id=1100, lib_whitebox, abc9_flop *) +(* abc9_flop, lib_whitebox *) module FDRE ( (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) (* invertible_pin = "IS_C_INVERTED" *) input C, + (* abc9_required=109 *) input CE, (* invertible_pin = "IS_D_INVERTED" *) + //(* abc9_required=-46 *) // Negative required times not currently supported input D, (* invertible_pin = "IS_R_INVERTED" *) + (* abc9_required=404 *) input R ); parameter [0:0] INIT = 1'b0; @@ -349,30 +352,38 @@ module FDRE ( endcase endgenerate endmodule -(* abc9_box_id=1101, lib_whitebox, abc9_flop *) +(* abc9_flop, lib_whitebox *) module FDRE_1 ( (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) input C, - input CE, D, R + (* abc9_required=109 *) + input CE, + //(* abc9_required=-46 *) // Negative required times not currently supported + input D, + (* abc9_required=404 *) + input R ); parameter [0:0] INIT = 1'b0; initial Q <= INIT; always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; endmodule -(* abc9_box_id=1102, lib_whitebox, abc9_flop *) +(* abc9_flop, lib_whitebox *) module FDSE ( (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) (* invertible_pin = "IS_C_INVERTED" *) input C, + (* abc9_required=109 *) input CE, (* invertible_pin = "IS_D_INVERTED" *) + //(* abc9_required=-46 *) // Negative required times not currently supported input D, (* invertible_pin = "IS_S_INVERTED" *) + (* abc9_required=404 *) input S ); parameter [0:0] INIT = 1'b1; @@ -386,13 +397,18 @@ module FDSE ( endcase endgenerate endmodule -(* abc9_box_id=1103, lib_whitebox, abc9_flop *) +(* abc9_flop, lib_whitebox *) module FDSE_1 ( (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) input C, - input CE, D, S + (* abc9_required=109 *) + input CE, + //(* abc9_required=-46 *) // Negative required times not currently supported + input D, + (* abc9_required=404 *) + input S ); parameter [0:0] INIT = 1'b1; initial Q <= INIT; @@ -405,6 +421,7 @@ module FDRSE ( (* invertible_pin = "IS_C_INVERTED" *) input C, (* invertible_pin = "IS_CE_INVERTED" *) + (* abc9_required=109 *) input CE, (* invertible_pin = "IS_D_INVERTED" *) input D, @@ -434,17 +451,20 @@ module FDRSE ( Q <= d; endmodule -(* abc9_box_id=1104, lib_whitebox, abc9_flop *) +(* abc9_flop, lib_whitebox *) module FDCE ( (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) (* invertible_pin = "IS_C_INVERTED" *) input C, + (* abc9_required=109 *) input CE, (* invertible_pin = "IS_CLR_INVERTED" *) + (* abc9_required=764 *) input CLR, (* invertible_pin = "IS_D_INVERTED" *) + //(* abc9_required=-46 *) // Negative required times not currently supported input D ); parameter [0:0] INIT = 1'b0; @@ -460,30 +480,38 @@ module FDCE ( endcase endgenerate endmodule -(* abc9_box_id=1105, lib_whitebox, abc9_flop *) +(* abc9_flop, lib_whitebox *) module FDCE_1 ( (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) input C, - input CE, D, CLR + (* abc9_required=109 *) + input CE, + (* abc9_required=764 *) + input CLR, + //(* abc9_required=-46 *) // Negative required times not currently supported + input D ); parameter [0:0] INIT = 1'b0; initial Q <= INIT; always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; endmodule -(* abc9_box_id=1106, lib_whitebox, abc9_flop *) +(* abc9_flop, lib_whitebox *) module FDPE ( (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) (* invertible_pin = "IS_C_INVERTED" *) input C, + (* abc9_required=109 *) input CE, (* invertible_pin = "IS_D_INVERTED" *) + //(* abc9_required=-46 *) // Negative required times not currently supported input D, (* invertible_pin = "IS_PRE_INVERTED" *) + (* abc9_required=764 *) input PRE ); parameter [0:0] INIT = 1'b1; @@ -499,13 +527,18 @@ module FDPE ( endcase endgenerate endmodule -(* abc9_box_id=1107, lib_whitebox, abc9_flop *) +(* abc9_flop, lib_whitebox *) module FDPE_1 ( (* abc9_arrival=303 *) output reg Q, (* clkbuf_sink *) input C, - input CE, D, PRE + (* abc9_required=109 *) + input CE, + //(* abc9_required=-46 *) // Negative required times not currently supported + input D, + (* abc9_required=764 *) + input PRE ); parameter [0:0] INIT = 1'b1; initial Q <= INIT; From 1c88a6c24084743c95db9fb21c2b429a3736fb77 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 15:20:04 -0800 Subject: [PATCH 19/25] abc9_ops: implement a requireds_cache --- passes/techmap/abc9_ops.cc | 60 +++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 0c95f7ff6..1de95128f 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -387,7 +387,7 @@ void prep_delays(RTLIL::Design *design) std::set delays; pool flops; std::vector cells; - std::map> requireds; + dict>> requireds_cache; for (auto module : design->selected_modules()) { if (module->processes.size() > 0) { log("Skipping module %s as it contains processes.\n", log_id(module)); @@ -418,48 +418,56 @@ void prep_delays(RTLIL::Design *design) } delays.clear(); - requireds.clear(); for (auto cell : cells) { RTLIL::Module* inst_module = module->design->module(cell->type); log_assert(inst_module); + auto &cell_requireds = requireds_cache[cell->type]; for (auto &conn : cell->connections_) { auto port_wire = inst_module->wire(conn.first); if (!port_wire->port_input) continue; - auto it = port_wire->attributes.find("\\abc9_required"); - if (it == port_wire->attributes.end()) - continue; - - int count = 0; - requireds.clear(); - if (it->second.flags == 0) { - count = 1; - requireds[it->second.as_int()].push_back(0); + auto r = cell_requireds.insert(conn.first); + auto &requireds = r.first->second; + if (r.second) { + auto it = port_wire->attributes.find("\\abc9_required"); + if (it == port_wire->attributes.end()) + continue; + if (it->second.flags == 0) { + int delay = it->second.as_int(); + delays.insert(delay); + requireds.emplace_back(delay); + } + else + for (const auto &tok : split_tokens(it->second.decode_string())) { + int delay = atoi(tok.c_str()); + delays.insert(delay); + requireds.push_back(delay); + } } - else - for (const auto &tok : split_tokens(it->second.decode_string())) - requireds[atoi(tok.c_str())].push_back(count++); - if (count > 1 && count != GetSize(port_wire)) + + if (requireds.empty()) + continue; + if (GetSize(requireds) > 1 && GetSize(requireds) != GetSize(port_wire)) log_error("%s.%s is %d bits wide but abc9_required = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first), - GetSize(port_wire), log_signal(it->second), count); + GetSize(port_wire), log_signal(port_wire->attributes.at("\\abc9_required")), GetSize(requireds)); SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); - for (const auto &i : requireds) { + auto it = requireds.begin(); + for (int i = 0; i < GetSize(conn.second); ++i) { #ifndef NDEBUG if (ys_debug(1)) { static std::set> seen; - if (seen.emplace(cell->type, conn.first).second) log("%s.%s abc9_required = %d\n", log_id(cell->type), log_id(conn.first), i.first); + if (seen.emplace(cell->type, conn.first).second) log("%s.%s abc9_required = %d\n", log_id(cell->type), log_id(conn.first), requireds[i]); } #endif - delays.insert(i.first); - for (auto offset : i.second) { - auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); - box->setPort(ID(I), conn.second[offset]); - box->setPort(ID(O), O[offset]); - box->setParam(ID(DELAY), i.first); - conn.second[offset] = O[offset]; - } + auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); + box->setPort(ID(I), conn.second[i]); + box->setPort(ID(O), O[i]); + box->setParam(ID(DELAY), *it); + if (requireds.size() > 1) + it++; + conn.second[i] = O[i]; } } } From f60e071e1c3ab64d1a45c4aea3580027b4242908 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 15:24:44 -0800 Subject: [PATCH 20/25] abc9_ops: -check to check abc9_{arrival,required} --- passes/techmap/abc9_ops.cc | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 1de95128f..4d05b5afb 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -73,6 +73,36 @@ void check(RTLIL::Design *design) carry_out = port_name; } } + + auto it = w->attributes.find("\\abc9_arrival"); + if (it != w->attributes.end()) { + int count = 0; + if (it->second.flags == 0) + count++; + else + for (const auto &tok : split_tokens(it->second.decode_string())) { + (void) tok; + count++; + } + if (count > 1 && count != GetSize(w)) + log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(m), log_id(port_name), + GetSize(w), log_signal(it->second), count); + } + + it = w->attributes.find("\\abc9_required"); + if (it != w->attributes.end()) { + int count = 0; + if (it->second.flags == 0) + count++; + else + for (const auto &tok : split_tokens(it->second.decode_string())) { + (void) tok; + count++; + } + if (count > 1 && count != GetSize(w)) + log_error("%s.%s is %d bits wide but abc9_required = %s has %d value(s)!\n", log_id(m), log_id(port_name), + GetSize(w), log_signal(it->second), count); + } } if (carry_in != IdString() && carry_out == IdString()) @@ -448,9 +478,6 @@ void prep_delays(RTLIL::Design *design) if (requireds.empty()) continue; - if (GetSize(requireds) > 1 && GetSize(requireds) != GetSize(port_wire)) - log_error("%s.%s is %d bits wide but abc9_required = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first), - GetSize(port_wire), log_signal(port_wire->attributes.at("\\abc9_required")), GetSize(requireds)); SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); auto it = requireds.begin(); From 485e08e4363f2aa93204f8bcc6c1ff5243936ea6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Jan 2020 16:33:41 -0800 Subject: [PATCH 21/25] abc9_ops: cope with (* abc9_flop *) in place of (* abc9_box_id *) --- backends/aiger/xaiger.cc | 2 +- passes/techmap/abc9_ops.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c2d076c86..66ddbde33 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -318,7 +318,7 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); log_assert(box_module); - log_assert(box_module->attributes.count("\\abc9_box_id")); + log_assert(box_module->attributes.count("\\abc9_box_id") || box_module->get_bool_attribute("\\abc9_flop")); auto r = box_ports.insert(cell->type); if (r.second) { diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 4d05b5afb..fd2759ae5 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -117,7 +117,7 @@ void check(RTLIL::Design *design) if (wire->port_output) num_outputs++; } if (num_outputs != 1) - log_error("Module '%s' with (* abc_flop *) has %d outputs (expect 1).\n", log_id(m), num_outputs); + log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", log_id(m), num_outputs); } } } @@ -333,7 +333,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) log_assert(cell); RTLIL::Module* box_module = design->module(cell->type); - if (!box_module || !box_module->attributes.count("\\abc9_box_id")) + if (!box_module || (!box_module->attributes.count("\\abc9_box_id") && !box_module->get_bool_attribute("\\abc9_flop"))) continue; cell->attributes["\\abc9_box_seq"] = box_count++; From 5a63c197477d59567424faab3b56329c426394b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 15 Jan 2020 13:14:48 -0800 Subject: [PATCH 22/25] abc9_ops: -write_box is empty, output a dummy box to prevent ABC error --- passes/techmap/abc9_exe.cc | 3 +-- passes/techmap/abc9_ops.cc | 3 +++ techlibs/common/Makefile.inc | 1 - techlibs/common/dummy.box | 1 - 4 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 techlibs/common/dummy.box diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index a2acfac91..484964ddf 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -510,9 +510,8 @@ struct Abc9ExePass : public Pass { } } - // ABC expects a box file for XAIG if (box_file.empty()) - box_file = "+/dummy.box"; + log_cmd_error("abc9_exe '-box' option is mandatory.\n"); rewrite_filename(box_file); if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index fd2759ae5..13340f311 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -569,6 +569,9 @@ void write_box(RTLIL::Module *module, const std::string &src, const std::string module->attributes.erase(it); } + if (ofs.tellp() == 0) + ofs << "(dummy) 1 0 0 0"; + ofs.close(); } diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index a42f63128..42f1068ad 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -29,4 +29,3 @@ $(eval $(call add_share_file,share,techlibs/common/gate2lut.v)) $(eval $(call add_share_file,share,techlibs/common/cmp2lut.v)) $(eval $(call add_share_file,share,techlibs/common/cells.lib)) $(eval $(call add_share_file,share,techlibs/common/mul2dsp.v)) -$(eval $(call add_share_file,share,techlibs/common/dummy.box)) diff --git a/techlibs/common/dummy.box b/techlibs/common/dummy.box deleted file mode 100644 index 0c18070a0..000000000 --- a/techlibs/common/dummy.box +++ /dev/null @@ -1 +0,0 @@ -(dummy) 1 0 0 0 From 168c9d5871e331341058b026cf9b4f6a99a0f759 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 15 Jan 2020 14:42:00 -0800 Subject: [PATCH 23/25] Update README.md for (* abc9_required *) --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 77e9410da..043e772ba 100644 --- a/README.md +++ b/README.md @@ -373,10 +373,15 @@ Verilog Attributes and non-standard features `abc9` to preserve the integrity of carry-chains. Specifying this attribute onto a bus port will affect only its most significant bit. -- The port attribute ``abc9_arrival`` specifies an integer (for output ports - only) to be used as the arrival time of this sequential port. It can be used, - for example, to specify the clk-to-Q delay of a flip-flop for consideration - during `abc9` techmapping. +- The output port attribute ``abc9_arrival`` specifies an integer, or a string + of space-separated integers to be used as the arrival time of this blackbox + port. It can be used, for example, to specify the clk-to-Q delay of a flip- + flop output for consideration during `abc9` techmapping. + +- The input port attribute ``abc9_requiredl`` specifies an integer, or a string + of space-separated integers to be used as the required time of this blackbox + port. It can be used, for example, to specify the setup-time of a flip-flop + input for consideration during `abc9` techmapping. - The module attribute ``abc9_flop`` is a boolean marking the module as a flip-flop. This allows `abc9` to analyse its contents in order to perform From e0bdf5d7a9280c9f975a34fc265793de86fd9bec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 Jan 2020 12:30:39 -0800 Subject: [PATCH 24/25] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 043e772ba..09429cbe0 100644 --- a/README.md +++ b/README.md @@ -378,7 +378,7 @@ Verilog Attributes and non-standard features port. It can be used, for example, to specify the clk-to-Q delay of a flip- flop output for consideration during `abc9` techmapping. -- The input port attribute ``abc9_requiredl`` specifies an integer, or a string +- The input port attribute ``abc9_required`` specifies an integer, or a string of space-separated integers to be used as the required time of this blackbox port. It can be used, for example, to specify the setup-time of a flip-flop input for consideration during `abc9` techmapping. From 21ce1b37fbc93562942c10f631c7f415f8fdba2e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 Jan 2020 14:22:46 -0800 Subject: [PATCH 25/25] abc9_ops: -check for negative arrival/required times --- passes/techmap/abc9_ops.cc | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 0fc4de3bb..2b4a5c802 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -77,11 +77,20 @@ void check(RTLIL::Design *design) auto it = w->attributes.find("\\abc9_arrival"); if (it != w->attributes.end()) { int count = 0; - if (it->second.flags == 0) + if (it->second.flags == 0) { + if (it->second.as_int() < 0) + log_error("%s.%s has negative arrival value %d!\n", log_id(m), log_id(port_name), + it->second.as_int()); count++; + } else for (const auto &tok : split_tokens(it->second.decode_string())) { - (void) tok; + if (tok.find_first_not_of("0123456789") != std::string::npos) + log_error("%s.%s has non-integer arrival value '%s'!\n", log_id(m), log_id(port_name), + tok.c_str()); + if (atoi(tok.c_str()) < 0) + log_error("%s.%s has negative arrival value %s!\n", log_id(m), log_id(port_name), + tok.c_str()); count++; } if (count > 1 && count != GetSize(w)) @@ -92,11 +101,20 @@ void check(RTLIL::Design *design) it = w->attributes.find("\\abc9_required"); if (it != w->attributes.end()) { int count = 0; - if (it->second.flags == 0) + if (it->second.flags == 0) { + if (it->second.as_int() < 0) + log_error("%s.%s has negative required value %d!\n", log_id(m), log_id(port_name), + it->second.as_int()); count++; + } else for (const auto &tok : split_tokens(it->second.decode_string())) { - (void) tok; + if (tok.find_first_not_of("0123456789") != std::string::npos) + log_error("%s.%s has non-integer required value '%s'!\n", log_id(m), log_id(port_name), + tok.c_str()); + if (atoi(tok.c_str()) < 0) + log_error("%s.%s has negative required value %s!\n", log_id(m), log_id(port_name), + tok.c_str()); count++; } if (count > 1 && count != GetSize(w))