Skip to content

Commit

Permalink
[ot] scripts/opentitan: cfggen.py: use more flexible option switches
Browse files Browse the repository at this point in the history
it is noe possible to either:
- specify the path to the top configuration file, or
- specify the path to the OT directory and the top name

Signed-off-by: Emmanuel Blot <[email protected]>
  • Loading branch information
rivos-eblot committed Jan 24, 2025
1 parent 926faf1 commit 75629d4
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 21 deletions.
4 changes: 2 additions & 2 deletions docs/opentitan/cfggen.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ parse, each of which can be overidden with options `-c`, `-l` and `-t`.
* `-s` specify a SoC identifier for OT platforms with mulitple SoCs

* `-T` specify the OpenTitan _top_ name, such as `Darjeeling`, `EarlGrey`, ... This option is
mandatory.
mandatory if `-t` is not specified. Requires a TOPDIR path

* `-t` alternative path to the `top_<top>.gen.hjson` file
* `-t` path to the `top_<top>.gen.hjson` file. This option is mandatory is `-T` is not specified.

* `-v` can be repeated to increase verbosity of the script, mostly for debug purpose.

Expand Down
81 changes: 62 additions & 19 deletions scripts/opentitan/cfggen.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from argparse import ArgumentParser
from configparser import ConfigParser
from logging import getLogger
from os.path import dirname, isdir, isfile, join as joinpath, normpath
from os.path import abspath, dirname, isdir, isfile, join as joinpath, normpath
from traceback import format_exc
from typing import Optional
import re
Expand Down Expand Up @@ -53,12 +53,18 @@ def __init__(self):
self._roms: dict[Optional[int], dict[str, str]] = {}
self._otp: dict[str, str] = {}
self._lc: dict[str, str] = {}
self._top_name: Optional[str] = None

@property
def top_name(self) -> Optional[str]:
return self._top_name

def load_top_config(self, toppath: str) -> None:
"""Load data from HJSON top configuration file."""
assert not _HJSON_ERROR
with open(toppath, 'rt') as tfp:
cfg = hjload(tfp)
self._top_name = cfg.get('name')
for module in cfg.get('module') or []:
modtype = module.get('type')
if modtype == 'rom_ctrl':
Expand Down Expand Up @@ -232,9 +238,9 @@ def main():
desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip()
argparser = ArgumentParser(description=f'{desc}.')
files = argparser.add_argument_group(title='Files')
files.add_argument('opentitan', nargs=1, metavar='TOPDIR',
files.add_argument('opentitan', nargs='*', metavar='OTDIR',
help='OpenTitan top directory')
files.add_argument('-T', '--top', choices=top_map.keys(), required=True,
files.add_argument('-T', '--top', choices=top_map.keys(),
help='OpenTitan top name')
files.add_argument('-o', '--out', metavar='CFG',
help='Filename of the config file to generate')
Expand All @@ -258,25 +264,63 @@ def main():
args = argparser.parse_args()
debug = args.debug

configure_loggers(args.verbose, 'cfggen', 'otp')
log = configure_loggers(args.verbose, 'cfggen', 'otp')[0]

if _HJSON_ERROR:
argparser.error('Missing HJSON module: {_HJSON_ERROR}')

topdir = args.opentitan[0]
if not isdir(topdir):
argparser.error('Invalid OpenTitan top directory')
ot_dir = normpath(topdir)
ltop = args.top.lower()
top = f'top_{ltop}'
var = top_map[args.top]
if not args.topcfg:
cfgpath = joinpath(ot_dir, f'hw/{top}/data/autogen/{top}.gen.hjson')
else:
cfgpath = args.topcfg
if not isfile(cfgpath):
argparser.error(f"No such file '{cfgpath}'")
cfg = OtConfiguration()

topcfg = args.topcfg
if not topcfg:
if not args.opentitan:
argparser.error('TOPDIR is required is no top file is '
'specified')
ot_dir = args.opentitan[0]
if not isdir(ot_dir):
argparser.error('Invalid OpenTitan top directory')
ot_dir = abspath(ot_dir)
if not args.top:
argparser.error('Top name is required if no top file is '
'specified')
ltop = args.top.lower()
top = f'top_{ltop}'
topvar = top_map[args.top]
topcfg = joinpath(ot_dir, f'hw/{top}/data/autogen/{top}.gen.hjson')
if not isfile(topcfg):
argparser.error(f"No such file '{topcfg}'")
log.info("Top config: '%s'", topcfg)
cfg.load_top_config(topcfg)
else:
if not isfile(topcfg):
argparser.error(f'No such top file: {topcfg}')
cfg.load_top_config(topcfg)
ltop = cfg.top_name
if not ltop:
argparser.error('Unknown top name')
log.info("Top: '%s'", cfg.top_name)
ltop = ltop.lower()
topvar = {k.lower(): v for k, v in top_map.items()}.get(ltop)
if not topvar:
argparser.error(f'Unsupported top name: {cfg.top_name}')
top = f'top_{ltop}'
ot_dir = args.opentitan[0] if args.opentitan else None
if not ot_dir:
check_dir = f'hw/{top}/data'
cur_dir = dirname(topcfg)
while cur_dir:
check_path = joinpath(cur_dir, check_dir)
if isdir(check_path):
ot_dir = cur_dir
break
cur_dir = dirname(cur_dir)
if not ot_dir:
argparser.error('Cannot find OT directory')
elif not isdir(ot_dir):
argparser.error('Invalid OpenTitan top directory')
ot_dir = abspath(ot_dir)
log.info("OT directory: '%s'", ot_dir)
log.info("Variant: '%s'", topvar)
if not args.lifecycle:
lcpath = joinpath(ot_dir, 'hw/ip/lc_ctrl/rtl/lc_ctrl_state_pkg.sv')
else:
Expand All @@ -293,10 +337,9 @@ def main():
argparser.error(f"No such file '{ocpath}'")

cfg = OtConfiguration()
cfg.load_top_config(cfgpath)
cfg.load_lifecycle(lcpath)
cfg.load_otp_constants(ocpath)
cfg.save(var, args.socid, args.count, args.out)
cfg.save(topvar, args.socid, args.count, args.out)

except (IOError, ValueError, ImportError) as exc:
print(f'\nError: {exc}', file=sys.stderr)
Expand Down

0 comments on commit 75629d4

Please sign in to comment.