Skip to content

Commit

Permalink
Add xcelium SystemC support issue #126
Browse files Browse the repository at this point in the history
  • Loading branch information
Risto97 committed Mar 6, 2025
1 parent 14b3503 commit 4d85dbc
Show file tree
Hide file tree
Showing 17 changed files with 319 additions and 73 deletions.
1 change: 1 addition & 0 deletions cmake/build_scripts/systemc/systemc_build.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ function(systemc_build)
${CMAKE_ARG_VERSION}
${CMAKE_CXX_STANDARD_ARG}
-DCMAKE_INSTALL_PREFIX=${ARG_INSTALL_DIR}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
COMMAND_ECHO STDOUT
)

Expand Down
89 changes: 81 additions & 8 deletions cmake/sim/cadence/xcelium.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
include_guard(GLOBAL)

function(xcelium IP_LIB)
cmake_parse_arguments(ARG "NO_RUN_TARGET;GUI" "RUN_TARGET_NAME;TOP_MODULE;LIBRARY" "COMPILE_ARGS;SV_COMPILE_ARGS;VHDL_COMPILE_ARGS;ELABORATE_ARGS;RUN_ARGS" ${ARGN})
cmake_parse_arguments(ARG "NO_RUN_TARGET;GUI;32BIT" "RUN_TARGET_NAME;TOP_MODULE;LIBRARY" "COMPILE_ARGS;SV_COMPILE_ARGS;VHDL_COMPILE_ARGS;ELABORATE_ARGS;RUN_ARGS" ${ARGN})
if(ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}")
endif()
Expand Down Expand Up @@ -48,6 +48,14 @@ function(xcelium IP_LIB)
endif()
file(MAKE_DIRECTORY ${OUTDIR})

if(ARG_32BIT)
set(bitness 32)
set(ARG_BITNESS 32BIT)
else()
set(bitness 64)
unset(ARG_BITNESS)
endif()

if(ARG_COMPILE_ARGS)
set(ARG_COMPILE_ARGS COMPILE_ARGS ${ARG_COMPILE_ARGS})
endif()
Expand All @@ -61,6 +69,7 @@ function(xcelium IP_LIB)
if(NOT TARGET ${IP_LIB}_xcelium_complib)
__xcelium_compile_lib(${IP_LIB}
OUTDIR ${OUTDIR}
${ARG_BITNESS}
${ARG_LIBRARY}
${ARG_COMPILE_ARGS}
${ARG_SV_COMPILE_ARGS}
Expand All @@ -69,6 +78,50 @@ function(xcelium IP_LIB)
endif()
set(comp_tgt ${IP_LIB}_xcelium_complib)

get_ip_links(__ips ${IP_LIB})
unset(systemc_libs)
foreach(lib ${__ips})
get_target_property(ip_type ${lib} TYPE)
if(ip_type STREQUAL "SHARED_LIBRARY" OR ip_type STREQUAL "STATIC_LIBRARY" OR ip_type STREQUAL "OBJECT_LIBRARY")
get_target_property(socmake_cxx_library_type ${lib} SOCMAKE_CXX_LIBRARY_TYPE)
if(socmake_cxx_library_type STREQUAL "SYSTEMC")
list(APPEND systemc_libs ${lib})
endif()
endif()
endforeach()

unset(systemc_lib_args)
if(systemc_libs)
set(systemc_lib_name ${IP_LIB}_xcelium_systemc)

## Because shared library without any source files is not possible
file(WRITE "${OUTDIR}/__null.cpp" "")
add_library(${systemc_lib_name} SHARED
"${OUTDIR}/__null.cpp"
)
if(ARG_32BIT)
target_compile_options(${systemc_lib_name} PUBLIC -m32)
target_link_options( ${systemc_lib_name} PUBLIC -m32)
endif()

if(bitness STREQUAL "64")
set(libpath "lib/64bit/gnu")
else()
set(libpath "lib/gnu")
endif()

__find_xcelium_home(xcelium_home)
target_link_libraries(${IP_LIB}_${CMAKE_CURRENT_FUNCTION}_systemc PUBLIC
${systemc_libs}
${xcelium_home}/tools/systemc/${libpath}/libncscCoSim_sh.so
${xcelium_home}/tools/systemc/${libpath}/libncscCoroutines_sh.so
${xcelium_home}/tools/systemc/${libpath}/libsystemc_sh.so
)

set(systemc_lib_args -loadsc $<TARGET_FILE:${IP_LIB}_${CMAKE_CURRENT_FUNCTION}_systemc>)
list(APPEND comp_tgt ${IP_LIB}_${CMAKE_CURRENT_FUNCTION}_systemc)
endif()

__get_xcelium_search_lib_args(${IP_LIB}
${ARG_LIBRARY}
OUTDIR ${OUTDIR})
Expand All @@ -83,6 +136,7 @@ function(xcelium IP_LIB)
-q
-nocopyright
${hdl_libs_args}
${systemc_lib_args}
${ARG_ELABORATE_ARGS}
-top ${LIBRARY}.${ARG_TOP_MODULE}
)
Expand Down Expand Up @@ -340,27 +394,46 @@ function(__get_xcelium_search_lib_args IP_LIB)
set(DPI_LIBS_ARGS ${dpi_libs_args} PARENT_SCOPE)
endfunction()

function(__find_xcelium_home OUTVAR)
find_program(exec_path xrun REQUIRED)
get_filename_component(bin_path "${exec_path}" DIRECTORY)
cmake_path(SET xcelium_home NORMALIZE "${bin_path}/../../")

set(${OUTVAR} ${xcelium_home} PARENT_SCOPE)
endfunction()

function(__add_xcelium_cxx_properties_to_libs IP_LIB)
if(ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}")
endif()
# Find the Xcelium tools/include directory, needed for VPI/DPI libraries
find_program(xrun_exec_path xrun)
get_filename_component(vpi_inc_path "${xrun_exec_path}" DIRECTORY)
cmake_path(SET vpi_inc_path NORMALIZE "${vpi_inc_path}/../include")
__find_xcelium_home(xcelium_home)
set(tools_dir_path "${xcelium_home}/tools")

get_ip_links(ips ${IP_LIB})
foreach(lib ${ips})
# In case linked library is C/C++ shared/static object, dont try to compile it, just append its path to -sv_lib arg
get_target_property(ip_type ${lib} TYPE)
if(ip_type STREQUAL "SHARED_LIBRARY" OR ip_type STREQUAL "STATIC_LIBRARY")
if(NOT xrun_exec_path)
message(FATAL_ERROR "Xcelium executable xrun was not found, cannot set include directory on DPI library")
if(ip_type STREQUAL "SHARED_LIBRARY" OR ip_type STREQUAL "STATIC_LIBRARY" OR ip_type STREQUAL "OBJECT_LIBRARY")
get_target_property(socmake_cxx_library_type ${lib} SOCMAKE_CXX_LIBRARY_TYPE)

if(socmake_cxx_library_type STREQUAL "SYSTEMC")
target_include_directories(${lib} PUBLIC
${tools_dir_path}/systemc/include
${tools_dir_path}/tbsc/include
${tools_dir_path}/vic/include
)
endif()
# Add tools/include directory to the include directories of DPI libraries
# TODO do this only when its needed
target_include_directories(${lib} PUBLIC ${vpi_inc_path})
target_include_directories(${lib} PUBLIC "${tools_dir_path}/include")
target_compile_definitions(${lib} PUBLIC INCA)
endif()
endforeach()
endfunction()

macro(xcelium_configure_cxx)
__find_xcelium_home(xcelium_home)
set(CMAKE_CXX_COMPILER "${xcelium_home}/tools.lnx86/cdsgcc/gcc/bin/g++")
set(CMAKE_C_COMPILER "${xcelium_home}/tools.lnx86/cdsgcc/gcc/bin/gcc")
endmacro()
2 changes: 2 additions & 0 deletions cmake/utils/socmake_graph.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ function(__all_vertices_removed NODE RET)
endif()
get_target_property(RM_LIST ${NODE} __RM_LIST)
get_target_property(LINK_LIBS ${NODE} INTERFACE_LINK_LIBRARIES)
list(REMOVE_DUPLICATES LINK_LIBS)

