xref: /XiangShan/scripts/xiangshan.py (revision f9277093a624565ca17d8d26b7636647ed8c1dc0)
1c6d43980SLemover#***************************************************************************************
254cc3a06STang Haojin# Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC)
354cc3a06STang Haojin# Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences
4f320e0f0SYinan Xu# Copyright (c) 2020-2021 Peng Cheng Laboratory
5c6d43980SLemover#
6c6d43980SLemover# XiangShan is licensed under Mulan PSL v2.
7c6d43980SLemover# You can use this software according to the terms and conditions of the Mulan PSL v2.
8c6d43980SLemover# You may obtain a copy of Mulan PSL v2 at:
9c6d43980SLemover#          http://license.coscl.org.cn/MulanPSL2
10c6d43980SLemover#
11c6d43980SLemover# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12c6d43980SLemover# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13c6d43980SLemover# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14c6d43980SLemover#
15c6d43980SLemover# See the Mulan PSL v2 for more details.
16c6d43980SLemover#***************************************************************************************
17c6d43980SLemover
18c11a4d2cSYinan Xu# Simple version of xiangshan python wrapper
19c11a4d2cSYinan Xu
20c11a4d2cSYinan Xuimport argparse
219f32a80dSYinan Xuimport json
2259bcbb59SYinan Xuimport os
2359bcbb59SYinan Xuimport random
249f32a80dSYinan Xuimport signal
25c11a4d2cSYinan Xuimport subprocess
2659bcbb59SYinan Xuimport sys
275ef7374fSLi Qianruoimport time
289810c04aSYangyu Chenimport shlex
2994e266cbSYinan Xuimport psutil
30a941bfc4STang Haojinimport re
31c11a4d2cSYinan Xu
32fcefab32SHaojin Tangdef find_files_with_suffix(root_dir, suffixes):
33fcefab32SHaojin Tang    matching_files = []
34fcefab32SHaojin Tang    for dirpath, _, filenames in os.walk(root_dir):
35fcefab32SHaojin Tang        for filename in filenames:
36fcefab32SHaojin Tang            if any(filename.endswith(suffix) for suffix in suffixes):
37fcefab32SHaojin Tang                absolute_path = os.path.join(dirpath, filename)
38fcefab32SHaojin Tang                matching_files.append(absolute_path)
39fcefab32SHaojin Tang    return matching_files
40fcefab32SHaojin Tang
41fcefab32SHaojin Tangdef load_all_gcpt(gcpt_paths):
429f32a80dSYinan Xu    all_gcpt = []
43fcefab32SHaojin Tang    for gcpt_path in gcpt_paths:
44fcefab32SHaojin Tang        all_gcpt.extend(find_files_with_suffix(gcpt_path, ['.zstd', '.gz']))
459f32a80dSYinan Xu    return all_gcpt
469f32a80dSYinan Xu
47c11a4d2cSYinan Xuclass XSArgs(object):
48c11a4d2cSYinan Xu    script_path = os.path.realpath(__file__)
49c11a4d2cSYinan Xu    # default path to the repositories
50c11a4d2cSYinan Xu    noop_home = os.path.join(os.path.dirname(script_path), "..")
51c11a4d2cSYinan Xu    nemu_home = os.path.join(noop_home, "../NEMU")
52c11a4d2cSYinan Xu    am_home = os.path.join(noop_home, "../nexus-am")
53c11a4d2cSYinan Xu    dramsim3_home = os.path.join(noop_home, "../DRAMsim3")
54c11a4d2cSYinan Xu    rvtest_home = os.path.join(noop_home, "../riscv-tests")
5524e2eab6SJinYue    default_wave_home = os.path.join(noop_home, "build")
5624e2eab6SJinYue    wave_home   = default_wave_home
57c11a4d2cSYinan Xu
58c11a4d2cSYinan Xu    def __init__(self, args):
59c11a4d2cSYinan Xu        # all path environment variables that should be set
60c11a4d2cSYinan Xu        all_path = [
61c11a4d2cSYinan Xu            # (python argument, environment variable, default, target function)
62c11a4d2cSYinan Xu            (None, "NOOP_HOME", self.noop_home, self.set_noop_home),
63c11a4d2cSYinan Xu            (args.nemu, "NEMU_HOME", self.nemu_home, self.set_nemu_home),
64c11a4d2cSYinan Xu            (args.am, "AM_HOME", self.am_home, self.set_am_home),
65c11a4d2cSYinan Xu            (args.dramsim3, "DRAMSIM3_HOME", self.dramsim3_home, self.set_dramsim3_home),
66c11a4d2cSYinan Xu            (args.rvtest, "RVTEST_HOME", self.rvtest_home, self.set_rvtest_home),
67c11a4d2cSYinan Xu        ]
68c11a4d2cSYinan Xu        for (arg_in, env, default, set_func) in all_path:
69c11a4d2cSYinan Xu            set_func(self.__extract_path(arg_in, env, default))
70c11a4d2cSYinan Xu        # Chisel arguments
711545277aSYinan Xu        self.enable_log = args.enable_log
725ef7374fSLi Qianruo        self.num_cores = args.num_cores
73c11a4d2cSYinan Xu        # Makefile arguments
74c11a4d2cSYinan Xu        self.threads = args.threads
75c11a4d2cSYinan Xu        self.with_dramsim3 = 1 if args.with_dramsim3 else None
761545277aSYinan Xu        self.is_release = 1 if args.release else None
777d45a146SYinan Xu        self.is_spike = "Spike" if args.spike else None
7840f31726Sgood-circle        self.trace = 1 if args.trace or not args.disable_fork and not args.trace_fst else None
7940f31726Sgood-circle        self.trace_fst = "fst" if args.trace_fst else None
806c0058d3SYinan Xu        self.config = args.config
815bd65c56STang Haojin        self.yaml_config = args.yaml_config
82453674e0STang Haojin        self.emu_optimize = args.emu_optimize
8354cc3a06STang Haojin        self.xprop = 1 if args.xprop else None
8428bf0330STang Haojin        self.issue = args.issue
850b62a2fbSChen Xi        self.with_chiseldb = 0 if args.no_db else 1
86c11a4d2cSYinan Xu        # emu arguments
87c11a4d2cSYinan Xu        self.max_instr = args.max_instr
8825ac26c6SWilliam Wang        self.ram_size = args.ram_size
8959bcbb59SYinan Xu        self.seed = random.randint(0, 9999)
90c11a4d2cSYinan Xu        self.numa = args.numa
91f9930da0SYinan Xu        self.diff = args.diff
9238e9143dSYinan Xu        if args.spike and "nemu" in args.diff:
9338e9143dSYinan Xu            self.diff = self.diff.replace("nemu-interpreter", "spike")
94078fde2bSJinYue        self.fork = not args.disable_fork
959c297294SWilliam Wang        self.disable_diff = args.no_diff
96e3cd2c1fSwakafa        self.disable_db = args.no_db
97bc247239SXuan Hu        self.gcpt_restore_bin = args.gcpt_restore_bin
989810c04aSYangyu Chen        self.pgo = args.pgo
999810c04aSYangyu Chen        self.pgo_max_cycle = args.pgo_max_cycle
1009810c04aSYangyu Chen        self.pgo_emu_args = args.pgo_emu_args
1019810c04aSYangyu Chen        self.llvm_profdata = args.llvm_profdata
10224e2eab6SJinYue        # wave dump path
10324e2eab6SJinYue        if args.wave_dump is not None:
10424e2eab6SJinYue            self.set_wave_home(args.wave_dump)
10524e2eab6SJinYue        else:
10624e2eab6SJinYue            self.set_wave_home(self.default_wave_home)
107c11a4d2cSYinan Xu
108c11a4d2cSYinan Xu    def get_env_variables(self):
109c11a4d2cSYinan Xu        all_env = {
110c11a4d2cSYinan Xu            "NOOP_HOME"    : self.noop_home,
111c11a4d2cSYinan Xu            "NEMU_HOME"    : self.nemu_home,
11224e2eab6SJinYue            "WAVE_HOME"    : self.wave_home,
113c11a4d2cSYinan Xu            "AM_HOME"      : self.am_home,
114e5597226Swakafa            "DRAMSIM3_HOME": self.dramsim3_home,
115e5597226Swakafa            "MODULEPATH": "/usr/share/Modules/modulefiles:/etc/modulefiles"
116c11a4d2cSYinan Xu        }
117c11a4d2cSYinan Xu        return all_env
118c11a4d2cSYinan Xu
119c11a4d2cSYinan Xu    def get_chisel_args(self, prefix=None):
120d3126fd3STang Haojin        chisel_args = [
1211545277aSYinan Xu            (self.enable_log, "enable-log")
122c11a4d2cSYinan Xu        ]
123d3126fd3STang Haojin        args = map(lambda x: x[1], filter(lambda arg: arg[0], chisel_args))
124c11a4d2cSYinan Xu        if prefix is not None:
125c11a4d2cSYinan Xu            args = map(lambda x: prefix + x, args)
126c11a4d2cSYinan Xu        return args
127c11a4d2cSYinan Xu
128c11a4d2cSYinan Xu    def get_makefile_args(self):
129c11a4d2cSYinan Xu        makefile_args = [
130c11a4d2cSYinan Xu            (self.threads,       "EMU_THREADS"),
131c11a4d2cSYinan Xu            (self.with_dramsim3, "WITH_DRAMSIM3"),
1321545277aSYinan Xu            (self.is_release,    "RELEASE"),
13338e9143dSYinan Xu            (self.is_spike,      "REF"),
1346c0058d3SYinan Xu            (self.trace,         "EMU_TRACE"),
13540f31726Sgood-circle            (self.trace_fst,     "EMU_TRACE"),
1365ef7374fSLi Qianruo            (self.config,        "CONFIG"),
137084afb77STang Haojin            (self.num_cores,     "NUM_CORES"),
13854cc3a06STang Haojin            (self.emu_optimize,  "EMU_OPTIMIZE"),
13954cc3a06STang Haojin            (self.xprop,         "ENABLE_XPROP"),
1409810c04aSYangyu Chen            (self.with_chiseldb, "WITH_CHISELDB"),
1415bd65c56STang Haojin            (self.yaml_config,   "YAML_CONFIG"),
1429810c04aSYangyu Chen            (self.pgo,           "PGO_WORKLOAD"),
1439810c04aSYangyu Chen            (self.pgo_max_cycle, "PGO_MAX_CYCLE"),
1449810c04aSYangyu Chen            (self.pgo_emu_args,  "PGO_EMU_ARGS"),
1459810c04aSYangyu Chen            (self.llvm_profdata, "LLVM_PROFDATA"),
14628bf0330STang Haojin            (self.issue,         "ISSUE"),
147c11a4d2cSYinan Xu        ]
148c11a4d2cSYinan Xu        args = filter(lambda arg: arg[0] is not None, makefile_args)
1499810c04aSYangyu Chen        args = [(shlex.quote(str(arg[0])), arg[1]) for arg in args] # shell escape
150c11a4d2cSYinan Xu        return args
151c11a4d2cSYinan Xu
152c11a4d2cSYinan Xu    def get_emu_args(self):
153c11a4d2cSYinan Xu        emu_args = [
15459bcbb59SYinan Xu            (self.max_instr, "max-instr"),
155f9930da0SYinan Xu            (self.diff,      "diff"),
15625ac26c6SWilliam Wang            (self.seed,      "seed"),
15725ac26c6SWilliam Wang            (self.ram_size,  "ram-size"),
158c11a4d2cSYinan Xu        ]
159c11a4d2cSYinan Xu        args = filter(lambda arg: arg[0] is not None, emu_args)
160c11a4d2cSYinan Xu        return args
161c11a4d2cSYinan Xu
162c11a4d2cSYinan Xu    def show(self):
163c11a4d2cSYinan Xu        print("Extra environment variables:")
164c11a4d2cSYinan Xu        env = self.get_env_variables()
165c11a4d2cSYinan Xu        for env_name in env:
166c11a4d2cSYinan Xu            print(f"{env_name}: {env[env_name]}")
167c11a4d2cSYinan Xu        print()
168c11a4d2cSYinan Xu        print("Chisel arguments:")
169c11a4d2cSYinan Xu        print(" ".join(self.get_chisel_args()))
170c11a4d2cSYinan Xu        print()
171c11a4d2cSYinan Xu        print("Makefile arguments:")
172c11a4d2cSYinan Xu        for val, name in self.get_makefile_args():
173c11a4d2cSYinan Xu            print(f"{name}={val}")
174c11a4d2cSYinan Xu        print()
175c11a4d2cSYinan Xu        print("emu arguments:")
176c11a4d2cSYinan Xu        for val, name in self.get_emu_args():
177c11a4d2cSYinan Xu            print(f"--{name} {val}")
178c11a4d2cSYinan Xu        print()
179c11a4d2cSYinan Xu
180c11a4d2cSYinan Xu    def __extract_path(self, path, env=None, default=None):
181c11a4d2cSYinan Xu        if path is None and env is not None:
182c11a4d2cSYinan Xu            path = os.getenv(env)
183c11a4d2cSYinan Xu        if path is None and default is not None:
184c11a4d2cSYinan Xu            path = default
185c11a4d2cSYinan Xu        path = os.path.realpath(path)
186c11a4d2cSYinan Xu        return path
187c11a4d2cSYinan Xu
188c11a4d2cSYinan Xu    def set_noop_home(self, path):
189c11a4d2cSYinan Xu        self.noop_home = path
190c11a4d2cSYinan Xu
191c11a4d2cSYinan Xu    def set_nemu_home(self, path):
192c11a4d2cSYinan Xu        self.nemu_home = path
193c11a4d2cSYinan Xu
194c11a4d2cSYinan Xu    def set_am_home(self, path):
195c11a4d2cSYinan Xu        self.am_home = path
196c11a4d2cSYinan Xu
197c11a4d2cSYinan Xu    def set_dramsim3_home(self, path):
198c11a4d2cSYinan Xu        self.dramsim3_home = path
199c11a4d2cSYinan Xu
200c11a4d2cSYinan Xu    def set_rvtest_home(self, path):
201c11a4d2cSYinan Xu        self.rvtest_home = path
202c11a4d2cSYinan Xu
20324e2eab6SJinYue    def set_wave_home(self, path):
20424e2eab6SJinYue        print(f"set wave home to {path}")
20524e2eab6SJinYue        self.wave_home = path
20624e2eab6SJinYue
207c11a4d2cSYinan Xu# XiangShan environment
208c11a4d2cSYinan Xuclass XiangShan(object):
209c11a4d2cSYinan Xu    def __init__(self, args):
210c11a4d2cSYinan Xu        self.args = XSArgs(args)
2119f32a80dSYinan Xu        self.timeout = args.timeout
212c11a4d2cSYinan Xu
213c11a4d2cSYinan Xu    def show(self):
214c11a4d2cSYinan Xu        self.args.show()
215c11a4d2cSYinan Xu
216ef3b5b96SWilliam Wang    def make_clean(self):
217ef3b5b96SWilliam Wang        print("Clean up CI workspace")
218ef3b5b96SWilliam Wang        self.show()
219ef3b5b96SWilliam Wang        return_code = self.__exec_cmd(f'make -C $NOOP_HOME clean')
220ef3b5b96SWilliam Wang        return return_code
221ef3b5b96SWilliam Wang
222c11a4d2cSYinan Xu    def generate_verilog(self):
223c11a4d2cSYinan Xu        print("Generating XiangShan verilog with the following configurations:")
224c11a4d2cSYinan Xu        self.show()
225c11a4d2cSYinan Xu        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
226c11a4d2cSYinan Xu        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
227c11a4d2cSYinan Xu        return_code = self.__exec_cmd(f'make -C $NOOP_HOME verilog SIM_ARGS="{sim_args}" {make_args}')
228c11a4d2cSYinan Xu        return return_code
229c11a4d2cSYinan Xu
230e5597226Swakafa    def generate_sim_verilog(self):
231e5597226Swakafa        print("Generating XiangShan sim-verilog with the following configurations:")
232e5597226Swakafa        self.show()
233e5597226Swakafa        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
234e5597226Swakafa        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
235e5597226Swakafa        return_code = self.__exec_cmd(f'make -C $NOOP_HOME sim-verilog SIM_ARGS="{sim_args}" {make_args}')
236e5597226Swakafa        return return_code
237e5597226Swakafa
238c11a4d2cSYinan Xu    def build_emu(self):
239c11a4d2cSYinan Xu        print("Building XiangShan emu with the following configurations:")
240c11a4d2cSYinan Xu        self.show()
241c11a4d2cSYinan Xu        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
242c11a4d2cSYinan Xu        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
243a3e87608SWilliam Wang        return_code = self.__exec_cmd(f'make -C $NOOP_HOME emu -j200 SIM_ARGS="{sim_args}" {make_args}')
244c11a4d2cSYinan Xu        return return_code
245c11a4d2cSYinan Xu
246e5597226Swakafa    def build_simv(self):
247e5597226Swakafa        print("Building XiangShan simv with the following configurations")
248e5597226Swakafa        self.show()
249e5597226Swakafa        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
250e5597226Swakafa        # TODO: make the following commands grouped as unseen scripts
251e5597226Swakafa        return_code = self.__exec_cmd(f'\
252e5597226Swakafa            eval `/usr/bin/modulecmd zsh load license`;\
253e5597226Swakafa            eval `/usr/bin/modulecmd zsh load synopsys/vcs/Q-2020.03-SP2`;\
254e5597226Swakafa            eval `/usr/bin/modulecmd zsh load synopsys/verdi/S-2021.09-SP1`;\
255e5597226Swakafa            VERDI_HOME=/nfs/tools/synopsys/verdi/S-2021.09-SP1 \
256e5597226Swakafa            make -C $NOOP_HOME simv {make_args} CONSIDER_FSDB=1')  # set CONSIDER_FSDB for compatibility
257e5597226Swakafa        return return_code
258e5597226Swakafa
259c11a4d2cSYinan Xu    def run_emu(self, workload):
260c11a4d2cSYinan Xu        print("Running XiangShan emu with the following configurations:")
261c11a4d2cSYinan Xu        self.show()
262c11a4d2cSYinan Xu        emu_args = " ".join(map(lambda arg: f"--{arg[1]} {arg[0]}", self.args.get_emu_args()))
263c11a4d2cSYinan Xu        print("workload:", workload)
264c9d90c8dSYinan Xu        numa_args = ""
265c9d90c8dSYinan Xu        if self.args.numa:
26694e266cbSYinan Xu            numa_info = get_free_cores(self.args.threads)
267c9d90c8dSYinan Xu            numa_args = f"numactl -m {numa_info[0]} -C {numa_info[1]}-{numa_info[2]}"
26875ed9f4bSTang Haojin        fork_args = "--enable-fork" if self.args.fork else ""
2699c297294SWilliam Wang        diff_args = "--no-diff" if self.args.disable_diff else ""
270e3cd2c1fSwakafa        chiseldb_args = "--dump-db" if not self.args.disable_db else ""
271bc247239SXuan Hu        gcpt_restore_args = f"-r {self.args.gcpt_restore_bin}" if len(self.args.gcpt_restore_bin) != 0 else ""
272bc247239SXuan Hu        return_code = self.__exec_cmd(f'ulimit -s {32 * 1024}; {numa_args} $NOOP_HOME/build/emu -i {workload} {emu_args} {fork_args} {diff_args} {chiseldb_args} {gcpt_restore_args}')
273c11a4d2cSYinan Xu        return return_code
274c11a4d2cSYinan Xu
275e5597226Swakafa    def run_simv(self, workload):
276e5597226Swakafa        print("Running XiangShan simv with the following configurations:")
277e5597226Swakafa        self.show()
278e5597226Swakafa        diff_args = "$NOOP_HOME/"+ args.diff
27954cc3a06STang Haojin        assert_args = "-assert finish_maxfail=30 -assert global_finish_maxfail=10000"
280ae0295f4STang Haojin        return_code = self.__exec_cmd(f'cd $NOOP_HOME/build && ./simv +workload={workload} +diff={diff_args} +dump-wave=fsdb {assert_args} | tee simv.log')
281823787d8STang Haojin        with open(f"{self.args.noop_home}/build/simv.log") as f:
282ae0295f4STang Haojin            content = f.read()
283ae0295f4STang Haojin            if "Offending" in content or "HIT GOOD TRAP" not in content:
284823787d8STang Haojin                return 1
285ae0295f4STang Haojin        return return_code
286e5597226Swakafa
287c11a4d2cSYinan Xu    def run(self, args):
288c11a4d2cSYinan Xu        if args.ci is not None:
289c11a4d2cSYinan Xu            return self.run_ci(args.ci)
290e5597226Swakafa        if args.ci_vcs is not None:
291e5597226Swakafa            return self.run_ci_vcs(args.ci_vcs)
292c11a4d2cSYinan Xu        actions = [
293c11a4d2cSYinan Xu            (args.generate, lambda _ : self.generate_verilog()),
294e5597226Swakafa            (args.vcs_gen, lambda _ : self.generate_sim_verilog()),
295c11a4d2cSYinan Xu            (args.build, lambda _ : self.build_emu()),
296e5597226Swakafa            (args.vcs_build, lambda _ : self.build_simv()),
297ef3b5b96SWilliam Wang            (args.workload, lambda args: self.run_emu(args.workload)),
298ef3b5b96SWilliam Wang            (args.clean, lambda _ : self.make_clean())
299c11a4d2cSYinan Xu        ]
300c11a4d2cSYinan Xu        valid_actions = map(lambda act: act[1], filter(lambda act: act[0], actions))
301c11a4d2cSYinan Xu        for i, action in enumerate(valid_actions):
302c11a4d2cSYinan Xu            print(f"Action {i}:")
303c11a4d2cSYinan Xu            ret = action(args)
304c11a4d2cSYinan Xu            if ret:
305c11a4d2cSYinan Xu                return ret
306c11a4d2cSYinan Xu        return 0
307c11a4d2cSYinan Xu
308c11a4d2cSYinan Xu    def __exec_cmd(self, cmd):
309c11a4d2cSYinan Xu        env = dict(os.environ)
310c11a4d2cSYinan Xu        env.update(self.args.get_env_variables())
311c11a4d2cSYinan Xu        print("subprocess call cmd:", cmd)
3125ef7374fSLi Qianruo        start = time.time()
3139f32a80dSYinan Xu        proc = subprocess.Popen(cmd, shell=True, env=env, preexec_fn=os.setsid)
3149f32a80dSYinan Xu        try:
3159f32a80dSYinan Xu            return_code = proc.wait(self.timeout)
3165ef7374fSLi Qianruo            end = time.time()
3175ef7374fSLi Qianruo            print(f"Elapsed time: {end - start} seconds")
318c11a4d2cSYinan Xu            return return_code
3199f32a80dSYinan Xu        except (KeyboardInterrupt, subprocess.TimeoutExpired):
3209f32a80dSYinan Xu            os.killpg(os.getpgid(proc.pid), signal.SIGINT)
3219f32a80dSYinan Xu            print(f"KeyboardInterrupt or TimeoutExpired.")
3229f32a80dSYinan Xu            return 0
323c11a4d2cSYinan Xu
324c11a4d2cSYinan Xu    def __get_ci_cputest(self, name=None):
3250d7009bfSXu, Zefan        # base_dir = os.path.join(self.args.am_home, "tests/cputest/build")
3260d7009bfSXu, Zefan        base_dir = "/nfs/home/share/ci-workloads/nexus-am-workloads/tests/cputest"
327c11a4d2cSYinan Xu        cputest = os.listdir(base_dir)
328c11a4d2cSYinan Xu        cputest = filter(lambda x: x.endswith(".bin"), cputest)
329c11a4d2cSYinan Xu        cputest = map(lambda x: os.path.join(base_dir, x), cputest)
330c11a4d2cSYinan Xu        return cputest
331c11a4d2cSYinan Xu
332c11a4d2cSYinan Xu    def __get_ci_rvtest(self, name=None):
333c11a4d2cSYinan Xu        base_dir = os.path.join(self.args.rvtest_home, "isa/build")
334c11a4d2cSYinan Xu        riscv_tests = os.listdir(base_dir)
335c11a4d2cSYinan Xu        riscv_tests = filter(lambda x: x.endswith(".bin"), riscv_tests)
33641d8d239Shappy-lx        all_rv_tests = ["rv64ui", "rv64um", "rv64ua", "rv64uf", "rv64ud", "rv64mi"]
337c11a4d2cSYinan Xu        riscv_tests = filter(lambda x: x[:6] in all_rv_tests, riscv_tests)
338c11a4d2cSYinan Xu        riscv_tests = map(lambda x: os.path.join(base_dir, x), riscv_tests)
339c11a4d2cSYinan Xu        return riscv_tests
340c11a4d2cSYinan Xu
341675acc68SYinan Xu    def __get_ci_misc(self, name=None):
342da3b568bSYinan Xu        base_dir = "/nfs/home/share/ci-workloads"
343675acc68SYinan Xu        workloads = [
344675acc68SYinan Xu            "bitmanip/bitMisc.bin",
3453feeca58Szfw            "crypto/crypto-riscv64-noop.bin",
3460d7009bfSXu, Zefan            # "coremark_rv64gc_o2/coremark-riscv64-xs.bin",
3470d7009bfSXu, Zefan            # "coremark_rv64gc_o3/coremark-riscv64-xs.bin",
3480d7009bfSXu, Zefan            # "coremark_rv64gcb_o3/coremark-riscv64-xs.bin",
3490d7009bfSXu, Zefan            "nexus-am-workloads/amtest/external_intr-riscv64-xs.bin",
3500d7009bfSXu, Zefan            "nexus-am-workloads/tests/aliastest/aliastest-riscv64-xs.bin",
351af2f7849Shappy-lx            "Svinval/rv64mi-p-svinval.bin",
352b6982e83SLemover            "pmp/pmp.riscv.bin",
3530d7009bfSXu, Zefan            "nexus-am-workloads/amtest/pmp_test-riscv64-xs.bin",
3540d7009bfSXu, Zefan            "nexus-am-workloads/amtest/sv39_hp_atom_test-riscv64-xs.bin",
35545f497a4Shappy-lx            "asid/asid.bin",
3567d9edc86SLemover            "isa_misc/xret_clear_mprv.bin",
357705cbec3SLemover            "isa_misc/satp_ppn.bin",
358ad15bdb2SNewPaulWalker            "cache-management/softprefetchtest-riscv64-xs.bin",
3594293ded2Slinzhida            "smstateen/rvh_test.bin",
360f346d727SYanqin Li            "zacas/zacas-riscv64-xs.bin",
361718a93f5SHaoyuan Feng            "Svpbmt/rvh_test.bin",
3626520f4f4STang Haojin            "Svnapot/svnapot-test.bin",
3636520f4f4STang Haojin            "Zawrs/Zawrs-zawrs.bin"
364675acc68SYinan Xu        ]
365675acc68SYinan Xu        misc_tests = map(lambda x: os.path.join(base_dir, x), workloads)
366675acc68SYinan Xu        return misc_tests
367675acc68SYinan Xu
3681f903014SXu, Zefan    def __get_ci_rvhtest(self, name=None):
3691f903014SXu, Zefan        base_dir = "/nfs/home/share/ci-workloads/H-extension-tests"
3701f903014SXu, Zefan        workloads = [
371afdeb382SXu, Zefan            "riscv-hyp-tests/rvh_test.bin",
3721f903014SXu, Zefan            "xvisor_wboxtest/checkpoint.gz",
373189833a1SHaoyuan Feng            "pointer-masking-test/M_HS_test/rvh_test.bin",
374189833a1SHaoyuan Feng            "pointer-masking-test/U_test/hint_UMode_hupmm2/rvh_test.bin",
375189833a1SHaoyuan Feng            "pointer-masking-test/U_test/vu_senvcfgpmm2/rvh_test.bin"
3761f903014SXu, Zefan        ]
3771f903014SXu, Zefan        rvh_tests = map(lambda x: os.path.join(base_dir, x), workloads)
3781f903014SXu, Zefan        return rvh_tests
3791f903014SXu, Zefan
3806ebd27e9Slwd    def __get_ci_rvvbench(self, name=None):
3816ebd27e9Slwd        base_dir = "/nfs/home/share/ci-workloads"
3826ebd27e9Slwd        workloads = [
3836ebd27e9Slwd            "rvv-bench/poly1305.bin",
3846ebd27e9Slwd            "rvv-bench/mergelines.bin"
3856ebd27e9Slwd        ]
3866ebd27e9Slwd        rvvbench = map(lambda x: os.path.join(base_dir, x), workloads)
3876ebd27e9Slwd        return rvvbench
3886ebd27e9Slwd
3896ebd27e9Slwd    def __get_ci_rvvtest(self, name=None):
3906ebd27e9Slwd        base_dir = "/nfs/home/share/ci-workloads/V-extension-tests"
3916ebd27e9Slwd        workloads = [
3926ebd27e9Slwd            "rvv-test/vluxei32.v-0.bin",
3936ebd27e9Slwd            "rvv-test/vlsseg4e32.v-0.bin",
3946ebd27e9Slwd            "rvv-test/vlseg4e32.v-0.bin",
3956ebd27e9Slwd            "rvv-test/vsetvl-0.bin",
3966ebd27e9Slwd            "rvv-test/vsetivli-0.bin",
3976ebd27e9Slwd            "rvv-test/vsuxei32.v-0.bin",
3986ebd27e9Slwd            "rvv-test/vse16.v-0.bin",
3996ebd27e9Slwd            "rvv-test/vsse16.v-1.bin",
4006ebd27e9Slwd            "rvv-test/vlse32.v-0.bin",
4016ebd27e9Slwd            "rvv-test/vsetvli-0.bin",
4026ebd27e9Slwd            "rvv-test/vle16.v-0.bin",
4036ebd27e9Slwd            "rvv-test/vle32.v-0.bin",
4046ebd27e9Slwd            "rvv-test/vfsgnj.vv-0.bin",
4056ebd27e9Slwd            "rvv-test/vfadd.vf-0.bin",
4066ebd27e9Slwd            "rvv-test/vfsub.vf-0.bin",
4076ebd27e9Slwd            "rvv-test/vslide1down.vx-0.bin"
4086ebd27e9Slwd        ]
4096ebd27e9Slwd        rvv_test = map(lambda x: os.path.join(base_dir, x), workloads)
4106ebd27e9Slwd        return rvv_test
4116ebd27e9Slwd
412dd16cea7SHeiHuDie    def __get_ci_F16test(self, name=None):
413dd16cea7SHeiHuDie        base_dir = "/nfs/home/share/ci-workloads/vector/F16-tests/build"
414dd16cea7SHeiHuDie        workloads = [
415dd16cea7SHeiHuDie            "rv64uzfhmin-p-fzfhmincvt.bin",
416dd16cea7SHeiHuDie            "rv64uzfh-p-fadd.bin",
417dd16cea7SHeiHuDie            "rv64uzfh-p-fclass.bin",
418dd16cea7SHeiHuDie            "rv64uzfh-p-fcmp.bin",
419dd16cea7SHeiHuDie            "rv64uzfh-p-fcvt.bin",
420dd16cea7SHeiHuDie            "rv64uzfh-p-fcvt_w.bin",
421dd16cea7SHeiHuDie            "rv64uzfh-p-fdiv.bin",
422dd16cea7SHeiHuDie            "rv64uzfh-p-fmadd.bin",
423dd16cea7SHeiHuDie            "rv64uzfh-p-fmin.bin",
424dd16cea7SHeiHuDie            "rv64uzfh-p-ldst.bin",
425dd16cea7SHeiHuDie            "rv64uzfh-p-move.bin",
426dd16cea7SHeiHuDie            "rv64uzfh-p-recoding.bin",
427dd16cea7SHeiHuDie            "rv64uzvfh-p-vfadd.bin",
428dd16cea7SHeiHuDie            "rv64uzvfh-p-vfclass.bin",
429dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtfx.bin",
430dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtfxu.bin",
431dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtrxf.bin",
432dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtrxuf.bin",
433dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtxf.bin",
434dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtxuf.bin",
435dd16cea7SHeiHuDie            "rv64uzvfh-p-vfdiv.bin",
436dd16cea7SHeiHuDie            "rv64uzvfh-p-vfdown.bin",
437dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmacc.bin",
438dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmadd.bin",
439dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmax.bin",
440dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmerge.bin",
441dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmin.bin",
442dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmsac.bin",
443dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmsub.bin",
444dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmul.bin",
445dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmv.bin",
446dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtff.bin",
447dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtfx.bin",
448dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtfxu.bin",
449dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtrff.bin",
450dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtrxf.bin",
451dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtrxuf.bin",
452dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtxf.bin",
453dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtxuf.bin",
454dd16cea7SHeiHuDie            "rv64uzvfh-p-vfnmacc.bin",
455dd16cea7SHeiHuDie            "rv64uzvfh-p-vfnmadd.bin",
456dd16cea7SHeiHuDie            "rv64uzvfh-p-vfnmsac.bin",
457dd16cea7SHeiHuDie            "rv64uzvfh-p-vfnmsub.bin",
458dd16cea7SHeiHuDie            "rv64uzvfh-p-vfrdiv.bin",
459dd16cea7SHeiHuDie            "rv64uzvfh-p-vfrec7.bin",
460dd16cea7SHeiHuDie            "rv64uzvfh-p-vfredmax.bin",
461dd16cea7SHeiHuDie            "rv64uzvfh-p-vfredmin.bin",
462dd16cea7SHeiHuDie            "rv64uzvfh-p-vfredosum.bin",
463dd16cea7SHeiHuDie            "rv64uzvfh-p-vfredusum.bin",
464dd16cea7SHeiHuDie            "rv64uzvfh-p-vfrsqrt7.bin",
465dd16cea7SHeiHuDie            "rv64uzvfh-p-vfrsub.bin",
466dd16cea7SHeiHuDie            "rv64uzvfh-p-vfsgnj.bin",
467dd16cea7SHeiHuDie            "rv64uzvfh-p-vfsgnjn.bin",
468dd16cea7SHeiHuDie            "rv64uzvfh-p-vfsgnjx.bin",
469dd16cea7SHeiHuDie            "rv64uzvfh-p-vfsqrt.bin",
470dd16cea7SHeiHuDie            "rv64uzvfh-p-vfsub.bin",
471dd16cea7SHeiHuDie            "rv64uzvfh-p-vfup.bin",
472dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwadd.bin",
473dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwadd-w.bin",
474dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtff.bin",
475dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtfx.bin",
476dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtfxu.bin",
477dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtrxf.bin",
478dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtrxuf.bin",
479dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtxf.bin",
480dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtxuf.bin",
481dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwmacc.bin",
482dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwmsac.bin",
483dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwmul.bin",
484dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwnmacc.bin",
485dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwnmsac.bin",
486dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwredosum.bin",
487dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwredusum.bin",
488dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwsub.bin",
489dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwsub-w.bin",
490dd16cea7SHeiHuDie            "rv64uzvfh-p-vmfeq.bin",
491dd16cea7SHeiHuDie            "rv64uzvfh-p-vmfge.bin",
492dd16cea7SHeiHuDie            "rv64uzvfh-p-vmfgt.bin",
493dd16cea7SHeiHuDie            "rv64uzvfh-p-vmfle.bin",
494dd16cea7SHeiHuDie            "rv64uzvfh-p-vmflt.bin",
495dd16cea7SHeiHuDie            "rv64uzvfh-p-vmfne.bin"
496dd16cea7SHeiHuDie        ]
497dd16cea7SHeiHuDie        f16_test = map(lambda x: os.path.join(base_dir, x), workloads)
498dd16cea7SHeiHuDie        return f16_test
499393755c7SHuSipeng    def __get_ci_zcbtest(self, name=None):
500393755c7SHuSipeng        base_dir = "/nfs/home/share/ci-workloads/zcb-test"
501393755c7SHuSipeng        workloads = [
502393755c7SHuSipeng            "zcb-test-riscv64-xs.bin"
503393755c7SHuSipeng        ]
504393755c7SHuSipeng        zcb_test = map(lambda x: os.path.join(base_dir, x), workloads)
505393755c7SHuSipeng        return zcb_test
506dd16cea7SHeiHuDie
507ef3b5b96SWilliam Wang    def __get_ci_mc(self, name=None):
508ef3b5b96SWilliam Wang        base_dir = "/nfs/home/share/ci-workloads"
509ef3b5b96SWilliam Wang        workloads = [
5100d7009bfSXu, Zefan            "nexus-am-workloads/tests/dualcoretest/ldvio-riscv64-xs.bin"
511ef3b5b96SWilliam Wang        ]
512ef3b5b96SWilliam Wang        mc_tests = map(lambda x: os.path.join(base_dir, x), workloads)
513ef3b5b96SWilliam Wang        return mc_tests
514ef3b5b96SWilliam Wang
5159c297294SWilliam Wang    def __get_ci_nodiff(self, name=None):
516da3b568bSYinan Xu        base_dir = "/nfs/home/share/ci-workloads"
5179c297294SWilliam Wang        workloads = [
5189c297294SWilliam Wang            "cache-management/cacheoptest-riscv64-xs.bin"
5199c297294SWilliam Wang        ]
5209c297294SWilliam Wang        tests = map(lambda x: os.path.join(base_dir, x), workloads)
5219c297294SWilliam Wang        return tests
5229c297294SWilliam Wang
523c11a4d2cSYinan Xu    def __am_apps_path(self, bench):
5240d7009bfSXu, Zefan        base_dir = '/nfs/home/share/ci-workloads/nexus-am-workloads/apps'
5250d7009bfSXu, Zefan        filename = f"{bench}-riscv64-xs.bin"
5260d7009bfSXu, Zefan        return [os.path.join(base_dir, bench, filename)]
527c11a4d2cSYinan Xu
528c11a4d2cSYinan Xu    def __get_ci_workloads(self, name):
529c11a4d2cSYinan Xu        workloads = {
530c11a4d2cSYinan Xu            "linux-hello": "bbl.bin",
531fac0ab56Swakafa            "linux-hello-smp": "bbl.bin",
5324a8a734eSceba            "linux-hello-opensbi": "fw_payload.bin",
5334a8a734eSceba            "linux-hello-smp-opensbi": "fw_payload.bin",
534e975de62STang Haojin            "linux-hello-new": "bbl.bin",
535e975de62STang Haojin            "linux-hello-smp-new": "bbl.bin",
5365092a298Szfw            "povray": "_700480000000_.gz",
5375092a298Szfw            "mcf": "_17520000000_.gz",
5385092a298Szfw            "xalancbmk": "_266100000000_.gz",
5395092a298Szfw            "gcc": "_39720000000_.gz",
5405092a298Szfw            "namd": "_434640000000_.gz",
5415092a298Szfw            "milc": "_103620000000_.gz",
5425092a298Szfw            "lbm": "_140840000000_.gz",
5437b441e5eSYinan Xu            "gromacs": "_275480000000_.gz",
5447b441e5eSYinan Xu            "wrf": "_1916220000000_.gz",
545517c737eSAnzo            "astar": "_122060000000_.gz",
546517c737eSAnzo            "hmmer-Vector": "_6598_0.250135_.zstd"
547c11a4d2cSYinan Xu        }
5489f32a80dSYinan Xu        if name in workloads:
549da3b568bSYinan Xu            return [os.path.join("/nfs/home/share/ci-workloads", name, workloads[name])]
5509f32a80dSYinan Xu        # select a random SPEC checkpoint
5519f32a80dSYinan Xu        assert(name == "random")
552fcefab32SHaojin Tang        all_cpt_dir = [
55301efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec06_rv64gcb_o2_20m/take_cpt",
55401efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec06_rv64gcb_o3_20m/take_cpt",
55501efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec06_rv64gc_o2_20m/take_cpt",
55601efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec06_rv64gc_o2_50m/take_cpt",
55701efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec17_rv64gcb_o2_20m/take_cpt",
55801efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec17_rv64gcb_o3_20m/take_cpt",
55901efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec17_rv64gc_o2_50m/take_cpt",
560fcefab32SHaojin Tang            "/nfs/home/share/checkpoints_profiles/spec17_speed_rv64gcb_o3_20m/take_cpt",
561fcefab32SHaojin Tang            "/nfs/home/share/checkpoints_profiles/spec06_rv64gcb_O3_20m_gcc12.2.0-intFpcOff-jeMalloc/zstd-checkpoint-0-0-0",
562fcefab32SHaojin Tang            "/nfs/home/share/checkpoints_profiles/spec06_gcc15_rv64gcbv_O3_lto_base_nemu_single_core_NEMU_archgroup_2024-10-12-16-05/checkpoint-0-0-0"
5639f32a80dSYinan Xu        ]
564fcefab32SHaojin Tang        all_gcpt = load_all_gcpt(all_cpt_dir)
5659f32a80dSYinan Xu        return [random.choice(all_gcpt)]
566c11a4d2cSYinan Xu
567c11a4d2cSYinan Xu    def run_ci(self, test):
568c11a4d2cSYinan Xu        all_tests = {
569c11a4d2cSYinan Xu            "cputest": self.__get_ci_cputest,
570c11a4d2cSYinan Xu            "riscv-tests": self.__get_ci_rvtest,
571675acc68SYinan Xu            "misc-tests": self.__get_ci_misc,
572ef3b5b96SWilliam Wang            "mc-tests": self.__get_ci_mc,
5739c297294SWilliam Wang            "nodiff-tests": self.__get_ci_nodiff,
5741f903014SXu, Zefan            "rvh-tests": self.__get_ci_rvhtest,
575c11a4d2cSYinan Xu            "microbench": self.__am_apps_path,
5766ebd27e9Slwd            "coremark": self.__am_apps_path,
57720156f77STang Haojin            "coremark-1-iteration": self.__am_apps_path,
5786ebd27e9Slwd            "rvv-bench": self.__get_ci_rvvbench,
579dd16cea7SHeiHuDie            "rvv-test": self.__get_ci_rvvtest,
580393755c7SHuSipeng            "f16_test": self.__get_ci_F16test,
581393755c7SHuSipeng            "zcb-test": self.__get_ci_zcbtest
582c11a4d2cSYinan Xu        }
583c11a4d2cSYinan Xu        for target in all_tests.get(test, self.__get_ci_workloads)(test):
584c11a4d2cSYinan Xu            print(target)
585c11a4d2cSYinan Xu            ret = self.run_emu(target)
586c11a4d2cSYinan Xu            if ret:
58724e2eab6SJinYue                if self.args.default_wave_home != self.args.wave_home:
58824e2eab6SJinYue                    print("copy wave file to " + self.args.wave_home)
58924e2eab6SJinYue                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.vcd $WAVE_HOME")
590*f9277093STang Haojin                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.fst $WAVE_HOME")
591bc063562SLemover                    self.__exec_cmd(f"cp $NOOP_HOME/build/emu $WAVE_HOME")
59245f43e6eSTang Haojin                    self.__exec_cmd(f"cp $NOOP_HOME/build/rtl/SimTop.v $WAVE_HOME")
593e3cd2c1fSwakafa                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.db $WAVE_HOME")
594c11a4d2cSYinan Xu                return ret
595c11a4d2cSYinan Xu        return 0
596c11a4d2cSYinan Xu
597e5597226Swakafa    def run_ci_vcs(self, test):
598e5597226Swakafa        all_tests = {
599e5597226Swakafa            "cputest": self.__get_ci_cputest,
600e5597226Swakafa            "riscv-tests": self.__get_ci_rvtest,
601e5597226Swakafa            "misc-tests": self.__get_ci_misc,
602e5597226Swakafa            "mc-tests": self.__get_ci_mc,
603e5597226Swakafa            "nodiff-tests": self.__get_ci_nodiff,
6041f903014SXu, Zefan            "rvh-tests": self.__get_ci_rvhtest,
605e5597226Swakafa            "microbench": self.__am_apps_path,
6066ebd27e9Slwd            "coremark": self.__am_apps_path,
60720156f77STang Haojin            "coremark-1-iteration": self.__am_apps_path,
6086ebd27e9Slwd            "rvv-bench": self.__get_ci_rvvbench,
609dd16cea7SHeiHuDie            "rvv-test": self.__get_ci_rvvtest,
610393755c7SHuSipeng            "f16_test": self.__get_ci_F16test,
611393755c7SHuSipeng            "zcb-test": self.__get_ci_zcbtest
612e5597226Swakafa        }
613e5597226Swakafa        for target in all_tests.get(test, self.__get_ci_workloads)(test):
614e5597226Swakafa            print(target)
615e5597226Swakafa            ret = self.run_simv(target)
616e5597226Swakafa            if ret:
617e5597226Swakafa                if self.args.default_wave_home != self.args.wave_home:
618e5597226Swakafa                    print("copy wave file to " + self.args.wave_home)
61954cc3a06STang Haojin                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.fsdb $WAVE_HOME")
62054cc3a06STang Haojin                    self.__exec_cmd(f"cp $NOOP_HOME/build/simv $WAVE_HOME")
62145f43e6eSTang Haojin                    self.__exec_cmd(f"cp $NOOP_HOME/build/rtl/SimTop.v $WAVE_HOME")
622e3cd2c1fSwakafa                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.db $WAVE_HOME")
623e5597226Swakafa                return ret
624e5597226Swakafa        return 0
625e5597226Swakafa
62694e266cbSYinan Xudef get_free_cores(n):
627a941bfc4STang Haojin    numa_re = re.compile(r'.*numactl +.*-C +([0-9]+)-([0-9]+).*')
62894e266cbSYinan Xu    while True:
629a941bfc4STang Haojin        disable_cores = []
630a941bfc4STang Haojin        for proc in psutil.process_iter():
631a941bfc4STang Haojin            try:
632a941bfc4STang Haojin                joint = ' '.join(proc.cmdline())
633a941bfc4STang Haojin                numa_match = numa_re.match(joint)
634dd720caeSTang Haojin                if numa_match and 'ssh' not in proc.name():
635a941bfc4STang Haojin                    disable_cores.extend(range(int(numa_match.group(1)), int(numa_match.group(2)) + 1))
636a941bfc4STang Haojin            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
637a941bfc4STang Haojin                pass
638b86f926fSYinan Xu        num_logical_core = psutil.cpu_count(logical=False)
63994e266cbSYinan Xu        core_usage = psutil.cpu_percent(interval=1, percpu=True)
64094e266cbSYinan Xu        num_window = num_logical_core // n
64194e266cbSYinan Xu        for i in range(num_window):
642a941bfc4STang Haojin            if set(disable_cores) & set(range(i * n, i * n + n)):
643a941bfc4STang Haojin                continue
64494e266cbSYinan Xu            window_usage = core_usage[i * n : i * n + n]
64501a51437SYinan Xu            if sum(window_usage) < 30 * n and True not in map(lambda x: x > 90, window_usage):
64671f0f4ccSTang Haojin                return (((i * n) % num_logical_core) // (num_logical_core // 2), i * n, i * n + n - 1)
64794e266cbSYinan Xu        print(f"No free {n} cores found. CPU usage: {core_usage}\n")
64843f08742STang Haojin        time.sleep(random.uniform(1, 60))
64994e266cbSYinan Xu
650c11a4d2cSYinan Xuif __name__ == "__main__":
651c11a4d2cSYinan Xu    parser = argparse.ArgumentParser(description='Python wrapper for XiangShan')
652c11a4d2cSYinan Xu    parser.add_argument('workload', nargs='?', type=str, default="",
653c11a4d2cSYinan Xu                        help='input workload file in binary format')
654c11a4d2cSYinan Xu    # actions
655c11a4d2cSYinan Xu    parser.add_argument('--build', action='store_true', help='build XS emu')
656c11a4d2cSYinan Xu    parser.add_argument('--generate', action='store_true', help='generate XS verilog')
657e5597226Swakafa    parser.add_argument('--vcs-gen', action='store_true', help='generate XS sim verilog for vcs')
658e5597226Swakafa    parser.add_argument('--vcs-build', action='store_true', help='build XS simv')
659c11a4d2cSYinan Xu    parser.add_argument('--ci', nargs='?', type=str, const="", help='run CI tests')
660e5597226Swakafa    parser.add_argument('--ci-vcs', nargs='?', type=str, const="", help='run CI tests on simv')
661ef3b5b96SWilliam Wang    parser.add_argument('--clean', action='store_true', help='clean up XiangShan CI workspace')
6629f32a80dSYinan Xu    parser.add_argument('--timeout', nargs='?', type=int, default=None, help='timeout (in seconds)')
663c11a4d2cSYinan Xu    # environment variables
664c11a4d2cSYinan Xu    parser.add_argument('--nemu', nargs='?', type=str, help='path to nemu')
665c11a4d2cSYinan Xu    parser.add_argument('--am', nargs='?', type=str, help='path to nexus-am')
666c11a4d2cSYinan Xu    parser.add_argument('--dramsim3', nargs='?', type=str, help='path to dramsim3')
667c11a4d2cSYinan Xu    parser.add_argument('--rvtest', nargs='?', type=str, help='path to riscv-tests')
66824e2eab6SJinYue    parser.add_argument('--wave-dump', nargs='?', type=str , help='path to dump wave')
669c11a4d2cSYinan Xu    # chisel arguments
6701545277aSYinan Xu    parser.add_argument('--enable-log', action='store_true', help='enable log')
6715ef7374fSLi Qianruo    parser.add_argument('--num-cores', type=int, help='number of cores')
672c11a4d2cSYinan Xu    # makefile arguments
6731545277aSYinan Xu    parser.add_argument('--release', action='store_true', help='enable release')
67438e9143dSYinan Xu    parser.add_argument('--spike', action='store_true', help='enable spike diff')
675c11a4d2cSYinan Xu    parser.add_argument('--with-dramsim3', action='store_true', help='enable dramsim3')
676c11a4d2cSYinan Xu    parser.add_argument('--threads', nargs='?', type=int, help='number of emu threads')
67740f31726Sgood-circle    parser.add_argument('--trace', action='store_true', help='enable vcd waveform')
67840f31726Sgood-circle    parser.add_argument('--trace-fst', action='store_true', help='enable fst waveform')
6796c0058d3SYinan Xu    parser.add_argument('--config', nargs='?', type=str, help='config')
6805bd65c56STang Haojin    parser.add_argument('--yaml-config', nargs='?', type=str, help='yaml config')
681453674e0STang Haojin    parser.add_argument('--emu-optimize', nargs='?', type=str, help='verilator optimization letter')
68254cc3a06STang Haojin    parser.add_argument('--xprop', action='store_true', help='enable xprop for vcs')
68328bf0330STang Haojin    parser.add_argument('--issue', nargs='?', type=str, help='CHI issue')
684c11a4d2cSYinan Xu    # emu arguments
685c11a4d2cSYinan Xu    parser.add_argument('--numa', action='store_true', help='use numactl')
686f9930da0SYinan Xu    parser.add_argument('--diff', nargs='?', default="./ready-to-run/riscv64-nemu-interpreter-so", type=str, help='nemu so')
687c11a4d2cSYinan Xu    parser.add_argument('--max-instr', nargs='?', type=int, help='max instr')
688078fde2bSJinYue    parser.add_argument('--disable-fork', action='store_true', help='disable lightSSS')
6899c297294SWilliam Wang    parser.add_argument('--no-diff', action='store_true', help='disable difftest')
69025ac26c6SWilliam Wang    parser.add_argument('--ram-size', nargs='?', type=str, help='manually set simulation memory size (8GB by default)')
691bc247239SXuan Hu    parser.add_argument('--gcpt-restore-bin', type=str, default="", help="specify the bin used to restore from gcpt")
69254cc3a06STang Haojin    # both makefile and emu arguments
693e3cd2c1fSwakafa    parser.add_argument('--no-db', action='store_true', help='disable chiseldb dump')
6949810c04aSYangyu Chen    parser.add_argument('--pgo', nargs='?', type=str, help='workload for pgo (null to disable pgo)')
6959810c04aSYangyu Chen    parser.add_argument('--pgo-max-cycle', nargs='?', default=400000, type=int, help='maximun cycle to train pgo')
6969810c04aSYangyu Chen    parser.add_argument('--pgo-emu-args', nargs='?', default='--no-diff', type=str, help='emu arguments for pgo')
6979810c04aSYangyu Chen    parser.add_argument('--llvm-profdata', nargs='?', type=str, help='corresponding llvm-profdata command of clang to compile emu, do not set with GCC')
698c11a4d2cSYinan Xu
699c11a4d2cSYinan Xu    args = parser.parse_args()
700c11a4d2cSYinan Xu
701c11a4d2cSYinan Xu    xs = XiangShan(args)
702c11a4d2cSYinan Xu    ret = xs.run(args)
703c11a4d2cSYinan Xu
704c11a4d2cSYinan Xu    sys.exit(ret)
705