From b27109518a3024e758309ea91bfa976125b752c6 Mon Sep 17 00:00:00 2001 From: Erik Anderson Date: Fri, 28 Feb 2020 14:19:17 -0800 Subject: [PATCH 1/3] initial cap table support added --- src/hammer-tech/filters.py | 15 +++++++ src/hammer-tech/hammer_tech.py | 2 +- src/hammer-tech/schema.json | 3 ++ .../hammer_vlsi/hammer_vlsi_impl.py | 39 +++++++++++++++---- 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/hammer-tech/filters.py b/src/hammer-tech/filters.py index f5ce3f0bb..70a2efe7a 100644 --- a/src/hammer-tech/filters.py +++ b/src/hammer-tech/filters.py @@ -128,6 +128,21 @@ def paths_func(lib: "Library") -> List[str]: return LibraryFilter.new("qrc", "qrc RC corner tech file", paths_func=paths_func, is_file=True) + @property + def cap_table_filter(self) -> LibraryFilter: + """ + Selecting cap table RC Corner tech files. + """ + + def paths_func(lib: "Library") -> List[str]: + if lib.cap_table_file is not None: + return [lib.cap_table_file] + else: + return [] + + return LibraryFilter.new("cap_table", "cap table RC corner tech file", + paths_func=paths_func, is_file=True) + @property def verilog_synth_filter(self) -> LibraryFilter: """ diff --git a/src/hammer-tech/hammer_tech.py b/src/hammer-tech/hammer_tech.py index 0651c9fd5..1700369ab 100644 --- a/src/hammer-tech/hammer_tech.py +++ b/src/hammer-tech/hammer_tech.py @@ -811,7 +811,7 @@ def process_library_filter(self, # Next, extract paths and prepend them to get the real paths. def get_and_prepend_path(lib: Library) -> Tuple[Library, List[str]]: paths = filt.paths_func(lib) - full_paths = list(map(lambda path: self.prepend_dir_path(path, lib), paths)) + full_paths = list(map(lambda path: self.prepend_dir_path(path, lib) if path else '', paths)) return lib, full_paths libs_and_paths = list(map(get_and_prepend_path, filtered_libs)) # type: List[Tuple[Library, List[str]]] diff --git a/src/hammer-tech/schema.json b/src/hammer-tech/schema.json index a36aaa975..75a73bec8 100644 --- a/src/hammer-tech/schema.json +++ b/src/hammer-tech/schema.json @@ -116,6 +116,9 @@ "qrc techfile" : { "type" : "string" }, + "cap table file" : { + "type" : "string" + }, "supplies" : { "title" : "Supplies", "type" : "object", diff --git a/src/hammer-vlsi/hammer_vlsi/hammer_vlsi_impl.py b/src/hammer-vlsi/hammer_vlsi/hammer_vlsi_impl.py index 1c78e4022..1b42eb5ea 100644 --- a/src/hammer-vlsi/hammer_vlsi/hammer_vlsi_impl.py +++ b/src/hammer-vlsi/hammer_vlsi/hammer_vlsi_impl.py @@ -1473,7 +1473,16 @@ def get_mmmc_qrc(self, corner: MMMCCorner) -> str: lib_args = self.technology.read_libs([hammer_tech.filters.qrc_tech_filter], hammer_tech.HammerTechnologyUtils.to_plain_item, extra_pre_filters=[ - self.filter_for_mmmc(voltage=corner.voltage, temp=corner.temp)]) + self.filter_for_mmmc(voltage=corner.voltage, temp=corner.temp)], + must_exist=False) + return " ".join(lib_args) + + def get_mmmc_cap_table(self, corner: MMMCCorner) -> str: + lib_args = self.technology.read_libs([hammer_tech.filters.cap_table_filter], + hammer_tech.HammerTechnologyUtils.to_plain_item, + extra_pre_filters=[ + self.filter_for_mmmc(voltage=corner.voltage, temp=corner.temp)], + must_exist=False) return " ".join(lib_args) def get_qrc_tech(self) -> str: @@ -1487,6 +1496,17 @@ def get_qrc_tech(self) -> str: ], hammer_tech.HammerTechnologyUtils.to_plain_item) return " ".join(lib_args) + def get_cap_table(self) -> str: + """ + Helper function to get the list of cap table files in space separated format. + + :return: List of cap table files separated by spaces + """ + lib_args = self.technology.read_libs([ + hammer_tech.filters.cap_table_filter + ], hammer_tech.HammerTechnologyUtils.to_plain_item) + return " ".join(lib_args) + def generate_mmmc_script(self) -> str: """ Output for the mmmc.tcl script. @@ -1565,16 +1585,18 @@ def append_mmmc(cmd: str) -> None: name="{n}.hold_cond".format(n=hold_corner.name), list="{n}.hold_set".format(n=hold_corner.name) )) - # Next, create Innovus rc corners from qrc tech files - append_mmmc("create_rc_corner -name {name} -temperature {tempInCelsius} {qrc}".format( + # Next, create Innovus rc corners from qrc tech or cap table files + append_mmmc("create_rc_corner -name {name} -temperature {tempInCelsius} {qrc} {cap_table}".format( name="{n}.setup_rc".format(n=setup_corner.name), tempInCelsius=str(setup_corner.temp.value), - qrc="-qrc_tech {}".format(self.get_mmmc_qrc(setup_corner)) if self.get_mmmc_qrc(setup_corner) != '' else '' + qrc="-qrc_tech {}".format(self.get_mmmc_qrc(setup_corner)) if self.get_mmmc_qrc(setup_corner) != '' else '', + cap_table="-cap_table {}".format(self.get_mmmc_cap_table(setup_corner)) if self.get_mmmc_cap_table(setup_corner) != '' else '' )) - append_mmmc("create_rc_corner -name {name} -temperature {tempInCelsius} {qrc}".format( + append_mmmc("create_rc_corner -name {name} -temperature {tempInCelsius} {qrc} {cap_table}".format( name="{n}.hold_rc".format(n=hold_corner.name), tempInCelsius=str(hold_corner.temp.value), - qrc="-qrc_tech {}".format(self.get_mmmc_qrc(hold_corner)) if self.get_mmmc_qrc(hold_corner) != '' else '' + qrc="-qrc_tech {}".format(self.get_mmmc_qrc(hold_corner)) if self.get_mmmc_qrc(hold_corner) != '' else '', + cap_table="-cap_table {}".format(self.get_mmmc_cap_table(hold_corner)) if self.get_mmmc_cap_table(hold_corner) != '' else '' )) # Next, create an Innovus delay corner. append_mmmc( @@ -1610,10 +1632,11 @@ def append_mmmc(cmd: str) -> None: )) # extra junk: -opcond ... rc_corner_name = "rc_cond" - append_mmmc("create_rc_corner -name {name} -temperature {tempInCelsius} {qrc}".format( + append_mmmc("create_rc_corner -name {name} -temperature {tempInCelsius} {qrc} {cap_table}".format( name=rc_corner_name, tempInCelsius=120, # TODO: this should come from tech config - qrc="-qrc_tech {}".format(self.get_qrc_tech()) if self.get_qrc_tech() != '' else '' + qrc="-qrc_tech {}".format(self.get_qrc_tech()) if self.get_qrc_tech() != '' else '', + cap_table="-cap_table {}".format(self.get_cap_table()) if self.get_cap_table() != '' else '' )) # Next, create an Innovus delay corner. delay_corner_name = "my_delay_corner" From 117d547e348ca8592c55763b60d995bb1b3520fa Mon Sep 17 00:00:00 2001 From: Erik Anderson Date: Tue, 10 Mar 2020 22:09:11 -0700 Subject: [PATCH 2/3] removed space and reinserted indents --- src/hammer-vlsi/hammer_vlsi/hammer_vlsi_impl.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hammer-vlsi/hammer_vlsi/hammer_vlsi_impl.py b/src/hammer-vlsi/hammer_vlsi/hammer_vlsi_impl.py index 1b42eb5ea..e6fac3936 100644 --- a/src/hammer-vlsi/hammer_vlsi/hammer_vlsi_impl.py +++ b/src/hammer-vlsi/hammer_vlsi/hammer_vlsi_impl.py @@ -1473,16 +1473,14 @@ def get_mmmc_qrc(self, corner: MMMCCorner) -> str: lib_args = self.technology.read_libs([hammer_tech.filters.qrc_tech_filter], hammer_tech.HammerTechnologyUtils.to_plain_item, extra_pre_filters=[ - self.filter_for_mmmc(voltage=corner.voltage, temp=corner.temp)], - must_exist=False) + self.filter_for_mmmc(voltage=corner.voltage, temp=corner.temp)], must_exist=False) return " ".join(lib_args) def get_mmmc_cap_table(self, corner: MMMCCorner) -> str: lib_args = self.technology.read_libs([hammer_tech.filters.cap_table_filter], hammer_tech.HammerTechnologyUtils.to_plain_item, extra_pre_filters=[ - self.filter_for_mmmc(voltage=corner.voltage, temp=corner.temp)], - must_exist=False) + self.filter_for_mmmc(voltage=corner.voltage, temp=corner.temp)], must_exist=False) return " ".join(lib_args) def get_qrc_tech(self) -> str: @@ -1585,7 +1583,7 @@ def append_mmmc(cmd: str) -> None: name="{n}.hold_cond".format(n=hold_corner.name), list="{n}.hold_set".format(n=hold_corner.name) )) - # Next, create Innovus rc corners from qrc tech or cap table files + # Next, create Innovus rc corners from qrc tech or cap table files append_mmmc("create_rc_corner -name {name} -temperature {tempInCelsius} {qrc} {cap_table}".format( name="{n}.setup_rc".format(n=setup_corner.name), tempInCelsius=str(setup_corner.temp.value), From 5ac4327f41742993c58d62d38d51b17165a7e749 Mon Sep 17 00:00:00 2001 From: Erik Anderson Date: Wed, 11 Mar 2020 10:28:47 -0700 Subject: [PATCH 3/3] Added cap table test and added property in Library stub class for type checking cap table --- src/hammer-tech/library_filter.py | 2 ++ src/hammer-vlsi/tech_test.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/hammer-tech/library_filter.py b/src/hammer-tech/library_filter.py index 9f010cdc5..f3b879557 100644 --- a/src/hammer-tech/library_filter.py +++ b/src/hammer-tech/library_filter.py @@ -28,6 +28,8 @@ def spice_file(self) -> Optional[str]: pass def verilog_synth(self) -> Optional[str]: pass @property def verilog_sim(self) -> Optional[str]: pass + @property + def cap_table_file(self) -> Optional[str]: pass PathsFunctionType = Callable[["Library"], List[str]] diff --git a/src/hammer-vlsi/tech_test.py b/src/hammer-vlsi/tech_test.py index efb30aa23..889e28bda 100644 --- a/src/hammer-vlsi/tech_test.py +++ b/src/hammer-vlsi/tech_test.py @@ -140,6 +140,37 @@ def add_duplicates(in_dict: Dict[str, Any]) -> Dict[str, Any]: # Cleanup shutil.rmtree(tech_dir_base) + def test_cap_table_file_library_filter(self) -> None: + """ + Test that process_library_filter removes duplicates. + """ + import hammer_config + + tech_dir, tech_dir_base = HammerToolTestHelpers.create_tech_dir("dummy28") + tech_json_filename = os.path.join(tech_dir, "dummy28.tech.json") + + def add_cap_table(in_dict: Dict[str, Any]) -> Dict[str, Any]: + out_dict = deepdict(in_dict) + out_dict["libraries"].append({ + "cap table file": "test/cap_table_file" + }) + return out_dict + + HammerToolTestHelpers.write_tech_json(tech_json_filename, add_cap_table) + tech = self.get_tech(hammer_tech.HammerTechnology.load_from_dir("dummy28", tech_dir)) + tech.cache_dir = tech_dir + + database = hammer_config.HammerDatabase() + tech.set_database(database) + outputs = tech.process_library_filter(pre_filts=[], filt=hammer_tech.filters.cap_table_filter, + must_exist=False, + output_func=lambda str, _: [str]) + + self.assertEqual(outputs, ["{0}/cap_table_file".format(tech_dir)]) + + # Cleanup + shutil.rmtree(tech_dir_base) + @staticmethod def add_tarballs(in_dict: Dict[str, Any]) -> Dict[str, Any]: """