Verissimo SystemVerilog Testbench Linter User Guide
Rev. 24.1.5, 13 March 2024

7.2 Custom Report Examples

Example 1 - CSV Report Template

,Status,Rule Title, Name, ID, Severity, Category
,,,,,,
<#list linter.getChecks() as check>
,${check.getStatus()},"${check.getTitle()?replace("\"","\'")}","${check.getName()}","${check.getId()}",${check.getSeverity()},"${check.getCategory()}" 
<#if !check.getHits().isEmpty()>
Hits: ,Details,Severity,File,Line
<#list check.getHits() as hit>
, "${hit.getDetails()}","${hit.getSeverity()}",${hit.getFile()},${hit.getLine()}
</#list>
,,,,
</#if>
</#list>
,,,,,
,Hits,
,ID, Name, Details, Severity, File, Line, Annotation Name, Annotation Value
,,,,,
<#list linter.getHits() as hit> 
${hit_index + 1},"${hit.getCheck().getId()}","${hit.getCheck().getName()}","${hit.getDetails()}","${hit.getSeverity()}",${hit.getFile()},${hit.getLine()},,
   <#list hit.getAnnotations()?keys as key>
       ,,,,,,,${key}, "${hit.getAnnotations()[key]}"
   </#list> 
</#list>

,Files,
,File, Line, Name, Severity, Description
,,,,
<#list linter.getFiles() as file> 
,${file.getName()},${file.isPreWaivedFor("ALL_CHECKS")},,,,
<#if !file.getHits().isEmpty()>
<#list file.getHits() as hit>
,,${hit.getLine()},"${hit.getCheck().getName()}","${hit.getSeverity()}","${hit.getDetails()}"
</#list>
,,,,
</#if>
</#list>
,,,,
,Summary,
,Total rules, ${linter.getChecks().size()}
,Checks passed, ${linter.getChecksSummary().getNofPassed()}
,Checks failed, ${linter.getChecksSummary().getNofErrors()}
,Checks warnings, ${linter.getChecksSummary().getNofWarnings()}
,Checks infos, ${linter.getChecksSummary().getNofInfos()}
,Checks disabled, ${linter.getChecksSummary().getNofDisabled()}
,Checks nonexistent, ${linter.getChecksSummary().getNofNonexistent()}
,Checks duplicate, ${linter.getChecksSummary().getNofDuplicate()}
,,,,,,
,Hits failed, "${linter.getHitsSummary().getNofErrors()}"
,Hits warnings, "${linter.getHitsSummary().getNofWarnings()}"
,Hits infos, "${linter.getHitsSummary().getNofInfos()}"
,Hits disabled, "${linter.getHitsSummary().getNofDisabled()}"
,,,,,,
<#if linter.isPassed() == true>
   ,LINT PASSED,
<#else>
   ,LINT FAILED,
</#if>
,Custom report generated by, ${linter.getEnvVar("$USER")} 

The resulting CSV file will look like this:

' Example 2 - XML Report Template'

<report>
<#if (linter.getChecks()?size > 0)>
<#assign printedCategory = linter.getChecks()?first.getCategory()>
<category name="${printedCategory}">
<#list linter.getChecks() as check>
<#if printedCategory != check.getCategory()>
<#assign printedCategory = check.getCategory()>
</category>
<category name="${printedCategory}">
</#if>
<#if (check.getHits()?size > 0)>
<check id="${check.getId()}" name="${check.getName()}" title="${check.getTitle()?xml}" status="${check.getStatus()}" severity="${check.getSeverity()}" autocorrectable="${check.isAutocorrectable()?c}">
<#list check.getHits() as hit>
<hit file="${hit.getFile()}" line="${hit.getLine()}" details="${hit.getDetails()?xml}" severity="${hit.getSeverity()}" />
</#list>
</check>
<#else>
<check id="${check.getId()}" name="${check.getName()}" title="${check.getTitle()?xml}" status="${check.getStatus()}" severity="${check.getSeverity()}" autocorrectable="${check.isAutocorrectable()?c}"/>
</#if>
</#list>
</category>
</#if>
</report>

The resulting XML file will look like this:

<report>
  <category name="XVM Architecture">
    <check id="XVM.2.2.3" name="UVM.2.2.3" title="Driver Has Analysis Port" status="ERROR" severity="ERROR" autocorrectable="false">
      <hit file="/uvm-1.2_ubus/sv/ubus_master_driver.sv" line="28" details="uvm_analysis_port was not found in driver &apos;ubus_master_driver&apos;" severity="ERROR" />
      <hit file="/uvm-1.2_ubus/sv/ubus_slave_driver.sv" line="28" details="uvm_analysis_port was not found in driver &apos;ubus_slave_driver&apos;" severity="ERROR" />
    </check>
    <check id="XVM.2.3.8.1" name="UVM.2.3.8.1" title="A monitor shall access interface signals only through the input ports of a &apos;mon_mp&apos; modport" status="ERROR" severity="ERROR" autocorrectable="false">
      <hit file="/uvm-1.2_ubus/sv/ubus_bus_monitor.sv" line="204" details="Illegal direct interface access: &apos;vif.sig_reset&apos;!" severity="ERROR" />
      <hit file="/uvm-1.2_ubus/sv/ubus_bus_monitor.sv" line="209" details="Illegal direct interface access: &apos;vif.sig_reset&apos;!" severity="ERROR" />
    </check>
  </category>
  <category name="XVM Factory Create">
    <check id="XVM.2.1.4.2.6" name="UVM.2.1.4.2.6" title="Class fields (variables) should be constructed using &quot;UVM create calls&quot;" status="ERROR" severity="ERROR" autocorrectable="false">
      <hit file="/uvm-1.2_ubus/sv/ubus_bus_monitor.sv" line="174" details="&apos;ubus_transfer&apos; is created using new()" severity="ERROR" />
      <hit file="/uvm-1.2_ubus/sv/ubus_slave_monitor.sv" line="106" details="&apos;ubus_transfer&apos; is created using new()" severity="ERROR" />
    </check>
    <check id="XVM.2.1.4.2.7" name="UVM.2.1.4.2.7" title="For all class fields inside a UVM component, the constructed string name must match the field name" status="ERROR" severity="ERROR" autocorrectable="false">
      <hit file="/uvm-1.2_ubus/sv/ubus_bus_monitor.sv" line="174" details="The creation of &apos;trans_collected&apos; does not use the component&apos;s member variable instance name" severity="ERROR" />
      <hit file="/uvm-1.2_ubus/sv/ubus_slave_monitor.sv" line="106" details="The creation of &apos;trans_collected&apos; does not use the component&apos;s member variable instance name" severity="ERROR" />
    </check>
  </category>
</report>

Example 3 - JSON Report Template

<#setting datetime_format="yyyy-MM-dd hh:mm:ss">
<#function toJSON x>
  <#return x?json_string?replace("'","\\'")?replace("/","\\/")>
</#function>
<#assign dateTime = .now>
{
"hits": [
<#list linter.getHits() as hit>
{
"categoryName":"${hit.getCheck().getCategory()}",
"categoryDescription":<#if (hit.getCheck().getCategoryDescription())?has_content>"${hit.getCheck().getCategoryDescription()}"<#else>"''"</#if>,
"checkName":"${hit.getCheck().getName()}",
"checkTitle":"'${toJSON(hit.getCheck().getTitle())}'",
"checkDescription":"'${toJSON(hit.getCheck().getDescription())}'",
"message":"'${toJSON(hit.getDetails())}'",
"severity":"${hit.getSeverity()}",
"file":"${hit.getFile()}",
"line":"${hit.getLine()}",
"date":"${dateTime}"
}<#sep>,</#sep>
</#list>
]
}

The resulting JSON file will look like this

{
"hits": [
{
"categoryName":"XVM Architecture",
"categoryDescription":"''",
"checkName":"UVM.2.2.3",
"checkTitle":"'Driver Has Analysis Port'",
"checkDescription":"'At least one analysis port must be provided in the driver class into which the sequence item should be placed with each item operation.\nThis allows analysis components to connect directly to the driver in case a monitor is unable to fully reconstruct the item.\nExample:\n...\ntask run();\n  forever begin\n    seq_item_port.get_next_item(item);\n    request_analysis_port.write(item);\n    ...\n  end\nendtask: run'",
"message":"'uvm_analysis_port was not found in driver \'ubus_master_driver\''",
"severity":"ERROR",
"file":"/uvm-1.2_ubus/sv/ubus_master_driver.sv",
"line":28,
"date":"2017-07-24 07:59:41"
},
{
"categoryName":"XVM Architecture",
"categoryDescription":"''",
"checkName":"UVM.2.2.3",
"checkTitle":"'Driver Has Analysis Port'",
"checkDescription":"'At least one analysis port must be provided in the driver class into which the sequence item should be placed with each item operation.\nThis allows analysis components to connect directly to the driver in case a monitor is unable to fully reconstruct the item.\nExample:\n...\ntask run();\n  forever begin\n    seq_item_port.get_next_item(item);\n    request_analysis_port.write(item);\n    ...\n  end\nendtask: run'",
"message":"'uvm_analysis_port was not found in driver \'ubus_slave_driver\''",
"severity":"ERROR",
"file":"/uvm-1.2_ubus/sv/ubus_slave_driver.sv",
"line":"28",
"date":"2017-07-24 07:59:41"
},
{
"categoryName":"XVM Architecture",
"categoryDescription":"''",
"checkName":"UVM.2.3.8.1",
"checkTitle":"'A monitor shall access interface signals only through the input ports of a \'mon_mp\' modport'",
"checkDescription":"'The \'mon_mp\' port directions should all be configured to input.\n This simulation runtime checks ensure that the monitor will never drive the bus.'",
"message":"'Illegal direct interface access: \'vif.sig_reset\'!'",
"severity":"ERROR",
"file":"/uvm-1.2_ubus/sv/ubus_bus_monitor.sv",
"line":"204",
"date":"2017-07-24 07:59:41"
},
{
"categoryName":"XVM Architecture",
"categoryDescription":"''",
"checkName":"UVM.2.3.8.1",
"checkTitle":"'A monitor shall access interface signals only through the input ports of a \'mon_mp\' modport'",
"checkDescription":"'The \'mon_mp\' port directions should all be configured to input.\n This simulation runtime checks ensure that the monitor will never drive the bus.'",
"message":"'Illegal direct interface access: \'vif.sig_reset\'!'",
"severity":"ERROR",
"file":"/uvm-1.2_ubus/sv/ubus_bus_monitor.sv",
"line":"209",
"date":"2017-07-24 07:59:41"
},