Skip to content

Commit

Permalink
simulate.py: Extend support for custom simulation commands
Browse files Browse the repository at this point in the history
  • Loading branch information
colluca committed Sep 11, 2023
1 parent 9db1c54 commit 8a4608b
Showing 1 changed file with 59 additions and 42 deletions.
101 changes: 59 additions & 42 deletions util/sim/simulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
BANSHEE_CFG = 'src/banshee.yaml'

# Tool settings
SIMULATORS = ['vsim', 'banshee', 'verilator', 'vcs']
SIMULATORS = ['vsim', 'banshee', 'verilator', 'vcs', 'other']
DEFAULT_SIMULATOR = SIMULATORS[0]
SIMULATOR_BINS = {
'vsim': 'bin/snitch_cluster.vsim',
Expand Down Expand Up @@ -81,6 +81,51 @@ def check_exit_code(test, exit_code):
return exit_code


def run_simulation(cmd, simulator, test):
# Defaults
result = 1

# Spawn simulation subprocess
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, universal_newlines=True)

# Poll simulation subprocess and log its output
while p.poll() is None:
line = p.stdout.readline()
print(line, end='', flush=True)

# When simulating with vsim or vcs, we need to parse the simulation
# log to catch the application's return code
if simulator in ['vsim', 'vcs']:
# Capture success
regex_success = r'\[SUCCESS\] Program finished successfully'
match_success = re.search(regex_success, line)
if match_success:
result = 0
else:
regex_fail = r'\[FAILURE\] Finished with exit code\s+(\d+)'
match = re.search(regex_fail, line)
if match:
exit_code = match.group(1)
result = check_exit_code(test, exit_code)

# Check if the subprocess terminated correctly
exit_code = p.poll()
# In Banshee and Verilator the exit code of the Snitch binary is returned
# through the exit code of the simulation command
if simulator in ['banshee', 'verilator']:
result = check_exit_code(test, exit_code)
# For custom commands the return code is that of the command
elif simulator == 'other':
result = exit_code
# For standard simulation commands the simulated Snitch binary exit
# code is overriden only if the simulator failed
else:
if exit_code != 0:
result = exit_code

return result


def run_test(test, args):
# Extract args
simulator = args.simulator
Expand All @@ -94,59 +139,31 @@ def run_test(test, args):
return 0

# Construct path to executable
elf = Path(testlist).absolute().parent / Path(test['elf'])
elf = Path(test['elf'])
if testlist:
elf = Path(testlist).absolute().parent / elf
cprint(f'Run test {colored(elf, "cyan")}', attrs=["bold"])

# Construct simulation command (override only supported for RTL)
if 'cmd' in test and simulator != 'banshee':
cmd = test['cmd']
cmd = cmd.format(sim_bin=sim_bin, elf=elf, simulator=simulator)
simulator = 'other'
else:
cmd = SIMULATOR_CMDS[simulator]
cmd = cmd.format(sim_bin=sim_bin, elf=elf)
cmd = cmd.format(sim_bin=sim_bin, elf=elf)
print(f'$ {cmd}', flush=True)

# Run test
# Run simulation
result = 0
if not dry_run:
result = 1

# When simulating with vsim or vcs, we need to parse the simulation
# log to catch the application's return code
if simulator in ['vsim', 'vcs']:
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
text=True)

while p.poll() is None:
line = p.stdout.readline()
print(line, end='', flush=True)

# Capture success
regex_success = r'\[SUCCESS\] Program finished successfully'
match_success = re.search(regex_success, line)
if match_success:
result = 0
else:
regex_fail = r'\[FAILURE\] Finished with exit code\s+(\d+)'
match = re.search(regex_fail, line)
if match:
exit_code = match.group(1)
result = check_exit_code(test, exit_code)

# Check if the subprocess terminated correctly
if p.poll() != 0:
result = p.poll()
result = run_simulation(cmd, simulator, test)

else:
p = subprocess.Popen(cmd, shell=True)
p.wait()
exit_code = p.returncode
result = check_exit_code(test, exit_code)

# Report failure or success
if result != 0:
cprint(f'{elf} test failed', 'red', attrs=['bold'], flush=True)
else:
cprint(f'{elf} test passed', 'green', attrs=['bold'], flush=True)
# Report failure or success
if result != 0:
cprint(f'{elf} test failed', 'red', attrs=['bold'], flush=True)
else:
cprint(f'{elf} test passed', 'green', attrs=['bold'], flush=True)

return result

Expand Down

0 comments on commit 8a4608b

Please sign in to comment.