scripts/liberty: Accept target output file as argument

Instead of giving the library and corner to gnerate, you can provide
the target .lib file you want generated and this will pick the right
parameters to generate that file

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
Sylvain Munaut 2020-07-23 09:39:05 +02:00
parent ba5e4eb2d0
commit 9a4821ec6c
1 changed files with 51 additions and 7 deletions

View File

@ -194,6 +194,36 @@ def top_corner_file(libname, corner, corner_type: TimingType, directory_prefix =
corner_type=corner_type.file)
def top_liberty_file(libname, corner, corner_type: TimingType, directory_prefix = "timing"):
"""
>>> top_liberty_file("sky130_fd_sc_hd", "ff_100C_1v65", TimingType.ccsnoise)
'timing/sky130_fd_sc_hd__ff_100C_1v65_ccsnoise.lib'
>>> top_liberty_file("sky130_fd_sc_hd", "ff_100C_1v65", TimingType.basic)
'timing/sky130_fd_sc_hd__ff_100C_1v65.lib'
>>> top_liberty_file("sky130_fd_sc_hd", "ff_100C_1v65", TimingType.basic, "")
'sky130_fd_sc_hd__ff_100C_1v65.lib'
"""
return top_corner_file(libname, corner, corner_type, directory_prefix).replace('.lib.json', '.lib')
def top_liberty_file_split(fname):
"""
Splits a fully specified top liberty file name into library / corner / corner_type
>>> top_liberty_file_split('timing/sky130_fd_sc_hd__ff_100C_1v65_ccsnoise.lib')
('sky130_fd_sc_hd', 'ff_100C_1v65', <TimingType.ccsnoise: 3>)
>>> top_liberty_file_split('timing/sky130_fd_sc_hd__ff_100C_1v65.lib')
('sky130_fd_sc_hd', 'ff_100C_1v65', <TimingType.basic: 1>)
"""
m = re.match('(.*)__(.*)\.lib', os.path.basename(fname))
if m is None:
return None
return ( m.group(1), *TimingType.parse(m.group(2)) )
def collect(library_dir) -> Tuple[Dict[str, TimingType], List[str]]:
"""Collect the available timing information in corners.
@ -337,7 +367,7 @@ remove_ccsnoise_from_library = remove_ccsnoise_from_dict
def generate(library_dir, lib, corner, ocorner_type, icorner_type, cells, output_directory):
output_directory_prefix = None if output_directory else "timing"
top_fname = top_corner_file(lib, corner, ocorner_type, output_directory_prefix).replace('.lib.json', '.lib')
top_fname = top_liberty_file(lib, corner, ocorner_type, output_directory_prefix)
output_directory = output_directory if output_directory else library_dir
top_fpath = os.path.join(output_directory, top_fname)
@ -1133,14 +1163,28 @@ def main():
retcode = 0
lib, corners, all_cells = collect(libdir)
if libdir.is_dir():
# libdir is a directory, collect available corners and process specified ones
if args.ccsnoise:
output_corner_type = TimingType.ccsnoise
elif args.leakage:
output_corner_type = TimingType.leakage
else:
output_corner_type = TimingType.basic
elif libdir.suffix == '.lib':
# libdir is directly the liberty target file to generate, derive params from it
s = top_liberty_file_split(libdir.name)
libdir = libdir.parents[1]
args.corner = [ s[1] ]
output_corner_type = s[2]
if args.ccsnoise:
output_corner_type = TimingType.ccsnoise
elif args.leakage:
output_corner_type = TimingType.leakage
else:
output_corner_type = TimingType.basic
msg_err("Invalid library path (neither source directory or liberty library target")
return 1
lib, corners, all_cells = collect(libdir)
if args.corner == ['all']:
args.corner = list(sorted(k for k, (v0, v1) in corners.items() if output_corner_type in v0))