Skip to content

Commit

Permalink
efabless ring IO template + hooks (#792)
Browse files Browse the repository at this point in the history
* efabless ring IO template + hooks

* consolidate docs

* add sky130_fd_io library from open_pdks, fix template IO file

* fix corner cell, make met5 stripes like caravel

* met5 rings now connected to clamped3 pads

* add set_dont_touch on tie_hi/lo_esd output pins

* Update IO file instructions

* typos, move section

* More clarity

* fix IO filler placement to prevent them from being rotated

Without setting the fillers' place status to `fixed`, Innovus resets the
orientation of all fillers at some point during placement.

* Sky130: snap die to mfg grid for top-level

MPW/ChipIgnite die sizes are not on the placement grid (the default grid
snap); set the snap grid to the manufacturing grid for top-level modules
so that the die size can be set correctly.

* Update core size + docs surrounding core

Larger margins required to keep the entire core in low-tap-density
region.

* Sky130: add docs for IO cells during synthesis

IO cells (or at minimum, the HV tie nets) must be `dont_touch`ed during
synthesis to avoid Genus replacing HV tie connections with constant tie
cells.

* Reformat TCL & Markdown

Use fenced code blocks with proper language in Markdown, dedent TCL
snippets.

* Add patches to spacer cells and note about supplies

* Sky130: Add connect slices to example configuration

Change example hook to use connect filler slices and add critical
regular filler slices to template IO file.

---------

Co-authored-by: Ethan Wu <ethanwu10@gmail.com>
  • Loading branch information
harrisonliew and ethanwu10 committed Jun 15, 2023
1 parent 820ac1f commit 46b4e75
Show file tree
Hide file tree
Showing 9 changed files with 1,949 additions and 16 deletions.
60 changes: 56 additions & 4 deletions hammer/technology/sky130/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,62 @@ Note that the various configurations of the SRAMs available are encoded in the f
To modify this file to include different configurations, or switch to using the OpenRAM SRAMs,
navigate to ``./extra/[sram22|openram]`` and run the script ``./sram-cache-gen.py`` for usage information.
IO Library
----------
The IO ring required by efabless for MPW/ChipIgnite can be created in Innovus using the `sky130_fd_io` and `sky130_ef_io `IO cell libraries. Here are the steps to use them:

1. `extra/efabless_template.io` is a template IO file. You should modify this by replacing the `<inst_path>`s with the netlist paths to your GPIO & analog pads. **DO NOT MODIFY ANY POSITIONS OR REPLACE CLAMP CELLS WITH IO CELLS**.

a. For pad assignment: the ordering in the instance lists are from left to right (for top/bottom edges) and **bottom to top (for left/right edges)**.

b. Refer to [this documentation](https://skywater-pdk.readthedocs.io/en/main/contents/libraries/sky130_fd_io/docs/user_guide.html) for how to configure the pins of the IO cells (not exhaustive).

c. Your chip reset signal must go thru the `xres4v2` cell. Since this is in your netlist, you must remove the `cell=...` instantiation from your IO file (it is only in the template for clarity) and update the inst name. Otherwise a separate instance will be placed instead.

d. The `ENABLE_INP_H` pin must be hard-tied to `TIE_HI_ESD` or `TIE_LO_ESD`. Since this is at a higher voltage, verify that this is routed as a wire only (no buffers can be inserted).

e. `ENABLE_H` must be low at chip startup before going high. Absent using the power detector cell from the NDA IO library, you may elect to connect this to a reset signal.

f. This template file does not contain dedicated clamps for the `VSWITCH` or `VCCHIB` supplies (following Caravel). EFabless provides a `sky130_ef_io__connect_vcchib_vccd_and_vswitch_vddio_slice_20um` slice in `open_pdks` that replaces a standard 20um spacer with a slice that connects `VCCHIB` and `VCCD` together, and `VSWITCH` and `VDDIO` together. Note that this slice cannot be placed immediately to the right (in the R0 orientation) of a `*_clamped3_pad` cell, because otherwise they *will* create a supply short. The template IO file contains normal 20um spacer slices explicitly placed at these critical locations, and the provided hook instantiates the `connect` slice in place of the standard 20um spacer. This can be modified if desired. Caravel distributes the `*connect*` slices across the bottom edge of the padframe.

2. Then, in your design YAML file, specify your IO file with the following. The top-level constraint must be exactly as below:

```yaml
technology.sky130.io_file: <path/to/ring.io>
technology.sky130.io_file_meta: prependlocal
path: Top
type: toplevel
x: 0
y: 0
width: 3588
height: 5188
margins:
left: 249.78
right: 249.78
top: 252.08
bottom: 252.08
```

3. In your CLIDriver, you must import the following hook from the tech plugin and insert it as a `post_insertion_hook` after `floorplan_design`.

```python
from hammer.technology.sky130 import efabless_ring_io
```

In addition, to ensure ties to `TIE_HI_ESD` / `TIE_LO_ESD` are preserved during synthesis, a `post_insertion_hook` to `init_environment` should be added to `dont_touch` the IO cells

```python
def donttouch_iocells(x: HammerTool) -> bool:
x.append('set_dont_touch [get_db insts -if {.base_cell.name == sky130_ef_io__*}] true')
return True
```

4. If you want to use the NDA s8iom0s8 library, you must include the `s8io.yml` file with `-p` on the `hammer-vlsi` command line, and then change the cells to that library in the IO file. Net names in the hook above will need to be lower-cased.

5. DRC requires a rectangle of `areaid.lowTapDensity` (GDS layer 81/14) around the core area to check latchup correctly. Currently, this is not yet implemented in Hammer, and will need to be added manually in a GDS editor after GDS streamout.

NDA Files
---------
The NDA version of the Sky130 PDK is only required for Siemens Calibre to perform DRC/LVS signoff with the commercial VLSI flow.
Expand All @@ -63,8 +119,6 @@ We use the Calibre decks in the ``s8`` PDK, version ``V2.0.1``,
see [here for the DRC deck path](https://github.com/ucb-bar/hammer/blob/612b4b662a774b1cab5cf25e8f41c6a771388e47/hammer/technology/sky130/sky130.tech.json#L16)
and [here for the LVS deck path](https://github.com/ucb-bar/hammer/blob/612b4b662a774b1cab5cf25e8f41c6a771388e47/hammer/technology/sky130/sky130.tech.json#L24).

Resources
---------
The good thing about this process being open-source is that most questions about the process are answerable through a google search.
Expand Down Expand Up @@ -195,5 +249,3 @@ make install
This generates all the Sky130 PDK files and installs them to `$PDK_ROOT/share/pdk/sky130A`




89 changes: 88 additions & 1 deletion hammer/technology/sky130/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@

import hammer.tech
from hammer.tech import HammerTechnology
from hammer.vlsi import HammerTool, HammerPlaceAndRouteTool, TCLTool, HammerDRCTool, HammerLVSTool, HammerToolHookAction
from hammer.vlsi import HammerTool, HammerPlaceAndRouteTool, TCLTool, HammerDRCTool, HammerLVSTool, \
HammerToolHookAction, HierarchicalMode

import hammer.tech.specialcells as specialcells
from hammer.tech.specialcells import CellType, SpecialCell
Expand All @@ -31,6 +32,7 @@ def post_install_script(self) -> None:
self.setup_verilog()
self.setup_techlef()
self.setup_lvs_deck()
self.setup_io_lefs()
print('Loaded Sky130 Tech')


Expand Down Expand Up @@ -160,6 +162,41 @@ def setup_lvs_deck(self) -> None:
df.write(matcher.sub("", sf.read()))
df.write(LVS_DECK_INSERT_LINES)

# Power pins for clamps must be CLASS CORE
# connect/disconnect spacers must be CLASS PAD SPACER, not AREAIO
def setup_io_lefs(self) -> None:
sky130A_path = Path(self.get_setting('technology.sky130.sky130A'))
source_path = sky130A_path / 'libs.ref' / 'sky130_fd_io' / 'lef' / 'sky130_ef_io.lef'
if not source_path.exists():
raise FileNotFoundError(f"IO LEF not found: {source_path}")

cache_tech_dir_path = Path(self.cache_dir)
os.makedirs(cache_tech_dir_path, exist_ok=True)
dest_path = cache_tech_dir_path / 'sky130_ef_io.lef'

with open(source_path, 'r') as sf:
with open(dest_path, 'w') as df:
self.logger.info("Modifying IO LEF: {} -> {}".format
(source_path, dest_path))
sl = sf.readlines()
for net in ['VCCD1', 'VSSD1']:
start = [idx for idx,line in enumerate(sl) if 'PIN ' + net in line]
end = [idx for idx,line in enumerate(sl) if 'END ' + net in line]
intervals = zip(start, end)
for intv in intervals:
port_idx = [idx for idx,line in enumerate(sl[intv[0]:intv[1]]) if 'PORT' in line]
for idx in port_idx:
sl[intv[0]+idx]=sl[intv[0]+idx].replace('PORT', 'PORT\n CLASS CORE ;')
for cell in [
'sky130_ef_io__connect_vcchib_vccd_and_vswitch_vddio_slice_20um',
'sky130_ef_io__disconnect_vccd_slice_5um',
'sky130_ef_io__disconnect_vdda_slice_5um',
]:
# force class to spacer
start = [idx for idx, line in enumerate(sl) if f'MACRO {cell}' in line]
sl[start[0] + 1] = sl[start[0] + 1].replace('AREAIO', 'SPACER')
df.writelines(sl)

def get_tech_par_hooks(self, tool_name: str) -> List[HammerToolHookAction]:
hooks = {
"innovus": [
Expand Down Expand Up @@ -285,6 +322,13 @@ def sky130_innovus_settings(ht: HammerTool) -> bool:
set_db route_design_detail_use_multi_cut_via_effort medium
'''
)
if ht.hierarchical_mode in {HierarchicalMode.Top, HierarchicalMode.Flat}:
ht.append(
'''
# For top module: snap die to manufacturing grid, not placement grid
set_db floorplan_snap_die_grid manufacturing
'''
)
return True

def sky130_connect_nets(ht: HammerTool) -> bool:
Expand Down Expand Up @@ -319,6 +363,49 @@ def sky130_add_endcaps(ht: HammerTool) -> bool:
)
return True

def efabless_ring_io(ht: HammerTool) -> bool:
assert isinstance(ht, HammerPlaceAndRouteTool), "IO ring instantiation only for par"
assert isinstance(ht, TCLTool), "IO ring instantiation can only run on TCL tools"
io_file = ht.get_setting("technology.sky130.io_file")
ht.append(f"read_io_file {io_file} -no_die_size_adjust")
p_nets = list(map(lambda s: s.name, ht.get_independent_power_nets()))
g_nets = list(map(lambda s: s.name, ht.get_independent_ground_nets()))
ht.append(f'''
# Global net connections
connect_global_net VDDA -type pg_pin -pin_base_name VDDA -verbose
connect_global_net VDDIO -type pg_pin -pin_base_name VDDIO* -verbose
connect_global_net {p_nets[0]} -type pg_pin -pin_base_name VCCD* -verbose
connect_global_net {p_nets[0]} -type pg_pin -pin_base_name VCCHIB -verbose
connect_global_net {p_nets[0]} -type pg_pin -pin_base_name VSWITCH -verbose
connect_global_net {g_nets[0]} -type pg_pin -pin_base_name VSSA -verbose
connect_global_net {g_nets[0]} -type pg_pin -pin_base_name VSSIO* -verbose
connect_global_net {g_nets[0]} -type pg_pin -pin_base_name VSSD* -verbose
''')
ht.append('''
# IO fillers
set io_fillers {sky130_ef_io__connect_vcchib_vccd_and_vswitch_vddio_slice_20um sky130_ef_io__com_bus_slice_10um sky130_ef_io__com_bus_slice_5um sky130_ef_io__com_bus_slice_1um}
add_io_fillers -prefix IO_FILLER -io_ring 1 -cells $io_fillers -side top -filler_orient r0
add_io_fillers -prefix IO_FILLER -io_ring 1 -cells $io_fillers -side right -filler_orient r270
add_io_fillers -prefix IO_FILLER -io_ring 1 -cells $io_fillers -side bottom -filler_orient r180
add_io_fillers -prefix IO_FILLER -io_ring 1 -cells $io_fillers -side left -filler_orient r90
# Fix placement
set io_filler_insts [get_db insts IO_FILLER_*]
set_db $io_filler_insts .place_status fixed
''')
# An offset of 40um is used to place the core ring inside the core area. It
# can be decreased down to 5um as desired, but will require additional
# routing / settings to connect the core power stripes to the ring.
ht.append(f'''
# Core ring
add_rings -follow io -layer met5 -nets {{ {p_nets[0]} {g_nets[0]} }} -offset 40 -width 13 -spacing 3
route_special -connect pad_pin -nets {{ {p_nets[0]} {g_nets[0]} }} -detailed_log
''')
ht.append('''
# Prevent buffering on TIE_LO_ESD and TIE_HI_ESD
set_dont_touch [get_db [get_db pins -if {.name == *TIE*ESD}] .net]
''')
return True

def drc_blackbox_srams(ht: HammerTool) -> bool:
assert isinstance(ht, HammerDRCTool), "Exlude SRAMs only in DRC"
drc_box = ''
Expand Down
3 changes: 3 additions & 0 deletions hammer/technology/sky130/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ technology.sky130:

drc_blackbox_srams: false
lvs_blackbox_srams: false

io_file: "extra/efabless_template.io" # IO ring - take this template and modify for your own use
io_file_meta: prependlocal


mentor.extra_env_vars_meta: lazydeepsubst # Mentor environment variables
Expand Down
3 changes: 3 additions & 0 deletions hammer/technology/sky130/defaults_types.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ technology.sky130:
# Shouldn't need to change these
pdk_home: Optional[str]
lvs_deck_sources: Optional[list[str]]

# Path to IO file
io_file: str
124 changes: 124 additions & 0 deletions hammer/technology/sky130/extra/efabless_template.io
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@

(globals
version = 3
io_order = default
)
(row_margin
(top
(io_row ring_number = 1 margin = 0)
)
(right
(io_row ring_number = 1 margin = 0)
)
(bottom
(io_row ring_number = 1 margin = 0)
)
(left
(io_row ring_number = 1 margin = 0)
)
)
(iopad
(topleft
(locals ring_number = 1)
(inst name = "corner_topleft" orientation=R90 cell="sky130_ef_io__corner_pad")
)

(top
(locals ring_number = 1)
(inst name = "<pad_inst>" orientation=R0 offset=381)
(inst name = "<pad_inst>" orientation=R0 offset=638)
(inst name = "<pad_inst>" orientation=R0 offset=895)
(inst name = "<pad_inst>" orientation=R0 offset=1152)
(inst name = "<pad_inst>" orientation=R0 offset=1410)
(inst name = "clamp_0" orientation=R0 cell="sky130_ef_io__vssio_hvc_clamped_pad" offset=1667)
(inst name = "<pad_inst>" orientation=R0 offset=1919)
(inst name = "<pad_inst>" orientation=R0 offset=2364)
(inst name = "<pad_inst>" orientation=R0 offset=2621)
(inst name = "clamp_1" orientation=R0 cell="sky130_ef_io__vssa_hvc_clamped_pad" offset=2878)
(inst name = "<pad_inst>" orientation=R0 offset=3130)
)

(topright
(locals ring_number = 1)
(inst name = "corner_topright" orientation=R0 cell="sky130_ef_io__corner_pad")
)

(right
(locals ring_number = 1)
(inst name = "<pad_inst>" orientation=R270 offset=580)
(inst name = "<pad_inst>" orientation=R270 offset=806)
(inst name = "<pad_inst>" orientation=R270 offset=1031)
(inst name = "<pad_inst>" orientation=R270 offset=1257)
(inst name = "<pad_inst>" orientation=R270 offset=1482)
(inst name = "<pad_inst>" orientation=R270 offset=1707)
(inst name = "<pad_inst>" orientation=R270 offset=1933)
(inst name = "clamp_2" orientation=R270 cell="sky130_ef_io__vssa_hvc_clamped_pad" offset=2153)
(inst name = "clamp_3" orientation=R270 cell="sky130_ef_io__vssd_lvc_clamped3_pad" offset=2374)
(inst name = "clamp_4" orientation=R270 cell="sky130_ef_io__vdda_hvc_clamped_pad" offset=2594)
(inst name = "<pad_inst>" orientation=R270 offset=2819)
(inst name = "<pad_inst>" orientation=R270 offset=3045)
(inst name = "<pad_inst>" orientation=R270 offset=3270)
(inst name = "<pad_inst>" orientation=R270 offset=3496)
(inst name = "<pad_inst>" orientation=R270 offset=3721)
(inst name = "<pad_inst>" orientation=R270 offset=3946)
(inst name = "clamp_5" orientation=R270 cell="sky130_ef_io__vdda_hvc_clamped_pad" offset=4167)
(inst name = "<pad_inst>" orientation=R270 offset=4392)
(inst name = "clamp_6" orientation=R270 cell="sky130_ef_io__vccd_lvc_clamped3_pad" offset=4613)
(inst name = "<pad_inst>" orientation=R270 offset=4838)
(inst name = "IO_FILLER_MANUAL_E_1" orientation = R270 offset = 4593 cell = "sky130_ef_io__com_bus_slice_20um")
(inst name = "IO_FILLER_MANUAL_E_2" orientation = R270 offset = 2354 cell = "sky130_ef_io__com_bus_slice_20um")
)

(bottomright
(locals ring_number = 1)
(inst name = "corner_bottomright" orientation=R270 cell="sky130_ef_io__corner_pad")
)

(bottom
(locals ring_number = 1)
(inst name = "clamp_7" orientation=R180 cell="sky130_ef_io__vssa_hvc_clamped_pad" offset=469)
(inst name = "reset" orientation=R180 cell="sky130_fd_io__top_xres4v2" offset=738)
(inst name = "<pad_inst>" orientation=R180 offset=1012)
(inst name = "clamp_8" orientation=R180 cell="sky130_ef_io__vssd_lvc_clamped_pad" offset=1281)
(inst name = "<pad_inst>" orientation=R180 offset=1555)
(inst name = "<pad_inst>" orientation=R180 offset=1829)
(inst name = "<pad_inst>" orientation=R180 offset=2103)
(inst name = "<pad_inst>" orientation=R180 offset=2377)
(inst name = "<pad_inst>" orientation=R180 offset=2651)
(inst name = "clamp_9" orientation=R180 cell="sky130_ef_io__vssio_hvc_clamped_pad" offset=2920)
(inst name = "clamp_10" orientation=R180 cell="sky130_ef_io__vdda_hvc_clamped_pad" offset=3189)
)

(bottomleft
(locals ring_number = 1)
(inst name = "corner_bottomleft" orientation=R180 cell="sky130_ef_io__corner_pad")
)

(left
(locals ring_number = 1)
(inst name = "clamp_11" orientation=R90 cell="sky130_ef_io__vccd_lvc_clamped_pad" offset=340)
(inst name = "clamp_12" orientation=R90 cell="sky130_ef_io__vddio_hvc_clamped_pad" offset=551)
(inst name = "<pad_inst>" orientation=R90 offset=908)
(inst name = "<pad_inst>" orientation=R90 offset=1124)
(inst name = "<pad_inst>" orientation=R90 offset=1340)
(inst name = "<pad_inst>" orientation=R90 offset=1556)
(inst name = "<pad_inst>" orientation=R90 offset=1772)
(inst name = "<pad_inst>" orientation=R90 offset=1988)
(inst name = "clamp_13" orientation=R90 cell="sky130_ef_io__vssd_lvc_clamped3_pad" offset=2204)
(inst name = "clamp_14" orientation=R90 cell="sky130_ef_io__vdda_hvc_clamped_pad" offset=2415)
(inst name = "<pad_inst>" orientation=R90 offset=2626)
(inst name = "<pad_inst>" orientation=R90 offset=2842)
(inst name = "<pad_inst>" orientation=R90 offset=3058)
(inst name = "<pad_inst>" orientation=R90 offset=3274)
(inst name = "<pad_inst>" orientation=R90 offset=3490)
(inst name = "<pad_inst>" orientation=R90 offset=3706)
(inst name = "<pad_inst>" orientation=R90 offset=3922)
(inst name = "clamp_15" orientation=R90 cell="sky130_ef_io__vssa_hvc_clamped_pad" offset=4138)
(inst name = "clamp_16" orientation=R90 cell="sky130_ef_io__vddio_hvc_clamped_pad" offset=4349)
(inst name = "clamp_17" orientation=R90 cell="sky130_ef_io__vccd_lvc_clamped3_pad" offset=4560)
(inst name = "<pad_inst>" orientation=R90 offset=4771)
(inst name = "IO_FILLER_MANUAL_W_1" orientation = R90 offset = 415 cell = "sky130_ef_io__com_bus_slice_20um")
(inst name = "IO_FILLER_MANUAL_W_2" orientation = R90 offset = 2279 cell = "sky130_ef_io__com_bus_slice_20um")
(inst name = "IO_FILLER_MANUAL_W_3" orientation = R90 offset = 4635 cell = "sky130_ef_io__com_bus_slice_20um")
)
)
Loading

0 comments on commit 46b4e75

Please sign in to comment.