mirror of
https://github.com/vortexgpgpu/vortex.git
synced 2025-06-28 01:28:42 -04:00
adding support for top-module parameter replacement during synthesis tests
This commit is contained in:
parent
b8ccff7ade
commit
9e54ccde6d
3 changed files with 135 additions and 21 deletions
|
@ -18,45 +18,56 @@ includes=()
|
||||||
externs=()
|
externs=()
|
||||||
|
|
||||||
output_file=""
|
output_file=""
|
||||||
global_file=""
|
define_header=""
|
||||||
|
top_module=""
|
||||||
copy_folder=""
|
copy_folder=""
|
||||||
prepropressor=0
|
prepropressor=0
|
||||||
|
|
||||||
defines_str=""
|
defines_str=""
|
||||||
|
params_str=""
|
||||||
includes_str=""
|
includes_str=""
|
||||||
|
|
||||||
|
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||||
|
|
||||||
# parse command arguments
|
# parse command arguments
|
||||||
while getopts D:I:J:O:G:C:Ph flag
|
while getopts D:G:T:I:J:O:H:C:Ph flag
|
||||||
do
|
do
|
||||||
case "${flag}" in
|
case "${flag}" in
|
||||||
D) defines+=( ${OPTARG} )
|
D) defines+=( ${OPTARG} )
|
||||||
defines_str+="-D${OPTARG} "
|
defines_str+="-D${OPTARG} "
|
||||||
;;
|
;;
|
||||||
|
G) params_str+="-G${OPTARG} "
|
||||||
|
;;
|
||||||
|
T) top_module=( ${OPTARG} )
|
||||||
|
;;
|
||||||
I) includes+=( ${OPTARG} )
|
I) includes+=( ${OPTARG} )
|
||||||
includes_str+="-I${OPTARG} "
|
includes_str+="-I${OPTARG} "
|
||||||
;;
|
;;
|
||||||
J) externs+=( ${OPTARG} )
|
J) externs+=( ${OPTARG} )
|
||||||
includes_str+="-I${OPTARG} "
|
includes_str+="-I${OPTARG} "
|
||||||
;;
|
;;
|
||||||
O) output_file=( ${OPTARG} );;
|
O) output_file=( ${OPTARG} )
|
||||||
G) global_file=( ${OPTARG} );;
|
;;
|
||||||
C) copy_folder=( ${OPTARG} );;
|
H) define_header=( ${OPTARG} )
|
||||||
P) prepropressor=1;;
|
;;
|
||||||
h) echo "Usage: [-D<macro>] [-I<include-path>] [-J<external-path>] [-O<output-file>] [-C<dest-folder>: copy to] [-G<global_header>] [-P: macro prepropressing] [-h help]"
|
C) copy_folder=( ${OPTARG} )
|
||||||
|
;;
|
||||||
|
P) prepropressor=1
|
||||||
|
;;
|
||||||
|
h) echo "Usage: [-D<macro>] [-G<param>=<value>] [-T<top-module>] [-I<include-path>] [-J<external-path>] [-O<output-file>] [-C<dest-folder>: copy to] [-H<define_header>] [-P: macro prepropressing] [-h help]"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
\?)
|
\?) echo "Invalid option: -$OPTARG" 1>&2
|
||||||
echo "Invalid option: -$OPTARG" 1>&2
|
exit 1
|
||||||
exit 1
|
;;
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$global_file" != "" ]; then
|
if [ "$define_header" != "" ]; then
|
||||||
directory=$(dirname "$global_file")
|
directory=$(dirname "$define_header")
|
||||||
mkdir -p "$directory"
|
mkdir -p "$directory"
|
||||||
{
|
{
|
||||||
# dump defines into a global header
|
# dump defines into a header file
|
||||||
for value in ${defines[@]}; do
|
for value in ${defines[@]}; do
|
||||||
arrNV=(${value//=/ })
|
arrNV=(${value//=/ })
|
||||||
if (( ${#arrNV[@]} > 1 ));
|
if (( ${#arrNV[@]} > 1 ));
|
||||||
|
@ -66,7 +77,7 @@ if [ "$global_file" != "" ]; then
|
||||||
echo "\`define $value"
|
echo "\`define $value"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
} > $global_file
|
} > $define_header
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$copy_folder" != "" ]; then
|
if [ "$copy_folder" != "" ]; then
|
||||||
|
@ -74,9 +85,16 @@ if [ "$copy_folder" != "" ]; then
|
||||||
mkdir -p $copy_folder
|
mkdir -p $copy_folder
|
||||||
for dir in ${includes[@]}; do
|
for dir in ${includes[@]}; do
|
||||||
find "$dir" -maxdepth 1 -type f | while read -r file; do
|
find "$dir" -maxdepth 1 -type f | while read -r file; do
|
||||||
ext="${file##*.}"
|
file_ext="${file##*.}"
|
||||||
if [ $prepropressor != 0 ] && { [ "$ext" == "v" ] || [ "$ext" == "sv" ]; }; then
|
file_name=$(basename -- $file)
|
||||||
verilator $defines_str $includes_str -E -P $file > $copy_folder/$(basename -- $file)
|
if [ $prepropressor != 0 ] && { [ "$file_ext" == "v" ] || [ "$file_ext" == "sv" ]; }; then
|
||||||
|
if [[ -n "$params_str" && $file_name == "$top_module."* ]]; then
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
$script_dir/repl_params.py $params_str -T$top_module $file > $temp_file
|
||||||
|
verilator $defines_str $includes_str -E -P $temp_file > $copy_folder/$file_name
|
||||||
|
else
|
||||||
|
verilator $defines_str $includes_str -E -P $file > $copy_folder/$file_name
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
cp $file $copy_folder
|
cp $file $copy_folder
|
||||||
fi
|
fi
|
||||||
|
@ -86,7 +104,7 @@ fi
|
||||||
|
|
||||||
if [ "$output_file" != "" ]; then
|
if [ "$output_file" != "" ]; then
|
||||||
{
|
{
|
||||||
if [ "$global_file" == "" ]; then
|
if [ "$define_header" == "" ]; then
|
||||||
# dump defines
|
# dump defines
|
||||||
for value in ${defines[@]}; do
|
for value in ${defines[@]}; do
|
||||||
echo "+define+$value"
|
echo "+define+$value"
|
||||||
|
|
96
hw/scripts/repl_params.py
Executable file
96
hw/scripts/repl_params.py
Executable file
|
@ -0,0 +1,96 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright © 2019-2023
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def read_file_contents(filename):
|
||||||
|
with open(filename, 'r') as file:
|
||||||
|
return file.read()
|
||||||
|
|
||||||
|
def write_to_console(output):
|
||||||
|
print(output, end='')
|
||||||
|
|
||||||
|
def check_module_and_parameter_existence(file_content, top_module, params):
|
||||||
|
# Check if the module exists
|
||||||
|
module_exists_pattern = re.compile(rf'\bmodule\s+{top_module}\b', re.DOTALL)
|
||||||
|
if not re.search(module_exists_pattern, file_content):
|
||||||
|
print(f"Error: Top module '{top_module}' not found in file '{filename}'.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Check if parameters exist
|
||||||
|
for param in params.keys():
|
||||||
|
param_exists_pattern = re.compile(rf'\bparameter\s+((?:\[\s*\d*\s*:\s*\d*\s*\]\s*)?(\w+\s+)?){param}\s*(\[\s*\])?\s*=', re.DOTALL)
|
||||||
|
if not re.search(param_exists_pattern, file_content):
|
||||||
|
print(f"Error: Parameter '{param}' not found in module '{top_module}'.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def replace_parameter(file_content, top_module, param, value):
|
||||||
|
# Define a pattern to locate the specified top module's parameter section
|
||||||
|
module_header_pattern = re.compile(rf'(module\s+{top_module}\s*.*?\(\s*)(.*?)(\)\s*;)', re.DOTALL)
|
||||||
|
param_declaration_pattern = re.compile(rf'(\bparameter\b\s+(?:\w+\s+)?{param}\s*=\s*)([^,;]+)', re.DOTALL)
|
||||||
|
|
||||||
|
def parameter_replacer(match):
|
||||||
|
before_params, params_section, after_params = match.groups()
|
||||||
|
# Check if the specific parameter is found within the parameter section
|
||||||
|
if re.search(param_declaration_pattern, params_section):
|
||||||
|
# Replace the parameter value, avoiding f-string for backreference
|
||||||
|
new_params_section = re.sub(param_declaration_pattern, lambda m: m.group(1) + value, params_section)
|
||||||
|
return f'{before_params}{new_params_section}{after_params}'
|
||||||
|
else:
|
||||||
|
return match.group(0) # Return original content if parameter not found
|
||||||
|
|
||||||
|
# Apply the replacement within the specified top module
|
||||||
|
modified_content, num_replacements = re.subn(module_header_pattern, parameter_replacer, file_content)
|
||||||
|
|
||||||
|
if num_replacements == 0:
|
||||||
|
print(f"Warning: Top module '{top_module}' or parameter '{param}' not found. No replacement made.")
|
||||||
|
|
||||||
|
return modified_content
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = sys.argv[1:]
|
||||||
|
filename = ''
|
||||||
|
top_module = ''
|
||||||
|
params = {}
|
||||||
|
|
||||||
|
for i, arg in enumerate(args):
|
||||||
|
if arg.startswith('-G'):
|
||||||
|
param, value = arg[2:].split('=')
|
||||||
|
params[param] = value
|
||||||
|
elif arg.startswith('-T'):
|
||||||
|
top_module = arg[2:]
|
||||||
|
else:
|
||||||
|
filename = arg
|
||||||
|
|
||||||
|
if not top_module:
|
||||||
|
print("Error: Top module not specified.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not filename:
|
||||||
|
print("Error: Verilog file name not specified.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
file_content = read_file_contents(filename)
|
||||||
|
|
||||||
|
check_module_and_parameter_existence(file_content, top_module, params)
|
||||||
|
|
||||||
|
for param, value in params.items():
|
||||||
|
file_content = replace_parameter(file_content, top_module, param, value)
|
||||||
|
|
||||||
|
write_to_console(file_content)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -34,7 +34,7 @@ all: gen-sources $(PROJECT).sta.rpt $(PROJECT).pow.rpt
|
||||||
gen-sources: src
|
gen-sources: src
|
||||||
src:
|
src:
|
||||||
mkdir -p src
|
mkdir -p src
|
||||||
$(SCRIPT_DIR)/gen_sources.sh $(CONFIGS) $(RTL_INCLUDE) -P -Csrc
|
$(SCRIPT_DIR)/gen_sources.sh $(CONFIGS) $(RTL_INCLUDE) -T$(TOP_LEVEL_ENTITY) -P -Csrc
|
||||||
|
|
||||||
syn: $(PROJECT).syn.rpt
|
syn: $(PROJECT).syn.rpt
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue