diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml index b87f4f116..b065cd924 100644 --- a/.github/workflows/install.yml +++ b/.github/workflows/install.yml @@ -18,7 +18,7 @@ on: paths: - 'bin/wally-tool-chain-install.sh' - 'bin/wally-distro-check.sh' - - 'wally-package-install.sh' + - 'bin/wally-package-install.sh' schedule: - cron: "0 7 * * 3" # Run at 12:00 AM Pacific Time on Wednesdays diff --git a/README.md b/README.md index 2c2bc0d0a..40dc08d51 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,7 @@ The Synopsys Installer automatically installs all downloaded product files into ``` > [!Note] -> Although most parts of Wally, including the Questa simulator, will work on most modern Linux platforms, as of 2022, the Synopsys CAD tools for SoC design are only supported on RedHat Enterprise Linux 7.4 or 8 or SUSE Linux Enterprise Server (SLES) 12 or 15. Moreover, the RISC-V formal specification (sail-riscv) does not build gracefully on RHEL7. +> Although most parts of Wally, including the Questa simulator, will work on most modern Linux platforms, as of 2024, the Synopsys CAD tools for SoC design are only supported on Red Hat Enterprise Linux (or AlmaLinux/Rocky) 8.4+ or 9.1+ or SUSE Linux Enterprise Server (SLES) 15. The Verilog simulation has been tested with Siemens Questa/ModelSim. This package is available to universities worldwide as part of the Design Verification Bundle through the Siemens Academic Partner Program members for $990/year. diff --git a/bin/nightly_build.py b/bin/nightly_build.py index 349bdb378..cb8583eef 100755 --- a/bin/nightly_build.py +++ b/bin/nightly_build.py @@ -288,33 +288,34 @@ class TestRunner: makefile_location = self.cvw.joinpath(makefile_path) os.chdir(makefile_location) - output_file = self.log_dir.joinpath(f"make-{target}-output.log") + if target: + output_file = self.log_dir.joinpath(f"make-{target}-output.log") + else: output_file = self.log_dir.joinpath(f"make-output.log") - command = ["make"] - - # Add target to the command if specified - if target: - command.append(target) - self.logger.info(f"Command used in directory {makefile_location}: {command[0]} {command[1]}") + # Execute make with target and cores/2 + if target: + command = ["make", target, "--jobs=$(($(nproc)/2))"] else: - self.logger.info(f"Command used in directory {makefile_location}: {command[0]}") + command = ["make", "--jobs=$(($(nproc)/2))"] + + self.logger.info(f"Command used in directory {makefile_location}: {' '.join(command)}") # Execute the command using subprocess and save the output into a file with open(output_file, "w") as f: formatted_datetime = self.current_datetime.strftime("%Y-%m-%d %H:%M:%S") f.write(formatted_datetime) f.write("\n\n") - result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True) + result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True, shell=True) # Execute the command using a subprocess and not save the output #result = subprocess.run(command, text=True) # Check the result if result.returncode == 0: - self.logger.info(f"Tests have been made with target: {target}") + self.logger.info(f"Tests have been made with target: {' '.join(command)}") return True else: - self.logger.error(f"Error making the tests. Target: {target}") + self.logger.error(f"Error making the tests. Command: {' '.join(command)}") return False def run_tests(self, test_type=None, test_name=None, test_extensions=None): @@ -422,7 +423,7 @@ class TestRunner: elif "Failures detected in output" in line: # Text explicitly fails try: config_name = line.split(':')[0].strip() - log_file = os.path.abspath(os.path.join("logs", config_name, ".log")) + log_file = os.path.abspath(os.path.join("logs", config_name)) failed_configs.append((config_name, log_file)) except: failed_configs.append((config_name, "Log file not found")) @@ -672,7 +673,7 @@ def main(): parser.add_argument('--path',default = "nightly", help='specify the path for where the nightly repositories will be cloned ex: "nightly-runs') parser.add_argument('--repository',default = "https://github.com/openhwgroup/cvw", help='specify which github repository you want to clone') - parser.add_argument('--target', default = "--jobs", help='types of tests you can make are: all, wally-riscv-arch-test, no') + parser.add_argument('--target', default = "", help='types of tests you can make are: all, wally-riscv-arch-test, no') parser.add_argument('--tests', default = "nightly", help='types of tests you can run are: nightly, test, test_lint') parser.add_argument('--send_email',default = "", nargs="+", help='What emails to send test results to. Example: "[email1],[email2],..."') diff --git a/bin/regression-wally b/bin/regression-wally index 643787adc..0a7a8fa69 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -334,22 +334,29 @@ def search_log_for_text(text, grepfile): # print(" search_log_for_text invoking %s" % grepcmd) return os.system(grepcmd) == 0 -def run_test_case(config): - """Run the given test case, and return 0 if the test suceeds and 1 if it fails""" +def run_test_case(config, dryrun: bool = False): + """ + Run the given test case, and return 0 if the test suceeds and 1 if it fails + + Do not execute commands if dryrun + """ grepfile = config.grepfile cmd = config.cmd os.chdir(regressionDir) - # print(" run_test_case invoking %s" % cmd, flush=True) - os.system(cmd) - if search_log_for_text(config.grepstr, grepfile): - # Flush is needed to flush output to stdout when running in multiprocessing Pool -# print(f"{bcolors.OKGREEN}%s_%s: Success{bcolors.ENDC}" % (config.variant, config.name), flush=True) - print(f"{bcolors.OKGREEN}%s: Success{bcolors.ENDC}" % (config.cmd), flush=True) + if dryrun: + print(f"Executing {cmd}", flush=True) return 0 else: - print(f"{bcolors.FAIL}%s: Failures detected in output{bcolors.ENDC}" % (config.cmd), flush=True) - print(" Check %s" % grepfile) - return 1 + os.system(cmd) + if search_log_for_text(config.grepstr, grepfile): + # Flush is needed to flush output to stdout when running in multiprocessing Pool + # print(f"{bcolors.OKGREEN}%s_%s: Success{bcolors.ENDC}" % (config.variant, config.name), flush=True) + print(f"{bcolors.OKGREEN}%s: Success{bcolors.ENDC}" % (config.cmd), flush=True) + return 0 + else: + print(f"{bcolors.FAIL}%s: Failures detected in output{bcolors.ENDC}" % (config.cmd), flush=True) + print(" Check %s" % grepfile) + return 1 ################################## # Main body @@ -363,6 +370,7 @@ os.chdir(regressionDir) coveragesim = "questa" # Questa is required for code/functional coverage #defaultsim = "questa" # Default simulator for all other tests; change to Verilator when flow is ready defaultsim = "verilator" # Default simulator for all other tests +lockstepsim = "questa" parser = argparse.ArgumentParser() parser.add_argument("--ccov", help="Code Coverage", action="store_true") @@ -371,6 +379,7 @@ parser.add_argument("--nightly", help="Run large nightly regression", action="st parser.add_argument("--buildroot", help="Include Buildroot Linux boot test (takes many hours, done along with --nightly)", action="store_true") parser.add_argument("--testfloat", help="Include Testfloat floating-point unit tests", action="store_true") parser.add_argument("--fp", help="Include floating-point tests in coverage (slower runtime)", action="store_true") +parser.add_argument("--dryrun", help="Print commands invoked to console without running regression", action="store_true") args = parser.parse_args() if (args.nightly): @@ -404,7 +413,7 @@ configs = [ # run full buildroot boot simulation (slow) if buildroot flag is set. Start it early to overlap with other tests if (args.buildroot): # addTests(tests_buildrootboot, defaultsim) # non-lockstep with Verilator runs in about 2 hours - addTests(tests_buildrootbootlockstep, "questa") # lockstep with Questa and ImperasDV runs overnight + addTests(tests_buildrootbootlockstep, lockstepsim) # lockstep with Questa and ImperasDV runs overnight if (args.ccov): # only run RV64GC tests on Questa in code coverage mode addTests(tests64gc_nofp, coveragesim) @@ -417,7 +426,7 @@ elif (args.fcov): # only run RV64GC tests on Questa in lockstep in functional c else: for sim in sims: - if (not (args.buildroot and sim == defaultsim)): # skip short buildroot sim if running long one + if (not (args.buildroot and sim == lockstepsim)): # skip short buildroot sim if running long one addTests(tests_buildrootshort, sim) addTests(tests, sim) addTests(tests64gc_nofp, sim) @@ -425,9 +434,10 @@ else: # run derivative configurations and lockstep tests in nightly regression if (args.nightly): - addLockstepTestsByDir(WALLY+"/tests/coverage", "rv64gc", "questa", 0) - addLockstepTestsByDir(WALLY+"/tests/riscof/work/wally-riscv-arch-test/rv64i_m", "rv64gc", "questa", 0) + addLockstepTestsByDir(WALLY+"/tests/coverage", "rv64gc", lockstepsim, 0) + addLockstepTestsByDir(WALLY+"/tests/riscof/work/wally-riscv-arch-test/rv64i_m", "rv64gc", lockstepsim, 0) addTests(derivconfigtests, defaultsim) + # addTests(bpredtests, defaultsim) # This is currently broken in regression due to something related to the new wsim script. # testfloat tests if (args.testfloat): # for testfloat alone, just run testfloat tests @@ -540,9 +550,9 @@ def main(): # Coverage report if args.ccov: - os.system('make QuestaCodeCoverage') + os.system('make QuestaCodeCoverage') if args.fcov: - os.system('make -f '+WALLY+'/addins/cvw-arch-verif/Makefile merge') + os.system('make -f '+WALLY+'/addins/cvw-arch-verif/Makefile merge') # Count the number of failures if num_fail: print(f"{bcolors.FAIL}Regression failed with %s failed configurations{bcolors.ENDC}" % num_fail) diff --git a/bin/wally-package-install.sh b/bin/wally-package-install.sh index 725d3b201..1fc003189 100755 --- a/bin/wally-package-install.sh +++ b/bin/wally-package-install.sh @@ -123,5 +123,14 @@ else eval "$UPDATE_COMMAND" # Install packages listed above using appropriate package manager sudo $PACKAGE_MANAGER install -y "${GENERAL_PACKAGES[@]}" "${GNU_PACKAGES[@]}" "${QEMU_PACKAGES[@]}" "${SPIKE_PACKAGES[@]}" "${VERILATOR_PACKAGES[@]}" "${BUILDROOT_PACKAGES[@]}" "${OTHER_PACKAGES[@]}" "${VIVADO_PACKAGES[@]}" + + # Post install steps + # Vivado looks for ncurses5 libraries, but Ubuntu 24.04 only has ncurses6 + # Create symbolic links to the ncurses6 libraries to fool Vivado + if (( UBUNTU_VERSION >= 24 )); then + sudo ln -vsf /lib/x86_64-linux-gnu/libncurses.so.6 /lib/x86_64-linux-gnu/libncurses.so.5 + sudo ln -vsf /lib/x86_64-linux-gnu/libtinfo.so.6 /lib/x86_64-linux-gnu/libntinfo.so.5 + fi + echo -e "${SUCCESS_COLOR}Packages successfully installed.${ENDC}" fi diff --git a/config/rv32gc/coverage.svh b/config/rv32gc/coverage.svh index 217e8788a..2eb52541f 100644 --- a/config/rv32gc/coverage.svh +++ b/config/rv32gc/coverage.svh @@ -10,6 +10,9 @@ `include "RV32M_coverage.svh" `include "RV32F_coverage.svh" `include "RV32D_coverage.svh" +`include "RV32ZfaF_coverage.svh" +`include "RV32ZfaD_coverage.svh" +`include "RV32ZfaZfh_coverage.svh" `include "RV32ZfhD_coverage.svh" `include "RV32Zfh_coverage.svh" `include "RV32Zicond_coverage.svh" diff --git a/config/rv64gc/coverage.svh b/config/rv64gc/coverage.svh index 0491b4ab3..d594a3a44 100644 --- a/config/rv64gc/coverage.svh +++ b/config/rv64gc/coverage.svh @@ -10,6 +10,9 @@ `include "RV64M_coverage.svh" `include "RV64F_coverage.svh" `include "RV64D_coverage.svh" +`include "RV64ZfaF_coverage.svh" +`include "RV32ZfaD_coverage.svh" +`include "RV32ZfaZfh_coverage.svh" `include "RV64ZfhD_coverage.svh" `include "RV64Zfh_coverage.svh" `include "RV64Zicond_coverage.svh" diff --git a/src/fpu/fround.sv b/src/fpu/fround.sv index 3265ec626..6c37d2973 100644 --- a/src/fpu/fround.sv +++ b/src/fpu/fround.sv @@ -76,7 +76,7 @@ module fround import cvw::*; #(parameter cvw_t P) ( assign Eeqm1 = ($signed(E) == -1); // Logic for nonnegative mask and rounding bits - assign IMask = {1'b1, {P.NF{1'b0}}} >>> E; /// if E > Nf, this produces all 0s instead of all 1s. Hence exact handling is needed below. + assign IMask = $signed({1'b1, {P.NF{1'b0}}}) >>> E; /// if E > Nf, this produces all 0s instead of all 1s. Hence exact handling is needed below. assign Tmasknonneg = ~IMask >>> 1'b1; assign HotE = IMask & ~(IMask << 1'b1); assign HotEP1 = HotE >> 1'b1;