Use Templates to Create SystemVerilog DPI and UVM Components
This example shows how to generate SystemVerilog direct programming interface (DPI) and universal verification methodology (UVM) components from MATLAB® functions using built-in templates. This example also reviews the generated SystemVerilog and how it relates to the template. This example teaches you basic template capabilities, that you can use to create a custom template.
HDL Verifier™ provides built-in templates that cover most use cases. If you require a different template, create a custom template using concepts shown in this example.
Introduction
In this example, you use a sine wave MATLAB function as a design under test (DUT), and follow the steps to generate a SystemVerilog DPI component by using the built-in sequential DPI template. After generating a SystemVerilog DPI component, you generate a UVM scoreboard by using the built-in UVM scoreboard template to check the output of the DUT. From this example, you learn how to:
Define a template variable by using the dictionary.
Assign a value to a template variable.
Override a template variable from the svdpiConfiguration object.
Represent a collection of ports as a group in the template.
Generate SystemVerilog DPI Component
The sequential module template generates the Systemverilog DPI component from a sine wave MATLAB function.
To generate your component from the template, first create a svdpiConfiguration object.
svcfg=svdpiConfiguration
svcfg = svdpiConfiguration with properties: ComponentKind: 'sequential-module' FloatingPointTolerance: 4.4409e-16 CoderConfiguration: [1×1 coder.EmbeddedCodeConfig] PreserveStructures: 0 ScalarizePorts: 0 ComponentTypeName: '' TestBenchTypeName: '' MATLABFunctionName: '' PortGroups: [] ComponentTemplateFiles: {'/mathworks/devel/bat/filer/batfs2566-0/Bdoc25a.2864802/build/runnable/matlab/toolbox/hdlverifier/dpigenerator/rtw/SequentialModuleML.tlc'} TestBenchTemplateFiles: {'/mathworks/devel/bat/filer/batfs2566-0/Bdoc25a.2864802/build/runnable/matlab/toolbox/hdlverifier/dpigenerator/rtw/SequentialTestBenchML.tlc'} TemplateDictionary: []
By default, the component kind is set to 'sequential-module
'
The 'sequential-module
' uses the SequentialModuleML.tlc
template file to generate the component. You can find the templates at this location.
templateLocation = fileparts(svcfg.ComponentTemplateFiles{1});
Next, generate the component using dpigen
function.
dpigen sineWaveGen -testbench sineWaveGen_tb -args {0,0} -config svcfg
### Generating DPI-C Wrapper sineWaveGen_dpi.c ### Generating DPI-C Wrapper header file sineWaveGen_dpi.h ### Generating makefiles for: sineWaveGen_dpi ### Running simulation to capture input and expected outputs for a standalone testbench. ### This may take some time... Code generation successful.
### ...DONE with test-vector capture. ### Running simulation to capture input and expected outputs for a standalone testbench. ### This may take some time... Code generation successful.
### ...DONE with test-vector capture. ### Compiling the DPI Component Code generation successful.
Define and Assign Template Variables
After generating your DPI component, review the generated SystemVerilog files, and relate them to the template. Open these two template files.
edit(svcfg.ComponentTemplateFiles{1});
edit(fullfile(fileparts(svcfg.ComponentTemplateFiles{1}),'SystemVerilogTemplateLibrary.tlc'));
Open the SystemVerilog DPI component file that you generated.
edit(fullfile('codegen','dll','sineWaveGen','sineWaveGen.sv'));
To understand how to assign values to template variables, compare the generated component file to the template file. The sineWaveGen.sv
file is created from the following section of the SequentialModuleML.tlc
template file. It contains a template variable SVTLCommonHeader
, and also includes the contents of the SystemVerilogTemplateLibrary.tlc
file.
The template variable SVTLCommonHeader
is defined in the SystemVerilogTemplateLibrary.tlc
file using %openfile and %closefile
directives.
After defining the template variable in the local dictionary, you use the variable in your template file with the format of %<
variable_name
>
. In this example, the variable is %<SVTLCommonHeader>
. During code generation, the template variable is replaced by its defined content. In this DPI component, the sineWaveGen.sv
includes the content of the SVTLCommonHeader
template variable.
Generate UVM Scoreboard
A UVM scoreboard is a UVM component. Typically, the scoreboard accepts inputs from the DUT through a monitor, and from a golden reference model (predictor). For more information about the UVM test bench, see UVM Component Generation Overview.
In this part of the example, you generate a UVM scoreboard, which compares the output of the sine wave generator (DUT) with the output of a golden reference. To monitor the output, the scoreboard uses a normalized sine wave function as a golden reference, and the amplitude of the DUT sine wave as a parameter of the scoreboard configuration object.
On the MATLAB command line, set the component kind to 'uvm-scoreboard'
.
clear svcfg; svcfg=svdpiConfiguration; svcfg.ComponentKind = 'uvm-scoreboard'
svcfg = svdpiConfiguration with properties: ComponentKind: 'uvm-scoreboard' FloatingPointTolerance: 4.4409e-16 CoderConfiguration: [1×1 coder.EmbeddedCodeConfig] PreserveStructures: 0 ScalarizePorts: 0 ComponentTypeName: '' TestBenchTypeName: '' MATLABFunctionName: '' PortGroups: [] ComponentTemplateFiles: {'/mathworks/devel/bat/filer/batfs2566-0/Bdoc25a.2864802/build/runnable/matlab/toolbox/hdlverifier/dpigenerator/rtw/ScoreboardComponentML.tlc'} TestBenchTemplateFiles: {'/mathworks/devel/bat/filer/batfs2566-0/Bdoc25a.2864802/build/runnable/matlab/toolbox/hdlverifier/dpigenerator/rtw/ScoreboardTestBenchML.tlc'} TemplateDictionary: []
Open the scoreboard template file.
edit(svcfg.ComponentTemplateFiles{:});
The template variable InputTransTypeName
is a predefined variable in the global dictionary. The default value is scoreboard_input_trans
. You can use svdpiConfiguration
object to override the value of this template variable:
svcfg.TemplateDictionary = {'InputTransTypeName','sineWaveTrans'};
The tempalte variable defined in the global dictionary can be use by the template file with the format of %<gtd.
variable_name
>
.
This scoreboard template has three port groups: PREDICTOR_INPUTS
, MONITOR_INPUTS
, and CONFIG_OBJECT_INPUTS
. Before generating the code use the svdpiConfiguration
to specify which port belongs to which port group. For this example, the sineWaveCheck.m
file has 5 inputs: in1FromMon
, in2FromMon
, inFromPred
, amp1
, and amp2
. The in1FromMon
, and in2FromMon
inputs belong to the MONITOR_INPUTS
group. The inFromPred
input belongs to the PREDICTOR_INPUTS
group. The amp1
, and amp2
inputs belong to the CONFIG_OBJECT_INPUTS
group. Assign each input to its respective port group.
addPortGroup(svcfg,'MONITOR_INPUTS',{'in1FromMon','in2FromMon'}); addPortGroup(svcfg,'PREDICTOR_INPUTS',{'inFromPred'}); addPortGroup(svcfg,'CONFIG_OBJECT_INPUTS',{'amp1','amp2'});
Generate a UVM scoreboard component.
dpigen sineWaveCheck -testbench sineWaveCheck_tb -args {zeros(1,100),zeros(1,100),zeros(1,100),0,0} -config svcfg
### Generating DPI-C Wrapper sineWaveCheck_dpi.c ### Generating DPI-C Wrapper header file sineWaveCheck_dpi.h ### Generating makefiles for: sineWaveCheck_dpi ### Running simulation to capture input and expected outputs for a standalone testbench. ### This may take some time... Code generation successful.
### ...DONE with test-vector capture. ### Running simulation to capture input and expected outputs for a standalone testbench. ### This may take some time... Code generation successful.
### ...DONE with test-vector capture. ### Compiling the DPI Component Code generation successful.
Open the generated scoreboard component file.
edit(fullfile('codegen','dll','sineWaveCheck','sineWaveCheck.sv'))
HDL Verifier assigns the value of InputTransTypeName
as sineWaveTrans
in the generated sineWaveCheck.sv
, and so all the related items use sineWaveTrans
.
The template iterates over a port group to emit code using %foreach
and %endforeach
directives. In this example, the code block iterates all the ports in the monitor port group and uses its port name to create SystemVerilog code.
Make sure that ModelSim® is on the system path, and then enter this directive to navigate to the test bench directory.
cd(fullfile('codegen','dll','sineWaveCheck','dpi_tb'))
Run the test bench and verify the generated scoreboard component in ModelSim.
!vsim < run_tb_mq.do
Note that the test passed in HDL simulation.
# UVM_INFO @ 0: reporter [RNTST] Running test sineWaveCheck_tb_test...
# UVM_INFO ./sineWaveCheck_tb.sv(98) @ 40: uvm_test_top [WRITING_INPUTS] writing scoreboard inputs
# UVM_INFO ./sineWaveCheck_tb.sv(104) @ 41: uvm_test_top [GETTING_RESULT] getting scoreboard result
# **************TEST COMPLETED (PASSED)**************
# ** Note: $finish : ./sineWaveCheck_tb.sv(223)
# Time: 42 ns Iteration: 0 Instance: /sineWaveCheck_tb
# End time: 16:48:55 on Jan 18,2023, Elapsed time: 0:00:02
# Errors: 0, Warnings: 0
Summary
This example shows how to generate SystemVerilog DPI and UVM components from MATLAB functions using built-in templates. From this example, you learn how to:
define template variables by using the dictionary
override the default value of a template variable by using the svdpiConfiguration object
represent a collection of ports as a group in the template
You can use these methods to create your own template or copy and modify the built-in template to suit your needs. For more information about the template language syntax see Custom Template Language Syntax.