1
0

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
This commit is contained in:
Megan Wachs 2016-08-19 14:01:33 -07:00
parent dd4a50c452
commit 3dd51ff734
5 changed files with 164 additions and 277 deletions

View File

@ -3,7 +3,9 @@ package rocketchip
import Chisel._
import uncore.devices.{DebugBusIO, AsyncDebugBusTo, AsyncDebugBusFrom, DebugBusReq, DebugBusResp, DMKey}
import junctions._
import cde.{Parameters}
import cde.{Parameters, Field}
case object IncludeJtagDTM extends Field[Boolean]
/* JTAG-based Debug Transport Module
* and synchronization logic.

View File

@ -6,7 +6,6 @@ import Chisel._
import cde.{Parameters, Field}
import rocket.Util._
import junctions._
import uncore.devices.{IncludeJtagDTM}
class TestHarness(implicit p: Parameters) extends Module {
val io = new Bundle {
@ -53,16 +52,20 @@ class TestHarness(implicit p: Parameters) extends Module {
dut.io.jtag.get.TRST := reset
jtag_vpi.io.enable := ~reset
jtag_vpi.io.init_done := ~reset
// 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
// Todo: enable the usage of different clocks.
// Todo: enable the usage of different clocks
// to test the synchronizer more aggressively.
val dtm_clock = clock
val dtm_reset = reset
dtm.io.clk := dtm_clock
dtm.io.reset := dtm_reset
if (dut.io.debug_clk.isDefined)

View File

@ -8,7 +8,7 @@ import uncore.util._
import junctions._
import cde.{Parameters, Config, Field}
// *****************************************r
// *****************************************
// Constants which are interesting even
// outside of this module
// *****************************************
@ -264,7 +264,6 @@ class DefaultDebugModuleConfig (val ncomponents : Int, val xlen:Int)
nNDResetCycles = 1)
case object DMKey extends Field[DebugModuleConfig]
case object IncludeJtagDTM extends Field[Boolean]
// *****************************************
// Module Interfaces

View File

@ -1,271 +0,0 @@
module AsyncFifo (
// Write Interface
enq_clock
, enq_reset
, enq_ready
, enq_valid
, enq_bits
// Read Interface
, deq_clock
, deq_reset
, deq_ready
, deq_valid
, deq_bits
);
//--------------------------------------------------------
// Parameter Declarations
parameter DEPTH_LG_2 = 0; // default is 'mailbox'.
parameter WIDTH = 64;
localparam DEPTH = 2**DEPTH_LG_2;
//--------------------------------------------------------
// I/O Declarations
// Write Interface
input enq_clock;
wire w_clock = enq_clock;
input enq_reset;
wire w_reset = enq_reset;
output enq_ready;
wire w_ready;
assign enq_ready = w_ready;
input enq_valid;
wire w_valid = enq_valid;
input [WIDTH - 1 : 0 ] enq_bits;
wire [WIDTH - 1 : 0 ] w_bits = enq_bits;
// Read Interface
input deq_clock;
wire r_clock = deq_clock;
input deq_reset;
wire r_reset = deq_reset;
output deq_valid;
wire r_valid;
assign deq_valid = r_valid;
input deq_ready;
wire r_ready = deq_ready;
output [WIDTH - 1 : 0] deq_bits;
wire [WIDTH - 1 : 0] r_bits;
assign deq_bits = r_bits;
//--------------------------------------------------------
// FIFO Memory Declaration
generate
if (DEPTH > 1) begin : mem1_scope
reg [WIDTH - 1 : 0] fifoMem [ 0 : DEPTH - 1];
end else begin : mem2_scope
reg [WIDTH - 1 :0] fifoMem;
end
endgenerate
//--------------------------------------------------------
// Reg and Wire Declarations
wire w_full;
wire w_fire;
wire r_empty;
wire r_fire;
// Read & Write Address Pointers
generate
if (DEPTH_LG_2 > 0) begin : reg1_scope
reg [DEPTH_LG_2 : 0 ] w_wrAddrReg;
wire [DEPTH_LG_2 : 0] w_wrAddrNxt;
reg [DEPTH_LG_2 : 0 ] w_wrAddrGrayReg;
wire [DEPTH_LG_2 : 0] w_wrAddrGrayNxt;
reg [DEPTH_LG_2 : 0 ] r_rdAddrReg;
wire [DEPTH_LG_2 : 0] r_rdAddrNxt;
reg [DEPTH_LG_2 : 0 ] r_rdAddrGrayReg;
wire [DEPTH_LG_2 : 0] r_rdAddrGrayNxt;
reg [DEPTH_LG_2 : 0 ] wrAddrGrayReg_sync;
reg [DEPTH_LG_2 : 0 ] rdAddrGrayReg_sync;
reg [DEPTH_LG_2 : 0 ] r_wrAddrGrayReg;
reg [DEPTH_LG_2 : 0 ] w_rdAddrGrayReg;
end else begin : reg2_scope
reg w_wrAddrReg;
wire w_wrAddrNxt;
reg r_rdAddrReg;
wire r_rdAddrNxt;
reg wrAddrReg_sync;
reg rdAddrReg_sync;
reg r_wrAddrReg;
reg w_rdAddrReg;
end
endgenerate
//--------------------------------------------------------
// Reg and Wire Declarations
// Pointer Logic
generate
if (DEPTH_LG_2 > 0) begin : ptr_logic_scope
assign w_full = ~(reg1_scope.w_wrAddrGrayReg[DEPTH_LG_2] == reg1_scope.w_rdAddrGrayReg[DEPTH_LG_2]) &
(reg1_scope.w_wrAddrGrayReg[DEPTH_LG_2 - 1 : 0] == reg1_scope.w_rdAddrGrayReg[DEPTH_LG_2 - 1 : 0 ]);
assign reg1_scope.w_wrAddrNxt = reg1_scope.w_wrAddrReg + 1'b1; // OK / expected to overflow
assign reg1_scope.w_wrAddrGrayNext = reg1_scope.w_wrAddrNxt ^ (reg1_scope.w_wrAddrNxt >> 1);
assign reg1_scope.r_rdAddrNxt = reg1_scope.r_rdAddrReg + 1'b1; // OK / expected to overflow
assign reg1_scope.r_rdAddrGrayNext = reg1_scope.r_rdAddrNxt ^ (reg1_scope.r_rdAddrNxt >> 1);
assign r_empty = (reg1_scope.r_wrAddrGrayReg == reg1_scope.r_rdAddrGrayReg);
end else begin : ptr_logic_scope
assign w_full = ~(reg2_scope.w_wrAddrReg == reg2_scope.r_rdAddrReg);
assign reg2_scope.w_wrAddrNxt = ~reg2_scope.w_wrAddrReg ;
assign reg2_scope.r_rdAddrNxt = ~reg2_scope.r_rdAddrReg;
assign r_empty = (reg2_scope.r_wrAddrReg == reg2_scope.r_rdAddrReg);
end
endgenerate
assign w_ready = ~w_full;
assign w_fire = w_ready & w_valid;
// Read Logic
assign r_valid = ~r_empty;
assign r_fire = r_ready & r_valid;
generate
if (DEPTH > 1) begin : rw_scope1
if (DEPTH > 2) begin : rw_scope2
assign r_bits = mem1_scope.fifoMem[reg1_scope.r_rdAddrReg[DEPTH_LG_2-1:0]];
always @(posedge w_clock) begin
if (w_fire) begin
mem1_scope.fifoMem[reg1_scope.w_wrAddrReg[DEPTH_LG_2-1:0]] <= w_bits;
end
end
end else begin
assign r_bits = mem1_scope.fifoMem[reg1_scope.r_rdAddrReg[0]];
always @(posedge w_clock) begin
if (w_fire) begin
mem1_scope.fifoMem[reg1_scope.w_wrAddrReg[0]] <= w_bits;
end
end
end
end else begin
assign r_bits = mem2_scope.fifoMem;
always @(posedge w_clock) begin
if (w_fire) begin
mem2_scope.fifoMem <= w_bits;
end
end
end
endgenerate
//--------------------------------------------------------
// Sequential logic
//
generate
if (DEPTH_LG_2 > 0) begin : seq1_scope
always @(posedge w_clock or posedge w_reset) begin
if (w_reset) begin
reg1_scope.w_wrAddrReg <= 'b0;
reg1_scope.w_wrAddrGrayReg <= 'b0;
reg1_scope.rdAddrGrayReg_sync <= 'b0;
reg1_scope.w_rdAddrGrayReg <= 'b0;
end else begin
if (w_fire) begin
reg1_scope.w_wrAddrReg <= reg1_scope.w_wrAddrNxt;
reg1_scope.w_wrAddrGrayReg <= reg1_scope.w_wrAddrGrayNxt;
end
reg1_scope.rdAddrGrayReg_sync <= reg1_scope.r_rdAddrGrayReg;
reg1_scope.w_rdAddrGrayReg <= reg1_scope.rdAddrGrayReg_sync;
end
end
always @(posedge r_clock or posedge r_reset) begin
if (r_reset) begin
reg1_scope.r_rdAddrReg <= 'b0;
reg1_scope.r_rdAddrGrayReg <= 'b0;
reg1_scope.reg1_scope.wrAddrGrayReg_sync <= 'b0;
reg1_scope.reg1_scope.r_wrAddrGrayReg <= 'b0;
end else begin
if (r_fire) begin
reg1_scope.r_rdAddrReg <= reg1_scope.r_rdAddrNxt;
reg1_scope.r_rdAddrGrayReg <= reg1_scope.r_rdAddrGrayNxt;
end
reg1_scope.wrAddrGrayReg_sync <= reg1_scope.w_wrAddrGrayReg;
reg1_scope.r_wrAddrGrayReg <= reg1_scope.wrAddrGrayReg_sync;
end
end // always @ (posedge r_clock)
end else begin : seq2_scope // block: seq1_scope
always @(posedge w_clock or posedge w_reset) begin
if (w_reset ) begin
reg2_scope.w_wrAddrReg <= 1'b0;
reg2_scope.rdAddrReg_sync <= 1'b0;
reg2_scope.w_rdAddrReg <= 1'b0;
end else begin
if (w_fire) begin
reg2_scope.w_wrAddrReg <= reg2_scope.w_wrAddrNxt;
end
reg2_scope.rdAddrReg_sync <= reg2_scope.r_rdAddrReg;
reg2_scope.w_rdAddrReg <= reg2_scope.rdAddrReg_sync;
end
end
always @(posedge r_clock or posedge r_reset) begin
if (r_reset) begin
reg2_scope.r_rdAddrReg <= 1'b0;
reg2_scope.wrAddrReg_sync <= 1'b0;
reg2_scope.r_wrAddrReg <= 1'b0;
end else begin
if (r_fire) begin
reg2_scope.r_rdAddrReg <= reg2_scope.r_rdAddrNxt;
end
reg2_scope.wrAddrReg_sync <= reg2_scope.w_wrAddrReg;
reg2_scope.r_wrAddrReg <= reg2_scope.wrAddrReg_sync;
end
end // always @ (posedge r_clock)
end // block: seq2_scope
endgenerate
endmodule // AsyncFifo

154
vsrc/AsyncMailbox.v Normal file
View File

@ -0,0 +1,154 @@
module AsyncMailbox (
// Write Interface
enq_clock
, enq_reset
, enq_ready
, enq_valid
, enq_bits
// Read Interface
, deq_clock
, deq_reset
, deq_ready
, deq_valid
, deq_bits
);
//--------------------------------------------------------
// Parameter Declarations
parameter WIDTH = 64;
//--------------------------------------------------------
// I/O Declarations
// Write Interface
input enq_clock;
wire w_clock = enq_clock;
input enq_reset;
wire w_reset = enq_reset;
output enq_ready;
wire w_ready;
assign enq_ready = w_ready;
input enq_valid;
wire w_valid = enq_valid;
input [WIDTH - 1 : 0 ] enq_bits;
wire [WIDTH - 1 : 0 ] w_bits = enq_bits;
// Read Interface
input deq_clock;
wire r_clock = deq_clock;
input deq_reset;
wire r_reset = deq_reset;
output deq_valid;
wire r_valid;
assign deq_valid = r_valid;
input deq_ready;
wire r_ready = deq_ready;
output [WIDTH - 1 : 0] deq_bits;
wire [WIDTH - 1 : 0] r_bits;
assign deq_bits = r_bits;
//--------------------------------------------------------
// FIFO Memory Declaration
reg [WIDTH - 1 :0] mailboxReg;
//--------------------------------------------------------
// Reg and Wire Declarations
wire w_full;
wire w_fire;
wire r_empty;
wire r_fire;
// Read & Write Address Pointers
reg w_wrAddrReg;
wire w_wrAddrNxt;
reg r_rdAddrReg;
wire r_rdAddrNxt;
reg wrAddrReg_sync;
reg rdAddrReg_sync;
reg r_wrAddrReg;
reg w_rdAddrReg;
//--------------------------------------------------------
// Reg and Wire Declarations
assign w_full = ~(w_wrAddrReg == r_rdAddrReg);
assign w_wrAddrNxt = ~w_wrAddrReg ;
assign r_rdAddrNxt = ~r_rdAddrReg;
assign r_empty = (r_wrAddrReg == r_rdAddrReg);
assign w_ready = ~w_full;
assign w_fire = w_ready & w_valid;
// Read Logic
assign r_valid = ~r_empty;
assign r_fire = r_ready & r_valid;
assign r_bits = mailboxReg;
always @(posedge w_clock) begin
if (w_fire) begin
mailboxReg <= w_bits;
end
end
//--------------------------------------------------------
// Sequential logic
//
always @(posedge w_clock or posedge w_reset) begin
if (w_reset ) begin
w_wrAddrReg <= 1'b0;
rdAddrReg_sync <= 1'b0;
w_rdAddrReg <= 1'b0;
end else begin
if (w_fire) begin
w_wrAddrReg <= w_wrAddrNxt;
end
rdAddrReg_sync <= r_rdAddrReg;
w_rdAddrReg <= rdAddrReg_sync;
end
end
always @(posedge r_clock or posedge r_reset) begin
if (r_reset) begin
r_rdAddrReg <= 1'b0;
wrAddrReg_sync <= 1'b0;
r_wrAddrReg <= 1'b0;
end else begin
if (r_fire) begin
r_rdAddrReg <= r_rdAddrNxt;
end
wrAddrReg_sync <= w_wrAddrReg;
r_wrAddrReg <= wrAddrReg_sync;
end
end // always @ (posedge r_clock)
endmodule // AsyncMailbox