Skip to content

Commit 24b234c

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

File tree

3 files changed

+59
-14
lines changed

3 files changed

+59
-14
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 & 10 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,12 @@ 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-
-> None:
164+
def save(self, kind: str, topname: Optional[str], hjname: str,
165+
scriptname: str, cfp: TextIO) -> None:
165166
"""Generate a source file with register definition for the partitions.
166167
167168
:param kind: kind of generation output
169+
:param topname: the name of the OpenTitan top
168170
:param hjname: the name of the input HJSON configuration file
169171
:param scriptname: the name of the script that generates this output
170172
:param cfp: the output text stream
@@ -199,11 +201,11 @@ def save(self, kind: str, hjname: str, scriptname: str, cfp: TextIO) \
199201
slots.append(OtpSlotDescriptor(f'{part.name}_ZER', offset,
200202
OtpPartition.ZER_SIZE, True))
201203

202-
save(hjname, scriptname, cfp, slots)
204+
save(topname, hjname, scriptname, cfp, slots)
203205

204-
def _save_qemu(self, hjname: str, scriptname: str, cfp: TextIO,
205-
slots: list[OtpSlotDescriptor]) -> None:
206-
print(f'/* Generated from {hjname} with {scriptname} */')
206+
def _save_qemu(self, topname: Optional[str], hjname: str, scriptname: str,
207+
cfp: TextIO, slots: list[OtpSlotDescriptor]) -> None:
208+
print(f'/* Generated from {hjname} with {scriptname} */', file=cfp)
207209
print(file=cfp)
208210
for slot in slots:
209211
if slot.part:
@@ -293,12 +295,17 @@ def _save_qemu(self, hjname: str, scriptname: str, cfp: TextIO,
293295
#undef CASE_DIGEST
294296
}
295297
'''
298+
if topname:
299+
tname = OpenTitanTop.short_name(topname)
300+
if tname:
301+
code = code.replace('ot_otp_swcfg_reg_name',
302+
f'ot_otp_{tname}_swcfg_reg_name')
296303
code = redent(code)
297304
code = code.replace('_CASES_', '\n '.join(cases))
298305
print(redent(code), '', file=cfp)
299306

300-
def _save_bmtest(self, hjname: str, scriptname: str, cfp: TextIO,
301-
slots: list[OtpSlotDescriptor]) -> None:
307+
def _save_bmtest(self, topname: Optional[str], hjname: str, scriptname: str,
308+
cfp: TextIO, slots: list[OtpSlotDescriptor]) -> None:
302309
# pylint: disable=unused-argument
303310
print(f'// Generated from {hjname} with {scriptname}', file=cfp)
304311
print(file=cfp)

scripts/opentitan/otptool.py

Lines changed: 37 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,31 @@ 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+
top_prefix = 'top_'
74+
if tail.startswith(top_prefix):
75+
candidate = tail.removeprefix(top_prefix)
76+
if candidate in top_names:
77+
return candidate
78+
return None
79+
80+
5381
def main():
5482
"""Main routine"""
5583
debug = True
@@ -143,6 +171,9 @@ def main():
143171
default=outkinds[0],
144172
help=f'select output format for code generation'
145173
f' (default: {outkinds[0]})')
174+
commands.add_argument('--top-name',
175+
help='optional top name for code generation '
176+
'(default: auto)')
146177
extra = argparser.add_argument_group(title='Extras')
147178
extra.add_argument('-v', '--verbose', action='count',
148179
help='increase verbosity')
@@ -226,8 +257,11 @@ def main():
226257
partdesc.save(args.out_kind, basename(args.otp_map.name),
227258
basename(sys.argv[0]), output)
228259
elif args.generate == 'REGS':
260+
topname = args.top_name
261+
if not topname:
262+
topname = get_top_name(args.otp_map)
229263
regdef = OtpRegisterDef(otpmap)
230-
regdef.save(args.out_kind, basename(args.otp_map.name),
264+
regdef.save(args.out_kind, topname, basename(args.otp_map.name),
231265
basename(sys.argv[0]), output)
232266
elif args.generate == 'LCVAL':
233267
lcext.save(args.out_kind, output, True)

0 commit comments

Comments
 (0)