forked from firesim/FireMarshal
-
Notifications
You must be signed in to change notification settings - Fork 1
/
marshal
executable file
·162 lines (140 loc) · 7.1 KB
/
marshal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/bin/env python3
import sys
import argparse
import os
import logging
import wlutil
import contextlib
if 'RISCV' not in os.environ:
sys.exit("Please source firesim/sourceme-manager-f1.sh first\n")
# Delete a file but don't throw an exception if it doesn't exist
def deleteSafe(pth):
with contextlib.suppress(FileNotFoundError):
os.remove(pth)
def main():
parser = argparse.ArgumentParser(
description="Build and run (in spike or qemu) boot code and disk images for firesim")
parser.add_argument('--workdir', help='Use a custom workload directory (defaults to the same directory as the first config file)')
parser.add_argument('-v', '--verbose',
help='Print all output of subcommands to stdout as well as the logs', action='store_true')
parser.add_argument('-i', '--initramfs', action='store_true', help="Use the initramfs version of this workload")
subparsers = parser.add_subparsers(title='Commands', dest='command')
# Build command
build_parser = subparsers.add_parser(
'build', help='Build an image from the given configuration.')
build_parser.add_argument('config_files', metavar="config", nargs='+', help="Configuration file(s) to use.")
build_parser.add_argument('-B', '--binOnly', action='store_true', help="Only build the binary")
build_parser.add_argument('-I', '--imgOnly', action='store_true', help="Only build the image (may require an image if you have guest-init scripts)")
# Launch command
launch_parser = subparsers.add_parser(
'launch', help='Launch an image on a software simulator (defaults to qemu)')
launch_parser.add_argument('-s', '--spike', action='store_true',
help="Use the spike isa simulator instead of qemu")
launch_parser.add_argument('-j', '--job', nargs='?', default='all',
help="Launch the specified job. Defaults to running the base image.")
# the type= option here allows us to only accept one argument but store it
# in a list so it matches the "build" behavior
launch_parser.add_argument('config_files', metavar='config', nargs='?', type=(lambda c: [ c ]), help="Configuration file to use.")
# Test command
test_parser = subparsers.add_parser(
'test', help="Test each workload.")
test_parser.add_argument('config_files', metavar="config", nargs='+', help="Configuration file(s) to use.")
test_parser.add_argument('-s', '--spike', action='store_true',
help="Use the spike isa simulator instead of qemu")
test_parser.add_argument('-m', '--manual', metavar='testDir', help="Manual test, don't build or run, just compare testDir against the reference output.")
# Clean Command
clean_parser = subparsers.add_parser(
'clean', help="Removes build outputs of the provided config (img and bin). Does not affect logs or runOutputs.")
clean_parser.add_argument('config_files', metavar="config", nargs='+', help="Configuration file(s) to use.")
# Install Command
install_parser = subparsers.add_parser(
'install', help="Install this workload to firesim (create configs in firesim/deploy/workloads)")
install_parser.add_argument('config_files', metavar="config", nargs='+', help="Configuration file(s) to use.")
args = parser.parse_args()
# Load all the configs from the workload directory
args.config_files = [ os.path.abspath(f) for f in args.config_files ]
if args.workdir is None:
args.workdir = os.path.dirname(args.config_files[0])
cfgs = wlutil.ConfigManager([args.workdir])
if args.command == 'test':
suitePass = True
for cfgPath in args.config_files:
# Each config gets it's own logging output and results directory
wlutil.setRunName(cfgPath, args.command)
wlutil.initLogging(args.verbose)
log = logging.getLogger()
if not args.verbose:
print("To check on progress, either call marshal with '-v' or see the live output at: ")
print(os.path.join(wlutil.log_dir, wlutil.getRunName() + ".log"))
targetCfg = cfgs[cfgPath]
if args.initramfs:
targetCfg['initramfs'] = True
if 'jobs' in targetCfg:
for j in targetCfg['jobs'].values():
j['initramfs'] = True
if args.command == "build":
try:
if args.binOnly or args.imgOnly:
# It's fine if they pass -IB, it just builds both
wlutil.buildWorkload(cfgPath, cfgs, buildBin=args.binOnly, buildImg=args.imgOnly)
else:
wlutil.buildWorkload(cfgPath, cfgs)
except Exception as e:
log.exception("Error while building workload")
elif args.command == "launch":
# job-configs are named special internally
if args.job != 'all':
if 'jobs' in targetCfg:
args.job = targetCfg['name'] + '-' + args.job
else:
log.error("Job " + args.job + " requested, but no jobs specified in config file\n")
parser.print_help()
try:
wlutil.launchWorkload(cfgPath, cfgs, args.job, args.spike)
except Exception as e:
log.exception("Failed to launch workload:")
elif args.command == "test":
skipCount = 0
failCount = 0
log.info("Running: " + cfgPath)
res = wlutil.testWorkload(cfgPath, cfgs, args.verbose, spike=args.spike, cmp_only=args.manual)
if res is wlutil.testResult.failure:
print("Test Failed")
suitePass = False
failCount += 1
elif res is wlutil.testResult.skip:
print("Test Skipped")
skipCount += 1
else:
print("Test Passed")
log.info("")
elif args.command == 'clean':
# with contextlib.suppress(FileNotFoundError):
if 'bin' in targetCfg:
deleteSafe(targetCfg['bin'])
deleteSafe(targetCfg['bin'] + '-initramfs')
if 'img' in targetCfg:
deleteSafe(targetCfg['img'])
if 'jobs' in targetCfg:
for jCfg in targetCfg['jobs'].values():
if 'bin' in jCfg:
deleteSafe(jCfg['bin'])
deleteSafe(jCfg['bin'] + '-initramfs')
if 'img' in jCfg:
deleteSafe(jCfg['img'])
elif args.command == 'install':
wlutil.installWorkload(cfgPath, cfgs)
else:
log.error("No subcommand specified")
sys.exit(1)
log.info("Log available at: " + os.path.join(wlutil.log_dir, wlutil.getRunName() + ".log"))
if args.command == 'test':
if suitePass:
log.info("SUCCESS: All Tests Passed (" + str(skipCount) + " tests skipped)")
sys.exit(0)
else:
log.error("FAILURE: " + str(failCount) + " tests failed")
sys.exit(1)
sys.exit(0)
if __name__ == "__main__":
main()