xref: /XiangShan/scripts/xiangshan.py (revision fac0ab5637c337471e0dfc512fd00e3229c10d88)
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
679c297294SWilliam 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
167ef3b5b96SWilliam Wang    def make_clean(self):
168ef3b5b96SWilliam Wang        print("Clean up CI workspace")
169ef3b5b96SWilliam Wang        self.show()
170ef3b5b96SWilliam Wang        return_code = self.__exec_cmd(f'make -C $NOOP_HOME clean')
171ef3b5b96SWilliam Wang        return return_code
172ef3b5b96SWilliam Wang
173c11a4d2cSYinan Xu    def generate_verilog(self):
174c11a4d2cSYinan Xu        print("Generating XiangShan verilog with the following configurations:")
175c11a4d2cSYinan Xu        self.show()
176c11a4d2cSYinan Xu        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
177c11a4d2cSYinan Xu        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
178c11a4d2cSYinan Xu        return_code = self.__exec_cmd(f'make -C $NOOP_HOME verilog SIM_ARGS="{sim_args}" {make_args}')
179c11a4d2cSYinan Xu        return return_code
180c11a4d2cSYinan Xu
181c11a4d2cSYinan Xu    def build_emu(self):
182c11a4d2cSYinan Xu        print("Building XiangShan emu with the following configurations:")
183c11a4d2cSYinan Xu        self.show()
184c11a4d2cSYinan Xu        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
185c11a4d2cSYinan Xu        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
186a3e87608SWilliam Wang        return_code = self.__exec_cmd(f'make -C $NOOP_HOME emu -j200 SIM_ARGS="{sim_args}" {make_args}')
187c11a4d2cSYinan Xu        return return_code
188c11a4d2cSYinan Xu
189c11a4d2cSYinan Xu    def run_emu(self, workload):
190c11a4d2cSYinan Xu        print("Running XiangShan emu with the following configurations:")
191c11a4d2cSYinan Xu        self.show()
192c11a4d2cSYinan Xu        emu_args = " ".join(map(lambda arg: f"--{arg[1]} {arg[0]}", self.args.get_emu_args()))
193c11a4d2cSYinan Xu        print("workload:", workload)
194c9d90c8dSYinan Xu        numa_args = ""
195c9d90c8dSYinan Xu        if self.args.numa:
19694e266cbSYinan Xu            numa_info = get_free_cores(self.args.threads)
197c9d90c8dSYinan Xu            numa_args = f"numactl -m {numa_info[0]} -C {numa_info[1]}-{numa_info[2]}"
198078fde2bSJinYue        fork_args = "--enable-fork" if self.args.fork else ""
1999c297294SWilliam Wang        diff_args = "--no-diff" if self.args.disable_diff else ""
2009c297294SWilliam Wang        return_code = self.__exec_cmd(f'{numa_args} $NOOP_HOME/build/emu -i {workload} {emu_args} {fork_args} {diff_args}')
201c11a4d2cSYinan Xu        return return_code
202c11a4d2cSYinan Xu
203c11a4d2cSYinan Xu    def run(self, args):
204c11a4d2cSYinan Xu        if args.ci is not None:
205c11a4d2cSYinan Xu            return self.run_ci(args.ci)
206c11a4d2cSYinan Xu        actions = [
207c11a4d2cSYinan Xu            (args.generate, lambda _ : self.generate_verilog()),
208c11a4d2cSYinan Xu            (args.build, lambda _ : self.build_emu()),
209ef3b5b96SWilliam Wang            (args.workload, lambda args: self.run_emu(args.workload)),
210ef3b5b96SWilliam Wang            (args.clean, lambda _ : self.make_clean())
211c11a4d2cSYinan Xu        ]
212c11a4d2cSYinan Xu        valid_actions = map(lambda act: act[1], filter(lambda act: act[0], actions))
213c11a4d2cSYinan Xu        for i, action in enumerate(valid_actions):
214c11a4d2cSYinan Xu            print(f"Action {i}:")
215c11a4d2cSYinan Xu            ret = action(args)
216c11a4d2cSYinan Xu            if ret:
217c11a4d2cSYinan Xu                return ret
218c11a4d2cSYinan Xu        return 0
219c11a4d2cSYinan Xu
220c11a4d2cSYinan Xu    def __exec_cmd(self, cmd):
221c11a4d2cSYinan Xu        env = dict(os.environ)
222c11a4d2cSYinan Xu        env.update(self.args.get_env_variables())
223c11a4d2cSYinan Xu        print("subprocess call cmd:", cmd)
2245ef7374fSLi Qianruo        start = time.time()
225c11a4d2cSYinan Xu        return_code = subprocess.call(cmd, shell=True, env=env)
2265ef7374fSLi Qianruo        end = time.time()
2275ef7374fSLi Qianruo        print(f"Elapsed time: {end - start} seconds")
228c11a4d2cSYinan Xu        return return_code
229c11a4d2cSYinan Xu
230c11a4d2cSYinan Xu    def __get_ci_cputest(self, name=None):
231c11a4d2cSYinan Xu        base_dir = os.path.join(self.args.am_home, "tests/cputest/build")
232c11a4d2cSYinan Xu        cputest = os.listdir(base_dir)
233c11a4d2cSYinan Xu        cputest = filter(lambda x: x.endswith(".bin"), cputest)
234c11a4d2cSYinan Xu        cputest = map(lambda x: os.path.join(base_dir, x), cputest)
235c11a4d2cSYinan Xu        return cputest
236c11a4d2cSYinan Xu
237c11a4d2cSYinan Xu    def __get_ci_rvtest(self, name=None):
238c11a4d2cSYinan Xu        base_dir = os.path.join(self.args.rvtest_home, "isa/build")
239c11a4d2cSYinan Xu        riscv_tests = os.listdir(base_dir)
240c11a4d2cSYinan Xu        riscv_tests = filter(lambda x: x.endswith(".bin"), riscv_tests)
241c11a4d2cSYinan Xu        all_rv_tests = ["rv64ui", "rv64um", "rv64ua", "rv64uf", "rv64ud"]
242c11a4d2cSYinan Xu        riscv_tests = filter(lambda x: x[:6] in all_rv_tests, riscv_tests)
243c11a4d2cSYinan Xu        riscv_tests = map(lambda x: os.path.join(base_dir, x), riscv_tests)
244c11a4d2cSYinan Xu        return riscv_tests
245c11a4d2cSYinan Xu
246675acc68SYinan Xu    def __get_ci_misc(self, name=None):
247da3b568bSYinan Xu        base_dir = "/nfs/home/share/ci-workloads"
248675acc68SYinan Xu        workloads = [
249675acc68SYinan Xu            "bitmanip/bitMisc.bin",
2503feeca58Szfw            "crypto/crypto-riscv64-noop.bin",
251675acc68SYinan Xu            "coremark_rv64gc_o2/coremark-riscv64-xs.bin",
252675acc68SYinan Xu            "coremark_rv64gc_o3/coremark-riscv64-xs.bin",
25364a887e0SYinan Xu            "coremark_rv64gcb_o3/coremark-riscv64-xs.bin",
25435620aa8Swakafa            "ext_intr/amtest-riscv64-xs.bin",
2553f4ec46fSCODE-JTZ            "cache-alias/aliastest-riscv64-xs.bin",
256af2f7849Shappy-lx            "Svinval/rv64mi-p-svinval.bin",
257b6982e83SLemover            "pmp/pmp.riscv.bin",
25845f497a4Shappy-lx            "asid/asid.bin",
2597d9edc86SLemover            "isa_misc/xret_clear_mprv.bin",
260705cbec3SLemover            "isa_misc/satp_ppn.bin",
2619c297294SWilliam Wang            "cache-management/softprefetchtest-riscv64-xs.bin"
262675acc68SYinan Xu        ]
263675acc68SYinan Xu        misc_tests = map(lambda x: os.path.join(base_dir, x), workloads)
264675acc68SYinan Xu        return misc_tests
265675acc68SYinan Xu
266ef3b5b96SWilliam Wang    def __get_ci_mc(self, name=None):
267ef3b5b96SWilliam Wang        base_dir = "/nfs/home/share/ci-workloads"
268ef3b5b96SWilliam Wang        workloads = [
269ef3b5b96SWilliam Wang            "dualcoretest/ldvio-riscv64-xs.bin"
270ef3b5b96SWilliam Wang        ]
271ef3b5b96SWilliam Wang        mc_tests = map(lambda x: os.path.join(base_dir, x), workloads)
272ef3b5b96SWilliam Wang        return mc_tests
273ef3b5b96SWilliam Wang
2749c297294SWilliam Wang    def __get_ci_nodiff(self, name=None):
275da3b568bSYinan Xu        base_dir = "/nfs/home/share/ci-workloads"
2769c297294SWilliam Wang        workloads = [
2779c297294SWilliam Wang            "cache-management/cacheoptest-riscv64-xs.bin"
2789c297294SWilliam Wang        ]
2799c297294SWilliam Wang        tests = map(lambda x: os.path.join(base_dir, x), workloads)
2809c297294SWilliam Wang        return tests
2819c297294SWilliam Wang
282c11a4d2cSYinan Xu    def __am_apps_path(self, bench):
283c11a4d2cSYinan Xu        filename = f"{bench}-riscv64-noop.bin"
284c11a4d2cSYinan Xu        return [os.path.join(self.args.am_home, "apps", bench, "build", filename)]
285c11a4d2cSYinan Xu
286c11a4d2cSYinan Xu    def __get_ci_workloads(self, name):
287c11a4d2cSYinan Xu        workloads = {
288c11a4d2cSYinan Xu            "linux-hello": "bbl.bin",
289*fac0ab56Swakafa            "linux-hello-smp": "bbl.bin",
2905092a298Szfw            "povray": "_700480000000_.gz",
2915092a298Szfw            "mcf": "_17520000000_.gz",
2925092a298Szfw            "xalancbmk": "_266100000000_.gz",
2935092a298Szfw            "gcc": "_39720000000_.gz",
2945092a298Szfw            "namd": "_434640000000_.gz",
2955092a298Szfw            "milc": "_103620000000_.gz",
2965092a298Szfw            "lbm": "_140840000000_.gz",
2977b441e5eSYinan Xu            "gromacs": "_275480000000_.gz",
2987b441e5eSYinan Xu            "wrf": "_1916220000000_.gz",
2997b441e5eSYinan Xu            "astar": "_122060000000_.gz"
300c11a4d2cSYinan Xu        }
301da3b568bSYinan Xu        return [os.path.join("/nfs/home/share/ci-workloads", name, workloads[name])]
302c11a4d2cSYinan Xu
303c11a4d2cSYinan Xu    def run_ci(self, test):
304c11a4d2cSYinan Xu        all_tests = {
305c11a4d2cSYinan Xu            "cputest": self.__get_ci_cputest,
306c11a4d2cSYinan Xu            "riscv-tests": self.__get_ci_rvtest,
307675acc68SYinan Xu            "misc-tests": self.__get_ci_misc,
308ef3b5b96SWilliam Wang            "mc-tests": self.__get_ci_mc,
3099c297294SWilliam Wang            "nodiff-tests": self.__get_ci_nodiff,
310c11a4d2cSYinan Xu            "microbench": self.__am_apps_path,
311c11a4d2cSYinan Xu            "coremark": self.__am_apps_path
312c11a4d2cSYinan Xu        }
313c11a4d2cSYinan Xu        for target in all_tests.get(test, self.__get_ci_workloads)(test):
314c11a4d2cSYinan Xu            print(target)
315c11a4d2cSYinan Xu            ret = self.run_emu(target)
316c11a4d2cSYinan Xu            if ret:
31724e2eab6SJinYue                if self.args.default_wave_home != self.args.wave_home:
31824e2eab6SJinYue                    print("copy wave file to " + self.args.wave_home)
31924e2eab6SJinYue                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.vcd $WAVE_HOME")
320bc063562SLemover                    self.__exec_cmd(f"cp $NOOP_HOME/build/emu $WAVE_HOME")
321bc063562SLemover                    self.__exec_cmd(f"cp $NOOP_HOME/build/SimTop.v $WAVE_HOME")
322c11a4d2cSYinan Xu                return ret
323c11a4d2cSYinan Xu        return 0
324c11a4d2cSYinan Xu
32594e266cbSYinan Xudef get_free_cores(n):
32694e266cbSYinan Xu    while True:
32794e266cbSYinan Xu        # To avoid potential conflicts, we allow CI to use SMT.
32894e266cbSYinan Xu        num_logical_core = psutil.cpu_count(logical=True)
32994e266cbSYinan Xu        core_usage = psutil.cpu_percent(interval=1, percpu=True)
33094e266cbSYinan Xu        num_window = num_logical_core // n
33194e266cbSYinan Xu        for i in range(num_window):
33294e266cbSYinan Xu            window_usage = core_usage[i * n : i * n + n]
33394e266cbSYinan Xu            if sum(window_usage) < 0.3 * n and True not in map(lambda x: x > 0.5, window_usage):
33494e266cbSYinan Xu                return (((i * n) % 128)// 64, i * n, i * n + n - 1)
33594e266cbSYinan Xu        print(f"No free {n} cores found. CPU usage: {core_usage}\n")
33694e266cbSYinan Xu
337c11a4d2cSYinan Xuif __name__ == "__main__":
338c11a4d2cSYinan Xu    parser = argparse.ArgumentParser(description='Python wrapper for XiangShan')
339c11a4d2cSYinan Xu    parser.add_argument('workload', nargs='?', type=str, default="",
340c11a4d2cSYinan Xu                        help='input workload file in binary format')
341c11a4d2cSYinan Xu    # actions
342c11a4d2cSYinan Xu    parser.add_argument('--build', action='store_true', help='build XS emu')
343c11a4d2cSYinan Xu    parser.add_argument('--generate', action='store_true', help='generate XS verilog')
344c11a4d2cSYinan Xu    parser.add_argument('--ci', nargs='?', type=str, const="", help='run CI tests')
345ef3b5b96SWilliam Wang    parser.add_argument('--clean', action='store_true', help='clean up XiangShan CI workspace')
346c11a4d2cSYinan Xu    # environment variables
347c11a4d2cSYinan Xu    parser.add_argument('--nemu', nargs='?', type=str, help='path to nemu')
348c11a4d2cSYinan Xu    parser.add_argument('--am', nargs='?', type=str, help='path to nexus-am')
349c11a4d2cSYinan Xu    parser.add_argument('--dramsim3', nargs='?', type=str, help='path to dramsim3')
350c11a4d2cSYinan Xu    parser.add_argument('--rvtest', nargs='?', type=str, help='path to riscv-tests')
35124e2eab6SJinYue    parser.add_argument('--wave-dump', nargs='?', type=str , help='path to dump wave')
352c11a4d2cSYinan Xu    # chisel arguments
3531545277aSYinan Xu    parser.add_argument('--enable-log', action='store_true', help='enable log')
3545ef7374fSLi Qianruo    parser.add_argument('--num-cores', type=int, help='number of cores')
355c11a4d2cSYinan Xu    # makefile arguments
3561545277aSYinan Xu    parser.add_argument('--release', action='store_true', help='enable release')
357c11a4d2cSYinan Xu    parser.add_argument('--with-dramsim3', action='store_true', help='enable dramsim3')
358c11a4d2cSYinan Xu    parser.add_argument('--threads', nargs='?', type=int, help='number of emu threads')
359c11a4d2cSYinan Xu    parser.add_argument('--trace', action='store_true', help='enable waveform')
3606c0058d3SYinan Xu    parser.add_argument('--config', nargs='?', type=str, help='config')
361c11a4d2cSYinan Xu    # emu arguments
362c11a4d2cSYinan Xu    parser.add_argument('--numa', action='store_true', help='use numactl')
363f9930da0SYinan Xu    parser.add_argument('--diff', nargs='?', default="./ready-to-run/riscv64-nemu-interpreter-so", type=str, help='nemu so')
364c11a4d2cSYinan Xu    parser.add_argument('--max-instr', nargs='?', type=int, help='max instr')
365078fde2bSJinYue    parser.add_argument('--disable-fork', action='store_true', help='disable lightSSS')
3669c297294SWilliam Wang    parser.add_argument('--no-diff', action='store_true', help='disable difftest')
36724e2eab6SJinYue    # ci action head sha
368c11a4d2cSYinan Xu
369c11a4d2cSYinan Xu    args = parser.parse_args()
370c11a4d2cSYinan Xu
371c11a4d2cSYinan Xu    xs = XiangShan(args)
372c11a4d2cSYinan Xu    ret = xs.run(args)
373c11a4d2cSYinan Xu
374c11a4d2cSYinan Xu    sys.exit(ret)
375