xref: /XiangShan/scripts/xiangshan.py (revision 9c297294630838f15cf95d24893cf5fe990a6524)
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
2694e266cbSYinan Xuimport psutil
2794e266cbSYinan 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
67*9c297294SWilliam Wang        self.disable_diff = args.no_diff
6824e2eab6SJinYue        # wave dump path
6924e2eab6SJinYue        if args.wave_dump is not None:
7024e2eab6SJinYue            self.set_wave_home(args.wave_dump)
7124e2eab6SJinYue        else:
7224e2eab6SJinYue            self.set_wave_home(self.default_wave_home)
73c11a4d2cSYinan Xu
74c11a4d2cSYinan Xu    def get_env_variables(self):
75c11a4d2cSYinan Xu        all_env = {
76c11a4d2cSYinan Xu            "NOOP_HOME"    : self.noop_home,
77c11a4d2cSYinan Xu            "NEMU_HOME"    : self.nemu_home,
7824e2eab6SJinYue            "WAVE_HOME"    : self.wave_home,
79c11a4d2cSYinan Xu            "AM_HOME"      : self.am_home,
80c11a4d2cSYinan Xu            "DRAMSIM3_HOME": self.dramsim3_home
81c11a4d2cSYinan Xu        }
82c11a4d2cSYinan Xu        return all_env
83c11a4d2cSYinan Xu
84c11a4d2cSYinan Xu    def get_chisel_args(self, prefix=None):
85c11a4d2cSYinan Xu        chisel_args = [
861545277aSYinan Xu            (self.enable_log, "enable-log")
87c11a4d2cSYinan Xu        ]
88c11a4d2cSYinan Xu        args = map(lambda x: x[1], filter(lambda arg: arg[0], chisel_args))
89c11a4d2cSYinan Xu        if prefix is not None:
90c11a4d2cSYinan Xu            args = map(lambda x: prefix + x, args)
91c11a4d2cSYinan Xu        return args
92c11a4d2cSYinan Xu
93c11a4d2cSYinan Xu    def get_makefile_args(self):
94c11a4d2cSYinan Xu        makefile_args = [
95c11a4d2cSYinan Xu            (self.threads,       "EMU_THREADS"),
96c11a4d2cSYinan Xu            (self.with_dramsim3, "WITH_DRAMSIM3"),
971545277aSYinan Xu            (self.is_release,    "RELEASE"),
986c0058d3SYinan Xu            (self.trace,         "EMU_TRACE"),
995ef7374fSLi Qianruo            (self.config,        "CONFIG"),
1005ef7374fSLi Qianruo            (self.num_cores,     "NUM_CORES")
101c11a4d2cSYinan Xu        ]
102c11a4d2cSYinan Xu        args = filter(lambda arg: arg[0] is not None, makefile_args)
103c11a4d2cSYinan Xu        return args
104c11a4d2cSYinan Xu
105c11a4d2cSYinan Xu    def get_emu_args(self):
106c11a4d2cSYinan Xu        emu_args = [
10759bcbb59SYinan Xu            (self.max_instr, "max-instr"),
108f9930da0SYinan Xu            (self.diff,      "diff"),
10959bcbb59SYinan Xu            (self.seed,      "seed")
110c11a4d2cSYinan Xu        ]
111c11a4d2cSYinan Xu        args = filter(lambda arg: arg[0] is not None, emu_args)
112c11a4d2cSYinan Xu        return args
113c11a4d2cSYinan Xu
114c11a4d2cSYinan Xu    def show(self):
115c11a4d2cSYinan Xu        print("Extra environment variables:")
116c11a4d2cSYinan Xu        env = self.get_env_variables()
117c11a4d2cSYinan Xu        for env_name in env:
118c11a4d2cSYinan Xu            print(f"{env_name}: {env[env_name]}")
119c11a4d2cSYinan Xu        print()
120c11a4d2cSYinan Xu        print("Chisel arguments:")
121c11a4d2cSYinan Xu        print(" ".join(self.get_chisel_args()))
122c11a4d2cSYinan Xu        print()
123c11a4d2cSYinan Xu        print("Makefile arguments:")
124c11a4d2cSYinan Xu        for val, name in self.get_makefile_args():
125c11a4d2cSYinan Xu            print(f"{name}={val}")
126c11a4d2cSYinan Xu        print()
127c11a4d2cSYinan Xu        print("emu arguments:")
128c11a4d2cSYinan Xu        for val, name in self.get_emu_args():
129c11a4d2cSYinan Xu            print(f"--{name} {val}")
130c11a4d2cSYinan Xu        print()
131c11a4d2cSYinan Xu
132c11a4d2cSYinan Xu    def __extract_path(self, path, env=None, default=None):
133c11a4d2cSYinan Xu        if path is None and env is not None:
134c11a4d2cSYinan Xu            path = os.getenv(env)
135c11a4d2cSYinan Xu        if path is None and default is not None:
136c11a4d2cSYinan Xu            path = default
137c11a4d2cSYinan Xu        path = os.path.realpath(path)
138c11a4d2cSYinan Xu        return path
139c11a4d2cSYinan Xu
140c11a4d2cSYinan Xu    def set_noop_home(self, path):
141c11a4d2cSYinan Xu        self.noop_home = path
142c11a4d2cSYinan Xu
143c11a4d2cSYinan Xu    def set_nemu_home(self, path):
144c11a4d2cSYinan Xu        self.nemu_home = path
145c11a4d2cSYinan Xu
146c11a4d2cSYinan Xu    def set_am_home(self, path):
147c11a4d2cSYinan Xu        self.am_home = path
148c11a4d2cSYinan Xu
149c11a4d2cSYinan Xu    def set_dramsim3_home(self, path):
150c11a4d2cSYinan Xu        self.dramsim3_home = path
151c11a4d2cSYinan Xu
152c11a4d2cSYinan Xu    def set_rvtest_home(self, path):
153c11a4d2cSYinan Xu        self.rvtest_home = path
154c11a4d2cSYinan Xu
15524e2eab6SJinYue    def set_wave_home(self, path):
15624e2eab6SJinYue        print(f"set wave home to {path}")
15724e2eab6SJinYue        self.wave_home = path
15824e2eab6SJinYue
159c11a4d2cSYinan Xu# XiangShan environment
160c11a4d2cSYinan Xuclass XiangShan(object):
161c11a4d2cSYinan Xu    def __init__(self, args):
162c11a4d2cSYinan Xu        self.args = XSArgs(args)
163c11a4d2cSYinan Xu
164c11a4d2cSYinan Xu    def show(self):
165c11a4d2cSYinan Xu        self.args.show()
166c11a4d2cSYinan Xu
167c11a4d2cSYinan Xu    def generate_verilog(self):
168c11a4d2cSYinan Xu        print("Generating XiangShan verilog with the following configurations:")
169c11a4d2cSYinan Xu        self.show()
170c11a4d2cSYinan Xu        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
171c11a4d2cSYinan Xu        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
172c11a4d2cSYinan Xu        return_code = self.__exec_cmd(f'make -C $NOOP_HOME verilog SIM_ARGS="{sim_args}" {make_args}')
173c11a4d2cSYinan Xu        return return_code
174c11a4d2cSYinan Xu
175c11a4d2cSYinan Xu    def build_emu(self):
176c11a4d2cSYinan Xu        print("Building XiangShan emu with the following configurations:")
177c11a4d2cSYinan Xu        self.show()
178c11a4d2cSYinan Xu        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
179c11a4d2cSYinan Xu        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
180a3e87608SWilliam Wang        return_code = self.__exec_cmd(f'make -C $NOOP_HOME emu -j200 SIM_ARGS="{sim_args}" {make_args}')
181c11a4d2cSYinan Xu        return return_code
182c11a4d2cSYinan Xu
183c11a4d2cSYinan Xu    def run_emu(self, workload):
184c11a4d2cSYinan Xu        print("Running XiangShan emu with the following configurations:")
185c11a4d2cSYinan Xu        self.show()
186c11a4d2cSYinan Xu        emu_args = " ".join(map(lambda arg: f"--{arg[1]} {arg[0]}", self.args.get_emu_args()))
187c11a4d2cSYinan Xu        print("workload:", workload)
18894e266cbSYinan Xu        numa_info = get_free_cores(self.args.threads)
18994e266cbSYinan Xu        numa_args = f"numactl -m {numa_info[0]} -C {numa_info[1]}-{numa_info[2]}" if self.args.numa else ""
190078fde2bSJinYue        fork_args = "--enable-fork" if self.args.fork else ""
191*9c297294SWilliam Wang        diff_args = "--no-diff" if self.args.disable_diff else ""
192*9c297294SWilliam Wang        return_code = self.__exec_cmd(f'{numa_args} $NOOP_HOME/build/emu -i {workload} {emu_args} {fork_args} {diff_args}')
193c11a4d2cSYinan Xu        return return_code
194c11a4d2cSYinan Xu
195c11a4d2cSYinan Xu    def run(self, args):
196c11a4d2cSYinan Xu        if args.ci is not None:
197c11a4d2cSYinan Xu            return self.run_ci(args.ci)
198c11a4d2cSYinan Xu        actions = [
199c11a4d2cSYinan Xu            (args.generate, lambda _ : self.generate_verilog()),
200c11a4d2cSYinan Xu            (args.build, lambda _ : self.build_emu()),
201c11a4d2cSYinan Xu            (args.workload, lambda args: self.run_emu(args.workload))
202c11a4d2cSYinan Xu        ]
203c11a4d2cSYinan Xu        valid_actions = map(lambda act: act[1], filter(lambda act: act[0], actions))
204c11a4d2cSYinan Xu        for i, action in enumerate(valid_actions):
205c11a4d2cSYinan Xu            print(f"Action {i}:")
206c11a4d2cSYinan Xu            ret = action(args)
207c11a4d2cSYinan Xu            if ret:
208c11a4d2cSYinan Xu                return ret
209c11a4d2cSYinan Xu        return 0
210c11a4d2cSYinan Xu
211c11a4d2cSYinan Xu    def __exec_cmd(self, cmd):
212c11a4d2cSYinan Xu        env = dict(os.environ)
213c11a4d2cSYinan Xu        env.update(self.args.get_env_variables())
214c11a4d2cSYinan Xu        print("subprocess call cmd:", cmd)
2155ef7374fSLi Qianruo        start = time.time()
216c11a4d2cSYinan Xu        return_code = subprocess.call(cmd, shell=True, env=env)
2175ef7374fSLi Qianruo        end = time.time()
2185ef7374fSLi Qianruo        print(f"Elapsed time: {end - start} seconds")
219c11a4d2cSYinan Xu        return return_code
220c11a4d2cSYinan Xu
221c11a4d2cSYinan Xu    def __get_ci_cputest(self, name=None):
222c11a4d2cSYinan Xu        base_dir = os.path.join(self.args.am_home, "tests/cputest/build")
223c11a4d2cSYinan Xu        cputest = os.listdir(base_dir)
224c11a4d2cSYinan Xu        cputest = filter(lambda x: x.endswith(".bin"), cputest)
225c11a4d2cSYinan Xu        cputest = map(lambda x: os.path.join(base_dir, x), cputest)
226c11a4d2cSYinan Xu        return cputest
227c11a4d2cSYinan Xu
228c11a4d2cSYinan Xu    def __get_ci_rvtest(self, name=None):
229c11a4d2cSYinan Xu        base_dir = os.path.join(self.args.rvtest_home, "isa/build")
230c11a4d2cSYinan Xu        riscv_tests = os.listdir(base_dir)
231c11a4d2cSYinan Xu        riscv_tests = filter(lambda x: x.endswith(".bin"), riscv_tests)
232c11a4d2cSYinan Xu        all_rv_tests = ["rv64ui", "rv64um", "rv64ua", "rv64uf", "rv64ud"]
233c11a4d2cSYinan Xu        riscv_tests = filter(lambda x: x[:6] in all_rv_tests, riscv_tests)
234c11a4d2cSYinan Xu        riscv_tests = map(lambda x: os.path.join(base_dir, x), riscv_tests)
235c11a4d2cSYinan Xu        return riscv_tests
236c11a4d2cSYinan Xu
237675acc68SYinan Xu    def __get_ci_misc(self, name=None):
238675acc68SYinan Xu        base_dir = "/home/ci-runner/xsenv/workloads"
239675acc68SYinan Xu        workloads = [
240675acc68SYinan Xu            "bitmanip/bitMisc.bin",
2413feeca58Szfw            "crypto/crypto-riscv64-noop.bin",
242675acc68SYinan Xu            "coremark_rv64gc_o2/coremark-riscv64-xs.bin",
243675acc68SYinan Xu            "coremark_rv64gc_o3/coremark-riscv64-xs.bin",
24464a887e0SYinan Xu            "coremark_rv64gcb_o3/coremark-riscv64-xs.bin",
24535620aa8Swakafa            "ext_intr/amtest-riscv64-xs.bin",
2463f4ec46fSCODE-JTZ            "cache-alias/aliastest-riscv64-xs.bin",
247af2f7849Shappy-lx            "Svinval/rv64mi-p-svinval.bin",
248b6982e83SLemover            "pmp/pmp.riscv.bin",
24945f497a4Shappy-lx            "asid/asid.bin",
2507d9edc86SLemover            "isa_misc/xret_clear_mprv.bin",
251705cbec3SLemover            "isa_misc/satp_ppn.bin",
252*9c297294SWilliam Wang            "cache-management/softprefetchtest-riscv64-xs.bin"
253675acc68SYinan Xu        ]
254675acc68SYinan Xu        misc_tests = map(lambda x: os.path.join(base_dir, x), workloads)
255675acc68SYinan Xu        return misc_tests
256675acc68SYinan Xu
257*9c297294SWilliam Wang    def __get_ci_nodiff(self, name=None):
258*9c297294SWilliam Wang        base_dir = "/home/ci-runner/xsenv/workloads"
259*9c297294SWilliam Wang        workloads = [
260*9c297294SWilliam Wang            "cache-management/cacheoptest-riscv64-xs.bin"
261*9c297294SWilliam Wang        ]
262*9c297294SWilliam Wang        tests = map(lambda x: os.path.join(base_dir, x), workloads)
263*9c297294SWilliam Wang        return tests
264*9c297294SWilliam Wang
265c11a4d2cSYinan Xu    def __am_apps_path(self, bench):
266c11a4d2cSYinan Xu        filename = f"{bench}-riscv64-noop.bin"
267c11a4d2cSYinan Xu        return [os.path.join(self.args.am_home, "apps", bench, "build", filename)]
268c11a4d2cSYinan Xu
269c11a4d2cSYinan Xu    def __get_ci_workloads(self, name):
270c11a4d2cSYinan Xu        workloads = {
271c11a4d2cSYinan Xu            "linux-hello": "bbl.bin",
2725092a298Szfw            "povray": "_700480000000_.gz",
2735092a298Szfw            "mcf": "_17520000000_.gz",
2745092a298Szfw            "xalancbmk": "_266100000000_.gz",
2755092a298Szfw            "gcc": "_39720000000_.gz",
2765092a298Szfw            "namd": "_434640000000_.gz",
2775092a298Szfw            "milc": "_103620000000_.gz",
2785092a298Szfw            "lbm": "_140840000000_.gz",
2797b441e5eSYinan Xu            "gromacs": "_275480000000_.gz",
2807b441e5eSYinan Xu            "wrf": "_1916220000000_.gz",
2817b441e5eSYinan Xu            "astar": "_122060000000_.gz"
282c11a4d2cSYinan Xu        }
283c11a4d2cSYinan Xu        return [os.path.join("/home/ci-runner/xsenv/workloads", name, workloads[name])]
284c11a4d2cSYinan Xu
285c11a4d2cSYinan Xu    def run_ci(self, test):
286c11a4d2cSYinan Xu        all_tests = {
287c11a4d2cSYinan Xu            "cputest": self.__get_ci_cputest,
288c11a4d2cSYinan Xu            "riscv-tests": self.__get_ci_rvtest,
289675acc68SYinan Xu            "misc-tests": self.__get_ci_misc,
290*9c297294SWilliam Wang            "nodiff-tests": self.__get_ci_nodiff,
291c11a4d2cSYinan Xu            "microbench": self.__am_apps_path,
292c11a4d2cSYinan Xu            "coremark": self.__am_apps_path
293c11a4d2cSYinan Xu        }
294c11a4d2cSYinan Xu        for target in all_tests.get(test, self.__get_ci_workloads)(test):
295c11a4d2cSYinan Xu            print(target)
296c11a4d2cSYinan Xu            ret = self.run_emu(target)
297c11a4d2cSYinan Xu            if ret:
29824e2eab6SJinYue                if self.args.default_wave_home != self.args.wave_home:
29924e2eab6SJinYue                    print("copy wave file to " + self.args.wave_home)
30024e2eab6SJinYue                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.vcd $WAVE_HOME")
301bc063562SLemover                    self.__exec_cmd(f"cp $NOOP_HOME/build/emu $WAVE_HOME")
302bc063562SLemover                    self.__exec_cmd(f"cp $NOOP_HOME/build/SimTop.v $WAVE_HOME")
303c11a4d2cSYinan Xu                return ret
304c11a4d2cSYinan Xu        return 0
305c11a4d2cSYinan Xu
30694e266cbSYinan Xudef get_free_cores(n):
30794e266cbSYinan Xu    while True:
30894e266cbSYinan Xu        # To avoid potential conflicts, we allow CI to use SMT.
30994e266cbSYinan Xu        num_logical_core = psutil.cpu_count(logical=True)
31094e266cbSYinan Xu        core_usage = psutil.cpu_percent(interval=1, percpu=True)
31194e266cbSYinan Xu        num_window = num_logical_core // n
31294e266cbSYinan Xu        for i in range(num_window):
31394e266cbSYinan Xu            window_usage = core_usage[i * n : i * n + n]
31494e266cbSYinan Xu            if sum(window_usage) < 0.3 * n and True not in map(lambda x: x > 0.5, window_usage):
31594e266cbSYinan Xu                return (((i * n) % 128)// 64, i * n, i * n + n - 1)
31694e266cbSYinan Xu        print(f"No free {n} cores found. CPU usage: {core_usage}\n")
31794e266cbSYinan Xu
318c11a4d2cSYinan Xuif __name__ == "__main__":
319c11a4d2cSYinan Xu    parser = argparse.ArgumentParser(description='Python wrapper for XiangShan')
320c11a4d2cSYinan Xu    parser.add_argument('workload', nargs='?', type=str, default="",
321c11a4d2cSYinan Xu                        help='input workload file in binary format')
322c11a4d2cSYinan Xu    # actions
323c11a4d2cSYinan Xu    parser.add_argument('--build', action='store_true', help='build XS emu')
324c11a4d2cSYinan Xu    parser.add_argument('--generate', action='store_true', help='generate XS verilog')
325c11a4d2cSYinan Xu    parser.add_argument('--ci', nargs='?', type=str, const="", help='run CI tests')
326c11a4d2cSYinan Xu    # environment variables
327c11a4d2cSYinan Xu    parser.add_argument('--nemu', nargs='?', type=str, help='path to nemu')
328c11a4d2cSYinan Xu    parser.add_argument('--am', nargs='?', type=str, help='path to nexus-am')
329c11a4d2cSYinan Xu    parser.add_argument('--dramsim3', nargs='?', type=str, help='path to dramsim3')
330c11a4d2cSYinan Xu    parser.add_argument('--rvtest', nargs='?', type=str, help='path to riscv-tests')
33124e2eab6SJinYue    parser.add_argument('--wave-dump', nargs='?', type=str , help='path to dump wave')
332c11a4d2cSYinan Xu    # chisel arguments
3331545277aSYinan Xu    parser.add_argument('--enable-log', action='store_true', help='enable log')
3345ef7374fSLi Qianruo    parser.add_argument('--num-cores', type=int, help='number of cores')
335c11a4d2cSYinan Xu    # makefile arguments
3361545277aSYinan Xu    parser.add_argument('--release', action='store_true', help='enable release')
337c11a4d2cSYinan Xu    parser.add_argument('--with-dramsim3', action='store_true', help='enable dramsim3')
338c11a4d2cSYinan Xu    parser.add_argument('--threads', nargs='?', type=int, help='number of emu threads')
339c11a4d2cSYinan Xu    parser.add_argument('--trace', action='store_true', help='enable waveform')
3406c0058d3SYinan Xu    parser.add_argument('--config', nargs='?', type=str, help='config')
341c11a4d2cSYinan Xu    # emu arguments
342c11a4d2cSYinan Xu    parser.add_argument('--numa', action='store_true', help='use numactl')
343f9930da0SYinan Xu    parser.add_argument('--diff', nargs='?', default="./ready-to-run/riscv64-nemu-interpreter-so", type=str, help='nemu so')
344c11a4d2cSYinan Xu    parser.add_argument('--max-instr', nargs='?', type=int, help='max instr')
345078fde2bSJinYue    parser.add_argument('--disable-fork', action='store_true', help='disable lightSSS')
346*9c297294SWilliam Wang    parser.add_argument('--no-diff', action='store_true', help='disable difftest')
34724e2eab6SJinYue    # ci action head sha
348c11a4d2cSYinan Xu
349c11a4d2cSYinan Xu    args = parser.parse_args()
350c11a4d2cSYinan Xu
351c11a4d2cSYinan Xu    xs = XiangShan(args)
352c11a4d2cSYinan Xu    ret = xs.run(args)
353c11a4d2cSYinan Xu
354c11a4d2cSYinan Xu    sys.exit(ret)
355