blob: f7339dc91e6a9f131c8fad7f08e50c4a6b024aac [file] [log] [blame]
#!/usr/bin/env python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
'''Run a test on the OTBN simulator.'''
import argparse
import subprocess
import sys
from shared.check import CheckResult
from shared.reg_dump import parse_reg_dump
# Names of special registers
ERR_BITS = 'ERR_BITS'
INSN_CNT = 'INSN_CNT'
STOP_PC = 'STOP_PC'
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument('simulator',
help='Path to the standalone OTBN simulator.')
parser.add_argument('expected',
metavar='FILE',
type=argparse.FileType('r'),
help=(f'File containing expected register values. '
f'Registers that are not listed are allowed to '
f'have any value, except for {ERR_BITS}. If '
f'{ERR_BITS} is not listed, the test will assume '
f'there are no errors expected (i.e. {ERR_BITS}'
f'= 0).'))
parser.add_argument('elf',
help='Path to the .elf file for the OTBN program.')
parser.add_argument('-v', '--verbose', action='store_true')
args = parser.parse_args()
# Parse expected values.
result = CheckResult()
expected_regs = parse_reg_dump(args.expected.read())
# Run the simulation and produce a register dump.
cmd = [args.simulator, '--dump-regs', '-', args.elf]
sim_proc = subprocess.run(cmd, check=True,
stdout=subprocess.PIPE, universal_newlines=True)
actual_regs = parse_reg_dump(sim_proc.stdout)
# Special handling for the ERR_BITS register.
expected_err = expected_regs.get(ERR_BITS, 0)
actual_err = actual_regs[ERR_BITS]
insn_cnt = actual_regs[INSN_CNT]
stop_pc = actual_regs[STOP_PC]
if expected_err == 0 and actual_err != 0:
# Test is expected to have no errors, but an error occurred. In this
# case, give a special error message and exit rather than print all the
# mismatched registers.
if actual_err != 0:
result.err(f'OTBN encountered an unexpected error.\n'
f' {ERR_BITS}\t= {actual_err:#010x}\n'
f' {INSN_CNT}\t= {insn_cnt:#010x}\n'
f' {STOP_PC}\t= {stop_pc:#010x}')
else:
for reg, expected_value in expected_regs.items():
actual_value = actual_regs.get(reg, None)
if actual_value != expected_value:
if reg.startswith('w'):
expected_str = f'{expected_value:#066x}'
actual_str = f'{actual_value:#066x}'
else:
expected_str = f'{expected_value:#010x}'
actual_str = f'{actual_value:#010x}'
result.err(f'Mismatch for register {reg}:\n'
f' Expected: {expected_str}\n'
f' Actual: {actual_str}')
if result.has_errors() or result.has_warnings() or args.verbose:
print(result.report())
return 1 if result.has_errors() else 0
if __name__ == "__main__":
sys.exit(main())