1#*************************************************************************************** 2# Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 3# Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences 4# Copyright (c) 2020-2021 Peng Cheng Laboratory 5# 6# XiangShan is licensed under Mulan PSL v2. 7# You can use this software according to the terms and conditions of the Mulan PSL v2. 8# You may obtain a copy of Mulan PSL v2 at: 9# http://license.coscl.org.cn/MulanPSL2 10# 11# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 12# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 13# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 14# 15# See the Mulan PSL v2 for more details. 16#*************************************************************************************** 17 18# Simple version of xiangshan python wrapper 19 20import argparse 21import json 22import os 23import random 24import signal 25import subprocess 26import sys 27import time 28import shlex 29import psutil 30 31 32def load_all_gcpt(gcpt_path, json_path): 33 all_gcpt = [] 34 with open(json_path) as f: 35 data = json.load(f) 36 for benchspec in data: 37 for point in data[benchspec]: 38 weight = data[benchspec][point] 39 gcpt = os.path.join(gcpt_path, "_".join([benchspec, point, weight])) 40 bin_dir = os.path.join(gcpt, "0") 41 bin_file = list(os.listdir(bin_dir)) 42 assert(len(bin_file) == 1) 43 bin_path = os.path.join(bin_dir, bin_file[0]) 44 assert(os.path.isfile(bin_path)) 45 all_gcpt.append(bin_path) 46 return all_gcpt 47 48class XSArgs(object): 49 script_path = os.path.realpath(__file__) 50 # default path to the repositories 51 noop_home = os.path.join(os.path.dirname(script_path), "..") 52 nemu_home = os.path.join(noop_home, "../NEMU") 53 am_home = os.path.join(noop_home, "../nexus-am") 54 dramsim3_home = os.path.join(noop_home, "../DRAMsim3") 55 rvtest_home = os.path.join(noop_home, "../riscv-tests") 56 default_wave_home = os.path.join(noop_home, "build") 57 wave_home = default_wave_home 58 59 def __init__(self, args): 60 # all path environment variables that should be set 61 all_path = [ 62 # (python argument, environment variable, default, target function) 63 (None, "NOOP_HOME", self.noop_home, self.set_noop_home), 64 (args.nemu, "NEMU_HOME", self.nemu_home, self.set_nemu_home), 65 (args.am, "AM_HOME", self.am_home, self.set_am_home), 66 (args.dramsim3, "DRAMSIM3_HOME", self.dramsim3_home, self.set_dramsim3_home), 67 (args.rvtest, "RVTEST_HOME", self.rvtest_home, self.set_rvtest_home), 68 ] 69 for (arg_in, env, default, set_func) in all_path: 70 set_func(self.__extract_path(arg_in, env, default)) 71 # Chisel arguments 72 self.enable_log = args.enable_log 73 self.num_cores = args.num_cores 74 # Makefile arguments 75 self.threads = args.threads 76 self.with_dramsim3 = 1 if args.with_dramsim3 else None 77 self.is_release = 1 if args.release else None 78 self.is_spike = "Spike" if args.spike else None 79 self.trace = 1 if args.trace or not args.disable_fork and not args.trace_fst else None 80 self.trace_fst = "fst" if args.trace_fst else None 81 self.config = args.config 82 self.is_mfc = 1 if args.mfc else None 83 self.emu_optimize = args.emu_optimize 84 self.xprop = 1 if args.xprop else None 85 self.with_chiseldb = 0 if args.no_db else None 86 # emu arguments 87 self.max_instr = args.max_instr 88 self.ram_size = args.ram_size 89 self.seed = random.randint(0, 9999) 90 self.numa = args.numa 91 self.diff = args.diff 92 if args.spike and "nemu" in args.diff: 93 self.diff = self.diff.replace("nemu-interpreter", "spike") 94 self.fork = not args.disable_fork 95 self.disable_diff = args.no_diff 96 self.disable_db = args.no_db 97 self.gcpt_restore_bin = args.gcpt_restore_bin 98 self.pgo = args.pgo 99 self.pgo_max_cycle = args.pgo_max_cycle 100 self.pgo_emu_args = args.pgo_emu_args 101 self.llvm_profdata = args.llvm_profdata 102 # wave dump path 103 if args.wave_dump is not None: 104 self.set_wave_home(args.wave_dump) 105 else: 106 self.set_wave_home(self.default_wave_home) 107 108 def get_env_variables(self): 109 all_env = { 110 "NOOP_HOME" : self.noop_home, 111 "NEMU_HOME" : self.nemu_home, 112 "WAVE_HOME" : self.wave_home, 113 "AM_HOME" : self.am_home, 114 "DRAMSIM3_HOME": self.dramsim3_home, 115 "MODULEPATH": "/usr/share/Modules/modulefiles:/etc/modulefiles" 116 } 117 return all_env 118 119 def get_chisel_args(self, prefix=None): 120 chisel_args = [ 121 (self.enable_log, "enable-log") 122 ] 123 args = map(lambda x: x[1], filter(lambda arg: arg[0], chisel_args)) 124 if prefix is not None: 125 args = map(lambda x: prefix + x, args) 126 return args 127 128 def get_makefile_args(self): 129 makefile_args = [ 130 (self.threads, "EMU_THREADS"), 131 (self.with_dramsim3, "WITH_DRAMSIM3"), 132 (self.is_release, "RELEASE"), 133 (self.is_spike, "REF"), 134 (self.trace, "EMU_TRACE"), 135 (self.trace_fst, "EMU_TRACE"), 136 (self.config, "CONFIG"), 137 (self.num_cores, "NUM_CORES"), 138 (self.is_mfc, "MFC"), 139 (self.emu_optimize, "EMU_OPTIMIZE"), 140 (self.xprop, "ENABLE_XPROP"), 141 (self.with_chiseldb, "WITH_CHISELDB"), 142 (self.pgo, "PGO_WORKLOAD"), 143 (self.pgo_max_cycle, "PGO_MAX_CYCLE"), 144 (self.pgo_emu_args, "PGO_EMU_ARGS"), 145 (self.llvm_profdata, "LLVM_PROFDATA"), 146 ] 147 args = filter(lambda arg: arg[0] is not None, makefile_args) 148 args = [(shlex.quote(str(arg[0])), arg[1]) for arg in args] # shell escape 149 return args 150 151 def get_emu_args(self): 152 emu_args = [ 153 (self.max_instr, "max-instr"), 154 (self.diff, "diff"), 155 (self.seed, "seed"), 156 (self.ram_size, "ram-size"), 157 ] 158 args = filter(lambda arg: arg[0] is not None, emu_args) 159 return args 160 161 def show(self): 162 print("Extra environment variables:") 163 env = self.get_env_variables() 164 for env_name in env: 165 print(f"{env_name}: {env[env_name]}") 166 print() 167 print("Chisel arguments:") 168 print(" ".join(self.get_chisel_args())) 169 print() 170 print("Makefile arguments:") 171 for val, name in self.get_makefile_args(): 172 print(f"{name}={val}") 173 print() 174 print("emu arguments:") 175 for val, name in self.get_emu_args(): 176 print(f"--{name} {val}") 177 print() 178 179 def __extract_path(self, path, env=None, default=None): 180 if path is None and env is not None: 181 path = os.getenv(env) 182 if path is None and default is not None: 183 path = default 184 path = os.path.realpath(path) 185 return path 186 187 def set_noop_home(self, path): 188 self.noop_home = path 189 190 def set_nemu_home(self, path): 191 self.nemu_home = path 192 193 def set_am_home(self, path): 194 self.am_home = path 195 196 def set_dramsim3_home(self, path): 197 self.dramsim3_home = path 198 199 def set_rvtest_home(self, path): 200 self.rvtest_home = path 201 202 def set_wave_home(self, path): 203 print(f"set wave home to {path}") 204 self.wave_home = path 205 206# XiangShan environment 207class XiangShan(object): 208 def __init__(self, args): 209 self.args = XSArgs(args) 210 self.timeout = args.timeout 211 212 def show(self): 213 self.args.show() 214 215 def make_clean(self): 216 print("Clean up CI workspace") 217 self.show() 218 return_code = self.__exec_cmd(f'make -C $NOOP_HOME clean') 219 return return_code 220 221 def generate_verilog(self): 222 print("Generating XiangShan verilog with the following configurations:") 223 self.show() 224 sim_args = " ".join(self.args.get_chisel_args(prefix="--")) 225 make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args())) 226 return_code = self.__exec_cmd(f'make -C $NOOP_HOME verilog SIM_ARGS="{sim_args}" {make_args}') 227 return return_code 228 229 def generate_sim_verilog(self): 230 print("Generating XiangShan sim-verilog with the following configurations:") 231 self.show() 232 sim_args = " ".join(self.args.get_chisel_args(prefix="--")) 233 make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args())) 234 return_code = self.__exec_cmd(f'make -C $NOOP_HOME sim-verilog SIM_ARGS="{sim_args}" {make_args}') 235 return return_code 236 237 def build_emu(self): 238 print("Building XiangShan emu with the following configurations:") 239 self.show() 240 sim_args = " ".join(self.args.get_chisel_args(prefix="--")) 241 make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args())) 242 return_code = self.__exec_cmd(f'make -C $NOOP_HOME emu -j200 SIM_ARGS="{sim_args}" {make_args}') 243 return return_code 244 245 def build_simv(self): 246 print("Building XiangShan simv with the following configurations") 247 self.show() 248 make_args = " ".join(map(lambda arg: f"{arg[1]}={arg[0]}", self.args.get_makefile_args())) 249 # TODO: make the following commands grouped as unseen scripts 250 return_code = self.__exec_cmd(f'\ 251 eval `/usr/bin/modulecmd zsh load license`;\ 252 eval `/usr/bin/modulecmd zsh load synopsys/vcs/Q-2020.03-SP2`;\ 253 eval `/usr/bin/modulecmd zsh load synopsys/verdi/S-2021.09-SP1`;\ 254 VERDI_HOME=/nfs/tools/synopsys/verdi/S-2021.09-SP1 \ 255 make -C $NOOP_HOME simv {make_args} CONSIDER_FSDB=1') # set CONSIDER_FSDB for compatibility 256 return return_code 257 258 def run_emu(self, workload): 259 print("Running XiangShan emu with the following configurations:") 260 self.show() 261 emu_args = " ".join(map(lambda arg: f"--{arg[1]} {arg[0]}", self.args.get_emu_args())) 262 print("workload:", workload) 263 numa_args = "" 264 if self.args.numa: 265 numa_info = get_free_cores(self.args.threads) 266 numa_args = f"numactl -m {numa_info[0]} -C {numa_info[1]}-{numa_info[2]}" 267 fork_args = "--enable-fork" if self.args.fork else "" 268 diff_args = "--no-diff" if self.args.disable_diff else "" 269 chiseldb_args = "--dump-db" if not self.args.disable_db else "" 270 gcpt_restore_args = f"-r {self.args.gcpt_restore_bin}" if len(self.args.gcpt_restore_bin) != 0 else "" 271 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}') 272 return return_code 273 274 def run_simv(self, workload): 275 print("Running XiangShan simv with the following configurations:") 276 self.show() 277 diff_args = "$NOOP_HOME/"+ args.diff 278 assert_args = "-assert finish_maxfail=30 -assert global_finish_maxfail=10000" 279 return_code = self.__exec_cmd(f'cd $NOOP_HOME/build && ./simv +workload={workload} +diff={diff_args} +dump-wave=fsdb {assert_args} | tee simv.log') 280 with open(f"{self.args.noop_home}/build/simv.log") as f: 281 content = f.read() 282 if "Offending" in content or "HIT GOOD TRAP" not in content: 283 return 1 284 return return_code 285 286 def run(self, args): 287 if args.ci is not None: 288 return self.run_ci(args.ci) 289 if args.ci_vcs is not None: 290 return self.run_ci_vcs(args.ci_vcs) 291 actions = [ 292 (args.generate, lambda _ : self.generate_verilog()), 293 (args.vcs_gen, lambda _ : self.generate_sim_verilog()), 294 (args.build, lambda _ : self.build_emu()), 295 (args.vcs_build, lambda _ : self.build_simv()), 296 (args.workload, lambda args: self.run_emu(args.workload)), 297 (args.clean, lambda _ : self.make_clean()) 298 ] 299 valid_actions = map(lambda act: act[1], filter(lambda act: act[0], actions)) 300 for i, action in enumerate(valid_actions): 301 print(f"Action {i}:") 302 ret = action(args) 303 if ret: 304 return ret 305 return 0 306 307 def __exec_cmd(self, cmd): 308 env = dict(os.environ) 309 env.update(self.args.get_env_variables()) 310 print("subprocess call cmd:", cmd) 311 start = time.time() 312 proc = subprocess.Popen(cmd, shell=True, env=env, preexec_fn=os.setsid) 313 try: 314 return_code = proc.wait(self.timeout) 315 end = time.time() 316 print(f"Elapsed time: {end - start} seconds") 317 return return_code 318 except (KeyboardInterrupt, subprocess.TimeoutExpired): 319 os.killpg(os.getpgid(proc.pid), signal.SIGINT) 320 print(f"KeyboardInterrupt or TimeoutExpired.") 321 return 0 322 323 def __get_ci_cputest(self, name=None): 324 base_dir = os.path.join(self.args.am_home, "tests/cputest/build") 325 cputest = os.listdir(base_dir) 326 cputest = filter(lambda x: x.endswith(".bin"), cputest) 327 cputest = map(lambda x: os.path.join(base_dir, x), cputest) 328 return cputest 329 330 def __get_ci_rvtest(self, name=None): 331 base_dir = os.path.join(self.args.rvtest_home, "isa/build") 332 riscv_tests = os.listdir(base_dir) 333 riscv_tests = filter(lambda x: x.endswith(".bin"), riscv_tests) 334 all_rv_tests = ["rv64ui", "rv64um", "rv64ua", "rv64uf", "rv64ud"] 335 riscv_tests = filter(lambda x: x[:6] in all_rv_tests, riscv_tests) 336 riscv_tests = map(lambda x: os.path.join(base_dir, x), riscv_tests) 337 return riscv_tests 338 339 def __get_ci_misc(self, name=None): 340 base_dir = "/nfs/home/share/ci-workloads" 341 workloads = [ 342 "bitmanip/bitMisc.bin", 343 "crypto/crypto-riscv64-noop.bin", 344 "coremark_rv64gc_o2/coremark-riscv64-xs.bin", 345 "coremark_rv64gc_o3/coremark-riscv64-xs.bin", 346 "coremark_rv64gcb_o3/coremark-riscv64-xs.bin", 347 "ext_intr/amtest-riscv64-xs.bin", 348 "cache-alias/aliastest-riscv64-xs.bin", 349 "Svinval/rv64mi-p-svinval.bin", 350 "pmp/pmp.riscv.bin", 351 "pmp/pmp-am/amtest-riscv64-xs.bin", 352 "pmp/hugepage-pmp-atom/amtest-riscv64-xs.bin", 353 "asid/asid.bin", 354 "isa_misc/xret_clear_mprv.bin", 355 "isa_misc/satp_ppn.bin", 356 "cache-management/softprefetchtest-riscv64-xs.bin" 357 ] 358 misc_tests = map(lambda x: os.path.join(base_dir, x), workloads) 359 return misc_tests 360 361 def __get_ci_mc(self, name=None): 362 base_dir = "/nfs/home/share/ci-workloads" 363 workloads = [ 364 "dualcoretest/ldvio-riscv64-xs.bin" 365 ] 366 mc_tests = map(lambda x: os.path.join(base_dir, x), workloads) 367 return mc_tests 368 369 def __get_ci_nodiff(self, name=None): 370 base_dir = "/nfs/home/share/ci-workloads" 371 workloads = [ 372 "cache-management/cacheoptest-riscv64-xs.bin" 373 ] 374 tests = map(lambda x: os.path.join(base_dir, x), workloads) 375 return tests 376 377 def __am_apps_path(self, bench): 378 filename = f"{bench}-riscv64-noop.bin" 379 return [os.path.join(self.args.am_home, "apps", bench, "build", filename)] 380 381 def __get_ci_workloads(self, name): 382 workloads = { 383 "linux-hello": "bbl.bin", 384 "linux-hello-smp": "bbl.bin", 385 "linux-hello-opensbi": "fw_payload.bin", 386 "linux-hello-smp-opensbi": "fw_payload.bin", 387 "linux-hello-new": "bbl.bin", 388 "linux-hello-smp-new": "bbl.bin", 389 "linux-hello-smp-newcsr": "bbl.bin", 390 "povray": "_700480000000_.gz", 391 "mcf": "_17520000000_.gz", 392 "xalancbmk": "_266100000000_.gz", 393 "gcc": "_39720000000_.gz", 394 "namd": "_434640000000_.gz", 395 "milc": "_103620000000_.gz", 396 "lbm": "_140840000000_.gz", 397 "gromacs": "_275480000000_.gz", 398 "wrf": "_1916220000000_.gz", 399 "astar": "_122060000000_.gz" 400 } 401 if name in workloads: 402 return [os.path.join("/nfs/home/share/ci-workloads", name, workloads[name])] 403 # select a random SPEC checkpoint 404 assert(name == "random") 405 all_cpt = [ 406 "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o2_20m/take_cpt", 407 "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o3_20m/take_cpt", 408 "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_20m/take_cpt", 409 "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_50m/take_cpt", 410 "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o2_20m/take_cpt", 411 "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o3_20m/take_cpt", 412 "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gc_o2_50m/take_cpt", 413 "/nfs-nvme/home/share/checkpoints_profiles/spec17_speed_rv64gcb_o3_20m/take_cpt" 414 ] 415 all_json = [ 416 "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o2_20m/json/simpoint_summary.json", 417 "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gcb_o3_20m/simpoint_summary.json", 418 "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_20m/simpoint_summary.json", 419 "/nfs-nvme/home/share/checkpoints_profiles/spec06_rv64gc_o2_50m/simpoint_summary.json", 420 "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o2_20m/simpoint_summary.json", 421 "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gcb_o3_20m/simpoint_summary.json", 422 "/nfs-nvme/home/share/checkpoints_profiles/spec17_rv64gc_o2_50m/simpoint_summary.json", 423 "/nfs-nvme/home/share/checkpoints_profiles/spec17_speed_rv64gcb_o3_20m/simpoint_summary.json" 424 ] 425 assert(len(all_cpt) == len(all_json)) 426 cpt_path, json_path = random.choice(list(zip(all_cpt, all_json))) 427 all_gcpt = load_all_gcpt(cpt_path, json_path) 428 return [random.choice(all_gcpt)] 429 430 def run_ci(self, test): 431 all_tests = { 432 "cputest": self.__get_ci_cputest, 433 "riscv-tests": self.__get_ci_rvtest, 434 "misc-tests": self.__get_ci_misc, 435 "mc-tests": self.__get_ci_mc, 436 "nodiff-tests": self.__get_ci_nodiff, 437 "microbench": self.__am_apps_path, 438 "coremark": self.__am_apps_path 439 } 440 for target in all_tests.get(test, self.__get_ci_workloads)(test): 441 print(target) 442 ret = self.run_emu(target) 443 if ret: 444 if self.args.default_wave_home != self.args.wave_home: 445 print("copy wave file to " + self.args.wave_home) 446 self.__exec_cmd(f"cp $NOOP_HOME/build/*.vcd $WAVE_HOME") 447 self.__exec_cmd(f"cp $NOOP_HOME/build/emu $WAVE_HOME") 448 self.__exec_cmd(f"cp $NOOP_HOME/build/rtl/SimTop.v $WAVE_HOME") 449 self.__exec_cmd(f"cp $NOOP_HOME/build/*.db $WAVE_HOME") 450 return ret 451 return 0 452 453 def run_ci_vcs(self, test): 454 all_tests = { 455 "cputest": self.__get_ci_cputest, 456 "riscv-tests": self.__get_ci_rvtest, 457 "misc-tests": self.__get_ci_misc, 458 "mc-tests": self.__get_ci_mc, 459 "nodiff-tests": self.__get_ci_nodiff, 460 "microbench": self.__am_apps_path, 461 "coremark": self.__am_apps_path 462 } 463 for target in all_tests.get(test, self.__get_ci_workloads)(test): 464 print(target) 465 ret = self.run_simv(target) 466 if ret: 467 if self.args.default_wave_home != self.args.wave_home: 468 print("copy wave file to " + self.args.wave_home) 469 self.__exec_cmd(f"cp $NOOP_HOME/build/*.fsdb $WAVE_HOME") 470 self.__exec_cmd(f"cp $NOOP_HOME/build/simv $WAVE_HOME") 471 self.__exec_cmd(f"cp $NOOP_HOME/build/rtl/SimTop.v $WAVE_HOME") 472 self.__exec_cmd(f"cp $NOOP_HOME/build/*.db $WAVE_HOME") 473 return ret 474 return 0 475 476def get_free_cores(n): 477 while True: 478 # To avoid potential conflicts, we allow CI to use SMT. 479 num_logical_core = psutil.cpu_count(logical=False) 480 core_usage = psutil.cpu_percent(interval=1, percpu=True) 481 num_window = num_logical_core // n 482 for i in range(num_window): 483 window_usage = core_usage[i * n : i * n + n] 484 if sum(window_usage) < 30 * n and True not in map(lambda x: x > 90, window_usage): 485 return (((i * n) % 128)// 64, i * n, i * n + n - 1) 486 print(f"No free {n} cores found. CPU usage: {core_usage}\n") 487 488if __name__ == "__main__": 489 parser = argparse.ArgumentParser(description='Python wrapper for XiangShan') 490 parser.add_argument('workload', nargs='?', type=str, default="", 491 help='input workload file in binary format') 492 # actions 493 parser.add_argument('--build', action='store_true', help='build XS emu') 494 parser.add_argument('--generate', action='store_true', help='generate XS verilog') 495 parser.add_argument('--vcs-gen', action='store_true', help='generate XS sim verilog for vcs') 496 parser.add_argument('--vcs-build', action='store_true', help='build XS simv') 497 parser.add_argument('--ci', nargs='?', type=str, const="", help='run CI tests') 498 parser.add_argument('--ci-vcs', nargs='?', type=str, const="", help='run CI tests on simv') 499 parser.add_argument('--clean', action='store_true', help='clean up XiangShan CI workspace') 500 parser.add_argument('--timeout', nargs='?', type=int, default=None, help='timeout (in seconds)') 501 # environment variables 502 parser.add_argument('--nemu', nargs='?', type=str, help='path to nemu') 503 parser.add_argument('--am', nargs='?', type=str, help='path to nexus-am') 504 parser.add_argument('--dramsim3', nargs='?', type=str, help='path to dramsim3') 505 parser.add_argument('--rvtest', nargs='?', type=str, help='path to riscv-tests') 506 parser.add_argument('--wave-dump', nargs='?', type=str , help='path to dump wave') 507 # chisel arguments 508 parser.add_argument('--enable-log', action='store_true', help='enable log') 509 parser.add_argument('--num-cores', type=int, help='number of cores') 510 # makefile arguments 511 parser.add_argument('--release', action='store_true', help='enable release') 512 parser.add_argument('--spike', action='store_true', help='enable spike diff') 513 parser.add_argument('--with-dramsim3', action='store_true', help='enable dramsim3') 514 parser.add_argument('--threads', nargs='?', type=int, help='number of emu threads') 515 parser.add_argument('--trace', action='store_true', help='enable vcd waveform') 516 parser.add_argument('--trace-fst', action='store_true', help='enable fst waveform') 517 parser.add_argument('--config', nargs='?', type=str, help='config') 518 parser.add_argument('--mfc', action='store_true', help='use mfc') 519 parser.add_argument('--emu-optimize', nargs='?', type=str, help='verilator optimization letter') 520 parser.add_argument('--xprop', action='store_true', help='enable xprop for vcs') 521 # emu arguments 522 parser.add_argument('--numa', action='store_true', help='use numactl') 523 parser.add_argument('--diff', nargs='?', default="./ready-to-run/riscv64-nemu-interpreter-so", type=str, help='nemu so') 524 parser.add_argument('--max-instr', nargs='?', type=int, help='max instr') 525 parser.add_argument('--disable-fork', action='store_true', help='disable lightSSS') 526 parser.add_argument('--no-diff', action='store_true', help='disable difftest') 527 parser.add_argument('--ram-size', nargs='?', type=str, help='manually set simulation memory size (8GB by default)') 528 parser.add_argument('--gcpt-restore-bin', type=str, default="", help="specify the bin used to restore from gcpt") 529 # both makefile and emu arguments 530 parser.add_argument('--no-db', action='store_true', help='disable chiseldb dump') 531 parser.add_argument('--pgo', nargs='?', type=str, help='workload for pgo (null to disable pgo)') 532 parser.add_argument('--pgo-max-cycle', nargs='?', default=400000, type=int, help='maximun cycle to train pgo') 533 parser.add_argument('--pgo-emu-args', nargs='?', default='--no-diff', type=str, help='emu arguments for pgo') 534 parser.add_argument('--llvm-profdata', nargs='?', type=str, help='corresponding llvm-profdata command of clang to compile emu, do not set with GCC') 535 536 args = parser.parse_args() 537 538 xs = XiangShan(args) 539 ret = xs.run(args) 540 541 sys.exit(ret) 542