Skip to content

Commit

Permalink
Enhancements + Bugfixes to Multi-PDK Support (The-OpenROAD-Project#1138)
Browse files Browse the repository at this point in the history
+ Added two new PDK-specific variables: SYNTH_CLK_DRIVING_CELL, SYNTH_DRIVING_CELL_PIN, which are used in the sdc file so clocks specifically can be driven by a different cell
~ NO_PG now also generated for the excluded cells
~ Document PDK-specific variables in their right place
~ Magic -> 085131b
~ Fix verify_versions.py
  • Loading branch information
donn authored Jun 18, 2022
1 parent 732c856 commit a988333
Show file tree
Hide file tree
Showing 14 changed files with 123 additions and 121 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ export PDK_ROOT := $(shell $(PYTHON_BIN) -c "import os; print(os.path.realpath('
PDK_OPTS = -v $(PDK_ROOT):$(PDK_ROOT) -e PDK_ROOT=$(PDK_ROOT)
endif

export PDK ?= sky130A
export STD_CELL_LIBRARY ?= sky130_fd_sc_hd
STD_CELL_OPTS := -e STD_CELL_LIBRARY=$(STD_CELL_LIBRARY)

PDK_OPTS += -e PDK=$(PDK) -e STD_CELL_LIBRARY=$(STD_CELL_LIBRARY)

# ./designs is mounted over ./install so env.tcl is not found inside the Docker
# container if the user had previously installed it.
Expand Down
94 changes: 36 additions & 58 deletions configuration/README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dependencies/tool_metadata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
make install
- name: magic
repo: https://github.com/rtimothyedwards/magic
commit: a205a0e9419f973346740171618956afe08b2d74
commit: 085131b090cb511d785baf52a10cf6df8a657d44
build: |
./configure --prefix=$PREFIX $MAGIC_CONFIG_OPTS
make clean
Expand Down Expand Up @@ -59,7 +59,7 @@
- name: openroad_app
repo: https://github.com/The-OpenROAD-Project/OpenROAD
commit: 0b8b7ae255f8fbbbefa57d443949b84e73eed757
build: ''
build: ""
in_install: false
- name: git
repo: https://github.com/git/git
Expand Down
2 changes: 1 addition & 1 deletion dependencies/verify_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def verify_versions(
if not os.getenv("PDK_ROOT"):
pdk_root = join(openlane_dir, "pdks")

if pdk is not None:
if pdk.startswith("sky130"):
pdk_dir = join(pdk_root, pdk)

if not pathlib.Path(pdk_dir).is_dir():
Expand Down
57 changes: 29 additions & 28 deletions docs/source/pdk_structure.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Porting a PDK

This readme describes how to port a PDK to openlane.
This readme describes how to structure a PDK for use with OpenLane.

## Folder structure
This is the expected folder structure for a PDK:
Expand Down Expand Up @@ -29,8 +28,7 @@ This is the expected folder structure for a PDK:


## PDK Variables

This section defines the neccessary variables for PDK configuration file. Note that all defaults are for sky130A.
This section defines the neccessary variables for PDK configuration file. Note that all examples given are for sky130A.

| Variable | Description |
|---------------|---------------------------------------------------------------|
Expand All @@ -51,27 +49,27 @@ This section defines the neccessary variables for PDK configuration file. Note t
| `NETGEN_SETUP_FILE` | Points to the setup file for netgen(lvs), that can exclude certain cells etc.. |
| `FP_TAPCELL_DIST` | The distance between tapcell columns. Used in floorplanning in tapcell insertion. |
| `DEFAULT_MAX_TRAN` | Defines the default maximum transition value, used in CTS & synthesis. |
| `FP_PDN_RAIL_OFFSET` | Defines the rail offset for met1 used in PDN. <br> Default: `0`. |
| `FP_PDN_VWIDTH` | Defines the strap width for the vertical layer used in PDN. <br> Default: `1.6`. |
| `FP_PDN_HWIDTH` | Defines the strap width for the horizontal layer used in PDN. <br> Default: `1.6`. |
| `FP_PDN_CORE_RING_VWIDTH` | Defines the vertical width for the vertical layer used to create the core ring in the PDN. <br> Default: `20`. |
| `FP_PDN_CORE_RING_HWIDTH` | Defines the horizontal width for the horizontal layer used to create the core ring in the PDN. <br> Default: `20`. |
| `FP_PDN_CORE_RING_VSPACING` | Defines the spacing for the vertical layer used to create the core ring in the PDN. <br> Default: `5`. |
| `FP_PDN_CORE_RING_HSPACING` | Defines the spacing for the horizontal layer used to create the core ring in the PDN. <br> Default: `5`. |
| `FP_PDN_CORE_RING_VOFFSET` | Defines the offset for the vertical layer used to create the core ring in the PDN. <br> Default: `20`. |
| `FP_PDN_CORE_RING_HOFFSET` | Defines the offset for the horizontal layer used to create the core ring in the PDN. <br> Default: `20`. |
| `WIRE_RC_LAYER` | The metal layer used in estimate parastics `set_wire_rc`. <br> Default: `met1`.|
| `GLB_RT_LAYER_ADJUSTMENTS` | Layer-specific reductions in the routing capacity of the edges between the cells in the global routing graph, delimited by commas. Values range from 0 to 1. <br> (Default: `0.99,0,0,0,0,0`)
| `FP_IO_HLAYER` | The metal layer on which to place the io pins horizontally (top and bottom of the die). <br>(Default: `met3`)|
| `FP_IO_VLAYER` | The metal layer on which to place the io pins vertically (sides of the die) <br> (Default: `met2`)|
| `RT_MIN_LAYER` | The lowest metal layer to route on. <br>(Default: `met1`)|
| `RT_MAX_LAYER` | The highest metal layer to route on. <br> (Default: `met5`)|
| `FP_PDN_RAIL_OFFSET` | Defines the rail offset for met1 used in PDN. <br> (Example: `0`) | |
| `FP_PDN_VWIDTH` | Defines the strap width for the vertical layer used in PDN. <br> (Example: `1.6`) | |
| `FP_PDN_HWIDTH` | Defines the strap width for the horizontal layer used in PDN. <br> (Example: `1.6`) | |
| `FP_PDN_CORE_RING_VWIDTH` | Defines the vertical width for the vertical layer used to create the core ring in the PDN. <br> (Example: `20`) | |
| `FP_PDN_CORE_RING_HWIDTH` | Defines the horizontal width for the horizontal layer used to create the core ring in the PDN. <br> (Example: `20`) | |
| `FP_PDN_CORE_RING_VSPACING` | Defines the spacing for the vertical layer used to create the core ring in the PDN. <br> (Example: `5`) | |
| `FP_PDN_CORE_RING_HSPACING` | Defines the spacing for the horizontal layer used to create the core ring in the PDN. <br> (Example: `5`) | |
| `FP_PDN_CORE_RING_VOFFSET` | Defines the offset for the vertical layer used to create the core ring in the PDN. <br> (Example: `20`) | |
| `FP_PDN_CORE_RING_HOFFSET` | Defines the offset for the horizontal layer used to create the core ring in the PDN. <br> (Example: `20`) | |
| `WIRE_RC_LAYER` | The metal layer used in estimate parastics `set_wire_rc`. <br> (Example: `met1`) ||
| `GLB_RT_LAYER_ADJUSTMENTS` | Layer-specific reductions in the routing capacity of the edges between the cells in the global routing graph, delimited by commas. Values range from 0 to 1. <br> (Example: `0.99,0,0,0,0,0`)
| `FP_IO_HLAYER` | The metal layer on which to place the io pins horizontally (top and bottom of the die). <br>(Example: `met3`)|
| `FP_IO_VLAYER` | The metal layer on which to place the io pins vertically (sides of the die) <br> (Example: `met2`)|
| `RT_MIN_LAYER` | The lowest metal layer to route on. <br>(Example: `met1`)|
| `RT_MAX_LAYER` | The highest metal layer to route on. <br> (Example: `met5`)|
| `RCX_RULES_MIN` | OpenRCX rules at the minimum corner. (Optional) |
| `RCX_RULES` | OpenRCX rules at the nominal corner. |
| `RCX_RULES_MAX` | OpenRCX rules at the maximum corner. (Optional) |


## Standard cell library-specific variables
## SCL-specific variables

This section defines the necessary variables to configure a standard cell library for use with OpenLane:

Expand All @@ -87,22 +85,25 @@ This section defines the necessary variables to configure a standard cell librar
| `PLACE_SITE_HEIGHT` | Defines the main site height. Used during floorplanning to generate the rows. |
| `FP_WELLTAP_CELL` | Defines the tapcell to be used in tapcell insertion. <br> If this is not defined then tapcell insertion will be skipped but the flow will resume normally |
| `FP_ENDCAP_CELL` | Defines the decapcell. Inserted during floorplanning at the sides of the design. |
| `SYNTH_DRIVING_CELL` | Defines the cell to drive the input ports. Used in synthesis |
| `SYNTH_DRIVING_CELL_PIN` | Defines the driving cell output pin. Used in synthesis |
| `SYNTH_DRIVING_CELL` | The cell to drive the input ports, used in synthesis and static timing analysis. <br>(Example: `sky130_fd_sc_hd__inv_1`)|
| `SYNTH_DRIVING_CELL_PIN` | The name of the `SYNTH_DRIVING_CELL`'s output pin. <br>(Default: `Y`)|
| `SYNTH_CLK_DRIVING_CELL` | An alternative cell with which to drive clock inputs. Can be left empty, where the SDC script will use `SYNTH_DRIVING_CELL` for clock inputs as well. |
| `SYNTH_CLK_DRIVING_CELL_PIN` | The name of the SYNTH_CLK_DRIVING_CELL output pin. Can be left empty, where the SDC script will use `SYNTH_DRIVING_CELL_PIN`. |
| `SYNTH_CAP_LOAD` | Defines the capacitive load on the output ports in femtofarads. Used in synthesis |
| `SYNTH_MIN_BUF_PORT` | Defines the buffer, followed by its input port and output port to be used by `ins_buf` statements by yosys. It inserts buffer cells into the design for directly connected wires. Example: `sky130_fd_sc_hd__buf_2 A X` |
| `SYNTH_TIEHI_PORT` | Defines the tie high cell followed by the port that implements the tie high functionality. Used in synthesis. Example: `sky130_fd_sc_hd__conb_1 HI` |
| `SYNTH_TIELO_PORT` | Defines the tie low cell followed by the port that implements the tie high functionality. Used in synthesis. Example: `sky130_fd_sc_hd__conb_1 LO` |
| `SYNTH_MIN_BUF_PORT` | Defines the buffer, followed by its input port and output port to be used by `ins_buf` statements by yosys. It inserts buffer cells into the design for directly connected wires. <br> (Example: `sky130_fd_sc_hd__buf_2 A X` )|
| `SYNTH_TIEHI_PORT` | Defines the tie high cell followed by the port that implements the tie high functionality. Used in synthesis. <br> (Example: `sky130_fd_sc_hd__conb_1 HI`)|
| `SYNTH_TIELO_PORT` | Defines the tie low cell followed by the port that implements the tie high functionality. Used in synthesis. <br> (Example: `sky130_fd_sc_hd__conb_1 LO`)|
| `CELL_CLK_PORT` | Defines the name of clk port of the flip flops and other cells. Used in CTS. |
| `PL_LIB` | Points to the lib view used in time driven placement. |
| `FILL_CELL` | Defines the fill cell. Used in fill insertion. Can use a wild card to define a class of cells. Example `sky130_fd_sc_hd__fill_*` |
| `DECAP_CELL` | Defines the decap cell used for fill insertion. Can use a wild card to define a class of cells. Example `sky130_fd_sc_hd__fill_*` |
| `CELL_PAD` | Defines the number of sites to pad the cells lef views with. |
| `CELL_PAD_EXCLUDE` | Defines the cells to exclude from padding. |
| `CTS_ROOT_BUFFER` | Defines the cell inserted at the root of the clock tree. Used in CTS. |
| `CLK_BUFFER` | Defines the clock buffer cell. Used in CTS. |
| `CLK_BUFFER_INPUT` | Defines the clock buffer cell input port. Used in CTS. |
| `CLK_BUFFER_OUTPUT` | Defines the clock buffer cell output port. Used in CTS. |
| `ROOT_CLK_BUFFER` | Root clock buffer of the clock tree. <br> (Example: `sky130_fd_sc_hd__clkbuf_16`) |
| `CLK_BUFFER` | Clock buffer used for inner nodes of the clock tree. <br> (Example: `sky130_fd_sc_hd__clkbuf_4`) |
| `CLK_BUFFER_INPUT` | Input pin of the clock tree buffer. <br> (Example: `A`) |
| `CLK_BUFFER_OUTPUT` | Output pin of the clock tree buffer. <br> (Example: `X`)|
| `CTS_CLK_BUFFER_LIST` | Defines the list of clock buffers to be used in CTS. |
| `CTS_MAX_CAP` | Defines the maximum capacitance, used in CTS. |
| `FP_PDN_RAIL_WIDTH` | Defines the rail width for met1 used in PDN. |
Expand Down
2 changes: 1 addition & 1 deletion env.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def issue_survey():
status = "OK"
try:
mismatches = verify_versions(
no_tools=True, report_file=f, pdk="sky130A"
no_tools=True, report_file=f, pdk=os.getenv("PDK") or "sky130A"
)
if mismatches:
status = "MISMATCH"
Expand Down
28 changes: 20 additions & 8 deletions scripts/base.sdc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
if {[info exists ::env(CLOCK_PORT)] && $::env(CLOCK_PORT) != ""} {
if {[info exists ::env(CLOCK_PORT)] && $::env(CLOCK_PORT) != ""} {
create_clock [get_ports $::env(CLOCK_PORT)] -name $::env(CLOCK_PORT) -period $::env(CLOCK_PERIOD)
} else {
create_clock -name __VIRTUAL_CLK__ -period $::env(CLOCK_PERIOD)
Expand All @@ -11,20 +11,32 @@ puts "\[INFO\]: Setting input delay to: $input_delay_value"

set_max_fanout $::env(SYNTH_MAX_FANOUT) [current_design]

set clk_indx [lsearch [all_inputs] [get_port $::env(CLOCK_PORT)]]
#set rst_indx [lsearch [all_inputs] [get_port resetn]]
set all_inputs_wo_clk [lreplace [all_inputs] $clk_indx $clk_indx]
#set all_inputs_wo_clk_rst [lreplace $all_inputs_wo_clk $rst_indx $rst_indx]
set all_inputs_wo_clk_rst $all_inputs_wo_clk
set clk_input [get_port $::env(CLOCK_PORT)]
set clk_indx [lsearch [all_inputs] $clk_input]
set all_inputs_wo_clk [lreplace [all_inputs] $clk_indx $clk_indx ""]

#set rst_input [get_port resetn]
#set rst_indx [lsearch [all_inputs] $rst_input]
#set all_inputs_wo_clk_rst [lreplace $all_inputs_wo_clk $rst_indx $rst_indx ""]
set all_inputs_wo_clk_rst $all_inputs_wo_clk

# correct resetn
set_input_delay $input_delay_value -clock [get_clocks $::env(CLOCK_PORT)] $all_inputs_wo_clk_rst
#set_input_delay 0.0 -clock [get_clocks $::env(CLOCK_PORT)] {resetn}
set_output_delay $output_delay_value -clock [get_clocks $::env(CLOCK_PORT)] [all_outputs]

# TODO set this as parameter
set_driving_cell -lib_cell $::env(SYNTH_DRIVING_CELL) -pin $::env(SYNTH_DRIVING_CELL_PIN) [all_inputs]
if { ![info exists ::env(SYNTH_CLK_DRIVING_CELL)] } {
set ::env(SYNTH_CLK_DRIVING_CELL) $::env(SYNTH_DRIVING_CELL)
}

if { ![info exists ::env(SYNTH_CLK_DRIVING_CELL_PIN)] } {
set ::env(SYNTH_CLK_DRIVING_CELL_PIN) $::env(SYNTH_DRIVING_CELL_PIN)
}

set_driving_cell -lib_cell $::env(SYNTH_DRIVING_CELL) -pin $::env(SYNTH_DRIVING_CELL_PIN) $all_inputs_wo_clk_rst

set_driving_cell -lib_cell $::env(SYNTH_CLK_DRIVING_CELL) -pin $::env(SYNTH_CLK_DRIVING_CELL_PIN) $clk_input

set cap_load [expr $::env(SYNTH_CAP_LOAD) / 1000.0]
puts "\[INFO\]: Setting load to: $cap_load"
set_load $cap_load [all_outputs]
Expand Down
10 changes: 6 additions & 4 deletions scripts/libtrim.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/python3
# Copyright 2020-2021 Efabless Corporation
# Copyright 2020-2022 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -24,9 +24,11 @@
@click.option("-o", "--output", required=True, help="Output liberty file")
@click.argument("input_lib_files", nargs=-1)
def cli(cell_file, output, input_lib_files):
excluded_cells = list(
map(lambda x: x.strip(), open(cell_file).read().strip().split("\n"))
)
excluded_cells = [
cell.strip()
for cell in open(cell_file).read().strip().split("\n")
if cell.strip() != ""
]

output_file_handle = open(output, "w")

Expand Down
10 changes: 5 additions & 5 deletions scripts/openroad/pdn.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
# limitations under the License.
#
foreach lib $::env(LIB_SYNTH_COMPLETE) {
read_liberty $lib
read_liberty $lib
}

if { [info exists ::env(EXTRA_LIBS) ] } {
foreach lib $::env(EXTRA_LIBS) {
read_liberty $lib
}
foreach lib $::env(EXTRA_LIBS) {
read_liberty $lib
}
}

if {[catch {read_lef $::env(MERGED_LEF_UNPADDED)} errmsg]} {
Expand Down Expand Up @@ -52,7 +52,7 @@ if { $::env(FP_PDN_CHECK_NODES) } {

if { $::env(FP_PDN_IRDROP) } {
# set rc values
source $::env(SCRIPTS_DIR)/openroad/set_rc.tcl
source $::env(SCRIPTS_DIR)/openroad/set_rc.tcl
analyze_power_grid -net $::env(VDD_NET) -outfile $::env(PGA_RPT_FILE)
}

Expand Down
13 changes: 2 additions & 11 deletions scripts/openroad/pdn_cfg.tcl
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
# 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) {
Expand All @@ -28,7 +19,7 @@ if { [info exists ::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS)] } {
}

if { $::env(FP_PDN_ENABLE_MACROS_GRID) == 1 &&
[info exists ::env(FP_PDN_MACRO_HOOKS)]} {
[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]
Expand Down Expand Up @@ -138,7 +129,7 @@ if { $::env(FP_PDN_ENABLE_RAILS) == 1 } {
add_pdn_connect \
-grid stdcell_grid \
-layers "$::env(FP_PDN_RAILS_LAYER) $::env(FP_PDN_LOWER_LAYER)"
}
}


# Adds the core ring if enabled.
Expand Down
8 changes: 8 additions & 0 deletions scripts/tcl_commands/routing.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,14 @@ proc gen_pdn {args} {
set ::env(SAVE_DEF) [index_file $::env(floorplan_tmpfiles)/pdn.def]
set ::env(PGA_RPT_FILE) [index_file $::env(floorplan_tmpfiles)/pdn.pga.rpt]

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)
}

run_openroad_script $::env(SCRIPTS_DIR)/openroad/pdn.tcl \
|& -indexed_log [index_file $::env(floorplan_logs)/pdn.log]

Expand Down
8 changes: 8 additions & 0 deletions scripts/tcl_commands/synthesis.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ proc run_yosys {args} {
lappend ::env(LIB_SYNTH_COMPLETE_NO_PG) $lib_path
}

set ::env(LIB_SYNTH_NO_PG) [list]
foreach lib $::env(LIB_SYNTH) {
set fbasename [file rootname [file tail $lib]]
set lib_path [index_file $::env(synthesis_tmpfiles)/$fbasename.no_pg.lib]
convert_pg_pins $lib $lib_path
lappend ::env(LIB_SYNTH_NO_PG) $lib_path
}

try_catch $::env(SYNTH_BIN) \
-c $::env(SYNTH_SCRIPT) \
-l [index_file $::env(synthesis_logs)/synthesis.log] \
Expand Down
2 changes: 1 addition & 1 deletion scripts/yosys/synth.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ proc run_strategy {output script ext} {
insbuf -buf {*}$::env(SYNTH_MIN_BUF_PORT)

tee -o "$::env(synth_report_prefix).$ext.chk.rpt" check
tee -o "$::env(synth_report_prefix).$ext.stat.rpt" stat -top $::env(DESIGN_NAME) -liberty [lindex $::env(LIB_SYNTH_COMPLETE_NO_PG) 0]
tee -o "$::env(synth_report_prefix).$ext.stat.rpt" stat -top $::env(DESIGN_NAME) -liberty [lindex $::env(LIB_SYNTH_NO_PG) 0]
write_verilog -noattr -noexpr -nohex -nodec -defparam $output
design -reset
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/yosys/synth_top.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ if { [info exists ::env(VERILOG_FILES_BLACKBOX)] } {


for { set i 0 } { $i < [llength $::env(VERILOG_FILES)] } { incr i } {
read_verilog {*}$vIdirsArgs [lindex $::env(VERILOG_FILES) $i]
read_verilog {*}$vIdirsArgs [lindex $::env(VERILOG_FILES) $i]
}

if { [info exists ::env(SYNTH_PARAMETERS) ] } {
Expand Down

0 comments on commit a988333

Please sign in to comment.