Skip to main content

Toolchain Configuration

The Verik toolchain is implemented as a plugin to the Gradle build system. The plugin registers three Gradle tasks to each Verik project.

  • verik: Run the compiler and importer and generate makefiles for tool targets.
  • verikImport: Import SystemVerilog source files to be used in Verik projects.
  • verikCompile: Generate SystemVerilog output from Verik source files.

The verik Gradle task automatically invokes verikImport and verikCompile if the source files are out-of-date. The toolchain is configured in the Gradle build file build.gradle.kts. The version of the toolchain is set in the plugin block. For local builds of the toolchain set the version to local-SNAPSHOT.

plugins {
kotlin("jvm") version "1.5.31"
id("io.verik.verik-plugin") version "0.1.16"
}

The toolchain is configured with the verik block. The importer, compiler, and targets are each configured with subblocks within the verik block. The top level configuration with default values are shown below.

verik {
debug = false // prints stack traces for debug
maxErrorCount = 60 // maximum error count to display
}

Importer Configuration

The importer is configured with the import block. Default values are shown below.

verik {
import {
importedFiles = listOf() // list of SystemVerilog files to import
includeDirs = listOf() // list of include directories to search
enablePreprocessorOutput = true // show output of preprocessor
suppressedWarnings = ArrayList() // suppressed warnings
promotedWarnings = ArrayList() // promoted warnings
}
}

The list of warnings that can be suppressed or promoted can be found here. The Gradle build file can be configured with arbitrary Kotlin code. Here we set importedFiles to all Verilog files matching *.v in src/main/verilog.

verik {
import {
val importedDir = projectDir.resolve("src/main/verilog").toPath()
importedFiles = Files.walk(importedDir)
.filter { it.endsWith(".v") }
.toList()
}
}

Compiler Configuration

The compiler is configured with the compile block. Default values are shown below.

verik {
compile {
timescale = "1ns / 1ns" // simulation timescale
entryPoints = ArrayList() // qualified name of the points for elaboration
enableDeadCodeElimination = true // enable dead code elimination
labelLines = true // label original line numbers
indentLength = 4 // indent length
wrapLength = 120 // line wrap length
suppressedWarnings = ArrayList() // suppressed warnings
promotedWarnings = ArrayList() // promoted warnings
}
}

By default, if no entry points are specified, all declarations annotated with @Entry are used as entry points for elaboration. The list of warnings that can be suppressed or promoted can be found here.

Target Configuration

The Verik toolchain can generate makefiles for common simulator and synthesis tool targets. They are provided for convenience and the use of these makefiles are optional. The following tool targets are supported.

Xilinx Vivado

The Xilinx Vivado toolchain is configured with the vivado block. We can make use of Vivado IP by providing the .v stub files to the importer and the .xci configuration files to ipConfigFiles. Vivado can be used for simulation, synthesis, or both. Here we target the Arctix-7 FPGA with part number xc7a100tcsg324-3.

verik {
import {
importedFiles = listOf(projectDir.toPath().resolve("ip/BlkMem.v"))
}
vivado {
part = "xc7a100tcsg324-3"
ipConfigFiles = listOf(projectDir.toPath().resolve("ip/BlkMem.xci"))
simTop = "SimTop"
synthTop = "FpgaTop"
constraintsFile = projectDir.toPath().resolve("constraints.xdc")
}
}

Metrics Dsim

The Metrics Dsim simulator is configured with the dsim block. Dsim can compile multiple top-level modules and select one of them for simulation.

verik {
dsim {
compileTops = listOf("AddTest", "SubTest")
sim {
name = "simAdd"
simTop = "AddTest"
}
sim {
name = "simSub"
simTop = "SubTest"
}
}
}

We can use Dsim with the UVM by providing the UVM source files and include directories to the importer and the dsim block. Here we provide the plusarg +UVM_TESTNAME=random_test to select the UVM test at runtime. We use the environment variable UVM_HOME to point to the UVM directory.

verik {
import {
val uvmHome = Paths.get(System.getenv("UVM_HOME"))
importedFiles = listOf(uvmHome.resolve("src/uvm.sv"))
includeDirs = listOf(uvmHome.resolve("src"))
}
dsim {
val uvmHome = Paths.get("\$(UVM_HOME)")
compileTops = listOf("top")
extraFiles = listOf(uvmHome.resolve("src/uvm.sv"))
extraIncludeDirs = listOf(uvmHome.resolve("src"))
dpiLibs = listOf(uvmHome.resolve("src/dpi/libuvm_dpi.so"))
sim {
name = "sim"
plusArgs["UVM_TESTNAME"] = "random_test"
}
}
}

Cadence Xcelium

The Cadence Xcelium simulator is configured with the xrun block. We set the top-level module with top.

verik {
xrun {
top = "top"
}
}

Icarus Verilog

The Icarus Verilog simulator is configured with the iverilog block. We set the top-level module with top.

verik {
iverilog {
top = "top"
}
}