mirror of
https://github.com/The-OpenROAD-Project/OpenLane.git
synced 2026-05-29 00:23:55 +08:00
Miscellaneous Enhancements (#745)
+ Add RUN_MAGIC_DRC flag to control running DRC with magic + Add RUN_LVS flag to control running LVS ~ replace grepCount.sh with something sane
This commit is contained in:
@@ -263,7 +263,9 @@ These variables worked initially, but they were too sky130 specific to be scalab
|
||||
| `USE_GPIO_PADS` | Decides whether or not to use the gpio pads in routing by merging their LEF file set in `::env(USE_GPIO_ROUTING_LEF)` and blackboxing their verilog modules set in `::env(GPIO_PADS_VERILOG)`. 1=Enabled, 0=Disabled. <br> (Default: `0`) |
|
||||
| `LEC_ENABLE` | Enables logic verification using yosys, for comparing each netlist at each stage of the flow with the previous netlist and verifying that they are logically equivalent. Warning: this will increase the runtime significantly. 1 = Enabled, 0 = Disabled <br> (Default: `0`)|
|
||||
| `RUN_ROUTING_DETAILED` | Enables detailed routing. 1 = Enabled, 0 = Disabled <br> (Default: `1`)|
|
||||
| `RUN_LVS` | Enables running LVS. 1 = Enabled, 0 = Disabled <br> (Default: `1`)|
|
||||
| `RUN_MAGIC` | Enables running magic and GDSII streaming. 1 = Enabled, 0 = Disabled <br> (Default: `1`)|
|
||||
| `RUN_MAGIC_DRC` | Enables running magic DRC on GDS-II produced by magic. 1 = Enabled, 0 = Disabled <br> (Default: `1`)|
|
||||
| `RUN_KLAYOUT` | Enables running Klayout and GDSII streaming. 1 = Enabled, 0 = Disabled <br> (Default: `1`)|
|
||||
| `RUN_KLAYOUT_DRC` | Enables running Klayout DRC on GDS-II produced by magic. 1 = Enabled, 0 = Disabled <br> (Default: `1`)|
|
||||
| `KLAYOUT_DRC_KLAYOUT_GDS` | Enables running Klayout DRC on GDS-II produced by Klayout. 1 = Enabled, 0 = Disabled <br> (Default: `0`)|
|
||||
|
||||
@@ -22,10 +22,13 @@ if { ! [info exists ::env(STD_CELL_LIBRARY)] } {
|
||||
set ::env(USE_GPIO_PADS) 0
|
||||
|
||||
# Flow control defaults
|
||||
set ::env(RUN_LVS) 1
|
||||
|
||||
set ::env(LEC_ENABLE) 0
|
||||
set ::env(YOSYS_REWRITE_VERILOG) 0
|
||||
|
||||
set ::env(RUN_MAGIC) 1
|
||||
set ::env(RUN_MAGIC_DRC) 1
|
||||
set ::env(MAGIC_PAD) 0
|
||||
set ::env(MAGIC_ZEROIZE_ORIGIN) 0
|
||||
set ::env(MAGIC_GENERATE_GDS) 1
|
||||
@@ -75,4 +78,4 @@ if { [file exists /build/transforms/] } {
|
||||
set ::env(PSN_TRANSFORM_PATH) /build/transforms
|
||||
} else {
|
||||
set ::env(PSN_TRANSFORM_PATH) $::env(HOME)/.local/transforms
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# Copyright 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.
|
||||
|
||||
grep $1 $2 | wc -l
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
|
||||
proc check_assign_statements {args} {
|
||||
set checker [ exec sh $::env(SCRIPTS_DIR)/grepCount.sh assign $::env(synthesis_results).v ]
|
||||
set checker [count_matches assign $::env(synthesis_results).v]
|
||||
|
||||
if { $checker != 0 } {
|
||||
puts_err "There are assign statements in the netlist"
|
||||
@@ -207,7 +207,7 @@ proc check_macro_placer_num_solns {args} {
|
||||
|
||||
proc quit_on_tr_drc {args} {
|
||||
if { [info exists ::env(QUIT_ON_TR_DRC)] && $::env(QUIT_ON_TR_DRC) } {
|
||||
set checker [ exec sh $::env(SCRIPTS_DIR)/grepCount.sh violation $::env(routing_reports)/detailed.drc ]
|
||||
set checker [count_matches violation $::env(routing_reports)/detailed.drc]
|
||||
|
||||
if { $checker != 0 } {
|
||||
puts_err "There are violations in the design after detailed routing."
|
||||
@@ -227,7 +227,7 @@ proc quit_on_magic_drc {args} {
|
||||
}
|
||||
parse_key_args "quit_on_magic_drc" args arg_values $options
|
||||
|
||||
set checker [ exec sh $::env(SCRIPTS_DIR)/grepCount.sh violation $arg_values(-log) ]
|
||||
set checker [count_matches violation $arg_values(-log)]
|
||||
|
||||
if { $checker != 0 } {
|
||||
puts_err "There are violations in the design after Magic DRC."
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
proc verilog_to_verilogPower {args} {
|
||||
puts_info "Adding Power Nets to Verilog..."
|
||||
set options {
|
||||
{-input required}
|
||||
{-output required}
|
||||
{-lef required}
|
||||
{-power required}
|
||||
{-ground required}
|
||||
{-input required}
|
||||
{-output required}
|
||||
{-lef required}
|
||||
{-power required}
|
||||
{-ground required}
|
||||
}
|
||||
set flags {}
|
||||
parse_key_args "verilog_to_verilogPower" args arg_values $options flags_map $flags
|
||||
@@ -32,10 +32,10 @@ proc verilog_to_verilogPower {args} {
|
||||
set lef $arg_values(-lef)
|
||||
|
||||
try_catch $bin \
|
||||
-v $power \
|
||||
-g $gnd \
|
||||
-l $lef \
|
||||
$in |& tee $out
|
||||
-v $power \
|
||||
-g $gnd \
|
||||
-l $lef \
|
||||
$in |& tee $out
|
||||
}
|
||||
|
||||
# WORKS ON DEF FILES
|
||||
@@ -43,13 +43,13 @@ proc write_powered_verilog {args} {
|
||||
increment_index
|
||||
puts_info "Writing Powered Verilog..."
|
||||
set options {
|
||||
{-def optional}
|
||||
{-output_def optional}
|
||||
{-output_verilog optional}
|
||||
{-lef optional}
|
||||
{-power optional}
|
||||
{-ground optional}
|
||||
{-powered_netlist optional}
|
||||
{-def optional}
|
||||
{-output_def optional}
|
||||
{-output_verilog optional}
|
||||
{-lef optional}
|
||||
{-power optional}
|
||||
{-ground optional}
|
||||
{-powered_netlist optional}
|
||||
}
|
||||
set flags {}
|
||||
parse_key_args "write_powered_verilog" args arg_values $options flags_map $flags
|
||||
@@ -68,86 +68,88 @@ proc write_powered_verilog {args} {
|
||||
}
|
||||
|
||||
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/write_powered_def.py \
|
||||
-d $arg_values(-def) \
|
||||
-l $arg_values(-lef) \
|
||||
--power-port $arg_values(-power) \
|
||||
--ground-port $arg_values(-ground) \
|
||||
--powered-netlist $arg_values(-powered_netlist) \
|
||||
-o $arg_values(-output_def) \
|
||||
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(routing_logs)/write_powered_verilog.log]
|
||||
|
||||
-d $arg_values(-def) \
|
||||
-l $arg_values(-lef) \
|
||||
--power-port $arg_values(-power) \
|
||||
--ground-port $arg_values(-ground) \
|
||||
--powered-netlist $arg_values(-powered_netlist) \
|
||||
-o $arg_values(-output_def) \
|
||||
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(routing_logs)/write_powered_verilog.log]
|
||||
|
||||
write_verilog $arg_values(-output_verilog) -def $arg_values(-output_def) -log $::env(routing_logs)/write_verilog.log -canonical
|
||||
}
|
||||
|
||||
# "layout": a spice netlist
|
||||
# "schematic": a verilog netlist
|
||||
proc run_lvs {{layout "$::env(EXT_NETLIST)"} {schematic "$::env(CURRENT_NETLIST)"}} {
|
||||
# LEF LVS output to lvs.lef.log, design.lvs.lef.log, design.lvs.lef.json, design.lvs.lef.log
|
||||
# GDS LVS output to lvs.gds.log, design.lvs.gds.log, design.lvs.gds.json, design.lvs.gds.log
|
||||
# GDS LVS uses STD_CELL_LIBRARY spice and
|
||||
# if defined, additional LVS_EXTRA_STD_CELL_LIBRARY spice and LVS_EXTRA_GATE_LEVEL_VERILOG files
|
||||
increment_index
|
||||
TIMER::timer_start
|
||||
if { [info exist ::env(MAGIC_EXT_USE_GDS)] && $::env(MAGIC_EXT_USE_GDS) } {
|
||||
set extract_type gds
|
||||
puts_info "Running GDS LVS..."
|
||||
} else {
|
||||
set extract_type lef
|
||||
puts_info "Running LEF LVS..."
|
||||
}
|
||||
|
||||
set layout [subst $layout]
|
||||
set schematic [subst $schematic]
|
||||
|
||||
set setup_file $::env(NETGEN_SETUP_FILE)
|
||||
set module_name $::env(DESIGN_NAME)
|
||||
#writes setup_file_*_lvs to tmp directory.
|
||||
set lvs_file_path [index_file $::env(finishing_tmpfiles)/setup_file.$extract_type.lvs]
|
||||
set lvs_file [open $lvs_file_path w]
|
||||
if { "$extract_type" == "gds" } {
|
||||
if { [info exist ::env(LVS_EXTRA_STD_CELL_LIBRARY)] } {
|
||||
set libs_in $::env(LVS_EXTRA_STD_CELL_LIBRARY)
|
||||
foreach lib_file $libs_in {
|
||||
puts $lvs_file "puts \"Reading spice netlist file $lib_file\""
|
||||
puts $lvs_file "readnet spice $lib_file 1"
|
||||
}
|
||||
if { $::env(RUN_LVS) } {
|
||||
# LEF LVS output to lvs.lef.log, design.lvs.lef.log, design.lvs.lef.json, design.lvs.lef.log
|
||||
# GDS LVS output to lvs.gds.log, design.lvs.gds.log, design.lvs.gds.json, design.lvs.gds.log
|
||||
# GDS LVS uses STD_CELL_LIBRARY spice and
|
||||
# if defined, additional LVS_EXTRA_STD_CELL_LIBRARY spice and LVS_EXTRA_GATE_LEVEL_VERILOG files
|
||||
increment_index
|
||||
TIMER::timer_start
|
||||
if { [info exist ::env(MAGIC_EXT_USE_GDS)] && $::env(MAGIC_EXT_USE_GDS) } {
|
||||
set extract_type gds
|
||||
puts_info "Running GDS LVS..."
|
||||
} else {
|
||||
if { [info exist ::env(STD_CELL_LIBRARY)] } {
|
||||
set std_cell_source $::env(PDK_ROOT)/$::env(PDK)/libs.ref/$::env(STD_CELL_LIBRARY)/spice/$::env(STD_CELL_LIBRARY).spice
|
||||
set extract_type lef
|
||||
puts_info "Running LEF LVS..."
|
||||
}
|
||||
|
||||
set layout [subst $layout]
|
||||
set schematic [subst $schematic]
|
||||
|
||||
set setup_file $::env(NETGEN_SETUP_FILE)
|
||||
set module_name $::env(DESIGN_NAME)
|
||||
#writes setup_file_*_lvs to tmp directory.
|
||||
set lvs_file_path [index_file $::env(finishing_tmpfiles)/setup_file.$extract_type.lvs]
|
||||
set lvs_file [open $lvs_file_path w]
|
||||
if { "$extract_type" == "gds" } {
|
||||
if { [info exist ::env(LVS_EXTRA_STD_CELL_LIBRARY)] } {
|
||||
set libs_in $::env(LVS_EXTRA_STD_CELL_LIBRARY)
|
||||
foreach lib_file $libs_in {
|
||||
puts $lvs_file "puts \"Reading spice netlist file $lib_file\""
|
||||
puts $lvs_file "readnet spice $lib_file 1"
|
||||
}
|
||||
} else {
|
||||
set std_cell_source $::env(PDK_ROOT)/$::env(PDK)/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice
|
||||
if { [info exist ::env(STD_CELL_LIBRARY)] } {
|
||||
set std_cell_source $::env(PDK_ROOT)/$::env(PDK)/libs.ref/$::env(STD_CELL_LIBRARY)/spice/$::env(STD_CELL_LIBRARY).spice
|
||||
} else {
|
||||
set std_cell_source $::env(PDK_ROOT)/$::env(PDK)/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice
|
||||
}
|
||||
puts $lvs_file "puts \"Reading spice netlist file $std_cell_source\""
|
||||
puts $lvs_file "readnet spice $std_cell_source 1"
|
||||
}
|
||||
puts $lvs_file "puts \"Reading spice netlist file $std_cell_source\""
|
||||
puts $lvs_file "readnet spice $std_cell_source 1"
|
||||
}
|
||||
if { [info exist ::env(LVS_EXTRA_GATE_LEVEL_VERILOG)] } {
|
||||
set libs_in $::env(LVS_EXTRA_GATE_LEVEL_VERILOG)
|
||||
foreach lib_file $libs_in {
|
||||
puts $lvs_file "puts \"Reading verilog netlist file $lib_file\""
|
||||
puts $lvs_file "readnet verilog $lib_file 1"
|
||||
if { [info exist ::env(LVS_EXTRA_GATE_LEVEL_VERILOG)] } {
|
||||
set libs_in $::env(LVS_EXTRA_GATE_LEVEL_VERILOG)
|
||||
foreach lib_file $libs_in {
|
||||
puts $lvs_file "puts \"Reading verilog netlist file $lib_file\""
|
||||
puts $lvs_file "readnet verilog $lib_file 1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set extraction_prefix [index_file $::env(finishing_logs)/$::env(DESIGN_NAME).$extract_type]
|
||||
|
||||
puts $lvs_file "lvs {$layout $module_name} {$schematic $module_name} $setup_file $extraction_prefix.log -json"
|
||||
close $lvs_file
|
||||
|
||||
puts_info "$layout against $schematic"
|
||||
|
||||
try_catch netgen -batch source $lvs_file_path \
|
||||
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/$extract_type.log]
|
||||
|
||||
set count_lvs_log [index_file $::env(finishing_logs)/$::env(DESIGN_NAME).lvs.$extract_type.log]
|
||||
|
||||
exec python3 $::env(SCRIPTS_DIR)/count_lvs.py \
|
||||
-f $extraction_prefix.json \
|
||||
|& tee $::env(TERMINAL_OUTPUT) $count_lvs_log
|
||||
|
||||
TIMER::timer_stop
|
||||
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "lvs - netgen"
|
||||
quit_on_lvs_error -log $count_lvs_log
|
||||
}
|
||||
|
||||
set extraction_prefix [index_file $::env(finishing_logs)/$::env(DESIGN_NAME).$extract_type]
|
||||
|
||||
puts $lvs_file "lvs {$layout $module_name} {$schematic $module_name} $setup_file $extraction_prefix.log -json"
|
||||
close $lvs_file
|
||||
|
||||
puts_info "$layout against $schematic"
|
||||
|
||||
try_catch netgen -batch source $lvs_file_path \
|
||||
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/$extract_type.log]
|
||||
|
||||
set count_lvs_log [index_file $::env(finishing_logs)/$::env(DESIGN_NAME).lvs.$extract_type.log]
|
||||
|
||||
exec python3 $::env(SCRIPTS_DIR)/count_lvs.py \
|
||||
-f $extraction_prefix.json \
|
||||
|& tee $::env(TERMINAL_OUTPUT) $count_lvs_log
|
||||
|
||||
TIMER::timer_stop
|
||||
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "lvs - netgen"
|
||||
quit_on_lvs_error -log $count_lvs_log
|
||||
}
|
||||
|
||||
proc run_netgen {args} {
|
||||
@@ -155,3 +157,4 @@ proc run_netgen {args} {
|
||||
}
|
||||
|
||||
package provide openlane 0.9
|
||||
|
||||
|
||||
@@ -88,50 +88,52 @@ proc run_magic {args} {
|
||||
|
||||
|
||||
proc run_magic_drc {args} {
|
||||
increment_index
|
||||
TIMER::timer_start
|
||||
puts_info "Running Magic DRC..."
|
||||
if { $::env(RUN_MAGIC_DRC) } {
|
||||
increment_index
|
||||
TIMER::timer_start
|
||||
puts_info "Running Magic DRC..."
|
||||
|
||||
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)"
|
||||
set ::env(drc_prefix) $::env(finishing_reports)/drc
|
||||
# Has to be maglef for DRC Checking
|
||||
set ::env(MAGTYPE) maglef
|
||||
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)"
|
||||
set ::env(drc_prefix) $::env(finishing_reports)/drc
|
||||
# Has to be maglef for DRC Checking
|
||||
set ::env(MAGTYPE) maglef
|
||||
|
||||
try_catch magic \
|
||||
-noconsole \
|
||||
-dnull \
|
||||
-rcfile $::env(MAGIC_MAGICRC) \
|
||||
$::env(SCRIPTS_DIR)/magic/drc.tcl \
|
||||
</dev/null \
|
||||
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/drc.log]
|
||||
try_catch magic \
|
||||
-noconsole \
|
||||
-dnull \
|
||||
-rcfile $::env(MAGIC_MAGICRC) \
|
||||
$::env(SCRIPTS_DIR)/magic/drc.tcl \
|
||||
</dev/null \
|
||||
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/drc.log]
|
||||
|
||||
puts_info "Converting Magic DRC Violations to Magic Readable Format..."
|
||||
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_tcl.py \
|
||||
-i $::env(drc_prefix).rpt \
|
||||
-o $::env(drc_prefix).tcl
|
||||
puts_info "Converting Magic DRC Violations to Magic Readable Format..."
|
||||
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_tcl.py \
|
||||
-i $::env(drc_prefix).rpt \
|
||||
-o $::env(drc_prefix).tcl
|
||||
|
||||
puts_info "Converting Magic DRC Violations to Klayout XML Database..."
|
||||
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_tr_drc.py \
|
||||
-i $::env(drc_prefix).rpt \
|
||||
-o $::env(drc_prefix).tr
|
||||
puts_info "Converting Magic DRC Violations to Klayout XML Database..."
|
||||
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_tr_drc.py \
|
||||
-i $::env(drc_prefix).rpt \
|
||||
-o $::env(drc_prefix).tr
|
||||
|
||||
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/tr2klayout.py \
|
||||
-i $::env(drc_prefix).tr \
|
||||
-o $::env(drc_prefix).klayout.xml \
|
||||
--design-name $::env(DESIGN_NAME)
|
||||
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/tr2klayout.py \
|
||||
-i $::env(drc_prefix).tr \
|
||||
-o $::env(drc_prefix).klayout.xml \
|
||||
--design-name $::env(DESIGN_NAME)
|
||||
|
||||
if { $::env(MAGIC_CONVERT_DRC_TO_RDB) == 1 } {
|
||||
puts_info "Converting DRC Violations to RDB Format..."
|
||||
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_rdb.py \
|
||||
--magic_drc_in $::env(drc_prefix).rpt \
|
||||
--rdb_out $::env(drc_prefix).rdb
|
||||
puts_info "Converted DRC Violations to RDB Format"
|
||||
}
|
||||
file copy -force $::env(MAGIC_MAGICRC) $::env(finishing_results)/.magicrc
|
||||
TIMER::timer_stop
|
||||
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "drc - magic"
|
||||
|
||||
quit_on_magic_drc -log $::env(drc_prefix).tr
|
||||
if { $::env(MAGIC_CONVERT_DRC_TO_RDB) == 1 } {
|
||||
puts_info "Converting DRC Violations to RDB Format..."
|
||||
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_rdb.py \
|
||||
--magic_drc_in $::env(drc_prefix).rpt \
|
||||
--rdb_out $::env(drc_prefix).rdb
|
||||
puts_info "Converted DRC Violations to RDB Format"
|
||||
}
|
||||
file copy -force $::env(MAGIC_MAGICRC) $::env(finishing_results)/.magicrc
|
||||
TIMER::timer_stop
|
||||
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "drc - magic"
|
||||
|
||||
quit_on_magic_drc -log $::env(drc_prefix).tr
|
||||
}
|
||||
}
|
||||
|
||||
proc run_magic_spice_export {args} {
|
||||
@@ -304,7 +306,7 @@ antennacheck
|
||||
try_catch awk "/Cell:/ {print \$2}" $antenna_log > $antenna_log
|
||||
|
||||
set ::env(ANTENNA_CHECKER_LOG) $antenna_log
|
||||
|
||||
|
||||
TIMER::timer_stop
|
||||
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "antenna check - magic"
|
||||
|
||||
|
||||
@@ -335,5 +335,10 @@ proc assert_files_exist {files} {
|
||||
}
|
||||
}
|
||||
|
||||
proc count_matches {pattern search_file} {
|
||||
set count [exec bash -c "grep $pattern $search_file | wc -l"]
|
||||
return $count
|
||||
}
|
||||
|
||||
|
||||
package provide openlane_utils 0.9
|
||||
|
||||
Reference in New Issue
Block a user