-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial tmake cmake function file added. * Useless message print cleaned. * Cleaned debugging code. * Added copy cmake function. * list-files without args.out creates a circular deps problem. * copy func updated. * duplicated tmake supported removed. * TOP verilog files parsing commented for now. * rtl copy cmake func typo fixed. * Save commit. * added tmrg verilog elaborate to keep only needed files. * Parsing rtl files with TMRG VerilogParser class to keep only necessary files. * Removed verbose SV2V print * Added cmake add_test for cocotb tb. * executable first to enable add_test for cocotb modules. * Passing each ENV var for each add_test() for correct syntax.' * Added regex to detect test failure. * Added more failure detection for cocotb tests. * Removed useless else confition. --------- Co-authored-by: Benoit Denkinger <[email protected]> Co-authored-by: Marco Andorno <[email protected]>
- Loading branch information
1 parent
b2a0d94
commit 927c844
Showing
8 changed files
with
271 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
function(add_cocotb_iverilog_tests IP_LIB DIRECTORY) | ||
include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../utils/subdirectory_search.cmake") | ||
include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../utils/colours.cmake") | ||
|
||
SUBDIRLIST(TEST_SUBDIRS ${DIRECTORY}) | ||
|
||
# Assume the IP library is the latest one provided if full name is not given | ||
ip_assume_last(IP_LIB ${IP_LIB}) | ||
|
||
unset(msg) | ||
list(APPEND _msg "-------------------------------------------------------------------------\n") | ||
string(REPLACE "__" "::" ALIAS_NAME ${IP_LIB}) | ||
list(APPEND _msg "------------ Adding tests for IP_LIB: \"${ALIAS_NAME}\"\n") | ||
list(APPEND _msg "Added tests:\n") | ||
|
||
enable_testing() | ||
foreach(test ${TEST_SUBDIRS}) | ||
add_subdirectory("${DIRECTORY}/${test}" "${test}_test") | ||
if(SOCMAKE_DONT_ADD_TEST) | ||
unset(SOCMAKE_DONT_ADD_TEST) | ||
continue() | ||
endif() | ||
foreach(cocotb_test ${COCOTB_TB_NAME}) | ||
list(APPEND _msg " ${cocotb_test}: ${${cocotb_test}_DESCRIPTION}\n") | ||
list(APPEND test_list ${cocotb_test}) | ||
string(TOUPPER ${cocotb_test} COCOTB_TEST_PROP) | ||
get_target_property(COCOTB_IVERILOG_TEST_CMD ${IP_LIB} COCOTB_IVERILOG_${COCOTB_TEST_PROP}_CMD) | ||
get_target_property(COCOTB_IVERILOG_TEST_ENV ${IP_LIB} COCOTB_IVERILOG_${COCOTB_TEST_PROP}_ENV) | ||
add_test( | ||
NAME ${cocotb_test} | ||
COMMAND ${COCOTB_IVERILOG_TEST_CMD} | ||
) | ||
# The ENVIRONMENT property expect the variables in a specific format so its safer to | ||
# set them one by one and let the function do the correct formating | ||
foreach(prop ${COCOTB_IVERILOG_TEST_ENV}) | ||
set_property(TEST ${cocotb_test} APPEND PROPERTY ENVIRONMENT ${prop}) | ||
endforeach() | ||
# vvp (iverilog) always returns 0 (pass) so check the output to detect a failure | ||
# Also detect if python env is not correct otherwise we have a silent failure | ||
# In general Error is not expected | ||
set_property(TEST ${cocotb_test} PROPERTY | ||
FAIL_REGULAR_EXPRESSION "[^a-z]FAIL;Error;ERROR;error" | ||
) | ||
endforeach() | ||
endforeach() | ||
|
||
include(ProcessorCount) | ||
ProcessorCount(NPROC) | ||
add_custom_target(check | ||
COMMAND ${CMAKE_CTEST_COMMAND} -j${NPROC} | ||
DEPENDS ${test_list} ${IP_LIB} | ||
) | ||
|
||
list(APPEND _msg "\nTo run ctest on all of the tests run:\n") | ||
list(APPEND _msg " make check\n") | ||
list(APPEND _msg "To run any of the added tests execute:\n") | ||
list(APPEND _msg " make run_<test_name>\n") | ||
list(APPEND _msg "-------------------------------------------------------------------------") | ||
string(REPLACE ";" "" _msg "${_msg}") | ||
msg("${_msg}" Blue) | ||
endfunction() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
function(copy_rtl_files IP_LIB) | ||
cmake_parse_arguments(ARG "" "OUTDIR;TOP_MODULE" "" ${ARGN}) | ||
if(ARG_UNPARSED_ARGUMENTS) | ||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}") | ||
endif() | ||
|
||
include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../hwip.cmake") | ||
include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../find_python.cmake") | ||
|
||
ip_assume_last(IP_LIB ${IP_LIB}) | ||
|
||
if(NOT ARG_OUTDIR) | ||
set(OUTDIR ${CMAKE_BINARY_DIR}/ip_sources) | ||
else() | ||
set(OUTDIR ${ARG_OUTDIR}) | ||
endif() | ||
|
||
# Check if a top module is provided. In this case only the modules in its hierarchy are kept | ||
if(ARG_TOP_MODULE) | ||
set(TOP_MODULE --top-module ${ARG_TOP_MODULE}) | ||
endif() | ||
|
||
# Get the list of RTL sources | ||
get_ip_rtl_sources(RTL_SOURCES ${IP_LIB}) | ||
# Create a list to hold the RTL files as arguments for the Python script | ||
set(RTL_FILES_ARGS) | ||
# Add each RTL file to the list of arguments | ||
foreach(file ${RTL_SOURCES}) | ||
list(APPEND RTL_FILES_ARGS ${file}) | ||
endforeach() | ||
|
||
find_python3() | ||
set(__CMD ${Python3_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/copy_rtl_files.py | ||
${TOP_MODULE} --stats --outdir ${OUTDIR} ${RTL_FILES_ARGS} | ||
) | ||
|
||
# Call the Python script with the output directory and the RTL files | ||
set(STAMP_FILE "${CMAKE_BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}.stamp") | ||
add_custom_command( | ||
OUTPUT ${STAMP_FILE} | ||
COMMAND ${__CMD} | ||
COMMENT "Copying RTL files to ${OUTDIR}" | ||
VERBATIM | ||
) | ||
|
||
# Create a target to run the custom command | ||
add_custom_target( | ||
${IP_LIB}_copy_rtl | ||
ALL DEPENDS ${IP_LIB} ${STAMP_FILE} | ||
) | ||
endfunction() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import os | ||
import shutil | ||
import argparse | ||
from tmrg.verilog_elaborator import VerilogElaborator | ||
|
||
def remove_common_path(file_paths): | ||
# Find the common path | ||
common_path = os.path.commonpath(file_paths) | ||
|
||
# Get the last common directory | ||
last_common_directory = os.path.basename(common_path) | ||
|
||
# Iterate over each file path and remove the common path | ||
updated_paths = [] | ||
for path in file_paths: | ||
relative_path = os.path.relpath(path, common_path) | ||
updated_path = os.path.join(last_common_directory, relative_path) | ||
updated_paths.append(updated_path) | ||
|
||
return updated_paths | ||
|
||
def parse_input_files(velab, input_files): | ||
|
||
def _enterH(velab, module, i="", done=[], hierarchy_files=[], hierarchy_missing_files=[]): | ||
i += " |" | ||
for instName, inst in velab.global_namespace.modules[module].instances: | ||
if inst.module_name in velab.global_namespace.modules: | ||
print(i+"- "+instName+":"+inst.module_name) | ||
hierarchy_files.append(velab.global_namespace.modules[inst.module_name].file.filename) | ||
if id(inst) in done: | ||
continue | ||
else: | ||
done.append(id(inst)) | ||
_enterH(velab, inst.module_name, i, done, hierarchy_files, hierarchy_missing_files) | ||
else: | ||
print(i+"- [!] "+instName+":"+inst.module_name) | ||
if inst.module_name not in hierarchy_missing_files: | ||
hierarchy_missing_files.append(inst.module_name) | ||
|
||
done = [] | ||
hierarchy_files = [] | ||
hierarchy_missing_files = [] | ||
_enterH(velab, velab.topModule, "", done, hierarchy_files, hierarchy_missing_files) | ||
|
||
# for module in hierarchy_files: | ||
# print(f"Module {module} found") | ||
|
||
for module in hierarchy_missing_files: | ||
print(f"WARNING: Module {module} missing") | ||
|
||
return hierarchy_files | ||
|
||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description="Filter RTL files based on module hierarchy.") | ||
# parser.add_argument('--top', help='Top module name') | ||
parser.add_argument('--outdir', help='Output directory where files will be copied') | ||
parser.add_argument('--list-files', action="store_true", help="Don't generate files, but instead just list the files that will be generated") | ||
parser.add_argument("--inc-dir", dest="inc_dir", action="append", default=[], | ||
help="Directory where to look for include files (use option --include to actualy include the files during preprocessing)") | ||
parser.add_argument("--include", dest="include", | ||
action="store_true", default=False, help="Include include files") | ||
parser.add_argument("--generate-report", dest="generateBugReport", | ||
action="store_true", default=False, help="Generate bug report") | ||
parser.add_argument("--stats", dest="stats", action="store_true", help="Print statistics") | ||
parser.add_argument("--top-module", dest="top_module", action="store", default="", help="Specify top module name") | ||
parser.add_argument('files', metavar='F', type=str, nargs='+', help='List of RTL file paths') | ||
|
||
args = parser.parse_args() | ||
|
||
try: | ||
files = args.files | ||
|
||
# We manually add some attributes to be compliant with the expected options | ||
args.libs = [] | ||
# We use TMRG libraries to elaborate our design | ||
velab = VerilogElaborator(args, files, "tmrg") | ||
# First files have to be parsed | ||
velab.parse() | ||
# Then the design can be elaborated | ||
velab.elaborate(allowMissingModules=True) | ||
# Get on the files from the hierarchy if top module is provided | ||
if args.top_module: | ||
files = parse_input_files(velab, files) | ||
|
||
|
||
# Remove common path of the files | ||
files_striped = remove_common_path(files) | ||
# Get absolute path of the dst directory | ||
abs_path = os.path.abspath(args.outdir) | ||
# Change file paths to dst directory | ||
files_dst = [] | ||
for f_dst in files_striped: | ||
files_dst.append(abs_path + '/' + f_dst) | ||
|
||
# Only print the files if argument is passed | ||
if args.list_files: | ||
print(*files_dst) | ||
else: | ||
file_list_path = abs_path + '/file_list.txt' | ||
# Check if the file list exist, otherwise create it | ||
os.makedirs(os.path.dirname(file_list_path), exist_ok=True) | ||
# Write the files to the file list | ||
with open(file_list_path, 'w') as outfile: | ||
for f_src, f_dst in zip(files, files_dst): | ||
# Write the path to the list of path file | ||
outfile.write(f_dst + '\n') | ||
# Create the folder hierarchy | ||
os.makedirs(os.path.dirname(f_dst), exist_ok=True) | ||
# Copy the file to the new location | ||
shutil.copy2(f_src, f_dst) | ||
|
||
# Add empty line at the end of the file | ||
outfile.write('\n') | ||
print(f"Filtered file list written to {file_list_path}") | ||
except ValueError as e: | ||
print(e) | ||
|
||
if __name__ == "__main__": | ||
main() |