blob: f4de39b68bde68378e05816a412871c199f55570 [file] [log] [blame]
# Copyright (c) Efabless Corporation. All rights reserved.
# See LICENSE file in the project root for full license information.
proc set_def {def} {
set ::env(CURRENT_DEF) $def
set replace [string map {/ \\/} $def]
exec sed -i -e "s/\\(set ::env(CURRENT_DEF)\\).*/\\1 $replace/" "$::env(GLB_CFG_FILE)"
}
proc prep {args} {
set ::env(timer_start) [clock seconds]
source $::env(OPENLANE_ROOT)/scripts/utils/utils.tcl
set ::env(SCRIPTS_DIR) "$::env(OPENLANE_ROOT)/scripts/"
set ::env(PATH) "$::env(PATH):$::env(SCRIPTS_DIR)/pdn/src/scripts"
set ::env(TCLLIBPATH) "$::env(SCRIPTS_DIR)/pdn/src/scripts"
foreach tcl_file [glob $::env(SCRIPTS_DIR)/utils/*.tcl] {
source $tcl_file
}
foreach tcl_file [glob $::env(SCRIPTS_DIR)/tcl_commands/*.tcl] {
if {[string first "pkgIndex.tcl" $tcl_file 0] == -1} {
source $tcl_file
}
}
set options {{-design required} \
{-tag optional} \
{-config optional} \
}
set flags {-init_design_config -disable_output -overwrite}
set args_copy $args
parse_key_args "flow.tcl" args arg_values $options flags_map $flags
if { [info exists arg_values(-config)] } {
set config_tag $arg_values(-config)
} else {
set config_tag "config"
}
if { [info exist flags_map(-init_design_config)] } {
set config_tag "config"
if { [info exist arg_values(-tag) ] } {
set config_tag $arg_values(-tag)
}
init_design $arg_values(-design) $config_tag
exit
}
if { ! [info exist flags_map(-disable_output)] } {
set ::env(TERMINAL_OUTPUT) "/dev/tty"
} else {
set ::env(TERMINAL_OUTPUT) "/dev/null"
}
set ::env(datetime) [clock format [clock seconds] -format %d-%m_%H-%M]
if { [lsearch -exact $args_copy -tag ] >= 0} {
set tag "$arg_values(-tag)"
} else {
set tag $::env(datetime)
}
#set flow_config "./configuration/flow_default.tcl"
set ::env(CONFIGS) [glob $::env(OPENLANE_ROOT)/configuration/*.tcl]
set ::env(DESIGN_DIR) [file normalize $arg_values(-design)]
if { ![file exists $::env(DESIGN_DIR)] } {
set ::env(DESIGN_DIR) [file normalize $::env(OPENLANE_ROOT)/designs/$arg_values(-design)/]
}
set ::env(DESIGN_CONFIG) $::env(DESIGN_DIR)/$config_tag.tcl
foreach config $::env(CONFIGS) {
source $config
}
source $::env(DESIGN_CONFIG)
set pdk_config $::env(PDK_ROOT)/$::env(PDK)/libs.tech/openlane/config.tcl
set pdk_variant_config $::env(PDK_ROOT)/$::env(PDK)/libs.tech/openlane/$::env(PDK_VARIANT)/config.tcl
source $pdk_config
source $pdk_variant_config
source $::env(DESIGN_CONFIG)
#
############################
# Prep directories and files
############################
#
set ::env(RUN_TAG) "$tag"
set ::env(RUN_DIR) "$::env(DESIGN_DIR)/runs/$tag/"
set ::env(RESULTS_DIR) "$::env(DESIGN_DIR)/runs/$tag/results/"
set ::env(TMP_DIR) "$::env(DESIGN_DIR)/runs/$tag/tmp/"
set ::env(LOG_DIR) "$::env(DESIGN_DIR)/runs/$tag/logs/"
set ::env(REPORTS_DIR) "$::env(DESIGN_DIR)/runs/$tag/reports/"
set ::env(GLB_CFG_FILE) "$::env(DESIGN_DIR)/runs/$tag/config.tcl"
if { [file exists $::env(RUN_DIR)] } {
if { [info exists flags_map(-overwrite)] } {
puts "Removing exisiting run $::env(RUN_DIR)"
exec rm -r $::env(RUN_DIR)
} else {
puts "A run for $::env(DESIGN_NAME) with tag: $tag already exists pass -overwrite option to overwrite it"
}
}
if { [file exists $::env(GLB_CFG_FILE)] } {
if { [info exist flags_map(-overwrite)] } {
puts "Removing $::env(GLB_CFG_FILE)"
exec rm $::env(GLB_CFG_FILE)
} else {
puts "sourcing $::env(GLB_CFG_FILE)"
source $::env(GLB_CFG_FILE)
}
}
set tmp_output {
{yosys "synthesis/yosys"}
{opensta synthesis/opensta}
{verilog2def floorplan/verilog2def}
{ioPlacer floorplan/ioPlacer}
{pdn floorplan/pdn}
{tapcell floorplan/tapcell}
{replaceio placement/replace}
{psn placement/psn}
{opendp placement/opendp}
{addspacers routing/addspacers}
{fastroute routing/fastroute}
{tritonRoute routing/tritonRoute}
{magic magic/magic}
{cts cts/cts}
{lvs lvs/lvs}
}
set final_output \
[list \
[list yosys synthesis/$::env(DESIGN_NAME).synthesis] \
[list tapcell floorplan/$::env(DESIGN_NAME).floorplan] \
[list opendp placement/$::env(DESIGN_NAME).placement] \
[list tritonRoute routing/$::env(DESIGN_NAME).routing] \
[list cts cts/$::env(DESIGN_NAME).cts] \
[list magic magic/$::env(DESIGN_NAME).magic] \
[list lvs lvs/$::env(DESIGN_NAME).lvs] \
]
array set results_file_name [make_array $final_output $::env(RESULTS_DIR)]
array set reports_file_name [make_array $tmp_output $::env(REPORTS_DIR)]
array set logs_file_name [make_array $tmp_output $::env(LOG_DIR)]
array set tmp_file_name [make_array $tmp_output $::env(TMP_DIR)]
foreach {key value} [array get results_file_name] {
set ::env(${key}_result_file_tag) $value
}
foreach {key value} [array get reports_file_name] {
set ::env(${key}_report_file_tag) $value
}
foreach {key value} [array get logs_file_name] {
set ::env(${key}_log_file_tag) $value
}
foreach {key value} [array get tmp_file_name] {
set ::env(${key}_tmp_file_tag) $value
}
exec mkdir -p $::env(RESULTS_DIR) $::env(TMP_DIR) $::env(LOG_DIR) $::env(REPORTS_DIR)
set stages {synthesis floorplan placement cts routing magic lvs}
foreach stage $stages {
exec mkdir -p $::env(RESULTS_DIR)/$stage \
$::env(TMP_DIR)/$stage \
$::env(LOG_DIR)/$stage \
$::env(REPORTS_DIR)/$stage
}
# merge cells
exec $::env(SCRIPTS_DIR)/mergeLef.py -i $::env(TECH_LEF) $::env(CELLS_LEF) -o $::env(TMP_DIR)/merged_unpadded.lef |& tee $::env(TERMINAL_OUTPUT)
set ::env(MERGED_LEF_UNPADDED) $::env(TMP_DIR)/merged_unpadded.lef
# pad lef
set ::env(CELLS_LEF_UNPADDED) $::env(TMP_DIR)/merged_unpadded.lef
try_catch $::env(SCRIPTS_DIR)/padLefMacro.py -s $::env(PLACE_SITE) -r $::env(CELL_PAD) -i $::env(CELLS_LEF_UNPADDED) -o $::env(TMP_DIR)/merged.lef -e "$::env(CELL_PAD_EXECLUDE)" |& tee $::env(TERMINAL_OUTPUT)
set ::env(CELLS_LEF) $::env(TMP_DIR)/merged.lef
if { $::env(USE_GPIO_PADS) } {
exec cp $::env(CELLS_LEF) $::env(CELLS_LEF).old
exec $::env(SCRIPTS_DIR)/mergeLef.py -i $::env(CELLS_LEF).old {*}$::env(GPIO_PADS_LEF) -o $::env(CELLS_LEF)
}
set ::env(MERGED_LEF) $::env(CELLS_LEF)
# trim libs
set trimmed_lib $::env(TMP_DIR)/trimmed.lib
if { ![info exists $trimmed_lib] } {
puts $::env(LIB_SYNTH)
exec $::env(SCRIPTS_DIR)/libtrim.pl $::env(PDK_VARIANT) $::env(LIB_SYNTH) > $trimmed_lib
set ::env(LIB_SYNTH) $trimmed_lib
}
set tracks_copy $::env(TMP_DIR)/tracks_copy.info
exec cp $::env(TRACKS_INFO_FILE) $tracks_copy
# change to system verilog
#if {$::env(SYSTEM_VERILOG)} {
# foreach verilogfile $::env(VERILOG_FILES) {
# system_verilog_2_verilog \
# -include $::env(VERILOG_FILES) \
# -input $verilogfile \
# -output [file rootname $verilogfile].v \
# -define SYNTHESIS
# }
#}
set util $::env(FP_CORE_UTIL)
set density $::env(PL_TARGET_DENSITY)
# Fill config file
#General
exec echo "# General config" > $::env(GLB_CFG_FILE)
set_log ::env(PDK) $::env(PDK) $::env(GLB_CFG_FILE) 1
set_log ::env(PDK_VARIANT) $::env(PDK_VARIANT) $::env(GLB_CFG_FILE) 1
set_log ::env(PDK_ROOT) $::env(PDK_ROOT) $::env(GLB_CFG_FILE) 1
set_log ::env(CELL_PAD) $::env(CELL_PAD) $::env(GLB_CFG_FILE) 1
set_log ::env(MERGED_LEF) $::env(MERGED_LEF) $::env(GLB_CFG_FILE) 1
set_log ::env(TRACKS_INFO_FILE) $::env(TRACKS_INFO_FILE) $::env(GLB_CFG_FILE) 1
set_log ::env(TECH_LEF) $::env(TECH_LEF) $::env(GLB_CFG_FILE) 1
# Design
exec echo "# Design config" >> $::env(GLB_CFG_FILE)
set_log ::env(CLOCK_PERIOD) $::env(CLOCK_PERIOD) $::env(GLB_CFG_FILE) 1
# Synthesis
exec echo "# Synthesis config" >> $::env(GLB_CFG_FILE)
set_log ::env(LIB_SYNTH) $::env(LIB_SYNTH) $::env(GLB_CFG_FILE) 1
set_log ::env(SYNTH_DRIVING_CELL) $::env(SYNTH_DRIVING_CELL) $::env(GLB_CFG_FILE) 1
set_log ::env(SYNTH_CAP_LOAD) $::env(SYNTH_CAP_LOAD) $::env(GLB_CFG_FILE) 1; # femtofarad
set_log ::env(SYNTH_MAX_FANOUT) $::env(SYNTH_MAX_FANOUT) $::env(GLB_CFG_FILE) 1
if { [info exist ::env(SYNTH_MAX_TRAN)] } {
set_log ::env(SYNTH_MAX_TRAN) $::env(SYNTH_MAX_TRAN) $::env(GLB_CFG_FILE) 1
} else {
set_log ::env(SYNTH_MAX_TRAN) "\[\expr {0.1*$::env(CLOCK_PERIOD)}\]" $::env(GLB_CFG_FILE) 1
}
set_log ::env(LIB_MIN) $::env(LIB_MIN) $::env(GLB_CFG_FILE) 1
set_log ::env(LIB_MAX) $::env(LIB_MAX) $::env(GLB_CFG_FILE) 1
set_log ::env(LIB_TYPICAL) $::env(LIB_TYPICAL) $::env(GLB_CFG_FILE) 1
if { $::env(SYNTH_TOP_LEVEL) } {
set_log ::env(SYNTH_SCRIPT) "$::env(OPENLANE_ROOT)/scripts/synth_top.tcl" $::env(GLB_CFG_FILE) 0
} else {
set_log ::env(SYNTH_SCRIPT) "$::env(OPENLANE_ROOT)/scripts/synth.tcl" $::env(GLB_CFG_FILE) 0
}
set_log ::env(SYNTH_STRATEGY) $::env(SYNTH_STRATEGY) $::env(GLB_CFG_FILE) 1
set_log ::env(CLOCK_BUFFER_FANOUT) $::env(CLOCK_BUFFER_FANOUT) $::env(GLB_CFG_FILE) 1
set_log ::env(SYNTH_OPT) 0 $::env(GLB_CFG_FILE) 0
# Floorplan
exec echo "# Floorplan config" >> $::env(GLB_CFG_FILE)
set_log ::env(FP_SIZING) $::env(FP_SIZING) $::env(GLB_CFG_FILE) 0; # absolute, relative
set_log ::env(FP_CORE_UTIL) $util $::env(GLB_CFG_FILE) 1
set_log ::env(FP_ASPECT_RATIO) $::env(FP_ASPECT_RATIO) $::env(GLB_CFG_FILE) 1
set_log ::env(FP_CORE_MARGIN) $::env(FP_CORE_MARGIN) $::env(GLB_CFG_FILE) 1
set_log ::env(FP_IO_HMETAL) $::env(FP_IO_HMETAL) $::env(GLB_CFG_FILE) 1
set_log ::env(FP_IO_VMETAL) $::env(FP_IO_VMETAL) $::env(GLB_CFG_FILE) 1
set_log ::env(FP_IO_RANDOM) 2 $::env(GLB_CFG_FILE) 0; #0 (default, disabled) 1 fully random, 2 evenly distributed, 3 group on the middle of core edge
set_log ::env(FP_WELLTAP_CELL) $::env(FP_WELLTAP_CELL) $::env(GLB_CFG_FILE) 1
set_log ::env(FP_ENDCAP_CELL) $::env(FP_ENDCAP_CELL) $::env(GLB_CFG_FILE) 1
set_log ::env(FP_PDN_VOFFSET) $::env(FP_PDN_VOFFSET) $::env(GLB_CFG_FILE) 1
set_log ::env(FP_PDN_VPITCH) $::env(FP_PDN_VPITCH) $::env(GLB_CFG_FILE) 1
set_log ::env(FP_PDN_HOFFSET) $::env(FP_PDN_HOFFSET) $::env(GLB_CFG_FILE) 1
set_log ::env(FP_PDN_HPITCH) $::env(FP_PDN_HPITCH) $::env(GLB_CFG_FILE) 1
set_log ::env(FP_TAPCELL_DIST) $::env(FP_TAPCELL_DIST) $::env(GLB_CFG_FILE) 1
# Placement
exec echo "# Placement config" >> $::env(GLB_CFG_FILE)
set_log ::env(PL_TARGET_DENSITY) $density $::env(GLB_CFG_FILE) 1
set_log ::env(PL_INIT_COEFF) 0.00002 $::env(GLB_CFG_FILE) 0
set_log ::env(PL_TIME_DRIVEN) $::env(PL_TIME_DRIVEN) $::env(GLB_CFG_FILE) 1
set_log ::env(PL_LIB) $::env(PL_LIB) $::env(GLB_CFG_FILE) 1
set_log ::env(PL_IO_ITER) 5 $::env(GLB_CFG_FILE) 0
# CTS
exec echo "# CTS config" >> $::env(GLB_CFG_FILE)
set_log ::env(CTS_TARGET_SKEW) $::env(CTS_TARGET_SKEW) $::env(GLB_CFG_FILE) 1
set_log ::env(CTS_ROOT_BUFFER) $::env(CTS_ROOT_BUFFER) $::env(GLB_CFG_FILE) 1
set_log ::env(CTS_TECH_DIR) $::env(CTS_TECH_DIR) $::env(GLB_CFG_FILE) 1
set_log ::env(CTS_TOLERANCE) $::env(CTS_TOLERANCE) $::env(GLB_CFG_FILE) 1
# ROUTING
exec echo "# Routing config" >> $::env(GLB_CFG_FILE)
set_log ::env(GLB_RT_MAXLAYER) $::env(GLB_RT_MAXLAYER) $::env(GLB_CFG_FILE) 1
set_log ::env(GLB_RT_ADJUSTMENT) $::env(GLB_RT_ADJUSTMENT) $::env(GLB_CFG_FILE) 1
set_log ::env(GLB_RT_LI1_ADJUSTMENT) $::env(GLB_RT_LI1_ADJUSTMENT) $::env(GLB_CFG_FILE) 1
set_log ::env(GLB_RT_MET1_ADJUSTMENT) $::env(GLB_RT_MET1_ADJUSTMENT) $::env(GLB_CFG_FILE) 1
set_log ::env(GLB_RT_MINLAYER) $::env(GLB_RT_MINLAYER) $::env(GLB_CFG_FILE) 1
set_log ::env(GLB_RT_MAXLAYER) $::env(GLB_RT_MAXLAYER) $::env(GLB_CFG_FILE) 1
# Flow control
exec echo "# Flow control config" >> $::env(GLB_CFG_FILE)
set_log ::env(RUN_MAGIC) $::env(RUN_MAGIC) $::env(GLB_CFG_FILE) 1
set_log ::env(RUN_SIMPLE_CTS) $::env(RUN_SIMPLE_CTS) $::env(GLB_CFG_FILE) 1
set_log ::env(RUN_ROUTING_DETAILED) $::env(RUN_ROUTING_DETAILED) $::env(GLB_CFG_FILE) 1
set_log ::env(CLOCK_TREE_SYNTH) $::env(CLOCK_TREE_SYNTH) $::env(GLB_CFG_FILE) 1
set_log ::env(FILL_INSERTION) $::env(FILL_INSERTION) $::env(GLB_CFG_FILE) 1
if { [info exists ::env(CURRENT_DEF)] } {
set_log ::env(CURRENT_DEF) $::env(CURRENT_DEF) $::env(GLB_CFG_FILE) 1
} else {
set ::env(CURRENT_DEF) 0
set_log ::env(CURRENT_DEF) $::env(CURRENT_DEF) $::env(GLB_CFG_FILE) 1
}
puts "Done"
return 0
}
proc run_cts {args} {
# |----------------------------------------------------|
# |---------------- 4. CTS --------------------------|
# |----------------------------------------------------|
set ::env(CURRENT_STAGE) cts
if {![info exists ::env(OPENROAD)]} {
set ::env(OPENROAD) ~/.local/bin
}
TIMER::timer_start
if {$::env(CLOCK_TREE_SYNTH)} {
exec openroad < $::env(OPENLANE_ROOT)/scripts/cts.tcl |& tee $::env(TERMINAL_OUTPUT)
exit
# set_core_dims \
# -log_path $::env(verilog2def_log_file_tag).log \
#
# gen_cts_config \
# -verilog $::env(yosys_result_file_tag).v \
# -def $::env(opendp_result_file_tag).def \
# -root_buffer $::env(CTS_ROOT_BUFFER) \
# -target_skew $::env(CTS_TARGET_SKEW) \
# -output $::env(cts_tmp_file_tag).config \
# -toler $::env(CTS_TOLERANCE)
#
# gen_clock_tree \
# -config $::env(cts_tmp_file_tag).config
# eval exec mv [glob $::env(RESULTS_DIR)/cts/*] $::env(TMP_DIR)/cts/
# exec mv $::env(TMP_DIR)/cts/$::env(DESIGN_NAME).cts.v $::env(RESULTS_DIR)/cts/$::env(DESIGN_NAME).cts.v
# exec mv $::env(TMP_DIR)/cts/$::env(DESIGN_NAME).cts.def $::env(RESULTS_DIR)/cts/$::env(DESIGN_NAME).cts.def
} else {
exec echo "SKIPPED!" >> $::env(cts_log_file_tag).log
try_catch cp $::env(opendp_result_file_tag).def $::env(cts_result_file_tag).def
}
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" >> $::env(cts_log_file_tag)_runtime.txt
}
proc run_magic {args} {
# |----------------------------------------------------|
# |---------------- 6. TAPE-OUT ---------------------|
# |----------------------------------------------------|
if {$::env(RUN_MAGIC)} {
puts "Streaming out GDS II..."
set ::env(CURRENT_STAGE) finishing
if {[catch {exec tclsh $::env(SCRIPTS_DIR)/run_magic.tcl} issue]} { }
# set PDKPATH $::env(PDK_ROOT)/$::env(PDK)/
# set tech $PDKPATH/libs.tech/magic/current/EFS8A.tech
# cd $::env(TMP_DIR)
# exec /ef/apps/bin/magicGdrc -T $tech $::env(magic_result_file_tag).gds $::env(DESIGN_NAME) \
|& tee $::env(TERMINAL_OUTPUT) $::env(magic_log_file_tag).drc
}
}
proc run_magic_drc {args} {
set magicrc $::env(TMP_DIR)/magic.magicrc
set ::env(PDKPATH) "$::env(PDK_ROOT)/ef-skywater-s8/EFS8A"
set ::env(MAGPATH) "$::env(PDKPATH)/libs.ref/maglef"
exec envsubst < $::env(MAGIC_MAGICRC) > $magicrc
exec magic \
-noconsole \
-dnull \
-rcfile $magicrc \
$::env(SCRIPTS_DIR)/magic_drc.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) $::env(magic_log_file_tag)_drc.log
}
proc padframe_gen {args} {
set pfg_exec $::env(SCRIPTS_DIR)/pfg.py
set pf_src $::env(DESIGN_DIR)/src
set pf_src_tmp $::env(TMP_DIR)/src
file copy $pf_src $pf_src_tmp
fake_display_buffer
exec $pfg_exec -nogui -tech-path=$::env(PDK_ROOT)/$::env(PDK) \
-project-path=$pf_src_tmp \
|& tee $::env(TERMINAL_OUTPUT) $pf_src_tmp/pfg.log
kill_display_buffer
}
package provide openlane 0.9