aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/docs/usrp3/sim/writing_sim_makefile.md
blob: c503e7e0470dc051a148fcbd6054d7f328a087fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# Writing a Simulation Makefile

The testbench Makefile tells the build tools what to build, where to build it,
dependency information, and runtime information. The build infrastructure will
handle the how-to part for each supported simulation tool.

An example makefile for a testbench is shown below. If creating a testbench for
RFNoC, it is recommended to use the RFNoC ModTool to generate a Makefile
template for your RFNoC block.

    #
    # Copyright 2020 Ettus Research, a National Instruments Brand
    #
    # SPDX-License-Identifier: LGPL-3.0-or-later
    #

    #-------------------------------------------------
    # Top-of-Makefile
    #-------------------------------------------------
    # Define BASE_DIR to point to the "top" dir. Note:
    # UHD_FPGA_DIR must be passed into this Makefile.
    ifndef UHD_FPGA_DIR
    $(error "UHD_FPGA_DIR is not set! Must point to UHD FPGA repository!")
    endif
    BASE_DIR = $(UHD_FPGA_DIR)/usrp3/top
    # Include viv_sim_preample after defining BASE_DIR
    include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak

    #-------------------------------------------------
    # Design Specific
    #-------------------------------------------------
    # Define part using PART_ID (<device>/<package>/<speedgrade>)
    ARCH = kintex7
    PART_ID = xc7k410t/ffg900/-2

    # Include makefiles and sources for the DUT and its dependencies
    include $(BASE_DIR)/../lib/rfnoc/core/Makefile.srcs
    include $(BASE_DIR)/../lib/rfnoc/utils/Makefile.srcs
    include $(BASE_DIR)/../lib/fifo/Makefile.srcs
    include $(BASE_DIR)/../lib/axi/Makefile.srcs
    include $(BASE_DIR)/../lib/control/Makefile.srcs

    DESIGN_SRCS += $(abspath \
    $(RFNOC_CORE_SRCS) \
    $(RFNOC_UTIL_SRCS) \
    $(RFNOC_OOT_SRCS) \
    $(FIFO_SRCS) \
    $(AXI_SRCS) \
    $(CONTROL_LIB_SRCS) \
    )

    #-------------------------------------------------
    # IP Specific
    #-------------------------------------------------
    # If simulation contains IP, define the IP_DIR and point
    # it to the base level IP directory
    IP_DIR = $(BASE_DIR)/x300/ip
    LIB_IP_DIR = $(BASE_DIR)/../lib/ip

    # Include makefiles and sources for all IP components
    # *after* defining the IP_DIR
    include $(IP_DIR)/fifo_4k_2clk/Makefile.inc
    include $(LIB_IP_DIR)/axi_fft/Makefile.inc

    DESIGN_SRCS += $(abspath \
    $(IP_FIFO_4K_2CLK_SRCS) \
    $(LIB_IP_AXI_FFT_SRCS) \
    rfnoc_block_example.v \
    )

    #-------------------------------------------------
    # Testbench Specific
    #-------------------------------------------------
    include $(BASE_DIR)/../sim/general/Makefile.srcs
    include $(BASE_DIR)/../sim/axi/Makefile.srcs

    # Define only one top-level module
    SIM_TOP = rfnoc_block_example_tb

    # Simulation runtime in microseconds
    SIM_RUNTIME_US = 1000

    SIM_SRCS = \
    $(abspath rfnoc_block_example_tb.sv) \

    #-------------------------------------------------
    # Bottom-of-Makefile
    #-------------------------------------------------
    # Include all simulator specific makefiles here
    # Each should define a unique target to simulate
    # e.g. xsim, vsim, etc and a common "clean" target
    include $(BASE_DIR)/../tools/make/viv_simulator.mak

You will notice that the Makefile has 5 distinct sections.

## Section 1: Boilerplate

    #-------------------------------------------------
    # Top-of-Makefile
    #-------------------------------------------------
    # Define BASE_DIR to point to the "top" dir. Note:
    # UHD_FPGA_DIR must be passed into this Makefile.
    ifndef UHD_FPGA_DIR
    $(error "UHD_FPGA_DIR is not set! Must point to UHD FPGA repository!")
    endif
    BASE_DIR = $(UHD_FPGA_DIR)/usrp3/top
    # Include viv_sim_preample after defining BASE_DIR
    include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak

Before declaring any variables or using any recipes, the following must be
performed (in order):

- Define `BASE_DIR` to tell the build system where the `<repo>/fpga/usrp3/top`
  directory is relative to the current testbench directory
- Include `viv_sim_preamble.mak` to initialize boilerplate variables and
  functions

This example uses the make variable UHD_FPGA_DIR to specify the location of the
FPGA repository. This is useful for out-of-tree modules. UHD_FPGA_DIR is the
variable used by CMake for the RFNoC examples.

