xref: /XiangShan/scripts/xiangshan.py (revision f346d72749d2a958fafe5aea9f317b64283b416e)
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
81453674e0STang Haojin        self.emu_optimize = args.emu_optimize
8254cc3a06STang Haojin        self.xprop = 1 if args.xprop else None
830b62a2fbSChen Xi        self.with_chiseldb = 0 if args.no_db else 1
84c11a4d2cSYinan Xu        # emu arguments
85c11a4d2cSYinan Xu        self.max_instr = args.max_instr
8625ac26c6SWilliam Wang        self.ram_size = args.ram_size
8759bcbb59SYinan Xu        self.seed = random.randint(0, 9999)
88c11a4d2cSYinan Xu        self.numa = args.numa
89f9930da0SYinan Xu        self.diff = args.diff
9038e9143dSYinan Xu        if args.spike and "nemu" in args.diff:
9138e9143dSYinan Xu            self.diff = self.diff.replace("nemu-interpreter", "spike")
92078fde2bSJinYue        self.fork = not args.disable_fork
939c297294SWilliam Wang        self.disable_diff = args.no_diff
94e3cd2c1fSwakafa        self.disable_db = args.no_db
95bc247239SXuan Hu        self.gcpt_restore_bin = args.gcpt_restore_bin
969810c04aSYangyu Chen        self.pgo = args.pgo
979810c04aSYangyu Chen        self.pgo_max_cycle = args.pgo_max_cycle
989810c04aSYangyu Chen        self.pgo_emu_args = args.pgo_emu_args
999810c04aSYangyu Chen        self.llvm_profdata = args.llvm_profdata
10024e2eab6SJinYue        # wave dump path
10124e2eab6SJinYue        if args.wave_dump is not None:
10224e2eab6SJinYue            self.set_wave_home(args.wave_dump)
10324e2eab6SJinYue        else:
10424e2eab6SJinYue            self.set_wave_home(self.default_wave_home)
105c11a4d2cSYinan Xu
106c11a4d2cSYinan Xu    def get_env_variables(self):
107c11a4d2cSYinan Xu        all_env = {
108c11a4d2cSYinan Xu            "NOOP_HOME"    : self.noop_home,
109c11a4d2cSYinan Xu            "NEMU_HOME"    : self.nemu_home,
11024e2eab6SJinYue            "WAVE_HOME"    : self.wave_home,
111c11a4d2cSYinan Xu            "AM_HOME"      : self.am_home,
112e5597226Swakafa            "DRAMSIM3_HOME": self.dramsim3_home,
113e5597226Swakafa            "MODULEPATH": "/usr/share/Modules/modulefiles:/etc/modulefiles"
114c11a4d2cSYinan Xu        }
115c11a4d2cSYinan Xu        return all_env
116c11a4d2cSYinan Xu
117c11a4d2cSYinan Xu    def get_chisel_args(self, prefix=None):
118d3126fd3STang Haojin        chisel_args = [
1191545277aSYinan Xu            (self.enable_log, "enable-log")
120c11a4d2cSYinan Xu        ]
121d3126fd3STang Haojin        args = map(lambda x: x[1], filter(lambda arg: arg[0], chisel_args))
122c11a4d2cSYinan Xu        if prefix is not None:
123c11a4d2cSYinan Xu            args = map(lambda x: prefix + x, args)
124c11a4d2cSYinan Xu        return args
125c11a4d2cSYinan Xu
126c11a4d2cSYinan Xu    def get_makefile_args(self):
127c11a4d2cSYinan Xu        makefile_args = [
128c11a4d2cSYinan Xu            (self.threads,       "EMU_THREADS"),
129c11a4d2cSYinan Xu            (self.with_dramsim3, "WITH_DRAMSIM3"),
1301545277aSYinan Xu            (self.is_release,    "RELEASE"),
13138e9143dSYinan Xu            (self.is_spike,      "REF"),
1326c0058d3SYinan Xu            (self.trace,         "EMU_TRACE"),
13340f31726Sgood-circle            (self.trace_fst,     "EMU_TRACE"),
1345ef7374fSLi Qianruo            (self.config,        "CONFIG"),
135084afb77STang Haojin            (self.num_cores,     "NUM_CORES"),
13654cc3a06STang Haojin            (self.emu_optimize,  "EMU_OPTIMIZE"),
13754cc3a06STang Haojin            (self.xprop,         "ENABLE_XPROP"),
1389810c04aSYangyu Chen            (self.with_chiseldb, "WITH_CHISELDB"),
1399810c04aSYangyu Chen            (self.pgo,           "PGO_WORKLOAD"),
1409810c04aSYangyu Chen            (self.pgo_max_cycle, "PGO_MAX_CYCLE"),
1419810c04aSYangyu Chen            (self.pgo_emu_args,  "PGO_EMU_ARGS"),
1429810c04aSYangyu Chen            (self.llvm_profdata, "LLVM_PROFDATA"),
143c11a4d2cSYinan Xu        ]
144c11a4d2cSYinan Xu        args = filter(lambda arg: arg[0] is not None, makefile_args)
1459810c04aSYangyu Chen        args = [(shlex.quote(str(arg[0])), arg[1]) for arg in args] # shell escape
146c11a4d2cSYinan Xu        return args
147c11a4d2cSYinan Xu
148c11a4d2cSYinan Xu    def get_emu_args(self):
149c11a4d2cSYinan Xu        emu_args = [
15059bcbb59SYinan Xu            (self.max_instr, "max-instr"),
151f9930da0SYinan Xu            (self.diff,      "diff"),
15225ac26c6SWilliam Wang            (self.seed,      "seed"),
15325ac26c6SWilliam Wang            (self.ram_size,  "ram-size"),
154c11a4d2cSYinan Xu        ]
155c11a4d2cSYinan Xu        args = filter(lambda arg: arg[0] is not None, emu_args)
156c11a4d2cSYinan Xu        return args
157c11a4d2cSYinan Xu
158c11a4d2cSYinan Xu    def show(self):
159c11a4d2cSYinan Xu        print("Extra environment variables:")
160c11a4d2cSYinan Xu        env = self.get_env_variables()
161c11a4d2cSYinan Xu        for env_name in env:
162c11a4d2cSYinan Xu            print(f"{env_name}: {env[env_name]}")
163c11a4d2cSYinan Xu        print()
164c11a4d2cSYinan Xu        print("Chisel arguments:")
165c11a4d2cSYinan Xu        print(" ".join(self.get_chisel_args()))
166c11a4d2cSYinan Xu        print()
167c11a4d2cSYinan Xu        print("Makefile arguments:")
168c11a4d2cSYinan Xu        for val, name in self.get_makefile_args():
169c11a4d2cSYinan Xu            print(f"{name}={val}")
170c11a4d2cSYinan Xu        print()
171c11a4d2cSYinan Xu        print("emu arguments:")
172c11a4d2cSYinan Xu        for val, name in self.get_emu_args():
173c11a4d2cSYinan Xu            print(f"--{name} {val}")
174c11a4d2cSYinan Xu        print()
175c11a4d2cSYinan Xu
176c11a4d2cSYinan Xu    def __extract_path(self, path, env=None, default=None):
177c11a4d2cSYinan Xu        if path is None and env is not None:
178c11a4d2cSYinan Xu            path = os.getenv(env)
179c11a4d2cSYinan Xu        if path is None and default is not None:
180c11a4d2cSYinan Xu            path = default
181c11a4d2cSYinan Xu        path = os.path.realpath(path)
182c11a4d2cSYinan Xu        return path
183c11a4d2cSYinan Xu
184c11a4d2cSYinan Xu    def set_noop_home(self, path):
185c11a4d2cSYinan Xu        self.noop_home = path
186c11a4d2cSYinan Xu
187c11a4d2cSYinan Xu    def set_nemu_home(self, path):
188c11a4d2cSYinan Xu        self.nemu_home = path
189c11a4d2cSYinan Xu
190c11a4d2cSYinan Xu    def set_am_home(self, path):
191c11a4d2cSYinan Xu        self.am_home = path
192c11a4d2cSYinan Xu
193c11a4d2cSYinan Xu    def set_dramsim3_home(self, path):
194c11a4d2cSYinan Xu        self.dramsim3_home = path
195c11a4d2cSYinan Xu
196c11a4d2cSYinan Xu    def set_rvtest_home(self, path):
197c11a4d2cSYinan Xu        self.rvtest_home = path
198c11a4d2cSYinan Xu
19924e2eab6SJinYue    def set_wave_home(self, path):
20024e2eab6SJinYue        print(f"set wave home to {path}")
20124e2eab6SJinYue        self.wave_home = path
20224e2eab6SJinYue
203c11a4d2cSYinan Xu# XiangShan environment
204c11a4d2cSYinan Xuclass XiangShan(object):
205c11a4d2cSYinan Xu    def __init__(self, args):
206c11a4d2cSYinan Xu        self.args = XSArgs(args)
2079f32a80dSYinan Xu        self.timeout = args.timeout
208c11a4d2cSYinan Xu
209c11a4d2cSYinan Xu    def show(self):
210c11a4d2cSYinan Xu        self.args.show()
211c11a4d2cSYinan Xu
212ef3b5b96SWilliam Wang    def make_clean(self):
213ef3b5b96SWilliam Wang        print("Clean up CI workspace")
214ef3b5b96SWilliam Wang        self.show()
215ef3b5b96SWilliam Wang        return_code = self.__exec_cmd(f'make -C $NOOP_HOME clean')
216ef3b5b96SWilliam Wang        return return_code
217ef3b5b96SWilliam Wang
218c11a4d2cSYinan Xu    def generate_verilog(self):
219c11a4d2cSYinan Xu        print("Generating XiangShan verilog with the following configurations:")
220c11a4d2cSYinan Xu        self.show()
221c11a4d2cSYinan Xu        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
222c11a4d2cSYinan Xu        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
223c11a4d2cSYinan Xu        return_code = self.__exec_cmd(f'make -C $NOOP_HOME verilog SIM_ARGS="{sim_args}" {make_args}')
224c11a4d2cSYinan Xu        return return_code
225c11a4d2cSYinan Xu
226e5597226Swakafa    def generate_sim_verilog(self):
227e5597226Swakafa        print("Generating XiangShan sim-verilog with the following configurations:")
228e5597226Swakafa        self.show()
229e5597226Swakafa        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
230e5597226Swakafa        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
231e5597226Swakafa        return_code = self.__exec_cmd(f'make -C $NOOP_HOME sim-verilog SIM_ARGS="{sim_args}" {make_args}')
232e5597226Swakafa        return return_code
233e5597226Swakafa
234c11a4d2cSYinan Xu    def build_emu(self):
235c11a4d2cSYinan Xu        print("Building XiangShan emu with the following configurations:")
236c11a4d2cSYinan Xu        self.show()
237c11a4d2cSYinan Xu        sim_args = " ".join(self.args.get_chisel_args(prefix="--"))
238c11a4d2cSYinan Xu        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
239a3e87608SWilliam Wang        return_code = self.__exec_cmd(f'make -C $NOOP_HOME emu -j200 SIM_ARGS="{sim_args}" {make_args}')
240c11a4d2cSYinan Xu        return return_code
241c11a4d2cSYinan Xu
242e5597226Swakafa    def build_simv(self):
243e5597226Swakafa        print("Building XiangShan simv with the following configurations")
244e5597226Swakafa        self.show()
245e5597226Swakafa        make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args()))
246e5597226Swakafa        # TODO: make the following commands grouped as unseen scripts
247e5597226Swakafa        return_code = self.__exec_cmd(f'\
248e5597226Swakafa            eval `/usr/bin/modulecmd zsh load license`;\
249e5597226Swakafa            eval `/usr/bin/modulecmd zsh load synopsys/vcs/Q-2020.03-SP2`;\
250e5597226Swakafa            eval `/usr/bin/modulecmd zsh load synopsys/verdi/S-2021.09-SP1`;\
251e5597226Swakafa            VERDI_HOME=/nfs/tools/synopsys/verdi/S-2021.09-SP1 \
252e5597226Swakafa            make -C $NOOP_HOME simv {make_args} CONSIDER_FSDB=1')  # set CONSIDER_FSDB for compatibility
253e5597226Swakafa        return return_code
254e5597226Swakafa
255c11a4d2cSYinan Xu    def run_emu(self, workload):
256c11a4d2cSYinan Xu        print("Running XiangShan emu with the following configurations:")
257c11a4d2cSYinan Xu        self.show()
258c11a4d2cSYinan Xu        emu_args = " ".join(map(lambda arg: f"--{arg[1]} {arg[0]}", self.args.get_emu_args()))
259c11a4d2cSYinan Xu        print("workload:", workload)
260c9d90c8dSYinan Xu        numa_args = ""
261c9d90c8dSYinan Xu        if self.args.numa:
26294e266cbSYinan Xu            numa_info = get_free_cores(self.args.threads)
263c9d90c8dSYinan Xu            numa_args = f"numactl -m {numa_info[0]} -C {numa_info[1]}-{numa_info[2]}"
264e76e9e54STang Haojin        fork_args = "--enable-fork -X 10" if self.args.fork else ""
2659c297294SWilliam Wang        diff_args = "--no-diff" if self.args.disable_diff else ""
266e3cd2c1fSwakafa        chiseldb_args = "--dump-db" if not self.args.disable_db else ""
267bc247239SXuan Hu        gcpt_restore_args = f"-r {self.args.gcpt_restore_bin}" if len(self.args.gcpt_restore_bin) != 0 else ""
268bc247239SXuan 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}')
269c11a4d2cSYinan Xu        return return_code
270c11a4d2cSYinan Xu
271e5597226Swakafa    def run_simv(self, workload):
272e5597226Swakafa        print("Running XiangShan simv with the following configurations:")
273e5597226Swakafa        self.show()
274e5597226Swakafa        diff_args = "$NOOP_HOME/"+ args.diff
27554cc3a06STang Haojin        assert_args = "-assert finish_maxfail=30 -assert global_finish_maxfail=10000"
276ae0295f4STang 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')
277823787d8STang Haojin        with open(f"{self.args.noop_home}/build/simv.log") as f:
278ae0295f4STang Haojin            content = f.read()
279ae0295f4STang Haojin            if "Offending" in content or "HIT GOOD TRAP" not in content:
280823787d8STang Haojin                return 1
281ae0295f4STang Haojin        return return_code
282e5597226Swakafa
283c11a4d2cSYinan Xu    def run(self, args):
284c11a4d2cSYinan Xu        if args.ci is not None:
285c11a4d2cSYinan Xu            return self.run_ci(args.ci)
286e5597226Swakafa        if args.ci_vcs is not None:
287e5597226Swakafa            return self.run_ci_vcs(args.ci_vcs)
288c11a4d2cSYinan Xu        actions = [
289c11a4d2cSYinan Xu            (args.generate, lambda _ : self.generate_verilog()),
290e5597226Swakafa            (args.vcs_gen, lambda _ : self.generate_sim_verilog()),
291c11a4d2cSYinan Xu            (args.build, lambda _ : self.build_emu()),
292e5597226Swakafa            (args.vcs_build, lambda _ : self.build_simv()),
293ef3b5b96SWilliam Wang            (args.workload, lambda args: self.run_emu(args.workload)),
294ef3b5b96SWilliam Wang            (args.clean, lambda _ : self.make_clean())
295c11a4d2cSYinan Xu        ]
296c11a4d2cSYinan Xu        valid_actions = map(lambda act: act[1], filter(lambda act: act[0], actions))
297c11a4d2cSYinan Xu        for i, action in enumerate(valid_actions):
298c11a4d2cSYinan Xu            print(f"Action {i}:")
299c11a4d2cSYinan Xu            ret = action(args)
300c11a4d2cSYinan Xu            if ret:
301c11a4d2cSYinan Xu                return ret
302c11a4d2cSYinan Xu        return 0
303c11a4d2cSYinan Xu
304c11a4d2cSYinan Xu    def __exec_cmd(self, cmd):
305c11a4d2cSYinan Xu        env = dict(os.environ)
306c11a4d2cSYinan Xu        env.update(self.args.get_env_variables())
307c11a4d2cSYinan Xu        print("subprocess call cmd:", cmd)
3085ef7374fSLi Qianruo        start = time.time()
3099f32a80dSYinan Xu        proc = subprocess.Popen(cmd, shell=True, env=env, preexec_fn=os.setsid)
3109f32a80dSYinan Xu        try:
3119f32a80dSYinan Xu            return_code = proc.wait(self.timeout)
3125ef7374fSLi Qianruo            end = time.time()
3135ef7374fSLi Qianruo            print(f"Elapsed time: {end - start} seconds")
314c11a4d2cSYinan Xu            return return_code
3159f32a80dSYinan Xu        except (KeyboardInterrupt, subprocess.TimeoutExpired):
3169f32a80dSYinan Xu            os.killpg(os.getpgid(proc.pid), signal.SIGINT)
3179f32a80dSYinan Xu            print(f"KeyboardInterrupt or TimeoutExpired.")
3189f32a80dSYinan Xu            return 0
319c11a4d2cSYinan Xu
320c11a4d2cSYinan Xu    def __get_ci_cputest(self, name=None):
3210d7009bfSXu, Zefan        # base_dir = os.path.join(self.args.am_home, "tests/cputest/build")
3220d7009bfSXu, Zefan        base_dir = "/nfs/home/share/ci-workloads/nexus-am-workloads/tests/cputest"
323c11a4d2cSYinan Xu        cputest = os.listdir(base_dir)
324c11a4d2cSYinan Xu        cputest = filter(lambda x: x.endswith(".bin"), cputest)
325c11a4d2cSYinan Xu        cputest = map(lambda x: os.path.join(base_dir, x), cputest)
326c11a4d2cSYinan Xu        return cputest
327c11a4d2cSYinan Xu
328c11a4d2cSYinan Xu    def __get_ci_rvtest(self, name=None):
329c11a4d2cSYinan Xu        base_dir = os.path.join(self.args.rvtest_home, "isa/build")
330c11a4d2cSYinan Xu        riscv_tests = os.listdir(base_dir)
331c11a4d2cSYinan Xu        riscv_tests = filter(lambda x: x.endswith(".bin"), riscv_tests)
33241d8d239Shappy-lx        all_rv_tests = ["rv64ui", "rv64um", "rv64ua", "rv64uf", "rv64ud", "rv64mi"]
333c11a4d2cSYinan Xu        riscv_tests = filter(lambda x: x[:6] in all_rv_tests, riscv_tests)
334c11a4d2cSYinan Xu        riscv_tests = map(lambda x: os.path.join(base_dir, x), riscv_tests)
335c11a4d2cSYinan Xu        return riscv_tests
336c11a4d2cSYinan Xu
337675acc68SYinan Xu    def __get_ci_misc(self, name=None):
338da3b568bSYinan Xu        base_dir = "/nfs/home/share/ci-workloads"
339675acc68SYinan Xu        workloads = [
340675acc68SYinan Xu            "bitmanip/bitMisc.bin",
3413feeca58Szfw            "crypto/crypto-riscv64-noop.bin",
3420d7009bfSXu, Zefan            # "coremark_rv64gc_o2/coremark-riscv64-xs.bin",
3430d7009bfSXu, Zefan            # "coremark_rv64gc_o3/coremark-riscv64-xs.bin",
3440d7009bfSXu, Zefan            # "coremark_rv64gcb_o3/coremark-riscv64-xs.bin",
3450d7009bfSXu, Zefan            "nexus-am-workloads/amtest/external_intr-riscv64-xs.bin",
3460d7009bfSXu, Zefan            "nexus-am-workloads/tests/aliastest/aliastest-riscv64-xs.bin",
347af2f7849Shappy-lx            "Svinval/rv64mi-p-svinval.bin",
348b6982e83SLemover            "pmp/pmp.riscv.bin",
3490d7009bfSXu, Zefan            "nexus-am-workloads/amtest/pmp_test-riscv64-xs.bin",
3500d7009bfSXu, Zefan            "nexus-am-workloads/amtest/sv39_hp_atom_test-riscv64-xs.bin",
35145f497a4Shappy-lx            "asid/asid.bin",
3527d9edc86SLemover            "isa_misc/xret_clear_mprv.bin",
353705cbec3SLemover            "isa_misc/satp_ppn.bin",
354ad15bdb2SNewPaulWalker            "cache-management/softprefetchtest-riscv64-xs.bin",
3554293ded2Slinzhida            "smstateen/rvh_test.bin",
356*f346d727SYanqin Li            "zacas/zacas-riscv64-xs.bin",
357*f346d727SYanqin Li            "Svpbmt/rvh_test.bin"
358675acc68SYinan Xu        ]
359675acc68SYinan Xu        misc_tests = map(lambda x: os.path.join(base_dir, x), workloads)
360675acc68SYinan Xu        return misc_tests
361675acc68SYinan Xu
3621f903014SXu, Zefan    def __get_ci_rvhtest(self, name=None):
3631f903014SXu, Zefan        base_dir = "/nfs/home/share/ci-workloads/H-extension-tests"
3641f903014SXu, Zefan        workloads = [
365afdeb382SXu, Zefan            "riscv-hyp-tests/rvh_test.bin",
3661f903014SXu, Zefan            "xvisor_wboxtest/checkpoint.gz",
367189833a1SHaoyuan Feng            "pointer-masking-test/M_HS_test/rvh_test.bin",
368189833a1SHaoyuan Feng            "pointer-masking-test/U_test/hint_UMode_hupmm2/rvh_test.bin",
369189833a1SHaoyuan Feng            "pointer-masking-test/U_test/vu_senvcfgpmm2/rvh_test.bin"
3701f903014SXu, Zefan        ]
3711f903014SXu, Zefan        rvh_tests = map(lambda x: os.path.join(base_dir, x), workloads)
3721f903014SXu, Zefan        return rvh_tests
3731f903014SXu, Zefan
3746ebd27e9Slwd    def __get_ci_rvvbench(self, name=None):
3756ebd27e9Slwd        base_dir = "/nfs/home/share/ci-workloads"
3766ebd27e9Slwd        workloads = [
3776ebd27e9Slwd            "rvv-bench/poly1305.bin",
3786ebd27e9Slwd            "rvv-bench/mergelines.bin"
3796ebd27e9Slwd        ]
3806ebd27e9Slwd        rvvbench = map(lambda x: os.path.join(base_dir, x), workloads)
3816ebd27e9Slwd        return rvvbench
3826ebd27e9Slwd
3836ebd27e9Slwd    def __get_ci_rvvtest(self, name=None):
3846ebd27e9Slwd        base_dir = "/nfs/home/share/ci-workloads/V-extension-tests"
3856ebd27e9Slwd        workloads = [
3866ebd27e9Slwd            "rvv-test/vluxei32.v-0.bin",
3876ebd27e9Slwd            "rvv-test/vlsseg4e32.v-0.bin",
3886ebd27e9Slwd            "rvv-test/vlseg4e32.v-0.bin",
3896ebd27e9Slwd            "rvv-test/vsetvl-0.bin",
3906ebd27e9Slwd            "rvv-test/vsetivli-0.bin",
3916ebd27e9Slwd            "rvv-test/vsuxei32.v-0.bin",
3926ebd27e9Slwd            "rvv-test/vse16.v-0.bin",
3936ebd27e9Slwd            "rvv-test/vsse16.v-1.bin",
3946ebd27e9Slwd            "rvv-test/vlse32.v-0.bin",
3956ebd27e9Slwd            "rvv-test/vsetvli-0.bin",
3966ebd27e9Slwd            "rvv-test/vle16.v-0.bin",
3976ebd27e9Slwd            "rvv-test/vle32.v-0.bin",
3986ebd27e9Slwd            "rvv-test/vfsgnj.vv-0.bin",
3996ebd27e9Slwd            "rvv-test/vfadd.vf-0.bin",
4006ebd27e9Slwd            "rvv-test/vfsub.vf-0.bin",
4016ebd27e9Slwd            "rvv-test/vslide1down.vx-0.bin"
4026ebd27e9Slwd        ]
4036ebd27e9Slwd        rvv_test = map(lambda x: os.path.join(base_dir, x), workloads)
4046ebd27e9Slwd        return rvv_test
4056ebd27e9Slwd
406dd16cea7SHeiHuDie    def __get_ci_F16test(self, name=None):
407dd16cea7SHeiHuDie        base_dir = "/nfs/home/share/ci-workloads/vector/F16-tests/build"
408dd16cea7SHeiHuDie        workloads = [
409dd16cea7SHeiHuDie            "rv64uzfhmin-p-fzfhmincvt.bin",
410dd16cea7SHeiHuDie            "rv64uzfh-p-fadd.bin",
411dd16cea7SHeiHuDie            "rv64uzfh-p-fclass.bin",
412dd16cea7SHeiHuDie            "rv64uzfh-p-fcmp.bin",
413dd16cea7SHeiHuDie            "rv64uzfh-p-fcvt.bin",
414dd16cea7SHeiHuDie            "rv64uzfh-p-fcvt_w.bin",
415dd16cea7SHeiHuDie            "rv64uzfh-p-fdiv.bin",
416dd16cea7SHeiHuDie            "rv64uzfh-p-fmadd.bin",
417dd16cea7SHeiHuDie            "rv64uzfh-p-fmin.bin",
418dd16cea7SHeiHuDie            "rv64uzfh-p-ldst.bin",
419dd16cea7SHeiHuDie            "rv64uzfh-p-move.bin",
420dd16cea7SHeiHuDie            "rv64uzfh-p-recoding.bin",
421dd16cea7SHeiHuDie            "rv64uzvfh-p-vfadd.bin",
422dd16cea7SHeiHuDie            "rv64uzvfh-p-vfclass.bin",
423dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtfx.bin",
424dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtfxu.bin",
425dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtrxf.bin",
426dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtrxuf.bin",
427dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtxf.bin",
428dd16cea7SHeiHuDie            "rv64uzvfh-p-vfcvtxuf.bin",
429dd16cea7SHeiHuDie            "rv64uzvfh-p-vfdiv.bin",
430dd16cea7SHeiHuDie            "rv64uzvfh-p-vfdown.bin",
431dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmacc.bin",
432dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmadd.bin",
433dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmax.bin",
434dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmerge.bin",
435dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmin.bin",
436dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmsac.bin",
437dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmsub.bin",
438dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmul.bin",
439dd16cea7SHeiHuDie            "rv64uzvfh-p-vfmv.bin",
440dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtff.bin",
441dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtfx.bin",
442dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtfxu.bin",
443dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtrff.bin",
444dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtrxf.bin",
445dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtrxuf.bin",
446dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtxf.bin",
447dd16cea7SHeiHuDie            "rv64uzvfh-p-vfncvtxuf.bin",
448dd16cea7SHeiHuDie            "rv64uzvfh-p-vfnmacc.bin",
449dd16cea7SHeiHuDie            "rv64uzvfh-p-vfnmadd.bin",
450dd16cea7SHeiHuDie            "rv64uzvfh-p-vfnmsac.bin",
451dd16cea7SHeiHuDie            "rv64uzvfh-p-vfnmsub.bin",
452dd16cea7SHeiHuDie            "rv64uzvfh-p-vfrdiv.bin",
453dd16cea7SHeiHuDie            "rv64uzvfh-p-vfrec7.bin",
454dd16cea7SHeiHuDie            "rv64uzvfh-p-vfredmax.bin",
455dd16cea7SHeiHuDie            "rv64uzvfh-p-vfredmin.bin",
456dd16cea7SHeiHuDie            "rv64uzvfh-p-vfredosum.bin",
457dd16cea7SHeiHuDie            "rv64uzvfh-p-vfredusum.bin",
458dd16cea7SHeiHuDie            "rv64uzvfh-p-vfrsqrt7.bin",
459dd16cea7SHeiHuDie            "rv64uzvfh-p-vfrsub.bin",
460dd16cea7SHeiHuDie            "rv64uzvfh-p-vfsgnj.bin",
461dd16cea7SHeiHuDie            "rv64uzvfh-p-vfsgnjn.bin",
462dd16cea7SHeiHuDie            "rv64uzvfh-p-vfsgnjx.bin",
463dd16cea7SHeiHuDie            "rv64uzvfh-p-vfsqrt.bin",
464dd16cea7SHeiHuDie            "rv64uzvfh-p-vfsub.bin",
465dd16cea7SHeiHuDie            "rv64uzvfh-p-vfup.bin",
466dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwadd.bin",
467dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwadd-w.bin",
468dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtff.bin",
469dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtfx.bin",
470dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtfxu.bin",
471dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtrxf.bin",
472dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtrxuf.bin",
473dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtxf.bin",
474dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwcvtxuf.bin",
475dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwmacc.bin",
476dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwmsac.bin",
477dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwmul.bin",
478dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwnmacc.bin",
479dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwnmsac.bin",
480dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwredosum.bin",
481dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwredusum.bin",
482dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwsub.bin",
483dd16cea7SHeiHuDie            "rv64uzvfh-p-vfwsub-w.bin",
484dd16cea7SHeiHuDie            "rv64uzvfh-p-vmfeq.bin",
485dd16cea7SHeiHuDie            "rv64uzvfh-p-vmfge.bin",
486dd16cea7SHeiHuDie            "rv64uzvfh-p-vmfgt.bin",
487dd16cea7SHeiHuDie            "rv64uzvfh-p-vmfle.bin",
488dd16cea7SHeiHuDie            "rv64uzvfh-p-vmflt.bin",
489dd16cea7SHeiHuDie            "rv64uzvfh-p-vmfne.bin"
490dd16cea7SHeiHuDie        ]
491dd16cea7SHeiHuDie        f16_test = map(lambda x: os.path.join(base_dir, x), workloads)
492dd16cea7SHeiHuDie        return f16_test
493393755c7SHuSipeng    def __get_ci_zcbtest(self, name=None):
494393755c7SHuSipeng        base_dir = "/nfs/home/share/ci-workloads/zcb-test"
495393755c7SHuSipeng        workloads = [
496393755c7SHuSipeng            "zcb-test-riscv64-xs.bin"
497393755c7SHuSipeng        ]
498393755c7SHuSipeng        zcb_test = map(lambda x: os.path.join(base_dir, x), workloads)
499393755c7SHuSipeng        return zcb_test
500dd16cea7SHeiHuDie
501ef3b5b96SWilliam Wang    def __get_ci_mc(self, name=None):
502ef3b5b96SWilliam Wang        base_dir = "/nfs/home/share/ci-workloads"
503ef3b5b96SWilliam Wang        workloads = [
5040d7009bfSXu, Zefan            "nexus-am-workloads/tests/dualcoretest/ldvio-riscv64-xs.bin"
505ef3b5b96SWilliam Wang        ]
506ef3b5b96SWilliam Wang        mc_tests = map(lambda x: os.path.join(base_dir, x), workloads)
507ef3b5b96SWilliam Wang        return mc_tests
508ef3b5b96SWilliam Wang
5099c297294SWilliam Wang    def __get_ci_nodiff(self, name=None):
510da3b568bSYinan Xu        base_dir = "/nfs/home/share/ci-workloads"
5119c297294SWilliam Wang        workloads = [
5129c297294SWilliam Wang            "cache-management/cacheoptest-riscv64-xs.bin"
5139c297294SWilliam Wang        ]
5149c297294SWilliam Wang        tests = map(lambda x: os.path.join(base_dir, x), workloads)
5159c297294SWilliam Wang        return tests
5169c297294SWilliam Wang
517c11a4d2cSYinan Xu    def __am_apps_path(self, bench):
5180d7009bfSXu, Zefan        base_dir = '/nfs/home/share/ci-workloads/nexus-am-workloads/apps'
5190d7009bfSXu, Zefan        filename = f"{bench}-riscv64-xs.bin"
5200d7009bfSXu, Zefan        return [os.path.join(base_dir, bench, filename)]
521c11a4d2cSYinan Xu
522c11a4d2cSYinan Xu    def __get_ci_workloads(self, name):
523c11a4d2cSYinan Xu        workloads = {
524c11a4d2cSYinan Xu            "linux-hello": "bbl.bin",
525fac0ab56Swakafa            "linux-hello-smp": "bbl.bin",
5264a8a734eSceba            "linux-hello-opensbi": "fw_payload.bin",
5274a8a734eSceba            "linux-hello-smp-opensbi": "fw_payload.bin",
528e975de62STang Haojin            "linux-hello-new": "bbl.bin",
529e975de62STang Haojin            "linux-hello-smp-new": "bbl.bin",
5305092a298Szfw            "povray": "_700480000000_.gz",
5315092a298Szfw            "mcf": "_17520000000_.gz",
5325092a298Szfw            "xalancbmk": "_266100000000_.gz",
5335092a298Szfw            "gcc": "_39720000000_.gz",
5345092a298Szfw            "namd": "_434640000000_.gz",
5355092a298Szfw            "milc": "_103620000000_.gz",
5365092a298Szfw            "lbm": "_140840000000_.gz",
5377b441e5eSYinan Xu            "gromacs": "_275480000000_.gz",
5387b441e5eSYinan Xu            "wrf": "_1916220000000_.gz",
5397b441e5eSYinan Xu            "astar": "_122060000000_.gz"
540c11a4d2cSYinan Xu        }
5419f32a80dSYinan Xu        if name in workloads:
542da3b568bSYinan Xu            return [os.path.join("/nfs/home/share/ci-workloads", name, workloads[name])]
5439f32a80dSYinan Xu        # select a random SPEC checkpoint
5449f32a80dSYinan Xu        assert(name == "random")
545fcefab32SHaojin Tang        all_cpt_dir = [
54601efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec06_rv64gcb_o2_20m/take_cpt",
54701efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec06_rv64gcb_o3_20m/take_cpt",
54801efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec06_rv64gc_o2_20m/take_cpt",
54901efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec06_rv64gc_o2_50m/take_cpt",
55001efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec17_rv64gcb_o2_20m/take_cpt",
55101efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec17_rv64gcb_o3_20m/take_cpt",
55201efe338STang Haojin            "/nfs/home/share/checkpoints_profiles/spec17_rv64gc_o2_50m/take_cpt",
553fcefab32SHaojin Tang            "/nfs/home/share/checkpoints_profiles/spec17_speed_rv64gcb_o3_20m/take_cpt",
554fcefab32SHaojin Tang            "/nfs/home/share/checkpoints_profiles/spec06_rv64gcb_O3_20m_gcc12.2.0-intFpcOff-jeMalloc/zstd-checkpoint-0-0-0",
555fcefab32SHaojin 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"
5569f32a80dSYinan Xu        ]
557fcefab32SHaojin Tang        all_gcpt = load_all_gcpt(all_cpt_dir)
5589f32a80dSYinan Xu        return [random.choice(all_gcpt)]
559c11a4d2cSYinan Xu
560c11a4d2cSYinan Xu    def run_ci(self, test):
561c11a4d2cSYinan Xu        all_tests = {
562c11a4d2cSYinan Xu            "cputest": self.__get_ci_cputest,
563c11a4d2cSYinan Xu            "riscv-tests": self.__get_ci_rvtest,
564675acc68SYinan Xu            "misc-tests": self.__get_ci_misc,
565ef3b5b96SWilliam Wang            "mc-tests": self.__get_ci_mc,
5669c297294SWilliam Wang            "nodiff-tests": self.__get_ci_nodiff,
5671f903014SXu, Zefan            "rvh-tests": self.__get_ci_rvhtest,
568c11a4d2cSYinan Xu            "microbench": self.__am_apps_path,
5696ebd27e9Slwd            "coremark": self.__am_apps_path,
57020156f77STang Haojin            "coremark-1-iteration": self.__am_apps_path,
5716ebd27e9Slwd            "rvv-bench": self.__get_ci_rvvbench,
572dd16cea7SHeiHuDie            "rvv-test": self.__get_ci_rvvtest,
573393755c7SHuSipeng            "f16_test": self.__get_ci_F16test,
574393755c7SHuSipeng            "zcb-test": self.__get_ci_zcbtest
575c11a4d2cSYinan Xu        }
576c11a4d2cSYinan Xu        for target in all_tests.get(test, self.__get_ci_workloads)(test):
577c11a4d2cSYinan Xu            print(target)
578c11a4d2cSYinan Xu            ret = self.run_emu(target)
579c11a4d2cSYinan Xu            if ret:
58024e2eab6SJinYue                if self.args.default_wave_home != self.args.wave_home:
58124e2eab6SJinYue                    print("copy wave file to " + self.args.wave_home)
58224e2eab6SJinYue                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.vcd $WAVE_HOME")
583bc063562SLemover                    self.__exec_cmd(f"cp $NOOP_HOME/build/emu $WAVE_HOME")
58445f43e6eSTang Haojin                    self.__exec_cmd(f"cp $NOOP_HOME/build/rtl/SimTop.v $WAVE_HOME")
585e3cd2c1fSwakafa                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.db $WAVE_HOME")
586c11a4d2cSYinan Xu                return ret
587c11a4d2cSYinan Xu        return 0
588c11a4d2cSYinan Xu
589e5597226Swakafa    def run_ci_vcs(self, test):
590e5597226Swakafa        all_tests = {
591e5597226Swakafa            "cputest": self.__get_ci_cputest,
592e5597226Swakafa            "riscv-tests": self.__get_ci_rvtest,
593e5597226Swakafa            "misc-tests": self.__get_ci_misc,
594e5597226Swakafa            "mc-tests": self.__get_ci_mc,
595e5597226Swakafa            "nodiff-tests": self.__get_ci_nodiff,
5961f903014SXu, Zefan            "rvh-tests": self.__get_ci_rvhtest,
597e5597226Swakafa            "microbench": self.__am_apps_path,
5986ebd27e9Slwd            "coremark": self.__am_apps_path,
59920156f77STang Haojin            "coremark-1-iteration": self.__am_apps_path,
6006ebd27e9Slwd            "rvv-bench": self.__get_ci_rvvbench,
601dd16cea7SHeiHuDie            "rvv-test": self.__get_ci_rvvtest,
602393755c7SHuSipeng            "f16_test": self.__get_ci_F16test,
603393755c7SHuSipeng            "zcb-test": self.__get_ci_zcbtest
604e5597226Swakafa        }
605e5597226Swakafa        for target in all_tests.get(test, self.__get_ci_workloads)(test):
606e5597226Swakafa            print(target)
607e5597226Swakafa            ret = self.run_simv(target)
608e5597226Swakafa            if ret:
609e5597226Swakafa                if self.args.default_wave_home != self.args.wave_home:
610e5597226Swakafa                    print("copy wave file to " + self.args.wave_home)
61154cc3a06STang Haojin                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.fsdb $WAVE_HOME")
61254cc3a06STang Haojin                    self.__exec_cmd(f"cp $NOOP_HOME/build/simv $WAVE_HOME")
61345f43e6eSTang Haojin                    self.__exec_cmd(f"cp $NOOP_HOME/build/rtl/SimTop.v $WAVE_HOME")
614e3cd2c1fSwakafa                    self.__exec_cmd(f"cp $NOOP_HOME/build/*.db $WAVE_HOME")
615e5597226Swakafa                return ret
616e5597226Swakafa        return 0
617e5597226Swakafa
61894e266cbSYinan Xudef get_free_cores(n):
619a941bfc4STang Haojin    numa_re = re.compile(r'.*numactl +.*-C +([0-9]+)-([0-9]+).*')
62094e266cbSYinan Xu    while True:
621a941bfc4STang Haojin        disable_cores = []
622a941bfc4STang Haojin        for proc in psutil.process_iter():
623a941bfc4STang Haojin            try:
624a941bfc4STang Haojin                joint = ' '.join(proc.cmdline())
625a941bfc4STang Haojin                numa_match = numa_re.match(joint)
626dd720caeSTang Haojin                if numa_match and 'ssh' not in proc.name():
627a941bfc4STang Haojin                    disable_cores.extend(range(int(numa_match.group(1)), int(numa_match.group(2)) + 1))
628a941bfc4STang Haojin            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
629a941bfc4STang Haojin                pass
630b86f926fSYinan Xu        num_logical_core = psutil.cpu_count(logical=False)
63194e266cbSYinan Xu        core_usage = psutil.cpu_percent(interval=1, percpu=True)
63294e266cbSYinan Xu        num_window = num_logical_core // n
63394e266cbSYinan Xu        for i in range(num_window):
634a941bfc4STang Haojin            if set(disable_cores) & set(range(i * n, i * n + n)):
635a941bfc4STang Haojin                continue
63694e266cbSYinan Xu            window_usage = core_usage[i * n : i * n + n]
63701a51437SYinan Xu            if sum(window_usage) < 30 * n and True not in map(lambda x: x > 90, window_usage):
63871f0f4ccSTang Haojin                return (((i * n) % num_logical_core) // (num_logical_core // 2), i * n, i * n + n - 1)
63994e266cbSYinan Xu        print(f"No free {n} cores found. CPU usage: {core_usage}\n")
64043f08742STang Haojin        time.sleep(random.uniform(1, 60))
64194e266cbSYinan Xu
642c11a4d2cSYinan Xuif __name__ == "__main__":
643c11a4d2cSYinan Xu    parser = argparse.ArgumentParser(description='Python wrapper for XiangShan')
644c11a4d2cSYinan Xu    parser.add_argument('workload', nargs='?', type=str, default="",
645c11a4d2cSYinan Xu                        help='input workload file in binary format')
646c11a4d2cSYinan Xu    # actions
647c11a4d2cSYinan Xu    parser.add_argument('--build', action='store_true', help='build XS emu')
648c11a4d2cSYinan Xu    parser.add_argument('--generate', action='store_true', help='generate XS verilog')
649e5597226Swakafa    parser.add_argument('--vcs-gen', action='store_true', help='generate XS sim verilog for vcs')
650e5597226Swakafa    parser.add_argument('--vcs-build', action='store_true', help='build XS simv')
651c11a4d2cSYinan Xu    parser.add_argument('--ci', nargs='?', type=str, const="", help='run CI tests')
652e5597226Swakafa    parser.add_argument('--ci-vcs', nargs='?', type=str, const="", help='run CI tests on simv')
653ef3b5b96SWilliam Wang    parser.add_argument('--clean', action='store_true', help='clean up XiangShan CI workspace')
6549f32a80dSYinan Xu    parser.add_argument('--timeout', nargs='?', type=int, default=None, help='timeout (in seconds)')
655c11a4d2cSYinan Xu    # environment variables
656c11a4d2cSYinan Xu    parser.add_argument('--nemu', nargs='?', type=str, help='path to nemu')
657c11a4d2cSYinan Xu    parser.add_argument('--am', nargs='?', type=str, help='path to nexus-am')
658c11a4d2cSYinan Xu    parser.add_argument('--dramsim3', nargs='?', type=str, help='path to dramsim3')
659c11a4d2cSYinan Xu    parser.add_argument('--rvtest', nargs='?', type=str, help='path to riscv-tests')
66024e2eab6SJinYue    parser.add_argument('--wave-dump', nargs='?', type=str , help='path to dump wave')
661c11a4d2cSYinan Xu    # chisel arguments
6621545277aSYinan Xu    parser.add_argument('--enable-log', action='store_true', help='enable log')
6635ef7374fSLi Qianruo    parser.add_argument('--num-cores', type=int, help='number of cores')
664c11a4d2cSYinan Xu    # makefile arguments
6651545277aSYinan Xu    parser.add_argument('--release', action='store_true', help='enable release')
66638e9143dSYinan Xu    parser.add_argument('--spike', action='store_true', help='enable spike diff')
667c11a4d2cSYinan Xu    parser.add_argument('--with-dramsim3', action='store_true', help='enable dramsim3')
668c11a4d2cSYinan Xu    parser.add_argument('--threads', nargs='?', type=int, help='number of emu threads')
66940f31726Sgood-circle    parser.add_argument('--trace', action='store_true', help='enable vcd waveform')
67040f31726Sgood-circle    parser.add_argument('--trace-fst', action='store_true', help='enable fst waveform')
6716c0058d3SYinan Xu    parser.add_argument('--config', nargs='?', type=str, help='config')
672453674e0STang Haojin    parser.add_argument('--emu-optimize', nargs='?', type=str, help='verilator optimization letter')
67354cc3a06STang Haojin    parser.add_argument('--xprop', action='store_true', help='enable xprop for vcs')
674c11a4d2cSYinan Xu    # emu arguments
675c11a4d2cSYinan Xu    parser.add_argument('--numa', action='store_true', help='use numactl')
676f9930da0SYinan Xu    parser.add_argument('--diff', nargs='?', default="./ready-to-run/riscv64-nemu-interpreter-so", type=str, help='nemu so')
677c11a4d2cSYinan Xu    parser.add_argument('--max-instr', nargs='?', type=int, help='max instr')
678078fde2bSJinYue    parser.add_argument('--disable-fork', action='store_true', help='disable lightSSS')
6799c297294SWilliam Wang    parser.add_argument('--no-diff', action='store_true', help='disable difftest')
68025ac26c6SWilliam Wang    parser.add_argument('--ram-size', nargs='?', type=str, help='manually set simulation memory size (8GB by default)')
681bc247239SXuan Hu    parser.add_argument('--gcpt-restore-bin', type=str, default="", help="specify the bin used to restore from gcpt")
68254cc3a06STang Haojin    # both makefile and emu arguments
683e3cd2c1fSwakafa    parser.add_argument('--no-db', action='store_true', help='disable chiseldb dump')
6849810c04aSYangyu Chen    parser.add_argument('--pgo', nargs='?', type=str, help='workload for pgo (null to disable pgo)')
6859810c04aSYangyu Chen    parser.add_argument('--pgo-max-cycle', nargs='?', default=400000, type=int, help='maximun cycle to train pgo')
6869810c04aSYangyu Chen    parser.add_argument('--pgo-emu-args', nargs='?', default='--no-diff', type=str, help='emu arguments for pgo')
6879810c04aSYangyu Chen    parser.add_argument('--llvm-profdata', nargs='?', type=str, help='corresponding llvm-profdata command of clang to compile emu, do not set with GCC')
688c11a4d2cSYinan Xu
689c11a4d2cSYinan Xu    args = parser.parse_args()
690c11a4d2cSYinan Xu
691c11a4d2cSYinan Xu    xs = XiangShan(args)
692c11a4d2cSYinan Xu    ret = xs.run(args)
693c11a4d2cSYinan Xu
694c11a4d2cSYinan Xu    sys.exit(ret)
695