Merge branch 'main' of https://github.com/openhwgroup/cvw into rvvi_setup

This commit is contained in:
Huda-10xe 2024-10-31 01:52:23 -07:00
commit 571ec51658
8 changed files with 408 additions and 39 deletions

View File

@ -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

View File

@ -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.

View File

@ -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],..."')

View File

@ -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)

View File

@ -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

View File

@ -59,12 +59,12 @@ if(args.testsuite.endswith('.elf') and args.elf == ""): # No --elf argument; che
args.testsuite = fields[1] + "_" + fields[3]
else:
args.testsuite = fields[2] + "_" + fields[3]
elif ('/' in args.testsuite):
elif ('/' in args.testsuite):
args.testsuite=args.testsuite.rsplit('/', 1)[1] # strip off path if present
else:
print("ELF file not found: " + args.testsuite)
exit(1)
if(args.lockstep and not args.testsuite.endswith('.elf')):
print(f"Invalid Options. Cannot run a testsuite, {args.testsuite} with lockstep. Must run a single elf.")
exit(1)
@ -89,13 +89,14 @@ if(int(args.locksteplog) >= 1): EnableLog = 1
else: EnableLog = 0
prefix = ""
if (args.lockstep or args.lockstepverbose or args.fcov or args.fcovimp):
if (args.sim == "questa" or args.sim == "vcs"):
if (args.sim == "questa" or args.sim == "vcs"):
prefix = "IMPERAS_TOOLS=" + WALLY + "/config/"+args.config+"/imperas.ic"
if (args.sim == "questa"):
prefix = "MTI_VCO_MODE=64 " + prefix
# Force Questa to use 64-bit mode, sometimes it defaults to 32-bit even on 64-bit machines
if (args.sim == "questa"):
prefix = "MTI_VCO_MODE=64 " + prefix
if (args.lockstep or args.lockstepverbose):
if(args.locksteplog != 0): ImperasPlusArgs = " +IDV_TRACE2LOG=" + str(EnableLog) + " +IDV_TRACE2LOG_AFTER=" + str(args.locksteplog)
if(args.locksteplog != 0): ImperasPlusArgs = " +IDV_TRACE2LOG=" + str(EnableLog) + " +IDV_TRACE2LOG_AFTER=" + str(args.locksteplog)
else: ImperasPlusArgs = ""
if(args.fcovimp):
CovEnableStr = "1" if int(args.covlog) > 0 else "0"

View File

@ -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;

View File

