Skip to content

Commit 46b4e75

Browse files
efabless ring IO template + hooks (#792)
* 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>
1 parent 820ac1f commit 46b4e75

File tree

9 files changed

+1949
-16
lines changed

9 files changed

+1949
-16
lines changed

hammer/technology/sky130/README.md

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,62 @@ Note that the various configurations of the SRAMs available are encoded in the f
4747
To modify this file to include different configurations, or switch to using the OpenRAM SRAMs,
4848
navigate to ``./extra/[sram22|openram]`` and run the script ``./sram-cache-gen.py`` for usage information.
4949
50+
IO Library
51+
----------
52+
53+
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:
54+
55+
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**.
56+
57+
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)**.
58+
59+
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).
60+
61+
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.
62+
63+
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).
64+
65+
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.
66+
67+
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.
68+
69+
2. Then, in your design YAML file, specify your IO file with the following. The top-level constraint must be exactly as below:
70+
71+
```yaml
72+
technology.sky130.io_file: <path/to/ring.io>
73+
technology.sky130.io_file_meta: prependlocal
74+
75+
path: Top
76+
type: toplevel
77+
x: 0
78+
y: 0
79+
width: 3588
80+
height: 5188
81+
margins:
82+
left: 249.78
83+
right: 249.78
84+
top: 252.08
85+
bottom: 252.08
86+
```
87+
88+
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`.
89+
90+
```python
91+
from hammer.technology.sky130 import efabless_ring_io
92+
```
93+
94+
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
95+
96+
```python
97+
def donttouch_iocells(x: HammerTool) -> bool:
98+
x.append('set_dont_touch [get_db insts -if {.base_cell.name == sky130_ef_io__*}] true')
99+
return True
100+
```
101+
102+
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.
103+
104+
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.
105+
50106
NDA Files
51107
---------
52108
The NDA version of the Sky130 PDK is only required for Siemens Calibre to perform DRC/LVS signoff with the commercial VLSI flow.
@@ -63,8 +119,6 @@ We use the Calibre decks in the ``s8`` PDK, version ``V2.0.1``,
63119
see [here for the DRC deck path](https://github.com/ucb-bar/hammer/blob/612b4b662a774b1cab5cf25e8f41c6a771388e47/hammer/technology/sky130/sky130.tech.json#L16)
64120
and [here for the LVS deck path](https://github.com/ucb-bar/hammer/blob/612b4b662a774b1cab5cf25e8f41c6a771388e47/hammer/technology/sky130/sky130.tech.json#L24).
65121

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

197251

198-
199-

hammer/technology/sky130/__init__.py

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212

1313
import hammer.tech
1414
from hammer.tech import HammerTechnology
15-
from hammer.vlsi import HammerTool, HammerPlaceAndRouteTool, TCLTool, HammerDRCTool, HammerLVSTool, HammerToolHookAction
15+
from hammer.vlsi import HammerTool, HammerPlaceAndRouteTool, TCLTool, HammerDRCTool, HammerLVSTool, \
16+
HammerToolHookAction, HierarchicalMode
1617

1718
import hammer.tech.specialcells as specialcells
1819
from hammer.tech.specialcells import CellType, SpecialCell
@@ -31,6 +32,7 @@ def post_install_script(self) -> None:
3132
self.setup_verilog()
3233
self.setup_techlef()
3334
self.setup_lvs_deck()
35+
self.setup_io_lefs()
3436
print('Loaded Sky130 Tech')
3537

3638

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

165+
# Power pins for clamps must be CLASS CORE
166+
# connect/disconnect spacers must be CLASS PAD SPACER, not AREAIO
167+
def setup_io_lefs(self) -> None:
168+
sky130A_path = Path(self.get_setting('technology.sky130.sky130A'))
169+
source_path = sky130A_path / 'libs.ref' / 'sky130_fd_io' / 'lef' / 'sky130_ef_io.lef'
170+
if not source_path.exists():
171+
raise FileNotFoundError(f"IO LEF not found: {source_path}")
172+
173+
cache_tech_dir_path = Path(self.cache_dir)
174+
os.makedirs(cache_tech_dir_path, exist_ok=True)
175+
dest_path = cache_tech_dir_path / 'sky130_ef_io.lef'
176+
177+
with open(source_path, 'r') as sf:
178+
with open(dest_path, 'w') as df:
179+
self.logger.info("Modifying IO LEF: {} -> {}".format
180+
(source_path, dest_path))
181+
sl = sf.readlines()
182+
for net in ['VCCD1', 'VSSD1']:
183+
start = [idx for idx,line in enumerate(sl) if 'PIN ' + net in line]
184+
end = [idx for idx,line in enumerate(sl) if 'END ' + net in line]
185+
intervals = zip(start, end)
186+
for intv in intervals:
187+
port_idx = [idx for idx,line in enumerate(sl[intv[0]:intv[1]]) if 'PORT' in line]
188+
for idx in port_idx:
189+
sl[intv[0]+idx]=sl[intv[0]+idx].replace('PORT', 'PORT\n CLASS CORE ;')
190+
for cell in [
191+
'sky130_ef_io__connect_vcchib_vccd_and_vswitch_vddio_slice_20um',
192+
'sky130_ef_io__disconnect_vccd_slice_5um',
193+
'sky130_ef_io__disconnect_vdda_slice_5um',
194+
]:
195+
# force class to spacer
196+
start = [idx for idx, line in enumerate(sl) if f'MACRO {cell}' in line]
197+
sl[start[0] + 1] = sl[start[0] + 1].replace('AREAIO', 'SPACER')
198+
df.writelines(sl)
199+
163200
def get_tech_par_hooks(self, tool_name: str) -> List[HammerToolHookAction]:
164201
hooks = {
165202
"innovus": [
@@ -285,6 +322,13 @@ def sky130_innovus_settings(ht: HammerTool) -> bool:
285322
set_db route_design_detail_use_multi_cut_via_effort medium
286323
'''
287324
)
325+
if ht.hierarchical_mode in {HierarchicalMode.Top, HierarchicalMode.Flat}:
326+
ht.append(
327+
'''
328+
# For top module: snap die to manufacturing grid, not placement grid
329+
set_db floorplan_snap_die_grid manufacturing
330+
'''
331+
)
288332
return True
289333

290334
def sky130_connect_nets(ht: HammerTool) -> bool:
@@ -319,6 +363,49 @@ def sky130_add_endcaps(ht: HammerTool) -> bool:
319363
)
320364
return True
321365

366+
def efabless_ring_io(ht: HammerTool) -> bool:
367+
assert isinstance(ht, HammerPlaceAndRouteTool), "IO ring instantiation only for par"
368+
assert isinstance(ht, TCLTool), "IO ring instantiation can only run on TCL tools"
369+
io_file = ht.get_setting("technology.sky130.io_file")
370+
ht.append(f"read_io_file {io_file} -no_die_size_adjust")
371+
p_nets = list(map(lambda s: s.name, ht.get_independent_power_nets()))
372+
g_nets = list(map(lambda s: s.name, ht.get_independent_ground_nets()))
373+
ht.append(f'''
374+
# Global net connections
375+
connect_global_net VDDA -type pg_pin -pin_base_name VDDA -verbose
376+
connect_global_net VDDIO -type pg_pin -pin_base_name VDDIO* -verbose
377+
connect_global_net {p_nets[0]} -type pg_pin -pin_base_name VCCD* -verbose
378+
connect_global_net {p_nets[0]} -type pg_pin -pin_base_name VCCHIB -verbose
379+
connect_global_net {p_nets[0]} -type pg_pin -pin_base_name VSWITCH -verbose
380+
connect_global_net {g_nets[0]} -type pg_pin -pin_base_name VSSA -verbose
381+
connect_global_net {g_nets[0]} -type pg_pin -pin_base_name VSSIO* -verbose
382+
connect_global_net {g_nets[0]} -type pg_pin -pin_base_name VSSD* -verbose
383+
''')
384+
ht.append('''
385+
# IO fillers
386+
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}
387+
add_io_fillers -prefix IO_FILLER -io_ring 1 -cells $io_fillers -side top -filler_orient r0
388+
add_io_fillers -prefix IO_FILLER -io_ring 1 -cells $io_fillers -side right -filler_orient r270
389+
add_io_fillers -prefix IO_FILLER -io_ring 1 -cells $io_fillers -side bottom -filler_orient r180
390+
add_io_fillers -prefix IO_FILLER -io_ring 1 -cells $io_fillers -side left -filler_orient r90
391+
# Fix placement
392+
set io_filler_insts [get_db insts IO_FILLER_*]
393+
set_db $io_filler_insts .place_status fixed
394+
''')
395+
# An offset of 40um is used to place the core ring inside the core area. It
396+
# can be decreased down to 5um as desired, but will require additional
397+
# routing / settings to connect the core power stripes to the ring.
398+
ht.append(f'''
399+
# Core ring
400+
add_rings -follow io -layer met5 -nets {{ {p_nets[0]} {g_nets[0]} }} -offset 40 -width 13 -spacing 3
401+
route_special -connect pad_pin -nets {{ {p_nets[0]} {g_nets[0]} }} -detailed_log
402+
''')
403+
ht.append('''
404+
# Prevent buffering on TIE_LO_ESD and TIE_HI_ESD
405+
set_dont_touch [get_db [get_db pins -if {.name == *TIE*ESD}] .net]
406+
''')
407+
return True
408+
322409
def drc_blackbox_srams(ht: HammerTool) -> bool:
323410
assert isinstance(ht, HammerDRCTool), "Exlude SRAMs only in DRC"
324411
drc_box = ''

hammer/technology/sky130/defaults.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ technology.sky130:
2626

2727
drc_blackbox_srams: false
2828
lvs_blackbox_srams: false
29+
30+
io_file: "extra/efabless_template.io" # IO ring - take this template and modify for your own use
31+
io_file_meta: prependlocal
2932

3033

3134
mentor.extra_env_vars_meta: lazydeepsubst # Mentor environment variables

hammer/technology/sky130/defaults_types.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ technology.sky130:
2020
# Shouldn't need to change these
2121
pdk_home: Optional[str]
2222
lvs_deck_sources: Optional[list[str]]
23+
24+
# Path to IO file
25+
io_file: str
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
2+
(globals
3+
version = 3
4+
io_order = default
5+
)
6+
(row_margin
7+
(top
8+
(io_row ring_number = 1 margin = 0)
9+
)
10+
(right
11+
(io_row ring_number = 1 margin = 0)
12+
)
13+
(bottom
14+
(io_row ring_number = 1 margin = 0)
15+
)
16+
(left
17+
(io_row ring_number = 1 margin = 0)
18+
)
19+
)
20+
(iopad
21+
(topleft
22+
(locals ring_number = 1)
23+
(inst name = "corner_topleft" orientation=R90 cell="sky130_ef_io__corner_pad")
24+
)
25+
26+
(top
27+
(locals ring_number = 1)
28+
(inst name = "<pad_inst>" orientation=R0 offset=381)
29+
(inst name = "<pad_inst>" orientation=R0 offset=638)
30+
(inst name = "<pad_inst>" orientation=R0 offset=895)
31+
(inst name = "<pad_inst>" orientation=R0 offset=1152)
32+
(inst name = "<pad_inst>" orientation=R0 offset=1410)
33+
(inst name = "clamp_0" orientation=R0 cell="sky130_ef_io__vssio_hvc_clamped_pad" offset=1667)
34+
(inst name = "<pad_inst>" orientation=R0 offset=1919)
35+
(inst name = "<pad_inst>" orientation=R0 offset=2364)
36+
(inst name = "<pad_inst>" orientation=R0 offset=2621)
37+
(inst name = "clamp_1" orientation=R0 cell="sky130_ef_io__vssa_hvc_clamped_pad" offset=2878)
38+
(inst name = "<pad_inst>" orientation=R0 offset=3130)
39+
)
40+
41+
(topright
42+
(locals ring_number = 1)
43+
(inst name = "corner_topright" orientation=R0 cell="sky130_ef_io__corner_pad")
44+
)
45+
46+
(right
47+
(locals ring_number = 1)
48+
(inst name = "<pad_inst>" orientation=R270 offset=580)
49+
(inst name = "<pad_inst>" orientation=R270 offset=806)
50+
(inst name = "<pad_inst>" orientation=R270 offset=1031)
51+
(inst name = "<pad_inst>" orientation=R270 offset=1257)
52+
(inst name = "<pad_inst>" orientation=R270 offset=1482)
53+
(inst name = "<pad_inst>" orientation=R270 offset=1707)
54+
(inst name = "<pad_inst>" orientation=R270 offset=1933)
55+
(inst name = "clamp_2" orientation=R270 cell="sky130_ef_io__vssa_hvc_clamped_pad" offset=2153)
56+
(inst name = "clamp_3" orientation=R270 cell="sky130_ef_io__vssd_lvc_clamped3_pad" offset=2374)
57+
(inst name = "clamp_4" orientation=R270 cell="sky130_ef_io__vdda_hvc_clamped_pad" offset=2594)
58+
(inst name = "<pad_inst>" orientation=R270 offset=2819)
59+
(inst name = "<pad_inst>" orientation=R270 offset=3045)
60+
(inst name = "<pad_inst>" orientation=R270 offset=3270)
61+
(inst name = "<pad_inst>" orientation=R270 offset=3496)
62+
(inst name = "<pad_inst>" orientation=R270 offset=3721)
63+
(inst name = "<pad_inst>" orientation=R270 offset=3946)
64+
(inst name = "clamp_5" orientation=R270 cell="sky130_ef_io__vdda_hvc_clamped_pad" offset=4167)
65+
(inst name = "<pad_inst>" orientation=R270 offset=4392)
66+
(inst name = "clamp_6" orientation=R270 cell="sky130_ef_io__vccd_lvc_clamped3_pad" offset=4613)
67+
(inst name = "<pad_inst>" orientation=R270 offset=4838)
68+
(inst name = "IO_FILLER_MANUAL_E_1" orientation = R270 offset = 4593 cell = "sky130_ef_io__com_bus_slice_20um")
69+
(inst name = "IO_FILLER_MANUAL_E_2" orientation = R270 offset = 2354 cell = "sky130_ef_io__com_bus_slice_20um")
70+
)
71+
72+
(bottomright
73+
(locals ring_number = 1)
74+
(inst name = "corner_bottomright" orientation=R270 cell="sky130_ef_io__corner_pad")
75+
)
76+
77+
(bottom
78+
(locals ring_number = 1)
79+
(inst name = "clamp_7" orientation=R180 cell="sky130_ef_io__vssa_hvc_clamped_pad" offset=469)
80+
(inst name = "reset" orientation=R180 cell="sky130_fd_io__top_xres4v2" offset=738)
81+
(inst name = "<pad_inst>" orientation=R180 offset=1012)
82+
(inst name = "clamp_8" orientation=R180 cell="sky130_ef_io__vssd_lvc_clamped_pad" offset=1281)
83+
(inst name = "<pad_inst>" orientation=R180 offset=1555)
84+
(inst name = "<pad_inst>" orientation=R180 offset=1829)
85+
(inst name = "<pad_inst>" orientation=R180 offset=2103)
86+
(inst name = "<pad_inst>" orientation=R180 offset=2377)
87+
(inst name = "<pad_inst>" orientation=R180 offset=2651)
88+
(inst name = "clamp_9" orientation=R180 cell="sky130_ef_io__vssio_hvc_clamped_pad" offset=2920)
89+
(inst name = "clamp_10" orientation=R180 cell="sky130_ef_io__vdda_hvc_clamped_pad" offset=3189)
90+
)
91+
92+
(bottomleft
93+
(locals ring_number = 1)
94+
(inst name = "corner_bottomleft" orientation=R180 cell="sky130_ef_io__corner_pad")
95+
)
96+
97+
(left
98+
(locals ring_number = 1)
99+
(inst name = "clamp_11" orientation=R90 cell="sky130_ef_io__vccd_lvc_clamped_pad" offset=340)
100+
(inst name = "clamp_12" orientation=R90 cell="sky130_ef_io__vddio_hvc_clamped_pad" offset=551)
101+
(inst name = "<pad_inst>" orientation=R90 offset=908)
102+
(inst name = "<pad_inst>" orientation=R90 offset=1124)
103+
(inst name = "<pad_inst>" orientation=R90 offset=1340)
104+
(inst name = "<pad_inst>" orientation=R90 offset=1556)
105+
(inst name = "<pad_inst>" orientation=R90 offset=1772)
106+
(inst name = "<pad_inst>" orientation=R90 offset=1988)
107+
(inst name = "clamp_13" orientation=R90 cell="sky130_ef_io__vssd_lvc_clamped3_pad" offset=2204)
108+
(inst name = "clamp_14" orientation=R90 cell="sky130_ef_io__vdda_hvc_clamped_pad" offset=2415)
109+
(inst name = "<pad_inst>" orientation=R90 offset=2626)
110+
(inst name = "<pad_inst>" orientation=R90 offset=2842)
111+
(inst name = "<pad_inst>" orientation=R90 offset=3058)
112+
(inst name = "<pad_inst>" orientation=R90 offset=3274)
113+
(inst name = "<pad_inst>" orientation=R90 offset=3490)
114+
(inst name = "<pad_inst>" orientation=R90 offset=3706)
115+
(inst name = "<pad_inst>" orientation=R90 offset=3922)
116+
(inst name = "clamp_15" orientation=R90 cell="sky130_ef_io__vssa_hvc_clamped_pad" offset=4138)
117+
(inst name = "clamp_16" orientation=R90 cell="sky130_ef_io__vddio_hvc_clamped_pad" offset=4349)
118+
(inst name = "clamp_17" orientation=R90 cell="sky130_ef_io__vccd_lvc_clamped3_pad" offset=4560)
119+
(inst name = "<pad_inst>" orientation=R90 offset=4771)
120+
(inst name = "IO_FILLER_MANUAL_W_1" orientation = R90 offset = 415 cell = "sky130_ef_io__com_bus_slice_20um")
121+
(inst name = "IO_FILLER_MANUAL_W_2" orientation = R90 offset = 2279 cell = "sky130_ef_io__com_bus_slice_20um")
122+
(inst name = "IO_FILLER_MANUAL_W_3" orientation = R90 offset = 4635 cell = "sky130_ef_io__com_bus_slice_20um")
123+
)
124+
)

0 commit comments

Comments
 (0)