xref: /XiangShan/scripts/xiangshan.py (revision 94e266cbb60b8a1f20a9cd8ece41fb25149f5673)
1c6d43980SLemover#***************************************************************************************
2c6d43980SLemover# Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3f320e0f0SYinan Xu# Copyright (c) 2020-2021 Peng Cheng Laboratory
4c6d43980SLemover#
5c6d43980SLemover# XiangShan is licensed under Mulan PSL v2.
6c6d43980SLemover# You can use this software according to the terms and conditions of the Mulan PSL v2.
7c6d43980SLemover# You may obtain a copy of Mulan PSL v2 at:
8c6d43980SLemover#          http://license.coscl.org.cn/MulanPSL2
9c6d43980SLemover#
10c6d43980SLemover# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11c6d43980SLemover# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12c6d43980SLemover# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13c6d43980SLemover#
14c6d43980SLemover# See the Mulan PSL v2 for more details.
15c6d43980SLemover#***************************************************************************************
16c6d43980SLemover
17c11a4d2cSYinan Xu# Simple version of xiangshan python wrapper
18c11a4d2cSYinan Xu
19c11a4d2cSYinan Xuimport argparse
2059bcbb59SYinan Xuimport os
2159bcbb59SYinan Xuimport random
22c11a4d2cSYinan Xuimport subprocess
2359bcbb59SYinan Xuimport sys
245ef7374fSLi Qianruoimport time
25c11a4d2cSYinan Xu
26*94e266cbSYinan Xuimport psutil
27*94e266cbSYinan Xu
28c11a4d2cSYinan Xu
29c11a4d2cSYinan Xuclass XSArgs(object):
30c11a4d2cSYinan Xu    script_path = os.path.realpath(__file__)
31c11a4d2cSYinan Xu    # default path to the repositories
32c11a4d2cSYinan Xu    noop_home = os.path.join(os.path.dirname(script_path), "..")
33c11a4d2cSYinan Xu    nemu_home = os.path.join(noop_home, "../NEMU")
34c11a4d2cSYinan Xu    am_home = os.path.join(noop_home, "../nexus-am")
35c11a4d2cSYinan Xu    dramsim3_home = os.path.join(noop_home, "../DRAMsim3")
36c11a4d2cSYinan Xu    rvtest_home = os.path.join(noop_home, "../riscv-tests")
3724e2eab6SJinYue    default_wave_home = os.path.join(noop_home, "build")
3824e2eab6SJinYue    wave_home   = default_wave_home
39c11a4d2cSYinan Xu
40c11a4d2cSYinan Xu    def __init__(self, args):
41c11a4d2cSYinan Xu        # all path environment variables that should be set
42c11a4d2cSYinan Xu        all_path = [
43c11a4d2cSYinan Xu            # (python argument, environment variable, default, target function)
44c11a4d2cSYinan Xu            (None, "NOOP_HOME", self.noop_home, self.set_noop_home),
45c11a4d2cSYinan Xu            (args.nemu, "NEMU_HOME", self.nemu_home, self.set_nemu_home),
46c11a4d2cSYinan Xu            (args.am, "AM_HOME", self.am_home, self.set_am_home),
47c11a4d2cSYinan Xu            (args.dramsim3, "DRAMSIM3_HOME", self.dramsim3_home, self.set_dramsim3_home),
48c11a4d2cSYinan Xu            (args.rvtest, "RVTEST_HOME", self.rvtest_home, self.set_rvtest_home),
49c11a4d2cSYinan Xu        ]
50c11a4d2cSYinan Xu        for (arg_in, env, default, set_func) in all_path:
51c11a4d2cSYinan Xu            set_func(self.__extract_path(arg_in, env, default))
52c11a4d2cSYinan Xu        # Chisel arguments
531545277aSYinan Xu        self.enable_log = args.enable_log
545ef7374fSLi Qianruo        self.num_cores = args.num_cores
55c11a4d2cSYinan Xu        # Makefile arguments
56c11a4d2cSYinan Xu        self.threads = args.threads
57c11a4d2cSYinan Xu        self.with_dramsim3 = 1 if args.with_dramsim3 else None
581545277aSYinan Xu        self.is_release = 1 if args.release else None
59eb852d4cSJinYue        self.trace = 1 if args.trace or not args.disable_fork  else None
606c0058d3SYinan Xu        self.config = args.config
61c11a4d2cSYinan Xu        # emu arguments
62c11a4d2cSYinan Xu        self.max_instr = args.max_instr
6359bcbb59SYinan Xu        self.seed = random.randint(0, 9999)
64c11a4d2cSYinan Xu        self.numa = args.numa
65f9930da0SYinan Xu        self.diff = args.diff
66078fde2bSJinYue        self.fork = not args.disable_fork
6724e2eab6SJinYue        # wave dump path
6824e2eab6SJinYue        if args.wave_dump is not None:
6924e2eab6SJinYue            self.set_wave_home(args.wave_dump)
7024e2eab6SJinYue        else:
7124e2eab6SJinYue            self.set_wave_home(self.default_wave_home)
72c11a4d2cSYinan Xu
73c11a4d2cSYinan Xu    def get_env_variables(self):
74c11a4d2cSYinan Xu        all_env = {
75c11a4d2cSYinan Xu            "NOOP_HOME"    : self.noop_home,
76c11a4d2cSYinan Xu            "NEMU_HOME"    : self.nemu_home,
7724e2eab6SJinYue            "WAVE_HOME"    : self.wave_home,
78c11a4d2cSYinan Xu            "AM_HOME"      : self.am_home,
79c11a4d2cSYinan Xu            "DRAMSIM3_HOME": self.dramsim3_home
80c11a4d2cSYinan Xu        }
81c11a4d2cSYinan Xu        return all_env
82c11a4d2cSYinan Xu
83c11a4d2cSYinan Xu    def get_chisel_args(self, prefix=None):
84c11a4d2cSYinan Xu        chisel_args = [
851545277aSYinan Xu            (self.enable_log, "enable-log")
86c11a4d2cSYinan Xu        ]
87c11a4d2cSYinan Xu        args = map(lambda x: x[1], filter(lambda arg: arg[0], chisel_args))
88c11a4d2cSYinan Xu        if prefix is not None:
89c11a4d2cSYinan Xu            args = map(lambda x: prefix + x, args)
90c11a4d2cSYinan Xu        return args
91c11a4d2cSYinan Xu
92c11a4d2cSYinan Xu    def get_makefile_args(self):
93c11a4d2cSYinan Xu        makefile_args = [
94c11a4d2cSYinan Xu            (self.threads,       "EMU_THREADS"),
95c11a4d2cSYinan Xu            (self.with_dramsim3, "WITH_DRAMSIM3"),
961545277aSYinan Xu            (self.is_release,    "RELEASE"),
976c0058d3SYinan Xu            (self.trace,         "EMU_TRACE"),
985ef7374fSLi Qianruo            (self.config,        "CONFIG"),
995ef7374fSLi Qianruo            (self.num_cores,     "NUM_CORES")
100c11a4d2cSYinan Xu        ]
101c11a4d2cSYinan Xu        args = filter(lambda arg: arg[0] is not None, makefile_args)
102c11a4d2cSYinan Xu        return args
103c11a4d2cSYinan Xu
104c11a4d2cSYinan Xu    def get_emu_args(self):
105c11a4d2cSYinan Xu        emu_args = [
10659bcbb59SYinan Xu            (self.max_instr, "max-instr"),
107f9930da0SYinan Xu            (self.diff,      "diff"),
10859bcbb59SYinan Xu            (self.seed,      "seed")
109c11a4d2cSYinan Xu        ]
110c11a4d2cSYinan Xu        args = filter(lambda arg: arg[0] is not None, emu_args)
111c11a4d2cSYinan Xu        return args
112c11a4d2cSYinan Xu
113c11a4d2cSYinan Xu    def show(self):
114c11a4d2cSYinan Xu        print("Extra environment variables:")
115c11a4d2cSYinan Xu        env = self.get_env_variables()
116c11a4d2cSYinan Xu        for env_name in env:
117c11a4d2cSYinan Xu            print(f"{env_name}: {env[env_name]}")
118c11a4d2cSYinan Xu        print()
119c11a4d2cSYinan Xu        print("Chisel arguments:")
120c11a4d2cSYinan Xu        print(" ".join(self.get_chisel_args()))
121c11a4d2cSYinan Xu        print()
122c11a4d2cSYinan Xu        print("Makefile arguments:")
123c11a4d2cSYinan Xu        for val, name in self.get_makefile_args():
124c11a4d2cSYinan Xu            print(f"{name}={val}")
125c11a4d2cSYinan Xu        print()
126c11a4d2cSYinan Xu        print("emu arguments:")
127c11a4d2cSYinan Xu        for val, name in self.get_emu_args():
128c11a4d2cSYinan Xu            print(f"--{name} {val}")
129c11a4d2cSYinan Xu        print()
130c11a4d2cSYinan Xu
131c11a4d2cSYinan Xu    def __extract_path(self, path, env=None, default=None):
132c11a4d2cSYinan Xu        if path is None and env is not None:
133c11a4d2cSYinan Xu            path = os.getenv(env)
134c11a4d2cSYinan Xu        if path is None and default is not None:
135c11a4d2cSYinan Xu            path = default
136c11a4d2cSYinan Xu        path = os.path.realpath(path)
137c11a4d2cSYinan Xu        return path
138c11a4d2cSYinan Xu
139c11a4d2cSYinan Xu    def set_noop_home(self, path):
140c11a4d2cSYinan Xu        self.noop_home = path
141c11a4d2cSYinan Xu
142c11a4d2cSYinan Xu    def set_nemu_home(self, path):
143c11a4d2cSYinan Xu        self.nemu_home = path
144c11a4d2cSYinan Xu
145c11a4d2cSYinan Xu    def set_am_home(self, path):
146c11a4d2cSYinan Xu        self.am_home = path
147c11a4d2cSYinan Xu
148c11a4d2cSYinan Xu    def set_dramsim3_home(self, path):
149c11a4d2cSYinan Xu        self.dramsim3_home = path
150c11a4d2cSYinan Xu
151c11a4d2cSYinan Xu    def set_rvtest_home(self, path):
152c11a4d2cSYinan Xu        self.rvtest_home = path
153c11a4d2cSYinan Xu
15424e2eab6SJinYue    def set_wave_home(self, path):
15524e2eab6SJinYue        print(f"set wave home to {path}")
15624e2eab6SJinYue        self.wave_home = path
15724e2eab6SJinYue
158c11a4d2cSYinan Xu# XiangShan environment
159c11a4d2cSYinan Xuclass XiangShan(object):
160c11a4d2cSYinan Xu    def __init__(self, args):
161c11a4d2cSYinan Xu        self.args = XSArgs(args)
162c11a4d2cSYinan Xu
163c11a4d2cSYinan Xu    def show(self):
164c11a4d2cSYinan Xu        self.args.show()
165c11a4d2cSYinan Xu
166c11a4d2cSYinan Xu    def generate_verilog(self):
167c11a4d2cSYinan Xu        print("Generating XiangShan verilog with the following configurations:")
168c11a4d2cSYinan Xu        self.show()
169c11a4d2cSYinan Xu        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
170c11a4d2cSYinan Xu        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
171c11a4d2cSYinan Xu        return_code = self.__exec_cmd(f'make -C $NOOP_HOME verilog SIM_ARGS="{sim_args}" {make_args}')
172c11a4d2cSYinan Xu        return return_code
173c11a4d2cSYinan Xu
174c11a4d2cSYinan Xu    def build_emu(self):
175c11a4d2cSYinan Xu        print("Building XiangShan emu with the following configurations:")
176c11a4d2cSYinan Xu        self.show()
177c11a4d2cSYinan Xu        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
178c11a4d2cSYinan Xu        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
179a3e87608SWilliam Wang        return_code = self.__exec_cmd(f'make -C $NOOP_HOME emu -j200 SIM_ARGS="{sim_args}" {make_args}')
180c11a4d2cSYinan Xu        return return_code
181c11a4d2cSYinan Xu
182c11a4d2cSYinan Xu    def run_emu(self, workload):
183c11a4d2cSYinan Xu        print("Running XiangShan emu with the following configurations:")
184c11a4d2cSYinan Xu        self.show()
185c11a4d2cSYinan Xu        emu_args = " ".join(map(lambda arg: f"--{arg[1]} {arg[0]}", self.args.get_emu_args()))
186c11a4d2cSYinan Xu        print("workload:", workload)
187*94e266cbSYinan Xu        numa_info = get_free_cores(self.args.threads)
188*94e266cbSYinan Xu        numa_args = f"numactl -m {numa_info[0]} -C {numa_info[1]}-{numa_info[2]}" if self.args.numa else ""
189078fde2bSJinYue        fork_args = "--enable-fork" if self.args.fork else ""
190078fde2bSJinYue        return_code = self.__exec_cmd(f'{numa_args} $NOOP_HOME/build/emu -i {workload} {emu_args} {fork_args}')
191c11a4d2cSYinan Xu        return return_code
192c11a4d2cSYinan Xu
193c11a4d2cSYinan Xu    def run(self, args):
194c11a4d2cSYinan Xu        if args.ci is not None:
195c11a4d2cSYinan Xu            return self.run_ci(args.ci)
196c11a4d2cSYinan Xu        actions = [
197c11a4d2cSYinan Xu            (args.generate, lambda _ : self.generate_verilog()),
198c11a4d2cSYinan Xu            (args.build, lambda _ : self.build_emu()),
199c11a4d2cSYinan Xu            (args.workload, lambda args: self.run_emu(args.workload))
200c11a4d2cSYinan Xu        ]
201c11a4d2cSYinan Xu        valid_actions = map(lambda act: act[1], filter(lambda act: act[0], actions))
202c11a4d2cSYinan Xu        for i, action in enumerate(valid_actions):
203c11a4d2cSYinan Xu            print(f"Action {i}:")
204c11a4d2cSYinan Xu            ret = action(args)
205c11a4d2cSYinan Xu            if ret:
206c11a4d2cSYinan Xu                return ret
207c11a4d2cSYinan Xu        return 0
208c11a4d2cSYinan Xu
209c11a4d2cSYinan Xu    def __exec_cmd(self, cmd):
210c11a4d2cSYinan Xu        env = dict(os.environ)
211c11a4d2cSYinan Xu        env.update(self.args.get_env_variables())
212c11a4d2cSYinan Xu        print("subprocess call cmd:", cmd)
2135ef7374fSLi Qianruo        start = time.time()
214c11a4d2cSYinan Xu        return_code = subprocess.call(cmd, shell=True, env=env)
2155ef7374fSLi Qianruo        end = time.time()
2165ef7374fSLi Qianruo        print(f"Elapsed time: {end - start} seconds")
217c11a4d2cSYinan Xu        return return_code
218c11a4d2cSYinan Xu
219c11a4d2cSYinan Xu    def __get_ci_cputest(self, name=None):
220c11a4d2cSYinan Xu        base_dir = os.path.join(self.args.am_home, "tests/cputest/build")
221c11a4d2cSYinan Xu        cputest = os.listdir(base_dir)
222c11a4d2cSYinan Xu        cputest = filter(lambda x: x.endswith(".bin"), cputest)
223c11a4d2cSYinan Xu        cputest = map(lambda x: os.path.join(base_dir, x), cputest)
224c11a4d2cSYinan Xu        return cputest
225c11a4d2cSYinan Xu
226c11a4d2cSYinan Xu    def __get_ci_rvtest(self, name=None):
227c11a4d2cSYinan Xu        base_dir = os.path.join(self.args.rvtest_home, "isa/build")
228c11a4d2cSYinan Xu        riscv_tests = os.listdir(base_dir)
229c11a4d2cSYinan Xu        riscv_tests = filter(lambda x: x.endswith(".bin"), riscv_tests)
230c11a4d2cSYinan Xu        all_rv_tests = ["rv64ui", "rv64um", "rv64ua", "rv64uf", "rv64ud"]
231c11a4d2cSYinan Xu        riscv_tests = filter(lambda x: x[:6] in all_rv_tests, riscv_tests)
232c11a4d2cSYinan Xu        riscv_tests = map(lambda x: os.path.join(base_dir, x), riscv_tests)
233c11a4d2cSYinan Xu        return riscv_tests
234c11a4d2cSYinan Xu
235675acc68SYinan Xu    def __get_ci_misc(self, name=None):
236675acc68SYinan Xu        base_dir = "/home/ci-runner/xsenv/workloads"
237675acc68SYinan Xu        workloads = [
238675acc68SYinan Xu            "bitmanip/bitMisc.bin",
2393feeca58Szfw            "crypto/crypto-riscv64-noop.bin",
240675acc68SYinan Xu            "coremark_rv64gc_o2/coremark-riscv64-xs.bin",
241675acc68SYinan Xu            "coremark_rv64gc_o3/coremark-riscv64-xs.bin",
24264a887e0SYinan Xu            "coremark_rv64gcb_o3/coremark-riscv64-xs.bin",
24335620aa8Swakafa            "ext_intr/amtest-riscv64-xs.bin",
2443f4ec46fSCODE-JTZ            "cache-alias/aliastest-riscv64-xs.bin",
245af2f7849Shappy-lx            "Svinval/rv64mi-p-svinval.bin",
246b6982e83SLemover            "pmp/pmp.riscv.bin",
24745f497a4Shappy-lx            "asid/asid.bin",
2483f4ec46fSCODE-JTZ            "cache-management/softprefetch-riscv64-noop.bin"
249675acc68SYinan Xu        ]
250675acc68SYinan Xu        misc_tests = map(lambda x: os.path.join(base_dir, x), workloads)
251675acc68SYinan Xu        return misc_tests
252675acc68SYinan Xu
253c11a4d2cSYinan Xu    def __am_apps_path(self, bench):
254c11a4d2cSYinan Xu        filename = f"{bench}-riscv64-noop.bin"
255c11a4d2cSYinan Xu        return [os.path.join(self.args.am_home, "apps", bench, "build", filename)]
256c11a4d2cSYinan Xu
257c11a4d2cSYinan Xu    def __get_ci_workloads(self, name):
258c11a4d2cSYinan Xu        workloads = {
259c11a4d2cSYinan Xu            "linux-hello": "bbl.bin",
2605092a298Szfw            "povray": "_700480000000_.gz",
2615092a298Szfw            "mcf": "_17520000000_.gz",
2625092a298Szfw            "xalancbmk": "_266100000000_.gz",
2635092a298Szfw            "gcc": "_39720000000_.gz",
2645092a298Szfw            "namd": "_434640000000_.gz",
2655092a298Szfw            "milc": "_103620000000_.gz",
2665092a298Szfw            "lbm": "_140840000000_.gz",
2677b441e5eSYinan Xu            "gromacs": "_275480000000_.gz",
2687b441e5eSYinan Xu            "wrf": "_1916220000000_.gz",
2697b441e5eSYinan Xu            "astar": "_122060000000_.gz"
270c11a4d2cSYinan Xu        }
271c11a4d2cSYinan Xu        return [os.path.join("/home/ci-runner/xsenv/workloads", name, workloads[name])]
272c11a4d2cSYinan Xu
273c11a4d2cSYinan Xu    def run_ci(self, test):
274c11a4d2cSYinan Xu        all_tests = {
275c11a4d2cSYinan Xu            "cputest": self.__get_ci_cputest,
276c11a4d2cSYinan Xu            "riscv-tests": self.__get_ci_rvtest,
277675acc68SYinan Xu            "misc-tests": self.__get_ci_misc,
278c11a4d2cSYinan Xu            "microbench": self.__am_apps_path,
279c11a4d2cSYinan Xu            "coremark": self.__am_apps_path
280c11a4d2cSYinan Xu        }
281c11a4d2cSYinan Xu        for target in all_tests.get(test, self.__get_ci_workloads)(test):
282c11a4d2cSYinan Xu            print(target)
283c11a4d2cSYinan Xu            ret = self.run_emu(target)
284c11a4d2cSYinan Xu            if ret:
28524e2eab6SJinYue                if self.args.default_wave_home != self.args.wave_home:
28624e2eab6SJinYue                    print("copy wave file to " + self.args.wave_home)
28724e2eab6SJinYue                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.vcd $WAVE_HOME")
288bc063562SLemover                    self.__exec_cmd(f"cp $NOOP_HOME/build/emu $WAVE_HOME")
289bc063562SLemover                    self.__exec_cmd(f"cp $NOOP_HOME/build/SimTop.v $WAVE_HOME")
290c11a4d2cSYinan Xu                return ret
291c11a4d2cSYinan Xu        return 0
292c11a4d2cSYinan Xu
293*94e266cbSYinan Xudef get_free_cores(n):
294*94e266cbSYinan Xu    while True:
295*94e266cbSYinan Xu        # To avoid potential conflicts, we allow CI to use SMT.
296*94e266cbSYinan Xu        num_logical_core = psutil.cpu_count(logical=True)
297*94e266cbSYinan Xu        core_usage = psutil.cpu_percent(interval=1, percpu=True)
298*94e266cbSYinan Xu        num_window = num_logical_core // n
299*94e266cbSYinan Xu        for i in range(num_window):
300*94e266cbSYinan Xu            window_usage = core_usage[i * n : i * n + n]
301*94e266cbSYinan Xu            if sum(window_usage) < 0.3 * n and True not in map(lambda x: x > 0.5, window_usage):
302*94e266cbSYinan Xu                return (((i * n) % 128)// 64, i * n, i * n + n - 1)
303*94e266cbSYinan Xu        print(f"No free {n} cores found. CPU usage: {core_usage}\n")
304*94e266cbSYinan Xu
305c11a4d2cSYinan Xuif __name__ == "__main__":
306c11a4d2cSYinan Xu    parser = argparse.ArgumentParser(description='Python wrapper for XiangShan')
307c11a4d2cSYinan Xu    parser.add_argument('workload', nargs='?', type=str, default="",
308c11a4d2cSYinan Xu                        help='input workload file in binary format')
309c11a4d2cSYinan Xu    # actions
310c11a4d2cSYinan Xu    parser.add_argument('--build', action='store_true', help='build XS emu')
311c11a4d2cSYinan Xu    parser.add_argument('--generate', action='store_true', help='generate XS verilog')
312c11a4d2cSYinan Xu    parser.add_argument('--ci', nargs='?', type=str, const="", help='run CI tests')
313c11a4d2cSYinan Xu    # environment variables
314c11a4d2cSYinan Xu    parser.add_argument('--nemu', nargs='?', type=str, help='path to nemu')
315c11a4d2cSYinan Xu    parser.add_argument('--am', nargs='?', type=str, help='path to nexus-am')
316c11a4d2cSYinan Xu    parser.add_argument('--dramsim3', nargs='?', type=str, help='path to dramsim3')
317c11a4d2cSYinan Xu    parser.add_argument('--rvtest', nargs='?', type=str, help='path to riscv-tests')
31824e2eab6SJinYue    parser.add_argument('--wave-dump', nargs='?', type=str , help='path to dump wave')
319c11a4d2cSYinan Xu    # chisel arguments
3201545277aSYinan Xu    parser.add_argument('--enable-log', action='store_true', help='enable log')
3215ef7374fSLi Qianruo    parser.add_argument('--num-cores', type=int, help='number of cores')
322c11a4d2cSYinan Xu    # makefile arguments
3231545277aSYinan Xu    parser.add_argument('--release', action='store_true', help='enable release')
324c11a4d2cSYinan Xu    parser.add_argument('--with-dramsim3', action='store_true', help='enable dramsim3')
325c11a4d2cSYinan Xu    parser.add_argument('--threads', nargs='?', type=int, help='number of emu threads')
326c11a4d2cSYinan Xu    parser.add_argument('--trace', action='store_true', help='enable waveform')
3276c0058d3SYinan Xu    parser.add_argument('--config', nargs='?', type=str, help='config')
328c11a4d2cSYinan Xu    # emu arguments
329c11a4d2cSYinan Xu    parser.add_argument('--numa', action='store_true', help='use numactl')
330f9930da0SYinan Xu    parser.add_argument('--diff', nargs='?', default="./ready-to-run/riscv64-nemu-interpreter-so", type=str, help='nemu so')
331c11a4d2cSYinan Xu    parser.add_argument('--max-instr', nargs='?', type=int, help='max instr')
332078fde2bSJinYue    parser.add_argument('--disable-fork', action='store_true', help='disable lightSSS')
33324e2eab6SJinYue    # ci action head sha
334c11a4d2cSYinan Xu
335c11a4d2cSYinan Xu    args = parser.parse_args()
336c11a4d2cSYinan Xu
337c11a4d2cSYinan Xu    xs = XiangShan(args)
338c11a4d2cSYinan Xu    ret = xs.run(args)
339c11a4d2cSYinan Xu
340c11a4d2cSYinan Xu    sys.exit(ret)
341