blob: 84ac04b67796f58d7ff0e1ec45f5dc644fc21f30 [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 #
#####################
# 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/u_sys_clk/u_sys_osc/sys_clk_o
set MAIN_RST_PIN IO_RST_N
# target is 100MHz, overconstrain by factor
set MAIN_TCK_TARGET_PERIOD 10
set MAIN_TCK_PERIOD [expr $MAIN_TCK_TARGET_PERIOD*$CLK_PERIOD_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]
#####################
# USB clock #
#####################
set USB_CLK_PIN u_ast/u_usb_clk/u_usb_osc/usb_clk_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_max_delay 1 -from [get_ports USB_N] -to [get_pins top_earlgrey/u_usbdev/i_usbdev_iomux/cdc_io_to_usb/gen_*u_impl_*/u_sync_1/gen_*u_impl*/gen_flops[2]*.u_size_only_reg/D]
set_max_delay 1 -from [get_ports USB_P] -to [get_pins top_earlgrey/u_usbdev/i_usbdev_iomux/cdc_io_to_usb/gen_*u_impl_*/u_sync_1/gen_*u_impl*/gen_flops[3]*.u_size_only_reg/D]
set_max_delay 1 -from [get_ports USB_*] -to [get_pins top_earlgrey/u_usbdev/i_usbdev_iomux/cdc_io_to_usb/gen_*u_impl_*/u_sync_1/gen_*u_impl*/gen_flops[1]*.u_size_only_reg/D]
set_max_delay 1 -from [get_pins top_earlgrey/u_usbdev/usbdev_impl/u_usb_fs_nb_pe/u_usb_fs_tx/usb_d_q_reg/Q] -to [get_ports USB_*]
set_max_delay 1 -from [get_pins top_earlgrey/u_usbdev/usbdev_impl/u_usb_fs_nb_pe/u_usb_fs_tx/oe_q_reg/Q] -to [get_ports USB_*]
#####################
# IO clk #
#####################
set IO_CLK_PIN u_ast/u_io_clk/u_io_osc/io_clk_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]
#set_ideal_network [get_pins ${IO_CLK_PIN}]
create_clock -name IO_CLK -period ${IO_TCK_PERIOD} [get_pins ${IO_CLK_PIN}]
set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} [get_clocks IO_CLK]
# generated clocks (div2/div4)
create_generated_clock -name IO_DIV2_CLK -divide_by 2 \
-source [get_pins top_earlgrey/u_clkmgr_aon/u_no_scan_io_div2_div/u_clk_mux/gen_*u_impl*/u_size_only_mux2/D1] \
[get_pins top_earlgrey/u_clkmgr_aon/u_no_scan_io_div2_div/u_clk_mux/gen_*u_impl*/u_size_only_inv/${DRIVING_CELL_PIN}]
create_generated_clock -name IO_DIV4_CLK -divide_by 4 \
-source [get_pins top_earlgrey/u_clkmgr_aon/u_no_scan_io_div4_div/u_clk_mux/gen_*u_impl*/u_size_only_mux2/D1] \
[get_pins top_earlgrey/u_clkmgr_aon/u_no_scan_io_div4_div/u_clk_mux/gen_*u_impl*/u_size_only_inv/${DRIVING_CELL_PIN}]
# 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.
# constrain muxed IOs running on IO_DIV2_CLK and IO_DIV4_CLK
set IO_IN_DEL_FRACTION 0.7
set IO_OUT_DEL_FRACTION 0.7
# 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} [get_ports IOA*] -clock IO_DIV2_CLK
set_input_delay ${IO_DIV2_IN_DEL} [get_ports IOB*] -clock IO_DIV2_CLK
set_input_delay ${IO_DIV2_IN_DEL} [get_ports IOC*] -clock IO_DIV2_CLK
set_input_delay ${IO_DIV2_IN_DEL} [get_ports IOR*] -clock IO_DIV2_CLK
set_output_delay ${IO_DIV2_OUT_DEL} [get_ports IOA*] -clock IO_DIV2_CLK
set_output_delay ${IO_DIV2_OUT_DEL} [get_ports IOB*] -clock IO_DIV2_CLK
set_output_delay ${IO_DIV2_OUT_DEL} [get_ports IOC*] -clock IO_DIV2_CLK
set_output_delay ${IO_DIV2_OUT_DEL} [get_ports IOR*] -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} [get_ports IOA*] -clock IO_DIV4_CLK -add_delay
set_input_delay ${IO_DIV4_IN_DEL} [get_ports IOB*] -clock IO_DIV4_CLK -add_delay
set_input_delay ${IO_DIV4_IN_DEL} [get_ports IOC*] -clock IO_DIV4_CLK -add_delay
set_input_delay ${IO_DIV4_IN_DEL} [get_ports IOR*] -clock IO_DIV4_CLK -add_delay
set_output_delay ${IO_DIV4_OUT_DEL} [get_ports IOA*] -clock IO_DIV4_CLK -add_delay
set_output_delay ${IO_DIV4_OUT_DEL} [get_ports IOB*] -clock IO_DIV4_CLK -add_delay
set_output_delay ${IO_DIV4_OUT_DEL} [get_ports IOC*] -clock IO_DIV4_CLK -add_delay
set_output_delay ${IO_DIV4_OUT_DEL} [get_ports IOR*] -clock IO_DIV4_CLK -add_delay
#####################
# AON clk #
#####################
set AON_CLK_PIN u_ast/u_aon_clk/u_aon_osc/aon_clk_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]
#####################
# RNG clock #
#####################
set RNG_CLK_PIN u_ast/u_rng/u_rng_osc/rng_clk_o
# target is 100MHz, overconstrain by factor
set RNG_TCK_TARGET_PERIOD 10
set RNG_TCK_PERIOD [expr $RNG_TCK_TARGET_PERIOD*$CLK_PERIOD_FACTOR]
create_clock -name RNG_CLK -period $RNG_TCK_PERIOD [get_pins $RNG_CLK_PIN]
#set_ideal_network [get_ports $RNG_CLK_PIN]
set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} [get_clocks RNG_CLK]
#####################
# SPI DEV clock #
#####################
# 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]
## TODO: Define SRAM clock, which is muxed clock. Do we need set_case_analysis?
## sram_clk is after clock gating cell
create_generated_clock -name SPI_SRAM_CLK -source SPI_DEV_CLK -divide_by 1 \
[get_pins top_earlgrey/u_spi_device/u_sram_clk_cg/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 #
#####################
# In Bronze the SPI host desing is a duplication of DEV design. For now, over-constraining with 62.5MHz
set SPI_HOST_CLK_PIN SPI_HOST_CLK
# 62.5MHz
set SPI_HOST_TCK 16.0
set_ideal_network ${SPI_HOST_CLK_PIN}
create_clock -name SPI_HOST_CLK -period ${SPI_HOST_TCK} [get_ports ${SPI_HOST_CLK_PIN}]
set_clock_uncertainty ${SETUP_CLOCK_UNCERTAINTY} [get_clocks SPI_HOST_CLK]
## TODO: Create generated clock for negedge SPI_HOST_CLK. Then make them clock group
## TODO: these are dummy constraints and likely incorrect, need to properly constrain min/max
set SPI_HOST_IN_DEL_FRACTION 0.7
set SPI_HOST_OUT_DEL_FRACTION 0.7
set SPI_HOST_IN_DEL [expr ${SPI_HOST_IN_DEL_FRACTION} * ${SPI_HOST_TCK}]
set SPI_HOST_OUT_DEL [expr ${SPI_HOST_OUT_DEL_FRACTION} * ${SPI_HOST_TCK}]
# bidir ports
set_input_delay ${SPI_HOST_IN_DEL} [get_ports SPI_HOST_CS_L] -clock SPI_HOST_CLK
set_input_delay ${SPI_HOST_IN_DEL} [get_ports SPI_HOST_D0] -clock SPI_HOST_CLK
set_input_delay ${SPI_HOST_IN_DEL} [get_ports SPI_HOST_D1] -clock SPI_HOST_CLK
set_input_delay ${SPI_HOST_IN_DEL} [get_ports SPI_HOST_D2] -clock SPI_HOST_CLK
set_input_delay ${SPI_HOST_IN_DEL} [get_ports SPI_HOST_D3] -clock SPI_HOST_CLK
set_output_delay ${SPI_HOST_OUT_DEL} [get_ports SPI_HOST_CS_L] -clock SPI_HOST_CLK
set_output_delay ${SPI_HOST_OUT_DEL} [get_ports SPI_HOST_D0] -clock SPI_HOST_CLK
set_output_delay ${SPI_HOST_OUT_DEL} [get_ports SPI_HOST_D1] -clock SPI_HOST_CLK
set_output_delay ${SPI_HOST_OUT_DEL} [get_ports SPI_HOST_D2] -clock SPI_HOST_CLK
set_output_delay ${SPI_HOST_OUT_DEL} [get_ports SPI_HOST_D3] -clock SPI_HOST_CLK
#####################
# SPI passthrough #
#####################
# Bronze: Over-constraining. Actual values will be set once design is ready
# input pad + internal + output pad
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 ] \
-group [get_clocks SPI_HOST_CLK ] \
-group [get_clocks IO_CLK ] \
-group [get_clocks IO_DIV2_CLK ] \
-group [get_clocks IO_DIV4_CLK ] \
-group [get_clocks RNG_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 #
#####################
# 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]
# set a nonzero critical range to be able to spot the violating paths better
# in the report
set_critical_range 0.5 ${DUT}
###################################
# Size Only and Don't touch Cells #
###################################
# 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 pad attribute at index [9]
#set_case_analysis 0 [get_pins u_padring/u_*_pad/attr_i[9]]
set_case_analysis 0 [get_pins u_padring/gen_*gen_*u_*_pad/attr_i[9]]