From 3dd51ff7341a99a9b26f7341a63fb92a8748f42a Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Fri, 19 Aug 2016 14:01:33 -0700 Subject: [PATCH] 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 --- src/main/scala/DebugTransport.scala | 4 +- src/main/scala/rocketchip/TestHarness.scala | 9 +- src/main/scala/uncore/devices/Debug.scala | 3 +- vsrc/AsyncFifo.v | 271 -------------------- vsrc/AsyncMailbox.v | 154 +++++++++++ 5 files changed, 164 insertions(+), 277 deletions(-) delete mode 100644 vsrc/AsyncFifo.v create mode 100644 vsrc/AsyncMailbox.v diff --git a/src/main/scala/DebugTransport.scala b/src/main/scala/DebugTransport.scala index 199b6809..169cf6f2 100644 --- a/src/main/scala/DebugTransport.scala +++ b/src/main/scala/DebugTransport.scala @@ -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. diff --git a/src/main/scala/rocketchip/TestHarness.scala b/src/main/scala/rocketchip/TestHarness.scala index fcc6833f..e51fa03e 100644 --- a/src/main/scala/rocketchip/TestHarness.scala +++ b/src/main/scala/rocketchip/TestHarness.scala @@ -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) diff --git a/src/main/scala/uncore/devices/Debug.scala b/src/main/scala/uncore/devices/Debug.scala index cc787f30..7443c9ac 100644 --- a/src/main/scala/uncore/devices/Debug.scala +++ b/src/main/scala/uncore/devices/Debug.scala @@ -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 diff --git a/vsrc/AsyncFifo.v b/vsrc/AsyncFifo.v deleted file mode 100644 index 4539b843..00000000 --- a/vsrc/AsyncFifo.v +++ /dev/null @@ -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 diff --git a/vsrc/AsyncMailbox.v b/vsrc/AsyncMailbox.v new file mode 100644 index 00000000..4460e9bf --- /dev/null +++ b/vsrc/AsyncMailbox.v @@ -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