blob: 661ea5d4a1c3093531ec2a86f055e59c95538589 [file] [log] [blame]
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# Generic constraints file for simple testsynthesis flow
# Note that we do not fix hold timing in this flow
set SETUP_CLOCK_UNCERTAINTY 0.5
set CLK_PERIOD_FACTOR 0.95 ;# clock period over constraining factor
puts "Applying constraints for top level"
# Note: the netlist does include pads at this level, but not all IO interfaces
# have been properly constrained yet. The clocks are generated inside AST and
# for the purpose of test synthesis, these clock nets are just set to ideal networks.
#####################
# Architectural CGs #
#####################
# This is not needed by CDC runs
if {!$IS_CDC_RUN} {
# in synthesis, we treat all clock networks as ideal nets.
# architecturally insterted CGs however can be interpreted as
# sequential cells by the tool, hence stopping automatic propagation
# of ideal network attributes. therefore, we go through the design and
# declare all architectural CG outputs as ideal.
set_ideal_network [get_pins -hier u_clkgate/Q]
}
#####################
# main clock #
#####################
set MAIN_CLK_PIN u_ast/clk_src_sys_o
set MAIN_RST_PIN IO_RST_N
# target is 100MHz, overconstrain by factor
set MAIN_TCK_TARGET_PERIOD 10
set MAIN_TCK_FACTOR 0.85
set MAIN_TCK_PERIOD [expr $MAIN_TCK_TARGET_PERIOD*$MAIN_TCK_FACTOR] ;# over constraining
# For now we remove this as clock is, by default, ideal. Reset, we'll try w/o ideal_network.
#set_ideal_network [get_pins ${MAIN_CLK_PIN}]
#set_ideal_network [get_ports ${MAIN_RST_PIN}]
create_clock -name MAIN_CLK -period ${MAIN_TCK_PERIOD} [get_pins ${MAIN_CLK_PIN}]
set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} [get_clocks MAIN_CLK]
#set_false_path -from [get_clocks ${MAIN_CLK_PIN_AST}] -to [get_clocks ${MAIN_CLK_PIN}]
#####################
# USB clock #
#####################
set USB_CLK_PIN u_ast/clk_src_usb_o
# target is 48MHz, overconstrain by 5%
set USB_TCK_TARGET_PERIOD 20.8
set USB_TCK_PERIOD [expr $USB_TCK_TARGET_PERIOD*$CLK_PERIOD_FACTOR]
#set_ideal_network [get_pins ${USB_CLK_PIN}]
create_clock -name USB_CLK -period ${USB_TCK_PERIOD} [get_pins ${USB_CLK_PIN}]
set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} [get_clocks USB_CLK]
set USBDEV_IOMUX_PATH top_earlgrey/u_usbdev/i_usbdev_iomux/cdc_io_to_usb/u_sync_1/gen_*u_impl*
set USBDEV_OUTREG_PATH top_earlgrey/u_usbdev/usbdev_impl/u_usb_fs_nb_pe/u_usb_fs_tx
# This requires knowledge of actual pin names, which are different depending on
# whether we run this with tech lizbs or not.
if {$FOUNDRY_ROOT != ""} {
set USB_N_PIN gen_flops[2]*.u_size_only_reg/D
set USB_P_PIN gen_flops[3]*.u_size_only_reg/D
set USB_PIN gen_flops[1]*.u_size_only_reg/D
set USB_D_PIN u_usb_d_flop/gen_*u_impl*/gen_flops[0]*.u_size_only_reg/Q
set USB_OE_PIN u_oe_flop/gen_*u_impl*/gen_flops[0]*.u_size_only_reg/Q
} else {
set USB_N_PIN d_i[2]
set USB_P_PIN d_i[3]
set USB_PIN d_i[1]
set USB_D_PIN u_usb_d_flop/gen_*u_impl*/q_o[0]
set USB_OE_PIN u_oe_flop/gen_*u_impl*/q_o[0]
}
set_max_delay 3 -from [get_ports USB_N] -to [get_pins ${USBDEV_IOMUX_PATH}/${USB_N_PIN}]
set_max_delay 3 -from [get_ports USB_P] -to [get_pins ${USBDEV_IOMUX_PATH}/${USB_P_PIN}]
set_max_delay 3 -from [get_ports USB_*] -to [get_pins ${USBDEV_IOMUX_PATH}/${USB_PIN}]
set_max_delay 3 -from [get_pins ${USBDEV_OUTREG_PATH}/${USB_D_PIN}] -to [get_ports USB_*]
set_max_delay 3 -from [get_pins ${USBDEV_OUTREG_PATH}/${USB_OE_PIN}] -to [get_ports USB_*]
#####################
# IO clk #
#####################
set IO_CLK_PIN u_ast/clk_src_io_o
# target is 96MHz, overconstrain by factor
set IO_TCK_TARGET_PERIOD 10.416
set IO_TCK_PERIOD [expr $IO_TCK_TARGET_PERIOD*$CLK_PERIOD_FACTOR]
create_clock -name IO_CLK -period ${IO_TCK_PERIOD} [get_pins ${IO_CLK_PIN}]
set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} [get_clocks IO_CLK]
# This requires knowledge of actual port name
set CLK_DST_NAME clk_o
# generated clocks (div2/div4)
set CLK_PATH top_earlgrey/u_clkmgr_aon/u_no_scan_io_div2_div
create_generated_clock -name IO_DIV2_CLK \
-source [get_pins ${IO_CLK_PIN}] -divide_by 2 [get_pins ${CLK_PATH}/${CLK_DST_NAME}]
set CLK_PATH top_earlgrey/u_clkmgr_aon/u_no_scan_io_div4_div
create_generated_clock -name IO_DIV4_CLK \
-source [get_pins ${IO_CLK_PIN}] -divide_by 4 [get_pins ${CLK_PATH}/${CLK_DST_NAME}]
# TODO: these are dummy constraints and likely incorrect, need to properly constrain min/max
# note that due to the muxing, additional timing views with set_case_analysis may be needed.
# aggregate all IO banks
set IO_BANKS [get_ports IOA*]
append_to_collection IO_BANKS [get_ports IOB*]
append_to_collection IO_BANKS [get_ports IOC*]
append_to_collection IO_BANKS [get_ports IOR*]
# constrain muxed IOs running on IO_DIV2_CLK and IO_DIV4_CLK
set IO_IN_DEL_FRACTION 0.45
set IO_OUT_DEL_FRACTION 0.45
# IO_DIV2_CLK
set IO_DIV2_IN_DEL [expr ${IO_IN_DEL_FRACTION} * ${IO_TCK_PERIOD} * 2.0]
set IO_DIV2_OUT_DEL [expr ${IO_OUT_DEL_FRACTION} * ${IO_TCK_PERIOD} * 2.0]
set_input_delay ${IO_DIV2_IN_DEL} ${IO_BANKS} -clock IO_DIV2_CLK
set_output_delay ${IO_DIV2_OUT_DEL} ${IO_BANKS} -clock IO_DIV2_CLK
# IO_DIV4_CLK
set IO_DIV4_IN_DEL [expr ${IO_IN_DEL_FRACTION} * ${IO_TCK_PERIOD} * 4.0]
set IO_DIV4_OUT_DEL [expr ${IO_OUT_DEL_FRACTION} * ${IO_TCK_PERIOD} * 4.0]
set_input_delay ${IO_DIV4_IN_DEL} ${IO_BANKS} -clock IO_DIV4_CLK -add_delay
set_output_delay ${IO_DIV4_OUT_DEL} ${IO_BANKS} -clock IO_DIV4_CLK -add_delay
#####################
# sysrst_ctrl #
#####################
# MIO paths that go into sysrst_ctrl and fan out into MIOs or dedicated sysrst_ctrl outputs are async in nature, hence we constrain them using a max delay.
set SYSRST_MAXDELAY 50.0
set_max_delay -from ${IO_BANKS} -to ${IO_BANKS} -through [get_cells top_earlgrey/u_sysrst_ctrl_aon/*] ${SYSRST_MAXDELAY}
#####################
# AON clk #
#####################
set AON_CLK_PIN u_ast/clk_src_aon_o
# target is 200KHz, overconstrain by factor
set AON_TCK_TARGET_PERIOD 5000.0
set AON_TCK_PERIOD [expr $AON_TCK_TARGET_PERIOD*$CLK_PERIOD_FACTOR]
#set_ideal_network [get_pins ${AON_CLK_PIN}]
create_clock -name AON_CLK -period ${AON_TCK_PERIOD} [get_pins ${AON_CLK_PIN}]
set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} [get_clocks AON_CLK]
#####################
# JTAG clock #
#####################
# TODO: set up constraints for JTAG.
set JTAG_CLK_PIN IOR3
# target is 20MHz, overconstrain by factor
set JTAG_TCK_TARGET_PERIOD 50
set JTAG_TCK_PERIOD [expr $JTAG_TCK_TARGET_PERIOD*$CLK_PERIOD_FACTOR]
create_clock -name JTAG_TCK -period $JTAG_TCK_PERIOD [get_ports $JTAG_CLK_PIN]
#set_ideal_network [get_ports $JTAG_CLK_PIN]
set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} [get_clocks JTAG_TCK]
#####################
# AST clock #
#####################
set AST_EXT_CLK_PIN IOC6
# target is 48MHz, overconstrain by factor
set AST_EXT_TCK_TARGET_PERIOD [expr $IO_TCK_TARGET_PERIOD*2]
set AST_EXT_TCK_PERIOD [expr $AST_EXT_TCK_TARGET_PERIOD*$CLK_PERIOD_FACTOR]
create_clock -name AST_EXT_CLK -period ${AST_EXT_TCK_PERIOD} [get_ports ${AST_EXT_CLK_PIN}]
set_clock_uncertainty -setup ${SETUP_CLOCK_UNCERTAINTY} [get_clocks AST_EXT_CLK]
# This is not needed by CDC runs because io_clk/usb_clk/main_clk/aon_clk are propagated from ast_ext_clk in ast.lib
# we don't use this constraint to avoid unnecessary CDC issues
if {!$IS_CDC_RUN} {
set_clock_groups -name group_ast -async -group [get_clocks AST_EXT_CLK]
}
####################################
# SPI System Parameters #
#####################################
# routing delay from external component to device
set PCB_DEL 1
# external spi host setup
set HOST_SETUP_DEL 4
# external spi host clk-to-q
set HOST_OUT_DEL 3
# external spi dev setup
set STORAGE_SETUP_DEL 3
# external spi dev clk-to-q
set STORAGE_OUT_DEL 7
#################
# SPI DEV clock #
#################
# TODO
# Add source delays for generated clocks
# Construct realistic input / output delays using system parameters
# strawman constraints. Device target freq is 48MHz. Using 62.5MHz to over-constraint
set SPI_DEV_CLK_PIN SPI_DEV_CLK
# 62.5MHz
set SPI_DEV_TCK 16.0
#set_ideal_network ${SPI_DEV_CLK_PIN}
## TODO: Create generated clock for negedge SPI_DEV_CLK. Then make them clock group
create_clock -name SPI_DEV_CLK -period ${SPI_DEV_TCK} [get_ports ${SPI_DEV_CLK_PIN}]
set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} [get_clocks SPI_DEV_CLK]
create_generated_clock -name SPI_DEV_IN_CLK -source SPI_DEV_CLK -divide_by 1 \
[get_pins top_earlgrey/u_spi_device/u_clk_spi_in_buf/clk_o]
create_generated_clock -name SPI_DEV_OUT_CLK -source SPI_DEV_CLK -divide_by 1 \
-invert [get_pins top_earlgrey/u_spi_device/u_clk_spi_out_buf/clk_o]
# CSb clock
create_clock -name SPI_CSB_CLK -period ${SPI_DEV_TCK} \
[get_pins top_earlgrey/u_spi_device/u_clk_csb_buf/clk_o]
## TODO: these are dummy constraints and likely incorrect, need to properly constrain min/max
# FRACTION is reduced to 0.2 as internal datapath for SPI is half clk period
set SPI_DEV_IN_DEL_FRACTION 0.2
set SPI_DEV_OUT_DEL_FRACTION 0.2
set SPI_DEV_IN_DEL [expr ${SPI_DEV_IN_DEL_FRACTION} * ${SPI_DEV_TCK}]
set SPI_DEV_OUT_DEL [expr ${SPI_DEV_OUT_DEL_FRACTION} * ${SPI_DEV_TCK}]
# this is an input only port
set_input_delay ${SPI_DEV_IN_DEL} [get_ports SPI_DEV_CS_L] -clock SPI_DEV_CLK
# bidir ports
set_input_delay ${SPI_DEV_IN_DEL} [get_ports SPI_DEV_D0] -clock SPI_DEV_CLK
set_input_delay ${SPI_DEV_IN_DEL} [get_ports SPI_DEV_D1] -clock SPI_DEV_CLK
set_input_delay ${SPI_DEV_IN_DEL} [get_ports SPI_DEV_D2] -clock SPI_DEV_CLK
set_input_delay ${SPI_DEV_IN_DEL} [get_ports SPI_DEV_D3] -clock SPI_DEV_CLK
set_output_delay ${SPI_DEV_OUT_DEL} [get_ports SPI_DEV_D0] -clock SPI_DEV_CLK
set_output_delay ${SPI_DEV_OUT_DEL} [get_ports SPI_DEV_D1] -clock SPI_DEV_CLK
set_output_delay ${SPI_DEV_OUT_DEL} [get_ports SPI_DEV_D2] -clock SPI_DEV_CLK
set_output_delay ${SPI_DEV_OUT_DEL} [get_ports SPI_DEV_D3] -clock SPI_DEV_CLK
# False path from CSb to return to host as CSb for that path behaves as reset.
#set_ideal_network [get_pins top_earlgrey/u_spi_device/u_csb_rst_scan_mux/clk_o]
set_false_path -through [get_pins top_earlgrey/u_spi_device/cio_csb_i] \
-through [get_pins top_earlgrey/u_spi_device/cio_sd_en_o*]
set_false_path -through [get_pins top_earlgrey/u_spi_device/cio_csb_i] \
-through [get_pins top_earlgrey/u_spi_device/cio_sd_o*]
##################
# SPI HOST clock #
##################
# SPI host core logic operates on the IO_CLK
#
# See https://docs.google.com/drawings/d/1qkUnXaRafIPyBnVpreqfbF_zSy0xlpHqXMZp6F-j8Cc/edit?usp=sharing
# During pre-layout, the SPI_HOST_CLK source latencies are estimanted to account for
# pad and logic latencies. After CTS, source latency must be removed as all clocks are propagated
# This requires knowledge of actual pin names, which are different depending on
# whether we run this with tech libs or not.
if {$FOUNDRY_ROOT != ""} {
set REG_PIN gen_flops[0]*.u_size_only_reg/Q
} else {
set REG_PIN q_o[0]
}
# cascaded generated clock on the port
create_generated_clock -name SPI_HOST_CLK -source [get_pins ${IO_CLK_PIN}] \
-divide_by 2 [get_ports SPI_HOST_CLK]
# Approximate source latency
# The following must be removed after CTS when clocks actually propagate
set SPI_HOST_SRC_LATENCY 5
set_clock_latency ${SPI_HOST_SRC_LATENCY} -source [get_clock SPI_HOST_CLK]
# set multicycle path for data going from SPI_HOST_CLK to logic
# the SPI host logic will read these paths at "full cycle"
set_multicycle_path -setup 2 -end -from [get_clocks SPI_HOST_CLK] -to [get_clocks IO_CLK]
set_multicycle_path -hold 1 -end -from [get_clocks SPI_HOST_CLK] -to [get_clocks IO_CLK]
# computed delays from connected device
# host in has 2x the pcb delay to account for delays on both outgoing clocks and incoming data
set SPI_HOST_IN_DEL [expr 2*${PCB_DEL} + ${STORAGE_OUT_DEL}]
set SPI_HOST_OUT_DEL [expr ${PCB_DEL} + ${STORAGE_SETUP_DEL}]
# bidir ports
set_input_delay ${SPI_HOST_IN_DEL} [get_ports SPI_HOST_CS_L] -clock SPI_HOST_CLK -add_delay
set_input_delay ${SPI_HOST_IN_DEL} [get_ports SPI_HOST_D0] -clock SPI_HOST_CLK -add_delay
set_input_delay ${SPI_HOST_IN_DEL} [get_ports SPI_HOST_D1] -clock SPI_HOST_CLK -add_delay
set_input_delay ${SPI_HOST_IN_DEL} [get_ports SPI_HOST_D2] -clock SPI_HOST_CLK -add_delay
set_input_delay ${SPI_HOST_IN_DEL} [get_ports SPI_HOST_D3] -clock SPI_HOST_CLK -add_delay
set_output_delay ${SPI_HOST_OUT_DEL} [get_ports SPI_HOST_CS_L] -clock SPI_HOST_CLK -add_delay
set_output_delay ${SPI_HOST_OUT_DEL} [get_ports SPI_HOST_D0] -clock SPI_HOST_CLK -add_delay
set_output_delay ${SPI_HOST_OUT_DEL} [get_ports SPI_HOST_D1] -clock SPI_HOST_CLK -add_delay
set_output_delay ${SPI_HOST_OUT_DEL} [get_ports SPI_HOST_D2] -clock SPI_HOST_CLK -add_delay
set_output_delay ${SPI_HOST_OUT_DEL} [get_ports SPI_HOST_D3] -clock SPI_HOST_CLK -add_delay
#####################################
# SPI DEV clock Passthru Operation #
#####################################
# Passthrough target freq is 33MHz. Using 40MHz to over-constrain
#
# The constraints below take the following approach:
# Define incoming passthrough clock on the SPI_DEV_CLK pin and relate all the inputs to it.
# Define also output delays since all pins are bidirectional.
# Define outgoing passthrough clock on the SPI_HOST_CLK pin but make sure it is a generated version
# of the incoming passthrough clock, relate the host side pins to this clock in both input/output
# directions.
#
# For details on SPI passthrough timing, please see
# https://docs.google.com/presentation/d/1GEPxKaOsr9ZcJwI_MBEL74P7jQvBFzOdzSbgru_yVLQ/edit?usp=sharing
set SPI_DEV_PASSTHRU_CK 25.0
create_clock -name SPI_DEV_PASSTHRU_CLK -period ${SPI_DEV_PASSTHRU_CK} [get_ports ${SPI_DEV_CLK_PIN}] -add
set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} [get_clocks SPI_DEV_PASSTHRU_CLK]
# clocks used by spi device internally
# Unlike spi-dev above, here the "incoming" clock is treated like the "launch", while the inverted
# is treated like "capture". The other way would work fine as well, but several other adjustments
# would need to be made the rest of the constraints.
create_generated_clock -name SPI_DEV_PASSTHRU_IN_CLK -source SPI_DEV_CLK -divide_by 1 \
-invert [get_pins top_earlgrey/u_spi_device/u_clk_spi_in_buf/clk_o] -add -master_clock SPI_DEV_PASSTHRU_CLK
create_generated_clock -name SPI_DEV_PASSTHRU_OUT_CLK -source SPI_DEV_CLK -divide_by 1 \
[get_pins top_earlgrey/u_spi_device/u_clk_spi_out_buf/clk_o] -add -master_clock SPI_DEV_PASSTHRU_CLK
# CSb clock (added to SPI_CSB_CLK)
create_clock -name SPI_DEV_PASSTHRU_CSB_CLK -period ${SPI_DEV_PASSTHRU_CK} \
[get_pins top_earlgrey/u_spi_device/u_clk_csb_buf/clk_o] -add
# clocks accounting for propagation delay to the other side
create_generated_clock -name SPI_HOST_PASSTHRU_CLK -source SPI_DEV_CLK \
-master_clock SPI_DEV_PASSTHRU_CLK -divide_by 1 \
[get_ports SPI_HOST_CLK] -add
# The propagated properties are needed to ensure the passthrough clocks assume all passthrough delay.
# This is done specifically for the passthrough interface to get realistic timing even during
# pre-layout.
set_propagated_clock [get_clock SPI_DEV_PASSTHRU_CLK]
set_propagated_clock [get_clock SPI_HOST_PASSTHRU_CLK]
# delays below are nominal since target frequency is already over constrained
set HALF_CYCLE [expr ${SPI_DEV_PASSTHRU_CK} / 2]
# These are delays facing the host
set SPI_DEV_PASSTHRU_HOST_IN_DEL [expr 2*${PCB_DEL} + ${HOST_OUT_DEL}]
set SPI_DEV_PASSTHRU_HOST_OUT_DEL [expr {${PCB_DEL} + ${HOST_SETUP_DEL}}]
# for transactions passing from storage into the device, they are going to be sampled
# by the host at "full cycle" boundaries
set SPI_DEV_PASSTHRU_STORAGE_IN_DEL [expr {2*${PCB_DEL} + ${STORAGE_OUT_DEL}}]
# for transactions passing through the device to the storage device, the commands
# are captured on half cycle boundaries
set SPI_DEV_PASSTHRU_STORAGE_OUT_DEL [expr ${PCB_DEL} + ${STORAGE_SETUP_DEL} + ${HALF_CYCLE}]
# bidir ports facing host
set_input_delay ${SPI_DEV_PASSTHRU_HOST_IN_DEL} [get_ports SPI_DEV_D0] -clock SPI_DEV_PASSTHRU_CLK -add_delay
set_input_delay ${SPI_DEV_PASSTHRU_HOST_IN_DEL} [get_ports SPI_DEV_D1] -clock SPI_DEV_PASSTHRU_CLK -add_delay
set_input_delay ${SPI_DEV_PASSTHRU_HOST_IN_DEL} [get_ports SPI_DEV_D2] -clock SPI_DEV_PASSTHRU_CLK -add_delay
set_input_delay ${SPI_DEV_PASSTHRU_HOST_IN_DEL} [get_ports SPI_DEV_D3] -clock SPI_DEV_PASSTHRU_CLK -add_delay
set_input_delay ${SPI_DEV_PASSTHRU_HOST_IN_DEL} [get_ports SPI_DEV_CS_L] -clock SPI_DEV_PASSTHRU_CLK -add_delay
set_output_delay ${SPI_DEV_PASSTHRU_HOST_OUT_DEL} [get_ports SPI_DEV_D0] -clock SPI_DEV_PASSTHRU_CLK -add_delay
set_output_delay ${SPI_DEV_PASSTHRU_HOST_OUT_DEL} [get_ports SPI_DEV_D1] -clock SPI_DEV_PASSTHRU_CLK -add_delay
set_output_delay ${SPI_DEV_PASSTHRU_HOST_OUT_DEL} [get_ports SPI_DEV_D2] -clock SPI_DEV_PASSTHRU_CLK -add_delay
set_output_delay ${SPI_DEV_PASSTHRU_HOST_OUT_DEL} [get_ports SPI_DEV_D3] -clock SPI_DEV_PASSTHRU_CLK -add_delay
# bidir ports facing storage device
set_input_delay ${SPI_DEV_PASSTHRU_STORAGE_IN_DEL} [get_ports SPI_HOST_D0] -clock SPI_HOST_PASSTHRU_CLK -add_delay
set_input_delay ${SPI_DEV_PASSTHRU_STORAGE_IN_DEL} [get_ports SPI_HOST_D1] -clock SPI_HOST_PASSTHRU_CLK -add_delay
set_input_delay ${SPI_DEV_PASSTHRU_STORAGE_IN_DEL} [get_ports SPI_HOST_D2] -clock SPI_HOST_PASSTHRU_CLK -add_delay
set_input_delay ${SPI_DEV_PASSTHRU_STORAGE_IN_DEL} [get_ports SPI_HOST_D3] -clock SPI_HOST_PASSTHRU_CLK -add_delay
set_output_delay ${SPI_DEV_PASSTHRU_STORAGE_OUT_DEL} [get_ports SPI_HOST_D0] -clock SPI_HOST_PASSTHRU_CLK -add_delay
set_output_delay ${SPI_DEV_PASSTHRU_STORAGE_OUT_DEL} [get_ports SPI_HOST_D1] -clock SPI_HOST_PASSTHRU_CLK -add_delay
set_output_delay ${SPI_DEV_PASSTHRU_STORAGE_OUT_DEL} [get_ports SPI_HOST_D2] -clock SPI_HOST_PASSTHRU_CLK -add_delay
set_output_delay ${SPI_DEV_PASSTHRU_STORAGE_OUT_DEL} [get_ports SPI_HOST_D3] -clock SPI_HOST_PASSTHRU_CLK -add_delay
set_output_delay ${SPI_DEV_PASSTHRU_STORAGE_OUT_DEL} [get_ports SPI_HOST_CS_L] -clock SPI_HOST_PASSTHRU_CLK -add_delay
#####################
# SPI passthrough #
#####################
# Bronze: Over-constraining. Actual values will be set once design is ready
# input pad + internal + output pad
#
# The commented out code below was the bronze approach. We may still return to it later
# for its simplicity. If we stick with the approach below, it will be necessary to add
# set_data_checks to ensure the signals are relatively balanced.
#set TPAD_I 1.2
#set THODI 2.0
#set TPAD_O 3.3
#set SPI_HODI_PASS_MAX_DELAY [expr ${TPAD_I} + ${THODI} + ${TPAD_O}]
#set SPI_HIDO_PASS_MAX_DELAY ${SPI_HODI_PASS_MAX_DELAY}
#
## TODO: These are strawman constraints and need to be refined.
#set_max_delay ${SPI_HODI_PASS_MAX_DELAY} -from [get_ports SPI_DEV_D0] -to [get_ports SPI_HOST_D0]
#set_max_delay ${SPI_HODI_PASS_MAX_DELAY} -from [get_ports SPI_DEV_D1] -to [get_ports SPI_HOST_D1]
#set_max_delay ${SPI_HODI_PASS_MAX_DELAY} -from [get_ports SPI_DEV_D2] -to [get_ports SPI_HOST_D2]
#set_max_delay ${SPI_HODI_PASS_MAX_DELAY} -from [get_ports SPI_DEV_D3] -to [get_ports SPI_HOST_D3]
#set_max_delay ${SPI_HODI_PASS_MAX_DELAY} -from [get_ports SPI_DEV_CS_L] -to [get_ports SPI_HOST_CS_L]
#
#set_max_delay ${SPI_HIDO_PASS_MAX_DELAY} -from [get_ports SPI_HOST_D0] -to [get_ports SPI_DEV_D0]
#set_max_delay ${SPI_HIDO_PASS_MAX_DELAY} -from [get_ports SPI_HOST_D1] -to [get_ports SPI_DEV_D1]
#set_max_delay ${SPI_HIDO_PASS_MAX_DELAY} -from [get_ports SPI_HOST_D2] -to [get_ports SPI_DEV_D2]
#set_max_delay ${SPI_HIDO_PASS_MAX_DELAY} -from [get_ports SPI_HOST_D3] -to [get_ports SPI_DEV_D3]
#####################
# CDC #
#####################
# this may need some refinement (and max delay / skew needs to be constrained)
set_clock_groups -name group1 -async \
-group [get_clocks MAIN_CLK ] \
-group [get_clocks USB_CLK ] \
-group [get_clocks {SPI_DEV_CLK SPI_DEV_IN_CLK SPI_DEV_OUT_CLK SPI_CSB_CLK} ] \
-group [get_clocks {SPI_DEV_PASSTHRU_CLK SPI_HOST_PASSTHRU_CLK SPI_DEV_PASSTHRU_IN_CLK SPI_DEV_PASSTHRU_OUT_CLK SPI_DEV_PASSTHRU_CSB_CLK} ] \
-group [get_clocks {IO_CLK SPI_HOST_INT_CLK SPI_HOST_CLK} ] \
-group [get_clocks IO_DIV2_CLK ] \
-group [get_clocks IO_DIV4_CLK ] \
-group [get_clocks JTAG_TCK ] \
-group [get_clocks AON_CLK ]
# UART loopback path can be considered to be a false path
set_false_path -through [get_pins top_earlgrey/u_uart*/cio_rx_i] -through [get_pins top_earlgrey/u_uart*/cio_tx_o]
# break all timing paths through bidirectional IO buffers (i.e., from output and oe to input buffer output)
set_false_path -through [get_pins *padring/*pad/*/oe_i] -through [get_pins *padring/*pad/*/in_o]
set_false_path -through [get_pins *padring/*pad/*/out_i] -through [get_pins *padring/*pad/*/in_o]
# break path through jtag mux
set_false_path -from [get_ports IOC7] -to [get_ports IOR*]
# pass through is not fully supported yet by SPI host
# TODO: revise this
# set_false_path -through [get_pins top_earlgrey/u_spi_host1/u_sck_passthrough/gen_*/u_size_only_mux2/${DRIVING_CELL_PIN}]
#####################
# I/O drive/load #
#####################
# This is not needed by CDC runs
if {!$IS_CDC_RUN} {
# attach load and drivers to IOs to get a more realistic estimate
set_driving_cell -no_design_rule -lib_cell ${DRIVING_PAD} -pin ${DRIVING_PAD_PIN} [all_inputs]
set_load [load_of ${LOAD_PAD_LIB}/${LOAD_PAD}/${LOAD_PAD_PIN}] [all_outputs]
}
###################################
# Size Only and Don't touch Cells #
###################################
# This is not needed by CDC runs
if {!$IS_CDC_RUN} {
# this is for architectural clock buffers, inverters and muxes
set_size_only -all_instances [get_cells -h *u_size_only*] true
# do not touch pad cells
set_dont_touch [get_cells -h *u_pad_macro*]
}
puts "Done applying constraints for top level"
##########################################
# Case analysis for quasi-static signals #
##########################################
# assume a value of 0 for the open drain pad attribute
set_case_analysis 0 [get_pins u_padring/*_pad/attr_i\[od_en\]]