Skip to content

Commit ff971d4

Browse files
committed
openroad: improve timing constraints
1 parent e1d257d commit ff971d4

File tree

3 files changed

+71
-22
lines changed

3 files changed

+71
-22
lines changed

openroad/src/constraints.sdc

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ set_driving_cell [all_inputs] -lib_cell sg13g2_IOPadOut16mA -pin pad
2929
##################
3030
puts "Clocks..."
3131

32-
# We target 80 MHz
33-
set TCK_SYS 12.5
32+
# We target 100 MHz
33+
set TCK_SYS 10.0
3434
create_clock -name clk_sys -period $TCK_SYS [get_ports clk_i]
3535

36-
set TCK_JTG 20.0
36+
set TCK_JTG 25.0
3737
create_clock -name clk_jtg -period $TCK_JTG [get_ports jtag_tck_i]
3838

3939
set TCK_RTC 50.0
@@ -45,7 +45,9 @@ create_clock -name clk_rtc -period $TCK_RTC [get_ports ref_clk_i]
4545
##################################
4646

4747
# Define which clocks are asynchronous to each other
48-
# -allow_paths re-activates timing checks between asyncs -> we must constrain CDCs!
48+
# If you have added a clock it is a good idea to temporarily add -allow_paths.
49+
# This means the paths between clocks (CDC) are timed and will show up as violations,
50+
# making them very easy to find and write constraints for.
4951
set_clock_groups -asynchronous -name clk_groups_async \
5052
-group {clk_rtc} \
5153
-group {clk_jtg} \
@@ -62,17 +64,17 @@ set_clock_transition 0.2 [all_clocks]
6264
####################
6365
puts "CDC/Sync..."
6466

65-
# Clock Domain Crossings: paths going from a FF with one clock to an FF with another another)
66-
# to increase the metastability-recovery window we do not wants any additional delays in these paths
67-
# so we deactivate the hold checking (as it may add buffers)
67+
# Clock Domain Crossings: paths going from an FF with one clock to an FF with another.
68+
# The setup/hold checks on these paths are deactivated by set_clock_groups -asynchronous.
69+
# An additional requirement is that the max delay is below min($TCK_SYS, $TCK_JTG)
70+
# to make sure any change propages within one cycle of either clock.
71+
# An (optional) lower delay is better for metastability recovery -> 3ns as a reasonable goal
6872

69-
# Constrain `cdc_2phase` for DMI request
70-
set_false_path -hold -through $JTAG_ASYNC_REQ
71-
set_max_delay [expr $TCK_SYS * 0.35] -through $JTAG_ASYNC_REQ -ignore_clock_latency
73+
## Constrain `cdc_2phase` for DMI request
74+
set_max_delay 3.0 -from $JTAG_ASYNC_REQ_START -to $JTAG_ASYNC_REQ_END -ignore_clock_latency
7275

7376
# Constrain `cdc_2phase` for DMI response
74-
set_false_path -hold -through $JTAG_ASYNC_RSP
75-
set_max_delay [expr $TCK_SYS * 0.35] -through $JTAG_ASYNC_RSP -ignore_clock_latency
77+
set_max_delay 3.0 -from $JTAG_ASYNC_RSP_START -to $JTAG_ASYNC_RSP_END -ignore_clock_latency
7678

7779

7880
#############
@@ -91,10 +93,10 @@ set_max_delay $TCK_SYS -from [get_ports rst_ni]
9193
##########
9294
puts "JTAG..."
9395

94-
set_input_delay -min -add_delay -clock clk_jtg [ expr $TCK_JTG * 0.10 ] [get_ports {jtag_tdi_i jtag_tms_i}]
95-
set_input_delay -max -add_delay -clock clk_jtg [ expr $TCK_JTG * 0.50 ] [get_ports {jtag_tdi_i jtag_tms_i}]
96-
set_output_delay -min -add_delay -clock clk_jtg [ expr $TCK_JTG * 0.10 / 2 ] [get_ports jtag_tdo_o]
97-
set_output_delay -max -add_delay -clock clk_jtg [ expr $TCK_JTG * 0.50 / 2 ] [get_ports jtag_tdo_o]
96+
set_input_delay -min -add_delay -clock clk_jtg [ expr $TCK_JTG * 0.10 ] [get_ports {jtag_tdi_i jtag_tms_i}]
97+
set_input_delay -max -add_delay -clock clk_jtg [ expr $TCK_JTG * 0.30 ] [get_ports {jtag_tdi_i jtag_tms_i}]
98+
set_output_delay -min -add_delay -clock clk_jtg [ expr $TCK_JTG * 0.10 ] [get_ports jtag_tdo_o]
99+
set_output_delay -max -add_delay -clock clk_jtg [ expr $TCK_JTG * 0.30 ] [get_ports jtag_tdo_o]
98100

99101
# Reset should propagate to system domain within a clock cycle.
100102
set_input_delay -max [ expr $TCK_JTG * 0.10 ] [get_ports jtag_trst_ni]
@@ -110,8 +112,12 @@ puts "GPIO..."
110112
set_input_delay -min -add_delay -clock clk_sys [ expr $TCK_SYS * 0.10 ] [get_ports {gpio* fetch_en_i}]
111113
set_input_delay -max -add_delay -clock clk_sys [ expr $TCK_SYS * 0.30 ] [get_ports {gpio* fetch_en_i}]
112114

113-
set_output_delay -min -add_delay -clock clk_sys [ expr $TCK_SYS * 0.10 ] [get_ports {status_o gpio*}]
114-
set_output_delay -max -add_delay -clock clk_sys [ expr $TCK_SYS * 0.30 ] [get_ports {status_o gpio*}]
115+
set_output_delay -min -add_delay -clock clk_sys [ expr $TCK_SYS * 0.10 ] [get_ports {gpio*}]
116+
set_output_delay -max -add_delay -clock clk_sys [ expr $TCK_SYS * 0.30 ] [get_ports {gpio*}]
117+
118+
# The timing of these signals are not important but we want to keep them in-cycle
119+
set_output_delay -min -add_delay -clock clk_sys [ expr $TCK_SYS * 0.10 ] [get_ports {status_o unused*}]
120+
set_output_delay -max -add_delay -clock clk_sys [ expr $TCK_SYS * 0.10 ] [get_ports {status_o unused*}]
115121

116122

117123
##########

openroad/src/instances.tcl

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,36 @@ set bank0_sram0 $SRAM$sram$SRAM_512x32
3131
set sram {\[1\].i_sram/}
3232
set bank1_sram0 $SRAM$sram$SRAM_512x32
3333

