mpw-6 pdn fix
diff --git a/Makefile b/Makefile
index 1fcad3c..09c44b5 100644
--- a/Makefile
+++ b/Makefile
@@ -207,6 +207,7 @@
gzip -f maglef/*
gzip -f spef/*
gzip -f spi/lvs/*
+ gzip -f verilog/gl/*
unzip:
gzip -d def/*
@@ -216,6 +217,7 @@
gzip -d maglef/*
gzip -d spef/*
gzip -d spi/lvs/*
+ gzip -d verilog/gl/*
.PHONY: help
help:
diff --git a/openlane/Makefile b/openlane/Makefile
index 735e66f..865f452 100644
--- a/openlane/Makefile
+++ b/openlane/Makefile
@@ -18,7 +18,7 @@
CONFIG = $(foreach block,$(BLOCKS), ./$(block)/config.tcl)
CLEAN = $(foreach block,$(BLOCKS), clean-$(block))
-OPENLANE_TAG = mpw6
+OPENLANE_TAG = mpw5
OPENLANE_IMAGE_NAME = riscduino/openlane:$(OPENLANE_TAG)
OPENLANE_BASIC_COMMAND = "cd $(PWD)/../openlane && flow.tcl -design ./$* -save_path .. -save -tag $* -overwrite"
OPENLANE_INTERACTIVE_COMMAND = "cd $(PWD)/../openlane && flow.tcl -design ./$* -save_path .. -save -tag $* -overwrite -it -file ./$*/interactive.tcl"
diff --git a/openlane/pinmux/config.tcl b/openlane/pinmux/config.tcl
index 7650732..f844215 100755
--- a/openlane/pinmux/config.tcl
+++ b/openlane/pinmux/config.tcl
@@ -85,6 +85,9 @@
set ::env(PL_TARGET_DENSITY) "0.30"
set ::env(CELL_PAD) "4"
+set ::env(FP_IO_VEXTEND) {6}
+set ::env(FP_IO_HEXTEND) {6}
+
# helps in anteena fix
set ::env(USE_ARC_ANTENNA_CHECK) "0"
@@ -105,6 +108,6 @@
set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
-set ::env(QUIT_ON_MAGIC_DRC) "0"
-set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_MAGIC_DRC) "1"
+set ::env(QUIT_ON_LVS_ERROR) "1"
set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
diff --git a/openlane/qspim_top/config.tcl b/openlane/qspim_top/config.tcl
index f17f63d..187e486 100755
--- a/openlane/qspim_top/config.tcl
+++ b/openlane/qspim_top/config.tcl
@@ -101,5 +101,5 @@
set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
set ::env(QUIT_ON_MAGIC_DRC) "1"
-set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_LVS_ERROR) "1"
set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
diff --git a/openlane/uart_i2cm_usb_spi_top/config.tcl b/openlane/uart_i2cm_usb_spi_top/config.tcl
index a97080d..802f0cf 100644
--- a/openlane/uart_i2cm_usb_spi_top/config.tcl
+++ b/openlane/uart_i2cm_usb_spi_top/config.tcl
@@ -128,5 +128,5 @@
set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
set ::env(QUIT_ON_MAGIC_DRC) "1"
-set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_LVS_ERROR) "1"
set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
diff --git a/openlane/user_project_wrapper/config.tcl b/openlane/user_project_wrapper/config.tcl
index 1751888..e58ee59 100644
--- a/openlane/user_project_wrapper/config.tcl
+++ b/openlane/user_project_wrapper/config.tcl
@@ -148,72 +148,51 @@
set ::env(FP_PDN_POWER_STRAPS) "vccd1 vssd1 1, vccd2 vssd2 0, vdda1 vssa1 0, vdda2 vssa2 0"
-set ::env(FP_PDN_MACRO_HOOKS) " \
- u_intercon vccd1 vssd1,\
- u_pinmux vccd1 vssd1,\
- u_qspi_master vccd1 vssd1,\
- u_riscv_top vccd1 vssd1,\
- u_tsram0_2kb vccd1 vssd1,\
- u_icache_2kb vccd1 vssd1,\
- u_dcache_2kb vccd1 vssd1,\
- u_sram0_2kb vccd1 vssd1,\
- u_sram1_2kb vccd1 vssd1,\
- u_sram2_2kb vccd1 vssd1,\
- u_sram3_2kb vccd1 vssd1,\
- u_uart_i2c_usb_spi vccd1 vssd1,\
- u_wb_host vccd1 vssd1,\
- u_riscv_top.i_core_top_0 vccd1 vssd1, \
- u_riscv_top.i_core_top_1 vccd1 vssd1, \
- u_riscv_top.u_intf vccd1 vssd1 \
- "
+#set ::env(FP_PDN_MACRO_HOOKS) " \
+# u_intercon vccd1 vssd1,\
+# u_pinmux vccd1 vssd1,\
+# u_qspi_master vccd1 vssd1,\
+# u_riscv_top vccd1 vssd1,\
+# u_tsram0_2kb vccd1 vssd1,\
+# u_icache_2kb vccd1 vssd1,\
+# u_dcache_2kb vccd1 vssd1,\
+# u_sram0_2kb vccd1 vssd1,\
+# u_sram1_2kb vccd1 vssd1,\
+# u_sram2_2kb vccd1 vssd1,\
+# u_sram3_2kb vccd1 vssd1,\
+# u_uart_i2c_usb_spi vccd1 vssd1,\
+# u_wb_host vccd1 vssd1,\
+# u_riscv_top.i_core_top_0 vccd1 vssd1, \
+# u_riscv_top.i_core_top_1 vccd1 vssd1, \
+# u_riscv_top.u_intf vccd1 vssd1 \
+# "
# The following is because there are no std cells in the example wrapper project.
set ::env(SYNTH_TOP_LEVEL) 0
set ::env(PL_RANDOM_GLB_PLACEMENT) 1
-
set ::env(PL_RESIZER_DESIGN_OPTIMIZATIONS) 0
set ::env(PL_RESIZER_TIMING_OPTIMIZATIONS) 0
set ::env(PL_RESIZER_BUFFER_INPUT_PORTS) 0
set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0
-
set ::env(FP_PDN_ENABLE_RAILS) 0
-
set ::env(DIODE_INSERTION_STRATEGY) 0
set ::env(FILL_INSERTION) 0
set ::env(TAP_DECAP_INSERTION) 0
set ::env(CLOCK_TREE_SYNTH) 0
-
-set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_LVS_ERROR) "1"
set ::env(QUIT_ON_MAGIC_DRC) "0"
set ::env(QUIT_ON_NEGATIVE_WNS) "0"
set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
-
set ::env(FP_PDN_IRDROP) "0"
set ::env(FP_PDN_HORIZONTAL_HALO) "10"
set ::env(FP_PDN_VERTICAL_HALO) "10"
-
-#
-
-set ::env(FP_PDN_CORE_RING_HOFFSET) {12.45}
-set ::env(FP_PDN_CORE_RING_HSPACING) {1.7}
-set ::env(FP_PDN_CORE_RING_HWIDTH) {3.1}
-
-set ::env(FP_PDN_CORE_RING_VOFFSET) {12.45}
-set ::env(FP_PDN_CORE_RING_VSPACING) {1.7}
-set ::env(FP_PDN_CORE_RING_VWIDTH) {3.1}
-
-
set ::env(FP_PDN_VOFFSET) "5"
set ::env(FP_PDN_VPITCH) "80"
set ::env(FP_PDN_VSPACING) "15.5"
set ::env(FP_PDN_VWIDTH) "3.1"
-
set ::env(FP_PDN_HOFFSET) "10"
set ::env(FP_PDN_HPITCH) "90"
set ::env(FP_PDN_HSPACING) "10"
set ::env(FP_PDN_HWIDTH) "3.1"
-
-
-
diff --git a/openlane/user_project_wrapper/interactive.mpw4.tcl b/openlane/user_project_wrapper/interactive.mpw4.tcl
deleted file mode 100644
index 1c24305..0000000
--- a/openlane/user_project_wrapper/interactive.mpw4.tcl
+++ /dev/null
@@ -1,394 +0,0 @@
-#!/usr/bin/tclsh
-# SPDX-FileCopyrightText: 2020 Efabless Corporation
-# Copyright 2020 Efabless Corporation
-# Copyright 2020 Sylvain Munaut
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# SPDX-License-Identifier: Apache-2.0
-
-package require openlane;
-
-
-proc run_placement_step {args} {
- if { ! [ info exists ::env(PLACEMENT_CURRENT_DEF) ] } {
- set ::env(PLACEMENT_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(PLACEMENT_CURRENT_DEF)
- }
-
- run_placement
-}
-
-proc run_placement {args} {
- puts_info "Running Placement..."
-# |----------------------------------------------------|
-# |---------------- 3. PLACEMENT ------------------|
-# |----------------------------------------------------|
- set ::env(CURRENT_STAGE) placement
-
- if { [info exists ::env(PL_TARGET_DENSITY_CELLS)] } {
- set old_pl_target_density $::env(PL_TARGET_DENSITY)
- set ::env(PL_TARGET_DENSITY) $::env(PL_TARGET_DENSITY_CELLS)
- }
-
- if { $::env(PL_RANDOM_GLB_PLACEMENT) } {
- # useful for very tiny designs
- random_global_placement
- } else {
- global_placement_or
- }
-
- if { [info exists ::env(PL_TARGET_DENSITY_CELLS)] } {
- set ::env(PL_TARGET_DENSITY) $old_pl_target_density
- }
-
- run_resizer_design
-
- if { [info exists ::env(DONT_BUFFER_PORTS) ]} {
- remove_buffers
- }
- detailed_placement_or
- scrot_klayout -layout $::env(CURRENT_DEF)
-}
-
-
-proc run_cts_step {args} {
- if { ! [ info exists ::env(CTS_CURRENT_DEF) ] } {
- set ::env(CTS_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(CTS_CURRENT_DEF)
- }
-
- run_cts
- run_resizer_timing
-}
-
-proc run_routing_step {args} {
- if { ! [ info exists ::env(ROUTING_CURRENT_DEF) ] } {
- set ::env(ROUTING_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(ROUTING_CURRENT_DEF)
- }
- run_routing
-}
-
-proc run_diode_insertion_2_5_step {args} {
- if { ! [ info exists ::env(DIODE_INSERTION_CURRENT_DEF) ] } {
- set ::env(DIODE_INSERTION_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(DIODE_INSERTION_CURRENT_DEF)
- }
- if { ($::env(DIODE_INSERTION_STRATEGY) == 2) || ($::env(DIODE_INSERTION_STRATEGY) == 5) } {
- run_antenna_check
- heal_antenna_violators; # modifies the routed DEF
- }
-
-}
-
-proc run_power_pins_insertion_step {args} {
- # set_def $::env(tritonRoute_result_file_tag).def
- if { ! [ info exists ::env(POWER_PINS_INSERTION_CURRENT_DEF) ] } {
- set ::env(POWER_PINS_INSERTION_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(POWER_PINS_INSERTION_CURRENT_DEF)
- }
- if { $::env(LVS_INSERT_POWER_PINS) } {
- write_powered_verilog
- set_netlist $::env(lvs_result_file_tag).powered.v
- }
-
-}
-
-
-proc run_lvs_step {{ lvs_enabled 1 }} {
- if { ! [ info exists ::env(LVS_CURRENT_DEF) ] } {
- set ::env(LVS_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(LVS_CURRENT_DEF)
- }
- if { $lvs_enabled } {
- run_magic_spice_export
- run_lvs; # requires run_magic_spice_export
- }
-
-}
-
-proc run_drc_step {{ drc_enabled 1 }} {
- if { ! [ info exists ::env(DRC_CURRENT_DEF) ] } {
- set ::env(DRC_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(DRC_CURRENT_DEF)
- }
- if { $drc_enabled } {
- run_magic_drc
- run_klayout_drc
- }
-}
-
-proc run_antenna_check_step {{ antenna_check_enabled 1 }} {
- if { ! [ info exists ::env(ANTENNA_CHECK_CURRENT_DEF) ] } {
- set ::env(ANTENNA_CHECK_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(ANTENNA_CHECK_CURRENT_DEF)
- }
- if { $antenna_check_enabled } {
- run_antenna_check
- }
-}
-
-
-proc gen_pdn {args} {
- puts_info "Generating PDN..."
- TIMER::timer_start
-
- set ::env(SAVE_DEF) [index_file $::env(pdn_tmp_file_tag).def]
- set ::env(PGA_RPT_FILE) [index_file $::env(pdn_report_file_tag).pga.rpt]
-
- try_catch $::env(OPENROAD_BIN) -exit $::env(SCRIPTS_DIR)/openroad/pdn.tcl \
- |& tee $::env(TERMINAL_OUTPUT) [index_file $::env(pdn_log_file_tag).log 0]
-
-
- TIMER::timer_stop
- exec echo "[TIMER::get_runtime]" >> [index_file $::env(pdn_log_file_tag)_runtime.txt 0]
-
- quit_on_unconnected_pdn_nodes
-
- set_def $::env(SAVE_DEF)
-}
-
-proc run_power_grid_generation {args} {
-
- if {[info exists ::env(FP_PDN_POWER_STRAPS)]} {
- set power_domains [split $::env(FP_PDN_POWER_STRAPS) ","]
- }
-
- # internal macros power connections
- if {[info exists ::env(FP_PDN_MACRO_HOOKS)]} {
- set macro_hooks [dict create]
- set pdn_hooks [split $::env(FP_PDN_MACRO_HOOKS) ","]
- foreach pdn_hook $pdn_hooks {
- set instance_name [lindex $pdn_hook 0]
- set power_net [lindex $pdn_hook 1]
- set ground_net [lindex $pdn_hook 2]
- dict append macro_hooks $instance_name [subst {$power_net $ground_net}]
- }
-
- set power_net_indx [lsearch $::env(VDD_NETS) $power_net]
- set ground_net_indx [lsearch $::env(GND_NETS) $ground_net]
-
- # make sure that the specified power domains exist.
- if { $power_net_indx == -1 || $ground_net_indx == -1 || $power_net_indx != $ground_net_indx } {
- puts_err "Can't find $power_net and $ground_net domain. \
- Make sure that both exist in $::env(VDD_NETS) and $::env(GND_NETS)."
- }
- }
-
- # generate multiple power grids per pair of (VDD,GND)
- # offseted by WIDTH + SPACING
- foreach domain $power_domains {
- set ::env(VDD_NET) [lindex $domain 0]
- set ::env(GND_NET) [lindex $domain 1]
- set ::env(_WITH_STRAPS) [lindex $domain 2]
-
- puts_info "Connecting Power: $::env(VDD_NET) & $::env(GND_NET) to All internal macros."
- # internal macros power connections
- set ::env(FP_PDN_MACROS) ""
- if { $::env(FP_PDN_ENABLE_MACROS_GRID) == 1 } {
- # if macros connections to power are explicitly set
- # default behavoir macro pins will be connected to the first power domain
- if { [info exists ::env(FP_PDN_MACRO_HOOKS)] } {
- set ::env(FP_PDN_ENABLE_MACROS_GRID) 0
- foreach {instance_name hooks} $macro_hooks {
- set power [lindex $hooks 0]
- set ground [lindex $hooks 1]
- if { $power == $::env(VDD_NET) && $ground == $::env(GND_NET) } {
- set ::env(FP_PDN_ENABLE_MACROS_GRID) 1
- set ::env(FP_PDN_IRDROP) "1"
- puts_info "Connecting $instance_name to $power and $ground nets."
- lappend ::env(FP_PDN_MACROS) $instance_name
- }
- }
- }
- } else {
- puts_warn "All internal macros will not be connected to power $::env(VDD_NET) & $::env(GND_NET)."
- }
-
- gen_pdn
-
- set ::env(FP_PDN_ENABLE_RAILS) 0
- set ::env(FP_PDN_ENABLE_MACROS_GRID) 0
- set ::env(FP_PDN_IRDROP) "0"
-
- # allow failure until open_pdks is up to date...
- catch {set ::env(FP_PDN_VOFFSET) [expr $::env(FP_PDN_VOFFSET)+$::env(FP_PDN_VWIDTH)+$::env(FP_PDN_VSPACING)]}
- catch {set ::env(FP_PDN_HOFFSET) [expr $::env(FP_PDN_HOFFSET)+$::env(FP_PDN_HWIDTH)+$::env(FP_PDN_HSPACING)]}
-
- catch {set ::env(FP_PDN_CORE_RING_VOFFSET) \
- [expr $::env(FP_PDN_CORE_RING_VOFFSET)\
- +2*($::env(FP_PDN_CORE_RING_VWIDTH)\
- +max($::env(FP_PDN_CORE_RING_VSPACING), $::env(FP_PDN_CORE_RING_HSPACING)))]}
- catch {set ::env(FP_PDN_CORE_RING_HOFFSET) [expr $::env(FP_PDN_CORE_RING_HOFFSET)\
- +2*($::env(FP_PDN_CORE_RING_HWIDTH)+\
- max($::env(FP_PDN_CORE_RING_VSPACING), $::env(FP_PDN_CORE_RING_HSPACING)))]}
- puts "FP_PDN_VOFFSET: $::env(FP_PDN_VOFFSET)"
- puts "FP_PDN_HOFFSET: $::env(FP_PDN_HOFFSET)"
- puts "FP_PDN_CORE_RING_VOFFSET: $::env(FP_PDN_CORE_RING_VOFFSET)"
- puts "FP_PDN_CORE_RING_HOFFSET: $::env(FP_PDN_CORE_RING_HOFFSET)"
-
- }
- set ::env(FP_PDN_ENABLE_RAILS) 1
-}
-
-
-proc run_floorplan {args} {
- puts_info "Running Floorplanning..."
- # |----------------------------------------------------|
- # |---------------- 2. FLOORPLAN ------------------|
- # |----------------------------------------------------|
- #
- # intial fp
- init_floorplan
-
-
- # place io
- if { [info exists ::env(FP_PIN_ORDER_CFG)] } {
- place_io_ol
- } else {
- if { [info exists ::env(FP_CONTEXT_DEF)] && [info exists ::env(FP_CONTEXT_LEF)] } {
- place_io
- global_placement_or
- place_contextualized_io \
- -lef $::env(FP_CONTEXT_LEF) \
- -def $::env(FP_CONTEXT_DEF)
- } else {
- place_io
- }
- }
-
- apply_def_template
-
- if { [info exist ::env(EXTRA_LEFS)] } {
- if { [info exist ::env(MACRO_PLACEMENT_CFG)] } {
- file copy -force $::env(MACRO_PLACEMENT_CFG) $::env(TMP_DIR)/macro_placement.cfg
- manual_macro_placement f
- } else {
- global_placement_or
- basic_macro_placement
- }
- }
-
- # tapcell
- tap_decap_or
- scrot_klayout -layout $::env(CURRENT_DEF)
- # power grid generation
- run_power_grid_generation
-}
-
-
-proc run_flow {args} {
- set script_dir [file dirname [file normalize [info script]]]
-
- set options {
- {-design required}
- {-save_path optional}
- {-no_lvs optional}
- {-no_drc optional}
- {-no_antennacheck optional}
- }
- set flags {-save}
- parse_key_args "run_flow" args arg_values $options flags_map $flags -no_consume
-
- prep {*}$args
-
- set LVS_ENABLED 1
- set DRC_ENABLED 0
- set ANTENNACHECK_ENABLED 1
-
- set steps [dict create \
- "synthesis" {run_synthesis "" } \
- "floorplan" {run_floorplan ""} \
- "placement" {run_placement_step ""} \
- "cts" {run_cts_step ""} \
- "routing" {run_routing_step ""} \
- "diode_insertion" {run_diode_insertion_2_5_step ""} \
- "power_pins_insertion" {run_power_pins_insertion_step ""} \
- "gds_magic" {run_magic ""} \
- "gds_drc_klayout" {run_klayout ""} \
- "gds_xor_klayout" {run_klayout_gds_xor ""} \
- "lvs" "run_lvs_step $LVS_ENABLED" \
- "drc" "run_drc_step $DRC_ENABLED" \
- "antenna_check" "run_antenna_check_step $ANTENNACHECK_ENABLED" \
- "cvc" {run_lef_cvc}
- ]
-
- set_if_unset arg_values(-to) "cvc";
-
- if { [info exists ::env(CURRENT_STEP) ] } {
- puts "\[INFO\]:Picking up where last execution left off"
- puts [format "\[INFO\]:Current stage is %s " $::env(CURRENT_STEP)]
- } else {
- set ::env(CURRENT_STEP) "synthesis";
- }
- set_if_unset arg_values(-from) $::env(CURRENT_STEP);
- set exe 0;
- dict for {step_name step_exe} $steps {
- if { [ string equal $arg_values(-from) $step_name ] } {
- set exe 1;
- }
-
- if { $exe } {
- # For when it fails
- set ::env(CURRENT_STEP) $step_name
- [lindex $step_exe 0] [lindex $step_exe 1] ;
- }
-
- if { [ string equal $arg_values(-to) $step_name ] } {
- set exe 0:
- break;
- }
-
- }
-
- # for when it resumes
- set steps_as_list [dict keys $steps]
- set next_idx [expr [lsearch $steps_as_list $::env(CURRENT_STEP)] + 1]
- set ::env(CURRENT_STEP) [lindex $steps_as_list $next_idx]
-
- if { [info exists flags_map(-save) ] } {
- if { ! [info exists arg_values(-save_path)] } {
- set arg_values(-save_path) ""
- }
- save_views -lef_path $::env(magic_result_file_tag).lef \
- -def_path $::env(CURRENT_DEF) \
- -gds_path $::env(magic_result_file_tag).gds \
- -mag_path $::env(magic_result_file_tag).mag \
- -maglef_path $::env(magic_result_file_tag).lef.mag \
- -spice_path $::env(magic_result_file_tag).spice \
- -spef_path $::env(CURRENT_SPEF) \
- -verilog_path $::env(CURRENT_NETLIST) \
- -save_path $arg_values(-save_path) \
- -tag $::env(RUN_TAG)
- }
-
-
- calc_total_runtime
- save_state
- generate_final_summary_report
-
- check_timing_violations
-
- puts_success "Flow Completed Without Fatal Errors."
-
-}
-
-run_flow {*}$argv
diff --git a/openlane/user_project_wrapper/interactive.tcl b/openlane/user_project_wrapper/interactive.tcl
index 07190b7..ccfa729 100644
--- a/openlane/user_project_wrapper/interactive.tcl
+++ b/openlane/user_project_wrapper/interactive.tcl
@@ -15,149 +15,100 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# SPDX-License-Identifier: Apache-2.0
-
package require openlane;
-
proc run_placement_step {args} {
- if { ! [ info exists ::env(PLACEMENT_CURRENT_DEF) ] } {
- set ::env(PLACEMENT_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(PLACEMENT_CURRENT_DEF)
- }
-
- run_placement
+ if { ! [ info exists ::env(PLACEMENT_CURRENT_DEF) ] } {
+ set ::env(PLACEMENT_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(PLACEMENT_CURRENT_DEF)
+ }
+ run_placement
}
-
proc run_cts_step {args} {
- if { ! [ info exists ::env(CTS_CURRENT_DEF) ] } {
- set ::env(CTS_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(CTS_CURRENT_DEF)
- }
-
- run_cts
- run_resizer_timing
+ if { ! [ info exists ::env(CTS_CURRENT_DEF) ] } {
+ set ::env(CTS_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(CTS_CURRENT_DEF)
+ }
+ run_cts
+ run_resizer_timing
}
-
proc run_routing_step {args} {
- if { ! [ info exists ::env(ROUTING_CURRENT_DEF) ] } {
- set ::env(ROUTING_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(ROUTING_CURRENT_DEF)
- }
- run_routing
+ if { ! [ info exists ::env(ROUTING_CURRENT_DEF) ] } {
+ set ::env(ROUTING_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(ROUTING_CURRENT_DEF)
+ }
+ run_routing
}
-
-proc run_parasitics_sta_step {args} {
- if { ! [ info exists ::env(PARSITICS_CURRENT_DEF) ] } {
- set ::env(PARSITICS_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(PARSITICS_CURRENT_DEF)
- }
-
- if { $::env(RUN_SPEF_EXTRACTION) } {
- run_parasitics_sta
- }
-}
-
proc run_diode_insertion_2_5_step {args} {
- if { ! [ info exists ::env(DIODE_INSERTION_CURRENT_DEF) ] } {
- set ::env(DIODE_INSERTION_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(DIODE_INSERTION_CURRENT_DEF)
- }
+ if { ! [ info exists ::env(DIODE_INSERTION_CURRENT_DEF) ] } {
+ set ::env(DIODE_INSERTION_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(DIODE_INSERTION_CURRENT_DEF)
+ }
if { ($::env(DIODE_INSERTION_STRATEGY) == 2) || ($::env(DIODE_INSERTION_STRATEGY) == 5) } {
run_antenna_check
heal_antenna_violators; # modifies the routed DEF
}
-
}
-
proc run_lvs_step {{ lvs_enabled 1 }} {
- if { ! [ info exists ::env(LVS_CURRENT_DEF) ] } {
- set ::env(LVS_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(LVS_CURRENT_DEF)
- }
-
- if { $lvs_enabled && $::env(RUN_LVS) } {
- run_magic_spice_export;
+ if { ! [ info exists ::env(LVS_CURRENT_DEF) ] } {
+ set ::env(LVS_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(LVS_CURRENT_DEF)
+ }
+ if { $lvs_enabled } {
+ run_magic_spice_export
run_lvs; # requires run_magic_spice_export
}
-
}
-
proc run_drc_step {{ drc_enabled 1 }} {
- if { ! [ info exists ::env(DRC_CURRENT_DEF) ] } {
- set ::env(DRC_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(DRC_CURRENT_DEF)
- }
+ if { ! [ info exists ::env(DRC_CURRENT_DEF) ] } {
+ set ::env(DRC_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(DRC_CURRENT_DEF)
+ }
if { $drc_enabled } {
- if { $::env(RUN_MAGIC_DRC) } {
- run_magic_drc
- }
- if {$::env(RUN_KLAYOUT_DRC)} {
- run_klayout_drc
- }
+ run_magic_drc
+ run_klayout_drc
}
}
-
proc run_antenna_check_step {{ antenna_check_enabled 1 }} {
- if { ! [ info exists ::env(ANTENNA_CHECK_CURRENT_DEF) ] } {
- set ::env(ANTENNA_CHECK_CURRENT_DEF) $::env(CURRENT_DEF)
- } else {
- set ::env(CURRENT_DEF) $::env(ANTENNA_CHECK_CURRENT_DEF)
- }
+ if { ! [ info exists ::env(ANTENNA_CHECK_CURRENT_DEF) ] } {
+ set ::env(ANTENNA_CHECK_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(ANTENNA_CHECK_CURRENT_DEF)
+ }
if { $antenna_check_enabled } {
run_antenna_check
}
}
-
proc run_eco_step {args} {
if { $::env(ECO_ENABLE) == 1 } {
- run_eco_flow
- }
+ run_eco
+ }
}
-
-proc run_magic_step {args} {
- if {$::env(RUN_MAGIC)} {
- run_magic
- }
-}
-
-proc run_klayout_step {args} {
- if {$::env(RUN_KLAYOUT)} {
- run_klayout
- }
- if {$::env(RUN_KLAYOUT_XOR)} {
- run_klayout_gds_xor
- }
-}
-
proc save_final_views {args} {
set options {
{-save_path optional}
}
set flags {}
parse_key_args "save_final_views" args arg_values $options flags_map $flags
-
set arg_list [list]
-
# If they don't exist, save_views will simply not copy them
- lappend arg_list -lef_path $::env(signoff_results)/$::env(DESIGN_NAME).lef
- lappend arg_list -gds_path $::env(signoff_results)/$::env(DESIGN_NAME).gds
- lappend arg_list -mag_path $::env(signoff_results)/$::env(DESIGN_NAME).mag
- lappend arg_list -maglef_path $::env(signoff_results)/$::env(DESIGN_NAME).lef.mag
- lappend arg_list -spice_path $::env(signoff_results)/$::env(DESIGN_NAME).spice
-
+ lappend arg_list -lef_path $::env(finishing_results)/$::env(DESIGN_NAME).lef
+ lappend arg_list -gds_path $::env(finishing_results)/$::env(DESIGN_NAME).gds
+ lappend arg_list -mag_path $::env(finishing_results)/$::env(DESIGN_NAME).mag
+ lappend arg_list -maglef_path $::env(finishing_results)/$::env(DESIGN_NAME).lef.mag
+ lappend arg_list -spice_path $::env(finishing_results)/$::env(DESIGN_NAME).spice
+
# Guaranteed to have default values
lappend arg_list -def_path $::env(CURRENT_DEF)
lappend arg_list -verilog_path $::env(CURRENT_NETLIST)
-
# Not guaranteed to have default values
- if { [info exists ::env(CURRENT_SPEF)] } {
- lappend arg_list -spef_path $::env(CURRENT_SPEF)
+ if { [info exists ::env(SPEF_TYPICAL)] } {
+ lappend arg_list -spef_path $::env(SPEF_TYPICAL)
}
if { [info exists ::env(CURRENT_SDF)] } {
lappend arg_list -sdf_path $::env(CURRENT_SDF)
@@ -165,17 +116,13 @@
if { [info exists ::env(CURRENT_SDC)] } {
lappend arg_list -sdc_path $::env(CURRENT_SDC)
}
-
# Add the path if it exists...
if { [info exists arg_values(-save_path) ] } {
lappend arg_list -save_path $arg_values(-save_path)
}
-
# Aaand fire!
save_views {*}$arg_list
-
}
-
proc run_post_run_hooks {} {
if { [file exists $::env(DESIGN_DIR)/hooks/post_run.py]} {
puts_info "Running post run hook"
@@ -185,72 +132,24 @@
puts_info "hooks/post_run.py not found, skipping"
}
}
-
proc gen_pdn {args} {
- increment_index
- TIMER::timer_start
puts_info "Generating PDN..."
-
- set ::env(SAVE_DEF) [index_file $::env(floorplan_tmpfiles)/pdn.def]
- set ::env(PGA_RPT_FILE) [index_file $::env(floorplan_tmpfiles)/pdn.pga.rpt]
-
+ TIMER::timer_start
+
+ set ::env(SAVE_DEF) [index_file $::env(floorplan_tmpfiles).def]
+ set ::env(PGA_RPT_FILE) [index_file $::env(floorplan_tmpfiles).pga.rpt]
run_openroad_script $::env(SCRIPTS_DIR)/openroad/pdn.tcl \
|& -indexed_log [index_file $::env(floorplan_logs)/pdn.log]
-
-
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "pdn generation - openroad"
-
quit_on_unconnected_pdn_nodes
-
set_def $::env(SAVE_DEF)
}
-
proc run_power_grid_generation {args} {
- if { [info exists ::env(VDD_NETS)] || [info exists ::env(GND_NETS)] } {
- # they both must exist and be equal in length
- # current assumption: they cannot have a common ground
- if { ! [info exists ::env(VDD_NETS)] || ! [info exists ::env(GND_NETS)] } {
- puts_err "VDD_NETS and GND_NETS must *both* either be defined or undefined"
- return -code error
- }
- # standard cell power and ground nets are assumed to be the first net
- set ::env(VDD_PIN) [lindex $::env(VDD_NETS) 0]
- set ::env(GND_PIN) [lindex $::env(GND_NETS) 0]
- } elseif { [info exists ::env(SYNTH_USE_PG_PINS_DEFINES)] } {
- set ::env(VDD_NETS) [list]
- set ::env(GND_NETS) [list]
- # get the pins that are in $synthesis_tmpfiles.pg_define.v
- # that are not in $synthesis_results.v
- #
- set full_pins {*}[extract_pins_from_yosys_netlist $::env(synthesis_tmpfiles)/pg_define.v]
- puts_info $full_pins
-
- set non_pg_pins {*}[extract_pins_from_yosys_netlist $::env(synthesis_results)/$::env(DESIGN_NAME).v]
- puts_info $non_pg_pins
-
- # assumes the pins are ordered correctly (e.g., vdd1, vss1, vcc1, vss1, ...)
- foreach {vdd gnd} $full_pins {
- if { $vdd ne "" && $vdd ni $non_pg_pins } {
- lappend ::env(VDD_NETS) $vdd
- }
- if { $gnd ne "" && $gnd ni $non_pg_pins } {
- lappend ::env(GND_NETS) $gnd
- }
- }
- } else {
- set ::env(VDD_NETS) $::env(VDD_PIN)
- set ::env(GND_NETS) $::env(GND_PIN)
+ if {[info exists ::env(FP_PDN_POWER_STRAPS)]} {
+ set power_domains [split $::env(FP_PDN_POWER_STRAPS) ","]
}
-
- puts_info "Power planning with power {$::env(VDD_NETS)} and ground {$::env(GND_NETS)}..."
-
- if { [llength $::env(VDD_NETS)] != [llength $::env(GND_NETS)] } {
- puts_err "VDD_NETS and GND_NETS must be of equal lengths"
- return -code error
- }
-
- # check internal macros' power connection definitions
+ # internal macros power connections
if {[info exists ::env(FP_PDN_MACRO_HOOKS)]} {
set macro_hooks [dict create]
set pdn_hooks [split $::env(FP_PDN_MACRO_HOOKS) ","]
@@ -260,20 +159,66 @@
set ground_net [lindex $pdn_hook 2]
dict append macro_hooks $instance_name [subst {$power_net $ground_net}]
}
-
+
set power_net_indx [lsearch $::env(VDD_NETS) $power_net]
set ground_net_indx [lsearch $::env(GND_NETS) $ground_net]
-
# make sure that the specified power domains exist.
if { $power_net_indx == -1 || $ground_net_indx == -1 || $power_net_indx != $ground_net_indx } {
puts_err "Can't find $power_net and $ground_net domain. \
- Make sure that both exist in $::env(VDD_NETS) and $::env(GND_NETS)."
- }
+ Make sure that both exist in $::env(VDD_NETS) and $::env(GND_NETS)."
+ }
}
-
- gen_pdn
+
+ # generate multiple power grids per pair of (VDD,GND)
+ # offseted by WIDTH + SPACING
+ foreach domain $power_domains {
+ set ::env(VDD_NET) [lindex $domain 0]
+ set ::env(GND_NET) [lindex $domain 1]
+ set ::env(_WITH_STRAPS) [lindex $domain 2]
+ puts_info "Connecting Power: $::env(VDD_NET) & $::env(GND_NET) to All internal macros."
+ # internal macros power connections
+ set ::env(FP_PDN_MACROS) ""
+ if { $::env(FP_PDN_ENABLE_MACROS_GRID) == 1 } {
+ # if macros connections to power are explicitly set
+ # default behavoir macro pins will be connected to the first power domain
+ if { [info exists ::env(FP_PDN_MACRO_HOOKS)] } {
+ set ::env(FP_PDN_ENABLE_MACROS_GRID) 0
+ foreach {instance_name hooks} $macro_hooks {
+ set power [lindex $hooks 0]
+ set ground [lindex $hooks 1]
+ if { $power == $::env(VDD_NET) && $ground == $::env(GND_NET) } {
+ set ::env(FP_PDN_ENABLE_MACROS_GRID) 1
+ set ::env(FP_PDN_IRDROP) "0"
+ puts_info "Connecting $instance_name to $power and $ground nets."
+ lappend ::env(FP_PDN_MACROS) $instance_name
+ }
+ }
+ }
+ } else {
+ puts_warn "All internal macros will not be connected to power $::env(VDD_NET) & $::env(GND_NET)."
+ }
+
+ gen_pdn
+ set ::env(FP_PDN_ENABLE_RAILS) 0
+ set ::env(FP_PDN_ENABLE_MACROS_GRID) 0
+ set ::env(FP_PDN_IRDROP) "0"
+ # allow failure until open_pdks is up to date...
+ catch {set ::env(FP_PDN_VOFFSET) [expr $::env(FP_PDN_VOFFSET)+$::env(FP_PDN_VWIDTH)+$::env(FP_PDN_VSPACING)]}
+ catch {set ::env(FP_PDN_HOFFSET) [expr $::env(FP_PDN_HOFFSET)+$::env(FP_PDN_HWIDTH)+$::env(FP_PDN_HSPACING)]}
+ catch {set ::env(FP_PDN_CORE_RING_VOFFSET) \
+ [expr $::env(FP_PDN_CORE_RING_VOFFSET)\
+ +2*($::env(FP_PDN_CORE_RING_VWIDTH)\
+ +max($::env(FP_PDN_CORE_RING_VSPACING), $::env(FP_PDN_CORE_RING_HSPACING)))]}
+ catch {set ::env(FP_PDN_CORE_RING_HOFFSET) [expr $::env(FP_PDN_CORE_RING_HOFFSET)\
+ +2*($::env(FP_PDN_CORE_RING_HWIDTH)+\
+ max($::env(FP_PDN_CORE_RING_VSPACING), $::env(FP_PDN_CORE_RING_HSPACING)))]}
+ puts "FP_PDN_VOFFSET: $::env(FP_PDN_VOFFSET)"
+ puts "FP_PDN_HOFFSET: $::env(FP_PDN_HOFFSET)"
+ puts "FP_PDN_CORE_RING_VOFFSET: $::env(FP_PDN_CORE_RING_VOFFSET)"
+ puts "FP_PDN_CORE_RING_HOFFSET: $::env(FP_PDN_CORE_RING_HOFFSET)"
+ }
+ set ::env(FP_PDN_ENABLE_RAILS) 1
}
-
proc run_floorplan {args} {
puts_info "Running Floorplanning..."
# |----------------------------------------------------|
@@ -282,7 +227,6 @@
#
# intial fp
init_floorplan
-
# check for deprecated io variables
if { [info exists ::env(FP_IO_HMETAL)]} {
set ::env(FP_IO_HLAYER) [lindex $::env(TECH_METAL_LAYERS) [expr {$::env(FP_IO_HMETAL) - 1}]]
@@ -290,15 +234,12 @@
puts_warn "We recommend you update your configuration as follows:"
puts_warn "\tset ::env(FP_IO_HLAYER) {$::env(FP_IO_HLAYER)}"
}
-
if { [info exists ::env(FP_IO_VMETAL)]} {
set ::env(FP_IO_VLAYER) [lindex $::env(TECH_METAL_LAYERS) [expr {$::env(FP_IO_VMETAL) - 1}]]
puts_warn "You're using FP_IO_VMETAL in your configuration, which is a deprecated variable that will be removed in the future."
puts_warn "We recommend you update your configuration as follows:"
puts_warn "\tset ::env(FP_IO_VLAYER) {$::env(FP_IO_VLAYER)}"
}
-
-
# place io
if { [info exists ::env(FP_PIN_ORDER_CFG)] } {
place_io_ol
@@ -313,9 +254,7 @@
place_io
}
}
-
apply_def_template
-
if { [info exist ::env(EXTRA_LEFS)] } {
if { [info exist ::env(MACRO_PLACEMENT_CFG)] } {
file copy -force $::env(MACRO_PLACEMENT_CFG) $::env(placement_tmpfiles)/macro_placement.cfg
@@ -325,15 +264,10 @@
basic_macro_placement
}
}
-
tap_decap_or
-
scrot_klayout -layout $::env(CURRENT_DEF) $::env(floorplan_logs)/screenshot.log
-
run_power_grid_generation
}
-
-
proc run_flow {args} {
set options {
{-design required}
@@ -346,11 +280,6 @@
parse_key_args "run_non_interactive_mode" args arg_values $options flags_map $flags -no_consume
prep {*}$args
# signal trap SIGINT save_state;
-
- if { [info exists flags_map(-gui)] } {
- or_gui
- return
- }
if { [info exists arg_values(-override_env)] } {
set env_overrides [split $arg_values(-override_env) ',']
foreach override $env_overrides {
@@ -360,67 +289,56 @@
set ::env(${key}) $value
}
}
-
set LVS_ENABLED 1
set DRC_ENABLED 0
set ANTENNACHECK_ENABLED 1
-
- set steps [dict create \
- "synthesis" "run_synthesis" \
- "floorplan" "run_floorplan" \
- "placement" "run_placement_step" \
- "cts" "run_cts_step" \
- "routing" "run_routing_step" \
- "parasitics_sta" "run_parasitics_sta_step" \
- "eco" "run_eco_step" \
- "diode_insertion" "run_diode_insertion_2_5_step" \
- "gds_magic" "run_magic_step" \
- "gds_klayout" "run_klayout_step" \
- "lvs" "run_lvs_step $LVS_ENABLED " \
- "drc" "run_drc_step $DRC_ENABLED " \
- "antenna_check" "run_antenna_check_step $ANTENNACHECK_ENABLED " \
- "cvc" "run_lef_cvc"
- ]
-
+ set steps [dict create \
+ "synthesis" {run_synthesis "" } \
+ "floorplan" {run_floorplan ""} \
+ "placement" {run_placement_step ""} \
+ "cts" {run_cts_step ""} \
+ "routing" {run_routing_step ""}\
+ "eco" {run_eco_step ""} \
+ "diode_insertion" {run_diode_insertion_2_5_step ""} \
+ "gds_magic" {run_magic ""} \
+ "gds_drc_klayout" {run_klayout ""} \
+ "gds_xor_klayout" {run_klayout_gds_xor ""} \
+ "lvs" "run_lvs_step $LVS_ENABLED" \
+ "drc" "run_drc_step $DRC_ENABLED" \
+ "antenna_check" "run_antenna_check_step $ANTENNACHECK_ENABLED" \
+ "cvc" {run_lef_cvc}
+ ]
set_if_unset arg_values(-to) "cvc";
-
if { [info exists ::env(CURRENT_STEP) ] } {
puts "\[INFO\]:Picking up where last execution left off"
puts [format "\[INFO\]:Current stage is %s " $::env(CURRENT_STEP)]
} else {
set ::env(CURRENT_STEP) "synthesis";
}
-
set_if_unset arg_values(-from) $::env(CURRENT_STEP);
set exe 0;
dict for {step_name step_exe} $steps {
if { [ string equal $arg_values(-from) $step_name ] } {
set exe 1;
}
-
if { $exe } {
# For when it fails
set ::env(CURRENT_STEP) $step_name
[lindex $step_exe 0] [lindex $step_exe 1] ;
}
-
if { [ string equal $arg_values(-to) $step_name ] } {
set exe 0:
break;
}
-
}
-
# for when it resumes
set steps_as_list [dict keys $steps]
set next_idx [expr [lsearch $steps_as_list $::env(CURRENT_STEP)] + 1]
set ::env(CURRENT_STEP) [lindex $steps_as_list $next_idx]
-
# Saves to <RUN_DIR>/results/final
if { $::env(SAVE_FINAL_VIEWS) == "1" } {
save_final_views
}
-
# Saves to design directory or custom
if { [info exists flags_map(-save) ] } {
if { ! [info exists arg_values(-save_path)] } {
@@ -448,9 +366,6 @@
}
puts_success "Flow complete."
-
show_warnings "Note that the following warnings have been generated:"
-
}
-
run_flow {*}$argv
diff --git a/openlane/user_project_wrapper/mpw5/config.tcl b/openlane/user_project_wrapper/mpw5/config.tcl
new file mode 100644
index 0000000..e58ee59
--- /dev/null
+++ b/openlane/user_project_wrapper/mpw5/config.tcl
@@ -0,0 +1,198 @@
+# SPDX-FileCopyrightText: 2020 Efabless Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# SPDX-License-Identifier: Apache-2.0
+
+# Base Configurations. Don't Touch
+# section begin
+
+set ::env(PDK) "sky130A"
+set ::env(STD_CELL_LIBRARY) "sky130_fd_sc_hd"
+
+# YOU ARE NOT ALLOWED TO CHANGE ANY VARIABLES DEFINED IN THE FIXED WRAPPER CFGS
+source $::env(CARAVEL_ROOT)/openlane/user_project_wrapper/fixed_wrapper_cfgs.tcl
+
+
+# YOU CAN CHANGE ANY VARIABLES DEFINED IN THE DEFAULT WRAPPER CFGS BY OVERRIDING THEM IN THIS CONFIG.TCL
+source $::env(CARAVEL_ROOT)/openlane/user_project_wrapper/default_wrapper_cfgs.tcl
+
+
+set script_dir [file dirname [file normalize [info script]]]
+set proj_dir [file dirname [file normalize [info script]]]
+
+set ::env(DESIGN_NAME) user_project_wrapper
+set verilog_root $proj_dir/../../verilog/
+set lef_root $proj_dir/../../lef/
+set gds_root $proj_dir/../../gds/
+#section end
+
+# User Configurations
+#
+set ::env(DESIGN_IS_CORE) 1
+set ::env(FP_PDN_CORE_RING) 1
+
+
+## Source Verilog Files
+set ::env(VERILOG_FILES) "\
+ $proj_dir/../../verilog/rtl//yifive/ycr2c/src/top/ycr2_top_wb.sv \
+ $proj_dir/../../verilog/rtl/user_project_wrapper.v"
+
+
+## Clock configurations
+set ::env(CLOCK_PORT) "user_clock2 wb_clk_i"
+#set ::env(CLOCK_NET) "mprj.clk"
+
+set ::env(CLOCK_PERIOD) "10"
+
+## Internal Macros
+### Macro Placement
+set ::env(FP_SIZING) "absolute"
+set ::env(MACRO_PLACEMENT_CFG) $proj_dir/macro.cfg
+
+set ::env(PDN_CFG) $proj_dir/pdn_cfg.tcl
+
+set ::env(SDC_FILE) "$proj_dir/base.sdc"
+set ::env(BASE_SDC_FILE) "$proj_dir/base.sdc"
+
+set ::env(SYNTH_READ_BLACKBOX_LIB) 1
+
+### Black-box verilog and views
+set ::env(VERILOG_FILES_BLACKBOX) "\
+ $proj_dir/../../verilog/gl/qspim_top.v \
+ $proj_dir/../../verilog/gl/wb_interconnect.v \
+ $proj_dir/../../verilog/gl/pinmux.v \
+ $proj_dir/../../verilog/gl/uart_i2c_usb_spi_top.v \
+ $proj_dir/../../verilog/gl/wb_host.v \
+ $proj_dir/../../verilog/gl/ycr_intf.v \
+ $proj_dir/../../verilog/gl/ycr_core_top.v \
+ $proj_dir/../../verilog/gl/ycr2_iconnect.v \
+ $proj_dir/../../verilog/gl/digital_pll.v \
+ $::env(PDK_ROOT)/sky130A/libs.ref/sky130_sram_macros/verilog/sky130_sram_2kbyte_1rw1r_32x512_8.v \
+ "
+
+set ::env(EXTRA_LEFS) "\
+ $lef_root/qspim_top.lef \
+ $lef_root/pinmux.lef \
+ $lef_root/wb_interconnect.lef \
+ $lef_root/uart_i2c_usb_spi_top.lef \
+ $lef_root/wb_host.lef \
+ $lef_root/ycr_intf.lef \
+ $lef_root/ycr_core_top.lef \
+ $lef_root/ycr2_iconnect.lef \
+ $lef_root/digital_pll.lef \
+ $::env(PDK_ROOT)/sky130A/libs.ref/sky130_sram_macros/lef/sky130_sram_2kbyte_1rw1r_32x512_8.lef \
+ "
+
+set ::env(EXTRA_GDS_FILES) "\
+ $gds_root/qspim_top.gds \
+ $gds_root/pinmux.gds \
+ $gds_root/wb_interconnect.gds \
+ $gds_root/uart_i2c_usb_spi_top.gds \
+ $gds_root/wb_host.gds \
+ $gds_root/ycr_intf.gds \
+ $gds_root/ycr_core_top.gds \
+ $gds_root/ycr2_iconnect.gds \
+ $gds_root/digital_pll.gds \
+ $::env(PDK_ROOT)/sky130A/libs.ref/sky130_sram_macros/gds/sky130_sram_2kbyte_1rw1r_32x512_8.gds \
+ "
+
+set ::env(SYNTH_DEFINES) [list SYNTHESIS ]
+
+set ::env(VERILOG_INCLUDE_DIRS) [glob $script_dir/../../verilog/rtl/yifive/ycr2c/src/includes ]
+
+#set ::env(GLB_RT_MAXLAYER) 6
+set ::env(RT_MAX_LAYER) {met5}
+
+set ::env(FP_PDN_CHECK_NODES) 0
+
+
+## Internal Macros
+### Macro PDN Connections
+set ::env(FP_PDN_ENABLE_MACROS_GRID) "1"
+set ::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS) "1"
+
+set ::env(VDD_NETS) {vccd1 vccd2 vdda1 vdda2}
+set ::env(GND_NETS) {vssd1 vssd2 vssa1 vssa2}
+#
+set ::env(VDD_PIN) {vccd1}
+set ::env(GND_PIN) {vssd1}
+
+set ::env(GLB_RT_OBS) " \
+ li1 150 130 833.1 546.54,\
+ met1 150 130 833.1 546.54,\
+ met2 150 130 833.1 546.54,\
+ met3 150 130 833.1 546.54,\
+
+ li1 950 130 1633.1 546.54,\
+ met1 950 130 1633.1 546.54,\
+ met2 950 130 1633.1 546.54,\
+ met3 950 130 1633.1 546.54,\
+
+ li1 150 750 833.1 1166.54,\
+ met1 150 750 833.1 1166.54,\
+ met2 150 750 833.1 1166.54,\
+ met3 150 750 833.1 1166.54,\
+ met1 950 650 1760 660 ,\
+ met3 950 650 1760 660 ,\
+ met5 0 0 2920 3520"
+
+set ::env(FP_PDN_POWER_STRAPS) "vccd1 vssd1 1, vccd2 vssd2 0, vdda1 vssa1 0, vdda2 vssa2 0"
+
+#set ::env(FP_PDN_MACRO_HOOKS) " \
+# u_intercon vccd1 vssd1,\
+# u_pinmux vccd1 vssd1,\
+# u_qspi_master vccd1 vssd1,\
+# u_riscv_top vccd1 vssd1,\
+# u_tsram0_2kb vccd1 vssd1,\
+# u_icache_2kb vccd1 vssd1,\
+# u_dcache_2kb vccd1 vssd1,\
+# u_sram0_2kb vccd1 vssd1,\
+# u_sram1_2kb vccd1 vssd1,\
+# u_sram2_2kb vccd1 vssd1,\
+# u_sram3_2kb vccd1 vssd1,\
+# u_uart_i2c_usb_spi vccd1 vssd1,\
+# u_wb_host vccd1 vssd1,\
+# u_riscv_top.i_core_top_0 vccd1 vssd1, \
+# u_riscv_top.i_core_top_1 vccd1 vssd1, \
+# u_riscv_top.u_intf vccd1 vssd1 \
+# "
+
+
+# The following is because there are no std cells in the example wrapper project.
+set ::env(SYNTH_TOP_LEVEL) 0
+set ::env(PL_RANDOM_GLB_PLACEMENT) 1
+set ::env(PL_RESIZER_DESIGN_OPTIMIZATIONS) 0
+set ::env(PL_RESIZER_TIMING_OPTIMIZATIONS) 0
+set ::env(PL_RESIZER_BUFFER_INPUT_PORTS) 0
+set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0
+set ::env(FP_PDN_ENABLE_RAILS) 0
+set ::env(DIODE_INSERTION_STRATEGY) 0
+set ::env(FILL_INSERTION) 0
+set ::env(TAP_DECAP_INSERTION) 0
+set ::env(CLOCK_TREE_SYNTH) 0
+set ::env(QUIT_ON_LVS_ERROR) "1"
+set ::env(QUIT_ON_MAGIC_DRC) "0"
+set ::env(QUIT_ON_NEGATIVE_WNS) "0"
+set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
+set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
+set ::env(FP_PDN_IRDROP) "0"
+set ::env(FP_PDN_HORIZONTAL_HALO) "10"
+set ::env(FP_PDN_VERTICAL_HALO) "10"
+set ::env(FP_PDN_VOFFSET) "5"
+set ::env(FP_PDN_VPITCH) "80"
+set ::env(FP_PDN_VSPACING) "15.5"
+set ::env(FP_PDN_VWIDTH) "3.1"
+set ::env(FP_PDN_HOFFSET) "10"
+set ::env(FP_PDN_HPITCH) "90"
+set ::env(FP_PDN_HSPACING) "10"
+set ::env(FP_PDN_HWIDTH) "3.1"
diff --git a/openlane/user_project_wrapper/mpw5/interactive.tcl b/openlane/user_project_wrapper/mpw5/interactive.tcl
new file mode 100644
index 0000000..ccfa729
--- /dev/null
+++ b/openlane/user_project_wrapper/mpw5/interactive.tcl
@@ -0,0 +1,371 @@
+#!/usr/bin/tclsh
+# SPDX-FileCopyrightText: 2020 Efabless Corporation
+# Copyright 2020 Efabless Corporation
+# Copyright 2020 Sylvain Munaut
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# SPDX-License-Identifier: Apache-2.0
+package require openlane;
+proc run_placement_step {args} {
+ if { ! [ info exists ::env(PLACEMENT_CURRENT_DEF) ] } {
+ set ::env(PLACEMENT_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(PLACEMENT_CURRENT_DEF)
+ }
+ run_placement
+}
+proc run_cts_step {args} {
+ if { ! [ info exists ::env(CTS_CURRENT_DEF) ] } {
+ set ::env(CTS_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(CTS_CURRENT_DEF)
+ }
+ run_cts
+ run_resizer_timing
+}
+proc run_routing_step {args} {
+ if { ! [ info exists ::env(ROUTING_CURRENT_DEF) ] } {
+ set ::env(ROUTING_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(ROUTING_CURRENT_DEF)
+ }
+ run_routing
+}
+proc run_diode_insertion_2_5_step {args} {
+ if { ! [ info exists ::env(DIODE_INSERTION_CURRENT_DEF) ] } {
+ set ::env(DIODE_INSERTION_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(DIODE_INSERTION_CURRENT_DEF)
+ }
+ if { ($::env(DIODE_INSERTION_STRATEGY) == 2) || ($::env(DIODE_INSERTION_STRATEGY) == 5) } {
+ run_antenna_check
+ heal_antenna_violators; # modifies the routed DEF
+ }
+}
+proc run_lvs_step {{ lvs_enabled 1 }} {
+ if { ! [ info exists ::env(LVS_CURRENT_DEF) ] } {
+ set ::env(LVS_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(LVS_CURRENT_DEF)
+ }
+ if { $lvs_enabled } {
+ run_magic_spice_export
+ run_lvs; # requires run_magic_spice_export
+ }
+}
+proc run_drc_step {{ drc_enabled 1 }} {
+ if { ! [ info exists ::env(DRC_CURRENT_DEF) ] } {
+ set ::env(DRC_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(DRC_CURRENT_DEF)
+ }
+ if { $drc_enabled } {
+ run_magic_drc
+ run_klayout_drc
+ }
+}
+proc run_antenna_check_step {{ antenna_check_enabled 1 }} {
+ if { ! [ info exists ::env(ANTENNA_CHECK_CURRENT_DEF) ] } {
+ set ::env(ANTENNA_CHECK_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(ANTENNA_CHECK_CURRENT_DEF)
+ }
+ if { $antenna_check_enabled } {
+ run_antenna_check
+ }
+}
+proc run_eco_step {args} {
+ if { $::env(ECO_ENABLE) == 1 } {
+ run_eco
+ }
+}
+proc save_final_views {args} {
+ set options {
+ {-save_path optional}
+ }
+ set flags {}
+ parse_key_args "save_final_views" args arg_values $options flags_map $flags
+ set arg_list [list]
+ # If they don't exist, save_views will simply not copy them
+ lappend arg_list -lef_path $::env(finishing_results)/$::env(DESIGN_NAME).lef
+ lappend arg_list -gds_path $::env(finishing_results)/$::env(DESIGN_NAME).gds
+ lappend arg_list -mag_path $::env(finishing_results)/$::env(DESIGN_NAME).mag
+ lappend arg_list -maglef_path $::env(finishing_results)/$::env(DESIGN_NAME).lef.mag
+ lappend arg_list -spice_path $::env(finishing_results)/$::env(DESIGN_NAME).spice
+
+ # Guaranteed to have default values
+ lappend arg_list -def_path $::env(CURRENT_DEF)
+ lappend arg_list -verilog_path $::env(CURRENT_NETLIST)
+ # Not guaranteed to have default values
+ if { [info exists ::env(SPEF_TYPICAL)] } {
+ lappend arg_list -spef_path $::env(SPEF_TYPICAL)
+ }
+ if { [info exists ::env(CURRENT_SDF)] } {
+ lappend arg_list -sdf_path $::env(CURRENT_SDF)
+ }
+ if { [info exists ::env(CURRENT_SDC)] } {
+ lappend arg_list -sdc_path $::env(CURRENT_SDC)
+ }
+ # Add the path if it exists...
+ if { [info exists arg_values(-save_path) ] } {
+ lappend arg_list -save_path $arg_values(-save_path)
+ }
+ # Aaand fire!
+ save_views {*}$arg_list
+}
+proc run_post_run_hooks {} {
+ if { [file exists $::env(DESIGN_DIR)/hooks/post_run.py]} {
+ puts_info "Running post run hook"
+ set result [exec $::env(OPENROAD_BIN) -python $::env(DESIGN_DIR)/hooks/post_run.py]
+ puts_info "$result"
+ } else {
+ puts_info "hooks/post_run.py not found, skipping"
+ }
+}
+proc gen_pdn {args} {
+ puts_info "Generating PDN..."
+ TIMER::timer_start
+
+ set ::env(SAVE_DEF) [index_file $::env(floorplan_tmpfiles).def]
+ set ::env(PGA_RPT_FILE) [index_file $::env(floorplan_tmpfiles).pga.rpt]
+ run_openroad_script $::env(SCRIPTS_DIR)/openroad/pdn.tcl \
+ |& -indexed_log [index_file $::env(floorplan_logs)/pdn.log]
+ TIMER::timer_stop
+ exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "pdn generation - openroad"
+ quit_on_unconnected_pdn_nodes
+ set_def $::env(SAVE_DEF)
+}
+proc run_power_grid_generation {args} {
+ if {[info exists ::env(FP_PDN_POWER_STRAPS)]} {
+ set power_domains [split $::env(FP_PDN_POWER_STRAPS) ","]
+ }
+ # internal macros power connections
+ if {[info exists ::env(FP_PDN_MACRO_HOOKS)]} {
+ set macro_hooks [dict create]
+ set pdn_hooks [split $::env(FP_PDN_MACRO_HOOKS) ","]
+ foreach pdn_hook $pdn_hooks {
+ set instance_name [lindex $pdn_hook 0]
+ set power_net [lindex $pdn_hook 1]
+ set ground_net [lindex $pdn_hook 2]
+ dict append macro_hooks $instance_name [subst {$power_net $ground_net}]
+ }
+
+ set power_net_indx [lsearch $::env(VDD_NETS) $power_net]
+ set ground_net_indx [lsearch $::env(GND_NETS) $ground_net]
+ # make sure that the specified power domains exist.
+ if { $power_net_indx == -1 || $ground_net_indx == -1 || $power_net_indx != $ground_net_indx } {
+ puts_err "Can't find $power_net and $ground_net domain. \
+ Make sure that both exist in $::env(VDD_NETS) and $::env(GND_NETS)."
+ }
+ }
+
+ # generate multiple power grids per pair of (VDD,GND)
+ # offseted by WIDTH + SPACING
+ foreach domain $power_domains {
+ set ::env(VDD_NET) [lindex $domain 0]
+ set ::env(GND_NET) [lindex $domain 1]
+ set ::env(_WITH_STRAPS) [lindex $domain 2]
+ puts_info "Connecting Power: $::env(VDD_NET) & $::env(GND_NET) to All internal macros."
+ # internal macros power connections
+ set ::env(FP_PDN_MACROS) ""
+ if { $::env(FP_PDN_ENABLE_MACROS_GRID) == 1 } {
+ # if macros connections to power are explicitly set
+ # default behavoir macro pins will be connected to the first power domain
+ if { [info exists ::env(FP_PDN_MACRO_HOOKS)] } {
+ set ::env(FP_PDN_ENABLE_MACROS_GRID) 0
+ foreach {instance_name hooks} $macro_hooks {
+ set power [lindex $hooks 0]
+ set ground [lindex $hooks 1]
+ if { $power == $::env(VDD_NET) && $ground == $::env(GND_NET) } {
+ set ::env(FP_PDN_ENABLE_MACROS_GRID) 1
+ set ::env(FP_PDN_IRDROP) "0"
+ puts_info "Connecting $instance_name to $power and $ground nets."
+ lappend ::env(FP_PDN_MACROS) $instance_name
+ }
+ }
+ }
+ } else {
+ puts_warn "All internal macros will not be connected to power $::env(VDD_NET) & $::env(GND_NET)."
+ }
+
+ gen_pdn
+ set ::env(FP_PDN_ENABLE_RAILS) 0
+ set ::env(FP_PDN_ENABLE_MACROS_GRID) 0
+ set ::env(FP_PDN_IRDROP) "0"
+ # allow failure until open_pdks is up to date...
+ catch {set ::env(FP_PDN_VOFFSET) [expr $::env(FP_PDN_VOFFSET)+$::env(FP_PDN_VWIDTH)+$::env(FP_PDN_VSPACING)]}
+ catch {set ::env(FP_PDN_HOFFSET) [expr $::env(FP_PDN_HOFFSET)+$::env(FP_PDN_HWIDTH)+$::env(FP_PDN_HSPACING)]}
+ catch {set ::env(FP_PDN_CORE_RING_VOFFSET) \
+ [expr $::env(FP_PDN_CORE_RING_VOFFSET)\
+ +2*($::env(FP_PDN_CORE_RING_VWIDTH)\
+ +max($::env(FP_PDN_CORE_RING_VSPACING), $::env(FP_PDN_CORE_RING_HSPACING)))]}
+ catch {set ::env(FP_PDN_CORE_RING_HOFFSET) [expr $::env(FP_PDN_CORE_RING_HOFFSET)\
+ +2*($::env(FP_PDN_CORE_RING_HWIDTH)+\
+ max($::env(FP_PDN_CORE_RING_VSPACING), $::env(FP_PDN_CORE_RING_HSPACING)))]}
+ puts "FP_PDN_VOFFSET: $::env(FP_PDN_VOFFSET)"
+ puts "FP_PDN_HOFFSET: $::env(FP_PDN_HOFFSET)"
+ puts "FP_PDN_CORE_RING_VOFFSET: $::env(FP_PDN_CORE_RING_VOFFSET)"
+ puts "FP_PDN_CORE_RING_HOFFSET: $::env(FP_PDN_CORE_RING_HOFFSET)"
+ }
+ set ::env(FP_PDN_ENABLE_RAILS) 1
+}
+proc run_floorplan {args} {
+ puts_info "Running Floorplanning..."
+ # |----------------------------------------------------|
+ # |---------------- 2. FLOORPLAN ------------------|
+ # |----------------------------------------------------|
+ #
+ # intial fp
+ init_floorplan
+ # check for deprecated io variables
+ if { [info exists ::env(FP_IO_HMETAL)]} {
+ set ::env(FP_IO_HLAYER) [lindex $::env(TECH_METAL_LAYERS) [expr {$::env(FP_IO_HMETAL) - 1}]]
+ puts_warn "You're using FP_IO_HMETAL in your configuration, which is a deprecated variable that will be removed in the future."
+ puts_warn "We recommend you update your configuration as follows:"
+ puts_warn "\tset ::env(FP_IO_HLAYER) {$::env(FP_IO_HLAYER)}"
+ }
+ if { [info exists ::env(FP_IO_VMETAL)]} {
+ set ::env(FP_IO_VLAYER) [lindex $::env(TECH_METAL_LAYERS) [expr {$::env(FP_IO_VMETAL) - 1}]]
+ puts_warn "You're using FP_IO_VMETAL in your configuration, which is a deprecated variable that will be removed in the future."
+ puts_warn "We recommend you update your configuration as follows:"
+ puts_warn "\tset ::env(FP_IO_VLAYER) {$::env(FP_IO_VLAYER)}"
+ }
+ # place io
+ if { [info exists ::env(FP_PIN_ORDER_CFG)] } {
+ place_io_ol
+ } else {
+ if { [info exists ::env(FP_CONTEXT_DEF)] && [info exists ::env(FP_CONTEXT_LEF)] } {
+ place_io
+ global_placement_or
+ place_contextualized_io \
+ -lef $::env(FP_CONTEXT_LEF) \
+ -def $::env(FP_CONTEXT_DEF)
+ } else {
+ place_io
+ }
+ }
+ apply_def_template
+ if { [info exist ::env(EXTRA_LEFS)] } {
+ if { [info exist ::env(MACRO_PLACEMENT_CFG)] } {
+ file copy -force $::env(MACRO_PLACEMENT_CFG) $::env(placement_tmpfiles)/macro_placement.cfg
+ manual_macro_placement f
+ } else {
+ global_placement_or
+ basic_macro_placement
+ }
+ }
+ tap_decap_or
+ scrot_klayout -layout $::env(CURRENT_DEF) $::env(floorplan_logs)/screenshot.log
+ run_power_grid_generation
+}
+proc run_flow {args} {
+ set options {
+ {-design required}
+ {-from optional}
+ {-to optional}
+ {-save_path optional}
+ {-override_env optional}
+ }
+ set flags {-save -run_hooks -no_lvs -no_drc -no_antennacheck }
+ parse_key_args "run_non_interactive_mode" args arg_values $options flags_map $flags -no_consume
+ prep {*}$args
+ # signal trap SIGINT save_state;
+ if { [info exists arg_values(-override_env)] } {
+ set env_overrides [split $arg_values(-override_env) ',']
+ foreach override $env_overrides {
+ set kva [split $override '=']
+ set key [lindex $kva 0]
+ set value [lindex $kva 1]
+ set ::env(${key}) $value
+ }
+ }
+ set LVS_ENABLED 1
+ set DRC_ENABLED 0
+ set ANTENNACHECK_ENABLED 1
+ set steps [dict create \
+ "synthesis" {run_synthesis "" } \
+ "floorplan" {run_floorplan ""} \
+ "placement" {run_placement_step ""} \
+ "cts" {run_cts_step ""} \
+ "routing" {run_routing_step ""}\
+ "eco" {run_eco_step ""} \
+ "diode_insertion" {run_diode_insertion_2_5_step ""} \
+ "gds_magic" {run_magic ""} \
+ "gds_drc_klayout" {run_klayout ""} \
+ "gds_xor_klayout" {run_klayout_gds_xor ""} \
+ "lvs" "run_lvs_step $LVS_ENABLED" \
+ "drc" "run_drc_step $DRC_ENABLED" \
+ "antenna_check" "run_antenna_check_step $ANTENNACHECK_ENABLED" \
+ "cvc" {run_lef_cvc}
+ ]
+ set_if_unset arg_values(-to) "cvc";
+ if { [info exists ::env(CURRENT_STEP) ] } {
+ puts "\[INFO\]:Picking up where last execution left off"
+ puts [format "\[INFO\]:Current stage is %s " $::env(CURRENT_STEP)]
+ } else {
+ set ::env(CURRENT_STEP) "synthesis";
+ }
+ set_if_unset arg_values(-from) $::env(CURRENT_STEP);
+ set exe 0;
+ dict for {step_name step_exe} $steps {
+ if { [ string equal $arg_values(-from) $step_name ] } {
+ set exe 1;
+ }
+ if { $exe } {
+ # For when it fails
+ set ::env(CURRENT_STEP) $step_name
+ [lindex $step_exe 0] [lindex $step_exe 1] ;
+ }
+ if { [ string equal $arg_values(-to) $step_name ] } {
+ set exe 0:
+ break;
+ }
+ }
+ # for when it resumes
+ set steps_as_list [dict keys $steps]
+ set next_idx [expr [lsearch $steps_as_list $::env(CURRENT_STEP)] + 1]
+ set ::env(CURRENT_STEP) [lindex $steps_as_list $next_idx]
+ # Saves to <RUN_DIR>/results/final
+ if { $::env(SAVE_FINAL_VIEWS) == "1" } {
+ save_final_views
+ }
+ # Saves to design directory or custom
+ if { [info exists flags_map(-save) ] } {
+ if { ! [info exists arg_values(-save_path)] } {
+ set arg_values(-save_path) $::env(DESIGN_DIR)
+ }
+ save_final_views\
+ -save_path $arg_values(-save_path)\
+ -tag $::env(RUN_TAG)
+ }
+ calc_total_runtime
+ save_state
+ generate_final_summary_report
+
+ check_timing_violations
+
+ if { [info exists arg_values(-save_path)]\
+ && $arg_values(-save_path) != "" } {
+ set ::env(HOOK_OUTPUT_PATH) "[file normalize $arg_values(-save_path)]"
+ } else {
+ set ::env(HOOK_OUTPUT_PATH) $::env(RESULTS_DIR)/final
+ }
+
+ if {[info exists flags_map(-run_hooks)]} {
+ run_post_run_hooks
+ }
+
+ puts_success "Flow complete."
+ show_warnings "Note that the following warnings have been generated:"
+}
+run_flow {*}$argv
diff --git a/openlane/user_project_wrapper/mpw5/pdn_cfg.tcl b/openlane/user_project_wrapper/mpw5/pdn_cfg.tcl
new file mode 100644
index 0000000..552a90e
--- /dev/null
+++ b/openlane/user_project_wrapper/mpw5/pdn_cfg.tcl
@@ -0,0 +1,82 @@
+# Power nets
+if { ! [info exists ::env(VDD_NET)] } {
+ set ::env(VDD_NET) $::env(VDD_PIN)
+}
+if { ! [info exists ::env(GND_NET)] } {
+ set ::env(GND_NET) $::env(GND_PIN)
+}
+set ::power_nets $::env(VDD_NET)
+set ::ground_nets $::env(GND_NET)
+if { [info exists ::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS)] } {
+ if { $::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS) == 1 } {
+ foreach power_pin $::env(STD_CELL_POWER_PINS) {
+ add_global_connection -net $::env(VDD_NET) -inst_pattern .* -pin_pattern $power_pin -power
+ }
+ foreach ground_pin $::env(STD_CELL_GROUND_PINS) {
+ add_global_connection -net $::env(GND_NET) -inst_pattern .* -pin_pattern $ground_pin -ground
+ }
+ }
+}
+set_voltage_domain -name CORE -power $::env(VDD_NET) -ground $::env(GND_NET)
+# Assesses whether the deisgn is the core of the chip or not based on the
+# value of $::env(DESIGN_IS_CORE) and uses the appropriate stdcell section
+if { $::env(DESIGN_IS_CORE) == 1 } {
+ # Used if the design is the core of the chip
+ define_pdn_grid -name stdcell_grid -starts_with POWER -voltage_domain CORE -pins [subst {$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)}]
+ if { $::env(_WITH_STRAPS) } {
+ add_pdn_stripe -grid stdcell_grid -layer $::env(FP_PDN_LOWER_LAYER) -width $::env(FP_PDN_VWIDTH) -pitch $::env(FP_PDN_VPITCH) -offset $::env(FP_PDN_VOFFSET) -starts_with POWER
+ add_pdn_stripe -grid stdcell_grid -layer $::env(FP_PDN_UPPER_LAYER) -width $::env(FP_PDN_HWIDTH) -pitch $::env(FP_PDN_HPITCH) -offset $::env(FP_PDN_HOFFSET) -starts_with POWER
+ }
+ add_pdn_connect -grid stdcell_grid -layers [subst {$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)}]
+} else {
+ # Used if the design is a macro in the core
+ define_pdn_grid -name stdcell_grid -starts_with POWER -voltage_domain CORE -pins $::env(FP_PDN_LOWER_LAYER)
+ add_pdn_stripe -grid stdcell_grid -layer $::env(FP_PDN_LOWER_LAYER) -width $::env(FP_PDN_VWIDTH) -pitch $::env(FP_PDN_VPITCH) -offset $::env(FP_PDN_VOFFSET) -starts_with POWER
+}
+# Adds the standard cell rails if enabled.
+if { $::env(FP_PDN_ENABLE_RAILS) == 1 } {
+ add_pdn_stripe -grid stdcell_grid -layer $::env(FP_PDN_RAILS_LAYER) -width $::env(FP_PDN_RAIL_WIDTH) -followpins -starts_with POWER
+ add_pdn_connect -grid stdcell_grid -layers [subst {$::env(FP_PDN_RAILS_LAYER) $::env(FP_PDN_LOWER_LAYER)}]
+}
+# Adds the core ring if enabled.
+if { $::env(FP_PDN_CORE_RING) == 1 } {
+ add_pdn_ring -grid stdcell_grid -layer [subst {$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)}] \
+ -widths [subst {$::env(FP_PDN_CORE_RING_VWIDTH) $::env(FP_PDN_CORE_RING_HWIDTH)}] \
+ -spacings [subst {$::env(FP_PDN_CORE_RING_VSPACING) $::env(FP_PDN_CORE_RING_HSPACING)}] \
+ -core_offset [subst {$::env(FP_PDN_CORE_RING_VOFFSET) $::env(FP_PDN_CORE_RING_HOFFSET)}]
+}
+# A general macro that follows the premise of the set heirarchy. You may want to modify this or add other macro configs
+# The macro power pin names are assumed to match the VDD and GND net names
+# TODO: parameterize the power pin names
+set macro {
+ orient {R0 R180 MX MY R90 R270 MXR90 MYR90}
+ power_pins $::env(VDD_NET)
+ ground_pins $::env(GND_NET)
+ blockages $::env(MACRO_BLOCKAGES_LAYER)
+ straps {
+ }
+ connect {{$::env(FP_PDN_LOWER_LAYER)_PIN_ver $::env(FP_PDN_UPPER_LAYER)}}
+}
+if { $::env(FP_PDN_ENABLE_MACROS_GRID) == 1} {
+ if { [llength $::env(FP_PDN_MACROS)] > 0 } {
+ # generate automatically per instance:
+ foreach macro_instance $::env(FP_PDN_MACROS) {
+ set macro_instance_grid [subst $macro]
+ dict append $macro_instance_grid instance $macro_instance
+ set ::halo [list $::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)]
+ pdngen::specify_grid macro [subst $macro_instance_grid]
+ }
+ } else {
+ set ::halo [list $::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)]
+ pdngen::specify_grid macro [subst $macro]
+ }
+ # CAN NOT ENABLE THE TCL COMMAND BECAUSE THERE IS NO ARGUMENT FOR SPECIFYING THE POWER AND GROUND PIN NAMES ON THE MACRO
+ # define_pdn_grid -macro -orient {R0 R180 MX MY R90 R270 MXR90 MYR90} -grid_over_pg_pins -starts_with POWER -pin_direction vertical -halo [subst {$::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)}]
+ # add_pdn_connect -layers [subst {$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)}]
+} else {
+ define_pdn_grid -macro -orient {R0 R180 MX MY R90 R270 MXR90 MYR90} -grid_over_pg_pins -starts_with POWER -halo [subst {$::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)}]
+}
+# POWER or GROUND #Std. cell rails starting with power or ground rails at the bottom of the core area
+set ::rails_start_with "POWER" ;
+# POWER or GROUND #Upper metal stripes starting with power or ground rails at the left/bottom of the core area
+set ::stripes_start_with "POWER" ;
diff --git a/openlane/user_project_wrapper/mpw6/config.tcl b/openlane/user_project_wrapper/mpw6/config.tcl
new file mode 100644
index 0000000..3826900
--- /dev/null
+++ b/openlane/user_project_wrapper/mpw6/config.tcl
@@ -0,0 +1,219 @@
+# SPDX-FileCopyrightText: 2020 Efabless Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# SPDX-License-Identifier: Apache-2.0
+
+# Base Configurations. Don't Touch
+# section begin
+
+set ::env(PDK) "sky130A"
+set ::env(STD_CELL_LIBRARY) "sky130_fd_sc_hd"
+
+# YOU ARE NOT ALLOWED TO CHANGE ANY VARIABLES DEFINED IN THE FIXED WRAPPER CFGS
+source $::env(CARAVEL_ROOT)/openlane/user_project_wrapper/fixed_wrapper_cfgs.tcl
+
+
+# YOU CAN CHANGE ANY VARIABLES DEFINED IN THE DEFAULT WRAPPER CFGS BY OVERRIDING THEM IN THIS CONFIG.TCL
+source $::env(CARAVEL_ROOT)/openlane/user_project_wrapper/default_wrapper_cfgs.tcl
+
+
+set script_dir [file dirname [file normalize [info script]]]
+set proj_dir [file dirname [file normalize [info script]]]
+
+set ::env(DESIGN_NAME) user_project_wrapper
+set verilog_root $proj_dir/../../verilog/
+set lef_root $proj_dir/../../lef/
+set gds_root $proj_dir/../../gds/
+#section end
+
+# User Configurations
+#
+set ::env(DESIGN_IS_CORE) 1
+set ::env(FP_PDN_CORE_RING) 1
+
+
+## Source Verilog Files
+set ::env(VERILOG_FILES) "\
+ $proj_dir/../../verilog/rtl//yifive/ycr2c/src/top/ycr2_top_wb.sv \
+ $proj_dir/../../verilog/rtl/user_project_wrapper.v"
+
+
+## Clock configurations
+set ::env(CLOCK_PORT) "user_clock2 wb_clk_i"
+#set ::env(CLOCK_NET) "mprj.clk"
+
+set ::env(CLOCK_PERIOD) "10"
+
+## Internal Macros
+### Macro Placement
+set ::env(FP_SIZING) "absolute"
+set ::env(MACRO_PLACEMENT_CFG) $proj_dir/macro.cfg
+
+set ::env(PDN_CFG) $proj_dir/pdn_cfg.tcl
+
+set ::env(SDC_FILE) "$proj_dir/base.sdc"
+set ::env(BASE_SDC_FILE) "$proj_dir/base.sdc"
+
+set ::env(SYNTH_READ_BLACKBOX_LIB) 1
+
+### Black-box verilog and views
+set ::env(VERILOG_FILES_BLACKBOX) "\
+ $proj_dir/../../verilog/gl/qspim_top.v \
+ $proj_dir/../../verilog/gl/wb_interconnect.v \
+ $proj_dir/../../verilog/gl/pinmux.v \
+ $proj_dir/../../verilog/gl/uart_i2c_usb_spi_top.v \
+ $proj_dir/../../verilog/gl/wb_host.v \
+ $proj_dir/../../verilog/gl/ycr_intf.v \
+ $proj_dir/../../verilog/gl/ycr_core_top.v \
+ $proj_dir/../../verilog/gl/ycr2_iconnect.v \
+ $proj_dir/../../verilog/gl/digital_pll.v \
+ $::env(PDK_ROOT)/sky130A/libs.ref/sky130_sram_macros/verilog/sky130_sram_2kbyte_1rw1r_32x512_8.v \
+ "
+
+set ::env(EXTRA_LEFS) "\
+ $lef_root/qspim_top.lef \
+ $lef_root/pinmux.lef \
+ $lef_root/wb_interconnect.lef \
+ $lef_root/uart_i2c_usb_spi_top.lef \
+ $lef_root/wb_host.lef \
+ $lef_root/ycr_intf.lef \
+ $lef_root/ycr_core_top.lef \
+ $lef_root/ycr2_iconnect.lef \
+ $lef_root/digital_pll.lef \
+ $::env(PDK_ROOT)/sky130A/libs.ref/sky130_sram_macros/lef/sky130_sram_2kbyte_1rw1r_32x512_8.lef \
+ "
+
+set ::env(EXTRA_GDS_FILES) "\
+ $gds_root/qspim_top.gds \
+ $gds_root/pinmux.gds \
+ $gds_root/wb_interconnect.gds \
+ $gds_root/uart_i2c_usb_spi_top.gds \
+ $gds_root/wb_host.gds \
+ $gds_root/ycr_intf.gds \
+ $gds_root/ycr_core_top.gds \
+ $gds_root/ycr2_iconnect.gds \
+ $gds_root/digital_pll.gds \
+ $::env(PDK_ROOT)/sky130A/libs.ref/sky130_sram_macros/gds/sky130_sram_2kbyte_1rw1r_32x512_8.gds \
+ "
+
+set ::env(SYNTH_DEFINES) [list SYNTHESIS ]
+
+set ::env(VERILOG_INCLUDE_DIRS) [glob $script_dir/../../verilog/rtl/yifive/ycr2c/src/includes ]
+
+#set ::env(GLB_RT_MAXLAYER) 6
+set ::env(RT_MAX_LAYER) {met5}
+
+set ::env(FP_PDN_CHECK_NODES) 0
+
+
+## Internal Macros
+### Macro PDN Connections
+set ::env(FP_PDN_ENABLE_MACROS_GRID) "1"
+set ::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS) "1"
+
+set ::env(VDD_NETS) {vccd1 vccd2 vdda1 vdda2}
+set ::env(GND_NETS) {vssd1 vssd2 vssa1 vssa2}
+#
+set ::env(VDD_PIN) {vccd1}
+set ::env(GND_PIN) {vssd1}
+
+set ::env(GLB_RT_OBS) " \
+ li1 150 130 833.1 546.54,\
+ met1 150 130 833.1 546.54,\
+ met2 150 130 833.1 546.54,\
+ met3 150 130 833.1 546.54,\
+
+ li1 950 130 1633.1 546.54,\
+ met1 950 130 1633.1 546.54,\
+ met2 950 130 1633.1 546.54,\
+ met3 950 130 1633.1 546.54,\
+
+ li1 150 750 833.1 1166.54,\
+ met1 150 750 833.1 1166.54,\
+ met2 150 750 833.1 1166.54,\
+ met3 150 750 833.1 1166.54,\
+ met1 950 650 1760 660 ,\
+ met3 950 650 1760 660 ,\
+ met5 0 0 2920 3520"
+
+set ::env(FP_PDN_POWER_STRAPS) "vccd1 vssd1 1, vccd2 vssd2 0, vdda1 vssa1 0, vdda2 vssa2 0"
+
+set ::env(FP_PDN_MACRO_HOOKS) " \
+ u_intercon vccd1 vssd1,\
+ u_pinmux vccd1 vssd1,\
+ u_qspi_master vccd1 vssd1,\
+ u_riscv_top vccd1 vssd1,\
+ u_tsram0_2kb vccd1 vssd1,\
+ u_icache_2kb vccd1 vssd1,\
+ u_dcache_2kb vccd1 vssd1,\
+ u_sram0_2kb vccd1 vssd1,\
+ u_sram1_2kb vccd1 vssd1,\
+ u_sram2_2kb vccd1 vssd1,\
+ u_sram3_2kb vccd1 vssd1,\
+ u_uart_i2c_usb_spi vccd1 vssd1,\
+ u_wb_host vccd1 vssd1,\
+ u_riscv_top.i_core_top_0 vccd1 vssd1, \
+ u_riscv_top.i_core_top_1 vccd1 vssd1, \
+ u_riscv_top.u_intf vccd1 vssd1 \
+ "
+
+
+# The following is because there are no std cells in the example wrapper project.
+set ::env(SYNTH_TOP_LEVEL) 0
+set ::env(PL_RANDOM_GLB_PLACEMENT) 1
+
+set ::env(PL_RESIZER_DESIGN_OPTIMIZATIONS) 0
+set ::env(PL_RESIZER_TIMING_OPTIMIZATIONS) 0
+set ::env(PL_RESIZER_BUFFER_INPUT_PORTS) 0
+set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0
+
+set ::env(FP_PDN_ENABLE_RAILS) 0
+
+set ::env(DIODE_INSERTION_STRATEGY) 0
+set ::env(FILL_INSERTION) 0
+set ::env(TAP_DECAP_INSERTION) 0
+set ::env(CLOCK_TREE_SYNTH) 0
+
+set ::env(QUIT_ON_LVS_ERROR) "1"
+set ::env(QUIT_ON_MAGIC_DRC) "0"
+set ::env(QUIT_ON_NEGATIVE_WNS) "0"
+set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
+set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
+
+set ::env(FP_PDN_IRDROP) "0"
+set ::env(FP_PDN_HORIZONTAL_HALO) "10"
+set ::env(FP_PDN_VERTICAL_HALO) "10"
+
+#
+
+set ::env(FP_PDN_CORE_RING_HOFFSET) {12.45}
+set ::env(FP_PDN_CORE_RING_HSPACING) {1.7}
+set ::env(FP_PDN_CORE_RING_HWIDTH) {3.1}
+
+set ::env(FP_PDN_CORE_RING_VOFFSET) {12.45}
+set ::env(FP_PDN_CORE_RING_VSPACING) {1.7}
+set ::env(FP_PDN_CORE_RING_VWIDTH) {3.1}
+
+
+set ::env(FP_PDN_VOFFSET) "5"
+set ::env(FP_PDN_VPITCH) "80"
+set ::env(FP_PDN_VSPACING) "15.5"
+set ::env(FP_PDN_VWIDTH) "3.1"
+
+set ::env(FP_PDN_HOFFSET) "10"
+set ::env(FP_PDN_HPITCH) "90"
+set ::env(FP_PDN_HSPACING) "10"
+set ::env(FP_PDN_HWIDTH) "3.1"
+
+
+
diff --git a/openlane/user_project_wrapper/mpw6/interactive.tcl b/openlane/user_project_wrapper/mpw6/interactive.tcl
new file mode 100644
index 0000000..07190b7
--- /dev/null
+++ b/openlane/user_project_wrapper/mpw6/interactive.tcl
@@ -0,0 +1,456 @@
+#!/usr/bin/tclsh
+# SPDX-FileCopyrightText: 2020 Efabless Corporation
+# Copyright 2020 Efabless Corporation
+# Copyright 2020 Sylvain Munaut
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# SPDX-License-Identifier: Apache-2.0
+
+package require openlane;
+
+proc run_placement_step {args} {
+ if { ! [ info exists ::env(PLACEMENT_CURRENT_DEF) ] } {
+ set ::env(PLACEMENT_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(PLACEMENT_CURRENT_DEF)
+ }
+
+ run_placement
+}
+
+proc run_cts_step {args} {
+ if { ! [ info exists ::env(CTS_CURRENT_DEF) ] } {
+ set ::env(CTS_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(CTS_CURRENT_DEF)
+ }
+
+ run_cts
+ run_resizer_timing
+}
+
+proc run_routing_step {args} {
+ if { ! [ info exists ::env(ROUTING_CURRENT_DEF) ] } {
+ set ::env(ROUTING_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(ROUTING_CURRENT_DEF)
+ }
+ run_routing
+}
+
+proc run_parasitics_sta_step {args} {
+ if { ! [ info exists ::env(PARSITICS_CURRENT_DEF) ] } {
+ set ::env(PARSITICS_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(PARSITICS_CURRENT_DEF)
+ }
+
+ if { $::env(RUN_SPEF_EXTRACTION) } {
+ run_parasitics_sta
+ }
+}
+
+proc run_diode_insertion_2_5_step {args} {
+ if { ! [ info exists ::env(DIODE_INSERTION_CURRENT_DEF) ] } {
+ set ::env(DIODE_INSERTION_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(DIODE_INSERTION_CURRENT_DEF)
+ }
+ if { ($::env(DIODE_INSERTION_STRATEGY) == 2) || ($::env(DIODE_INSERTION_STRATEGY) == 5) } {
+ run_antenna_check
+ heal_antenna_violators; # modifies the routed DEF
+ }
+
+}
+
+proc run_lvs_step {{ lvs_enabled 1 }} {
+ if { ! [ info exists ::env(LVS_CURRENT_DEF) ] } {
+ set ::env(LVS_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(LVS_CURRENT_DEF)
+ }
+
+ if { $lvs_enabled && $::env(RUN_LVS) } {
+ run_magic_spice_export;
+ run_lvs; # requires run_magic_spice_export
+ }
+
+}
+
+proc run_drc_step {{ drc_enabled 1 }} {
+ if { ! [ info exists ::env(DRC_CURRENT_DEF) ] } {
+ set ::env(DRC_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(DRC_CURRENT_DEF)
+ }
+ if { $drc_enabled } {
+ if { $::env(RUN_MAGIC_DRC) } {
+ run_magic_drc
+ }
+ if {$::env(RUN_KLAYOUT_DRC)} {
+ run_klayout_drc
+ }
+ }
+}
+
+proc run_antenna_check_step {{ antenna_check_enabled 1 }} {
+ if { ! [ info exists ::env(ANTENNA_CHECK_CURRENT_DEF) ] } {
+ set ::env(ANTENNA_CHECK_CURRENT_DEF) $::env(CURRENT_DEF)
+ } else {
+ set ::env(CURRENT_DEF) $::env(ANTENNA_CHECK_CURRENT_DEF)
+ }
+ if { $antenna_check_enabled } {
+ run_antenna_check
+ }
+}
+
+proc run_eco_step {args} {
+ if { $::env(ECO_ENABLE) == 1 } {
+ run_eco_flow
+ }
+}
+
+proc run_magic_step {args} {
+ if {$::env(RUN_MAGIC)} {
+ run_magic
+ }
+}
+
+proc run_klayout_step {args} {
+ if {$::env(RUN_KLAYOUT)} {
+ run_klayout
+ }
+ if {$::env(RUN_KLAYOUT_XOR)} {
+ run_klayout_gds_xor
+ }
+}
+
+proc save_final_views {args} {
+ set options {
+ {-save_path optional}
+ }
+ set flags {}
+ parse_key_args "save_final_views" args arg_values $options flags_map $flags
+
+ set arg_list [list]
+
+ # If they don't exist, save_views will simply not copy them
+ lappend arg_list -lef_path $::env(signoff_results)/$::env(DESIGN_NAME).lef
+ lappend arg_list -gds_path $::env(signoff_results)/$::env(DESIGN_NAME).gds
+ lappend arg_list -mag_path $::env(signoff_results)/$::env(DESIGN_NAME).mag
+ lappend arg_list -maglef_path $::env(signoff_results)/$::env(DESIGN_NAME).lef.mag
+ lappend arg_list -spice_path $::env(signoff_results)/$::env(DESIGN_NAME).spice
+
+ # Guaranteed to have default values
+ lappend arg_list -def_path $::env(CURRENT_DEF)
+ lappend arg_list -verilog_path $::env(CURRENT_NETLIST)
+
+ # Not guaranteed to have default values
+ if { [info exists ::env(CURRENT_SPEF)] } {
+ lappend arg_list -spef_path $::env(CURRENT_SPEF)
+ }
+ if { [info exists ::env(CURRENT_SDF)] } {
+ lappend arg_list -sdf_path $::env(CURRENT_SDF)
+ }
+ if { [info exists ::env(CURRENT_SDC)] } {
+ lappend arg_list -sdc_path $::env(CURRENT_SDC)
+ }
+
+ # Add the path if it exists...
+ if { [info exists arg_values(-save_path) ] } {
+ lappend arg_list -save_path $arg_values(-save_path)
+ }
+
+ # Aaand fire!
+ save_views {*}$arg_list
+
+}
+
+proc run_post_run_hooks {} {
+ if { [file exists $::env(DESIGN_DIR)/hooks/post_run.py]} {
+ puts_info "Running post run hook"
+ set result [exec $::env(OPENROAD_BIN) -python $::env(DESIGN_DIR)/hooks/post_run.py]
+ puts_info "$result"
+ } else {
+ puts_info "hooks/post_run.py not found, skipping"
+ }
+}
+
+proc gen_pdn {args} {
+ increment_index
+ TIMER::timer_start
+ puts_info "Generating PDN..."
+
+ set ::env(SAVE_DEF) [index_file $::env(floorplan_tmpfiles)/pdn.def]
+ set ::env(PGA_RPT_FILE) [index_file $::env(floorplan_tmpfiles)/pdn.pga.rpt]
+
+ run_openroad_script $::env(SCRIPTS_DIR)/openroad/pdn.tcl \
+ |& -indexed_log [index_file $::env(floorplan_logs)/pdn.log]
+
+
+ TIMER::timer_stop
+ exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "pdn generation - openroad"
+
+ quit_on_unconnected_pdn_nodes
+
+ set_def $::env(SAVE_DEF)
+}
+
+proc run_power_grid_generation {args} {
+ if { [info exists ::env(VDD_NETS)] || [info exists ::env(GND_NETS)] } {
+ # they both must exist and be equal in length
+ # current assumption: they cannot have a common ground
+ if { ! [info exists ::env(VDD_NETS)] || ! [info exists ::env(GND_NETS)] } {
+ puts_err "VDD_NETS and GND_NETS must *both* either be defined or undefined"
+ return -code error
+ }
+ # standard cell power and ground nets are assumed to be the first net
+ set ::env(VDD_PIN) [lindex $::env(VDD_NETS) 0]
+ set ::env(GND_PIN) [lindex $::env(GND_NETS) 0]
+ } elseif { [info exists ::env(SYNTH_USE_PG_PINS_DEFINES)] } {
+ set ::env(VDD_NETS) [list]
+ set ::env(GND_NETS) [list]
+ # get the pins that are in $synthesis_tmpfiles.pg_define.v
+ # that are not in $synthesis_results.v
+ #
+ set full_pins {*}[extract_pins_from_yosys_netlist $::env(synthesis_tmpfiles)/pg_define.v]
+ puts_info $full_pins
+
+ set non_pg_pins {*}[extract_pins_from_yosys_netlist $::env(synthesis_results)/$::env(DESIGN_NAME).v]
+ puts_info $non_pg_pins
+
+ # assumes the pins are ordered correctly (e.g., vdd1, vss1, vcc1, vss1, ...)
+ foreach {vdd gnd} $full_pins {
+ if { $vdd ne "" && $vdd ni $non_pg_pins } {
+ lappend ::env(VDD_NETS) $vdd
+ }
+ if { $gnd ne "" && $gnd ni $non_pg_pins } {
+ lappend ::env(GND_NETS) $gnd
+ }
+ }
+ } else {
+ set ::env(VDD_NETS) $::env(VDD_PIN)
+ set ::env(GND_NETS) $::env(GND_PIN)
+ }
+
+ puts_info "Power planning with power {$::env(VDD_NETS)} and ground {$::env(GND_NETS)}..."
+
+ if { [llength $::env(VDD_NETS)] != [llength $::env(GND_NETS)] } {
+ puts_err "VDD_NETS and GND_NETS must be of equal lengths"
+ return -code error
+ }
+
+ # check internal macros' power connection definitions
+ if {[info exists ::env(FP_PDN_MACRO_HOOKS)]} {
+ set macro_hooks [dict create]
+ set pdn_hooks [split $::env(FP_PDN_MACRO_HOOKS) ","]
+ foreach pdn_hook $pdn_hooks {
+ set instance_name [lindex $pdn_hook 0]
+ set power_net [lindex $pdn_hook 1]
+ set ground_net [lindex $pdn_hook 2]
+ dict append macro_hooks $instance_name [subst {$power_net $ground_net}]
+ }
+
+ set power_net_indx [lsearch $::env(VDD_NETS) $power_net]
+ set ground_net_indx [lsearch $::env(GND_NETS) $ground_net]
+
+ # make sure that the specified power domains exist.
+ if { $power_net_indx == -1 || $ground_net_indx == -1 || $power_net_indx != $ground_net_indx } {
+ puts_err "Can't find $power_net and $ground_net domain. \
+ Make sure that both exist in $::env(VDD_NETS) and $::env(GND_NETS)."
+ }
+ }
+
+ gen_pdn
+}
+
+proc run_floorplan {args} {
+ puts_info "Running Floorplanning..."
+ # |----------------------------------------------------|
+ # |---------------- 2. FLOORPLAN ------------------|
+ # |----------------------------------------------------|
+ #
+ # intial fp
+ init_floorplan
+
+ # check for deprecated io variables
+ if { [info exists ::env(FP_IO_HMETAL)]} {
+ set ::env(FP_IO_HLAYER) [lindex $::env(TECH_METAL_LAYERS) [expr {$::env(FP_IO_HMETAL) - 1}]]
+ puts_warn "You're using FP_IO_HMETAL in your configuration, which is a deprecated variable that will be removed in the future."
+ puts_warn "We recommend you update your configuration as follows:"
+ puts_warn "\tset ::env(FP_IO_HLAYER) {$::env(FP_IO_HLAYER)}"
+ }
+
+ if { [info exists ::env(FP_IO_VMETAL)]} {
+ set ::env(FP_IO_VLAYER) [lindex $::env(TECH_METAL_LAYERS) [expr {$::env(FP_IO_VMETAL) - 1}]]
+ puts_warn "You're using FP_IO_VMETAL in your configuration, which is a deprecated variable that will be removed in the future."
+ puts_warn "We recommend you update your configuration as follows:"
+ puts_warn "\tset ::env(FP_IO_VLAYER) {$::env(FP_IO_VLAYER)}"
+ }
+
+
+ # place io
+ if { [info exists ::env(FP_PIN_ORDER_CFG)] } {
+ place_io_ol
+ } else {
+ if { [info exists ::env(FP_CONTEXT_DEF)] && [info exists ::env(FP_CONTEXT_LEF)] } {
+ place_io
+ global_placement_or
+ place_contextualized_io \
+ -lef $::env(FP_CONTEXT_LEF) \
+ -def $::env(FP_CONTEXT_DEF)
+ } else {
+ place_io
+ }
+ }
+
+ apply_def_template
+
+ if { [info exist ::env(EXTRA_LEFS)] } {
+ if { [info exist ::env(MACRO_PLACEMENT_CFG)] } {
+ file copy -force $::env(MACRO_PLACEMENT_CFG) $::env(placement_tmpfiles)/macro_placement.cfg
+ manual_macro_placement f
+ } else {
+ global_placement_or
+ basic_macro_placement
+ }
+ }
+
+ tap_decap_or
+
+ scrot_klayout -layout $::env(CURRENT_DEF) $::env(floorplan_logs)/screenshot.log
+
+ run_power_grid_generation
+}
+
+
+proc run_flow {args} {
+ set options {
+ {-design required}
+ {-from optional}
+ {-to optional}
+ {-save_path optional}
+ {-override_env optional}
+ }
+ set flags {-save -run_hooks -no_lvs -no_drc -no_antennacheck }
+ parse_key_args "run_non_interactive_mode" args arg_values $options flags_map $flags -no_consume
+ prep {*}$args
+ # signal trap SIGINT save_state;
+
+ if { [info exists flags_map(-gui)] } {
+ or_gui
+ return
+ }
+ if { [info exists arg_values(-override_env)] } {
+ set env_overrides [split $arg_values(-override_env) ',']
+ foreach override $env_overrides {
+ set kva [split $override '=']
+ set key [lindex $kva 0]
+ set value [lindex $kva 1]
+ set ::env(${key}) $value
+ }
+ }
+
+ set LVS_ENABLED 1
+ set DRC_ENABLED 0
+ set ANTENNACHECK_ENABLED 1
+
+ set steps [dict create \
+ "synthesis" "run_synthesis" \
+ "floorplan" "run_floorplan" \
+ "placement" "run_placement_step" \
+ "cts" "run_cts_step" \
+ "routing" "run_routing_step" \
+ "parasitics_sta" "run_parasitics_sta_step" \
+ "eco" "run_eco_step" \
+ "diode_insertion" "run_diode_insertion_2_5_step" \
+ "gds_magic" "run_magic_step" \
+ "gds_klayout" "run_klayout_step" \
+ "lvs" "run_lvs_step $LVS_ENABLED " \
+ "drc" "run_drc_step $DRC_ENABLED " \
+ "antenna_check" "run_antenna_check_step $ANTENNACHECK_ENABLED " \
+ "cvc" "run_lef_cvc"
+ ]
+
+ set_if_unset arg_values(-to) "cvc";
+
+ if { [info exists ::env(CURRENT_STEP) ] } {
+ puts "\[INFO\]:Picking up where last execution left off"
+ puts [format "\[INFO\]:Current stage is %s " $::env(CURRENT_STEP)]
+ } else {
+ set ::env(CURRENT_STEP) "synthesis";
+ }
+
+ set_if_unset arg_values(-from) $::env(CURRENT_STEP);
+ set exe 0;
+ dict for {step_name step_exe} $steps {
+ if { [ string equal $arg_values(-from) $step_name ] } {
+ set exe 1;
+ }
+
+ if { $exe } {
+ # For when it fails
+ set ::env(CURRENT_STEP) $step_name
+ [lindex $step_exe 0] [lindex $step_exe 1] ;
+ }
+
+ if { [ string equal $arg_values(-to) $step_name ] } {
+ set exe 0:
+ break;
+ }
+
+ }
+
+ # for when it resumes
+ set steps_as_list [dict keys $steps]
+ set next_idx [expr [lsearch $steps_as_list $::env(CURRENT_STEP)] + 1]
+ set ::env(CURRENT_STEP) [lindex $steps_as_list $next_idx]
+
+ # Saves to <RUN_DIR>/results/final
+ if { $::env(SAVE_FINAL_VIEWS) == "1" } {
+ save_final_views
+ }
+
+ # Saves to design directory or custom
+ if { [info exists flags_map(-save) ] } {
+ if { ! [info exists arg_values(-save_path)] } {
+ set arg_values(-save_path) $::env(DESIGN_DIR)
+ }
+ save_final_views\
+ -save_path $arg_values(-save_path)\
+ -tag $::env(RUN_TAG)
+ }
+ calc_total_runtime
+ save_state
+ generate_final_summary_report
+
+ check_timing_violations
+
+ if { [info exists arg_values(-save_path)]\
+ && $arg_values(-save_path) != "" } {
+ set ::env(HOOK_OUTPUT_PATH) "[file normalize $arg_values(-save_path)]"
+ } else {
+ set ::env(HOOK_OUTPUT_PATH) $::env(RESULTS_DIR)/final
+ }
+
+ if {[info exists flags_map(-run_hooks)]} {
+ run_post_run_hooks
+ }
+
+ puts_success "Flow complete."
+
+ show_warnings "Note that the following warnings have been generated:"
+
+}
+
+run_flow {*}$argv
diff --git a/openlane/user_project_wrapper/mpw6/pdn_cfg.tcl b/openlane/user_project_wrapper/mpw6/pdn_cfg.tcl
new file mode 100644
index 0000000..1bd5f1e
--- /dev/null
+++ b/openlane/user_project_wrapper/mpw6/pdn_cfg.tcl
@@ -0,0 +1,165 @@
+# Power nets
+
+if { ! [info exists ::env(VDD_NET)] } {
+ set ::env(VDD_NET) $::env(VDD_PIN)
+}
+
+if { ! [info exists ::env(GND_NET)] } {
+ set ::env(GND_NET) $::env(GND_PIN)
+}
+
+if { [info exists ::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS)] } {
+ if { $::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS) == 1 } {
+ foreach power_pin $::env(STD_CELL_POWER_PINS) {
+ add_global_connection \
+ -net $::env(VDD_NET) \
+ -inst_pattern .* \
+ -pin_pattern $power_pin \
+ -power
+ }
+ foreach ground_pin $::env(STD_CELL_GROUND_PINS) {
+ add_global_connection \
+ -net $::env(GND_NET) \
+ -inst_pattern .* \
+ -pin_pattern $ground_pin \
+ -ground
+ }
+ }
+}
+
+if { $::env(FP_PDN_ENABLE_MACROS_GRID) == 1 &&
+ [info exists ::env(FP_PDN_MACRO_HOOKS)]} {
+ set pdn_hooks [split $::env(FP_PDN_MACRO_HOOKS) ","]
+ foreach pdn_hook $pdn_hooks {
+ set instance_name [lindex $pdn_hook 0]
+ set power_net [lindex $pdn_hook 1]
+ set ground_net [lindex $pdn_hook 2]
+ # This assumes the power pin and the power net have the same name.
+ # The macro hooks only give an instance name and not power pin names.
+
+ add_global_connection \
+ -net $power_net \
+ -inst_pattern $instance_name \
+ -pin_pattern $power_net \
+ -power
+
+ add_global_connection \
+ -net $ground_net \
+ -inst_pattern $instance_name \
+ -pin_pattern $ground_net \
+ -ground
+ }
+}
+
+set secondary []
+
+foreach vdd $::env(VDD_NETS) gnd $::env(GND_NETS) {
+ if { $vdd != $::env(VDD_NET)} {
+ lappend secondary $vdd
+
+ set db_net [[ord::get_db_block] findNet $vdd]
+ if {$db_net == "NULL"} {
+ set net [odb::dbNet_create [ord::get_db_block] $vdd]
+ $net setSpecial
+ $net setSigType "POWER"
+ }
+ }
+
+ if { $gnd != $::env(GND_NET)} {
+ lappend secondary $gnd
+
+ set db_net [[ord::get_db_block] findNet $gnd]
+ if {$db_net == "NULL"} {
+ set net [odb::dbNet_create [ord::get_db_block] $gnd]
+ $net setSpecial
+ $net setSigType "GROUND"
+ }
+ }
+}
+
+set_voltage_domain -name CORE -power $::env(VDD_NET) -ground $::env(GND_NET) \
+ -secondary_power $secondary
+
+# Assesses whether the design is the core of the chip or not based on the
+# value of $::env(DESIGN_IS_CORE) and uses the appropriate stdcell section
+if { $::env(DESIGN_IS_CORE) == 1 } {
+ # Used if the design is the core of the chip
+ define_pdn_grid \
+ -name stdcell_grid \
+ -starts_with POWER \
+ -voltage_domain CORE \
+ -pins "$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)"
+
+ add_pdn_stripe \
+ -grid stdcell_grid \
+ -layer $::env(FP_PDN_LOWER_LAYER) \
+ -width $::env(FP_PDN_VWIDTH) \
+ -pitch $::env(FP_PDN_VPITCH) \
+ -offset $::env(FP_PDN_VOFFSET) \
+ -nets "$::env(VDD_NET) $::env(GND_NET)" \
+ -starts_with POWER -extend_to_core_ring
+
+ add_pdn_stripe \
+ -grid stdcell_grid \
+ -layer $::env(FP_PDN_UPPER_LAYER) \
+ -width $::env(FP_PDN_HWIDTH) \
+ -pitch $::env(FP_PDN_HPITCH) \
+ -offset $::env(FP_PDN_HOFFSET) \
+ -nets "$::env(VDD_NET) $::env(GND_NET)" \
+ -starts_with POWER -extend_to_core_ring
+
+ add_pdn_connect \
+ -grid stdcell_grid \
+ -layers "$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)"
+} else {
+ # Used if the design is a macro in the core
+ define_pdn_grid \
+ -name stdcell_grid \
+ -starts_with POWER \
+ -voltage_domain CORE \
+ -pins $::env(FP_PDN_LOWER_LAYER)
+
+ add_pdn_stripe \
+ -grid stdcell_grid \
+ -layer $::env(FP_PDN_LOWER_LAYER) \
+ -width $::env(FP_PDN_VWIDTH) \
+ -pitch $::env(FP_PDN_VPITCH) \
+ -offset $::env(FP_PDN_VOFFSET) \
+ -starts_with POWER
+}
+
+# Adds the standard cell rails if enabled.
+if { $::env(FP_PDN_ENABLE_RAILS) == 1 } {
+ add_pdn_stripe \
+ -grid stdcell_grid \
+ -layer $::env(FP_PDN_RAILS_LAYER) \
+ -width $::env(FP_PDN_RAIL_WIDTH) \
+ -followpins \
+ -starts_with POWER
+
+ add_pdn_connect \
+ -grid stdcell_grid \
+ -layers "$::env(FP_PDN_RAILS_LAYER) $::env(FP_PDN_LOWER_LAYER)"
+}
+
+
+# Adds the core ring if enabled.
+if { $::env(FP_PDN_CORE_RING) == 1 } {
+ add_pdn_ring \
+ -grid stdcell_grid \
+ -layers "$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)" \
+ -widths "$::env(FP_PDN_CORE_RING_VWIDTH) $::env(FP_PDN_CORE_RING_HWIDTH)" \
+ -spacings "$::env(FP_PDN_CORE_RING_VSPACING) $::env(FP_PDN_CORE_RING_HSPACING)" \
+ -core_offset "$::env(FP_PDN_CORE_RING_VOFFSET) $::env(FP_PDN_CORE_RING_HOFFSET)"
+}
+
+define_pdn_grid \
+ -macro \
+ -default \
+ -name macro \
+ -starts_with POWER \
+ -halo "$::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)"
+
+add_pdn_connect \
+ -grid macro \
+ -layers "$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)"
diff --git a/openlane/user_project_wrapper/pdn_cfg.tcl b/openlane/user_project_wrapper/pdn_cfg.tcl
index 1bd5f1e..552a90e 100644
--- a/openlane/user_project_wrapper/pdn_cfg.tcl
+++ b/openlane/user_project_wrapper/pdn_cfg.tcl
@@ -1,165 +1,82 @@
# Power nets
-
if { ! [info exists ::env(VDD_NET)] } {
set ::env(VDD_NET) $::env(VDD_PIN)
}
-
if { ! [info exists ::env(GND_NET)] } {
set ::env(GND_NET) $::env(GND_PIN)
}
-
+set ::power_nets $::env(VDD_NET)
+set ::ground_nets $::env(GND_NET)
if { [info exists ::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS)] } {
if { $::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS) == 1 } {
foreach power_pin $::env(STD_CELL_POWER_PINS) {
- add_global_connection \
- -net $::env(VDD_NET) \
- -inst_pattern .* \
- -pin_pattern $power_pin \
- -power
+ add_global_connection -net $::env(VDD_NET) -inst_pattern .* -pin_pattern $power_pin -power
}
foreach ground_pin $::env(STD_CELL_GROUND_PINS) {
- add_global_connection \
- -net $::env(GND_NET) \
- -inst_pattern .* \
- -pin_pattern $ground_pin \
- -ground
+ add_global_connection -net $::env(GND_NET) -inst_pattern .* -pin_pattern $ground_pin -ground
}
}
}
-
-if { $::env(FP_PDN_ENABLE_MACROS_GRID) == 1 &&
- [info exists ::env(FP_PDN_MACRO_HOOKS)]} {
- set pdn_hooks [split $::env(FP_PDN_MACRO_HOOKS) ","]
- foreach pdn_hook $pdn_hooks {
- set instance_name [lindex $pdn_hook 0]
- set power_net [lindex $pdn_hook 1]
- set ground_net [lindex $pdn_hook 2]
- # This assumes the power pin and the power net have the same name.
- # The macro hooks only give an instance name and not power pin names.
-
- add_global_connection \
- -net $power_net \
- -inst_pattern $instance_name \
- -pin_pattern $power_net \
- -power
-
- add_global_connection \
- -net $ground_net \
- -inst_pattern $instance_name \
- -pin_pattern $ground_net \
- -ground
- }
-}
-
-set secondary []
-
-foreach vdd $::env(VDD_NETS) gnd $::env(GND_NETS) {
- if { $vdd != $::env(VDD_NET)} {
- lappend secondary $vdd
-
- set db_net [[ord::get_db_block] findNet $vdd]
- if {$db_net == "NULL"} {
- set net [odb::dbNet_create [ord::get_db_block] $vdd]
- $net setSpecial
- $net setSigType "POWER"
- }
- }
-
- if { $gnd != $::env(GND_NET)} {
- lappend secondary $gnd
-
- set db_net [[ord::get_db_block] findNet $gnd]
- if {$db_net == "NULL"} {
- set net [odb::dbNet_create [ord::get_db_block] $gnd]
- $net setSpecial
- $net setSigType "GROUND"
- }
- }
-}
-
-set_voltage_domain -name CORE -power $::env(VDD_NET) -ground $::env(GND_NET) \
- -secondary_power $secondary
-
-# Assesses whether the design is the core of the chip or not based on the
+set_voltage_domain -name CORE -power $::env(VDD_NET) -ground $::env(GND_NET)
+# Assesses whether the deisgn is the core of the chip or not based on the
# value of $::env(DESIGN_IS_CORE) and uses the appropriate stdcell section
if { $::env(DESIGN_IS_CORE) == 1 } {
# Used if the design is the core of the chip
- define_pdn_grid \
- -name stdcell_grid \
- -starts_with POWER \
- -voltage_domain CORE \
- -pins "$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)"
-
- add_pdn_stripe \
- -grid stdcell_grid \
- -layer $::env(FP_PDN_LOWER_LAYER) \
- -width $::env(FP_PDN_VWIDTH) \
- -pitch $::env(FP_PDN_VPITCH) \
- -offset $::env(FP_PDN_VOFFSET) \
- -nets "$::env(VDD_NET) $::env(GND_NET)" \
- -starts_with POWER -extend_to_core_ring
-
- add_pdn_stripe \
- -grid stdcell_grid \
- -layer $::env(FP_PDN_UPPER_LAYER) \
- -width $::env(FP_PDN_HWIDTH) \
- -pitch $::env(FP_PDN_HPITCH) \
- -offset $::env(FP_PDN_HOFFSET) \
- -nets "$::env(VDD_NET) $::env(GND_NET)" \
- -starts_with POWER -extend_to_core_ring
-
- add_pdn_connect \
- -grid stdcell_grid \
- -layers "$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)"
+ define_pdn_grid -name stdcell_grid -starts_with POWER -voltage_domain CORE -pins [subst {$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)}]
+ if { $::env(_WITH_STRAPS) } {
+ add_pdn_stripe -grid stdcell_grid -layer $::env(FP_PDN_LOWER_LAYER) -width $::env(FP_PDN_VWIDTH) -pitch $::env(FP_PDN_VPITCH) -offset $::env(FP_PDN_VOFFSET) -starts_with POWER
+ add_pdn_stripe -grid stdcell_grid -layer $::env(FP_PDN_UPPER_LAYER) -width $::env(FP_PDN_HWIDTH) -pitch $::env(FP_PDN_HPITCH) -offset $::env(FP_PDN_HOFFSET) -starts_with POWER
+ }
+ add_pdn_connect -grid stdcell_grid -layers [subst {$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)}]
} else {
# Used if the design is a macro in the core
- define_pdn_grid \
- -name stdcell_grid \
- -starts_with POWER \
- -voltage_domain CORE \
- -pins $::env(FP_PDN_LOWER_LAYER)
-
- add_pdn_stripe \
- -grid stdcell_grid \
- -layer $::env(FP_PDN_LOWER_LAYER) \
- -width $::env(FP_PDN_VWIDTH) \
- -pitch $::env(FP_PDN_VPITCH) \
- -offset $::env(FP_PDN_VOFFSET) \
- -starts_with POWER
+ define_pdn_grid -name stdcell_grid -starts_with POWER -voltage_domain CORE -pins $::env(FP_PDN_LOWER_LAYER)
+ add_pdn_stripe -grid stdcell_grid -layer $::env(FP_PDN_LOWER_LAYER) -width $::env(FP_PDN_VWIDTH) -pitch $::env(FP_PDN_VPITCH) -offset $::env(FP_PDN_VOFFSET) -starts_with POWER
}
-
# Adds the standard cell rails if enabled.
if { $::env(FP_PDN_ENABLE_RAILS) == 1 } {
- add_pdn_stripe \
- -grid stdcell_grid \
- -layer $::env(FP_PDN_RAILS_LAYER) \
- -width $::env(FP_PDN_RAIL_WIDTH) \
- -followpins \
- -starts_with POWER
-
- add_pdn_connect \
- -grid stdcell_grid \
- -layers "$::env(FP_PDN_RAILS_LAYER) $::env(FP_PDN_LOWER_LAYER)"
+ add_pdn_stripe -grid stdcell_grid -layer $::env(FP_PDN_RAILS_LAYER) -width $::env(FP_PDN_RAIL_WIDTH) -followpins -starts_with POWER
+ add_pdn_connect -grid stdcell_grid -layers [subst {$::env(FP_PDN_RAILS_LAYER) $::env(FP_PDN_LOWER_LAYER)}]
}
-
-
# Adds the core ring if enabled.
if { $::env(FP_PDN_CORE_RING) == 1 } {
- add_pdn_ring \
- -grid stdcell_grid \
- -layers "$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)" \
- -widths "$::env(FP_PDN_CORE_RING_VWIDTH) $::env(FP_PDN_CORE_RING_HWIDTH)" \
- -spacings "$::env(FP_PDN_CORE_RING_VSPACING) $::env(FP_PDN_CORE_RING_HSPACING)" \
- -core_offset "$::env(FP_PDN_CORE_RING_VOFFSET) $::env(FP_PDN_CORE_RING_HOFFSET)"
+ add_pdn_ring -grid stdcell_grid -layer [subst {$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)}] \
+ -widths [subst {$::env(FP_PDN_CORE_RING_VWIDTH) $::env(FP_PDN_CORE_RING_HWIDTH)}] \
+ -spacings [subst {$::env(FP_PDN_CORE_RING_VSPACING) $::env(FP_PDN_CORE_RING_HSPACING)}] \
+ -core_offset [subst {$::env(FP_PDN_CORE_RING_VOFFSET) $::env(FP_PDN_CORE_RING_HOFFSET)}]
}
-
-define_pdn_grid \
- -macro \
- -default \
- -name macro \
- -starts_with POWER \
- -halo "$::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)"
-
-add_pdn_connect \
- -grid macro \
- -layers "$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)"
+# A general macro that follows the premise of the set heirarchy. You may want to modify this or add other macro configs
+# The macro power pin names are assumed to match the VDD and GND net names
+# TODO: parameterize the power pin names
+set macro {
+ orient {R0 R180 MX MY R90 R270 MXR90 MYR90}
+ power_pins $::env(VDD_NET)
+ ground_pins $::env(GND_NET)
+ blockages $::env(MACRO_BLOCKAGES_LAYER)
+ straps {
+ }
+ connect {{$::env(FP_PDN_LOWER_LAYER)_PIN_ver $::env(FP_PDN_UPPER_LAYER)}}
+}
+if { $::env(FP_PDN_ENABLE_MACROS_GRID) == 1} {
+ if { [llength $::env(FP_PDN_MACROS)] > 0 } {
+ # generate automatically per instance:
+ foreach macro_instance $::env(FP_PDN_MACROS) {
+ set macro_instance_grid [subst $macro]
+ dict append $macro_instance_grid instance $macro_instance
+ set ::halo [list $::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)]
+ pdngen::specify_grid macro [subst $macro_instance_grid]
+ }
+ } else {
+ set ::halo [list $::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)]
+ pdngen::specify_grid macro [subst $macro]
+ }
+ # CAN NOT ENABLE THE TCL COMMAND BECAUSE THERE IS NO ARGUMENT FOR SPECIFYING THE POWER AND GROUND PIN NAMES ON THE MACRO
+ # define_pdn_grid -macro -orient {R0 R180 MX MY R90 R270 MXR90 MYR90} -grid_over_pg_pins -starts_with POWER -pin_direction vertical -halo [subst {$::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)}]
+ # add_pdn_connect -layers [subst {$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)}]
+} else {
+ define_pdn_grid -macro -orient {R0 R180 MX MY R90 R270 MXR90 MYR90} -grid_over_pg_pins -starts_with POWER -halo [subst {$::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)}]
+}
+# POWER or GROUND #Std. cell rails starting with power or ground rails at the bottom of the core area
+set ::rails_start_with "POWER" ;
+# POWER or GROUND #Upper metal stripes starting with power or ground rails at the left/bottom of the core area
+set ::stripes_start_with "POWER" ;
diff --git a/openlane/wb_host/config.tcl b/openlane/wb_host/config.tcl
index 0d8ff81..4116b09 100755
--- a/openlane/wb_host/config.tcl
+++ b/openlane/wb_host/config.tcl
@@ -109,5 +109,5 @@
set ::env(PL_RESIZER_DESIGN_OPTIMIZATIONS) "1"
set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
set ::env(QUIT_ON_MAGIC_DRC) "1"
-set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_LVS_ERROR) "1"
set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
diff --git a/openlane/wb_interconnect/config.tcl b/openlane/wb_interconnect/config.tcl
index 33ac3c6..55b38f4 100755
--- a/openlane/wb_interconnect/config.tcl
+++ b/openlane/wb_interconnect/config.tcl
@@ -119,7 +119,7 @@
set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
set ::env(QUIT_ON_MAGIC_DRC) "1"
-set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_LVS_ERROR) "1"
set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
set ::env(GLB_RESIZER_TIMING_OPTIMIZATIONS) "0"
diff --git a/openlane/ycr2_iconnect/config.tcl b/openlane/ycr2_iconnect/config.tcl
index 389847d..cf9debf 100644
--- a/openlane/ycr2_iconnect/config.tcl
+++ b/openlane/ycr2_iconnect/config.tcl
@@ -94,7 +94,7 @@
set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
set ::env(QUIT_ON_MAGIC_DRC) "1"
-set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_LVS_ERROR) "1"
set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
diff --git a/openlane/ycr_core_top/config.tcl b/openlane/ycr_core_top/config.tcl
index 161152f..70e8196 100644
--- a/openlane/ycr_core_top/config.tcl
+++ b/openlane/ycr_core_top/config.tcl
@@ -88,7 +88,7 @@
set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
set ::env(QUIT_ON_MAGIC_DRC) "1"
-set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_LVS_ERROR) "1"
set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
#Need to cross-check why global timing opimization creating setup vio with hugh hold fix
diff --git a/openlane/ycr_intf/config.tcl b/openlane/ycr_intf/config.tcl
index 8e583e5..2ef0b86 100644
--- a/openlane/ycr_intf/config.tcl
+++ b/openlane/ycr_intf/config.tcl
@@ -81,7 +81,7 @@
set ::env(QUIT_ON_TIMING_VIOLATIONS) "0"
set ::env(QUIT_ON_MAGIC_DRC) "1"
-set ::env(QUIT_ON_LVS_ERROR) "0"
+set ::env(QUIT_ON_LVS_ERROR) "1"
set ::env(QUIT_ON_SLEW_VIOLATIONS) "0"
#Need to cross-check why global timing opimization creating setup vio with hugh hold fix
diff --git a/signoff/user_project_wrapper/OPENLANE_VERSION b/signoff/user_project_wrapper/OPENLANE_VERSION
index 078e9d2..80c7664 100644
--- a/signoff/user_project_wrapper/OPENLANE_VERSION
+++ b/signoff/user_project_wrapper/OPENLANE_VERSION
@@ -1 +1 @@
-openlane 0dc6fb79c91082b94f8ded78d70f8bacbab96bf2
+openlane N/A
diff --git a/signoff/user_project_wrapper/PDK_SOURCES b/signoff/user_project_wrapper/PDK_SOURCES
index b08beb4..22e7dc1 100644
--- a/signoff/user_project_wrapper/PDK_SOURCES
+++ b/signoff/user_project_wrapper/PDK_SOURCES
@@ -1 +1,3 @@
-open_pdks 41c0908b47130d5675ff8484255b43f66463a7d6
+openlane 70923d7fbd8998c8da87d905cf9e69bffc13709f
+skywater-pdk c094b6e83a4f9298e47f696ec5a7fd53535ec5eb
+open_pdks 476f7428f7f686de51a5164c702629a9b9f2da46
diff --git a/signoff/user_project_wrapper/final_summary_report.csv b/signoff/user_project_wrapper/final_summary_report.csv
index 330ed0a..d4326b1 100644
--- a/signoff/user_project_wrapper/final_summary_report.csv
+++ b/signoff/user_project_wrapper/final_summary_report.csv
@@ -1,2 +1,2 @@
,design,design_name,config,flow_status,total_runtime,routed_runtime,(Cell/mm^2)/Core_Util,DIEAREA_mm^2,CellPer_mm^2,OpenDP_Util,Peak_Memory_Usage_MB,cell_count,tritonRoute_violations,Short_violations,MetSpc_violations,OffGrid_violations,MinHole_violations,Other_violations,Magic_violations,antenna_violations,lvs_total_errors,cvc_total_errors,klayout_violations,wire_length,vias,wns,pl_wns,optimized_wns,fastroute_wns,spef_wns,tns,pl_tns,optimized_tns,fastroute_tns,spef_tns,HPWL,routing_layer1_pct,routing_layer2_pct,routing_layer3_pct,routing_layer4_pct,routing_layer5_pct,routing_layer6_pct,wires_count,wire_bits,public_wires_count,public_wire_bits,memories_count,memory_bits,processes_count,cells_pre_abc,AND,DFF,NAND,NOR,OR,XOR,XNOR,MUX,inputs,outputs,level,EndCaps,TapCells,Diodes,Total_Physical_Cells,suggested_clock_frequency,suggested_clock_period,CLOCK_PERIOD,SYNTH_STRATEGY,SYNTH_MAX_FANOUT,FP_CORE_UTIL,FP_ASPECT_RATIO,FP_PDN_VPITCH,FP_PDN_HPITCH,PL_TARGET_DENSITY,GLB_RT_ADJUSTMENT,STD_CELL_LIBRARY,CELL_PAD,DIODE_INSERTION_STRATEGY
-0,/project/openlane/user_project_wrapper,user_project_wrapper,user_project_wrapper,flow completed,0h48m46s0ms,0h3m41s0ms,-2.0,-1,-1,-1,575.41,12,0,0,0,0,0,0,-1,0,0,-1,-1,1408320,10261,0.0,-1,-1,0.0,0.0,0.0,-1,-1,0.0,0.0,-1,0.0,5.31,6.28,1.5,2.1,0.0,349,3687,349,3687,0,0,0,12,0,0,0,0,0,0,0,0,-1,-1,-1,0,0,0,0,100.0,10.0,10,AREA 0,5,50,1,80,90,0.55,0.3,sky130_fd_sc_hd,4,0
+0,/home/dinesha/workarea/opencore/git/riscduino_dcore/openlane/user_project_wrapper,user_project_wrapper,user_project_wrapper,flow completed,1h43m41s0ms,0h4m1s0ms,-2.0,-1,-1,-1,594.3,13,0,0,0,0,0,0,-1,0,0,-1,-1,1415412,10457,0.0,-1,-1,0.0,0.0,0.0,-1,-1,0.0,0.0,-1,0.0,5.37,6.22,1.45,2.47,0.0,367,3710,367,3710,0,0,0,13,0,0,0,0,0,0,0,0,-1,-1,-1,0,0,0,0,100.0,10.0,10,AREA 0,5,50,1,80,90,0.55,0.3,sky130_fd_sc_hd,4,0