Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Adding genus constraints #726

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions v/chip/tcl/bsg_async.constraints.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
puts "BSG-info: Running script [info script]\n"

proc bsg_async_icl {clocks} {

foreach_in_collection launch_clk $clocks {
if { [get_db $launch_clk .is_generated] } {
set launch_group [get_generated_clocks -quiet -filter "master_clock==[get_db $launch_clk .master_clock]"]
append_to_collection launch_group [get_db $launch_clk .master_clock]
} else {
set launch_group [get_generated_clocks -quiet -filter "master_clock==[get_db $launch_clk .name]"]
append_to_collection launch_group $launch_clk
}

foreach_in_collection latch_clk [remove_from_collection $clocks $launch_group] {
set launch_period [expr [get_db $launch_clk .period] / 1000.0]
set latch_period [expr [get_db $latch_clk .period] / 1000.0]
set max_delay_ns [expr min($launch_period,$latch_period)/2]
set_max_delay $max_delay_ns -from $launch_clk -to $latch_clk -ignore_clock_latency
set_min_delay 0 -from $launch_clk -to $latch_clk -ignore_clock_latency
}
}
}

proc bsg_sync_constraints {} {
foreach_in_collection s1 [get_pins -quiet -of_objects [get_cells -quiet -hier *hard_sync_int1_BSG_SYNC*] -filter "name=~D"] {
set_false_path -to $s1 -setup
set_false_path -to $s1 -hold
}
}

puts "BSG-info: Completed script [info script]\n"
47 changes: 47 additions & 0 deletions v/chip/tcl/bsg_cdc.constraints.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
puts "Info: Start script [info script]\n"

proc bsg_chip_async_constraints {} {
set generated_clocks [get_generated_clocks]
foreach_in_collection clk [get_clocks -filter "!is_generated"] {
set clk_grp $clk
set clk_name [get_db [get_clocks $clk] .name]
append_to_collection clk_grp [get_generated_clocks -filter "master_clock==$clk_name"]
set_clock_groups -asynchronous -group $clk_grp
}
}

