Skip to content

Commit

Permalink
TMRG lib strip (#18)
Browse files Browse the repository at this point in the history
* module stripping initial commit.

* triplicated IP dependencies are stripped before to be passed as libraries to tmrg.

---------

Co-authored-by: Benoit Denkinger <[email protected]>
  • Loading branch information
benoitdenkinger and Benoit Denkinger authored Aug 16, 2024
1 parent ccc1a46 commit b2a0d94
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 39 deletions.
68 changes: 68 additions & 0 deletions cmake/tmrg/tmrg/lib_module_strip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import sys
import os
import shutil
import argparse

# Based on tmake: flows/tmrg/tmr/run.py.tpl
# commit: 96449c8a8a5b58ab7583fba04821cb89feda893a
def generate_implementation_lib(fname_in, fname_out):
"""This function loads a post-implementation netlist and
generates a simplified version retaining only port information
of the top module.
"""
module_name = os.path.splitext(os.path.basename(fname_in))[0]
_, file_extension = os.path.splitext('/path/to/somefile.ext')
in_package = False
in_module = False
in_module_header = False
with open(fname_in) as fin, open(fname_out, "w") as fout:
for line in fin.readlines():
line_stripped = line.strip()
# Additional check to skip packages
if line_stripped.startswith("package %s" % module_name):
in_package = True
break
if line_stripped.startswith("module %s" % module_name):
in_module_header = True
in_module = True
if in_module_header:
fout.write(line)
if line_stripped.endswith(");"):
in_module_header = False
elif in_module and file_extension == 'v' and (
line_stripped.startswith("input ")
or line_stripped.startswith("inout ")
or line_stripped.startswith("output ")
):
fout.write(line)
elif in_module and line_stripped.startswith("endmodule"):
fout.write(line)
in_module = False
# If we have a package file just copy it
if in_package:
shutil.copyfile(fname_in, fname_out)

parser = argparse.ArgumentParser(description='Systemverilog module stripping')

parser.add_argument('-f','--files', nargs='+', help='File(s) to strip')
parser.add_argument('-o','--outdir', type=str, help='Output directory where stripped files are generated', required=True)

print('Executing lib_module_strip.py')

options = parser.parse_args()

# Exit if no files are passed
if options.files is None:
print('No dependencies to strip')
sys.exit(0)

# Check the output directory exists
outdir = options.outdir
if not os.path.exists(outdir):
os.makedirs(outdir)

for file in options.files:
# Take the file basename
basename = os.path.basename(file)
stripped_file = f'{outdir}/{basename}'
generate_implementation_lib(file, stripped_file)
88 changes: 49 additions & 39 deletions cmake/tmrg/tmrg/tmrg.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -45,29 +45,10 @@ function(tmrg IP_LIB)
unset(ARG_CONFIG_FILE)
endif()

# Get all the TMRG sources (ip+dependencies)
get_tmrg_sources(TMRG_SRC_ALL ${IP_LIB})
# Get only the IP TMRG sources (not the dependencies)
# Get only the IP TMRG sources only (not the dependencies)
safe_get_target_property(TMRG_SRC_IP ${IP_LIB} TMRG_SOURCES "FATAL")
# get_target_property(TMRG_SRC_IP ${IP_LIB} TMRG_SOURCES)
list(REMOVE_DUPLICATES TMRG_SRC_IP)

# message("TMRG_FUNC: TMRG_SRC_ALL=${TMRG_SRC_ALL}")
# message("TMRG_FUNC: TMRG_SRC_IP=${TMRG_SRC_IP}")

set(TMRG_SRC_DEPS)
# Find the deps TMRG sources only
foreach(file ${TMRG_SRC_ALL})
list(FIND TMRG_SRC_IP ${file} index)
# message("TMRG_FUNC: searching ${file} in ${TMRG_SRC_IP}")
if(index EQUAL -1)
list(APPEND TMRG_SRC_DEPS ${file})
# message("File not found")
endif()
endforeach()

# message("TMRG_FUNC: TMRG_SRC_DEPS=${TMRG_SRC_DEPS}")

# We also get the non-triplicated sources
# For example, primitive cells are not all triplicated
# and instantiating them 3 times is fine
Expand All @@ -79,8 +60,10 @@ function(tmrg IP_LIB)
safe_get_target_property(V_SRC_IP ${IP_LIB} VERILOG_SOURCES "")
list(PREPEND SV_SRC_IP ${V_SRC_IP})

# message("TMRG_FUNC: SV_SRC_IP=${SV_SRC_IP}")

# Only the IP sources (not the dependencies) are triplicated
# The dependency sources are passed as libraries and its up
# to the dependencies to provide triplicated (or not triplicated)
# module definitions.
set(SRC_DEPS)
# Find the deps sources only
foreach(file ${IP_SRC_ALL})
Expand All @@ -90,22 +73,49 @@ function(tmrg IP_LIB)
endif()
endforeach()

# message("TMRG_FUNC: SRC_DEPS=${SRC_DEPS}")
# message("")
# message("")
# message("")
# Files passed as lib are stripped of their content to avoid
# missing module definition. For example, if one lib file instantiate
# a triplicated module of another lib file this creates an undefined module
# error by tmrg because tmrg tracks the non-triplicated module names.
set(LIB_STRIP_DIR ${OUTDIR}/lib_strip)
if(SRC_DEPS)
set(LIB_STRIP_CMD
${Python3_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/lib_module_strip.py --files ${SRC_DEPS} --outdir ${LIB_STRIP_DIR}
)
else()
set(LIB_STRIP_CMD
${Python3_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/lib_module_strip.py --outdir ${LIB_STRIP_DIR}
)
endif()

set(SCR_DEPS_STRIPPED)
foreach(file ${SRC_DEPS})
get_filename_component(BASE_NAME ${file} NAME)
set(NEW_FILE_PATH "${LIB_STRIP_DIR}/${BASE_NAME}")
list(APPEND SCR_DEPS_STRIPPED ${NEW_FILE_PATH})
endforeach()


# Only the IP sources (not the dependencies) are triplicated
# The dependency sources are passed as libraries and its up
# to the dependencies to provide triplicated (or not triplicated)
# module definitions.
set(STAMP_FILE "${BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}_lib_strip.stamp")
add_custom_command(
OUTPUT ${STAMP_FILE} ${SCR_DEPS_STRIPPED}
COMMAND ${LIB_STRIP_CMD}
COMMAND touch ${STAMP_FILE}
DEPENDS ${SRC_DEPS}
COMMENT "Running module stripping on deps files of ${IP_LIB}"
)

add_custom_target(
${IP_LIB}_${CMAKE_CURRENT_FUNCTION}_lib_strip
DEPENDS ${STAMP_FILE} ${SCR_DEPS_STRIPPED}
)

foreach(vfile ${TMRG_SRC_IP})
get_filename_component(V_SOURCE_WO_EXT ${vfile} NAME_WE)
get_filename_component(V_SOURCE_EXT ${vfile} EXT)
list(APPEND V_GEN "${OUTDIR}/${V_SOURCE_WO_EXT}TMR${V_SOURCE_EXT}")
list(APPEND TRMG_GEN "${OUTDIR}/${V_SOURCE_WO_EXT}TMR${V_SOURCE_EXT}")
endforeach()
set_source_files_properties(${V_GEN} PROPERTIES GENERATED TRUE)
set_source_files_properties(${TRMG_GEN} PROPERTIES GENERATED TRUE)

set(TMRG_COMMAND
${Python3_VIRTUAL_ENV}/bin/tmrg --stats --tmr-dir=${OUTDIR} ${ARG_CONFIG_FILE} ${TMRG_SRC_IP}
Expand All @@ -119,10 +129,10 @@ function(tmrg IP_LIB)
# SRC_DEPS contains non-triplicated and triplicated sources as
# long as the deps use tmrg with the REPLACE argument.
# Each dep source is passed as libraries
if(SRC_DEPS)
if(SCR_DEPS_STRIPPED)
set(SRC_LIBS)
# Each file needs to be passed with the '-l' option
foreach(file ${SRC_DEPS})
foreach(file ${SCR_DEPS_STRIPPED})
list(APPEND SRC_LIBS -l ${file})
endforeach()
set(TMRG_COMMAND ${TMRG_COMMAND} ${SRC_LIBS})
Expand All @@ -147,22 +157,22 @@ function(tmrg IP_LIB)
# sequence is always followed by a space. Otherwise, if 'wor' is used in a name (e.g., word_address)
# it will also be replaced (e.g., to wird_address).
if(ARG_SED_WOR)
set(SED_COMMAND COMMAND sed -i "s/wor /wire /g" ${V_GEN})
set(SED_COMMAND COMMAND sed -i "s/wor /wire /g" ${TRMG_GEN})
endif()

set(STAMP_FILE "${BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}.stamp")
add_custom_command(
OUTPUT ${V_GEN} ${STAMP_FILE}
OUTPUT ${TRMG_GEN} ${STAMP_FILE}
COMMAND ${TMRG_COMMAND}
${SED_COMMAND}
COMMAND touch ${STAMP_FILE}
DEPENDS ${TMRG_SRC_IP}
DEPENDS ${TMRG_SRC_IP} ${SCR_DEPS_STRIPPED}
COMMENT "Running ${CMAKE_CURRENT_FUNCTION} on ${IP_LIB}"
)

add_custom_target(
${IP_LIB}_${CMAKE_CURRENT_FUNCTION}
DEPENDS ${STAMP_FILE} ${TMRG_SRC_IP} ${V_GEN}
DEPENDS ${STAMP_FILE} ${TRMG_GEN}
)

if(ARG_REPLACE)
Expand All @@ -175,7 +185,7 @@ function(tmrg IP_LIB)
list(REMOVE_ITEM V_SRC ${TMRG_SRC_IP})

# Append generated files to correct source lists
foreach(i ${V_GEN})
foreach(i ${TRMG_GEN})
get_filename_component(FILE_EXT ${i} EXT)
if("${FILE_EXT}" STREQUAL ".sv")
list(APPEND SV_SRC ${i})
Expand Down

0 comments on commit b2a0d94

Please sign in to comment.