mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-06-28 17:43:09 -04:00
Merge branch 'openhwgroup:main' into main
This commit is contained in:
commit
c93cadc95c
19 changed files with 644 additions and 151 deletions
7
.github/workflows/install.yml
vendored
7
.github/workflows/install.yml
vendored
|
@ -67,6 +67,12 @@ jobs:
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
image: null
|
image: null
|
||||||
riscv_path: /home/riscv
|
riscv_path: /home/riscv
|
||||||
|
# Custom location user level installation
|
||||||
|
- name: custom-user-install
|
||||||
|
os: ubuntu-latest
|
||||||
|
image: null
|
||||||
|
user: true
|
||||||
|
riscv_path: $HOME/riscv-toolchain
|
||||||
|
|
||||||
# run on selected version of ubuntu or on ubuntu-latest with docker image
|
# run on selected version of ubuntu or on ubuntu-latest with docker image
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
@ -108,6 +114,7 @@ jobs:
|
||||||
fi
|
fi
|
||||||
# Set environment variables for the rest of the job
|
# Set environment variables for the rest of the job
|
||||||
- name: Set Environment Variables
|
- name: Set Environment Variables
|
||||||
|
if: always()
|
||||||
run: |
|
run: |
|
||||||
if [ ! -z ${{ matrix.riscv_path }} ]; then
|
if [ ! -z ${{ matrix.riscv_path }} ]; then
|
||||||
sed -i 's,exit 1,export RISCV=${{ matrix.riscv_path }},g' setup.sh
|
sed -i 's,exit 1,export RISCV=${{ matrix.riscv_path }},g' setup.sh
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||

|

