openlane2
openlane2 copied to clipboard
Time borrowing causes flow to fail
Description
Feeding the data input of a positive level triggered latch with the data output of a positive edge triggered flip-flop causese OpenSTA to invoke time borrowing. The setup path is listed as 0.000000 slack (MET), borrowing only enough time from data output of the latch to achieve a setup slack of zero for the input path. Later in the flow the zero setup slack in all corners uncluding the TT corners causes the flow to fail, claiming setup violations.
Expected Behavior
I would expect the flow not to fail, since OpenSTA used the zero setup slack to communicate a met setup condition.
Environment report
kernel: Linux
kernel_version: 5.15.153.1-microsoft-standard-WSL2
supported: True
distro: ubuntu
distro_version: 22.04
python_version: 3.10.12
python_path:
- /home/toivo/.local/bin
- /usr/lib/python310.zip
- /usr/lib/python3.10
- /usr/lib/python3.10/lib-dynload
- /home/toivo/.local/lib/python3.10/site-packages
- /usr/local/lib/python3.10/dist-packages
- /usr/lib/python3/dist-packages
tkinter: True
container_info:
engine: docker
version: 26.1.2
conmon: False
rootless: False
nix_info:
version_string: nix (Nix) 2.23.1
channels:
nix_command: True
flakes: True
Reproduction material
The error was produced using the Tiny Tapeout 8 local hardening setup, which uses OpenLane 2. The source file contents were
module top (
input wire [7:0] ui_in, // Dedicated inputs
output wire [7:0] uo_out, // Dedicated outputs
input wire [7:0] uio_in, // IOs: Input path
output wire [7:0] uio_out, // IOs: Output path
output wire [7:0] uio_oe, // IOs: Enable path (active high: 0=input, 1=output)
input wire ena, // always 1 when the design is powered, so you can ignore it
input wire clk, // clock
input wire rst_n // reset_n - low to reset
);
reg r_in, r_out;
wire q;
sky130_fd_sc_hd__dlxtp_1 latch( .GATE(clk), .D(r_in), .Q(q));
always @(posedge clk) begin
r_out <= q;
r_in <= ui_in[0];
end
assign uo_out = {7'd0, r_out};
assign uio_out = 0;
assign uio_oe = 0;
endmodule
The above code follows the Tiny Tapeout 8 top module template. If you don't have to do that, it should be enough with
module top (
input wire clk,
input wire d_in,
output wire d_out
);
reg r_in, r_out;
wire q;
sky130_fd_sc_hd__dlxtp_1 latch( .GATE(clk), .D(r_in), .Q(q));
always @(posedge clk) begin
r_out <= q;
r_in <= d_in;
end
assign d_out = r_out;
endmodule
Relevant log output
Excerpt from 51-openroad-stapostpnr/max_tt_025C_1v80/sta.log:
======================= max_tt_025C_1v80 Corner ===================================
Startpoint: _01_ (rising edge-triggered flip-flop clocked by clk)
Endpoint: latch (positive level-sensitive latch clocked by clk)
Path Group: clk
Path Type: max
Fanout Cap Slew Delay Time Description
---------------------------------------------------------------------------------------------
0.000000 0.000000 clock clk (rise edge)
0.000000 0.000000 clock source latency
1 0.009281 0.048256 0.031850 0.031850 ^ clk (in)
clk (net)
0.048263 0.000000 0.031850 ^ clkbuf_0_clk/A (sky130_fd_sc_hd__clkbuf_16)
2 0.018642 0.040678 0.125026 0.156876 ^ clkbuf_0_clk/X (sky130_fd_sc_hd__clkbuf_16)
clknet_0_clk (net)
0.040693 0.000967 0.157843 ^ clkbuf_1_0__f_clk/A (sky130_fd_sc_hd__clkbuf_16)
2 0.006818 0.030498 0.111099 0.268942 ^ clkbuf_1_0__f_clk/X (sky130_fd_sc_hd__clkbuf_16)
clknet_1_0__leaf_clk (net)
0.030499 0.000250 0.269193 ^ _01_/CLK (sky130_fd_sc_hd__dfxtp_1)
1 0.003762 0.048524 0.300794 0.569987 ^ _01_/Q (sky130_fd_sc_hd__dfxtp_1)
r_in (net)
0.048524 0.000218 0.570205 ^ latch/D (sky130_fd_sc_hd__dlxtp_1)
0.570205 data arrival time
0.000000 0.000000 clock clk (rise edge)
0.000000 0.000000 clock source latency
1 0.009281 0.048256 0.031850 0.031850 ^ clk (in)
clk (net)
0.048263 0.000000 0.031850 ^ clkbuf_0_clk/A (sky130_fd_sc_hd__clkbuf_16)
2 0.018642 0.040678 0.125026 0.156876 ^ clkbuf_0_clk/X (sky130_fd_sc_hd__clkbuf_16)
clknet_0_clk (net)
0.040693 0.000960 0.157836 ^ clkbuf_1_1__f_clk/A (sky130_fd_sc_hd__clkbuf_16)
1 0.002152 0.026067 0.105543 0.263380 ^ clkbuf_1_1__f_clk/X (sky130_fd_sc_hd__clkbuf_16)
clknet_1_1__leaf_clk (net)
0.026067 0.000151 0.263530 ^ latch/GATE (sky130_fd_sc_hd__dlxtp_1)
-0.250000 0.013530 clock uncertainty
0.000000 0.013530 clock reconvergence pessimism
0.556674 0.570205 time borrowed from endpoint
0.570205 data required time
---------------------------------------------------------------------------------------------
0.570205 data required time
-0.570205 data arrival time
---------------------------------------------------------------------------------------------
0.000000 slack (MET)
Time Borrowing Information
------------------------------------------------
clk nominal pulse width 10.000000
clock latency difference 0.009987
library setup time -0.198930
------------------------------------------------
max time borrow 9.811056
------------------------------------------------
actual time borrow 0.556674
open edge uncertainty -0.250000
------------------------------------------------
time given to startpoint 0.306674
------------------------------------------------
From end of OpenLane2 console output:
[04:51:50] WARNING [Checker.SetupViolations] Setup violations found in the following corners: flow.py:673
* max_ff_n40C_1v95
* max_ss_100C_1v60
* min_ff_n40C_1v95
* min_ss_100C_1v60
* nom_ff_n40C_1v95
* nom_ss_100C_1v60
[04:51:50] WARNING [Misc.ReportManufacturability] klayout__drc_error__count not reported. KLayout.DRC may flow.py:673
have been skipped.
[04:51:50] ERROR The following error was encountered while running the flow: __main__.py:152
One or more deferred errors were encountered:
Setup violations found in the following corners:
* max_tt_025C_1v80
* min_tt_025C_1v80
* nom_tt_025C_1v80
[04:51:50] ERROR OpenLane will now quit. __main__.py:153
Classic - Stage 68 - Netgen LVS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸━━━━ 67/75 0:00:312024-07-04 06:51:50,311 - project - ERROR - harden failed
Could you upload the entire raw log file please?
Of course. Which one, sta.log or something else?
sta.log
My workaround for this was:
diff --git a/openlane/scripts/openroad/sta/corner.tcl b/openlane/scripts/openroad/sta/corner.tcl
index ce3f452..b15b6d0 100644
--- a/openlane/scripts/openroad/sta/corner.tcl
+++ b/openlane/scripts/openroad/sta/corner.tcl
@@ -292,7 +292,7 @@ foreach path $hold_paths {
}
}
-set setup_violating_paths [find_timing_paths -unique_paths_to_endpoint -path_delay max -sort_by_slack -group_count $max_violator_count -slack_max 0]
+set setup_violating_paths [find_timing_paths -unique_paths_to_endpoint -path_delay max -sort_by_slack -group_count $max_violator_count -slack_max -0.000001]
foreach path $setup_violating_paths {
set start_pin [get_property $path startpoint]
set end_pin [get_property $path endpoint]
I'm not sure if that's good enough to take as a fix!