Skip to content

Commit a802feb

Browse files
committed
[ot] scripts/opentitan: otptool.py: add optional top name for code generation
Signed-off-by: Emmanuel Blot <[email protected]>
1 parent 2d2eff5 commit a802feb

File tree

3 files changed

+58
-13
lines changed

3 files changed

+58
-13
lines changed

docs/opentitan/otptool.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ usage: otptool.py [-h] [-j HJSON] [-m VMEM] [-l SV] [-o FILE] [-r RAW]
1414
[--erase PART:FIELD] [--clear-bit CLEAR_BIT]
1515
[--set-bit SET_BIT] [--toggle-bit TOGGLE_BIT]
1616
[--write ADDR/HEXBYTES] [--patch-token NAME=VALUE]
17-
[--out-kind {qemu,bmtest}] [-v] [-d]
17+
[--out-kind {qemu,bmtest}] [--top-name TOP_NAME] [-v] [-d]
1818
1919
QEMU OT tool to manage OTP files.
2020
@@ -69,6 +69,7 @@ Commands:
6969
--out-kind {qemu,bmtest}
7070
select output format for code generation (default:
7171
qemu)
72+
--top-name TOP_NAME optional top name for code generation (default: auto)
7273
7374
Extras:
7475
-v, --verbose increase verbosity
@@ -230,6 +231,9 @@ Fuse RAW images only use the v1 type.
230231
is only intended to corrupt the OTP content so that HW & SW behavior may be exercised should such
231232
a condition exists. See [Bit position syntax](#bit-syntax) for how to specify a bit.
232233

234+
* `--top-name` defines the OpenTitan top name for some code generation feature. It overrides any
235+
top name that may be automatically retrieved from the configuration file hierarchy.
236+
233237
* `--write` overrides any data (not ECC). If can be combined with `--fix-ecc` to automatically
234238
rebuild the ECC of the data slot that have been altered. This option may be repeated. The argument
235239
should comply with the `offset/hexdata` syntax, where the _offset_ part is defined in the

python/qemu/ot/otp/descriptor.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
"""
88

99
from logging import getLogger
10-
from typing import NamedTuple, TYPE_CHECKING, TextIO
10+
from typing import NamedTuple, Optional, TYPE_CHECKING, TextIO
1111

12-
from ..util.misc import redent
12+
from ot.top import OpenTitanTop
13+
from ot.util.misc import redent
1314
from .partition import OtpPartition
1415

1516
if TYPE_CHECKING:
@@ -160,11 +161,13 @@ def __init__(self, otpmap: 'OtpMap'):
160161
self._log = getLogger('otp.reg')
161162
self._otpmap = otpmap
162163

163-
def save(self, kind: str, hjname: str, scriptname: str, cfp: TextIO) \
164+
def save(self, kind: str, topname: Optional[str], hjname: str,
165+
scriptname: str,cfp: TextIO) \
164166
-> None:
165167
"""Generate a source file with register definition for the partitions.
166168
167169
:param kind: kind of generation output
170+
:param topname: the name of the OpenTitan top
168171
:param hjname: the name of the input HJSON configuration file
169172
:param scriptname: the name of the script that generates this output
170173
:param cfp: the output text stream
@@ -199,11 +202,11 @@ def save(self, kind: str, hjname: str, scriptname: str, cfp: TextIO) \
199202
slots.append(OtpSlotDescriptor(f'{part.name}_ZER', offset,
200203
OtpPartition.ZER_SIZE, True))
201204

202-
save(hjname, scriptname, cfp, slots)
205+
save(topname, hjname, scriptname, cfp, slots)
203206

204-
def _save_qemu(self, hjname: str, scriptname: str, cfp: TextIO,
205-
slots: list[OtpSlotDescriptor]) -> None:
206-
print(f'/* Generated from {hjname} with {scriptname} */')
207+
def _save_qemu(self, topname: Optional[str], hjname: str, scriptname: str,
208+
cfp: TextIO, slots: list[OtpSlotDescriptor]) -> None:
209+
print(f'/* Generated from {hjname} with {scriptname} */', file=cfp)
207210
print(file=cfp)
208211
for slot in slots:
209212
if slot.part:
@@ -293,13 +296,18 @@ def _save_qemu(self, hjname: str, scriptname: str, cfp: TextIO,
293296
#undef CASE_DIGEST
294297
}
295298
'''
299+
if topname:
300+
tname = OpenTitanTop.short_name(topname)
301+
if tname:
302+
code = code.replace('ot_otp_swcfg_reg_name',
303+
f'ot_otp_{tname}_swcfg_reg_name')
296304
code = redent(code)
297305
code = code.replace('_CASES_', '\n '.join(cases))
298306
print(redent(code), '', file=cfp)
299307

300308

301-
def _save_bmtest(self, hjname: str, scriptname: str, cfp: TextIO,
302-
slots: list[OtpSlotDescriptor]) -> None:
309+
def _save_bmtest(self, topname: Optional[str], hjname: str, scriptname: str,
310+
cfp: TextIO, slots: list[OtpSlotDescriptor]) -> None:
303311
# pylint: disable=unused-argument
304312
print(f'// Generated from {hjname} with {scriptname}', file=cfp)
305313
print(file=cfp)

scripts/opentitan/otptool.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010

1111
from argparse import ArgumentParser, FileType
1212
from binascii import unhexlify
13-
from os.path import basename, dirname, join as joinpath, normpath
13+
from io import IOBase
14+
from os.path import (basename, dirname, isfile, join as joinpath, normpath,
15+
split as splitpath)
1416
from re import match as re_match
1517
from traceback import format_exception
16-
from typing import Optional
18+
from typing import Optional, Union
1719
import sys
1820

1921
QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))),
@@ -28,6 +30,7 @@
2830
_EXC = exc
2931
from ot.otp import (OtpImage, OtpLifecycleExtension, OtpMap, OtpPartition,
3032
OtpPartitionDesc, OtpRegisterDef)
33+
from ot.top import OpenTitanTop
3134
from ot.util.log import configure_loggers
3235
from ot.util.misc import HexInt, to_bool
3336

@@ -50,6 +53,30 @@ def parse_lc_token(tkdesc: str) -> tuple[str, 'LifeCycleTokenPair']:
5053
return token_name, tkeng.build_from_text(tktext)
5154

5255

56+
def get_top_name(*filepaths: list[Union[str, IOBase]]) -> Optional[str]:
57+
"""Try to retrieve the top name from a list of configuration files.
58+
59+
:param filepaths: list of file path or file objects
60+
:return: the name of the identified top, if found
61+
"""
62+
for filepath in filepaths:
63+
if not isinstance(filepath, str):
64+
filepath = getattr(filepath, 'name', None)
65+
if not filepath:
66+
continue
67+
if not isfile(filepath):
68+
continue
69+
fdir = dirname(filepath)
70+
top_names = set(OpenTitanTop.names)
71+
while fdir:
72+
fdir, tail = splitpath(fdir)
73+
if tail.startswith('top_'):
74+
candidate = tail[4:]
75+
if candidate in top_names:
76+
return candidate
77+
return None
78+
79+
5380
def main():
5481
"""Main routine"""
5582
debug = True
@@ -143,6 +170,9 @@ def main():
143170
default=outkinds[0],
144171
help=f'select output format for code generation'
145172
f' (default: {outkinds[0]})')
173+
commands.add_argument('--top-name',
174+
help='optional top name for code generation '
175+
'(default: auto)')
146176
extra = argparser.add_argument_group(title='Extras')
147177
extra.add_argument('-v', '--verbose', action='count',
148178
help='increase verbosity')
@@ -226,8 +256,11 @@ def main():
226256
partdesc.save(args.out_kind, basename(args.otp_map.name),
227257
basename(sys.argv[0]), output)
228258
elif args.generate == 'REGS':
259+
topname = args.top_name
260+
if not topname:
261+
topname = get_top_name(args.otp_map)
229262
regdef = OtpRegisterDef(otpmap)
230-
regdef.save(args.out_kind, basename(args.otp_map.name),
263+
regdef.save(args.out_kind, topname, basename(args.otp_map.name),
231264
basename(sys.argv[0]), output)
232265
elif args.generate == 'LCVAL':
233266
lcext.save(args.out_kind, output, True)

0 commit comments

Comments
 (0)