proc bsg_chip_cdc_constraints { clks } {
foreach_in_collection clk $clks {
set clk_name [get_db [get_clocks $clk] .name]
set cdc_clk_name ${clk_name}_cdc
set cdc_clk_period [expr [get_db [get_clocks $clk] .period] / 1000.0]
set cdc_clk_source [get_db [get_clocks $clk] .sources]
create_clock -name $cdc_clk_name -period $cdc_clk_period -add $cdc_clk_source
}

foreach_in_collection cdc_clk [get_clocks *_cdc] {
set_false_path -from $cdc_clk -to $cdc_clk
}

set_clock_groups -physically_exclusive \
-group $clks \
-group [get_clocks *_cdc]

foreach_in_collection cdc_clk0 [get_clocks *_cdc] {
foreach_in_collection cdc_clk1 [remove_from_collection [get_clocks *_cdc] $cdc_clk0] {
set cdc_delay [lindex [lsort -real [expr [get_db [get_clocks "$cdc_clk0 $cdc_clk1"] .period] / 1000.0] 0]
set_max_delay $cdc_delay -from $cdc_clk0 -to $cdc_clk1
set_min_delay 0.0 -from $cdc_clk0 -to $cdc_clk1
}
}
}

proc bsg_async_two_clocks {period clk0 clk1} {
set max_delay_ns [expr $period/2]
set_max_delay $max_delay_ns -from $clk0 -to $clk1 -ignore_clock_latency
set_min_delay 0 -from $clk0 -to $clk1 -ignore_clock_latency
set_max_delay $max_delay_ns -from $clk1 -to $clk0 -ignore_clock_latency
set_min_delay 0 -from $clk1 -to $clk0 -ignore_clock_latency
}

puts "Info: Completed script [info script]\n"
36 changes: 36 additions & 0 deletions v/chip/tcl/bsg_clk_gen.constraints.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
puts "Info: Start script [info script]\n"

proc bsg_clk_gen_clock_create { osc_path clk_name clk_gen_period_int clk_gen_period_ext osc_uncertainty ds_uncertainty clk_uncertainty} {
# very little is actually timed with this domain; just the receive
# side of the bsg_tag_client and the downsampler.
#
# Although the fastest target period of the oscillator itself is below
# this, we don't want this support logic to not be able to keep up
# in the event that oscillator runs faster than the tools say
#

# this is for the output of the downsampler, goes to the clock selection mux
set clk_gen_period_ds [expr $clk_gen_period_int * 2.0]

# this is for the output of the oscillator, which goes to the downsampler
create_clock -period $clk_gen_period_int -name ${clk_name}_osc [get_pins -of_objects [get_db hinsts ${osc_path}clk_gen_osc_inst] -filter "pin_direction==out"]
set_clock_uncertainty $osc_uncertainty [get_clocks ${clk_name}_osc]

# Used for internal register clocks not detected by genus
#create_clock -period $clk_gen_period_ds -name ${clk_name}_adt_int [get_pins -of_objects [get_cells ${osc_path}clk_gen_osc_inst/adt_BSG_DONT_TOUCH/M1] -filter "pin_direction==out"]
#create_clock -period $clk_gen_period_ds -name ${clk_name}_cdt_int [get_pins -of_objects [get_cells ${osc_path}clk_gen_osc_inst/cdt_BSG_DONT_TOUCH/M1] -filter "pin_direction==out"]
#create_clock -period $clk_gen_period_ds -name ${clk_name}_fdt_int [get_pins -of_objects [get_cells ${osc_path}clk_gen_osc_inst/fdt_BSG_DONT_TOUCH/M2] -filter "pin_direction==out"]

# these are generated clocks; we call them clocks to get preferred shielding and routing
# nothing is actually timed with these
#create_clock -period $clk_gen_period_ds -name ${clk_name}_osc_ds [get_pins -of_objects [get_cells ${osc_path}clk_gen_ds_inst/clk_r_o_reg] -filter "pin_direction==out"]
#create_clock -period $clk_gen_period_ds -name ${clk_name}_osc_ds [get_pins -of_objects [get_db hinsts ${osc_path}clk_gen_ds_inst] -filter "pin_direction==out"]
create_clock -period $clk_gen_period_ds -name ${clk_name}_osc_ds [get_pins -of_objects [get_cells ${osc_path}clk_gen_ds_inst/clk_r_o_reg] -filter "pin_direction==out"]
set_clock_uncertainty $ds_uncertainty [get_clocks ${clk_name}_osc_ds]

# the output of the mux is the externally visible bonafide clock
create_clock -period $clk_gen_period_ext -name ${clk_name} [get_pins -of_objects [get_db hinsts ${osc_path}mux_inst] -filter "pin_direction==out"]
set_clock_uncertainty $clk_uncertainty [get_clocks ${clk_name}]
}

puts "Info: Completed script [info script]\n"
135 changes: 135 additions & 0 deletions v/chip/tcl/bsg_dmc.constraints.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
puts "Info: Start script [info script]\n"

proc bsg_dmc_create_ddr_intf { {prefix ""} } {
global ddr_intf
set ddr_intf(ck_p) [get_pins ${prefix}ddr_ck_p_o]
set ddr_intf(ck_n) [get_pins ${prefix}ddr_ck_n_o]
set ddr_intf(ca) [get_pins -hier ${prefix}* -filter "name=~ddr_*_o*&&name!~ddr_ck_*&&name!~ddr_dm_*&&name!~ddr_dq*"]
for {set gid 0} {$gid < 4} {incr gid} {
set ddr_intf($gid,dqs_p_i) [get_pins ${prefix}ddr_dqs_p_i[$gid]]
set ddr_intf($gid,dqs_p_o) [get_pins ${prefix}ddr_dqs_p_o[$gid]]
set ddr_intf($gid,dqs_en_o) [get_pins ${prefix}ddr_dqs_*_*en_o[$gid]]
set ddr_intf($gid,dqs_n_i) [get_pins ${prefix}ddr_dqs_n_i[$gid]]
set ddr_intf($gid,dqs_n_o) [get_pins ${prefix}ddr_dqs_n_o[$gid]]
set ddr_intf($gid,dm_o) [get_pins ${prefix}ddr_dm_*_o[$gid]]
for {set i [expr $gid*8]} {$i < [expr ($gid+1)*8]} {incr i} {
set ddr_intf($gid,dq_i) [get_pins ${prefix}ddr_dq_i[$i]]
set ddr_intf($gid,dq_o) [get_pins ${prefix}ddr_dq_*_o[$i]]
}
}
}

############################################
#
# bsg_dmc datapath timing assertions
#
proc bsg_dmc_data_timing_constraints { non_seq_chk id dfi_clk_1x_name dfi_clk_2x_name {prefix ""}} {
global ddr_intf
#
# dfi_clk_1x and dfi_clk_2x are defined inside bsg_dram_clk_gen
# we use their sources and cycle time to derive other dram-related clocks
set dfi_clk_1x_period [expr [lindex [get_db [get_clocks $dfi_clk_2x_name] .period] 0] * 2.0 / 1000.0]
set dfi_clk_1x_source [get_db [get_clocks $dfi_clk_1x_name] .sources]
# create input dqs clock
create_clock -period $dfi_clk_1x_period \
-name ${prefix}dqs_i_$id \
$ddr_intf($id,dqs_p_i)
create_clock -period $dfi_clk_1x_period \
-name ${prefix}dqs_n_i_$id \
$ddr_intf($id,dqs_n_i)
#create_clock -period $dfi_clk_1x_period \
# -name dqs_i_$id

set quarter_cycle [expr [lindex [get_db [get_clocks ${prefix}dqs_i_$id] .period] 0] / 4.0 / 1000.0]

# create 90-degree shifted clock on the output of delay line
#create_generated_clock -name dqs_i_${id}_dly \
# -edges {1 2 3} \
# -edge_shift [list $quarter_cycle $quarter_cycle $quarter_cycle] \
# -source [get_db [get_clocks dqs_i_$id] .sources] \
# [get_pins -leaf -of_objects [get_nets -hierarchical dqs_p_li[$id]] -filter "direction==out"]
#create_clock -period $dfi_clk_1x_period \
# -name dqs_i_${id}_dly \
# -waveform [list $quarter_cycle [expr 3 * $quarter_cycle]] \
# [get_pins -leaf -of_objects [get_nets -hierarchical dqs_p_li[$id]] -filter "direction==out"]
if {[get_cells -quiet -hier *clk_rst_gen] != ""} {
create_clock -period $dfi_clk_1x_period \
-name ${prefix}dqs_i_${id}_dly \
-waveform [list $quarter_cycle [expr 3 * $quarter_cycle]] \
[get_pins -hier *clk_rst_gen/dqs_clk_o[$id] -filter "direction==out"]
}
set max_io_skew_percent 5.0
set max_io_skew_time [expr $max_io_skew_percent * $dfi_clk_1x_period / 100.0]

# determin the max and min input delay
set max_input_delay [expr ($dfi_clk_1x_period / 4.0) - $max_io_skew_time]
set min_input_delay -$max_input_delay

# input timing constraints
# input data (dq) is edge aligned with input clock (dqs) after getting out of dram chips
# we set 20% of the clock cycle time to account for the misalignment when the signals propagate through the pcb traces and bond wire
set_input_delay $max_input_delay $ddr_intf($id,dq_i) -clock [get_clocks ${prefix}dqs_i_$id] -max
set_input_delay -$max_input_delay $ddr_intf($id,dq_i) -clock [get_clocks ${prefix}dqs_i_$id] -min

# basically we have two approaches to constrain the output paths
if { $non_seq_chk } {
# output timing constraints
# source synchronous output constraints, similar to comm_link output channels
foreach_in_collection from_obj $ddr_intf($id,dqs_p_o) {
foreach_in_collection to_obj [concat $ddr_intf($id,dq_o) $ddr_intf($id,dm_o)] {
# ideally output clock is center aligned with output data, so the clock has (-25%, +25%) of clock cycle time as the sampling window
# we deduct 20% from the margin and check if the clock is in the scope of (-5%, +5%) of the data center
set_data_check -from $from_obj -to $to_obj [expr $dfi_clk_1x_period * 0.2]
# set_data_check has a default zero cycle checking behavior which need to overcome in this case
# please take solvnet #024664 as a reference
set_multicycle_path -end -setup 1 -to $to_obj
set_multicycle_path -start -hold 0 -to $to_obj
}
}
} else {
# create generated output dqs clock based on 1x dfi clock
create_generated_clock -master_clock $dfi_clk_2x_name -divide_by 2 -source [get_db [get_clocks $dfi_clk_2x_name] .sources] -name dqs_p_o_$id -add $ddr_intf($id,dqs_p_o)
create_generated_clock -master_clock $dfi_clk_2x_name -divide_by 2 -source [get_db [get_clocks $dfi_clk_2x_name] .sources] -name dqs_n_o_$id -add $ddr_intf($id,dqs_n_o)

# determine max and min output delay
set max_output_delay $max_input_delay
set min_output_delay $min_input_delay

# similarly we use the output delay values to determin the worst skew between clock and data
# after they propagate through PCB traces and bond wires so that the data can be sampled
# correctly at the virtual registers outside the chip
# max_output_delay means data lags $max_output_delay behind clock
# min_input_delay means clock lags |$min_input_delay| behind data
set_output_delay -clock dqs_p_o_$id -max $max_output_delay $ddr_intf($id,dq_o)
set_output_delay -clock dqs_p_o_$id -max $max_output_delay $ddr_intf($id,dq_o) -add_delay -clock_fall
set_output_delay -clock dqs_p_o_$id -min $min_output_delay $ddr_intf($id,dq_o)
set_output_delay -clock dqs_p_o_$id -min $min_output_delay $ddr_intf($id,dq_o) -add_delay -clock_fall

set_output_delay -clock dqs_p_o_$id -max $max_output_delay $ddr_intf($id,dm_o)
set_output_delay -clock dqs_p_o_$id -max $max_output_delay $ddr_intf($id,dm_o) -add_delay -clock_fall
set_output_delay -clock dqs_p_o_$id -min $min_output_delay $ddr_intf($id,dm_o)
set_output_delay -clock dqs_p_o_$id -min $min_output_delay $ddr_intf($id,dm_o) -add_delay -clock_fall
}
}

############################################
#
# bsg_dmc address and command path timing assertions
#
proc bsg_dmc_ctrl_timing_constraints { dfi_clk_1x_name dfi_clk_2x_name prefix } {
global ddr_intf
#
# dfi_clk_1x and dfi_clk_2x are defined inside bsg_dram_clk_gen
# we use their sources and cycle time to derive other dram-related clocks
set dfi_clk_1x_period [expr [lindex [get_db [get_clocks $dfi_clk_2x_name] .period] 0] * 2.0 / 1000.0]
set dfi_clk_1x_source [get_db [get_clocks $dfi_clk_1x_name] .sources]
# create generated clocks to drive dram device, all the address and command signals are synchronous to these clocks
create_generated_clock -name ${prefix}ddr_ck_p -divide_by 1 -source $dfi_clk_1x_source -master_clock [get_clocks $dfi_clk_1x_name] -add $ddr_intf(ck_p)
create_generated_clock -name ${prefix}ddr_ck_n -divide_by 1 -invert -source $dfi_clk_1x_source -master_clock [get_clocks $dfi_clk_1x_name] -add $ddr_intf(ck_n)
# all the address and command signals are registered outputs which are aligned well with clock edges
# we give it a 10% margin to account for the misalignment caused by PCB traces and bond wires
set_output_delay [expr $dfi_clk_1x_period * 0.1] $ddr_intf(ca) -clock [get_clocks ${prefix}ddr_ck_p] -max
set_output_delay [expr -$dfi_clk_1x_period * 0.1] $ddr_intf(ca) -clock [get_clocks ${prefix}ddr_ck_p] -min
}

puts "Info: Completed script [info script]\n"
93 changes: 93 additions & 0 deletions v/chip/tcl/bsg_link_ddr.constraints.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#
# Paul Gao 03/2021
#
#

puts "Info: Start script [info script]\n"
set BSG_LINK_DDR_USE_GENERATED_CLOCK 1

proc bsg_link_ddr_in_constraints {clk_name ports max_delay min_delay} {
set_input_delay -max $max_delay -clock $clk_name -source_latency_included -network_latency_included $ports
set_input_delay -max $max_delay -clock $clk_name -source_latency_included -network_latency_included $ports -add_delay -clock_fall
set_input_delay -min $min_delay -clock $clk_name -source_latency_included -network_latency_included $ports
set_input_delay -min $min_delay -clock $clk_name -source_latency_included -network_latency_included $ports -add_delay -clock_fall
}

proc bsg_link_ddr_out_constraints {clk_port ports setup_time hold_time} {
foreach_in_collection obj $ports {
set_data_check -from $clk_port -to $obj -setup $setup_time
set_data_check -from $clk_port -to $obj -hold $hold_time
set_multicycle_path -end -setup 1 -to $obj
set_multicycle_path -start -hold 0 -to $obj
}
}

proc bsg_link_ddr_out_generated_clock_constraints {clk_name ports max_delay min_delay} {
set_output_delay -max $max_delay -clock $clk_name $ports
set_output_delay -max $max_delay -clock $clk_name $ports -add_delay -clock_fall
set_output_delay -min $min_delay -clock $clk_name $ports
set_output_delay -min $min_delay -clock $clk_name $ports -add_delay -clock_fall
}

proc bsg_link_ddr_constraints { \
master_clk_name \
out_clk_name \
out_clk_period \
out_clk_margin \
out_clk_port \
out_dv_port \
out_tkn_clk_name \
out_tkn_clk_port \
in_clk_name \
in_clk_period \
in_clk_margin \
in_clk_port \
in_dv_port \
in_tkn_clk_name \
in_tkn_clk_port \
uncertainty \
} {
# token
set in_tkn_clk_period [expr $in_clk_period]
create_clock -period $in_tkn_clk_period -name $in_tkn_clk_name $in_tkn_clk_port
set_clock_uncertainty $uncertainty [get_clocks $in_tkn_clk_name]

set out_tkn_clk_period [expr $out_clk_period]
create_clock -period $out_tkn_clk_period -name $out_tkn_clk_name $out_tkn_clk_port
set_clock_uncertainty $uncertainty [get_clocks $out_tkn_clk_name]

# input
set max_input_delay [expr ($in_clk_period/2.0)-$in_clk_margin]
set min_input_delay [expr $in_clk_margin]
create_clock -period $in_clk_period -name $in_clk_name $in_clk_port
set_clock_uncertainty $uncertainty [get_clocks $in_clk_name]
bsg_link_ddr_in_constraints $in_clk_name $in_dv_port $max_input_delay $min_input_delay
if {[get_ports -quiet $in_clk_port] != ""} {
set_driving_cell -no_design_rule -lib_cell "PDDW12DGZ_H_G" -pin C $in_clk_port
}
if {[get_ports -quiet $in_dv_port] != ""} {
set_driving_cell -no_design_rule -lib_cell "PDDW12DGZ_H_G" -pin C $in_dv_port
}

# output
global BSG_LINK_DDR_USE_GENERATED_CLOCK
puts "BSG_LINK_DDR_USE_GENERATED_CLOCK = $BSG_LINK_DDR_USE_GENERATED_CLOCK"
if {$BSG_LINK_DDR_USE_GENERATED_CLOCK == 0} {
set setup_time_output [expr ($out_clk_period/4.0)-$out_clk_margin]
set hold_time_output [expr ($out_clk_period/4.0)-$out_clk_margin]
bsg_link_ddr_out_constraints $out_clk_port $out_dv_port $setup_time_output $hold_time_output
} else {
set max_output_delay [expr ($out_clk_period/4.0)-$out_clk_margin]
set min_output_delay [expr $out_clk_margin-($out_clk_period/4.0)]
create_generated_clock -edges {2 4 6} -master_clock $master_clk_name -source [get_db [get_clocks $master_clk_name] .sources] -name $out_clk_name -add $out_clk_port
bsg_link_ddr_out_generated_clock_constraints $out_clk_name $out_dv_port $max_output_delay $min_output_delay
}
if {[get_ports -quiet $out_clk_port] != ""} {
set_load [load_of [get_lib_pin "*/PDDW12DGZ_H_G/I"]] $out_clk_port
}
if {[get_ports -quiet $out_dv_port] != ""} {
set_load [load_of [get_lib_pin "*/PDDW12DGZ_H_G/I"]] $out_dv_port
}
}

puts "Info: Completed script [info script]\n"
Loading