Skip to content

Commit cbc1414

Browse files
kenhoberkeleyken_ho
and
ken_ho
authored
New Method For Getting Timing Libs (#706)
Co-authored-by: ken_ho <[email protected]>
1 parent cc0927d commit cbc1414

File tree

4 files changed

+184
-0
lines changed

4 files changed

+184
-0
lines changed

Diff for: hammer/config/defaults.yml

+6
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ vlsi.technology:
9292
# the extracted contents of foobar.tar.gz.
9393
# If this is not specified, then the tarballs will be extracted to obj/<tech_dir>/extracted/.
9494

95+
timing_lib_pref: "NLDM"
96+
# Select a timing lib preference, available options include:
97+
# NLDM, ECSM, and CCS (lower or upper case acceptable).
98+
# If no preference is specified, then the following preference order is followed:
99+
# NLDM -> ECSM -> CCS
100+
95101
# General VLSI inputs.
96102
# These will vary per run of hammer-vlsi.
97103
vlsi.inputs:

Diff for: hammer/config/defaults_types.yml

+3
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ vlsi.technology:
6363
# Path where tarballs have been extracted.
6464
extracted_tarballs_dir: Optional[str]
6565

66+
# A preference for the timing lib.
67+
timing_lib_pref: str
68+
6669
# General VLSI inputs.
6770
# These will vary per run of hammer-vlsi.
6871
vlsi.inputs:

Diff for: hammer/tech/__init__.py

+39
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,45 @@ def paths_func(lib: Library) -> List[str]:
12581258
is_file=True
12591259
)
12601260

