1c6d43980SLemover#*************************************************************************************** 2c6d43980SLemover# Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3f320e0f0SYinan Xu# Copyright (c) 2020-2021 Peng Cheng Laboratory 4c6d43980SLemover# 5c6d43980SLemover# XiangShan is licensed under Mulan PSL v2. 6c6d43980SLemover# You can use this software according to the terms and conditions of the Mulan PSL v2. 7c6d43980SLemover# You may obtain a copy of Mulan PSL v2 at: 8c6d43980SLemover# http://license.coscl.org.cn/MulanPSL2 9c6d43980SLemover# 10c6d43980SLemover# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11c6d43980SLemover# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12c6d43980SLemover# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13c6d43980SLemover# 14c6d43980SLemover# See the Mulan PSL v2 for more details. 15c6d43980SLemover#*************************************************************************************** 16c6d43980SLemover 17c11a4d2cSYinan Xu# Simple version of xiangshan python wrapper 18c11a4d2cSYinan Xu 19c11a4d2cSYinan Xuimport argparse 209f32a80dSYinan Xuimport json 2159bcbb59SYinan Xuimport os 2259bcbb59SYinan Xuimport random 239f32a80dSYinan Xuimport signal 24c11a4d2cSYinan Xuimport subprocess 2559bcbb59SYinan Xuimport sys 265ef7374fSLi Qianruoimport time 27c11a4d2cSYinan Xu 2894e266cbSYinan Xuimport psutil 2994e266cbSYinan Xu 30c11a4d2cSYinan Xu 319f32a80dSYinan Xudef load_all_gcpt(gcpt_path, json_path): 329f32a80dSYinan Xu all_gcpt = [] 339f32a80dSYinan Xu with open(json_path) as f: 349f32a80dSYinan Xu data = json.load(f) 359f32a80dSYinan Xu for benchspec in data: 369f32a80dSYinan Xu for point in data[benchspec]: 379f32a80dSYinan Xu weight = data[benchspec][point] 389f32a80dSYinan Xu gcpt = os.path.join(gcpt_path, "_".join([benchspec, point, weight])) 399f32a80dSYinan Xu bin_dir = os.path.join(gcpt, "0") 409f32a80dSYinan Xu bin_file = list(os.listdir(bin_dir)) 419f32a80dSYinan Xu assert(len(bin_file) == 1) 429f32a80dSYinan Xu bin_path = os.path.join(bin_dir, bin_file[0]) 439f32a80dSYinan Xu assert(os.path.isfile(bin_path)) 449f32a80dSYinan Xu all_gcpt.append(bin_path) 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 7738e9143dSYinan Xu self.is_spike = "spike" if args.spike else None 78eb852d4cSJinYue self.trace = 1 if args.trace or not args.disable_fork else None 796c0058d3SYinan Xu self.config = args.config 80c11a4d2cSYinan Xu # emu arguments 81c11a4d2cSYinan Xu self.max_instr = args.max_instr 82*25ac26c6SWilliam Wang self.ram_size = args.ram_size 8359bcbb59SYinan Xu self.seed = random.randint(0, 9999) 84c11a4d2cSYinan Xu self.numa = args.numa 85f9930da0SYinan Xu self.diff = args.diff 8638e9143dSYinan Xu if args.spike and "nemu" in args.diff: 8738e9143dSYinan Xu self.diff = self.diff.replace("nemu-interpreter", "spike") 88078fde2bSJinYue self.fork = not args.disable_fork 899c297294SWilliam Wang self.disable_diff = args.no_diff 9024e2eab6SJinYue # wave dump path 9124e2eab6SJinYue if args.wave_dump is not None: 9224e2eab6SJinYue self.set_wave_home(args.wave_dump) 9324e2eab6SJinYue else: 9424e2eab6SJinYue self.set_wave_home(self.default_wave_home) 95c11a4d2cSYinan Xu 96c11a4d2cSYinan Xu def get_env_variables(self): 97c11a4d2cSYinan Xu all_env = { 98c11a4d2cSYinan Xu "NOOP_HOME" : self.noop_home, 99c11a4d2cSYinan Xu "NEMU_HOME" : self.nemu_home, 10024e2eab6SJinYue "WAVE_HOME" : self.wave_home, 101c11a4d2cSYinan Xu "AM_HOME" : self.am_home, 102c11a4d2cSYinan Xu "DRAMSIM3_HOME": self.dramsim3_home 103c11a4d2cSYinan Xu } 104c11a4d2cSYinan Xu return all_env 105c11a4d2cSYinan Xu 106c11a4d2cSYinan Xu def get_chisel_args(self, prefix=None): 107c11a4d2cSYinan Xu chisel_args = [ 1081545277aSYinan Xu (self.enable_log, "enable-log") 109c11a4d2cSYinan Xu ] 110c11a4d2cSYinan Xu args = map(lambda x: x[1], filter(lambda arg: arg[0], chisel_args)) 111c11a4d2cSYinan Xu if prefix is not None: 112c11a4d2cSYinan Xu args = map(lambda x: prefix + x, args) 113c11a4d2cSYinan Xu return args 114c11a4d2cSYinan Xu 115c11a4d2cSYinan Xu def get_makefile_args(self): 116c11a4d2cSYinan Xu makefile_args = [ 117c11a4d2cSYinan Xu (self.threads, "EMU_THREADS"), 118c11a4d2cSYinan Xu (self.with_dramsim3, "WITH_DRAMSIM3"), 1191545277aSYinan Xu (self.is_release, "RELEASE"), 12038e9143dSYinan Xu (self.is_spike, "REF"), 1216c0058d3SYinan Xu (self.trace, "EMU_TRACE"), 1225ef7374fSLi Qianruo (self.config, "CONFIG"), 1235ef7374fSLi Qianruo (self.num_cores, "NUM_CORES") 124c11a4d2cSYinan Xu ] 125c11a4d2cSYinan Xu args = filter(lambda arg: arg[0] is not None, makefile_args) 126c11a4d2cSYinan Xu return args 127c11a4d2cSYinan Xu 128c11a4d2cSYinan Xu def get_emu_args(self): 129c11a4d2cSYinan Xu emu_args = [ 13059bcbb59SYinan Xu (self.max_instr, "max-instr"), 131f9930da0SYinan Xu (self.diff, "diff"), 132*25ac26c6SWilliam Wang (self.seed, "seed"), 133*25ac26c6SWilliam Wang (self.ram_size, "ram-size"), 134c11a4d2cSYinan Xu ] 135c11a4d2cSYinan Xu args = filter(lambda arg: arg[0] is not None, emu_args) 136c11a4d2cSYinan Xu return args 137c11a4d2cSYinan Xu 138c11a4d2cSYinan Xu def show(self): 139c11a4d2cSYinan Xu print("Extra environment variables:") 140c11a4d2cSYinan Xu env = self.get_env_variables() 141c11a4d2cSYinan Xu for env_name in env: 142c11a4d2cSYinan Xu print(f"{env_name}: {env[env_name]}") 143c11a4d2cSYinan Xu print() 144c11a4d2cSYinan Xu print("Chisel arguments:") 145c11a4d2cSYinan Xu print(" ".join(self.get_chisel_args())) 146c11a4d2cSYinan Xu print() 147c11a4d2cSYinan Xu print("Makefile arguments:") 148c11a4d2cSYinan Xu for val, name in self.get_makefile_args(): 149c11a4d2cSYinan Xu print(f"{name}={val}") 150c11a4d2cSYinan Xu print() 151c11a4d2cSYinan Xu print("emu arguments:") 152c11a4d2cSYinan Xu for val, name in self.get_emu_args(): 153c11a4d2cSYinan Xu print(f"--{name} {val}") 154c11a4d2cSYinan Xu print() 155c11a4d2cSYinan Xu 156c11a4d2cSYinan Xu def __extract_path(self, path, env=None, default=None): 157c11a4d2cSYinan Xu if path is None and env is not None: 158c11a4d2cSYinan Xu path = os.getenv(env) 159c11a4d2cSYinan Xu if path is None and default is not None: 160c11a4d2cSYinan Xu path = default 161c11a4d2cSYinan Xu path = os.path.realpath(path) 162c11a4d2cSYinan Xu return path 163c11a4d2cSYinan Xu 164c11a4d2cSYinan Xu def set_noop_home(self, path): 165c11a4d2cSYinan Xu self.noop_home = path 166c11a4d2cSYinan Xu 167c11a4d2cSYinan Xu def set_nemu_home(self, path): 168c11a4d2cSYinan Xu self.nemu_home = path 169c11a4d2cSYinan Xu 170c11a4d2cSYinan Xu def set_am_home(self, path): 171c11a4d2cSYinan Xu self.am_home = path 172c11a4d2cSYinan Xu 173c11a4d2cSYinan Xu def set_dramsim3_home(self, path): 174c11a4d2cSYinan Xu self.dramsim3_home = path 175c11a4d2cSYinan Xu 176c11a4d2cSYinan Xu def set_rvtest_home(self, path): 177c11a4d2cSYinan Xu self.rvtest_home = path 178c11a4d2cSYinan Xu 17924e2eab6SJinYue def set_wave_home(self, path): 18024e2eab6SJinYue print(f"set wave home to {path}") 18124e2eab6SJinYue self.wave_home = path 18224e2eab6SJinYue 183c11a4d2cSYinan Xu# XiangShan environment 184c11a4d2cSYinan Xuclass XiangShan(object): 185c11a4d2cSYinan Xu def __init__(self, args): 186c11a4d2cSYinan Xu self.args = XSArgs(args) 1879f32a80dSYinan Xu self.timeout = args.timeout 188c11a4d2cSYinan Xu 189c11a4d2cSYinan Xu def show(self): 190c11a4d2cSYinan Xu self.args.show() 191c11a4d2cSYinan Xu 192ef3b5b96SWilliam Wang def make_clean(self): 193ef3b5b96SWilliam Wang print("Clean up CI workspace") 194ef3b5b96SWilliam Wang self.show() 195ef3b5b96SWilliam Wang return_code = self.__exec_cmd(f'make -C $NOOP_HOME clean') 196ef3b5b96SWilliam Wang return return_code 197ef3b5b96SWilliam Wang 198c11a4d2cSYinan Xu def generate_verilog(self): 199c11a4d2cSYinan Xu print("Generating XiangShan verilog with the following configurations:") 200c11a4d2cSYinan Xu self.show() 201c11a4d2cSYinan Xu sim_args = " ".join(self.args.get_chisel_args(prefix="--")) 202c11a4d2cSYinan Xu make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args())) 203c11a4d2cSYinan Xu return_code = self.__exec_cmd(f'make -C $NOOP_HOME verilog SIM_ARGS="{sim_args}" {make_args}') 204c11a4d2cSYinan Xu return return_code 205c11a4d2cSYinan Xu 206c11a4d2cSYinan Xu def build_emu(self): 207c11a4d2cSYinan Xu print("Building XiangShan emu with the following configurations:") 208c11a4d2cSYinan Xu self.show() 209c11a4d2cSYinan Xu sim_args = " ".join(self.args.get_chisel_args(prefix="--")) 210c11a4d2cSYinan Xu make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args())) 211a3e87608SWilliam Wang return_code = self.__exec_cmd(f'make -C $NOOP_HOME emu -j200 SIM_ARGS="{sim_args}" {make_args}') 212c11a4d2cSYinan Xu return return_code 213c11a4d2cSYinan Xu 214c11a4d2cSYinan Xu def run_emu(self, workload): 215c11a4d2cSYinan Xu print("Running XiangShan emu with the following configurations:") 216c11a4d2cSYinan Xu self.show() 217c11a4d2cSYinan Xu emu_args = " ".join(map(lambda arg: f"--{arg[1]} {arg[0]}", self.args.get_emu_args())) 218c11a4d2cSYinan Xu print("workload:", workload) 219c9d90c8dSYinan Xu numa_args = "" 220c9d90c8dSYinan Xu if self.args.numa: 22194e266cbSYinan Xu numa_info = get_free_cores(self.args.threads) 222c9d90c8dSYinan Xu numa_args = f"numactl -m {numa_info[0]} -C {numa_info[1]}-{numa_info[2]}" 223078fde2bSJinYue fork_args = "--enable-fork" if self.args.fork else "" 2249c297294SWilliam Wang diff_args = "--no-diff" if self.args.disable_diff else "" 2259c297294SWilliam Wang return_code = self.__exec_cmd(f'{numa_args} $NOOP_HOME/build/emu -i {workload} {emu_args} {fork_args} {diff_args}') 226c11a4d2cSYinan Xu return return_code 227c11a4d2cSYinan Xu 228c11a4d2cSYinan Xu def run(self, args): 229c11a4d2cSYinan Xu if args.ci is not None: 230c11a4d2cSYinan Xu return self.run_ci(args.ci) 231c11a4d2cSYinan Xu actions = [ 232c11a4d2cSYinan Xu (args.generate, lambda _ : self.generate_verilog()), 233c11a4d2cSYinan Xu (args.build, lambda _ : self.build_emu()), 234ef3b5b96SWilliam Wang (args.workload, lambda args: self.run_emu(args.workload)), 235ef3b5b96SWilliam Wang (args.clean, lambda _ : self.make_clean()) 236c11a4d2cSYinan Xu ] 237c11a4d2cSYinan Xu valid_actions = map(lambda act: act[1], filter(lambda act: act[0], actions)) 238c11a4d2cSYinan Xu for i, action in enumerate(valid_actions): 239c11a4d2cSYinan Xu print(f"Action {i}:") 240c11a4d2cSYinan Xu ret = action(args) 241c11a4d2cSYinan Xu if ret: 242c11a4d2cSYinan Xu return ret 243c11a4d2cSYinan Xu return 0 244c11a4d2cSYinan Xu 245c11a4d2cSYinan Xu def __exec_cmd(self, cmd): 246c11a4d2cSYinan Xu env = dict(os.environ) 247c11a4d2cSYinan Xu env.update(self.args.get_env_variables()) 248c11a4d2cSYinan Xu print("subprocess call cmd:", cmd) 2495ef7374fSLi Qianruo start = time.time() 2509f32a80dSYinan Xu proc = subprocess.Popen(cmd, shell=True, env=env, preexec_fn=os.setsid) 2519f32a80dSYinan Xu try: 2529f32a80dSYinan Xu return_code = proc.wait(self.timeout) 2535ef7374fSLi Qianruo end = time.time() 2545ef7374fSLi Qianruo print(f"Elapsed time: {end - start} seconds") 255c11a4d2cSYinan Xu return return_code 2569f32a80dSYinan Xu except (KeyboardInterrupt, subprocess.TimeoutExpired): 2579f32a80dSYinan Xu os.killpg(os.getpgid(proc.pid), signal.SIGINT) 2589f32a80dSYinan Xu print(f"KeyboardInterrupt or TimeoutExpired.") 2599f32a80dSYinan Xu return 0 260c11a4d2cSYinan Xu 261c11a4d2cSYinan Xu def __get_ci_cputest(self, name=None): 262c11a4d2cSYinan Xu base_dir = os.path.join(self.args.am_home, "tests/cputest/build") 263c11a4d2cSYinan Xu cputest = os.listdir(base_dir) 264c11a4d2cSYinan Xu cputest = filter(lambda x: x.endswith(".bin"), cputest) 265c11a4d2cSYinan Xu cputest = map(lambda x: os.path.join(base_dir, x), cputest) 266c11a4d2cSYinan Xu return cputest 267c11a4d2cSYinan Xu 268c11a4d2cSYinan Xu def __get_ci_rvtest(self, name=None): 269c11a4d2cSYinan Xu base_dir = os.path.join(self.args.rvtest_home, "isa/build") 270c11a4d2cSYinan Xu riscv_tests = os.listdir(base_dir) 271c11a4d2cSYinan Xu riscv_tests = filter(lambda x: x.endswith(".bin"), riscv_tests) 272c11a4d2cSYinan Xu all_rv_tests = ["rv64ui", "rv64um", "rv64ua", "rv64uf", "rv64ud"] 273c11a4d2cSYinan Xu riscv_tests = filter(lambda x: x[:6] in all_rv_tests, riscv_tests) 274c11a4d2cSYinan Xu riscv_tests = map(lambda x: os.path.join(base_dir, x), riscv_tests) 275c11a4d2cSYinan Xu return riscv_tests 276c11a4d2cSYinan Xu 277675acc68SYinan Xu def __get_ci_misc(self, name=None): 278da3b568bSYinan Xu base_dir = "/nfs/home/share/ci-workloads" 279675acc68SYinan Xu workloads = [ 280675acc68SYinan Xu "bitmanip/bitMisc.bin", 2813feeca58Szfw "crypto/crypto-riscv64-noop.bin", 282675acc68SYinan Xu "coremark_rv64gc_o2/coremark-riscv64-xs.bin", 283675acc68SYinan Xu "coremark_rv64gc_o3/coremark-riscv64-xs.bin", 28464a887e0SYinan Xu "coremark_rv64gcb_o3/coremark-riscv64-xs.bin", 28535620aa8Swakafa "ext_intr/amtest-riscv64-xs.bin", 2863f4ec46fSCODE-JTZ "cache-alias/aliastest-riscv64-xs.bin", 287af2f7849Shappy-lx "Svinval/rv64mi-p-svinval.bin", 288b6982e83SLemover "pmp/pmp.riscv.bin", 28945f497a4Shappy-lx "asid/asid.bin", 2907d9edc86SLemover "isa_misc/xret_clear_mprv.bin", 291705cbec3SLemover "isa_misc/satp_ppn.bin", 2929c297294SWilliam Wang "cache-management/softprefetchtest-riscv64-xs.bin" 293675acc68SYinan Xu ] 294675acc68SYinan Xu misc_tests = map(lambda x: os.path.join(base_dir, x), workloads) 295675acc68SYinan Xu return misc_tests 296675acc68SYinan Xu 297ef3b5b96SWilliam Wang def __get_ci_mc(self, name=None): 298ef3b5b96SWilliam Wang base_dir = "/nfs/home/share/ci-workloads" 299ef3b5b96SWilliam Wang workloads = [ 300ef3b5b96SWilliam Wang "dualcoretest/ldvio-riscv64-xs.bin" 301ef3b5b96SWilliam Wang ] 302ef3b5b96SWilliam Wang mc_tests = map(lambda x: os.path.join(base_dir, x), workloads) 303ef3b5b96SWilliam Wang return mc_tests 304ef3b5b96SWilliam Wang 3059c297294SWilliam Wang def __get_ci_nodiff(self, name=None): 306da3b568bSYinan Xu base_dir = "/nfs/home/share/ci-workloads" 3079c297294SWilliam Wang workloads = [ 3089c297294SWilliam Wang "cache-management/cacheoptest-riscv64-xs.bin" 3099c297294SWilliam Wang ] 3109c297294SWilliam Wang tests = map(lambda x: os.path.join(base_dir, x), workloads) 3119c297294SWilliam Wang return tests 3129c297294SWilliam Wang 313c11a4d2cSYinan Xu def __am_apps_path(self, bench): 314c11a4d2cSYinan Xu filename = f"{bench}-riscv64-noop.bin" 315c11a4d2cSYinan Xu return [os.path.join(self.args.am_home, "apps", bench, "build", filename)] 316c11a4d2cSYinan Xu 317c11a4d2cSYinan Xu def __get_ci_workloads(self, name): 318c11a4d2cSYinan Xu workloads = { 319c11a4d2cSYinan Xu "linux-hello": "bbl.bin", 320fac0ab56Swakafa "linux-hello-smp": "bbl.bin", 3215092a298Szfw "povray": "_700480000000_.gz", 3225092a298Szfw "mcf": "_17520000000_.gz", 3235092a298Szfw "xalancbmk": "_266100000000_.gz", 3245092a298Szfw "gcc": "_39720000000_.gz", 3255092a298Szfw "namd": "_434640000000_.gz", 3265092a298Szfw "milc": "_103620000000_.gz", 3275092a298Szfw "lbm": "_140840000000_.gz", 3287b441e5eSYinan Xu "gromacs": "_275480000000_.gz", 3297b441e5eSYinan Xu "wrf": "_1916220000000_.gz", 3307b441e5eSYinan Xu "astar": "_122060000000_.gz" 331c11a4d2cSYinan Xu } 3329f32a80dSYinan Xu if name in workloads: 333da3b568bSYinan Xu return [os.path.join("/nfs/home/share/ci-workloads", name, workloads[name])] 3349f32a80dSYinan Xu # select a random SPEC checkpoint 3359f32a80dSYinan Xu assert(name == "random") 3369f32a80dSYinan Xu all_cpt = [ 3379f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o2_20m/take_cpt", 3389f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o3_20m/take_cpt", 3399f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_20m/take_cpt", 3409f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_50m/take_cpt", 3419f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o2_20m/take_cpt", 3429f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o3_20m/take_cpt", 3439f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gc_o2_50m/take_cpt", 3449f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_speed_rv64gcb_o3_20m/take_cpt" 3459f32a80dSYinan Xu ] 3469f32a80dSYinan Xu all_json = [ 3479f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o2_20m/json/simpoint_summary.json", 3489f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o3_20m/simpoint_summary.json", 3499f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_20m/simpoint_summary.json", 3509f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_50m/simpoint_summary.json", 3519f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o2_20m/simpoint_summary.json", 3529f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o3_20m/simpoint_summary.json", 3539f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gc_o2_50m/simpoint_summary.json", 3549f32a80dSYinan Xu "/nfs-nvme/home/share/checkpoints_profiles/spec17_speed_rv64gcb_o3_20m/simpoint_summary.json" 3559f32a80dSYinan Xu ] 3569f32a80dSYinan Xu assert(len(all_cpt) == len(all_json)) 3579f32a80dSYinan Xu cpt_path, json_path = random.choice(list(zip(all_cpt, all_json))) 3589f32a80dSYinan Xu all_gcpt = load_all_gcpt(cpt_path, json_path) 3599f32a80dSYinan Xu return [random.choice(all_gcpt)] 360c11a4d2cSYinan Xu 361c11a4d2cSYinan Xu def run_ci(self, test): 362c11a4d2cSYinan Xu all_tests = { 363c11a4d2cSYinan Xu "cputest": self.__get_ci_cputest, 364c11a4d2cSYinan Xu "riscv-tests": self.__get_ci_rvtest, 365675acc68SYinan Xu "misc-tests": self.__get_ci_misc, 366ef3b5b96SWilliam Wang "mc-tests": self.__get_ci_mc, 3679c297294SWilliam Wang "nodiff-tests": self.__get_ci_nodiff, 368c11a4d2cSYinan Xu "microbench": self.__am_apps_path, 369c11a4d2cSYinan Xu "coremark": self.__am_apps_path 370c11a4d2cSYinan Xu } 371c11a4d2cSYinan Xu for target in all_tests.get(test, self.__get_ci_workloads)(test): 372c11a4d2cSYinan Xu print(target) 373c11a4d2cSYinan Xu ret = self.run_emu(target) 374c11a4d2cSYinan Xu if ret: 37524e2eab6SJinYue if self.args.default_wave_home != self.args.wave_home: 37624e2eab6SJinYue print("copy wave file to " + self.args.wave_home) 37724e2eab6SJinYue self.__exec_cmd(f"cp $NOOP_HOME/build/*.vcd $WAVE_HOME") 378bc063562SLemover self.__exec_cmd(f"cp $NOOP_HOME/build/emu $WAVE_HOME") 379bc063562SLemover self.__exec_cmd(f"cp $NOOP_HOME/build/SimTop.v $WAVE_HOME") 380c11a4d2cSYinan Xu return ret 381c11a4d2cSYinan Xu return 0 382c11a4d2cSYinan Xu 38394e266cbSYinan Xudef get_free_cores(n): 38494e266cbSYinan Xu while True: 38594e266cbSYinan Xu # To avoid potential conflicts, we allow CI to use SMT. 386b86f926fSYinan Xu num_logical_core = psutil.cpu_count(logical=False) 38794e266cbSYinan Xu core_usage = psutil.cpu_percent(interval=1, percpu=True) 38894e266cbSYinan Xu num_window = num_logical_core // n 38994e266cbSYinan Xu for i in range(num_window): 39094e266cbSYinan Xu window_usage = core_usage[i * n : i * n + n] 39194e266cbSYinan Xu if sum(window_usage) < 0.3 * n and True not in map(lambda x: x > 0.5, window_usage): 39294e266cbSYinan Xu return (((i * n) % 128)// 64, i * n, i * n + n - 1) 39394e266cbSYinan Xu print(f"No free {n} cores found. CPU usage: {core_usage}\n") 39494e266cbSYinan Xu 395c11a4d2cSYinan Xuif __name__ == "__main__": 396c11a4d2cSYinan Xu parser = argparse.ArgumentParser(description='Python wrapper for XiangShan') 397c11a4d2cSYinan Xu parser.add_argument('workload', nargs='?', type=str, default="", 398c11a4d2cSYinan Xu help='input workload file in binary format') 399c11a4d2cSYinan Xu # actions 400c11a4d2cSYinan Xu parser.add_argument('--build', action='store_true', help='build XS emu') 401c11a4d2cSYinan Xu parser.add_argument('--generate', action='store_true', help='generate XS verilog') 402c11a4d2cSYinan Xu parser.add_argument('--ci', nargs='?', type=str, const="", help='run CI tests') 403ef3b5b96SWilliam Wang parser.add_argument('--clean', action='store_true', help='clean up XiangShan CI workspace') 4049f32a80dSYinan Xu parser.add_argument('--timeout', nargs='?', type=int, default=None, help='timeout (in seconds)') 405c11a4d2cSYinan Xu # environment variables 406c11a4d2cSYinan Xu parser.add_argument('--nemu', nargs='?', type=str, help='path to nemu') 407c11a4d2cSYinan Xu parser.add_argument('--am', nargs='?', type=str, help='path to nexus-am') 408c11a4d2cSYinan Xu parser.add_argument('--dramsim3', nargs='?', type=str, help='path to dramsim3') 409c11a4d2cSYinan Xu parser.add_argument('--rvtest', nargs='?', type=str, help='path to riscv-tests') 41024e2eab6SJinYue parser.add_argument('--wave-dump', nargs='?', type=str , help='path to dump wave') 411c11a4d2cSYinan Xu # chisel arguments 4121545277aSYinan Xu parser.add_argument('--enable-log', action='store_true', help='enable log') 4135ef7374fSLi Qianruo parser.add_argument('--num-cores', type=int, help='number of cores') 414c11a4d2cSYinan Xu # makefile arguments 4151545277aSYinan Xu parser.add_argument('--release', action='store_true', help='enable release') 41638e9143dSYinan Xu parser.add_argument('--spike', action='store_true', help='enable spike diff') 417c11a4d2cSYinan Xu parser.add_argument('--with-dramsim3', action='store_true', help='enable dramsim3') 418c11a4d2cSYinan Xu parser.add_argument('--threads', nargs='?', type=int, help='number of emu threads') 419c11a4d2cSYinan Xu parser.add_argument('--trace', action='store_true', help='enable waveform') 4206c0058d3SYinan Xu parser.add_argument('--config', nargs='?', type=str, help='config') 421c11a4d2cSYinan Xu # emu arguments 422c11a4d2cSYinan Xu parser.add_argument('--numa', action='store_true', help='use numactl') 423f9930da0SYinan Xu parser.add_argument('--diff', nargs='?', default="./ready-to-run/riscv64-nemu-interpreter-so", type=str, help='nemu so') 424c11a4d2cSYinan Xu parser.add_argument('--max-instr', nargs='?', type=int, help='max instr') 425078fde2bSJinYue parser.add_argument('--disable-fork', action='store_true', help='disable lightSSS') 4269c297294SWilliam Wang parser.add_argument('--no-diff', action='store_true', help='disable difftest') 427*25ac26c6SWilliam Wang parser.add_argument('--ram-size', nargs='?', type=str, help='manually set simulation memory size (8GB by default)') 428c11a4d2cSYinan Xu 429c11a4d2cSYinan Xu args = parser.parse_args() 430c11a4d2cSYinan Xu 431c11a4d2cSYinan Xu xs = XiangShan(args) 432c11a4d2cSYinan Xu ret = xs.run(args) 433c11a4d2cSYinan Xu 434c11a4d2cSYinan Xu sys.exit(ret) 435