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 329f32a80dSYinan Xudef load_all_gcpt(gcpt_path, json_path): 339f32a80dSYinan Xu all_gcpt = [] 349f32a80dSYinan Xu with open(json_path) as f: 359f32a80dSYinan Xu data = json.load(f) 369f32a80dSYinan Xu for benchspec in data: 379f32a80dSYinan Xu for point in data[benchspec]: 389f32a80dSYinan Xu weight = data[benchspec][point] 399f32a80dSYinan Xu gcpt = os.path.join(gcpt_path, "_".join([benchspec, point, weight])) 409f32a80dSYinan Xu bin_dir = os.path.join(gcpt, "0") 419f32a80dSYinan Xu bin_file = list(os.listdir(bin_dir)) 429f32a80dSYinan Xu assert(len(bin_file) == 1) 439f32a80dSYinan Xu bin_path = os.path.join(bin_dir, bin_file[0]) 449f32a80dSYinan Xu assert(os.path.isfile(bin_path)) 459f32a80dSYinan Xu all_gcpt.append(bin_path) 469f32a80dSYinan Xu return all_gcpt 479f32a80dSYinan Xu 48c11a4d2cSYinan Xuclass XSArgs(object): 49c11a4d2cSYinan Xu script_path = os.path.realpath(__file__) 50c11a4d2cSYinan Xu # default path to the repositories 51c11a4d2cSYinan Xu noop_home = os.path.join(os.path.dirname(script_path), "..") 52c11a4d2cSYinan Xu nemu_home = os.path.join(noop_home, "../NEMU") 53c11a4d2cSYinan Xu am_home = os.path.join(noop_home, "../nexus-am") 54c11a4d2cSYinan Xu dramsim3_home = os.path.join(noop_home, "../DRAMsim3") 55c11a4d2cSYinan Xu rvtest_home = os.path.join(noop_home, "../riscv-tests") 5624e2eab6SJinYue default_wave_home = os.path.join(noop_home, "build") 5724e2eab6SJinYue wave_home = default_wave_home 58c11a4d2cSYinan Xu 59c11a4d2cSYinan Xu def __init__(self, args): 60c11a4d2cSYinan Xu # all path environment variables that should be set 61c11a4d2cSYinan Xu all_path = [ 62c11a4d2cSYinan Xu # (python argument, environment variable, default, target function) 63c11a4d2cSYinan Xu (None, "NOOP_HOME", self.noop_home, self.set_noop_home), 64c11a4d2cSYinan Xu (args.nemu, "NEMU_HOME", self.nemu_home, self.set_nemu_home), 65c11a4d2cSYinan Xu (args.am, "AM_HOME", self.am_home, self.set_am_home), 66c11a4d2cSYinan Xu (args.dramsim3, "DRAMSIM3_HOME", self.dramsim3_home, self.set_dramsim3_home), 67c11a4d2cSYinan Xu (args.rvtest, "RVTEST_HOME", self.rvtest_home, self.set_rvtest_home), 68c11a4d2cSYinan Xu ] 69c11a4d2cSYinan Xu for (arg_in, env, default, set_func) in all_path: 70c11a4d2cSYinan Xu set_func(self.__extract_path(arg_in, env, default)) 71c11a4d2cSYinan Xu # Chisel arguments 721545277aSYinan Xu self.enable_log = args.enable_log 735ef7374fSLi Qianruo self.num_cores = args.num_cores 74c11a4d2cSYinan Xu # Makefile arguments 75c11a4d2cSYinan Xu self.threads = args.threads 76c11a4d2cSYinan Xu self.with_dramsim3 = 1 if args.with_dramsim3 else None 771545277aSYinan Xu self.is_release = 1 if args.release else None 787d45a146SYinan Xu self.is_spike = "Spike" if args.spike else None 7940f31726Sgood-circle self.trace = 1 if args.trace or not args.disable_fork and not args.trace_fst else None 8040f31726Sgood-circle self.trace_fst = "fst" if args.trace_fst else None 816c0058d3SYinan Xu self.config = args.config 82453674e0STang Haojin self.emu_optimize = args.emu_optimize 8354cc3a06STang Haojin self.xprop = 1 if args.xprop else None 840b62a2fbSChen Xi self.with_chiseldb = 0 if args.no_db else 1 85c11a4d2cSYinan Xu # emu arguments 86c11a4d2cSYinan Xu self.max_instr = args.max_instr 8725ac26c6SWilliam Wang self.ram_size = args.ram_size 8859bcbb59SYinan Xu self.seed = random.randint(0, 9999) 89c11a4d2cSYinan Xu self.numa = args.numa 90f9930da0SYinan Xu self.diff = args.diff 9138e9143dSYinan Xu if args.spike and "nemu" in args.diff: 9238e9143dSYinan Xu self.diff = self.diff.replace("nemu-interpreter", "spike") 93078fde2bSJinYue self.fork = not args.disable_fork 949c297294SWilliam Wang self.disable_diff = args.no_diff 95e3cd2c1fSwakafa self.disable_db = args.no_db 96bc247239SXuan Hu self.gcpt_restore_bin = args.gcpt_restore_bin 979810c04aSYangyu Chen self.pgo = args.pgo 989810c04aSYangyu Chen self.pgo_max_cycle = args.pgo_max_cycle 999810c04aSYangyu Chen self.pgo_emu_args = args.pgo_emu_args 1009810c04aSYangyu Chen self.llvm_profdata = args.llvm_profdata 10124e2eab6SJinYue # wave dump path 10224e2eab6SJinYue if args.wave_dump is not None: 10324e2eab6SJinYue self.set_wave_home(args.wave_dump) 10424e2eab6SJinYue else: 10524e2eab6SJinYue self.set_wave_home(self.default_wave_home) 106c11a4d2cSYinan Xu 107c11a4d2cSYinan Xu def get_env_variables(self): 108c11a4d2cSYinan Xu all_env = { 109c11a4d2cSYinan Xu "NOOP_HOME" : self.noop_home, 110c11a4d2cSYinan Xu "NEMU_HOME" : self.nemu_home, 11124e2eab6SJinYue "WAVE_HOME" : self.wave_home, 112c11a4d2cSYinan Xu "AM_HOME" : self.am_home, 113e5597226Swakafa "DRAMSIM3_HOME": self.dramsim3_home, 114e5597226Swakafa "MODULEPATH": "/usr/share/Modules/modulefiles:/etc/modulefiles" 115c11a4d2cSYinan Xu } 116c11a4d2cSYinan Xu return all_env 117c11a4d2cSYinan Xu 118c11a4d2cSYinan Xu def get_chisel_args(self, prefix=None): 119d3126fd3STang Haojin chisel_args = [ 1201545277aSYinan Xu (self.enable_log, "enable-log") 121c11a4d2cSYinan Xu ] 122d3126fd3STang Haojin args = map(lambda x: x[1], filter(lambda arg: arg[0], chisel_args)) 123c11a4d2cSYinan Xu if prefix is not None: 124c11a4d2cSYinan Xu args = map(lambda x: prefix + x, args) 125c11a4d2cSYinan Xu return args 126c11a4d2cSYinan Xu 127c11a4d2cSYinan Xu def get_makefile_args(self): 128c11a4d2cSYinan Xu makefile_args = [ 129c11a4d2cSYinan Xu (self.threads, "EMU_THREADS"), 130c11a4d2cSYinan Xu (self.with_dramsim3, "WITH_DRAMSIM3"), 1311545277aSYinan Xu (self.is_release, "RELEASE"), 13238e9143dSYinan Xu (self.is_spike, "REF"), 1336c0058d3SYinan Xu (self.trace, "EMU_TRACE"), 13440f31726Sgood-circle (self.trace_fst, "EMU_TRACE"), 1355ef7374fSLi Qianruo (self.config, "CONFIG"), 136084afb77STang Haojin (self.num_cores, "NUM_CORES"), 13754cc3a06STang Haojin (self.emu_optimize, "EMU_OPTIMIZE"), 13854cc3a06STang Haojin (self.xprop, "ENABLE_XPROP"), 1399810c04aSYangyu Chen (self.with_chiseldb, "WITH_CHISELDB"), 1409810c04aSYangyu Chen (self.pgo, "PGO_WORKLOAD"), 1419810c04aSYangyu Chen (self.pgo_max_cycle, "PGO_MAX_CYCLE"), 1429810c04aSYangyu Chen (self.pgo_emu_args, "PGO_EMU_ARGS"), 1439810c04aSYangyu Chen (self.llvm_profdata, "LLVM_PROFDATA"), 144c11a4d2cSYinan Xu ] 145c11a4d2cSYinan Xu args = filter(lambda arg: arg[0] is not None, makefile_args) 1469810c04aSYangyu Chen args = [(shlex.quote(str(arg[0])), arg[1]) for arg in args] # shell escape 147c11a4d2cSYinan Xu return args 148c11a4d2cSYinan Xu 149c11a4d2cSYinan Xu def get_emu_args(self): 150c11a4d2cSYinan Xu emu_args = [ 15159bcbb59SYinan Xu (self.max_instr, "max-instr"), 152f9930da0SYinan Xu (self.diff, "diff"), 15325ac26c6SWilliam Wang (self.seed, "seed"), 15425ac26c6SWilliam Wang (self.ram_size, "ram-size"), 155c11a4d2cSYinan Xu ] 156c11a4d2cSYinan Xu args = filter(lambda arg: arg[0] is not None, emu_args) 157c11a4d2cSYinan Xu return args 158c11a4d2cSYinan Xu 159c11a4d2cSYinan Xu def show(self): 160c11a4d2cSYinan Xu print("Extra environment variables:") 161c11a4d2cSYinan Xu env = self.get_env_variables() 162c11a4d2cSYinan Xu for env_name in env: 163c11a4d2cSYinan Xu print(f"{env_name}: {env[env_name]}") 164c11a4d2cSYinan Xu print() 165c11a4d2cSYinan Xu print("Chisel arguments:") 166c11a4d2cSYinan Xu print(" ".join(self.get_chisel_args())) 167c11a4d2cSYinan Xu print() 168c11a4d2cSYinan Xu print("Makefile arguments:") 169c11a4d2cSYinan Xu for val, name in self.get_makefile_args(): 170c11a4d2cSYinan Xu print(f"{name}={val}") 171c11a4d2cSYinan Xu print() 172c11a4d2cSYinan Xu print("emu arguments:") 173c11a4d2cSYinan Xu for val, name in self.get_emu_args(): 174c11a4d2cSYinan Xu print(f"--{name} {val}") 175c11a4d2cSYinan Xu print() 176c11a4d2cSYinan Xu 177c11a4d2cSYinan Xu def __extract_path(self, path, env=None, default=None): 178c11a4d2cSYinan Xu if path is None and env is not None: 179c11a4d2cSYinan Xu path = os.getenv(env) 180c11a4d2cSYinan Xu if path is None and default is not None: 181c11a4d2cSYinan Xu path = default 182c11a4d2cSYinan Xu path = os.path.realpath(path) 183c11a4d2cSYinan Xu return path 184c11a4d2cSYinan Xu 185c11a4d2cSYinan Xu def set_noop_home(self, path): 186c11a4d2cSYinan Xu self.noop_home = path 187c11a4d2cSYinan Xu 188c11a4d2cSYinan Xu def set_nemu_home(self, path): 189c11a4d2cSYinan Xu self.nemu_home = path 190c11a4d2cSYinan Xu 191c11a4d2cSYinan Xu def set_am_home(self, path): 192c11a4d2cSYinan Xu self.am_home = path 193c11a4d2cSYinan Xu 194c11a4d2cSYinan Xu def set_dramsim3_home(self, path): 195c11a4d2cSYinan Xu self.dramsim3_home = path 196c11a4d2cSYinan Xu 197c11a4d2cSYinan Xu def set_rvtest_home(self, path): 198c11a4d2cSYinan Xu self.rvtest_home = path 199c11a4d2cSYinan Xu 20024e2eab6SJinYue def set_wave_home(self, path): 20124e2eab6SJinYue print(f"set wave home to {path}") 20224e2eab6SJinYue self.wave_home = path 20324e2eab6SJinYue 204c11a4d2cSYinan Xu# XiangShan environment 205c11a4d2cSYinan Xuclass XiangShan(object): 206c11a4d2cSYinan Xu def __init__(self, args): 207c11a4d2cSYinan Xu self.args = XSArgs(args) 2089f32a80dSYinan Xu self.timeout = args.timeout 209c11a4d2cSYinan Xu 210c11a4d2cSYinan Xu def show(self): 211c11a4d2cSYinan Xu self.args.show() 212c11a4d2cSYinan Xu 213ef3b5b96SWilliam Wang def make_clean(self): 214ef3b5b96SWilliam Wang print("Clean up CI workspace") 215ef3b5b96SWilliam Wang self.show() 216ef3b5b96SWilliam Wang return_code = self.__exec_cmd(f'make -C $NOOP_HOME clean') 217ef3b5b96SWilliam Wang return return_code 218ef3b5b96SWilliam Wang 219c11a4d2cSYinan Xu def generate_verilog(self): 220c11a4d2cSYinan Xu print("Generating XiangShan verilog with the following configurations:") 221c11a4d2cSYinan Xu self.show() 222c11a4d2cSYinan Xu sim_args = " ".join(self.args.get_chisel_args(prefix="--")) 223c11a4d2cSYinan Xu make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args())) 224c11a4d2cSYinan Xu return_code = self.__exec_cmd(f'make -C $NOOP_HOME verilog SIM_ARGS="{sim_args}" {make_args}') 225c11a4d2cSYinan Xu return return_code 226c11a4d2cSYinan Xu 227e5597226Swakafa def generate_sim_verilog(self): 228e5597226Swakafa print("Generating XiangShan sim-verilog with the following configurations:") 229e5597226Swakafa self.show() 230e5597226Swakafa sim_args = " ".join(self.args.get_chisel_args(prefix="--")) 231e5597226Swakafa make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args())) 232e5597226Swakafa return_code = self.__exec_cmd(f'make -C $NOOP_HOME sim-verilog SIM_ARGS="{sim_args}" {make_args}') 233e5597226Swakafa return return_code 234e5597226Swakafa 235c11a4d2cSYinan Xu def build_emu(self): 236c11a4d2cSYinan Xu print("Building XiangShan emu with the following configurations:") 237c11a4d2cSYinan Xu self.show() 238c11a4d2cSYinan Xu sim_args = " ".join(self.args.get_chisel_args(prefix="--")) 239c11a4d2cSYinan Xu make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args())) 240a3e87608SWilliam Wang return_code = self.__exec_cmd(f'make -C $NOOP_HOME emu -j200 SIM_ARGS="{sim_args}" {make_args}') 241c11a4d2cSYinan Xu return return_code 242c11a4d2cSYinan Xu 243e5597226Swakafa def build_simv(self): 244e5597226Swakafa print("Building XiangShan simv with the following configurations") 245e5597226Swakafa self.show() 246e5597226Swakafa make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args())) 247e5597226Swakafa # TODO: make the following commands grouped as unseen scripts 248e5597226Swakafa return_code = self.__exec_cmd(f'\ 249e5597226Swakafa eval `/usr/bin/modulecmd zsh load license`;\ 250e5597226Swakafa eval `/usr/bin/modulecmd zsh load synopsys/vcs/Q-2020.03-SP2`;\ 251e5597226Swakafa eval `/usr/bin/modulecmd zsh load synopsys/verdi/S-2021.09-SP1`;\ 252e5597226Swakafa VERDI_HOME=/nfs/tools/synopsys/verdi/S-2021.09-SP1 \ 253e5597226Swakafa make -C $NOOP_HOME simv {make_args} CONSIDER_FSDB=1') # set CONSIDER_FSDB for compatibility 254e5597226Swakafa return return_code 255e5597226Swakafa 256c11a4d2cSYinan Xu def run_emu(self, workload): 257c11a4d2cSYinan Xu print("Running XiangShan emu with the following configurations:") 258c11a4d2cSYinan Xu self.show() 259c11a4d2cSYinan Xu emu_args = " ".join(map(lambda arg: f"--{arg[1]} {arg[0]}", self.args.get_emu_args())) 260c11a4d2cSYinan Xu print("workload:", workload) 261c9d90c8dSYinan Xu numa_args = "" 262c9d90c8dSYinan Xu if self.args.numa: 26394e266cbSYinan Xu numa_info = get_free_cores(self.args.threads) 264c9d90c8dSYinan Xu numa_args = f"numactl -m {numa_info[0]} -C {numa_info[1]}-{numa_info[2]}" 265078fde2bSJinYue fork_args = "--enable-fork" if self.args.fork else "" 2669c297294SWilliam Wang diff_args = "--no-diff" if self.args.disable_diff else "" 267e3cd2c1fSwakafa chiseldb_args = "--dump-db" if not self.args.disable_db else "" 268bc247239SXuan Hu gcpt_restore_args = f"-r {self.args.gcpt_restore_bin}" if len(self.args.gcpt_restore_bin) != 0 else "" 269bc247239SXuan 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}') 270c11a4d2cSYinan Xu return return_code 271c11a4d2cSYinan Xu 272e5597226Swakafa def run_simv(self, workload): 273e5597226Swakafa print("Running XiangShan simv with the following configurations:") 274e5597226Swakafa self.show() 275e5597226Swakafa diff_args = "$NOOP_HOME/"+ args.diff 27654cc3a06STang Haojin assert_args = "-assert finish_maxfail=30 -assert global_finish_maxfail=10000" 277ae0295f4STang 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') 278823787d8STang Haojin with open(f"{self.args.noop_home}/build/simv.log") as f: 279ae0295f4STang Haojin content = f.read() 280ae0295f4STang Haojin if "Offending" in content or "HIT GOOD TRAP" not in content: 281823787d8STang Haojin return 1 282ae0295f4STang Haojin return return_code 283e5597226Swakafa 284c11a4d2cSYinan Xu def run(self, args): 285c11a4d2cSYinan Xu if args.ci is not None: 286c11a4d2cSYinan Xu return self.run_ci(args.ci) 287e5597226Swakafa if args.ci_vcs is not None: 288e5597226Swakafa return self.run_ci_vcs(args.ci_vcs) 289c11a4d2cSYinan Xu actions = [ 290c11a4d2cSYinan Xu (args.generate, lambda _ : self.generate_verilog()), 291e5597226Swakafa (args.vcs_gen, lambda _ : self.generate_sim_verilog()), 292c11a4d2cSYinan Xu (args.build, lambda _ : self.build_emu()), 293e5597226Swakafa (args.vcs_build, lambda _ : self.build_simv()), 294ef3b5b96SWilliam Wang (args.workload, lambda args: self.run_emu(args.workload)), 295ef3b5b96SWilliam Wang (args.clean, lambda _ : self.make_clean()) 296c11a4d2cSYinan Xu ] 297c11a4d2cSYinan Xu valid_actions = map(lambda act: act[1], filter(lambda act: act[0], actions)) 298c11a4d2cSYinan Xu for i, action in enumerate(valid_actions): 299c11a4d2cSYinan Xu print(f"Action {i}:") 300c11a4d2cSYinan Xu ret = action(args) 301c11a4d2cSYinan Xu if ret: 302c11a4d2cSYinan Xu return ret 303c11a4d2cSYinan Xu return 0 304c11a4d2cSYinan Xu 305c11a4d2cSYinan Xu def __exec_cmd(self, cmd): 306c11a4d2cSYinan Xu env = dict(os.environ) 307c11a4d2cSYinan Xu env.update(self.args.get_env_variables()) 308c11a4d2cSYinan Xu print("subprocess call cmd:", cmd) 3095ef7374fSLi Qianruo start = time.time() 3109f32a80dSYinan Xu proc = subprocess.Popen(cmd, shell=True, env=env, preexec_fn=os.setsid) 3119f32a80dSYinan Xu try: 3129f32a80dSYinan Xu return_code = proc.wait(self.timeout) 3135ef7374fSLi Qianruo end = time.time() 3145ef7374fSLi Qianruo print(f"Elapsed time: {end - start} seconds") 315c11a4d2cSYinan Xu return return_code 3169f32a80dSYinan Xu except (KeyboardInterrupt, subprocess.TimeoutExpired): 3179f32a80dSYinan Xu os.killpg(os.getpgid(proc.pid), signal.SIGINT) 3189f32a80dSYinan Xu print(f"KeyboardInterrupt or TimeoutExpired.") 3199f32a80dSYinan Xu return 0 320c11a4d2cSYinan Xu 321c11a4d2cSYinan Xu def __get_ci_cputest(self, name=None): 3220d7009bfSXu, Zefan # base_dir = os.path.join(self.args.am_home, "tests/cputest/build") 3230d7009bfSXu, Zefan base_dir = "/nfs/home/share/ci-workloads/nexus-am-workloads/tests/cputest" 324c11a4d2cSYinan Xu cputest = os.listdir(base_dir) 325c11a4d2cSYinan Xu cputest = filter(lambda x: x.endswith(".bin"), cputest) 326c11a4d2cSYinan Xu cputest = map(lambda x: os.path.join(base_dir, x), cputest) 327c11a4d2cSYinan Xu return cputest 328c11a4d2cSYinan Xu 329c11a4d2cSYinan Xu def __get_ci_rvtest(self, name=None): 330c11a4d2cSYinan Xu base_dir = os.path.join(self.args.rvtest_home, "isa/build") 331c11a4d2cSYinan Xu riscv_tests = os.listdir(base_dir) 332c11a4d2cSYinan Xu riscv_tests = filter(lambda x: x.endswith(".bin"), riscv_tests) 33341d8d239Shappy-lx all_rv_tests = ["rv64ui", "rv64um", "rv64ua", "rv64uf", "rv64ud", "rv64mi"] 334c11a4d2cSYinan Xu riscv_tests = filter(lambda x: x[:6] in all_rv_tests, riscv_tests) 335c11a4d2cSYinan Xu riscv_tests = map(lambda x: os.path.join(base_dir, x), riscv_tests) 336c11a4d2cSYinan Xu return riscv_tests 337c11a4d2cSYinan Xu 338675acc68SYinan Xu def __get_ci_misc(self, name=None): 339da3b568bSYinan Xu base_dir = "/nfs/home/share/ci-workloads" 340675acc68SYinan Xu workloads = [ 341675acc68SYinan Xu "bitmanip/bitMisc.bin", 3423feeca58Szfw "crypto/crypto-riscv64-noop.bin", 3430d7009bfSXu, Zefan # "coremark_rv64gc_o2/coremark-riscv64-xs.bin", 3440d7009bfSXu, Zefan # "coremark_rv64gc_o3/coremark-riscv64-xs.bin", 3450d7009bfSXu, Zefan # "coremark_rv64gcb_o3/coremark-riscv64-xs.bin", 3460d7009bfSXu, Zefan "nexus-am-workloads/amtest/external_intr-riscv64-xs.bin", 3470d7009bfSXu, Zefan "nexus-am-workloads/tests/aliastest/aliastest-riscv64-xs.bin", 348af2f7849Shappy-lx "Svinval/rv64mi-p-svinval.bin", 349b6982e83SLemover "pmp/pmp.riscv.bin", 3500d7009bfSXu, Zefan "nexus-am-workloads/amtest/pmp_test-riscv64-xs.bin", 3510d7009bfSXu, Zefan "nexus-am-workloads/amtest/sv39_hp_atom_test-riscv64-xs.bin", 35245f497a4Shappy-lx "asid/asid.bin", 3537d9edc86SLemover "isa_misc/xret_clear_mprv.bin", 354705cbec3SLemover "isa_misc/satp_ppn.bin", 3559c297294SWilliam Wang "cache-management/softprefetchtest-riscv64-xs.bin" 356675acc68SYinan Xu ] 357675acc68SYinan Xu misc_tests = map(lambda x: os.path.join(base_dir, x), workloads) 358675acc68SYinan Xu return misc_tests 359675acc68SYinan Xu 3601f903014SXu, Zefan def __get_ci_rvhtest(self, name=None): 3611f903014SXu, Zefan base_dir = "/nfs/home/share/ci-workloads/H-extension-tests" 3621f903014SXu, Zefan workloads = [ 363afdeb382SXu, Zefan "riscv-hyp-tests/rvh_test.bin", 3641f903014SXu, Zefan "xvisor_wboxtest/checkpoint.gz", 3651f903014SXu, Zefan ] 3661f903014SXu, Zefan rvh_tests = map(lambda x: os.path.join(base_dir, x), workloads) 3671f903014SXu, Zefan return rvh_tests 3681f903014SXu, Zefan 3696ebd27e9Slwd def __get_ci_rvvbench(self, name=None): 3706ebd27e9Slwd base_dir = "/nfs/home/share/ci-workloads" 3716ebd27e9Slwd workloads = [ 3726ebd27e9Slwd "rvv-bench/poly1305.bin", 3736ebd27e9Slwd "rvv-bench/mergelines.bin" 3746ebd27e9Slwd ] 3756ebd27e9Slwd rvvbench = map(lambda x: os.path.join(base_dir, x), workloads) 3766ebd27e9Slwd return rvvbench 3776ebd27e9Slwd 3786ebd27e9Slwd def __get_ci_rvvtest(self, name=None): 3796ebd27e9Slwd base_dir = "/nfs/home/share/ci-workloads/V-extension-tests" 3806ebd27e9Slwd workloads = [ 3816ebd27e9Slwd "rvv-test/vluxei32.v-0.bin", 3826ebd27e9Slwd "rvv-test/vlsseg4e32.v-0.bin", 3836ebd27e9Slwd "rvv-test/vlseg4e32.v-0.bin", 3846ebd27e9Slwd "rvv-test/vsetvl-0.bin", 3856ebd27e9Slwd "rvv-test/vsetivli-0.bin", 3866ebd27e9Slwd "rvv-test/vsuxei32.v-0.bin", 3876ebd27e9Slwd "rvv-test/vse16.v-0.bin", 3886ebd27e9Slwd "rvv-test/vsse16.v-1.bin", 3896ebd27e9Slwd "rvv-test/vlse32.v-0.bin", 3906ebd27e9Slwd "rvv-test/vsetvli-0.bin", 3916ebd27e9Slwd "rvv-test/vle16.v-0.bin", 3926ebd27e9Slwd "rvv-test/vle32.v-0.bin", 3936ebd27e9Slwd "rvv-test/vfsgnj.vv-0.bin", 3946ebd27e9Slwd "rvv-test/vfadd.vf-0.bin", 3956ebd27e9Slwd "rvv-test/vfsub.vf-0.bin", 3966ebd27e9Slwd "rvv-test/vslide1down.vx-0.bin" 3976ebd27e9Slwd ] 3986ebd27e9Slwd rvv_test = map(lambda x: os.path.join(base_dir, x), workloads) 3996ebd27e9Slwd return rvv_test 4006ebd27e9Slwd 401ef3b5b96SWilliam Wang def __get_ci_mc(self, name=None): 402ef3b5b96SWilliam Wang base_dir = "/nfs/home/share/ci-workloads" 403ef3b5b96SWilliam Wang workloads = [ 4040d7009bfSXu, Zefan "nexus-am-workloads/tests/dualcoretest/ldvio-riscv64-xs.bin" 405ef3b5b96SWilliam Wang ] 406ef3b5b96SWilliam Wang mc_tests = map(lambda x: os.path.join(base_dir, x), workloads) 407ef3b5b96SWilliam Wang return mc_tests 408ef3b5b96SWilliam Wang 4099c297294SWilliam Wang def __get_ci_nodiff(self, name=None): 410da3b568bSYinan Xu base_dir = "/nfs/home/share/ci-workloads" 4119c297294SWilliam Wang workloads = [ 4129c297294SWilliam Wang "cache-management/cacheoptest-riscv64-xs.bin" 4139c297294SWilliam Wang ] 4149c297294SWilliam Wang tests = map(lambda x: os.path.join(base_dir, x), workloads) 4159c297294SWilliam Wang return tests 4169c297294SWilliam Wang 417c11a4d2cSYinan Xu def __am_apps_path(self, bench): 4180d7009bfSXu, Zefan base_dir = '/nfs/home/share/ci-workloads/nexus-am-workloads/apps' 4190d7009bfSXu, Zefan filename = f"{bench}-riscv64-xs.bin" 4200d7009bfSXu, Zefan return [os.path.join(base_dir, bench, filename)] 421c11a4d2cSYinan Xu 422c11a4d2cSYinan Xu def __get_ci_workloads(self, name): 423c11a4d2cSYinan Xu workloads = { 424c11a4d2cSYinan Xu "linux-hello": "bbl.bin", 425fac0ab56Swakafa "linux-hello-smp": "bbl.bin", 4264a8a734eSceba "linux-hello-opensbi": "fw_payload.bin", 4274a8a734eSceba "linux-hello-smp-opensbi": "fw_payload.bin", 428e975de62STang Haojin "linux-hello-new": "bbl.bin", 429e975de62STang Haojin "linux-hello-smp-new": "bbl.bin", 430609a6cf0Schengguanghui "linux-hello-smp-newcsr": "bbl.bin", 4315092a298Szfw "povray": "_700480000000_.gz", 4325092a298Szfw "mcf": "_17520000000_.gz", 4335092a298Szfw "xalancbmk": "_266100000000_.gz", 4345092a298Szfw "gcc": "_39720000000_.gz", 4355092a298Szfw "namd": "_434640000000_.gz", 4365092a298Szfw "milc": "_103620000000_.gz", 4375092a298Szfw "lbm": "_140840000000_.gz", 4387b441e5eSYinan Xu "gromacs": "_275480000000_.gz", 4397b441e5eSYinan Xu "wrf": "_1916220000000_.gz", 4407b441e5eSYinan Xu "astar": "_122060000000_.gz" 441c11a4d2cSYinan Xu } 4429f32a80dSYinan Xu if name in workloads: 443da3b568bSYinan Xu return [os.path.join("/nfs/home/share/ci-workloads", name, workloads[name])] 4449f32a80dSYinan Xu # select a random SPEC checkpoint 4459f32a80dSYinan Xu assert(name == "random") 4469f32a80dSYinan Xu all_cpt = [ 4479f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o2_20m/take_cpt", 4489f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o3_20m/take_cpt", 4499f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_20m/take_cpt", 4509f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_50m/take_cpt", 4519f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o2_20m/take_cpt", 4529f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o3_20m/take_cpt", 4539f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gc_o2_50m/take_cpt", 4549f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_speed_rv64gcb_o3_20m/take_cpt" 4559f32a80dSYinan Xu ] 4569f32a80dSYinan Xu all_json = [ 4579f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o2_20m/json/simpoint_summary.json", 4589f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o3_20m/simpoint_summary.json", 4599f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_20m/simpoint_summary.json", 4609f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_50m/simpoint_summary.json", 4619f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o2_20m/simpoint_summary.json", 4629f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o3_20m/simpoint_summary.json", 4639f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gc_o2_50m/simpoint_summary.json", 4649f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_speed_rv64gcb_o3_20m/simpoint_summary.json" 4659f32a80dSYinan Xu ] 4669f32a80dSYinan Xu assert(len(all_cpt) == len(all_json)) 4679f32a80dSYinan Xu cpt_path, json_path = random.choice(list(zip(all_cpt, all_json))) 4689f32a80dSYinan Xu all_gcpt = load_all_gcpt(cpt_path, json_path) 4699f32a80dSYinan Xu return [random.choice(all_gcpt)] 470c11a4d2cSYinan Xu 471c11a4d2cSYinan Xu def run_ci(self, test): 472c11a4d2cSYinan Xu all_tests = { 473c11a4d2cSYinan Xu "cputest": self.__get_ci_cputest, 474c11a4d2cSYinan Xu "riscv-tests": self.__get_ci_rvtest, 475675acc68SYinan Xu "misc-tests": self.__get_ci_misc, 476ef3b5b96SWilliam Wang "mc-tests": self.__get_ci_mc, 4779c297294SWilliam Wang "nodiff-tests": self.__get_ci_nodiff, 4781f903014SXu, Zefan "rvh-tests": self.__get_ci_rvhtest, 479c11a4d2cSYinan Xu "microbench": self.__am_apps_path, 4806ebd27e9Slwd "coremark": self.__am_apps_path, 481*20156f77STang Haojin "coremark-1-iteration": self.__am_apps_path, 4826ebd27e9Slwd "rvv-bench": self.__get_ci_rvvbench, 4836ebd27e9Slwd "rvv-test": self.__get_ci_rvvtest 484c11a4d2cSYinan Xu } 485c11a4d2cSYinan Xu for target in all_tests.get(test, self.__get_ci_workloads)(test): 486c11a4d2cSYinan Xu print(target) 487c11a4d2cSYinan Xu ret = self.run_emu(target) 488c11a4d2cSYinan Xu if ret: 48924e2eab6SJinYue if self.args.default_wave_home != self.args.wave_home: 49024e2eab6SJinYue print("copy wave file to " + self.args.wave_home) 49124e2eab6SJinYue self.__exec_cmd(f"cp $NOOP_HOME/build/*.vcd $WAVE_HOME") 492bc063562SLemover self.__exec_cmd(f"cp $NOOP_HOME/build/emu $WAVE_HOME") 49345f43e6eSTang Haojin self.__exec_cmd(f"cp $NOOP_HOME/build/rtl/SimTop.v $WAVE_HOME") 494e3cd2c1fSwakafa self.__exec_cmd(f"cp $NOOP_HOME/build/*.db $WAVE_HOME") 495c11a4d2cSYinan Xu return ret 496c11a4d2cSYinan Xu return 0 497c11a4d2cSYinan Xu 498e5597226Swakafa def run_ci_vcs(self, test): 499e5597226Swakafa all_tests = { 500e5597226Swakafa "cputest": self.__get_ci_cputest, 501e5597226Swakafa "riscv-tests": self.__get_ci_rvtest, 502e5597226Swakafa "misc-tests": self.__get_ci_misc, 503e5597226Swakafa "mc-tests": self.__get_ci_mc, 504e5597226Swakafa "nodiff-tests": self.__get_ci_nodiff, 5051f903014SXu, Zefan "rvh-tests": self.__get_ci_rvhtest, 506e5597226Swakafa "microbench": self.__am_apps_path, 5076ebd27e9Slwd "coremark": self.__am_apps_path, 508*20156f77STang Haojin "coremark-1-iteration": self.__am_apps_path, 5096ebd27e9Slwd "rvv-bench": self.__get_ci_rvvbench, 5106ebd27e9Slwd "rvv-test": self.__get_ci_rvvtest 511e5597226Swakafa } 512e5597226Swakafa for target in all_tests.get(test, self.__get_ci_workloads)(test): 513e5597226Swakafa print(target) 514e5597226Swakafa ret = self.run_simv(target) 515e5597226Swakafa if ret: 516e5597226Swakafa if self.args.default_wave_home != self.args.wave_home: 517e5597226Swakafa print("copy wave file to " + self.args.wave_home) 51854cc3a06STang Haojin self.__exec_cmd(f"cp $NOOP_HOME/build/*.fsdb $WAVE_HOME") 51954cc3a06STang Haojin self.__exec_cmd(f"cp $NOOP_HOME/build/simv $WAVE_HOME") 52045f43e6eSTang Haojin self.__exec_cmd(f"cp $NOOP_HOME/build/rtl/SimTop.v $WAVE_HOME") 521e3cd2c1fSwakafa self.__exec_cmd(f"cp $NOOP_HOME/build/*.db $WAVE_HOME") 522e5597226Swakafa return ret 523e5597226Swakafa return 0 524e5597226Swakafa 52594e266cbSYinan Xudef get_free_cores(n): 526a941bfc4STang Haojin numa_re = re.compile(r'.*numactl +.*-C +([0-9]+)-([0-9]+).*') 52794e266cbSYinan Xu while True: 528a941bfc4STang Haojin disable_cores = [] 529a941bfc4STang Haojin for proc in psutil.process_iter(): 530a941bfc4STang Haojin try: 531a941bfc4STang Haojin joint = ' '.join(proc.cmdline()) 532a941bfc4STang Haojin numa_match = numa_re.match(joint) 533dd720caeSTang Haojin if numa_match and 'ssh' not in proc.name(): 534a941bfc4STang Haojin disable_cores.extend(range(int(numa_match.group(1)), int(numa_match.group(2)) + 1)) 535a941bfc4STang Haojin except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): 536a941bfc4STang Haojin pass 537b86f926fSYinan Xu num_logical_core = psutil.cpu_count(logical=False) 53894e266cbSYinan Xu core_usage = psutil.cpu_percent(interval=1, percpu=True) 53994e266cbSYinan Xu num_window = num_logical_core // n 54094e266cbSYinan Xu for i in range(num_window): 541a941bfc4STang Haojin if set(disable_cores) & set(range(i * n, i * n + n)): 542a941bfc4STang Haojin continue 54394e266cbSYinan Xu window_usage = core_usage[i * n : i * n + n] 54401a51437SYinan Xu if sum(window_usage) < 30 * n and True not in map(lambda x: x > 90, window_usage): 54571f0f4ccSTang Haojin return (((i * n) % num_logical_core) // (num_logical_core // 2), i * n, i * n + n - 1) 54694e266cbSYinan Xu print(f"No free {n} cores found. CPU usage: {core_usage}\n") 54743f08742STang Haojin time.sleep(random.uniform(1, 60)) 54894e266cbSYinan Xu 549c11a4d2cSYinan Xuif __name__ == "__main__": 550c11a4d2cSYinan Xu parser = argparse.ArgumentParser(description='Python wrapper for XiangShan') 551c11a4d2cSYinan Xu parser.add_argument('workload', nargs='?', type=str, default="", 552c11a4d2cSYinan Xu help='input workload file in binary format') 553c11a4d2cSYinan Xu # actions 554c11a4d2cSYinan Xu parser.add_argument('--build', action='store_true', help='build XS emu') 555c11a4d2cSYinan Xu parser.add_argument('--generate', action='store_true', help='generate XS verilog') 556e5597226Swakafa parser.add_argument('--vcs-gen', action='store_true', help='generate XS sim verilog for vcs') 557e5597226Swakafa parser.add_argument('--vcs-build', action='store_true', help='build XS simv') 558c11a4d2cSYinan Xu parser.add_argument('--ci', nargs='?', type=str, const="", help='run CI tests') 559e5597226Swakafa parser.add_argument('--ci-vcs', nargs='?', type=str, const="", help='run CI tests on simv') 560ef3b5b96SWilliam Wang parser.add_argument('--clean', action='store_true', help='clean up XiangShan CI workspace') 5619f32a80dSYinan Xu parser.add_argument('--timeout', nargs='?', type=int, default=None, help='timeout (in seconds)') 562c11a4d2cSYinan Xu # environment variables 563c11a4d2cSYinan Xu parser.add_argument('--nemu', nargs='?', type=str, help='path to nemu') 564c11a4d2cSYinan Xu parser.add_argument('--am', nargs='?', type=str, help='path to nexus-am') 565c11a4d2cSYinan Xu parser.add_argument('--dramsim3', nargs='?', type=str, help='path to dramsim3') 566c11a4d2cSYinan Xu parser.add_argument('--rvtest', nargs='?', type=str, help='path to riscv-tests') 56724e2eab6SJinYue parser.add_argument('--wave-dump', nargs='?', type=str , help='path to dump wave') 568c11a4d2cSYinan Xu # chisel arguments 5691545277aSYinan Xu parser.add_argument('--enable-log', action='store_true', help='enable log') 5705ef7374fSLi Qianruo parser.add_argument('--num-cores', type=int, help='number of cores') 571c11a4d2cSYinan Xu # makefile arguments 5721545277aSYinan Xu parser.add_argument('--release', action='store_true', help='enable release') 57338e9143dSYinan Xu parser.add_argument('--spike', action='store_true', help='enable spike diff') 574c11a4d2cSYinan Xu parser.add_argument('--with-dramsim3', action='store_true', help='enable dramsim3') 575c11a4d2cSYinan Xu parser.add_argument('--threads', nargs='?', type=int, help='number of emu threads') 57640f31726Sgood-circle parser.add_argument('--trace', action='store_true', help='enable vcd waveform') 57740f31726Sgood-circle parser.add_argument('--trace-fst', action='store_true', help='enable fst waveform') 5786c0058d3SYinan Xu parser.add_argument('--config', nargs='?', type=str, help='config') 579453674e0STang Haojin parser.add_argument('--emu-optimize', nargs='?', type=str, help='verilator optimization letter') 58054cc3a06STang Haojin parser.add_argument('--xprop', action='store_true', help='enable xprop for vcs') 581c11a4d2cSYinan Xu # emu arguments 582c11a4d2cSYinan Xu parser.add_argument('--numa', action='store_true', help='use numactl') 583f9930da0SYinan Xu parser.add_argument('--diff', nargs='?', default="./ready-to-run/riscv64-nemu-interpreter-so", type=str, help='nemu so') 584c11a4d2cSYinan Xu parser.add_argument('--max-instr', nargs='?', type=int, help='max instr') 585078fde2bSJinYue parser.add_argument('--disable-fork', action='store_true', help='disable lightSSS') 5869c297294SWilliam Wang parser.add_argument('--no-diff', action='store_true', help='disable difftest') 58725ac26c6SWilliam Wang parser.add_argument('--ram-size', nargs='?', type=str, help='manually set simulation memory size (8GB by default)') 588bc247239SXuan Hu parser.add_argument('--gcpt-restore-bin', type=str, default="", help="specify the bin used to restore from gcpt") 58954cc3a06STang Haojin # both makefile and emu arguments 590e3cd2c1fSwakafa parser.add_argument('--no-db', action='store_true', help='disable chiseldb dump') 5919810c04aSYangyu Chen parser.add_argument('--pgo', nargs='?', type=str, help='workload for pgo (null to disable pgo)') 5929810c04aSYangyu Chen parser.add_argument('--pgo-max-cycle', nargs='?', default=400000, type=int, help='maximun cycle to train pgo') 5939810c04aSYangyu Chen parser.add_argument('--pgo-emu-args', nargs='?', default='--no-diff', type=str, help='emu arguments for pgo') 5949810c04aSYangyu Chen parser.add_argument('--llvm-profdata', nargs='?', type=str, help='corresponding llvm-profdata command of clang to compile emu, do not set with GCC') 595c11a4d2cSYinan Xu 596c11a4d2cSYinan Xu args = parser.parse_args() 597c11a4d2cSYinan Xu 598c11a4d2cSYinan Xu xs = XiangShan(args) 599c11a4d2cSYinan Xu ret = xs.run(args) 600c11a4d2cSYinan Xu 601c11a4d2cSYinan Xu sys.exit(ret) 602