|
||||||
|
|
||||||
# core-v-wally
|
# core-v-wally
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ from pathlib import Path
|
||||||
class FolderManager:
|
class FolderManager:
|
||||||
"""A class for managing folders and repository cloning."""
|
"""A class for managing folders and repository cloning."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, basedir):
|
||||||
"""
|
"""
|
||||||
Initialize the FolderManager instance.
|
Initialize the FolderManager instance.
|
||||||
|
|
||||||
|
@ -92,8 +92,12 @@ class FolderManager:
|
||||||
base_dir (str): The base directory where folders will be managed and repository will be cloned.
|
base_dir (str): The base directory where folders will be managed and repository will be cloned.
|
||||||
"""
|
"""
|
||||||
env_extract_var = 'WALLY'
|
env_extract_var = 'WALLY'
|
||||||
|
if os.environ.get(env_extract_var):
|
||||||
self.base_dir = os.environ.get(env_extract_var)
|
self.base_dir = os.environ.get(env_extract_var)
|
||||||
self.base_parent_dir = os.path.dirname(self.base_dir)
|
self.base_parent_dir = os.path.dirname(self.base_dir)
|
||||||
|
else:
|
||||||
|
self.base_dir = basedir
|
||||||
|
self.base_parent_dir = self.base_dir
|
||||||
|
|
||||||
# logger.info(f"Base directory: {self.base_dir}")
|
# logger.info(f"Base directory: {self.base_dir}")
|
||||||
# logger.info(f"Parent Base directory: {self.base_parent_dir}")
|
# logger.info(f"Parent Base directory: {self.base_parent_dir}")
|
||||||
|
@ -313,7 +317,7 @@ class TestRunner:
|
||||||
self.logger.error(f"Error making the tests. Target: {target}")
|
self.logger.error(f"Error making the tests. Target: {target}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def run_tests(self, test_type=None, test_name=None, test_extension=None):
|
def run_tests(self, test_type=None, test_name=None, test_extensions=None):
|
||||||
"""
|
"""
|
||||||
Run a script through the terminal and save the output to a file.
|
Run a script through the terminal and save the output to a file.
|
||||||
|
|
||||||
|
@ -329,12 +333,12 @@ class TestRunner:
|
||||||
output_file = self.log_dir.joinpath(f"{test_name}-output.log")
|
output_file = self.log_dir.joinpath(f"{test_name}-output.log")
|
||||||
os.chdir(self.sim_dir)
|
os.chdir(self.sim_dir)
|
||||||
|
|
||||||
if test_extension:
|
if test_extensions:
|
||||||
command = [test_type, test_name, test_extension]
|
command = [test_type, test_name] + test_extensions
|
||||||
self.logger.info(f"Command used to run tests: {test_type} {test_name} {test_extension}")
|
self.logger.info(f"Command used to run tests in directory {self.sim_dir}: {test_type} {test_name} {' '.join(test_extensions)}")
|
||||||
else:
|
else:
|
||||||
command = [test_type, test_name]
|
command = [test_type, test_name]
|
||||||
self.logger.info(f"Command used to run tests: {test_type} {test_name}")
|
self.logger.info(f"Command used to run tests in directory {self.sim_dir}: {test_type} {test_name}")
|
||||||
|
|
||||||
|
|
||||||
# Execute the command using subprocess and save the output into a file
|
# Execute the command using subprocess and save the output into a file
|
||||||
|
@ -348,10 +352,10 @@ class TestRunner:
|
||||||
self.logger.error("There was an error in running the tests in the run_tests function: {e}")
|
self.logger.error("There was an error in running the tests in the run_tests function: {e}")
|
||||||
# Check if the command executed successfuly
|
# Check if the command executed successfuly
|
||||||
if result.returncode or result.returncode == 0:
|
if result.returncode or result.returncode == 0:
|
||||||
self.logger.info(f"Test ran successfuly. Test type: {test_type}, test name: {test_name}, test extention: {test_extension}")
|
self.logger.info(f"Test ran successfuly. Test type: {test_type}, test name: {test_name}, test extension: {' '.join(test_extensions)}")
|
||||||
return True, output_file
|
return True, output_file
|
||||||
else:
|
else:
|
||||||
self.logger.error(f"Error making test. Test type: {test_type}, test name: {test_name}, test extention: {test_extension}")
|
self.logger.error(f"Error making test. Test type: {test_type}, test name: {test_name}, test extension: {' '.join(test_extensions)}")
|
||||||
return False, output_file
|
return False, output_file
|
||||||
|
|
||||||
|
|
||||||
|
@ -406,23 +410,31 @@ class TestRunner:
|
||||||
# Remove ANSI escape codes
|
# Remove ANSI escape codes
|
||||||
line = re.sub(r'\x1b\[[0-9;]*[mGK]', '', lines[index])
|
line = re.sub(r'\x1b\[[0-9;]*[mGK]', '', lines[index])
|
||||||
|
|
||||||
if "Success" in line:
|
if "Success" in line: # test succeeds
|
||||||
passed_configs.append(line.split(':')[0].strip())
|
passed_configs.append(line.split(':')[0].strip())
|
||||||
elif "passed lint" in line:
|
elif "passed lint" in line:
|
||||||
passed_configs.append(line.split(' ')[0].strip())
|
passed_configs.append(f"Lint: {line.split(' ')[0].strip()}")
|
||||||
#passed_configs.append(line) # potentially use a space
|
#passed_configs.append(line) # potentially use a space
|
||||||
elif "failed lint" in line:
|
elif "failed lint" in line:
|
||||||
failed_configs.append(line.split(' ')[0].strip(), "no log file")
|
failed_configs.append([f"Lint: {line.split(' ')[0].strip()}", "No Log File"])
|
||||||
#failed_configs.append(line)
|
#failed_configs.append(line)
|
||||||
|
|
||||||
elif "Failures detected in output" in line:
|
elif "Failures detected in output" in line: # Text explicitly fails
|
||||||
try:
|
try:
|
||||||
config_name = line.split(':')[0].strip()
|
config_name = line.split(':')[0].strip()
|
||||||
log_file = os.path.abspath("logs/"+config_name+".log")
|
log_file = os.path.abspath(os.path.join("logs", config_name, ".log"))
|
||||||
failed_configs.append((config_name, log_file))
|
failed_configs.append((config_name, log_file))
|
||||||
except:
|
except:
|
||||||
failed_configs.append((config_name, "Log file not found"))
|
failed_configs.append((config_name, "Log file not found"))
|
||||||
|
|
||||||
|
elif "Timeout" in line: # Test times out
|
||||||
|
try:
|
||||||
|
config_name = line.split(':')[0].strip()
|
||||||
|
log_file = os.path.abspath("logs/"+config_name+".log")
|
||||||
|
failed_configs.append((f"Timeout: {config_name}", log_file))
|
||||||
|
except:
|
||||||
|
failed_configs.append((f"Timeout: {config_name}", "No Log File"))
|
||||||
|
|
||||||
|
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
|
@ -535,7 +547,7 @@ class TestRunner:
|
||||||
md_file.write(f"\n**Total failed tests: {total_number_failures}**")
|
md_file.write(f"\n**Total failed tests: {total_number_failures}**")
|
||||||
for (test_item, item) in zip(test_list, failed_tests):
|
for (test_item, item) in zip(test_list, failed_tests):
|
||||||
md_file.write(f"\n\n### {test_item[1]} test")
|
md_file.write(f"\n\n### {test_item[1]} test")
|
||||||
md_file.write(f"\n**Command used:** {test_item[0]} {test_item[1]} {test_item[2]}\n\n")
|
md_file.write(f"\n**Command used:** {test_item[0]} {test_item[1]} {' '.join(test_item[2])}\n\n")
|
||||||
md_file.write(f"**Failed Tests:**\n")
|
md_file.write(f"**Failed Tests:**\n")
|
||||||
|
|
||||||
|
|
||||||
|
@ -558,7 +570,7 @@ class TestRunner:
|
||||||
md_file.write(f"\n**Total successful tests: {total_number_success}**")
|
md_file.write(f"\n**Total successful tests: {total_number_success}**")
|
||||||
for (test_item, item) in zip(test_list, passed_tests):
|
for (test_item, item) in zip(test_list, passed_tests):
|
||||||
md_file.write(f"\n\n### {test_item[1]} test")
|
md_file.write(f"\n\n### {test_item[1]} test")
|
||||||
md_file.write(f"\n**Command used:** {test_item[0]} {test_item[1]} {test_item[2]}\n\n")
|
md_file.write(f"\n**Command used:** {test_item[0]} {test_item[1]} {' '.join(test_item[2])}\n\n")
|
||||||
md_file.write(f"\n**Successful Tests:**\n")
|
md_file.write(f"\n**Successful Tests:**\n")
|
||||||
|
|
||||||
|
|
||||||
|
@ -619,7 +631,7 @@ class TestRunner:
|
||||||
|
|
||||||
# check if there are any emails
|
# check if there are any emails
|
||||||
if not receiver_emails:
|
if not receiver_emails:
|
||||||
self.logger.ERROR("No receiver emails provided.")
|
self.logger.error("No receiver emails provided.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# grab the html file
|
# grab the html file
|
||||||
|
@ -660,7 +672,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('--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('--repository',default = "https://github.com/openhwgroup/cvw", help='specify which github repository you want to clone')
|
||||||
parser.add_argument('--target', default = "all", help='types of tests you can make are: all, wally-riscv-arch-test, no')
|
parser.add_argument('--target', default = "--jobs", 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('--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],..."')
|
parser.add_argument('--send_email',default = "", nargs="+", help='What emails to send test results to. Example: "[email1],[email2],..."')
|
||||||
|
|
||||||
|
@ -682,7 +694,7 @@ def main():
|
||||||
log_file_path = log_path.joinpath("nightly_build.log")
|
log_file_path = log_path.joinpath("nightly_build.log")
|
||||||
previous_cvw_path = Path.home().joinpath(args.path,f"{yesterday}/cvw")
|
previous_cvw_path = Path.home().joinpath(args.path,f"{yesterday}/cvw")
|
||||||
# creates the object
|
# creates the object
|
||||||
folder_manager = FolderManager()
|
folder_manager = FolderManager(basedir=args.path)
|
||||||
|
|
||||||
# setting the path on where to clone new repositories of cvw
|
# setting the path on where to clone new repositories of cvw
|
||||||
folder_manager.create_folders([cvw_path, results_path, log_path])
|
folder_manager.create_folders([cvw_path, results_path, log_path])
|
||||||
|
@ -691,14 +703,18 @@ def main():
|
||||||
folder_manager.clone_repository(cvw_path, args.repository)
|
folder_manager.clone_repository(cvw_path, args.repository)
|
||||||
|
|
||||||
# Define tests that we can run
|
# Define tests that we can run
|
||||||
if (args.tests == "nightly"):
|
#
|
||||||
test_list = [["python", "regression-wally", "--nightly --buildroot"]]
|
# flags are a list
|
||||||
elif (args.tests == "test"):
|
if (args.tests == "all"):
|
||||||
test_list = [["python", "regression-wally", ""]]
|
test_list = [["python", "./regression-wally", ["--nightly", "--buildroot"]]]
|
||||||
elif (args.tests == "test_lint"):
|
elif (args.tests == "nightly"):
|
||||||
test_list = [["bash", "lint-wally", "-nightly"]]
|
test_list = [["python", "./regression-wally", ["--nightly"]]]
|
||||||
|
elif (args.tests == "regression"):
|
||||||
|
test_list = [["python", "./regression-wally", []]]
|
||||||
|
elif (args.tests == "lint"):
|
||||||
|
test_list = [["bash", "./lint-wally", ["--nightly"]]]
|
||||||
else:
|
else:
|
||||||
print(f"Error: Invalid test '"+args.test+"' specified")
|
print(f"Error: Invalid test {args.tests} specified")
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
|
|
||||||
#############################################
|
#############################################
|
||||||
|
@ -747,12 +763,12 @@ def main():
|
||||||
|
|
||||||
if args.target != "no":
|
if args.target != "no":
|
||||||
test_runner.execute_makefile(target = args.target, makefile_path=test_runner.cvw)
|
test_runner.execute_makefile(target = args.target, makefile_path=test_runner.cvw)
|
||||||
if args.target == "all":
|
# TODO: remove vestigial code if no longer wanted
|
||||||
# Compile Linux for local testing
|
# if args.target == "all":
|
||||||
test_runner.set_env_var("RISCV",str(test_runner.cvw))
|
# # Compile Linux for local testing
|
||||||
linux_path = test_runner.cvw / "linux"
|
# test_runner.set_env_var("RISCV",str(test_runner.cvw))
|
||||||
test_runner.execute_makefile(target = "all_nosudo", makefile_path=linux_path)
|
# linux_path = test_runner.cvw / "linux"
|
||||||
test_runner.execute_makefile(target = "dumptvs_nosudo", makefile_path=linux_path)
|
# test_runner.execute_makefile(target = "all", makefile_path=linux_path)
|
||||||
|
|
||||||
#############################################
|
#############################################
|
||||||
# RUN TESTS #
|
# RUN TESTS #
|
||||||
|
@ -766,9 +782,9 @@ def main():
|
||||||
total_failures = []
|
total_failures = []
|
||||||
total_success = []
|
total_success = []
|
||||||
|
|
||||||
for test_type, test_name, test_extension in test_list:
|
for test_type, test_name, test_extensions in test_list:
|
||||||
|
|
||||||
check, output_location = test_runner.run_tests(test_type=test_type, test_name=test_name, test_extension=test_extension)
|
check, output_location = test_runner.run_tests(test_type=test_type, test_name=test_name, test_extensions=test_extensions)
|
||||||
try:
|
try:
|
||||||
if check: # this checks if the test actually ran successfuly
|
if check: # this checks if the test actually ran successfuly
|
||||||
output_log_list.append(output_location)
|
output_log_list.append(output_location)
|
||||||
|
@ -778,7 +794,7 @@ def main():
|
||||||
passed, failed = test_runner.clean_format_output(input_file = output_location)
|
passed, failed = test_runner.clean_format_output(input_file = output_location)
|
||||||
logger.info(f"{test_name} has been formatted to markdown")
|
logger.info(f"{test_name} has been formatted to markdown")
|
||||||
except:
|
except:
|
||||||
logger.ERROR(f"Error occured with formatting {test_name}")
|
logger.error(f"Error occured with formatting {test_name}")
|
||||||
|
|
||||||
logger.info(f"The # of failures are for {test_name}: {len(failed)}")
|
logger.info(f"The # of failures are for {test_name}: {len(failed)}")
|
||||||
total_number_failures+= len(failed)
|
total_number_failures+= len(failed)
|
||||||
|
@ -789,14 +805,18 @@ def main():
|
||||||
total_success.append(passed)
|
total_success.append(passed)
|
||||||
test_runner.rewrite_to_markdown(test_name, passed, failed)
|
test_runner.rewrite_to_markdown(test_name, passed, failed)
|
||||||
|
|
||||||
|
newlinechar = "\n"
|
||||||
|
logger.info(f"Failed tests: \n{newlinechar.join([x[0] for x in failed])}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("There was an error in running the tests: {e}")
|
logger.error(f"There was an error in running the tests: {e}")
|
||||||
|
|
||||||
logger.info(f"The total sucesses for all tests ran are: {total_number_success}")
|
logger.info(f"The total sucesses for all tests ran are: {total_number_success}")
|
||||||
logger.info(f"The total failures for all tests ran are: {total_number_failures}")
|
logger.info(f"The total failures for all tests ran are: {total_number_failures}")
|
||||||
|
|
||||||
# Copy actual test logs from sim/questa, sim/verilator
|
# Copy actual test logs from sim/questa, sim/verilator, sim/vcs
|
||||||
test_runner.copy_sim_logs([test_runner.cvw / "sim/questa/logs", test_runner.cvw / "sim/verilator/logs"])
|
if not args.tests == "test_lint":
|
||||||
|
test_runner.copy_sim_logs([test_runner.cvw / "sim/questa/logs", test_runner.cvw / "sim/verilator/logs", test_runner.cvw / "sim/vcs/logs"])
|
||||||
|
|
||||||
#############################################
|
#############################################
|
||||||
# FORMAT TESTS #
|
# FORMAT TESTS #
|
||||||
|
|
|
@ -507,7 +507,7 @@ def main():
|
||||||
TIMEOUT_DUR = 20*60 # seconds
|
TIMEOUT_DUR = 20*60 # seconds
|
||||||
os.system('rm -f questa/cov/*.ucdb')
|
os.system('rm -f questa/cov/*.ucdb')
|
||||||
elif args.fcov:
|
elif args.fcov:
|
||||||
TIMEOUT_DUR = 2*60
|
TIMEOUT_DUR = 8*60
|
||||||
os.system('rm -f questa/fcov_ucdb/* questa/fcov_logs/* questa/fcov/*')
|
os.system('rm -f questa/fcov_ucdb/* questa/fcov_logs/* questa/fcov/*')
|
||||||
elif args.buildroot:
|
elif args.buildroot:
|
||||||
TIMEOUT_DUR = 60*1440 # 1 day
|
TIMEOUT_DUR = 60*1440 # 1 day
|
||||||
|
@ -534,6 +534,7 @@ def main():
|
||||||
try:
|
try:
|
||||||
num_fail+=result.get(timeout=TIMEOUT_DUR)
|
num_fail+=result.get(timeout=TIMEOUT_DUR)
|
||||||
except TimeoutError:
|
except TimeoutError:
|
||||||
|
pool.terminate()
|
||||||
num_fail+=1
|
num_fail+=1
|
||||||
print(f"{bcolors.FAIL}%s: Timeout - runtime exceeded %d seconds{bcolors.ENDC}" % (config.cmd, TIMEOUT_DUR))
|
print(f"{bcolors.FAIL}%s: Timeout - runtime exceeded %d seconds{bcolors.ENDC}" % (config.cmd, TIMEOUT_DUR))
|
||||||
|
|
||||||
|
|
|
@ -48,28 +48,64 @@ ENDC='\033[0m' # Reset to default color
|
||||||
error() {
|
error() {
|
||||||
echo -e "${FAIL_COLOR}Error: $STATUS installation failed"
|
echo -e "${FAIL_COLOR}Error: $STATUS installation failed"
|
||||||
echo -e "Error on line ${BASH_LINENO[0]} with command $BASH_COMMAND${ENDC}"
|
echo -e "Error on line ${BASH_LINENO[0]} with command $BASH_COMMAND${ENDC}"
|
||||||
|
if [ -e "$RISCV/logs/$STATUS.log" ]; then
|
||||||
echo -e "Please check the log in $RISCV/logs/$STATUS.log for more information."
|
echo -e "Please check the log in $RISCV/logs/$STATUS.log for more information."
|
||||||
|
fi
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if a git repository exists, is up to date, and has been installed
|
# Check if a git repository exists, is up to date, and has been installed
|
||||||
# Clones the repository if it doesn't exist
|
# clones the repository if it doesn't exist
|
||||||
|
# $1: repo name
|
||||||
|
# $2: repo url to clone from
|
||||||
|
# $3: file to check if already installed
|
||||||
|
# $4: upstream branch, optional, default is master
|
||||||
git_check() {
|
git_check() {
|
||||||
local repo=$1
|
local repo=$1
|
||||||
local url=$2
|
local url=$2
|
||||||
local check=$3
|
local check=$3
|
||||||
local branch="${4:-master}"
|
local branch="${4:-master}"
|
||||||
if [[ ((! -e $repo) && ($(git clone "$url") || true)) || ($(cd "$repo"; git fetch; git rev-parse HEAD) != $(cd "$repo"; git rev-parse origin/"$branch")) || (! -e $check) ]]; then
|
|
||||||
return 0
|
# Clone repo if it doesn't exist
|
||||||
|
if [[ ! -e $repo ]]; then
|
||||||
|
for ((i=1; i<=5; i++)); do
|
||||||
|
git clone "$url" && break
|
||||||
|
echo -e "${WARNING_COLOR}Failed to clone $repo. Retrying.${ENDC}"
|
||||||
|
rm -rf "$repo"
|
||||||
|
sleep $i
|
||||||
|
done
|
||||||
|
if [[ ! -e $repo ]]; then
|
||||||
|
echo -e "${ERROR_COLOR}Failed to clone $repo after 5 attempts. Exiting.${ENDC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the current HEAD commit hash and the remote branch commit hash
|
||||||
|
cd "$repo"
|
||||||
|
git fetch
|
||||||
|
local local_head=$(git rev-parse HEAD)
|
||||||
|
local remote_head=$(git rev-parse origin/"$branch")
|
||||||
|
|
||||||
|
# Check if the git repository is not up to date or the specified file does not exist
|
||||||
|
if [[ "$local_head" != "$remote_head" ]]; then
|
||||||
|
echo "$repo is not up to date. Updating now."
|
||||||
|
true
|
||||||
|
elif [[ ! -e $check ]]; then
|
||||||
|
true
|
||||||
else
|
else
|
||||||
return 1
|
false
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Log output to a file and only print lines with keywords
|
# Log output to a file and only print lines with keywords
|
||||||
logger() {
|
logger() {
|
||||||
local log="$RISCV/logs/$1.log"
|
local log_file="$RISCV/logs/$1.log"
|
||||||
cat < /dev/stdin | tee -a "$log" | (grep -iE --color=never "(\bwarning|\berror|\bfail|\bsuccess|\bstamp|\bdoesn't work)" || true) | (grep -viE --color=never "(_warning|warning_|_error|error_|-warning|warning-|-error|error-|Werror|error\.o|warning flags)" || true)
|
local keyword_pattern="(\bwarning|\berror|\bfail|\bsuccess|\bstamp|\bdoesn't work)"
|
||||||
|
local exclude_pattern="(_warning|warning_|_error|error_|-warning|warning-|-error|error-|Werror|error\.o|warning flags)"
|
||||||
|
|
||||||
|
cat < /dev/stdin | tee -a "$log_file" | \
|
||||||
|
(grep -iE --color=never "$keyword_pattern" || true) | \
|
||||||
|
(grep -viE --color=never "$exclude_pattern" || true)
|
||||||
}
|
}
|
||||||
|
|
||||||
set -e # break on error
|
set -e # break on error
|
||||||
|
@ -111,6 +147,10 @@ fi
|
||||||
export PATH=$PATH:$RISCV/bin:/usr/bin
|
export PATH=$PATH:$RISCV/bin:/usr/bin
|
||||||
export PKG_CONFIG_PATH=$RISCV/lib64/pkgconfig:$RISCV/lib/pkgconfig:$RISCV/share/pkgconfig:$RISCV/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH
|
export PKG_CONFIG_PATH=$RISCV/lib64/pkgconfig:$RISCV/lib/pkgconfig:$RISCV/share/pkgconfig:$RISCV/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH
|
||||||
|
|
||||||
|
if (( RHEL_VERSION != 8 )); then
|
||||||
|
retry_on_host_error="--retry-on-host-error"
|
||||||
|
fi
|
||||||
|
|
||||||
# Check for incompatible PATH environment variable before proceeding with installation
|
# Check for incompatible PATH environment variable before proceeding with installation
|
||||||
if [[ ":$PATH:" == *::* || ":$PATH:" == *:.:* ]]; then
|
if [[ ":$PATH:" == *::* || ":$PATH:" == *:.:* ]]; then
|
||||||
echo -e "${FAIL_COLOR}Error: You seem to have the current working directory in your \$PATH environment variable."
|
echo -e "${FAIL_COLOR}Error: You seem to have the current working directory in your \$PATH environment variable."
|
||||||
|
@ -191,11 +231,13 @@ if (( RHEL_VERSION == 8 )) || (( UBUNTU_VERSION == 20 )); then
|
||||||
section_header "Installing glib"
|
section_header "Installing glib"
|
||||||
pip install -U meson # Meson is needed to build glib
|
pip install -U meson # Meson is needed to build glib
|
||||||
cd "$RISCV"
|
cd "$RISCV"
|
||||||
curl --location https://download.gnome.org/sources/glib/2.70/glib-2.70.5.tar.xz | tar xJ
|
wget -nv --retry-connrefused $retry_on_host_error https://download.gnome.org/sources/glib/2.70/glib-2.70.5.tar.xz
|
||||||
|
tar -xJf glib-2.70.5.tar.xz
|
||||||
|
rm -f glib-2.70.5.tar.xz
|
||||||
cd glib-2.70.5
|
cd glib-2.70.5
|
||||||
meson setup _build --prefix="$RISCV"
|
meson setup _build --prefix="$RISCV"
|
||||||
meson compile -C _build
|
meson compile -C _build -j "${NUM_THREADS}" 2>&1 | logger $STATUS; [ "${PIPESTATUS[0]}" == 0 ]
|
||||||
meson install -C _build
|
meson install -C _build 2>&1 | logger $STATUS; [ "${PIPESTATUS[0]}" == 0 ]
|
||||||
cd "$RISCV"
|
cd "$RISCV"
|
||||||
rm -rf glib-2.70.5
|
rm -rf glib-2.70.5
|
||||||
echo -e "${SUCCESS_COLOR}glib successfully installed!${ENDC}"
|
echo -e "${SUCCESS_COLOR}glib successfully installed!${ENDC}"
|
||||||
|
@ -208,11 +250,13 @@ if (( RHEL_VERSION == 8 )); then
|
||||||
if [ ! -e "$RISCV"/include/gmp.h ]; then
|
if [ ! -e "$RISCV"/include/gmp.h ]; then
|
||||||
section_header "Installing gmp"
|
section_header "Installing gmp"
|
||||||
cd "$RISCV"
|
cd "$RISCV"
|
||||||
curl --location https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.xz | tar xJ
|
wget -nv --retry-connrefused $retry_on_host_error https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.xz
|
||||||
|
tar -xJf gmp-6.3.0.tar.xz
|
||||||
|
rm -f gmp-6.3.0.tar.xz
|
||||||
cd gmp-6.3.0
|
cd gmp-6.3.0
|
||||||
./configure --prefix="$RISCV"
|
./configure --prefix="$RISCV"
|
||||||
make -j "${NUM_THREADS}"
|
make -j "${NUM_THREADS}" 2>&1 | logger $STATUS; [ "${PIPESTATUS[0]}" == 0 ]
|
||||||
make install
|
make install 2>&1 | logger $STATUS; [ "${PIPESTATUS[0]}" == 0 ]
|
||||||
cd "$RISCV"
|
cd "$RISCV"
|
||||||
rm -rf gmp-6.3.0
|
rm -rf gmp-6.3.0
|
||||||
echo -e "${SUCCESS_COLOR}gmp successfully installed!${ENDC}"
|
echo -e "${SUCCESS_COLOR}gmp successfully installed!${ENDC}"
|
||||||
|
@ -231,7 +275,7 @@ STATUS="riscv-gnu-toolchain"
|
||||||
cd "$RISCV"
|
cd "$RISCV"
|
||||||
# Temporarily pin riscv-gnu-toolchain to use GCC 13.2.0. GCC 14 does not work with the Q extension.
|
# Temporarily pin riscv-gnu-toolchain to use GCC 13.2.0. GCC 14 does not work with the Q extension.
|
||||||
if git_check "riscv-gnu-toolchain" "https://github.com/riscv/riscv-gnu-toolchain" "$RISCV/riscv-gnu-toolchain/stamps/build-gcc-newlib-stage2"; then
|
if git_check "riscv-gnu-toolchain" "https://github.com/riscv/riscv-gnu-toolchain" "$RISCV/riscv-gnu-toolchain/stamps/build-gcc-newlib-stage2"; then
|
||||||
cd riscv-gnu-toolchain
|
cd "$RISCV"/riscv-gnu-toolchain
|
||||||
git reset --hard && git clean -f && git checkout master && git pull
|
git reset --hard && git clean -f && git checkout master && git pull
|
||||||
./configure --prefix="${RISCV}" --with-multilib-generator="rv32e-ilp32e--;rv32i-ilp32--;rv32im-ilp32--;rv32iac-ilp32--;rv32imac-ilp32--;rv32imafc-ilp32f--;rv32imafdc-ilp32d--;rv64i-lp64--;rv64ic-lp64--;rv64iac-lp64--;rv64imac-lp64--;rv64imafdc-lp64d--;rv64im-lp64--;"
|
./configure --prefix="${RISCV}" --with-multilib-generator="rv32e-ilp32e--;rv32i-ilp32--;rv32im-ilp32--;rv32iac-ilp32--;rv32imac-ilp32--;rv32imafc-ilp32f--;rv32imafdc-ilp32d--;rv64i-lp64--;rv64ic-lp64--;rv64iac-lp64--;rv64imac-lp64--;rv64imafdc-lp64d--;rv64im-lp64--;"
|
||||||
make -j "${NUM_THREADS}" 2>&1 | logger $STATUS; [ "${PIPESTATUS[0]}" == 0 ]
|
make -j "${NUM_THREADS}" 2>&1 | logger $STATUS; [ "${PIPESTATUS[0]}" == 0 ]
|
||||||
|
@ -257,7 +301,7 @@ STATUS="elf2hex"
|
||||||
cd "$RISCV"
|
cd "$RISCV"
|
||||||
export PATH=$RISCV/bin:$PATH
|
export PATH=$RISCV/bin:$PATH
|
||||||
if git_check "elf2hex" "https://github.com/sifive/elf2hex.git" "$RISCV/bin/riscv64-unknown-elf-elf2bin"; then
|
if git_check "elf2hex" "https://github.com/sifive/elf2hex.git" "$RISCV/bin/riscv64-unknown-elf-elf2bin"; then
|
||||||
cd elf2hex
|
cd "$RISCV"/elf2hex
|
||||||
git reset --hard && git clean -f && git checkout master && git pull
|
git reset --hard && git clean -f && git checkout master && git pull
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
./configure --target=riscv64-unknown-elf --prefix="$RISCV"
|
./configure --target=riscv64-unknown-elf --prefix="$RISCV"
|
||||||
|
@ -279,7 +323,7 @@ section_header "Installing/Updating QEMU"
|
||||||
STATUS="qemu"
|
STATUS="qemu"
|
||||||
cd "$RISCV"
|
cd "$RISCV"
|
||||||
if git_check "qemu" "https://github.com/qemu/qemu" "$RISCV/include/qemu-plugin.h"; then
|
if git_check "qemu" "https://github.com/qemu/qemu" "$RISCV/include/qemu-plugin.h"; then
|
||||||
cd qemu
|
cd "$RISCV"/qemu
|
||||||
git reset --hard && git clean -f && git checkout master && git pull --recurse-submodules -j "${NUM_THREADS}"
|
git reset --hard && git clean -f && git checkout master && git pull --recurse-submodules -j "${NUM_THREADS}"
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
./configure --target-list=riscv64-softmmu --prefix="$RISCV"
|
./configure --target-list=riscv64-softmmu --prefix="$RISCV"
|
||||||
|
@ -301,7 +345,7 @@ section_header "Installing/Updating SPIKE"
|
||||||
STATUS="spike"
|
STATUS="spike"
|
||||||
cd "$RISCV"
|
cd "$RISCV"
|
||||||
if git_check "riscv-isa-sim" "https://github.com/riscv-software-src/riscv-isa-sim" "$RISCV/lib/pkgconfig/riscv-riscv.pc"; then
|
if git_check "riscv-isa-sim" "https://github.com/riscv-software-src/riscv-isa-sim" "$RISCV/lib/pkgconfig/riscv-riscv.pc"; then
|
||||||
cd riscv-isa-sim
|
cd "$RISCV"/riscv-isa-sim
|
||||||
git reset --hard && git clean -f && git checkout master && git pull
|
git reset --hard && git clean -f && git checkout master && git pull
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build
|
||||||
|
@ -327,7 +371,7 @@ STATUS="verilator"
|
||||||
cd "$RISCV"
|
cd "$RISCV"
|
||||||
if git_check "verilator" "https://github.com/verilator/verilator" "$RISCV/share/pkgconfig/verilator.pc"; then
|
if git_check "verilator" "https://github.com/verilator/verilator" "$RISCV/share/pkgconfig/verilator.pc"; then
|
||||||
unset VERILATOR_ROOT
|
unset VERILATOR_ROOT
|
||||||
cd verilator
|
cd "$RISCV"/verilator
|
||||||
git reset --hard && git clean -f && git checkout master && git pull
|
git reset --hard && git clean -f && git checkout master && git pull
|
||||||
autoconf
|
autoconf
|
||||||
./configure --prefix="$RISCV"
|
./configure --prefix="$RISCV"
|
||||||
|
@ -352,7 +396,9 @@ section_header "Installing/Updating Sail Compiler"
|
||||||
STATUS="Sail Compiler"
|
STATUS="Sail Compiler"
|
||||||
if [ ! -e "$RISCV"/bin/sail ]; then
|
if [ ! -e "$RISCV"/bin/sail ]; then
|
||||||
cd "$RISCV"
|
cd "$RISCV"
|
||||||
curl --location https://github.com/rems-project/sail/releases/latest/download/sail.tar.gz | tar xvz --directory="$RISCV" --strip-components=1
|
wget -nv --retry-connrefused $retry_on_host_error --output-document=sail.tar.gz https://github.com/rems-project/sail/releases/latest/download/sail.tar.gz
|
||||||
|
tar xz --directory="$RISCV" --strip-components=1 -f sail.tar.gz
|
||||||
|
rm -f sail.tar.gz
|
||||||
echo -e "${SUCCESS_COLOR}Sail Compiler successfully installed/updated!${ENDC}"
|
echo -e "${SUCCESS_COLOR}Sail Compiler successfully installed/updated!${ENDC}"
|
||||||
else
|
else
|
||||||
echo -e "${SUCCESS_COLOR}Sail Compiler already installed.${ENDC}"
|
echo -e "${SUCCESS_COLOR}Sail Compiler already installed.${ENDC}"
|
||||||
|
@ -363,7 +409,7 @@ fi
|
||||||
section_header "Installing/Updating RISC-V Sail Model"
|
section_header "Installing/Updating RISC-V Sail Model"
|
||||||
STATUS="riscv-sail-model"
|
STATUS="riscv-sail-model"
|
||||||
if git_check "sail-riscv" "https://github.com/riscv/sail-riscv.git" "$RISCV/bin/riscv_sim_RV32"; then
|
if git_check "sail-riscv" "https://github.com/riscv/sail-riscv.git" "$RISCV/bin/riscv_sim_RV32"; then
|
||||||
cd sail-riscv
|
cd "$RISCV"/sail-riscv
|
||||||
git reset --hard && git clean -f && git checkout master && git pull
|
git reset --hard && git clean -f && git checkout master && git pull
|
||||||
ARCH=RV64 make -j "${NUM_THREADS}" c_emulator/riscv_sim_RV64 2>&1 | logger $STATUS; [ "${PIPESTATUS[0]}" == 0 ]
|
ARCH=RV64 make -j "${NUM_THREADS}" c_emulator/riscv_sim_RV64 2>&1 | logger $STATUS; [ "${PIPESTATUS[0]}" == 0 ]
|
||||||
ARCH=RV32 make -j "${NUM_THREADS}" c_emulator/riscv_sim_RV32 2>&1 | logger $STATUS; [ "${PIPESTATUS[0]}" == 0 ]
|
ARCH=RV32 make -j "${NUM_THREADS}" c_emulator/riscv_sim_RV32 2>&1 | logger $STATUS; [ "${PIPESTATUS[0]}" == 0 ]
|
||||||
|
@ -386,7 +432,7 @@ STATUS="OSU Skywater 130 cell library"
|
||||||
mkdir -p "$RISCV"/cad/lib
|
mkdir -p "$RISCV"/cad/lib
|
||||||
cd "$RISCV"/cad/lib
|
cd "$RISCV"/cad/lib
|
||||||
if git_check "sky130_osu_sc_t12" "https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t12" "$RISCV/cad/lib/sky130_osu_sc_t12" "main"; then
|
if git_check "sky130_osu_sc_t12" "https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t12" "$RISCV/cad/lib/sky130_osu_sc_t12" "main"; then
|
||||||
cd sky130_osu_sc_t12
|
cd "$RISCV"/sky130_osu_sc_t12
|
||||||
git reset --hard && git clean -f && git checkout main && git pull
|
git reset --hard && git clean -f && git checkout main && git pull
|
||||||
echo -e "${SUCCESS_COLOR}OSU Skywater library successfully installed!${ENDC}"
|
echo -e "${SUCCESS_COLOR}OSU Skywater library successfully installed!${ENDC}"
|
||||||
else
|
else
|
||||||
|
@ -428,8 +474,8 @@ section_header "Downloading Site Setup Script"
|
||||||
STATUS="site-setup scripts"
|
STATUS="site-setup scripts"
|
||||||
cd "$RISCV"
|
cd "$RISCV"
|
||||||
if [ ! -e "${RISCV}"/site-setup.sh ]; then
|
if [ ! -e "${RISCV}"/site-setup.sh ]; then
|
||||||
wget https://raw.githubusercontent.com/openhwgroup/cvw/main/site-setup.sh
|
wget -nv --retry-connrefused $retry_on_host_error https://raw.githubusercontent.com/openhwgroup/cvw/main/site-setup.sh
|
||||||
wget https://raw.githubusercontent.com/openhwgroup/cvw/main/site-setup.csh
|
wget -nv --retry-connrefused $retry_on_host_error https://raw.githubusercontent.com/openhwgroup/cvw/main/site-setup.csh
|
||||||
echo -e "${SUCCESS_COLOR}Site setup script successfully downloaded!${ENDC}"
|
echo -e "${SUCCESS_COLOR}Site setup script successfully downloaded!${ENDC}"
|
||||||
echo -e "${WARNING_COLOR}Make sure to edit the environment variables in $RISCV/site-setup.sh (or .csh) to point to your installation of EDA tools and licensce files.${ENDC}"
|
echo -e "${WARNING_COLOR}Make sure to edit the environment variables in $RISCV/site-setup.sh (or .csh) to point to your installation of EDA tools and licensce files.${ENDC}"
|
||||||
else
|
else
|
||||||
|
|
1
bin/wsim
1
bin/wsim
|
@ -91,6 +91,7 @@ prefix = ""
|
||||||
if (args.lockstep or args.lockstepverbose or args.fcov or args.fcovimp):
|
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"
|
prefix = "IMPERAS_TOOLS=" + WALLY + "/config/"+args.config+"/imperas.ic"
|
||||||
|
# Force Questa to use 64-bit mode, sometimes it defaults to 32-bit even on 64-bit machines
|
||||||
if (args.sim == "questa"):
|
if (args.sim == "questa"):
|
||||||
prefix = "MTI_VCO_MODE=64 " + prefix
|
prefix = "MTI_VCO_MODE=64 " + prefix
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,20 @@
|
||||||
// This file is needed in the config subdirectory for each config supporting coverage.
|
// This file is needed in the config subdirectory for each config supporting coverage.
|
||||||
// It defines which extensions are enabled for that config.
|
// It defines which extensions are enabled for that config.
|
||||||
|
|
||||||
|
// Unprivileged extensions
|
||||||
`include "RV32I_coverage.svh"
|
`include "RV32I_coverage.svh"
|
||||||
`include "RV32M_coverage.svh"
|
`include "RV32M_coverage.svh"
|
||||||
`include "RV32F_coverage.svh"
|
`include "RV32F_coverage.svh"
|
||||||
|
`include "RV32D_coverage.svh"
|
||||||
|
`include "RV32ZfhD_coverage.svh"
|
||||||
`include "RV32Zfh_coverage.svh"
|
`include "RV32Zfh_coverage.svh"
|
||||||
`include "RV32Zicond_coverage.svh"
|
`include "RV32Zicond_coverage.svh"
|
||||||
`include "RV32Zca_coverage.svh"
|
`include "RV32Zca_coverage.svh"
|
||||||
`include "RV32Zcb_coverage.svh"
|
`include "RV32Zcb_coverage.svh"
|
||||||
`include "RV32ZcbM_coverage.svh"
|
`include "RV32ZcbM_coverage.svh"
|
||||||
`include "RV32ZcbZbb_coverage.svh"
|
`include "RV32ZcbZbb_coverage.svh"
|
||||||
|
`include "RV32Zcf_coverage.svh"
|
||||||
|
`include "RV32Zcd_coverage.svh"
|
||||||
|
|
||||||
|
// Privileged extensions
|
||||||
|
`include "ZicsrM_coverage.svh"
|
||||||
|
|
|
@ -59,6 +59,28 @@
|
||||||
#--override cpu/instret_undefined=T
|
#--override cpu/instret_undefined=T
|
||||||
#--override cpu/hpmcounter_undefined=T
|
#--override cpu/hpmcounter_undefined=T
|
||||||
|
|
||||||
|
## context registers not implemented
|
||||||
|
#--override cpu/scontext_undefined=True
|
||||||
|
#--override cpu/mcontext_undefined=True
|
||||||
|
|
||||||
|
# Disable all features that might want mseccfg or CSRs 7a0-7af
|
||||||
|
--override cpu/Smepmp_version=none
|
||||||
|
--override cpu/Smmpm=none
|
||||||
|
#--override cpu/Zicfilp=F
|
||||||
|
--override cpu/trigger_num=0 # disable CSRs 7a0-7a8
|
||||||
|
|
||||||
|
--override no_pseudo_inst=T # For code coverage, don't produce pseudoinstructions
|
||||||
|
|
||||||
|
|
||||||
|
# mcause and scause only have 4 lsbs of code and 1 msb of interrupt flag
|
||||||
|
#--override cpu/ecode_mask=0x8000000F # for RV32
|
||||||
|
--override cpu/ecode_mask=0x800000000000000F # for RV64
|
||||||
|
|
||||||
|
# Debug mode not yet supported
|
||||||
|
--override cpu/debug_mode=none
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--override cpu/reset_address=0x80000000
|
--override cpu/reset_address=0x80000000
|
||||||
|
|
||||||
--override cpu/unaligned=F # Zicclsm (should be true)
|
--override cpu/unaligned=F # Zicclsm (should be true)
|
||||||
|
|
|
@ -5,18 +5,25 @@
|
||||||
// This file is needed in the config subdirectory for each config supporting coverage.
|
// This file is needed in the config subdirectory for each config supporting coverage.
|
||||||
// It defines which extensions are enabled for that config.
|
// It defines which extensions are enabled for that config.
|
||||||
|
|
||||||
|
// Unprivileged extensions
|
||||||
`include "RV64I_coverage.svh"
|
`include "RV64I_coverage.svh"
|
||||||
`include "RV64M_coverage.svh"
|
`include "RV64M_coverage.svh"
|
||||||
`include "RV64F_coverage.svh"
|
`include "RV64F_coverage.svh"
|
||||||
|
`include "RV64D_coverage.svh"
|
||||||
|
`include "RV64ZfhD_coverage.svh"
|
||||||
`include "RV64Zfh_coverage.svh"
|
`include "RV64Zfh_coverage.svh"
|
||||||
`include "RV64VM_coverage.svh"
|
|
||||||
`include "RV64VM_PMP_coverage.svh"
|
|
||||||
`include "RV64CBO_VM_coverage.svh"
|
|
||||||
`include "RV64CBO_PMP_coverage.svh"
|
|
||||||
`include "RV64Zicbom_coverage.svh"
|
|
||||||
`include "RV64Zicond_coverage.svh"
|
`include "RV64Zicond_coverage.svh"
|
||||||
`include "RV64Zca_coverage.svh"
|
`include "RV64Zca_coverage.svh"
|
||||||
`include "RV64Zcb_coverage.svh"
|
`include "RV64Zcb_coverage.svh"
|
||||||
`include "RV64ZcbM_coverage.svh"
|
`include "RV64ZcbM_coverage.svh"
|
||||||
`include "RV64ZcbZbb_coverage.svh"
|
`include "RV64ZcbZbb_coverage.svh"
|
||||||
`include "RV64ZcbZba_coverage.svh"
|
`include "RV64ZcbZba_coverage.svh"
|
||||||
|
`include "RV64Zcd_coverage.svh"
|
||||||
|
|
||||||
|
// Privileged extensions
|
||||||
|
`include "RV64VM_coverage.svh"
|
||||||
|
`include "ZicsrM_coverage.svh"
|
||||||
|
// `include "RV64VM_PMP_coverage.svh"
|
||||||
|
// `include "RV64CBO_VM_coverage.svh"
|
||||||
|
// `include "RV64CBO_PMP_coverage.svh"
|
||||||
|
// `include "RV64Zicbom_coverage.svh"
|
||||||
|
|
|
@ -57,15 +57,32 @@
|
||||||
#--override cpu/instret_undefined=T
|
#--override cpu/instret_undefined=T
|
||||||
#--override cpu/hpmcounter_undefined=T
|
#--override cpu/hpmcounter_undefined=T
|
||||||
|
|
||||||
--override cpu/scontext_undefined=T
|
# context registers not implemented
|
||||||
--override cpu/mcontext_undefined=T
|
#--override cpu/scontext_undefined=True
|
||||||
|
#--override cpu/mcontext_undefined=True
|
||||||
|
|
||||||
|
# Disable all features that might want mseccfg or CSRs 7a0-7af
|
||||||
|
--override cpu/Smepmp_version=none
|
||||||
|
--override cpu/Smmpm=none
|
||||||
|
#--override cpu/Zicfilp=F
|
||||||
|
--override cpu/trigger_num=0 # disable CSRs 7a0-7a8
|
||||||
|
|
||||||
|
# For code coverage, don't produce pseudoinstructions
|
||||||
|
--override no_pseudo_inst=T
|
||||||
|
|
||||||
|
# nonratified mnosie register not implemented
|
||||||
--override cpu/mnoise_undefined=T
|
--override cpu/mnoise_undefined=T
|
||||||
# *** how to override other undefined registers: seed, mphmevent, mseccfg, debugger registers
|
|
||||||
#--override cpu/seed_undefined=T
|
# mcause and scause only have 4 lsbs of code and 1 msb of interrupt flag
|
||||||
#--override mhpmevent3_undefined=T
|
#--override cpu/ecode_mask=0x8000000F # for RV32
|
||||||
#--override cpu/mseccfg_undefined=T
|
--override cpu/ecode_mask=0x800000000000000F # for RV64
|
||||||
#--override cpu/tselect_undefined=T
|
|
||||||
#--override cpu/tdata1_undefined=T
|
# Debug mode not yet supported
|
||||||
|
--override cpu/debug_mode=none
|
||||||
|
|
||||||
|
# Zkr entropy source and seed register not supported.
|
||||||
|
--override cpu/Zkr=F
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--override cpu/reset_address=0x80000000
|
--override cpu/reset_address=0x80000000
|
||||||
|
|
|
@ -27,9 +27,16 @@ BINARIES := fw_jump.elf vmlinux busybox
|
||||||
OBJDUMPS := $(foreach name, $(BINARIES), $(basename $(name) .elf))
|
OBJDUMPS := $(foreach name, $(BINARIES), $(basename $(name) .elf))
|
||||||
OBJDUMPS := $(foreach name, $(OBJDUMPS), $(DIS)/$(name).objdump)
|
OBJDUMPS := $(foreach name, $(OBJDUMPS), $(DIS)/$(name).objdump)
|
||||||
|
|
||||||
.PHONY: all generate disassemble install clean cleanDTB cleanDriver check_write_permissions
|
.PHONY: all generate disassemble install clean cleanDTB check_write_permissions check_environment
|
||||||
|
|
||||||
all: check_write_permissions clean download Image disassemble install dumptvs
|
all: check_environment check_write_permissions clean download Image disassemble install dumptvs
|
||||||
|
|
||||||
|
check_environment: $(RISCV)
|
||||||
|
ifeq ($(findstring :$(RISCV)/lib:,:$(LD_LIBRARY_PATH):),)
|
||||||
|
@(echo "ERROR: Your environment variables are not set correctly." >&2 \
|
||||||
|
&& echo "Make sure to source setup.sh or install buildroot using the wally-tool-chain-install.sh script." >&2 \
|
||||||
|
&& exit 1)
|
||||||
|
endif
|
||||||
|
|
||||||
check_write_permissions:
|
check_write_permissions:
|
||||||
ifeq ($(SUDO), sudo)
|
ifeq ($(SUDO), sudo)
|
||||||
|
@ -41,17 +48,17 @@ endif
|
||||||
&& exit 1)
|
&& exit 1)
|
||||||
@$(SUDO) rm -r $(RISCV)/.test
|
@$(SUDO) rm -r $(RISCV)/.test
|
||||||
|
|
||||||
Image:
|
Image: check_environment
|
||||||
bash -c "unset LD_LIBRARY_PATH; $(MAKE) -C $(BUILDROOT)"
|
bash -c "unset LD_LIBRARY_PATH; $(MAKE) -C $(BUILDROOT)"
|
||||||
$(MAKE) generate
|
$(MAKE) generate
|
||||||
@echo "Buildroot Image successfully generated."
|
@echo "Buildroot Image successfully generated."
|
||||||
|
|
||||||
install: check_write_permissions
|
install: check_write_permissions check_environment
|
||||||
$(SUDO) rm -rf $(RISCV)/$(BUILDROOT)
|
$(SUDO) rm -rf $(RISCV)/$(BUILDROOT)
|
||||||
$(SUDO) mv $(BUILDROOT) $(RISCV)/$(BUILDROOT)
|
$(SUDO) mv $(BUILDROOT) $(RISCV)/$(BUILDROOT)
|
||||||
@echo "Buildroot successfully installed."
|
@echo "Buildroot successfully installed."
|
||||||
|
|
||||||
dumptvs: check_write_permissions
|
dumptvs: check_write_permissions check_environment
|
||||||
$(SUDO) mkdir -p $(RISCV)/linux-testvectors
|
$(SUDO) mkdir -p $(RISCV)/linux-testvectors
|
||||||
cd testvector-generation; ./genInitMem.sh
|
cd testvector-generation; ./genInitMem.sh
|
||||||
@echo "Testvectors successfully generated."
|
@echo "Testvectors successfully generated."
|
||||||
|
@ -70,7 +77,7 @@ $(RISCV):
|
||||||
@ echo "and sourced setup.sh"
|
@ echo "and sourced setup.sh"
|
||||||
|
|
||||||
# Disassembly rules ---------------------------------------------------
|
# Disassembly rules ---------------------------------------------------
|
||||||
disassemble:
|
disassemble: check_environment
|
||||||
rm -rf $(BUILDROOT)/output/images/disassembly
|
rm -rf $(BUILDROOT)/output/images/disassembly
|
||||||
find $(BUILDROOT)/output/build/linux-* -maxdepth 1 -name "vmlinux" | xargs cp -t $(BUILDROOT)/output/images/
|
find $(BUILDROOT)/output/build/linux-* -maxdepth 1 -name "vmlinux" | xargs cp -t $(BUILDROOT)/output/images/
|
||||||
mkdir -p $(DIS)
|
mkdir -p $(DIS)
|
||||||
|
@ -114,9 +121,6 @@ $(BUILDROOT):
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
# ---------------------------------------------------------------------
|
||||||
|
|
||||||
cleanDriver:
|
|
||||||
rm -f $(DRIVER)
|
|
||||||
|
|
||||||
cleanDTB:
|
cleanDTB:
|
||||||
rm -f $(IMAGES)/*.dtb
|
rm -f $(IMAGES)/*.dtb
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,7 @@ if {$DEBUG > 0} {
|
||||||
# suppress spurious warnngs about
|
# suppress spurious warnngs about
|
||||||
# "Extra checking for conflicts with always_comb done at vopt time"
|
# "Extra checking for conflicts with always_comb done at vopt time"
|
||||||
# because vsim will run vopt
|
# because vsim will run vopt
|
||||||
set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared +incdir+${FCRVVI} +incdir+${FCRVVI}/rv32 +incdir+${FCRVVI}/rv64 +incdir+${FCRVVI}/rv64_priv +incdir+${FCRVVI}/common"
|
set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared +incdir+${FCRVVI} +incdir+${FCRVVI}/rv32 +incdir+${FCRVVI}/rv64 +incdir+${FCRVVI}/rv64_priv +incdir+${FCRVVI}/priv +incdir+${FCRVVI}/common +incdir+${FCRVVI}"
|
||||||
set SOURCES "${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv"
|
set SOURCES "${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv"
|
||||||
vlog -permissive -lint -work ${WKDIR} {*}${INC_DIRS} {*}${FCvlog} {*}${FCdefineCOVER_EXTS} {*}${lockstepvlog} {*}${SOURCES} -suppress 2282,2583,7053,7063,2596,13286
|
vlog -permissive -lint -work ${WKDIR} {*}${INC_DIRS} {*}${FCvlog} {*}${FCdefineCOVER_EXTS} {*}${lockstepvlog} {*}${SOURCES} -suppress 2282,2583,7053,7063,2596,13286
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
// See RISC-V Privileged Mode Specification 20190608 3.1.10-11
|
// See RISC-V Privileged Mode Specification 20190608 3.1.10-11
|
||||||
//
|
//
|
||||||
// Documentation: RISC-V System on Chip Design
|
// Documentation: RISC-V System on Chip Design
|
||||||
// MHPMEVENT is not supported
|
|
||||||
//
|
//
|
||||||
// A component of the CORE-V-WALLY configurable RISC-V project.
|
// A component of the CORE-V-WALLY configurable RISC-V project.
|
||||||
// https://github.com/openhwgroup/cvw
|
// https://github.com/openhwgroup/cvw
|
||||||
|
@ -66,7 +65,8 @@ module csrc import cvw::*; #(parameter cvw_t P) (
|
||||||
localparam MTIME = 12'hB01; // this is a memory-mapped register; no such CSR exists, and access should faul;
|
localparam MTIME = 12'hB01; // this is a memory-mapped register; no such CSR exists, and access should faul;
|
||||||
localparam MHPMCOUNTERHBASE = 12'hB80;
|
localparam MHPMCOUNTERHBASE = 12'hB80;
|
||||||
localparam MTIMEH = 12'hB81; // this is a memory-mapped register; no such CSR exists, and access should fault
|
localparam MTIMEH = 12'hB81; // this is a memory-mapped register; no such CSR exists, and access should fault
|
||||||
localparam MHPMEVENTBASE = 12'h320;
|
localparam MHPMEVENTBASE = 12'h323;
|
||||||
|
localparam MHPMEVENTLAST = 12'h33F;
|
||||||
localparam HPMCOUNTERBASE = 12'hC00;
|
localparam HPMCOUNTERBASE = 12'hC00;
|
||||||
localparam HPMCOUNTERHBASE = 12'hC80;
|
localparam HPMCOUNTERHBASE = 12'hC80;
|
||||||
localparam TIME = 12'hC01;
|
localparam TIME = 12'hC01;
|
||||||
|
@ -156,6 +156,9 @@ module csrc import cvw::*; #(parameter cvw_t P) (
|
||||||
if (PrivilegeModeW == P.M_MODE |
|
if (PrivilegeModeW == P.M_MODE |
|
||||||
MCOUNTEREN_REGW[CounterNumM] & (!P.S_SUPPORTED | PrivilegeModeW == P.S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin
|
MCOUNTEREN_REGW[CounterNumM] & (!P.S_SUPPORTED | PrivilegeModeW == P.S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin
|
||||||
IllegalCSRCAccessM = 1'b0;
|
IllegalCSRCAccessM = 1'b0;
|
||||||
|
if (CSRAdrM >= MHPMEVENTBASE & CSRAdrM <= MHPMEVENTLAST) begin
|
||||||
|
CSRCReadValM = '0; // mphmevent[3:31] tied to read-only zero
|
||||||
|
end else begin
|
||||||
if (P.XLEN==64) begin // 64-bit counter reads
|
if (P.XLEN==64) begin // 64-bit counter reads
|
||||||
// Veri lator doesn't realize this only occurs for XLEN=64
|
// Veri lator doesn't realize this only occurs for XLEN=64
|
||||||
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
||||||
|
@ -188,6 +191,7 @@ module csrc import cvw::*; #(parameter cvw_t P) (
|
||||||
IllegalCSRCAccessM = 1'b1; // requested CSR doesn't exist
|
IllegalCSRCAccessM = 1'b1; // requested CSR doesn't exist
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end else begin
|
end else begin
|
||||||
CSRCReadValM = '0;
|
CSRCReadValM = '0;
|
||||||
IllegalCSRCAccessM = 1'b1; // no privileges for this csr
|
IllegalCSRCAccessM = 1'b1; // no privileges for this csr
|
||||||
|
|
|
@ -128,10 +128,13 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
||||||
else
|
else
|
||||||
assign STimerInt = 1'b0;
|
assign STimerInt = 1'b0;
|
||||||
|
|
||||||
|
logic [1:0] LegalizedCBIE;
|
||||||
|
assign LegalizedCBIE = CSRWriteValM[5:4] == 2'b10 ? SENVCFG_REGW[5:4] : CSRWriteValM[5:4]; // Assume WARL for reserved CBIE = 10, keeps old value
|
||||||
assign SENVCFG_WriteValM = {
|
assign SENVCFG_WriteValM = {
|
||||||
{(P.XLEN-8){1'b0}},
|
{(P.XLEN-8){1'b0}},
|
||||||
CSRWriteValM[7] & P.ZICBOZ_SUPPORTED,
|
CSRWriteValM[7] & P.ZICBOZ_SUPPORTED,
|
||||||
CSRWriteValM[6:4] & {3{P.ZICBOM_SUPPORTED}},
|
CSRWriteValM[6] & P.ZICBOM_SUPPORTED,
|
||||||
|
LegalizedCBIE & {2{P.ZICBOM_SUPPORTED}},
|
||||||
3'b0,
|
3'b0,
|
||||||
CSRWriteValM[0] & P.VIRTMEM_SUPPORTED
|
CSRWriteValM[0] & P.VIRTMEM_SUPPORTED
|
||||||
};
|
};
|
||||||
|
|
|
@ -234,9 +234,9 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
||||||
// SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1))
|
// SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1))
|
||||||
// Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv
|
// Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv
|
||||||
// Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase
|
// Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase
|
||||||
// When SckDiv is 0, count doesn't work and SCLKenable is simply PCLK
|
// When SckDiv is 0, count doesn't work and SCLKenable is simply PCLK *** dh 10/26/24: this logic is seriously broken. SCLK is not scaled to PCLK/(2*(SckDiv + 1)). SCLKenableEarly doesn't work right for SckDiv=0
|
||||||
assign ZeroDiv = ~|(SckDiv[10:0]);
|
assign ZeroDiv = ~|(SckDiv[10:0]);
|
||||||
assign SCLKenable = ZeroDiv ? PCLK : (DivCounter == SckDiv);
|
assign SCLKenable = ZeroDiv ? 1 : (DivCounter == SckDiv);
|
||||||
assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
|
assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
|
||||||
always_ff @(posedge PCLK)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) DivCounter <= '0;
|
if (~PRESETn) DivCounter <= '0;
|
||||||
|
|
348
src/uncore/spi_controller.sv
Normal file
348
src/uncore/spi_controller.sv
Normal 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
|
|
@ -540,7 +540,6 @@ module testbench;
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (LoadMem) begin
|
if (LoadMem) begin
|
||||||
$readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.ram.RAM);
|
$readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.ram.RAM);
|
||||||
$display("Read memfile %s", memfilename);
|
|
||||||
end
|
end
|
||||||
if (CopyRAM) begin
|
if (CopyRAM) begin
|
||||||
LogXLEN = (1 + P.XLEN/32); // 2 for rv32 and 3 for rv64
|
LogXLEN = (1 + P.XLEN/32); // 2 for rv32 and 3 for rv64
|
||||||
|
|
|
@ -28,6 +28,12 @@
|
||||||
// The PMP tests are sensitive to the exact addresses in this code, so unfortunately
|
// The PMP tests are sensitive to the exact addresses in this code, so unfortunately
|
||||||
// modifying anything breaks those tests.
|
// modifying anything breaks those tests.
|
||||||
|
|
||||||
|
// Provides simple firmware services through ecall. Place argument in a0 and issue ecall:
|
||||||
|
// 0: change to user mode
|
||||||
|
// 1: change to supervisor mode
|
||||||
|
// 3: change to machine mode
|
||||||
|
// 4: terminate program
|
||||||
|
|
||||||
.section .text.init
|
.section .text.init
|
||||||
.global rvtest_entry_point
|
.global rvtest_entry_point
|
||||||
|
|
||||||
|
|
|
@ -32,59 +32,59 @@
|
||||||
|
|
||||||
00000003
|
00000003
|
||||||
|
|
||||||
00000074
|
00000074 # spi_burst_send
|
||||||
|
|
||||||
00000063
|
00000063 # spi_burst_send
|
||||||
|
|
||||||
00000052
|
00000052 # spi_burst_send
|
||||||
|
|
||||||
00000041
|
00000041 # spi_burst_send
|
||||||
|
|
||||||
000000A1
|
000000A1 # spi_burst_send
|
||||||
|
|
||||||
00000003
|
00000003
|
||||||
|
|
||||||
000000B2
|
000000B2 # spi_burst_send
|
||||||
|
|
||||||
00000001
|
00000001
|
||||||
|
|
||||||
000000C3
|
000000C3 # spi_burst_send
|
||||||
|
|
||||||
000000D4
|
000000D4 # spi_burst_send
|
||||||
|
|
||||||
00000003
|
00000003
|
||||||
|
|
||||||
000000A4
|
000000A4 # tx_data write test
|
||||||
|
|
||||||
00000001
|
00000001
|
||||||
|
|
||||||
000000B4
|
000000B4 # tx_data write test
|
||||||
|
|
||||||
000000A5
|
000000A5 # spi_burst_send
|
||||||
|
|
||||||
000000B5
|
000000B5 # spi_burst_send
|
||||||
|
|
||||||
000000C5
|
000000C5 # spi_burst_send
|
||||||
|
|
||||||
000000D5
|
000000D5 # spi_burst_send
|
||||||
|
|
||||||
000000A7
|
000000A7 # spi_burst_send
|
||||||
|
|
||||||
000000B7
|
000000B7 # spi_burst_send
|
||||||
|
|
||||||
000000C7
|
000000C7 # spi_burst_send
|
||||||
|
|
||||||
00000002
|
00000002
|
||||||
|
|
||||||
000000D7
|
000000D7 # spi_burst_send
|
||||||
|
|
||||||
00000000
|
00000000
|
||||||
|
|
||||||
00000011 #basic read write
|
00000011 #basic read write
|
||||||
|
|
||||||
000000FF
|
000000FF # first test sck_div
|
||||||
|
|
||||||
000000AE
|
000000AE # min sck_div first spi_burst_send
|
||||||
|
|
||||||
000000AD
|
000000AD
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue