Skip to main content

Hierarchical design

SoCMake promotes hierarchical design, by organizing IP blocks into IP libraries, we can easily reuse IP blocks into different designs.

Let's try to create a bit more complex example to demonstrate how to link different libraries together. Imagine the following graph.

  • We have a top IP that instantiates some primitives: prim10 and prim11.
  • prim10 depends on prim00.
  • prim11 depends on prim00 and prim01.

Graph

CMakeLists.txt

We can create this hierarchy with the following CMakeLists.txt

CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(example
LANGUAGES NONE
VERSION 0.0.1)

include("deps/deps.cmake")
set(SOCMAKE_NOWARN_VLNV TRUE) # Do not warn incomplete VLNV format

## Define IP TOP
add_ip(top)
ip_sources(top VERILOG
${PROJECT_SOURCE_DIR}/top.v
)

# Define IP prim10
add_ip(prim10)
ip_sources(prim10 VERILOG
${PROJECT_SOURCE_DIR}/prim10.v
)

## Define IP prim11
add_ip(prim11)
ip_sources(prim11 VERILOG
${PROJECT_SOURCE_DIR}/prim11.v
)

## Define IP prim00
add_ip(prim00)
ip_sources(prim00 VERILOG
${PROJECT_SOURCE_DIR}/prim00.v
)

## Define IP prim01
add_ip(prim01)
ip_sources(prim01 VERILOG
${PROJECT_SOURCE_DIR}/prim01.v
)

ip_link(top prim10 prim11)
ip_link(prim10 prim00)
ip_link(prim11 prim00 prim01)

# Get Verilog sources
get_ip_sources(V_SOURCES top VERILOG)
# Just print sources
string(REPLACE ";" "\n " V_SOURCES "${V_SOURCES}")
message("V_SOURCES: \n ${V_SOURCES}")
warning

We can see in the highlighted lines add_ip() function calls, that we are adding IPs without VENDOR, LIBRARY, VERSION format, instead we only pass the NAME. This is not recommended, and we set SOCMAKE_NOWARN_VLNV variable to true, so we don't get a warning.

Finally we are describing our dependencies with ip_link() function. The ip_link() function as first positional argument takes the Dependent library, and the rest of the arguments are its Dependencies.

We can get the Source Filesets by calling get_ip_sources() on the IP library. First argument is the variable where to save the list of sources, second one is the name of the IP library and the last one is the file type.

We are finally printing the list of sources to stdout in the last 2 lines.

-- CPM: Adding package SoCMake@ (verilator_system_path)
V_SOURCES:
..../linking_ips/prim00.v
..../linking_ips/prim01.v
..../linking_ips/prim10.v
..../linking_ips/prim11.v
..../linking_ips/top.v
-- Configuring done
-- Generating done
-- Build files have been written to: ..../linking_ips/build
caution

CMake property populated in this case will be VERILOG_SOURCES, the library top will only hold its own VERILOG_SOURCES in this case top.v, so if you use get_target_property(V_SOURCES top VERILOG_SOURCES) you will only get one file, if you want to get the files of all IPs use get_ip_sources()

We can see that the order of the printed files is respected and that the lowest hierarchy IPs files are first.

tip

Running make graphviz on the previous example will generate the graph shown above

tip

It is recommended to keep libraries in separate directories and CMakeLists.txt files, and ideally on their own GIT repositories.