@ -0,0 +1,348 @@
///////////////////////////////////////////
// spi_controller.sv
//
// Written: jacobpease@protonmail.com
// Created: October 28th, 2024
// Modified:
//
// Purpose: Controller logic for SPI
//
// Documentation: RISC-V System on Chip Design
//
// A component of the CORE-V-WALLY configurable RISC-V project.
// https://github.com/openhwgroup/cvw
//
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
// may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work distributed under the
// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
////////////////////////////////////////////////////////////////////////////////////////////////
module spi_controller (
input logic PCLK,
input logic PRESETn,
input logic TransmitStart,
input logic [11:0] SckDiv,
input logic [1:0] SckMode,
input logic [1:0] CSMode,
input logic [15:0] Delay0,
input logic [15:0] Delay1,
input logic [7:0] txFIFORead,
input logic txFIFOReadEmpty,
output logic SPICLK,
output logic SPIOUT,
output logic CS
);
// CSMode Stuff
localparam HOLDMODE = 2'b10;
localparam AUTOMODE = 2'b00;
localparam OFFMODE = 2'b11;
typedef enum logic [2:0] {INACTIVE, CSSCK, TRANSMIT, SCKCS, HOLD, INTERCS, INTERXFR} statetype;
statetype CurrState, NextState;
// SCLKenable stuff
logic [11:0] DivCounter;
logic SCLKenable;
logic SCLKenableEarly;
logic SCLKenableLate;
logic EdgeTiming;
logic ZeroDiv;
logic Clock0;
logic Clock1;
logic SCK; // SUPER IMPORTANT, THIS CAN'T BE THE SAME AS SPICLK!
// Shift and Sample Edges
logic PreShiftEdge;
logic PreSampleEdge;
logic ShiftEdge;
logic SampleEdge;
// Frame stuff
logic [2:0] BitNum;
logic LastBit;
logic EndOfFrame;
logic EndOfFrameDelay;
logic PhaseOneOffset;
// Transmit Stuff
logic ContinueTransmit;
// SPIOUT Stuff
logic TransmitLoad;
logic [7:0] TransmitReg;
logic Transmitting;
logic EndTransmission;
logic HoldMode;
// Delay Stuff
logic [7:0] cssck;
logic [7:0] sckcs;
logic [7:0] intercs;
logic [7:0] interxfr;
logic HasCSSCK;
logic HasSCKCS;
logic HasINTERCS;
logic HasINTERXFR;
logic EndOfCSSCK;
logic EndOfSCKCS;
logic EndOfINTERCS;
logic EndOfINTERXFR;
logic [7:0] CSSCKCounter;
logic [7:0] SCKCSCounter;
logic [7:0] INTERCSCounter;
logic [7:0] INTERXFRCounter;
logic DelayIsNext;
// Convenient Delay Reg Names
assign cssck = Delay0[7:0];
assign sckcs = Delay0[15:8];
assign intercs = Delay1[7:0];
assign interxfr = Delay1[15:8];
// Do we have delay for anything?
assign HasCSSCK = cssck > 8'b0;
assign HasSCKCS = sckcs > 8'b0;
assign HasINTERCS = intercs > 8'b0;
assign HasINTERXFR = interxfr > 8'b0;
// Have we hit full delay for any of the delays?
assign EndOfCSSCK = CSSCKCounter == cssck;
assign EndOfSCKCS = SCKCSCounter == sckcs;
assign EndOfINTERCS = INTERCSCounter == intercs;
assign EndOfINTERXFR = INTERXFRCounter == interxfr;
// Clock Signal Stuff -----------------------------------------------
// I'm going to handle all clock stuff here, including ShiftEdge and
// SampleEdge. This makes sure that SPICLK is an output of a register
// and it properly synchronizes signals.
assign SCLKenableLate = DivCounter > SckDiv;
assign SCLKenable = DivCounter == SckDiv;
assign SCLKenableEarly = (DivCounter + 1'b1) == SckDiv;
assign LastBit = BitNum == 3'd7;
assign EdgeTiming = SckDiv > 12'b0 ? SCLKenableEarly : SCLKenable;
//assign SPICLK = Clock0;
assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrame;
assign EndTransmission = txFIFOReadEmpty & EndOfFrameDelay;
always_ff @(posedge PCLK) begin
if (~PRESETn) begin
DivCounter <= 12'b0;
SPICLK <= SckMode[1];
SCK <= 0;
BitNum <= 3'h0;
PreShiftEdge <= 0;
PreSampleEdge <= 0;
EndOfFrame <= 0;
end else begin
// TODO: Consolidate into one delay counter since none of the
// delays happen at the same time?
if (TransmitStart) begin
SCK <= 0;
end else if (SCLKenable) begin
SCK <= ~SCK;
end
if ((CurrState == CSSCK) & SCK) begin
CSSCKCounter <= CSSCKCounter + 8'd1;
end else begin
CSSCKCounter <= 8'd0;
end
if ((CurrState == SCKCS) & SCK) begin
SCKCSCounter <= SCKCSCounter + 8'd1;
end else begin
SCKCSCounter <= 8'd0;
end
if ((CurrState == INTERCS) & SCK) begin
INTERCSCounter <= INTERCSCounter + 8'd1;
end else begin
INTERCSCounter <= 8'd0;
end
if ((CurrState == INTERXFR) & SCK) begin
INTERXFRCounter <= INTERXFRCounter + 8'd1;
end else begin
INTERXFRCounter <= 8'd0;
end
// SPICLK Logic
if (TransmitStart) begin
SPICLK <= SckMode[1];
end else if (SCLKenable & Transmitting) begin
SPICLK <= (~EndTransmission & ~DelayIsNext) ? ~SPICLK : SckMode[1];
end
// Reset divider
if (SCLKenable | TransmitStart) begin
DivCounter <= 12'b0;
end else begin
DivCounter = DivCounter + 12'd1;
end
// EndOfFrame controller
// if (SckDiv > 0 ? SCLKenableEarly & LastBit & SPICLK : LastBit & ~SPICLK) begin
// EndOfFrame <= 1'b1;
// end else begin
// EndOfFrame <= 1'b0;
// end
if (~TransmitStart) begin
EndOfFrame <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting;
end
// Increment BitNum
if (ShiftEdge & Transmitting) begin
BitNum <= BitNum + 3'd1;
end else if (EndOfFrameDelay) begin
BitNum <= 3'b0;
end
end
end
// Delay ShiftEdge and SampleEdge by a half PCLK period
// Aligned EXACTLY ON THE MIDDLE of the leading and trailing edges.
// Sweeeeeeeeeet...
always_ff @(posedge ~PCLK) begin
if (~PRESETn | TransmitStart) begin
ShiftEdge <= 0;
PhaseOneOffset <= 0;
SampleEdge <= 0;
EndOfFrameDelay <= 0;
end else begin
ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & PhaseOneOffset;
PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : PhaseOneOffset;
SampleEdge <= (SckMode[1] ^ SckMode[0] ^ ~SPICLK) & SCLKenable & Transmitting;
EndOfFrameDelay <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting;
end
end
// typedef enum logic [2:0] {INACTIVE, CSSCK, TRANSMIT, SCKCS, HOLD, INTERCS, INTERXFR} statetype;
// statetype CurrState, NextState;
assign HoldMode = CSMode == 2'b10;
assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~txFIFOReadEmpty);
always_ff @(posedge PCLK) begin
if (~PRESETn) begin
CurrState <= INACTIVE;
end else if (SCLKenable) begin
CurrState <= NextState;
end
end
always_comb begin
case (CurrState)
INACTIVE: begin // INACTIVE case --------------------------------
if (TransmitStart) begin
if (~HasCSSCK) begin
NextState = TRANSMIT;
end else begin
NextState = CSSCK;
end
end else begin
NextState = INACTIVE;
end
end
CSSCK: begin // DELAY0 case -------------------------------------
if (EndOfCSSCK) begin
NextState = TRANSMIT;
end
end
TRANSMIT: begin // TRANSMIT case --------------------------------
case(CSMode)
AUTOMODE: begin
if (EndTransmission) begin
NextState = INACTIVE;
end else if (ContinueTransmit) begin
NextState = SCKCS;
end
end
HOLDMODE: begin
if (EndTransmission) begin
NextState = HOLD;
end else if (ContinueTransmit) begin
if (HasINTERXFR) NextState = INTERXFR;
end
end
OFFMODE: begin
end
endcase
end
SCKCS: begin // SCKCS case --------------------------------------
if (EndOfSCKCS) begin
if (EndTransmission) begin
if (CSMode == AUTOMODE) NextState = INACTIVE;
else if (CSMode == HOLDMODE) NextState = HOLD;
end else if (ContinueTransmit) begin
if (HasINTERCS) NextState = INTERCS;
else NextState = TRANSMIT;
end
end
end
HOLD: begin // HOLD mode case -----------------------------------
if (CSMode == AUTOMODE) begin
NextState = INACTIVE;
end else if (TransmitStart) begin // If FIFO is written to, start again.
NextState = TRANSMIT;
end
end
INTERCS: begin // INTERCS case ----------------------------------
if (EndOfINTERCS) begin
if (HasCSSCK) NextState = CSSCK;
else NextState = TRANSMIT;
end
end
INTERXFR: begin // INTERXFR case --------------------------------
if (EndOfINTERXFR) begin
NextState = TRANSMIT;
end
end
default: begin
NextState = INACTIVE;
end
endcase
end
assign Transmitting = CurrState == TRANSMIT;
assign DelayIsNext = (NextState == CSSCK | NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR);
//
always_ff @(posedge PCLK) begin
if (~PRESETn) begin
TransmitReg <= 8'b0;
end else if (TransmitLoad) begin
TransmitReg <= txFIFORead;
end else if (ShiftEdge) begin
TransmitReg <= {TransmitReg[6:0], TransmitReg[0]};
end
end
assign SPIOUT = TransmitReg[7];
assign CS = CurrState == INACTIVE | CurrState == INTERCS;
endmodule