34-
set JTAG_ASYNC_REQ [get_nets $JTAG/i_dmi_cdc.i_cdc_req/*async_*]
35-
set JTAG_ASYNC_RSP [get_nets $JTAG/i_dmi_cdc.i_cdc_resp/*async_*]
34+
# JTAG request and response CDCs
35+
# Goal: Find the async nets and their source and destination cells
36+
# We only want to constrain paths internal to the CDC and going through the async nets.
37+
# It is more complex than usual due to how OpenROAD currently dissolves hierarchy when reading in designs.
38+
set JTAG_CDC_REQ $JTAG/i_dmi_cdc.i_cdc_req
39+
# find all startpoints (flops) that drive through async_data nets and flops that directly drive async nets
40+
set JTAG_ASYNC_REQ_START [get_fanin -to [get_nets $JTAG_CDC_REQ/*async_data*] -flat -startpoints_only -only_cells]
41+
set JTAG_ASYNC_REQ_START [concat $JTAG_ASYNC_REQ_START [get_cells $JTAG_CDC_REQ/*async*_o*_reg]]
42+
# find all endpoints (flops) that are driven through async nets and are in the CDC
43+
set JTAG_ASYNC_REQ_END [list]
44+
set JTAG_ASYNC_REQ_CANDIDATES [get_fanout -from [get_nets $JTAG_CDC_REQ/*async*_data*] -flat -endpoints_only -only_cells]
45+
foreach cell $JTAG_ASYNC_REQ_CANDIDATES {
46+
if {[string match "${JTAG_CDC_REQ}/*" [get_name $cell]]} {
47+
lappend JTAG_ASYNC_REQ_END $cell
48+
}
49+
}
50+
# These paths (clear and isolate) go out of the CDC but we know they cannot cause timing violations
51+
# because they have a seperate 4-phase handshake making sure they stay stable for multiple cycles in each clock domain.
52+
lappend JTAG_ASYNC_REQ_END {*}[get_fanout -from [get_pins $JTAG_CDC_REQ/*i_cdc_reset_ctrlr_half_a*async_data*_reg/Q] -flat -endpoints_only -only_cells]
53+
54+
# The same for the response CDC
55+
set JTAG_CDC_RSP $JTAG/i_dmi_cdc.i_cdc_resp
56+
set JTAG_ASYNC_RSP_START [get_fanin -to [get_nets $JTAG_CDC_RSP/*async_data*] -flat -startpoints_only -only_cells]
57+
set JTAG_ASYNC_RSP_START [concat $JTAG_ASYNC_RSP_START [get_cells $JTAG_CDC_RSP/*async*_o*_reg]]
58+
set JTAG_ASYNC_RSP_END [list]
59+
set JTAG_ASYNC_RSP_CANDIDATES [get_fanout -from [get_nets $JTAG_CDC_RSP/*async*_data*] -flat -endpoints_only -only_cells]
60+
foreach cell $JTAG_ASYNC_RSP_CANDIDATES {
61+
if {[string match "${JTAG_CDC_RSP}/*" [get_name $cell]]} {
62+
lappend JTAG_ASYNC_RSP_END $cell
63+
}
64+
}
65+
lappend JTAG_ASYNC_RSP_END {*}[get_fanout -from [get_pins $JTAG_CDC_RSP/*i_cdc_reset_ctrlr_half_a*async_data*_reg/Q] -flat -endpoints_only -only_cells]
66+

yosys/scripts/yosys_synthesis.tcl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ yosys setattr -set keep_hierarchy 1 "t:reg_uart_wrap$*"
4646
yosys setattr -set keep_hierarchy 1 "t:soc_ctrl_regs$*"
4747
yosys setattr -set keep_hierarchy 1 "t:tc_clk*$*"
4848
yosys setattr -set keep_hierarchy 1 "t:tc_sram_impl$*"
49-
yosys setattr -set keep_hierarchy 1 "t:cdc_*$*"
49+
yosys setattr -set keep_hierarchy 1 "t:cdc_reset*$*"
50+
yosys setattr -set keep_hierarchy 1 "t:cdc*phase_*$*"
51+
yosys setattr -set keep_hierarchy 1 "t:cdc*_src*$*"
52+
yosys setattr -set keep_hierarchy 1 "t:cdc*_dst*$*"
5053
yosys setattr -set keep_hierarchy 1 "t:sync$*"
5154

5255

@@ -55,6 +58,7 @@ yosys blackbox "t:tc_sram_blackbox$*"
5558

5659
# map dont_touch attribute commonly applied to output-nets of async regs to keep
5760
yosys attrmap -rename dont_touch keep
61+
yosys attrmap -tocase keep -imap keep="true" keep=1
5862
# copy the keep attribute to their driving cells (retain on net for debugging)
5963
yosys attrmvcp -copy -attr keep
6064

@@ -77,7 +81,9 @@ yosys tee -q -o "${rep_dir}/${top_design}_initial_opt.rpt" stat
7781
yosys wreduce
7882
yosys peepopt
7983
yosys opt_clean
84+
yosys write_verilog -norename -noexpr ${tmp_dir}/${top_design}_yosys_abstract4.v
8085
yosys opt -full
86+
yosys write_verilog -norename -noexpr ${tmp_dir}/${top_design}_yosys_abstract5.v
8187
yosys booth
8288
yosys share
8389
yosys opt
@@ -92,10 +98,12 @@ yosys share
9298
yosys opt -full
9399
yosys clean -purge
94100

95-
yosys write_verilog -norename ${tmp_dir}/${top_design}_yosys_abstract.v
101+
yosys clean -purge
102+
yosys write_verilog -norename -noexpr ${tmp_dir}/${top_design}_yosys_abstract.v
96103
yosys tee -q -o "${rep_dir}/${top_design}_abstract.rpt" stat -tech cmos
97104

98105
yosys techmap
106+
yosys write_verilog -norename -noexpr ${tmp_dir}/${top_design}_yosys_abstract3.v
99107
yosys opt -fast
100108
yosys clean -purge
101109

@@ -105,7 +113,10 @@ yosys tee -q -o "${rep_dir}/${top_design}_generic.rpt" stat -tech cmos
105113
yosys tee -q -o "${rep_dir}/${top_design}_generic.json" stat -json -tech cmos
106114

107115
# flatten all hierarchy except marked modules
116+
yosys write_verilog -norename ${tmp_dir}/${top_design}_yosys_abstract2.v
108117
yosys flatten
118+
yosys write_verilog -norename ${tmp_dir}/${top_design}_flatten.v
119+
# yosys opt_hier
109120

110121
yosys clean -purge
111122

@@ -116,6 +127,7 @@ yosys clean -purge
116127
yosys splitnets -format __v
117128
# rename DFFs from the driven signal
118129
yosys rename -wire -suffix _reg t:*DFF*
130+
yosys write_verilog -norename ${tmp_dir}/${top_design}_yosys_rename.v
119131
yosys select -write ${rep_dir}/${top_design}_registers.rpt t:*DFF*
120132
# rename all other cells
121133
yosys autoname t:*DFF* %n

0 commit comments

Comments
 (0)