Skip to content

Commit

Permalink
Update plugin for Cadence's latest SKY 130 PDK release (#839)
Browse files Browse the repository at this point in the history
* update cadence SKY130 PDK

* fix task name

* fix deck file names

* fix lvs deck path

* update for eecs251b labs

* add option to output extraction data for Quantus

* Clean up fixes

* fix errors with LVS logic

---------

Co-authored-by: eecs251b <[email protected]>
  • Loading branch information
rohanku and eecs251b authored Feb 12, 2024
1 parent bec5269 commit 8124730
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 56 deletions.
3 changes: 2 additions & 1 deletion hammer/lvs/pegasus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def run_pegasus(self) -> bool:
"-check_schematic", # check schematic integrity
"-control", self.lvs_ctl_file,
"-log_dir", f"{self.top_module}_logs",
"-rc_data", # for PEX
"-ui_data" # for results viewer
] + rules

Expand Down Expand Up @@ -115,7 +116,7 @@ def generate_lvs_ctl_file(self) -> bool:
else:
f.write(f'schematic_path "{sf}" spice;\n')
for vf in verilog_files:
f.write(f'schematic_path "{vf}" verilog -keep_backslash -detect_buses -check_inconsistent_instances;\n')
f.write(f'schematic_path "{vf}" verilog -keep_backslash -detect_buses -check_inconsistent_instances -ignore_instances_with_missing_cell_master;\n')
f.write(textwrap.dedent(f'''
schematic_primary {self.top_module};
layout_path "{self.layout_file}";
Expand Down
93 changes: 42 additions & 51 deletions hammer/technology/sky130/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,20 @@ def setup_cdl(self) -> None:
dest_path = cache_tech_dir_path / f'{self.library_name}.cdl'

# device names expected in LVS decks
pmos = 'pfet_01v8_hvt'
nmos = 'nfet_01v8'
if (self.get_setting('vlsi.core.lvs_tool') == "hammer.lvs.calibre"):
pmos = 'phighvt'
nmos = 'nshort'
elif (self.get_setting('vlsi.core.lvs_tool') == "hammer.lvs.netgen"):
pmos = 'sky130_fd_pr__pfet_01v8_hvt'
nmos = 'sky130_fd_pr__nfet_01v8'
else:
shutil.copy2(source_path, dest_path)
return

with open(source_path, 'r') as sf:
with open(dest_path, 'w') as df:
self.logger.info("Modifying CDL netlist: {} -> {}".format
(source_path, dest_path))
df.write("*.SCALE MICRON\n")
for line in sf:
line = line.replace('pfet_01v8_hvt', pmos)
line = line.replace('nfet_01v8' , nmos)
Expand Down Expand Up @@ -100,25 +100,6 @@ def setup_verilog(self) -> None:
with open(dest_path, 'r') as sf:
sl = sf.readlines()

# Find timing declaration
start_idx = [idx for idx, line in enumerate(sl) if "`ifndef SKY130_FD_SC_HD__LPFLOW_BLEEDER_1_TIMING_V" in line][0]

# Search for the broken statement
search_range = range(start_idx+1, len(sl))
broken_specify_idx = len(sl)-1
broken_substr = "(SHORT => VPWR) = (0:0:0,0:0:0,0:0:0,0:0:0,0:0:0,0:0:0);"

broken_specify_idx = [idx for idx in search_range if broken_substr in sl[idx]][0]
endif_idx = [idx for idx in search_range if "`endif" in sl[idx]][0]

# Now, delete all the specify statements if specify exists before an endif.
if broken_specify_idx < endif_idx:
self.logger.info("Removing incorrectly formed specify block.")
cell_def_range = range(start_idx+1, endif_idx)
start_specify_idx = [idx for idx in cell_def_range if "specify" in sl[idx]][0]
end_specify_idx = [idx for idx in cell_def_range if "endspecify" in sl[idx]][0]
sl[start_specify_idx:end_specify_idx+1] = [] # Dice

# Deal with the nonexistent net tactfully (don't code in brittle replacements)
self.logger.info("Fixing broken net references with select specify blocks.")
pattern = r"^\s*wire SLEEP.*B.*delayed;"
Expand Down Expand Up @@ -212,28 +193,6 @@ def setup_io_lefs(self) -> None:
# 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')

# Current version has two one-off error that break lef parser.
self.logger.info("Fixing broken sky130_ef_io__analog_esd_pad LEF definition.")
start_broken_macro_list = ["MACRO sky130_ef_io__analog_esd_pad\n", "MACRO sky130_ef_io__analog_pad\n"]
end_broken_macro_list = ["END sky130_ef_io__analog_pad\n", "END sky130_ef_io__analog_noesd_pad\n"]
end_fixed_macro_list = ["END sky130_ef_io__analog_esd_pad\n", "END sky130_ef_io__analog_pad\n"]

for start_broken_macro, end_broken_macro, end_fixed_macro in zip(start_broken_macro_list, end_broken_macro_list, end_fixed_macro_list):
# Get all start indices to be checked
start_check_indices = [idx for idx, line in enumerate(sl) if line == start_broken_macro]

# Extract broken macro
for idx_broken_macro in start_check_indices:
# Find the start of the next_macro
idx_start_next_macro = [idx for idx in range(idx_broken_macro+1, len(sl)) if "MACRO" in sl[idx]][0]
# Find the broken macro ending
idx_end_broken_macro = len(sl)
idx_end_broken_macro = [idx for idx in range(idx_broken_macro+1, len(sl)) if end_broken_macro in sl[idx]][0]

# Fix
if idx_end_broken_macro < idx_start_next_macro:
sl[idx_end_broken_macro] = end_fixed_macro

df.writelines(sl)

Expand All @@ -249,19 +208,25 @@ def get_tech_par_hooks(self, tool_name: str) -> List[HammerToolHookAction]:

def get_tech_drc_hooks(self, tool_name: str) -> List[HammerToolHookAction]:
calibre_hooks = []
pegasus_hooks = []
if self.get_setting("technology.sky130.drc_blackbox_srams"):
calibre_hooks.append(HammerTool.make_post_insertion_hook("generate_drc_run_file", drc_blackbox_srams))
hooks = {"calibre": calibre_hooks
calibre_hooks.append(HammerTool.make_post_insertion_hook("generate_drc_run_file", calibre_drc_blackbox_srams))
pegasus_hooks.append(HammerTool.make_post_insertion_hook("generate_drc_ctl_file", pegasus_drc_blackbox_srams))
hooks = {"calibre": calibre_hooks,
"pegasus": pegasus_hooks
}
return hooks.get(tool_name, [])

def get_tech_lvs_hooks(self, tool_name: str) -> List[HammerToolHookAction]:
calibre_hooks = [HammerTool.make_post_insertion_hook("generate_lvs_run_file", setup_calibre_lvs_deck)]
pegasus_hooks = []
if self.use_sram22:
calibre_hooks.append(HammerTool.make_post_insertion_hook("generate_lvs_run_file", sram22_lvs_recognize_gates_all))
if self.get_setting("technology.sky130.lvs_blackbox_srams"):
calibre_hooks.append(HammerTool.make_post_insertion_hook("generate_lvs_run_file", lvs_blackbox_srams))
hooks = {"calibre": calibre_hooks
calibre_hooks.append(HammerTool.make_post_insertion_hook("generate_lvs_run_file", calibre_lvs_blackbox_srams))
pegasus_hooks.append(HammerTool.make_post_insertion_hook("generate_lvs_ctl_file", pegasus_lvs_blackbox_srams))
hooks = {"calibre": calibre_hooks,
"pegasus": pegasus_hooks
}
return hooks.get(tool_name, [])

Expand Down Expand Up @@ -433,7 +398,7 @@ def efabless_ring_io(ht: HammerTool) -> bool:
''')
return True

def drc_blackbox_srams(ht: HammerTool) -> bool:
def calibre_drc_blackbox_srams(ht: HammerTool) -> bool:
assert isinstance(ht, HammerDRCTool), "Exlude SRAMs only in DRC"
drc_box = ''
for name in SKY130Tech.sky130_sram_names():
Expand All @@ -443,7 +408,17 @@ def drc_blackbox_srams(ht: HammerTool) -> bool:
f.write(drc_box)
return True

def lvs_blackbox_srams(ht: HammerTool) -> bool:
def pegasus_drc_blackbox_srams(ht: HammerTool) -> bool:
assert isinstance(ht, HammerDRCTool), "Exlude SRAMs only in DRC"
drc_box = ''
for name in SKY130Tech.sky130_sram_names():
drc_box += f"\nexclude_cell {name}"
run_file = ht.drc_ctl_file # type: ignore
with open(run_file, "a") as f:
f.write(drc_box)
return True

def calibre_lvs_blackbox_srams(ht: HammerTool) -> bool:
assert isinstance(ht, HammerLVSTool), "Blackbox and filter SRAMs only in LVS"
lvs_box = ''
for name in SKY130Tech.sky130_sram_names():
Expand All @@ -454,8 +429,24 @@ def lvs_blackbox_srams(ht: HammerTool) -> bool:
f.write(lvs_box)
return True

def pegasus_lvs_blackbox_srams(ht: HammerTool) -> bool:
assert isinstance(ht, HammerLVSTool), "Blackbox and filter SRAMs only in LVS"
lvs_box = ''
for name in SKY130Tech.sky130_sram_names():
lvs_box += f"\nlvs_black_box {name} -gray"
run_file = ht.lvs_ctl_file # type: ignore
with open(run_file, "r+") as f:
# Remove SRAM SPICE file includes.
pattern = 'schematic_path.*({}).*spice;\n'.format('|'.join(SKY130Tech.sky130_sram_names()))
matcher = re.compile(pattern)
contents = f.read()
fixed_contents = matcher.sub("", contents) + lvs_box
f.seek(0)
f.write(fixed_contents)
return True

def sram22_lvs_recognize_gates_all(ht: HammerTool) -> bool:
assert isinstance(ht, HammerLVSTool), "Change 'LVS RECOGNIZE GATES' from 'NONE' to 'ALL' for Sram22"
assert isinstance(ht, HammerLVSTool), "Change 'LVS RECOGNIZE GATES' from 'NONE' to 'ALL' for SRAM22"
run_file = ht.lvs_run_file # type: ignore
with open(run_file, "a") as f:
f.write("LVS RECOGNIZE GATES ALL")
Expand Down
8 changes: 4 additions & 4 deletions hammer/technology/sky130/sky130.tech.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
{
"tool_name": "pegasus",
"deck_name": "pegasus_drc",
"path": "$SKY130_CDS/pegasus/sky130_rev0006.drc.pvl"
"path": "$SKY130_CDS/Sky130_DRC/sky130_rev_0.0_1.0.drc.pvl"
}
],
"additional_drc_text": "",
Expand All @@ -44,7 +44,7 @@
{
"tool_name": "pegasus",
"deck_name": "pegasus_lvs",
"path": "$SKY130_CDS/pegasus/sky130_rev0001.lvs.pvl"
"path": "$SKY130_CDS/Sky130_LVS/Sky130_rev_0.0_0.1.lvs.pvl"
}
],
"additional_lvs_text": "",
Expand All @@ -67,7 +67,7 @@
]
},
{
"spice_file": "$SKY130A/libs.ref/sky130_fd_io/spice/sky130_ef_io__analog.spice",
"spice_file": "$SKY130A/libs.ref/sky130_fd_io/spice/sky130_ef_io__analog_pad.spice",
"provides": [
{
"lib_type": "technology"
Expand Down Expand Up @@ -2055,4 +2055,4 @@
"y": 5.44
}
]
}
}

0 comments on commit 8124730

Please sign in to comment.