Skip to content

Commit

Permalink
Initial stab at adding verilog testbench generator for jtag
Browse files Browse the repository at this point in the history
  • Loading branch information
grebe committed Apr 11, 2017
1 parent e180514 commit eed218e
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 6 deletions.
3 changes: 3 additions & 0 deletions Makefrag
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ $(build_dir)/$(long_name).fir $(build_dir)/$(long_name).prm $(build_dir)/$(long_
mkdir -p $(build_dir)
cd $(base_dir) && $(SBT) "run-main $(PROJECT).Generator $(CHISEL_ARGS) $(build_dir) $(PROJECT) $(MODEL) $(CFG_PROJECT) $(CONFIG)"

$(base_dir)/vsrc/JtagTestHarness.v: $(build_dir)/$(long_name).fir
cd $(base_dir) && $(SBT) "run-main craft.JtagTestHarnessApp"

$(build_dir)/$(long_name).v $(build_dir)/$(long_name).harness.v $(build_dir)/$(long_name).conf: $(build_dir)/$(long_name).fir $(FIRRTL_JAR)
cd $(base_dir) && $(SBT) "run-main barstools.tapeout.transforms.GenerateTopAndHarness -i $< --top-o $(build_dir)/$(long_name).v --harness-o $(build_dir)/$(long_name).harness.v --syn-top $(VLSICORE) --harness-top $(MODEL) --seq-mem-flags \"-o:$(build_dir)/$(long_name).conf\" --list-clocks \"-o:$(build_dir)/$(long_name).domains\" --anno-file $(build_dir)/$(long_name).anno"

Expand Down
58 changes: 58 additions & 0 deletions src/main/resources/JtagTestHarness.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
`timescale {{timeUnitPs}}ps / {{timePrecisionFs}}fs
`define CLK_PERIOD {{clkMul}}
`define HALF_CLK_PERIOD {{clkHalfMul}}
`define RESET_TIME {{resetTime}}
`define INIT_TIME {{initTime}}

`define expect(nodeName, nodeVal, expVal, cycle, message) \
if (nodeVal !== expVal) begin \
$display("\t ASSERTION ON %s FAILED @ CYCLE = %d, 0x%h != EXPECTED 0x%h\n", nodeName,cycle,nodeVal,expVal); \
$display(message); \
$stop; \
end

module {{moduleName}}(
// Inputs of DUT, outputs to this testbench
{{#each inputs}}output {{signed}}[{{width}}-1:0] {{name}},
{{/each}}
// Outputs of DUT, inputs to this testbench
{{#each outputs}}input {{signed}}[{{width}}-1:0] {{name}},
{{/each}}
output finish
);

integer cycle = 0;
reg clock = 1;
reg reset = 1;

{{#each inputs}}reg {{signed}}[{{width}}-1:0] reg_{{name}} = 0;
{{/each}}

{{#each inputs}}assign {{name}} = reg_{{name}};
{{/each}}

always #`HALF_CLK_PERIOD clock = ~clock;

initial begin
#`RESET_TIME
forever #`CLK_PERIOD cycle = cycle + 1;
end

initial begin
#`INIT_TIME reset = 0;
{{#each statements}}
{{#if step}}// step {{step_n}}
#({{step_n}}*`CLK_PERIOD){{/if}}{{#if reset}}// reset {{reset_n}}
reset = 1;
#({{reset_n}}*`CLK_PERIOD)
reset = 0;{{/if}}{{#if poke}}// poke {{poke_name}} {{poke_value}}
reg_{{poke_name}} = {{poke_value}};{{/if}}{{#if expect}}// expect {{expect_name}} {{expect_value}} {{expect_message}}
`expect("{{expect_name}}", {{expect_name}}, {{expect_value}}, cycle, "{{expect_message}}"){{/if}}{{/each}}

// finish = 1;
{{#if end_on_finish}}
#`CLK_PERIOD $display("\t **Ran through all test vectors**"); $finish;
{{/if}}
end
endmodule

1 change: 1 addition & 0 deletions src/main/scala/craft/JTAG.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ trait JTAGTestLevelIO {
val tdi = Input(Bool())
val tdo = Output(Bool())
val tclk = Input(Bool())
val tdo_driven = Output(Bool())
}

139 changes: 139 additions & 0 deletions src/main/scala/craft/JtagTestHarness.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package craft


import cde._
import chisel3.iotesters._
import chisel3.iotesters.experimental._
import diplomacy._
import dspblocks._
import jtag._
import jtag.test._
import uncore.tilelink._
import _root_.junctions._

import org.scalatest._
object ReportVerilog {
def getResource(name: String):String = {
import scala.io.Source
val stream = getClass.getResourceAsStream(name)
Source.fromInputStream( stream ).getLines.mkString("\n")
}

def writeFile(name: String, contents:String): Unit = {
import java.io.{File, PrintWriter}
val writer = new PrintWriter(new File(name))
writer.write(contents)
writer.close()
}

def apply(stmts: Seq[Statement]): Unit = {
// inputs of the testbench, outputs of the DUT
val inputStrs = Set(stmts.map(_ match {
case PokeStatement(s, _) => Some(s)
case _ => None
}).flatten: _*)
// outputs of the testbench, inputs of the DUT
val outputStrs = Set(stmts.map(_ match {
case ExpectStatement(s, _, _) => Some(s)
case _ => None
}).flatten: _*) -- inputStrs
object JtagTest {
val moduleName = "JtagTestHarness"
val timeUnitPs = 1
val timePrecisionFs = 100
val clkMul = 16666
val clkHalfMul = clkMul/2
val resetTime = 0
val initTime = 0
val end_on_finish = true
val inputs = inputStrs.map(i => Map(
"width" -> 1,
"signed" -> "",
"name" -> i))
val outputs = outputStrs.map(o => Map(
"width" -> 1,
"signed" -> "",
"name" -> o))
val statements = stmts.map(s => {
val stepMap = s match {
case StepStatement(n) => Map(
"step" -> true,
"step_n" -> n)
case _ => Map(
"step" -> false,
"step_n" -> 0)
}
val resetMap = s match {
case ResetStatement(n) => Map(
"reset" -> true,
"reset_n" -> n)
case _ => Map(
"reset" -> false,
"reset_n" -> 0)
}
val pokeMap = s match {
case PokeStatement(n, v) => Map(
"poke" -> true,
"poke_name" -> n,
"poke_value" -> v)
case _ => Map(
"poke" -> false,
"poke_name" -> "",
"poke_value" -> 0)
}
val expectMap = s match {
case ExpectStatement(n, v, m) => Map(
"expect" -> true,
"expect_name" -> n,
"expect_value" -> v,
"expect_message" -> m)
case _ => Map(
"expect" -> false,
"expect_name" -> "",
"expect_value" -> 0,
"expect_message" -> "")
}
stepMap ++ resetMap ++ pokeMap ++ expectMap
})
}
val testbench: String = {
import com.gilt.handlebars.scala.binding.dynamic._
import com.gilt.handlebars.scala.Handlebars

val template = getResource("/JtagTestHarness.v")
val t= Handlebars(template)
t(JtagTest)
}

writeFile("vsrc/JtagTestHarness.v", testbench)
println(testbench)
}
}

object JtagTestHarnessApp extends App with JtagAxiUtilities {
val p = Parameters.root((new Craft2SimpleConfig).toInstance).alterPartial {
case TLId => "craft-radar"
}
def dut(p: Parameters) = LazyModule(new DspChainWithADC()(p)).module
test(dut(p), testerBackend=chisel3.iotesters.experimental.IntermediateBackend, options = new TesterOptionsManager {
testerOptions = testerOptions.copy(intermediateReportFunc = ReportVerilog.apply _)
interpreterOptions = interpreterOptions.copy(setVerbose = false, writeVCD = true)
}) { implicit t => c =>
implicit val n: HasNastiParameters = c.io.data_axi.ar.bits

c.io.jtag map { j =>
// let the chain come up
step(20)

axiRead(j, BigInt(0x7000L), BigInt(0x0))
step(10)

axiWrite(j, BigInt(0x7000L), BigInt(0x7), id = 1)
step(10)

axiRead(j, BigInt(0x7000L), BigInt(0x7))
step(10)
}
}

}
2 changes: 1 addition & 1 deletion tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ GCC=riscv64-unknown-elf-gcc
CFLAGS=-mcmodel=medany -std=gnu99 -O2 -fno-common -fno-builtin-printf
LDFLAGS=-static -nostdlib -nostartfiles -lgcc

default: memcpy-dma.riscv pwm.riscv noop.riscv fft.riscv adc.riscv pg_prog.riscv
default: memcpy-dma.riscv pwm.riscv noop.riscv fft.riscv adc.riscv pg_prog.riscv spin.riscv

%.o: %.S
$(GCC) $(CFLAGS) -D__ASSEMBLY__=1 -c $< -o $@
Expand Down
3 changes: 3 additions & 0 deletions tests/noop.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#define PWM_DUTY 0x2008
#define PWM_ENABLE 0x2010

#include <stdio.h>

static inline void write_reg(unsigned long addr, unsigned long data)
{
volatile unsigned long *ptr = (volatile unsigned long *) addr;
Expand All @@ -18,4 +20,5 @@ int main(void)
{
int i = 0;
i++;
printf("Oh hai mark");
}
5 changes: 5 additions & 0 deletions tests/spin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
int main(void)
{
while(1);
return 0;
}
32 changes: 27 additions & 5 deletions vsrc/TestDriver.v
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,27 @@ module TestDriver;
end
end

reg trst = 1'b0;
reg tclk;
reg tms;
reg tdi;
reg tdo;
reg tdo_driven;

`ifdef JTAG_HARNESS
JtagTestHarness jtagHarness(
.io_jtag_TMS(tms),
.io_jtag_TCK(tclk),
.io_jtag_TDI(tdi),
.io_jtag_TDO_driven(tdo_driven),
.io_jtag_TDO_data(tdo)
);
`else
tms = 1'b0;
tdi = 1'b0;
tclk = 1'b0;
`endif

wire [1:0] dummy;
TestHarness testHarness(
// TSI clock and reset
Expand All @@ -180,11 +201,12 @@ module TestDriver;
.io_ADCCLKP(dsp_clock),
.io_ADCCLKM(~dsp_clock),
// JTAG
.io_trst(reset),
.io_tclk(1'b0),
.io_tms(1'b0),
.io_tdi(1'b0),
.io_tdo(),
.io_trst(trst),
.io_tclk(tclk),
.io_tms(tms),
.io_tdi(tdi),
.io_tdo(tdo),
.io_tdo_driven(tdo_driven),
// test IO
.io_success(success)
);
Expand Down

0 comments on commit eed218e

Please sign in to comment.