Skip to content

Commit 2c4df6e

Browse files
committed
[ot] scripts/opentitan: pyot.py: add a new execution option to early exit
`validate` early-terminate QEMU execution when a string/pattern is matched. Signed-off-by: Emmanuel Blot <eblot@rivosinc.com>
1 parent 3ee01f5 commit 2c4df6e

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

scripts/opentitan/pyot.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python3
22

3-
# Copyright (c) 2023-2024 Rivos, Inc.
3+
# Copyright (c) 2023-2025 Rivos, Inc.
44
# SPDX-License-Identifier: Apache2
55

66
"""OpenTitan QEMU unit test sequencer.
@@ -229,6 +229,9 @@ def run(self, tdef: EasyDict[str, Any]) -> tuple[int, ExecTime, str]:
229229
- trigger, a string to match on the QEMU virtual comm port
230230
output to trigger the context execution. It may be
231231
defined as a regular expression.
232+
- validate, a string to match on the QEMU virtual comm port
233+
output to early exit. It may be defined as a regular
234+
expression.
232235
- start_delay, the delay to wait before starting the execution
233236
of the context once QEMU command has been started.
234237
:return: a 3-uple of exit code, execution time, and last guest error
@@ -237,23 +240,25 @@ def run(self, tdef: EasyDict[str, Any]) -> tuple[int, ExecTime, str]:
237240
# OT's UART0 is redirected to a TCP stream that can be accessed through
238241
# self._device. The VM pauses till the TCP socket is connected
239242
xre = re.compile(self.EXIT_ON)
243+
sync_event = None
240244
if tdef.trigger:
241245
sync_event = Event()
242-
if tdef.trigger.startswith("r'") and tdef.trigger.endswith("'"):
246+
match_pattern = tdef.trigger or tdef.validate
247+
if match_pattern:
248+
if match_pattern.startswith("r'") and match_pattern.endswith("'"):
243249
try:
244-
tmo = re.compile(tdef.trigger[2:-1].encode())
250+
tmo = re.compile(match_pattern[2:-1].encode())
245251
except re.error as exc:
246-
raise ValueError('Invalid trigger regex: {exc}') from exc
252+
raise ValueError('Invalid regex: {exc}') from exc
247253

248254
def trig_match(bline):
249255
return tmo.match(bline)
250256
else:
251-
btrigger = tdef.trigger.encode()
257+
btrigger = match_pattern.encode()
252258

253259
def trig_match(bline):
254260
return bline.find(btrigger) >= 0
255261
else:
256-
sync_event = None
257262
trig_match = None
258263
ret = None
259264
proc = None
@@ -401,10 +406,15 @@ def trig_match(bline):
401406
if trig_match and trig_match(line):
402407
# reset timeout from this event
403408
abstimeout = float(tdef.timeout) + now()
404-
log.info('Trigger pattern detected, resuming for '
405-
'%.0f secs', tdef.timeout)
406-
sync_event.set()
407409
trig_match = None
410+
if sync_event:
411+
log.info('Trigger pattern detected, resuming '
412+
'for %.0f secs', tdef.timeout)
413+
sync_event.set()
414+
else:
415+
log.info('Validation pattern detected, exiting')
416+
ret = 0
417+
break
408418
xmo = xre.search(line)
409419
if xmo:
410420
xend = now()
@@ -1573,14 +1583,18 @@ def _build_qemu_command(self, args: Namespace,
15731583
from exc
15741584
start_delay *= args.timeout_factor
15751585
trigger = getattr(args, 'trigger', '')
1586+
validate = getattr(args, 'validate', '')
1587+
if trigger and validate:
1588+
raise ValueError(f"{getattr(args, 'exec', '?')}: 'trigger' and "
1589+
f"'validate' are mutually exclusive")
15761590
vcp_args, vcp_map = self._build_qemu_vcp_args(args)
15771591
qemu_args.extend(vcp_args)
15781592
qemu_args.extend(args.global_opts or [])
15791593
if opts:
15801594
qemu_args.extend((str(o) for o in opts))
15811595
return EasyDict(command=qemu_args, vcp_map=vcp_map,
15821596
tmpfiles=temp_files, start_delay=start_delay,
1583-
trigger=trigger)
1597+
trigger=trigger, validate=validate)
15841598

15851599
def _build_qemu_test_command(self, filename: str) -> EasyDict[str, Any]:
15861600
test_name = self.get_test_radix(filename)

0 commit comments

Comments
 (0)