From 5277152e35f664a23e816c26fcc66e605173b19a Mon Sep 17 00:00:00 2001 From: cadeberkeley <74031820+cadeberkeley@users.noreply.github.com> Date: Mon, 13 May 2024 09:09:35 -0700 Subject: [PATCH] Added simple PLE flow and progress on iSpatial flow. (#829) * Added simple PLE flow and progress on iSpatial flow. * Removed hard-coded floorplan generation, now reads in def. * Updated comments describing physical flow effort levels. * Moved syn_opt step into syn_map because it is entirely conditional. * ispatial and ple * removed qrc bug fix --------- Co-authored-by: Cade Richard Co-authored-by: Class Account Co-authored-by: Evan Li <53130369+GooglyCoffee@users.noreply.github.com> --- hammer/synthesis/genus/__init__.py | 57 +++++++++++++++++++++++++++- hammer/synthesis/genus/defaults.yml | 7 ++++ hammer/tech/__init__.py | 1 + hammer/technology/sky130/__init__.py | 4 +- hammer/vlsi/cli_driver.py | 1 - 5 files changed, 65 insertions(+), 5 deletions(-) diff --git a/hammer/synthesis/genus/__init__.py b/hammer/synthesis/genus/__init__.py index a167f08b7..0133db8b6 100644 --- a/hammer/synthesis/genus/__init__.py +++ b/hammer/synthesis/genus/__init__.py @@ -85,6 +85,7 @@ def get_tool_hooks(self) -> List[HammerToolHookAction]: def steps(self) -> List[HammerToolStep]: steps_methods = [ self.init_environment, + self.predict_floorplan, self.syn_generic, self.syn_map, self.add_tieoffs, @@ -223,6 +224,19 @@ def init_environment(self) -> bool: files=" ".join(lef_files) )) + # Read qrc tech files for physical synthesis. + qrc_files = self.technology.read_libs([ + hammer_tech.filters.qrc_tech_filter + ], hammer_tech.HammerTechnologyUtils.to_plain_item) + verbose_append("set_db qrc_tech_file {{ {files} }}".format( + files=" ".join(qrc_files) + )) + + # Quit when ispatial is used with sky130 + if(not qrc_files and self.get_setting("synthesis.genus.phys_flow_effort").lower() == "high"): + self.logger.warning("Sky130 does not support ISpatial due to missing of qrc tech files.") + verbose_append("quit") + # Load input files and check that they are all Verilog. if not self.check_input_files([".v", ".sv", "vh"]): return False @@ -264,6 +278,12 @@ def init_environment(self) -> bool: # TODO: is there a way to track instance paths through the synthesis process? verbose_append("set_db root: .auto_ungroup none") + # Set design effort. + verbose_append(f"set_db phys_flow_effort {self.get_setting('synthesis.genus.phys_flow_effort')}") + + if self.get_setting("synthesis.genus.phys_flow_effort").lower() == "high": + self.verbose_append("set_db opt_spatial_effort extreme") + # Set "don't use" cells. for l in self.generate_dont_use_commands(): self.append(l) @@ -325,14 +345,28 @@ def syn_generic(self) -> bool: if len(inverter_cells) > 0 and len(logic_cells) > 0: # Clock mapping needs at least the attributes cts_inverter_cells and cts_logic_cells to be set self.append("set_db map_clock_tree true") - self.verbose_append("syn_generic") + + if self.get_setting("synthesis.genus.phys_flow_effort").lower() == "none": + self.verbose_append("syn_generic") + else: + self.verbose_append("syn_generic -physical") self.dedup_ilms() return True def syn_map(self) -> bool: - self.verbose_append("syn_map") + if self.get_setting("synthesis.genus.phys_flow_effort").lower() == "none": + self.verbose_append("syn_map") + else: + self.verbose_append("syn_map -physical") + + # High QoR optimization. + if self.get_setting("synthesis.genus.phys_flow_effort").lower() == "medium": + self.verbose_append("syn_opt") + elif self.get_setting("synthesis.genus.phys_flow_effort").lower() == "high": + self.verbose_append("syn_opt -spatial") + # Need to suffix modules for hierarchical simulation if not top if self.hierarchical_mode not in [HierarchicalMode.Flat, HierarchicalMode.Top]: self.verbose_append("update_names -module -log hier_updated_names.log -suffix _{MODULE}".format(MODULE=self.top_module)) @@ -340,6 +374,19 @@ def syn_map(self) -> bool: self.dedup_ilms() return True + + def predict_floorplan(self) -> bool: + if self.get_setting("synthesis.genus.phys_flow_effort").lower() == "none": + self.verbose_append("set_db predict_floorplan_enable_during_generic false") + self.verbose_append("set_db physical_force_predict_floorplan false") + else: + self.verbose_append("set_db invs_temp_dir temp_invs") + self.verbose_append(f"set_db innovus_executable {self.get_setting('par.innovus.innovus_bin')}") + self.verbose_append("set_db predict_floorplan_enable_during_generic true") + self.verbose_append("set_db physical_force_predict_floorplan true") + self.verbose_append(f"set_db predict_floorplan_use_innovus true") + self.verbose_append("predict_floorplan") + return True def add_tieoffs(self) -> bool: tie_hi_cells = self.technology.get_special_cell_by_type(CellType.TieHiCell) @@ -376,8 +423,13 @@ def generate_reports(self) -> bool: """Generate reports.""" # TODO: extend report generation capabilities self.verbose_append("write_reports -directory reports -tag final") + if self.get_setting("synthesis.genus.phys_flow_effort").lower() != "none": + self.verbose_append("report_ple > reports/final_ple.rpt") + #qor done by write_reports + # Write reports does not normally report unconstrained paths self.verbose_append("report_timing -unconstrained -max_paths 50 > reports/final_unconstrained.rpt") + return True def write_regs(self) -> bool: @@ -420,6 +472,7 @@ def write_outputs(self) -> bool: verbose_append("write_design -innovus {hier_flag} -gzip_files {top}".format( hier_flag="-hierarchical" if is_hier else "", top=top)) + verbose_append("write_db -common") self.ran_write_outputs = True return True diff --git a/hammer/synthesis/genus/defaults.yml b/hammer/synthesis/genus/defaults.yml index fee8294b9..d1ae43d6f 100644 --- a/hammer/synthesis/genus/defaults.yml +++ b/hammer/synthesis/genus/defaults.yml @@ -8,5 +8,12 @@ synthesis.genus: # Used to locate the binary - e.g. the '221' in ${cadence.cadence_home}/DDI/DDI221/GENUS221/bin/genus version: "231" + # Physical flow effort. + # Valid options: high, medium, and none. Requires Genus Physical Option (GEN40) license and access to the Innovus System. + # High effort: Provides the best QoR at the cost of runtime. Requires Genus_Physical_Opt license. + # Medium effort: Offers the best trade-off between the runtime and QoR and turns legalization off by default. + # None: Will result in the best runtime. Works with all base Genus products. + phys_flow_effort: "medium" + # Generate the TCL file but do not run it yet. generate_only: false diff --git a/hammer/tech/__init__.py b/hammer/tech/__init__.py index 24482b6d0..b4e844252 100644 --- a/hammer/tech/__init__.py +++ b/hammer/tech/__init__.py @@ -127,6 +127,7 @@ class Library(BaseModel): spice_model_file: Optional[SpiceModelFile] = None power_grid_library: Optional[str] = None extra_prefixes: Optional[List[PathPrefix]] = None + def_file: Optional[str] = None PathsFunctionType = Callable[[Library], List[str]] diff --git a/hammer/technology/sky130/__init__.py b/hammer/technology/sky130/__init__.py index 5eda84b08..a814688f1 100644 --- a/hammer/technology/sky130/__init__.py +++ b/hammer/technology/sky130/__init__.py @@ -29,9 +29,9 @@ def post_install_script(self) -> None: # check whether variables were overriden to point to a valid path self.use_sram22 = os.path.exists(self.get_setting("technology.sky130.sram22_sky130_macros")) self.setup_cdl() - self.setup_verilog() + # self.setup_verilog() self.setup_techlef() - self.setup_io_lefs() + # self.setup_io_lefs() self.logger.info('Loaded Sky130 Tech') diff --git a/hammer/vlsi/cli_driver.py b/hammer/vlsi/cli_driver.py index 574914862..b50aeee3c 100644 --- a/hammer/vlsi/cli_driver.py +++ b/hammer/vlsi/cli_driver.py @@ -156,7 +156,6 @@ def __init__(self) -> None: self.formal_rundir = "" # type: Optional[str] self.timing_rundir = "" # type: Optional[str] self.pcb_rundir = "" # type: Optional[str] - self.synthesis_action: CLIActionConfigType # If a subclass has defined these, don't clobber them in init # since the subclass still uses this init function.