Skip to content

Getting Started

Anastasiia Butko edited this page Jun 13, 2018 · 3 revisions

Dependencies

  • sbt
  • chisel3 (uploaded by sbt automatically)
  • clang++ or g++
  • verilator (v.3.904 or earlier)

How to include VTE to your chisel project?

Get a chisel3 template project from chisel-template and enter the directory:

cd MyChiselProject/

Adding the VTE submodule. Add a following line to the build.sbt:

unmanagedSourceDirectories in Compile += baseDirectory.value / "/vte"

Create the .gitmodule file:

touch .gitmodules

Add the following lines to the .gitmodule file:

[submodule "vte"]
         path = vte
         url = https://github.com/lbnlcomputerarch/vte.git

Run the following command to add the VTE submodule:

git submodule update --init

or

git submodule add https://github.com/lbnlcomputerarch/vte.git vte

Generate C++ testbench files using VTE Driver in Main.scala

Create a Main.scala file in src/main/scala/ that contains the following code:

package gcd
 
import chisel3._
import vte._
 
object Main {
  def main(args: Array[String]) {
    var moduleName: String = "gcd"
    val moduleToTest = () => new GCD
    VDriver(moduleToTest)	
  }
}

Run the sbt command:

sbt run

You will see the following output:

...
[info] Running gcd.Main 
[info] [0.003] Elaborating design...
[info] [0.100] Done elaborating.
Total FIRRTL Compile Time: 855.4 ms
verilator 
./MyChiselProject/src/test/cpp/gcd/testbench.cpp ./MyChiselProject/test_run_dir/gcd.GCD148322558/bits.cpp --cc ./MyChiselProject/test_run_dir/gcd.GCD148322558/GCD.v --assert -Wno-fatal -Wno-WIDTH -Wno-STMTDLY --trace -O1 --top-module GCD +define+TOP_TYPE=VGCD +define+PRINTF_COND=!GCD.reset +define+STOP_COND=!GCD.reset -CFLAGS -std=c++11 -Wno-undefined-bool-conversion -pedantic -O1 -DTOP_TYPE=VGCD -DVL_USER_FINISH -include VGCD.h --compiler clang -Mdir ./MyChiselProject/test_run_dir/gcd.GCD148322558 --exe ./MyChiselProject/test_run_dir/gcd.GCD148322558/GCD_main.cpp
[success] Total time: 13 s, completed Feb 12, 2018 2:33:27 PM

All simulation files are now located in the directory: test_run_dir/gcd.GCD148322558

All the input/output bundles as well as their parameters are listed in GCD_testbench.h:

class GCD_testbench : public Testbench<VGCD> {
public:
    Verilatorgcd_GCD__anon_1 io;
    GCD_testbench(): io(VerilatorCData("io_outputValid", 1, &dut->io_outputValid),
                        VerilatorSData("io_outputGCD", 16, &dut->io_outputGCD),
                        VerilatorCData("io_loadingValues", 1, &dut->io_loadingValues),
                        VerilatorSData("io_value2", 16, &dut->io_value2),
                        VerilatorSData("io_value1", 16, &dut->io_value1)) {
    }
    void run();
};

The main testbench file GCD_testbench.cpp contains an empty run function:

#include "GCD_testbench.h"
 
void GCD_testbench::run() {
}

Writing peek/pook tests using VTE

VTE provides similar to chisel3 IOTesters interface to test modules written in Chisel. It supports poke, expect and step functions. Multiple tests can be written in different *.cpp files and placed in a src/test/cpp/moduleName folder. These files can be used as an option in VDriver execution in Main.scala file to generate a non-empty *_testbench::run(){} function as follow:

package gcd
 
import chisel3._
import vte._
 
object Main {
  def main(args: Array[String]) {
    var moduleName: String = "gcd"
    val moduleToTest = () => new GCD
    VDriver(moduleToTest, 
            testbenchCppFileName = s"src/test/cpp/${moduleName}/testbench.cpp")	
  }
}

In the testbench.cpp file we write a sequence of test instructions:

#include "GCD_testbench.h"
 
struct expectGCD {
     int expected_gcd;
     int steps;
};
 
expectGCD computeGcd(int a, int b){
  int x = a;
  int y = b;
  int depth = 1;
 
  while(y > 0) {
    if (x > y) {
      x -= y;
    }
    else {
      y -= x;
    }
    depth += 1;
  }
  expectGCD result = {x, depth};
  return result;
}
 
void GCD_testbench::run() {
 
  expectGCD resultGCD;
 
  for (int i = 1; i < 40; i = i + 3) {
    for (int j = 1; j < 40; j = j + 7) {
      poke(io.value1, i);
      poke(io.value2, j);
      poke(io.loadingValues, 1);
      step(1);
      poke(io.loadingValues, 0);
 
      resultGCD = computeGcd(i, j);
 
      step(resultGCD.steps - 1);
      expect(io.outputGCD, resultGCD.expected_gcd);
      expect(io.outputValid, 1);   
    }
  }
}

Compile and run VTE tester

To compile the tester file simply go to the MyChiselProject/test_run_dir/gcd.GCD148322558 folder and tape:

make -f VGCD.mk

That will generate the VGCD executable file, which you can run as follow:

./VGCD

Did it work?

You should see a whole bunch of output that ends with something like the following lines:

...
EXPECT AT 959	io_outputGCD got 0x1 expected 0x1 PASS
EXPECT AT 959	io_outputValid got 0x1 expected 0x1 PASS
  POKE io_value1 <- 0x25
  POKE io_value2 <- 0x16
  POKE io_loadingValues <- 0x1
STEP 959 -> 960
  POKE io_loadingValues <- 0x0
STEP 960 -> 971
EXPECT AT 971	io_outputGCD got 0x1 expected 0x1 PASS
EXPECT AT 971	io_outputValid got 0x1 expected 0x1 PASS
  POKE io_value1 <- 0x25
  POKE io_value2 <- 0x1d
  POKE io_loadingValues <- 0x1
STEP 971 -> 972
  POKE io_loadingValues <- 0x0
STEP 972 -> 981
EXPECT AT 981	io_outputGCD got 0x1 expected 0x1 PASS
EXPECT AT 981	io_outputValid got 0x1 expected 0x1 PASS
  POKE io_value1 <- 0x25
  POKE io_value2 <- 0x24
  POKE io_loadingValues <- 0x1
STEP 981 -> 982
  POKE io_loadingValues <- 0x0
STEP 982 -> 1019
EXPECT AT 1019	io_outputGCD got 0x1 expected 0x1 PASS
EXPECT AT 1019	io_outputValid got 0x1 expected 0x1 PASS
RAN 1019 CYCLES PASSED