if(RM_LIST STREQUAL "RM_LIST-NOTFOUND")
set(RM_LIST "")
endif()
Expand Down
40 changes: 33 additions & 7 deletions examples/simple_mixed_language_sc_vlog/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,27 +1,47 @@
include("../../SoCMakeConfig.cmake")


set(FETCHCONTENT_BASE_DIR ${CMAKE_CURRENT_LIST_DIR}/deps/_deps)
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
set(SOCMAKE_ADDITIONAL_LANGUAGES SYSTEMC)

option_enum(SIMULATOR "Which Simulator to use" "mgc;osci" "mgc")
option_enum(SIMULATOR "Which Simulator to use" "mgc;osci;xcelium" "xcelium")
option_enum(TEST_LANG "Language for test module" "verilog;systemc" "verilog")
option_enum(DUT_LANG "Language for DUT modules" "verilog;systemc" "verilog")
option_boolean(MGC_GUI "Use GUI for modelsim" OFF)

if(SIMULATOR STREQUAL "xcelium")
xcelium_configure_cxx()
endif()

# If Using Verilator and Testbench is Verilog, we need coroutines for --timing from C++17
if(SIMULATOR STREQUAL "osci" AND TEST_LANG STREQUAL "verilog")
set(CMAKE_CXX_STANDARD 17)
else()
set(CMAKE_CXX_STANDARD 11)
endif()

cmake_minimum_required(VERSION 3.25)
project(simple_mixed_language_sc_vlog NONE)
project(simple_mixed_language_sc_vlog CXX)

add_subdirectory(tests)

# ################################################
# ################ XCELIUM #######################
# ################################################

if(SIMULATOR STREQUAL "xcelium")
xcelium(test_counters TOP_MODULE test_counters)

endif()

# ################################################
# ################ MODELSIM ######################
# ################################################

