diff --git a/doc/CAD-Tools/Pegasus.md b/doc/CAD-Tools/Pegasus.md new file mode 120000 index 000000000..54ad788b4 --- /dev/null +++ b/doc/CAD-Tools/Pegasus.md @@ -0,0 +1 @@ +../../hammer/drc/pegasus/README.md \ No newline at end of file diff --git a/doc/CAD-Tools/index.rst b/doc/CAD-Tools/index.rst index 74991b7ee..e47dd1cd2 100644 --- a/doc/CAD-Tools/index.rst +++ b/doc/CAD-Tools/index.rst @@ -15,3 +15,4 @@ The package should contain an class object named 'tool' to create an instance of Tool-Plugin-Setup OpenROAD ICV + Pegasus diff --git a/e2e/pdks/sky130-bwrc.yml b/e2e/pdks/sky130-bwrc.yml new file mode 100644 index 000000000..e7feb9a04 --- /dev/null +++ b/e2e/pdks/sky130-bwrc.yml @@ -0,0 +1,24 @@ +vlsi.core.technology: "hammer.technology.sky130" +technology.sky130: + sky130A: "/tools/commercial/skywater/local/chipyard-tutorial/.conda-sky130/share/pdk/sky130A" + sram22_sky130_macros: "/tools/commercial/skywater/local/chipyard-tutorial/sram22_sky130_macros" + openram_lib: "/tools/commercial/skywater/local/sky130_sram_macros" + sky130_nda: "/tools/commercial/skywater/swtech130/skywater-src-nda-20221031" + sky130_cds: "/tools/commercial/skywater/sky130_cds/sky130_prelim_release_091123" + +synthesis.genus.version: "211" +par.innovus.version: "211" + +sim.vcs.version: "S-2021.09-SP1-1" +sim.vcs.verdi_home: "/tools/synopsys/verdi/${sim.vcs.version}" +sim.vcs.verdi_home_meta: lazysubst + +synthesis.yosys.yosys_bin: "/tools/commercial/skywater/local/chipyard-tutorial/.conda-yosys/bin/yosys" +par.openroad.openroad_bin: "/tools/commercial/skywater/local/chipyard-tutorial/.conda-openroad/bin/openroad" +par.openroad.klayout_bin: "/tools/commercial/skywater/local/chipyard-tutorial/.conda-klayout/bin/klayout" +drc.magic.magic_bin: "/tools/commercial/skywater/local/chipyard-tutorial/.conda-signoff/bin/magic" +lvs.netgen.netgen_bin: "/tools/commercial/skywater/local/chipyard-tutorial/.conda-signoff/bin/netgen" + +# speed up tutorial runs & declutter log output +par.openroad.timing_driven: false +par.openroad.write_reports: false diff --git a/hammer/drc/pegasus/README.md b/hammer/drc/pegasus/README.md new file mode 100644 index 000000000..4cbb9f426 --- /dev/null +++ b/hammer/drc/pegasus/README.md @@ -0,0 +1,30 @@ +# DRC/LVS with Pegasus + +## Pegasus usage notes + + Although batch Pegasus is primarily command-line option driven, the only way to override certain directives in the rule decks is to generate a control file called `pegasusdrcctl` for DRC or `pegasuslvsctl` for LVS. +* This file can also be used to fill in fields in the GUI version for debugging, and changes in the the GUI will then overwrite this file. +* This file is generated by the `generate_drc_ctl_file`/`generate_lvs_ctl_file` step. Changes to what appears in this file must be done with either the key `drc.inputs.additional_drc_text`/`lvs.inputs.additional_lvs_text` with each line terminated by a semicolon (appends to the end of the generated file), or with a replacement hook. + +## Pegasus Design Review usage notes + +Pegasus Design Review (DR) and Results Viewer (RV) together are the GUI DRC/LVS results browser. + +The first time you open DR with the `view_drc`/`view_lvs` script, you will get an error message: + +A Valid Technology File Path is Required? +"": Not Found? + +This is because you need to load the DRC/LVS deck as a technology. + +To import the technology, in the main Design Review windows, go to: + +Tools -> Technology Manager (window pops up) -> File -> Import -> PVL (tab) + +In this dialog window, enter the technology basename in the Hammer input key `vlsi.core.technology` (e.g. "sky130", not "hammer.technology.sky130") in the "Technology Name" field and browse to the DRC/LVS deck in the PVL Rule File dialog. Then hit Import, close the Technology Manager, close DR, and run the `view_drc`/`view_lvs` script again. + +Subsequent openings of databases anywhere will map to this technology and label layers properly because the technology information is stored your home directory. + +Tested with: + +* sky130 diff --git a/hammer/drc/pegasus/__init__.py b/hammer/drc/pegasus/__init__.py new file mode 100644 index 000000000..1f5b3509e --- /dev/null +++ b/hammer/drc/pegasus/__init__.py @@ -0,0 +1,141 @@ +# hammer-vlsi plugin for Cadence Pegasus. +# +# See LICENSE for licence details. + +from hammer.vlsi import HammerToolStep +from hammer.vlsi import HammerDRCTool +from hammer.common.cadence import CadenceTool +from hammer.logging import HammerVLSILogging + +from typing import Dict, List, Optional + +import os +import textwrap + + +class PegasusDRC(HammerDRCTool, CadenceTool): + + def tool_config_prefix(self) -> str: + return "drc.pegasus" + + def drc_results_pre_waived(self) -> Dict[str, int]: + return {} + + def fill_outputs(self) -> bool: + return True + + # TODO: placeholder empty step + def empty_step(self) -> bool: + return True + + @property + def steps(self) -> List[HammerToolStep]: + steps = [self.generate_drc_ctl_file] # TODO: DRC steps require multiple runs of the tool how do we support this? + return self.make_steps_from_methods(steps) + + def do_post_steps(self) -> bool: + assert super().do_post_steps() + return self.run_pegasus() + + def globally_waived_drc_rules(self) -> List[str]: + return [] + + def run_pegasus(self) -> bool: + self.create_enter_script() + + rules = list(map(lambda d: d.path, self.get_drc_decks())) + + # set the command arguments + pegasus_bin = self.get_setting("drc.pegasus.pegasus_bin") + args = [ + pegasus_bin, + "-drc", # DRC mode + "-dp", str(self.get_setting("vlsi.core.max_threads")), + "-license_dp_continue", # don't quit if requested dp license not available + "-control", self.drc_ctl_file, + "-log_dir", f"{self.top_module}_logs", + "-ui_data" # for results viewer + # TODO: -interactive for block level + ] + rules + + HammerVLSILogging.enable_colour = False + HammerVLSILogging.enable_tag = False + self.run_executable(args, cwd=self.run_dir) # TODO: check for errors and deal with them + HammerVLSILogging.enable_colour = True + HammerVLSILogging.enable_tag = True + + # TODO: check that drc run was successful + + # Create view_drc script & design review macro script file + # See the README for how this works + os.makedirs(self.generated_scripts_dir, exist_ok=True) + + technology = self.get_setting("vlsi.core.technology").split(".")[-1] + with open(self.view_drc_script, "w") as f: + f.write(textwrap.dedent(f""" + cd {self.run_dir} + source ./enter + {pegasus_bin}DesignReview -qrv -tech {technology} -data {self.layout_file} -post {self.dr_rv_macro} -verbose + """)) + os.chmod(self.view_drc_script, 0o755) + + with open(self.dr_rv_macro, "w") as f: + f.write(textwrap.dedent(f''' + PVS::invoke_pvsrv("{self.run_dir}"); + ''')) + + return True + + def generate_drc_ctl_file(self) -> bool: + """ Generate the DRC control file self.drc_ctl_file and fill its contents """ + with open(self.drc_ctl_file, "w") as f: + f.write(self.header.replace("#","//")) + f.write(textwrap.dedent(f''' + virtual_connect -report yes; + layout_path "{self.layout_file}"; + layout_primary {self.top_module}; + results_db -drc "{self.drc_results_db}" -ascii; + report_summary -drc "{self.drc_results_file}" -replace; + ''')) + f.write(self.get_additional_drc_text()) + return True + + @property + def generated_scripts_dir(self) -> str: + return os.path.join(self.run_dir, "generated-scripts") + + @property + def view_drc_script(self) -> str: + return os.path.join(self.generated_scripts_dir, "view_drc") + + @property + def dr_rv_macro(self) -> str: + return os.path.join(self.generated_scripts_dir, "dr.mac") + + @property + def drc_ctl_file(self) -> str: + return os.path.join(self.run_dir, "pegasusdrcctl") + + @property + def drc_results_db(self) -> str: + return os.path.join(self.run_dir, self.top_module + ".drc_errors.ascii") + + @property + def drc_results_file(self) -> str: + return os.path.join(self.run_dir, self.top_module + ".drc_results") + + @property + def env_vars(self) -> Dict[str, str]: + """ + Get the list of environment variables required for this tool. + Note to subclasses: remember to include variables from super().env_vars! + """ + v = dict(super().env_vars) + v["PEGASUS_BIN"] = self.get_setting("drc.pegasus.pegasus_bin") + return v + + @property + def post_synth_sdc(self) -> Optional[str]: + pass + +tool = PegasusDRC diff --git a/hammer/drc/pegasus/defaults.yml b/hammer/drc/pegasus/defaults.yml new file mode 100644 index 000000000..ec13b9196 --- /dev/null +++ b/hammer/drc/pegasus/defaults.yml @@ -0,0 +1,8 @@ +# Default settings for Pegasus DRC, for project/technology configuration and overriding. +drc.pegasus: + # Location of the binary + pegasus_bin: "${cadence.cadence_home}/PEGASUS/PEGASUS${drc.pegasus.version}/bin/pegasus" + pegasus_bin_meta: lazysubst + + # type: str + version: "231" diff --git a/hammer/drc/pegasus/defaults_types.yml b/hammer/drc/pegasus/defaults_types.yml new file mode 100644 index 000000000..9a74dd234 --- /dev/null +++ b/hammer/drc/pegasus/defaults_types.yml @@ -0,0 +1,6 @@ +# Default settings for Pegasus DRC, for project/technology configuration and overriding. +drc.pegasus: + # Location of the binary + pegasus_bin: str + + version: str diff --git a/hammer/lvs/pegasus/README.md b/hammer/lvs/pegasus/README.md new file mode 120000 index 000000000..77db6a415 --- /dev/null +++ b/hammer/lvs/pegasus/README.md @@ -0,0 +1 @@ +../../drc/pegasus/README.md \ No newline at end of file diff --git a/hammer/lvs/pegasus/__init__.py b/hammer/lvs/pegasus/__init__.py new file mode 100644 index 000000000..140144c43 --- /dev/null +++ b/hammer/lvs/pegasus/__init__.py @@ -0,0 +1,185 @@ +# hammer-vlsi plugin for Cadence Pegasus. +# +# See LICENSE for licence details. + +from hammer.vlsi import HammerToolStep +from hammer.vlsi import HammerLVSTool +from hammer.common.cadence import CadenceTool +from hammer.logging import HammerVLSILogging +from hammer.utils import HammerFiletype, get_filetype +import hammer.tech as hammer_tech + +from typing import Dict, List, Optional + +import os +import textwrap + + +class PegasusLVS(HammerLVSTool, CadenceTool): + + def tool_config_prefix(self) -> str: + return "lvs.pegasus" + + def erc_results_pre_waived(self) -> Dict[str, int]: + return {} + + def lvs_results(self) -> List[str]: + return [] + + def fill_outputs(self) -> bool: + return True + + # TODO: placeholder empty step + def empty_step(self) -> bool: + return True + + @property + def steps(self) -> List[HammerToolStep]: + steps = [self.generate_lvs_ctl_file] # TODO: LVS steps require multiple runs of the tool how do we support this? + return self.make_steps_from_methods(steps) + + def do_post_steps(self) -> bool: + assert super().do_post_steps() + return self.run_pegasus() + + def globally_waived_erc_rules(self) -> List[str]: + return [] + + def run_pegasus(self) -> bool: + self.create_enter_script() + + rules = list(map(lambda d: d.path, self.get_lvs_decks())) + + # set the command arguments + pegasus_bin = self.get_setting("lvs.pegasus.pegasus_bin") + args = [ + pegasus_bin, + "-lvs", # LVS mode + "-dp", str(self.get_setting("vlsi.core.max_threads")), + "-license_dp_continue", # don't quit if requested dp license not available + "-automatch", # hierarchical correspondence + "-check_schematic", # check schematic integrity + "-control", self.lvs_ctl_file, + "-log_dir", f"{self.top_module}_logs", + "-ui_data" # for results viewer + ] + rules + + HammerVLSILogging.enable_colour = False + HammerVLSILogging.enable_tag = False + self.run_executable(args, cwd=self.run_dir) # TODO: check for errors and deal with them + HammerVLSILogging.enable_colour = True + HammerVLSILogging.enable_tag = True + + # TODO: check that lvs run was successful + + # Create view_lvs script & design review macro script file + # See the README for how this works + os.makedirs(self.generated_scripts_dir, exist_ok=True) + + technology = self.get_setting("vlsi.core.technology").split(".")[-1] + with open(self.view_lvs_script, "w") as f: + f.write(textwrap.dedent(f""" + cd {self.run_dir} + source ./enter + {pegasus_bin}DesignReview -qrv -tech {technology} -data {self.layout_file} -post {self.dr_rv_macro} -verbose + """)) + os.chmod(self.view_lvs_script, 0o755) + + with open(self.dr_rv_macro, "w") as f: + f.write(textwrap.dedent(f''' + PVS::invoke_pvsrv("{self.run_dir}"); + ''')) + + return True + + def generate_lvs_ctl_file(self) -> bool: + """ Generate the LVS control file self.lvs_ctl_file and fill its contents """ + library_spice_files = self.technology.read_libs([hammer_tech.filters.spice_filter], hammer_tech.HammerTechnologyUtils.to_plain_item) + ilms = list(map(lambda x: x.netlist, self.get_input_ilms())) # type: List[str] + + all_files = library_spice_files + self.schematic_files + ilms + spice_files = list(filter(lambda x: get_filetype(x) is HammerFiletype.SPICE, all_files)) + verilog_files = list(filter(lambda x: get_filetype(x) is HammerFiletype.VERILOG, all_files)) + unmatched = set(all_files).symmetric_difference(set(spice_files + verilog_files)) + if unmatched: + raise NotImplementedError("Unsupported netlist type for files: " + str(unmatched)) + + power_list="\n".join(map(lambda x: x.name, self.get_independent_power_nets())) + ground_list="\n".join(map(lambda x: x.name, self.get_independent_ground_nets())) + + with open(self.lvs_ctl_file, "w") as f: + f.write(self.header.replace("#","//") + "\n") + for sf in spice_files: + if os.path.basename(sf).split(".")[0] in ["cdl", "CDL"]: + f.write(f'schematic_path "{sf}" cdl;\n') + 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(textwrap.dedent(f''' + schematic_primary {self.top_module}; + layout_path "{self.layout_file}"; + layout_primary {self.top_module}; + lvs_power_name {power_list}; + lvs_ground_name {ground_list}; + lvs_find_shorts yes; + lvs_report_opt S; + results_db -erc "{self.erc_results_db}" -ascii; + report_summary -erc "{self.erc_results_file}" -replace; + lvs_report_file "{self.lvs_results_file}"; + ''')) + f.write(self.get_additional_lvs_text()) + return True + + @property + def hcells_file(self) -> str: + return os.path.join(self.run_dir, "hcells") + + def generate_hcells_file(self) -> None: + with open(self.hcells_file, "w") as f: + f.write("") + # TODO + + @property + def generated_scripts_dir(self) -> str: + return os.path.join(self.run_dir, "generated-scripts") + + @property + def view_lvs_script(self) -> str: + return os.path.join(self.generated_scripts_dir, "view_lvs") + + @property + def dr_rv_macro(self) -> str: + return os.path.join(self.generated_scripts_dir, "dr.mac") + + @property + def lvs_ctl_file(self) -> str: + return os.path.join(self.run_dir, "pegasuslvsctl") + + @property + def erc_results_db(self) -> str: + return os.path.join(self.run_dir, self.top_module + ".erc_errors.ascii") + + @property + def erc_results_file(self) -> str: + return os.path.join(self.run_dir, self.top_module + ".erc_results") + + @property + def lvs_results_file(self) -> str: + return os.path.join(self.run_dir, self.top_module + ".lvs_results") + + @property + def env_vars(self) -> Dict[str, str]: + """ + Get the list of environment variables required for this tool. + Note to subclasses: remember to include variables from super().env_vars! + """ + v = dict(super().env_vars) + v["PEGASUS_BIN"] = self.get_setting("lvs.pegasus.pegasus_bin") + return v + + @property + def post_synth_sdc(self) -> Optional[str]: + pass + +tool = PegasusLVS diff --git a/hammer/lvs/pegasus/defaults.yml b/hammer/lvs/pegasus/defaults.yml new file mode 100644 index 000000000..f9b7998d3 --- /dev/null +++ b/hammer/lvs/pegasus/defaults.yml @@ -0,0 +1,8 @@ +# Default settings for Pegasus LVS, for project/technology configuration and overriding. +lvs.pegasus: + # Location of the binary + pegasus_bin: "${cadence.cadence_home}/PEGASUS/PEGASUS${lvs.pegasus.version}/bin/pegasus" + pegasus_bin_meta: lazysubst + + # type: str + version: "231" diff --git a/hammer/lvs/pegasus/defaults_types.yml b/hammer/lvs/pegasus/defaults_types.yml new file mode 100644 index 000000000..6c728067b --- /dev/null +++ b/hammer/lvs/pegasus/defaults_types.yml @@ -0,0 +1,6 @@ +# Default settings for Pegasus LVS, for project/technology configuration and overriding. +lvs.pegasus: + # Location of the binary + pegasus_bin: str + + version: str diff --git a/hammer/tech/__init__.py b/hammer/tech/__init__.py index 3dc8beb32..35362c2c9 100644 --- a/hammer/tech/__init__.py +++ b/hammer/tech/__init__.py @@ -724,7 +724,7 @@ def check_installs(self) -> bool: path_key = install.path install_path = str(self.get_setting(path_key)) if not os.path.exists(install_path): - self.logger.error(f"The install path: {install_path} does not exist, looked at key {path_key}") + self.logger.warning(f"The install path: {install_path} does not exist, looked at key {path_key}") return False return True diff --git a/hammer/technology/sky130/__init__.py b/hammer/technology/sky130/__init__.py index 9587e2363..4c2201492 100644 --- a/hammer/technology/sky130/__init__.py +++ b/hammer/technology/sky130/__init__.py @@ -26,12 +26,10 @@ class SKY130Tech(HammerTechnology): def post_install_script(self) -> None: self.library_name = 'sky130_fd_sc_hd' # check whether variables were overriden to point to a valid path - self.use_nda_files = os.path.exists(self.get_setting("technology.sky130.sky130_nda")) self.use_sram22 = os.path.exists(self.get_setting("technology.sky130.sram22_sky130_macros")) self.setup_cdl() self.setup_verilog() self.setup_techlef() - self.setup_lvs_deck() self.setup_io_lefs() print('Loaded Sky130 Tech') @@ -134,34 +132,6 @@ def setup_techlef(self) -> None: if line.strip() == 'END pwell': df.write(_the_tlef_edit) - # Remove conflicting specification statements found in PDK LVS decks - def setup_lvs_deck(self) -> None: - if not self.use_nda_files: return - pattern = '.*({}).*\n'.format('|'.join(LVS_DECK_SCRUB_LINES)) - matcher = re.compile(pattern) - - source_paths = self.get_setting('technology.sky130.lvs_deck_sources') - lvs_decks = self.config.lvs_decks - if not lvs_decks: - return - for i in range(len(lvs_decks)): - deck = lvs_decks[i] - try: - source_path = Path(source_paths[i]) - except IndexError: - self.logger.error( - 'No corresponding source for LVS deck {}'.format(deck)) - if not source_path.exists(): - raise FileNotFoundError(f"LVS deck not found: {source_path}") - dest_path = self.expand_tech_cache_path(str(deck.path)) - self.ensure_dirs_exist(dest_path) - with open(source_path, 'r') as sf: - with open(dest_path, 'w') as df: - self.logger.info("Modifying LVS deck: {} -> {}".format - (source_path, dest_path)) - 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: @@ -216,7 +186,7 @@ def get_tech_drc_hooks(self, tool_name: str) -> List[HammerToolHookAction]: return hooks.get(tool_name, []) def get_tech_lvs_hooks(self, tool_name: str) -> List[HammerToolHookAction]: - calibre_hooks = [] + calibre_hooks = [HammerTool.make_post_insertion_hook("generate_lvs_run_file", setup_calibre_lvs_deck)] 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"): @@ -250,19 +220,6 @@ def sky130_sram_names() -> List[str]: END licon ''' -LVS_DECK_SCRUB_LINES = [ - "VIRTUAL CONNECT REPORT", - "SOURCE PRIMARY", - "SOURCE SYSTEM SPICE", - "SOURCE PATH", - "ERC", - "LVS REPORT" -] - -LVS_DECK_INSERT_LINES = ''' -LVS FILTER D OPEN SOURCE -LVS FILTER D OPEN LAYOUT -''' # various Innovus database settings def sky130_innovus_settings(ht: HammerTool) -> bool: @@ -434,4 +391,50 @@ def sram22_lvs_recognize_gates_all(ht: HammerTool) -> bool: f.write("LVS RECOGNIZE GATES ALL") return True + +LVS_DECK_SCRUB_LINES = [ + "VIRTUAL CONNECT REPORT", + "SOURCE PRIMARY", + "SOURCE SYSTEM SPICE", + "SOURCE PATH", + "ERC", + "LVS REPORT" +] + +LVS_DECK_INSERT_LINES = ''' +LVS FILTER D OPEN SOURCE +LVS FILTER D OPEN LAYOUT +''' + +def setup_calibre_lvs_deck(ht: HammerTool) -> bool: + assert isinstance(ht, HammerLVSTool), "Modify Calibre LVS deck for LVS only" + # Remove conflicting specification statements found in PDK LVS decks + pattern = '.*({}).*\n'.format('|'.join(LVS_DECK_SCRUB_LINES)) + matcher = re.compile(pattern) + + source_paths = ht.get_setting('technology.sky130.lvs_deck_sources') + lvs_decks = ht.technology.config.lvs_decks + if not lvs_decks: + return True + for i,deck in enumerate(lvs_decks): + if deck.tool_name != 'calibre': continue + try: + source_path = Path(source_paths[i]) + except IndexError: + ht.logger.error( + 'No corresponding source for LVS deck {}'.format(deck)) + continue + if not source_path.exists(): + raise FileNotFoundError(f"LVS deck not found: {source_path}") + dest_path = ht.technology.expand_tech_cache_path(str(deck.path)) + ht.technology.ensure_dirs_exist(dest_path) + with open(source_path, 'r') as sf: + with open(dest_path, 'w') as df: + ht.logger.info("Modifying LVS deck: {} -> {}".format + (source_path, dest_path)) + df.write(matcher.sub("", sf.read())) + df.write(LVS_DECK_INSERT_LINES) + return True + + tech = SKY130Tech() diff --git a/hammer/technology/sky130/defaults.yml b/hammer/technology/sky130/defaults.yml index 7f6250683..48068af66 100644 --- a/hammer/technology/sky130/defaults.yml +++ b/hammer/technology/sky130/defaults.yml @@ -8,6 +8,9 @@ technology.sky130: # this key is OPTIONAL, no NDA files will be used if it does not point to a valid path # By default, this is used to populate pdk_home below. # It should contain s8/V2.0.1 + + sky130_cds: "/path/to/sky130_cds" # This contains the Cadence PDK + # this key is OPTIONAL, and is only required if you are running Pegasus DRC/LVS. sram22_sky130_macros: "/path/to/sram22_sky130_macros" # SRAM path # /path/to/sram22_sky130_macros diff --git a/hammer/technology/sky130/defaults_types.yml b/hammer/technology/sky130/defaults_types.yml index b43a22faa..f46c2e6f7 100644 --- a/hammer/technology/sky130/defaults_types.yml +++ b/hammer/technology/sky130/defaults_types.yml @@ -10,7 +10,11 @@ technology.sky130: # By default, this is used to populate pdk_home below. # It should contain s8/V2.0.1 sky130_nda: str - + + # This contains the Cadence PDK + # this key is OPTIONAL, and is only required if you are running Pegasus DRC/LVS. + sky130_cds: str + # RAM paths # OpenRAM openram_lib: str diff --git a/hammer/technology/sky130/sky130.tech.json b/hammer/technology/sky130/sky130.tech.json index bdd9fa099..bf07a5bd6 100644 --- a/hammer/technology/sky130/sky130.tech.json +++ b/hammer/technology/sky130/sky130.tech.json @@ -9,6 +9,10 @@ { "id": "$SKY130A", "path": "technology.sky130.sky130A" + }, + { + "id": "$SKY130_CDS", + "path": "technology.sky130.sky130_cds" } ], "layer_map_file": "$SKY130_NDA/s8/V2.0.1/VirtuosoOA/libs/technology_library/technology_library.layermap", @@ -22,6 +26,11 @@ "tool_name": "klayout", "deck_name": "klayout_drc", "path": "$SKY130A/libs.tech/klayout/drc/sky130A.lydrc" + }, + { + "tool_name": "pegasus", + "deck_name": "pegasus_drc", + "path": "$SKY130_CDS/pegasus/sky130_rev0006.drc.pvl" } ], "additional_drc_text": "", @@ -31,6 +40,11 @@ "deck_name": "calibre_lvs", "old_path": "$SKY130_NDA/s8/V2.0.1/LVS/Calibre/lvsRules_s8", "path": "cache/lvsControlFile_s8" + }, + { + "tool_name": "pegasus", + "deck_name": "pegasus_lvs", + "path": "$SKY130_CDS/pegasus/sky130_rev0001.lvs.pvl" } ], "additional_lvs_text": "", @@ -2022,4 +2036,4 @@ "y": 5.44 } ] -} +} \ No newline at end of file