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:
parent
dd4a50c452
commit
3dd51ff734
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
271
vsrc/AsyncFifo.v
271
vsrc/AsyncFifo.v
@ -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
154
vsrc/AsyncMailbox.v
Normal 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
|
Loading…
Reference in New Issue
Block a user