if(SIMULATOR STREQUAL "mgc")
if(MGC_GUI)
set(modelsim_gui_args GUI_VISUALIZER RUN_ARGS -vopt -voptargs=+acc=pn)
set(modelsim_gui_args GUI RUN_ARGS -vopt -voptargs=+acc=pn)
endif()
modelsim(test_counters QUIET
${modelsim_gui_args}
Expand All @@ -47,28 +67,34 @@ if(SIMULATOR STREQUAL "osci")
# In case hierarchy is SystemC-SystemC or SystemC-Verilog
if(TEST_LANG STREQUAL "systemc")
enable_language(CXX)
set(CMAKE_CXX_STANDARD 11)
systemc_build(VERSION 2.3.4 EXACT_VERSION)

add_executable(systemc_example
tests/sc_main.cpp
)

target_link_libraries(systemc_example PUBLIC
SystemC::systemc
test_counters
)
target_link_libraries(test_counters PUBLIC SystemC::systemc)
target_compile_definitions(test_counters PUBLIC OSCI)


# In case DUT is verilog, use Verilator to convert from Verilog to SystemC
if(DUT_LANG STREQUAL "verilog")
verilator(counters SYSTEMC
VERILATOR_ARGS --pins-sc-uint
VERILATOR_ARGS --pins-sc-uint --timescale-override 1ps/1ps
PREFIX counters

)

# Link into the verilated static library
target_link_libraries(systemc_example PUBLIC
target_link_libraries(test_counters PUBLIC
counters__vlt
)
elseif(DUT_LANG STREQUAL "systemc")
target_link_libraries(counters PUBLIC SystemC::systemc)
target_compile_definitions(counters PUBLIC OSCI)
endif()
endif()

Expand Down
28 changes: 15 additions & 13 deletions examples/simple_mixed_language_sc_vlog/counter1/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@

add_ip(counter1)

if(DUT_LANG STREQUAL "verilog")
add_ip(counter1)
ip_sources(${IP} VERILOG
vlog/counter1.v
)
elseif(DUT_LANG STREQUAL "systemc")
ip_sources(${IP} SYSTEMC
HEADERS
sc/counter1.h
)
endif()
if(SIMULATOR STREQUAL "xcelium" OR SIMULATOR STREQUAL "osci")
set(IP counter1)
add_library(${IP} INTERFACE)
target_include_directories(${IP} INTERFACE ./sc)

ip_include_directories(${IP} SYSTEMC
sc
)
target_include_directories(${IP} INTERFACE
sc
)
# For now Questa uses SoCMake IP block for SystemC
elseif(SIMULATOR STREQUAL "mgc")
add_ip(counter1)
ip_sources(${IP} SYSTEMC
HEADERS
sc/counter1.h
)
ip_include_directories(${IP} SYSTEMC ./sc)
endif()
endif()
28 changes: 15 additions & 13 deletions examples/simple_mixed_language_sc_vlog/counter2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
add_ip(counter2)

if(DUT_LANG STREQUAL "verilog")
add_ip(counter2)
ip_sources(${IP} VERILOG
vlog/counter2.v
)
elseif(DUT_LANG STREQUAL "systemc")
ip_sources(${IP} SYSTEMC
HEADERS
sc/counter2.h
)
endif()

ip_include_directories(${IP} SYSTEMC
sc
)
target_include_directories(${IP} INTERFACE
sc
)
if(SIMULATOR STREQUAL "xcelium" OR SIMULATOR STREQUAL "osci")
set(IP counter2)
add_library(${IP} INTERFACE)
target_include_directories(${IP} INTERFACE ./sc)

# For now Questa uses SoCMake IP block for SystemC
elseif(SIMULATOR STREQUAL "mgc")
add_ip(counter2)
ip_sources(${IP} SYSTEMC
HEADERS
sc/counter2.h
)
ip_include_directories(${IP} SYSTEMC ./sc)
endif()
endif()
55 changes: 41 additions & 14 deletions examples/simple_mixed_language_sc_vlog/counters/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,29 +1,56 @@
add_ip(counters)

if(DUT_LANG STREQUAL "verilog")
add_ip(counters)
ip_sources(${IP} VERILOG
vlog/counters.v
)
if(SIMULATOR STREQUAL "xcelium")
target_include_directories(${IP} INTERFACE ./sc/xcelium_shell/)
elseif(SIMULATOR STREQUAL "mgc")
ip_include_directories(${IP} SYSTEMC ./sc/mgc_shell/)
endif()

elseif(DUT_LANG STREQUAL "systemc")
ip_sources(${IP} SYSTEMC
sc/counters.cpp
HEADERS
sc/counters.h
)
endif()

ip_include_directories(${IP} SYSTEMC
sc
)
target_include_directories(${IP} INTERFACE
sc
)
if(SIMULATOR STREQUAL "xcelium" OR SIMULATOR STREQUAL "osci")
set(IP counters)
add_library(${IP} OBJECT
./sc/counters.cpp
)

# This is Verilog shell for SystemC module, can be generated with xmshell
ip_sources(${IP} VERILOG
./vlog/xcelium_shell/counters.v
)

set_target_properties(${IP}
PROPERTIES
SOCMAKE_CXX_LIBRARY_TYPE SYSTEMC
POSITION_INDEPENDENT_CODE TRUE
)

target_include_directories(${IP} INTERFACE ./sc)
elseif(SIMULATOR STREQUAL "mgc")
add_ip(counters)
ip_sources(${IP} SYSTEMC
sc/counters.cpp
HEADERS
sc/counters.h
)
ip_include_directories(${IP} SYSTEMC ./sc)
endif()
endif()

add_subdirectory(../counter1/ "counter1")
add_subdirectory(../counter2/ "counter2")

ip_link(${IP}
ip_link(${IP}
counter1
counter2
)

if(DUT_LANG STREQUAL "systemc" AND (SIMULATOR STREQUAL "xcelium" OR SIMULATOR STREQUAL "osci"))
target_link_libraries(${IP} PUBLIC
counter1
counter2)
endif()
Loading

0 comments on commit 4d85dbc

Please sign in to comment.