1
0
rocket-chip/src/main/scala/rocketchip/TestHarness.scala

168 lines
4.5 KiB
Scala
Raw Normal View History

// See LICENSE for license details.
package rocketchip
import Chisel._
import cde.{Parameters, Field}
import rocket.Util._
import junctions._
class TestHarness(implicit p: Parameters) extends Module {
val io = new Bundle {
val success = Bool(OUTPUT)
}
val dut = Module(new Top(p))
// This test harness isn't especially flexible yet
require(dut.io.mem_clk.isEmpty)
require(dut.io.mem_rst.isEmpty)
require(dut.io.mem_ahb.isEmpty)
require(dut.io.mem_tl.isEmpty)
require(dut.io.bus_clk.isEmpty)
require(dut.io.bus_rst.isEmpty)
require(dut.io.mmio_clk.isEmpty)
require(dut.io.mmio_rst.isEmpty)
require(dut.io.mmio_ahb.isEmpty)
require(dut.io.mmio_tl.isEmpty)
require(dut.io.extra.elements.isEmpty)
for (int <- dut.io.interrupts)
int := false
if (dut.io.mem_axi.nonEmpty) {
val memSize = p(GlobalAddrMap)("mem").size
require(memSize % dut.io.mem_axi.size == 0)
for (axi <- dut.io.mem_axi)
Module(new SimAXIMem(memSize / dut.io.mem_axi.size)).io.axi <> axi
}
if (p(IncludeJtagDTM)) {
val jtag_vpi = Module (new JtagVpi)
dut.io.jtag.get <> jtag_vpi.io.jtag
// To be proper,
// TRST should really be synchronized
// with TCK. But this is a fairly
// accurate representation of how
// HW may drive this signal.
// Neither OpenOCD nor JtagVPI drive TRST.
dut.io.jtag.get.TRST := reset
jtag_vpi.io.enable := ~reset
jtag_vpi.io.init_done := ~reset
This commit adds Logic & test support for JTAG implementation of Debug Transport Module. - The DebugTransportModuleJtag is written in Verilog. It probably could be written in Chisel except for some negative edge clocking requirement. - For real implementations, the AsyncDebugBusTo/From is insufficient. This commit includes cases where they are used, but because they are not reset asynchronously, a Verilog 'AsyncMailbox' is used when p(AsyncDebug) is false. - This commit differs significantly from the earlier attempt. Now, the DTM and synchronizer is instantiated within Top, as it is a real piece of hardware (vs. test infrastructure). -TestHarness takes a parameter vs. creating an entirely new TestHarness class. It does not make sense to instantiate TestHarness when p(IncludeJtagDTM) is false, and it would not make sense to insantiate some other TestHarness if p(IncludeJtagDTM) is true. To build Verilog which includes the JtagDTM within Top: make CONFIG=WithJtagDTM_... To test using gdb->OpenOCD->jtag_vpi->Verilog: First, install openocd (included in this commit) ./bootstrap ./configure --prefix=$OPENOCD --enable-jtag-vpi make make install Then to run a simulation: On a 32-bit core: $(ROCKETCHIP)/riscv-tools/riscv-tests/debug/gdbserver.py \ --run ./simv-TestHarness-WithJtagDTM_... \ --cmd="$OPENOCD/bin/openocd --s $OPENOCD/share/openocd/scripts/" \ --freedom-e300-sim \ SimpleRegisterTest.test_s0 On a 64-bit core: $(ROCKETCHIP)/riscv-tools/riscv-tests/debug/gdbserver.py \ --run ./simv-TestHarness-WithJtagDTM_... \ --cmd="$OPENOCD/bin/openocd --s $OPENOCD/share/openocd/scripts/" \ --freedom-u500-sim \ SimpleRegisterTest.test_s0
2016-08-19 23:01:33 +02:00
// Success is determined by the gdbserver
// which is controlling this simulation.
io.success := Bool(false)
}
else {
val dtm = Module(new SimDTM)
dut.io.debug.get <> dtm.io.debug
This commit adds Logic & test support for JTAG implementation of Debug Transport Module. - The DebugTransportModuleJtag is written in Verilog. It probably could be written in Chisel except for some negative edge clocking requirement. - For real implementations, the AsyncDebugBusTo/From is insufficient. This commit includes cases where they are used, but because they are not reset asynchronously, a Verilog 'AsyncMailbox' is used when p(AsyncDebug) is false. - This commit differs significantly from the earlier attempt. Now, the DTM and synchronizer is instantiated within Top, as it is a real piece of hardware (vs. test infrastructure). -TestHarness takes a parameter vs. creating an entirely new TestHarness class. It does not make sense to instantiate TestHarness when p(IncludeJtagDTM) is false, and it would not make sense to insantiate some other TestHarness if p(IncludeJtagDTM) is true. To build Verilog which includes the JtagDTM within Top: make CONFIG=WithJtagDTM_... To test using gdb->OpenOCD->jtag_vpi->Verilog: First, install openocd (included in this commit) ./bootstrap ./configure --prefix=$OPENOCD --enable-jtag-vpi make make install Then to run a simulation: On a 32-bit core: $(ROCKETCHIP)/riscv-tools/riscv-tests/debug/gdbserver.py \ --run ./simv-TestHarness-WithJtagDTM_... \ --cmd="$OPENOCD/bin/openocd --s $OPENOCD/share/openocd/scripts/" \ --freedom-e300-sim \ SimpleRegisterTest.test_s0 On a 64-bit core: $(ROCKETCHIP)/riscv-tools/riscv-tests/debug/gdbserver.py \ --run ./simv-TestHarness-WithJtagDTM_... \ --cmd="$OPENOCD/bin/openocd --s $OPENOCD/share/openocd/scripts/" \ --freedom-u500-sim \ SimpleRegisterTest.test_s0
2016-08-19 23:01:33 +02:00
// Todo: enable the usage of different clocks
// to test the synchronizer more aggressively.
val dtm_clock = clock
val dtm_reset = reset
This commit adds Logic & test support for JTAG implementation of Debug Transport Module. - The DebugTransportModuleJtag is written in Verilog. It probably could be written in Chisel except for some negative edge clocking requirement. - For real implementations, the AsyncDebugBusTo/From is insufficient. This commit includes cases where they are used, but because they are not reset asynchronously, a Verilog 'AsyncMailbox' is used when p(AsyncDebug) is false. - This commit differs significantly from the earlier attempt. Now, the DTM and synchronizer is instantiated within Top, as it is a real piece of hardware (vs. test infrastructure). -TestHarness takes a parameter vs. creating an entirely new TestHarness class. It does not make sense to instantiate TestHarness when p(IncludeJtagDTM) is false, and it would not make sense to insantiate some other TestHarness if p(IncludeJtagDTM) is true. To build Verilog which includes the JtagDTM within Top: make CONFIG=WithJtagDTM_... To test using gdb->OpenOCD->jtag_vpi->Verilog: First, install openocd (included in this commit) ./bootstrap ./configure --prefix=$OPENOCD --enable-jtag-vpi make make install Then to run a simulation: On a 32-bit core: $(ROCKETCHIP)/riscv-tools/riscv-tests/debug/gdbserver.py \ --run ./simv-TestHarness-WithJtagDTM_... \ --cmd="$OPENOCD/bin/openocd --s $OPENOCD/share/openocd/scripts/" \ --freedom-e300-sim \ SimpleRegisterTest.test_s0 On a 64-bit core: $(ROCKETCHIP)/riscv-tools/riscv-tests/debug/gdbserver.py \ --run ./simv-TestHarness-WithJtagDTM_... \ --cmd="$OPENOCD/bin/openocd --s $OPENOCD/share/openocd/scripts/" \ --freedom-u500-sim \ SimpleRegisterTest.test_s0
2016-08-19 23:01:33 +02:00
dtm.io.clk := dtm_clock
dtm.io.reset := dtm_reset
if (dut.io.debug_clk.isDefined)
dut.io.debug_clk.get := dtm_clock
if (dut.io.debug_rst.isDefined)
dut.io.debug_rst.get := dtm_reset
io.success := dut.io.success.getOrElse(dtm.io.exit === 1)
when (dtm.io.exit >= 2) {
printf("*** FAILED *** (exit code = %d)\n", dtm.io.exit >> 1)
stop(1)
}
}
2016-08-20 03:57:34 +02:00
for (bus_axi <- dut.io.bus_axi) {
bus_axi.ar.valid := Bool(false)
bus_axi.aw.valid := Bool(false)
bus_axi.w.valid := Bool(false)
bus_axi.r.ready := Bool(false)
bus_axi.b.ready := Bool(false)
}
for (mmio_axi <- dut.io.mmio_axi) {
val slave = Module(new NastiErrorSlave)
slave.io <> mmio_axi
}
}
class SimAXIMem(size: BigInt)(implicit p: Parameters) extends Module {
val io = new Bundle {
val axi = new NastiIO().flip
}
val rValid = Reg(init = Bool(false))
val ar = RegEnable(io.axi.ar.bits, io.axi.ar.fire())
io.axi.ar.ready := !rValid
when (io.axi.ar.fire()) { rValid := true }
when (io.axi.r.fire()) {
assert(ar.burst === NastiConstants.BURST_INCR)
ar.addr := ar.addr + (UInt(1) << ar.size)
ar.len := ar.len - 1
when (ar.len === UInt(0)) { rValid := false }
}
val w = io.axi.w.bits
require((size * 8) % w.data.getWidth == 0)
val depth = (size * 8) / w.data.getWidth
val mem = Mem(depth.toInt, w.data)
val wValid = Reg(init = Bool(false))
val bValid = Reg(init = Bool(false))
val aw = RegEnable(io.axi.aw.bits, io.axi.aw.fire())
io.axi.aw.ready := !wValid && !bValid
io.axi.w.ready := wValid
when (io.axi.b.fire()) { bValid := false }
when (io.axi.aw.fire()) { wValid := true }
when (io.axi.w.fire()) {
assert(aw.burst === NastiConstants.BURST_INCR)
aw.addr := aw.addr + (UInt(1) << aw.size)
aw.len := aw.len - 1
when (aw.len === UInt(0)) {
wValid := false
bValid := true
}
def row = mem((aw.addr >> log2Ceil(w.data.getWidth/8))(log2Ceil(depth)-1, 0))
val mask = FillInterleaved(8, w.strb)
val newData = mask & w.data | ~mask & row
row := newData
}
io.axi.b.valid := bValid
io.axi.b.bits.id := aw.id
io.axi.b.bits.resp := UInt(0)
io.axi.r.valid := rValid
io.axi.r.bits.id := ar.id
io.axi.r.bits.data := mem((ar.addr >> log2Ceil(w.data.getWidth/8))(log2Ceil(depth)-1, 0))
io.axi.r.bits.resp := UInt(0)
io.axi.r.bits.last := ar.len === UInt(0)
}
class SimDTM(implicit p: Parameters) extends BlackBox {
val io = new Bundle {
val clk = Clock(INPUT)
val reset = Bool(INPUT)
val debug = new uncore.devices.DebugBusIO
val exit = UInt(OUTPUT, 32)
}
}
class JtagVpi(implicit val p: Parameters) extends BlackBox {
val io = new Bundle {
val jtag = new JtagIO(false)
val enable = Bool(INPUT)
val init_done = Bool(INPUT)
}
}