1261+
def get_timing_lib_with_preference(self, lib_pref: str = "NLDM") -> LibraryFilter:
1262+
"""
1263+
Select ASCII .lib timing libraries. Prefers NLDM, then ECSM, then CCS if multiple are present for
1264+
a single given .lib.
1265+
"""
1266+
lib_pref = lib_pref.upper()
1267+
1268+
def paths_func(lib: Library) -> List[str]:
1269+
pref_list = ["NLDM", "ECSM", "CCS"]
1270+
index = None
1271+
1272+
try:
1273+
index = pref_list.index(lib_pref)
1274+
except:
1275+
raise ValueError("Library preference must be one of NLDM, ECSM, or CCS.")
1276+
pref_list.insert(0, pref_list.pop(index))
1277+
1278+
for elem in pref_list:
1279+
if elem == "NLDM":
1280+
if lib.nldm_liberty_file is not None:
1281+
return [lib.nldm_liberty_file]
1282+
elif elem == "ECSM":
1283+
if lib.ecsm_liberty_file is not None:
1284+
return [lib.ecsm_liberty_file]
1285+
elif elem == "CCS":
1286+
if lib.ccs_liberty_file is not None:
1287+
return [lib.ccs_liberty_file]
1288+
else:
1289+
pass
1290+
1291+
return []
1292+
1293+
return LibraryFilter(
1294+
tag="timing_lib_with_nldm",
1295+
description="ECSM/CCS/NLDM timing lib (liberty ASCII .lib)",
1296+
paths_func=paths_func,
1297+
is_file=True
1298+
)
1299+
12611300
@property
12621301
def qrc_tech_filter(self) -> LibraryFilter:
12631302
"""

Diff for: tests/test_tool.py

+136
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from typing import List, Dict, Any
44
import sys
55
from pathlib import Path
6+
from abc import ABCMeta, abstractmethod
67

78
import pytest
89

@@ -69,6 +70,141 @@ def test_tool_format(lib, filt) -> List[str]:
6970
"drink {0}/orange".format(tech_dir)
7071
]
7172

73+
def test_timing_lib_with_preference_filter(self, tmp_path, request) -> None:
74+
"""
75+
Test that the library preference filter works as expected.
76+
"""
77+
import hammer.config as hammer_config
78+
79+
tech_dir_base = str(tmp_path)
80+
tech_name = request.function.__name__ # create unique technology folders for each test
81+
tech_dir = HammerToolTestHelpers.create_tech_dir(tech_dir_base, tech_name)
82+
tech_json_filename = os.path.join(tech_dir, f"{tech_name}.tech.json")
83+
tech_json = {
84+
"name": f"{tech_name}",
85+
"libraries": [
86+
{
87+
"ecsm_liberty_file": "eggs.ecsm",
88+
"ccs_liberty_file": "eggs.ccs",
89+
"nldm_liberty_file": "eggs.nldm"
90+
},
91+
{
92+
"ccs_liberty_file": "custard.ccs",
93+
"nldm_liberty_file": "custard.nldm"
94+
},
95+
{
96+
"nldm_liberty_file": "noodles.nldm"
97+
},
98+
{
99+
"ecsm_liberty_file": "eggplant.ecsm"
100+
},
101+
{
102+
"ccs_liberty_file": "cookies.ccs"
103+
}
104+
]
105+
106+
}
107+
with open(tech_json_filename, "w") as f:
108+
f.write(json.dumps(tech_json, cls=HammerJSONEncoder, indent=4))
109+
(Path(tech_dir) / "eggs.ecsm").write_text("eggs ecsm")
110+
(Path(tech_dir) / "eggs.ccs").write_text("eggs ccs")
111+
(Path(tech_dir) / "eggs.nldm").write_text("eggs nldm")
112+
(Path(tech_dir) / "custard.ccs").write_text("custard ccs")
113+
(Path(tech_dir) / "custard.nldm").write_text("custard nldm")
114+
(Path(tech_dir) / "noodles.nldm").write_text("noodles nldm")
115+
(Path(tech_dir) / "eggplant.ecsm").write_text("eggplant ecsm")
116+
(Path(tech_dir) / "cookies.ccs").write_text("cookies ccs")
117+
118+
sys.path.append(tech_dir_base)
119+
tech = self.get_tech(hammer_tech.HammerTechnology.load_from_module(tech_name))
120+
tech.cache_dir = tech_dir
121+
122+
logger = HammerVLSILogging.context("")
123+
logger.logging_class.clear_callbacks()
124+
tech.logger = logger
125+
126+
class Tool(hammer_vlsi.DummyHammerTool, metaclass=ABCMeta):
127+
128+
def __init__(self, removal=False):
129+
self.geek = "GeekforGeeks"
130+
131+
132+
lib_outputs = [] # type: List[str]
133+
@property
134+
def steps(self) -> List[hammer_vlsi.HammerToolStep]:
135+
return self.make_steps_from_methods([
136+
self.step_one,
137+
self.step_two,
138+
self.step_three
139+
])
140+
141+
# Test default NLDM preference.
142+
def step_one(self) -> bool:
143+
Tool.lib_outputs = tech.read_libs([hammer_tech.filters.get_timing_lib_with_preference()],
144+
hammer_tech.HammerTechnologyUtils.to_plain_item,
145+
must_exist=False)
146+
return True
147+
148+
# Test lower case key input.
149+
def step_two(self) -> bool:
150+
Tool.lib_outputs = tech.read_libs([hammer_tech.filters.get_timing_lib_with_preference("ecsm")],
151+
hammer_tech.HammerTechnologyUtils.to_plain_item,
152+
must_exist=False)
153+
return True
154+
155+
def step_three(self) -> bool:
156+
Tool.lib_outputs = tech.read_libs([hammer_tech.filters.get_timing_lib_with_preference("CCS")],
157+
hammer_tech.HammerTechnologyUtils.to_plain_item,
158+
must_exist=False)
159+
return True
160+
161+
test = Tool()
162+
test.logger = HammerVLSILogging.context("")
163+
test.run_dir = str(tmp_path / "rundir")
164+
test.technology = tech
165+
test.set_database(hammer_config.HammerDatabase())
166+
tech.set_database(hammer_config.HammerDatabase())
167+
168+
# Test the default case:
169+
test.run(hook_actions=[
170+
hammer_vlsi.HammerTool.make_removal_hook("step_two"),
171+
hammer_vlsi.HammerTool.make_removal_hook("step_three")])
172+
173+
assert set(Tool.lib_outputs) == {
174+
"{0}/eggs.nldm".format(tech_dir),
175+
"{0}/custard.nldm".format(tech_dir),
176+
"{0}/noodles.nldm".format(tech_dir),
177+
"{0}/eggplant.ecsm".format(tech_dir),
178+
"{0}/cookies.ccs".format(tech_dir)
179+
}
180+
181+
# Test the lower case input key and non-default ECSM preference.
182+
test.run(hook_actions=[
183+
hammer_vlsi.HammerTool.make_removal_hook("step_one"),
184+
hammer_vlsi.HammerTool.make_removal_hook("step_three")])
185+
186+
assert set(Tool.lib_outputs) == {
187+
"{0}/eggs.ecsm".format(tech_dir),
188+
"{0}/custard.nldm".format(tech_dir),
189+
"{0}/noodles.nldm".format(tech_dir),
190+
"{0}/eggplant.ecsm".format(tech_dir),
191+
"{0}/cookies.ccs".format(tech_dir)
192+
}
193+
194+
# Test the non-default CCS preference.
195+
test.run(hook_actions=[
196+
hammer_vlsi.HammerTool.make_removal_hook("step_one"),
197+
hammer_vlsi.HammerTool.make_removal_hook("step_two")])
198+
199+
assert set(Tool.lib_outputs) == {
200+
"{0}/eggs.ccs".format(tech_dir),
201+
"{0}/custard.ccs".format(tech_dir),
202+
"{0}/noodles.nldm".format(tech_dir),
203+
"{0}/eggplant.ecsm".format(tech_dir),
204+
"{0}/cookies.ccs".format(tech_dir)
205+
}
206+
207+
72208
def test_timing_lib_ecsm_filter(self, tmp_path, request) -> None:
73209
"""
74210
Test that the ECSM-first filter works as expected.

0 commit comments

Comments
 (0)