## Section 2: Design Specific

    #-------------------------------------------------
    # Design Specific
    #-------------------------------------------------
    # Define part using PART_ID (<device>/<package>/<speedgrade>)
    ARCH = kintex7
    PART_ID = xc7k410t/ffg900/-2

    # Include makefiles and sources for the DUT and its dependencies
    include $(BASE_DIR)/../lib/rfnoc/core/Makefile.srcs
    include $(BASE_DIR)/../lib/rfnoc/utils/Makefile.srcs
    include $(BASE_DIR)/../lib/fifo/Makefile.srcs
    include $(BASE_DIR)/../lib/axi/Makefile.srcs
    include $(BASE_DIR)/../lib/control/Makefile.srcs

    DESIGN_SRCS += $(abspath \
    $(RFNOC_CORE_SRCS) \
    $(RFNOC_UTIL_SRCS) \
    $(RFNOC_OOT_SRCS) \
    $(FIFO_SRCS) \
    $(AXI_SRCS) \
    $(CONTROL_LIB_SRCS) \
    )

This section contains pointers to sources and other variables needed for the
DUT to function. In the example above, we are including all sources from the
`lib/fifo`, `lib/axi`, `lib/control` directories. These may not be needed for
your simulation, in which case they can be removed to reduce compile times.

The following makefile variables are special and should be defined:

- `ARCH`: The architecture targeted for the simulation.
- `PART_ID`: The exact part targeted for the simulation. Format:
  `<device>/<package>/<speedgrade>`
- `DESIGN_SRCS`: Space-separated paths to the DUT and all of its dependencies.

If `ARCH` and `PART_ID` are not specified, a default part will be assumed. This
may be fine if your DUT doesn't have any architecture-specific IP.

## Section 3: IP Specific

    #-------------------------------------------------
    # IP Specific
    #-------------------------------------------------
    # If simulation contains IP, define the IP_DIR and point
    # it to the base level IP directory
    IP_DIR = $(BASE_DIR)/x300/ip
    LIB_IP_DIR = $(BASE_DIR)/../lib/ip

    # Include makefiles and sources for all IP components
    # *after* defining the IP_DIR
    include $(IP_DIR)/fifo_4k_2clk/Makefile.inc
    include $(LIB_IP_DIR)/axi_fft/Makefile.inc

    DESIGN_SRCS += $(abspath \
    $(IP_FIFO_4K_2CLK_SRCS) \
    $(LIB_IP_AXI_FFT_SRCS) \
    rfnoc_block_example.v \
    )

If the DUT depends on any Xilinx IP then this section is required. It tells the
tools which IP cores need to be built in order to run the simulation. The IP
specific Makefile `include` statements handle the "how" part of building IP. As
long as the correct Makefile is included and the IP XCI sources are added to
`DESIGN_SRCS`, the IP intermediates will be built correctly.

The `IP_DIR` variable shown here is defined to point to the base IP directory
that contains target-specific IP sources. The `IP_LIB_DIR` variable shown here
is defined to point to the base IP directory that contains target-independent
IP sources.

The IP included in this example may not be needed for your testbench, in which
case it can be removed to reduce compile times.

## Section 4: Testbench Specific

    #-------------------------------------------------
    # Testbench Specific
    #-------------------------------------------------
    include $(BASE_DIR)/../sim/general/Makefile.srcs
    include $(BASE_DIR)/../sim/axi/Makefile.srcs

    # Define only one top-level module
    SIM_TOP = rfnoc_block_example_tb

    # Simulation runtime in microseconds
    SIM_RUNTIME_US = 1000

    SIM_SRCS = \
    $(abspath rfnoc_block_example_tb.sv) \

This section contains all sources and parameters for the actual testbench. Any simulation
dependency makefiles can be included here.

The following variables should be defined:

- `SIM_TOP`: The top-level module name for the simulation.
- `SIM_RUNTIME_US`: The maximum runtime of the simulation in microseconds. At
  this time `$finish` will be called to terminate the testbench.
- `SIM_SRCS`: This is similar to DESIGN_SRCS except that it should contain a
  path to `SIM_TOP` and all of its dependencies.

## Section 5: Tool Support

    #-------------------------------------------------
    # Bottom-of-Makefile
    #-------------------------------------------------
    # Include all simulator specific makefiles here
    # Each should define a unique target to simulate
    # e.g. xsim, vsim, etc and a common "clean" target
    include $(BASE_DIR)/../tools/make/viv_simulator.mak

Now that the Makefile knows all the basic information about the testbench,
include tool-specific makefiles to implement simulation targets. Currently the
following simulator makefiles exits:

- `<repo>/fpga/tools/make/viv_simulator.mak`<br>
  This makefile supports both Vivado and ModelSim simulators.