From 9514eab75e7774d0fc2c31bbfd4f778279c62041 Mon Sep 17 00:00:00 2001 From: Matthew <106996253+Matthew-Otto@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:06:16 -0500 Subject: [PATCH] Implement progbuf and attempt to halt/resume using existing trap logic (very broken) --- bin/hw_debug_test.py | 27 +++++++---- bin/openocd_tcl_wrapper.py | 10 +++- config/rv64gc/config.vh | 3 ++ config/shared/debug.vh | 15 ++++++ config/shared/parameter-defs.vh | 4 +- src/cvw.sv | 3 ++ src/debug/dm.sv | 53 ++++++++++---------- src/debug/dmc.sv | 85 ++++++++++++++++++++------------- src/hazard/hazard.sv | 9 ++-- src/ifu/ifu.sv | 28 +++++++---- src/ifu/progbuf.sv | 69 ++++++++++++++++++++++++++ src/mmu/adrdecs.sv | 3 +- src/mmu/mmu.sv | 3 +- src/mmu/pmachecker.sv | 7 ++- src/privileged/csr.sv | 10 ++-- src/privileged/csrd.sv | 23 +++++---- src/privileged/privdec.sv | 13 +++-- src/privileged/privileged.sv | 10 ++-- src/wally/wallypipelinedcore.sv | 19 +++++--- src/wally/wallypipelinedsoc.sv | 11 +++-- 20 files changed, 282 insertions(+), 123 deletions(-) create mode 100644 src/ifu/progbuf.sv diff --git a/bin/hw_debug_test.py b/bin/hw_debug_test.py index c77577057..8cc59f96f 100755 --- a/bin/hw_debug_test.py +++ b/bin/hw_debug_test.py @@ -38,7 +38,13 @@ random_order = False def prog_buff_test(cvw): cvw.halt() - cvw.write_dmi("0x20", "0x7ee7beef") + cvw.write_dmi("0x20", "0x00100073") + #cvw.write_dmi("0x21", "0xf00daedd") + #cvw.write_dmi("0x22", "0xdaede105") + #cvw.write_dmi("0x23", "0x00100073") # ebreak + + cvw.write_data("DPC", "0x00002000") # Progbuf addr + cvw.resume() print() @@ -46,10 +52,13 @@ def flow_control_test(cvw): #time.sleep(70) # wait for OpenSBI cvw.halt() - cvw.read_data("DCSR") + time.sleep(1) + #cvw.read_data("DCSR") for _ in range(50): - cvw.step() - print(cvw.read_data("PCM")) + cvw.resume() + cvw.halt() + #cvw.step() + #print(cvw.read_data("PCM")) cvw.resume() @@ -154,11 +163,11 @@ def random_hex(reg_name): with OpenOCD() as cvw: - print(cvw.read_dmi("0x16")) - cvw.trst() + #cvw.trst() cvw.reset_dm() + time.sleep(1) cvw.reset_hart() - quit() + time.sleep(1) #register_rw_test(cvw) - flow_control_test(cvw) - #prog_buff_test(cvw) + #flow_control_test(cvw) + prog_buff_test(cvw) diff --git a/bin/openocd_tcl_wrapper.py b/bin/openocd_tcl_wrapper.py index b7cc1862d..4c1c8097e 100644 --- a/bin/openocd_tcl_wrapper.py +++ b/bin/openocd_tcl_wrapper.py @@ -114,6 +114,12 @@ class OpenOCD: raise Exception("Error: Hart failed to reset") self.write_dmi("0x10", "0x10000001") # ack HaveReset + def write_progbuf(self, data): + #TODO query progbuf size and error is len(data) is greater + baseaddr = 0x20 + for idx, instr in enumerate(data): + self.write_dmi(hex(baseaddr+idx), instr) + def set_haltonreset(self): self.write_dmi("0x10", "0x9") @@ -139,7 +145,7 @@ class OpenOCD: dcsr |= 0x4 self.write_data("DCSR", hex(dcsr)) # Resume once - self.resume() + self.write_dmi("0x10", "0x40000001") # Unset step bit dcsr &= ~0x4 self.write_data("DCSR", hex(dcsr)) @@ -153,7 +159,7 @@ class OpenOCD: data += int(math.log2(addr_size // 8)) << 20 data += write << 16 data += regno - self.write_dmi("0x17", hex(data)) + self.write_dmi("0x17", hex(data)) def write_data(self, register, data): """Write data to specified register""" diff --git a/config/rv64gc/config.vh b/config/rv64gc/config.vh index b2e70abcb..347a2a87b 100644 --- a/config/rv64gc/config.vh +++ b/config/rv64gc/config.vh @@ -186,6 +186,9 @@ localparam logic [63:0] SDC_RANGE = 64'h0000007F; localparam logic SPI_SUPPORTED = 1; localparam logic [63:0] SPI_BASE = 64'h10040000; localparam logic [63:0] SPI_RANGE = 64'h00000FFF; +// Debug program buffer support is enabled with DEBUG_SUPPORTED +localparam logic [63:0] PROGBUF_BASE = 64'h00002000; +localparam logic [63:0] PROGBUF_RANGE = 64'h0000000F; // Bus Interface width localparam AHBW = (XLEN); diff --git a/config/shared/debug.vh b/config/shared/debug.vh index a0dc27d2d..06f1e7c28 100755 --- a/config/shared/debug.vh +++ b/config/shared/debug.vh @@ -48,6 +48,21 @@ `define ABSTRACTAUTO `ADDR_WIDTH'h18 `define NEXTDM `ADDR_WIDTH'h1d `define PROGBUF0 `ADDR_WIDTH'h20 +`define PROGBUF1 `ADDR_WIDTH'h21 +`define PROGBUF2 `ADDR_WIDTH'h22 +`define PROGBUF3 `ADDR_WIDTH'h23 +`define PROGBUF4 `ADDR_WIDTH'h24 +`define PROGBUF5 `ADDR_WIDTH'h25 +`define PROGBUF6 `ADDR_WIDTH'h26 +`define PROGBUF7 `ADDR_WIDTH'h27 +`define PROGBUF8 `ADDR_WIDTH'h28 +`define PROGBUF9 `ADDR_WIDTH'h29 +`define PROGBUFA `ADDR_WIDTH'h2A +`define PROGBUFB `ADDR_WIDTH'h2B +`define PROGBUFC `ADDR_WIDTH'h2C +`define PROGBUFD `ADDR_WIDTH'h2D +`define PROGBUFE `ADDR_WIDTH'h2E +`define PROGBUFF `ADDR_WIDTH'h2F //`define dmcs2 `ADDR_WIDTH'h32 `define SBCS `ADDR_WIDTH'h38 diff --git a/config/shared/parameter-defs.vh b/config/shared/parameter-defs.vh index 060b6670d..68016f9e6 100644 --- a/config/shared/parameter-defs.vh +++ b/config/shared/parameter-defs.vh @@ -85,6 +85,8 @@ localparam cvw_t P = '{ SPI_SUPPORTED : SPI_SUPPORTED, SPI_BASE : SPI_BASE, SPI_RANGE : SPI_RANGE, + PROGBUF_BASE : PROGBUF_BASE, + PROGBUF_RANGE : PROGBUF_RANGE, GPIO_LOOPBACK_TEST : GPIO_LOOPBACK_TEST, SPI_LOOPBACK_TEST : SPI_LOOPBACK_TEST, UART_PRESCALE : UART_PRESCALE , @@ -200,5 +202,5 @@ localparam cvw_t P = '{ DURLEN : DURLEN, DIVb : DIVb, DIVBLEN : DIVBLEN, - DEBUG_SUPPORTED : DEBUG_SUPPORTED + DEBUG_SUPPORTED : DEBUG_SUPPORTED }; diff --git a/src/cvw.sv b/src/cvw.sv index ce339380f..b1e87d479 100644 --- a/src/cvw.sv +++ b/src/cvw.sv @@ -140,6 +140,9 @@ typedef struct packed { logic SPI_SUPPORTED; logic [63:0] SPI_BASE; logic [63:0] SPI_RANGE; + // Debug program buffer support is enabled with DEBUG_SUPPORTED + logic [63:0] PROGBUF_BASE; + logic [63:0] PROGBUF_RANGE; // Test modes diff --git a/src/debug/dm.sv b/src/debug/dm.sv index 132f902db..ee613ff54 100644 --- a/src/debug/dm.sv +++ b/src/debug/dm.sv @@ -74,12 +74,14 @@ module dm import cvw::*; #(parameter cvw_t P) ( output logic DebugRegUpdate, // writes values from scan register after scanning in // Program Buffer + output logic [3:0] ProgBufAddr, output logic ProgBuffScanEn, - output logic ProgBuffScanOut, output logic ExecProgBuff ); `include "debug.vh" + localparam PROGBUF_SIZE = (P.PROGBUF_RANGE+1)/4; + // DMI Signals logic ReqReady; logic ReqValid; @@ -93,7 +95,7 @@ module dm import cvw::*; #(parameter cvw_t P) ( // JTAG ID for Wally: // Version [31:28] = 0x1 : 0001 - // PartNumber [27:12] = 0x2A : 00000000_00101010 + // PartNumber [27:12] = 0x2A : Wally (00000000_00101010) // JEDEC number [11:1] = 0x602 : Bank 13 (1100) Open HW Group (0000010) // [0] = 1 localparam JTAG_DEVICE_ID = 32'h1002AC05; @@ -151,7 +153,7 @@ module dm import cvw::*; #(parameter cvw_t P) ( // DMStatus const logic NdmResetPending = 0; const logic StickyUnavail = 0; - const logic ImpEBreak = 1; + const logic ImpEBreak = 0; logic AllHaveReset; logic AnyHaveReset; logic AllResumeAck; @@ -170,7 +172,7 @@ module dm import cvw::*; #(parameter cvw_t P) ( const logic ConfStrPtrValid = 0; // Used with SysBusAccess const logic [3:0] Version = 3; // DM Version // AbstractCS - const logic [4:0] ProgBufSize = 1; + const logic [4:0] ProgBufSize = PROGBUF_SIZE; logic Busy; const logic RelaxedPriv = 1; logic [2:0] CmdErr; @@ -233,27 +235,27 @@ module dm import cvw::*; #(parameter cvw_t P) ( IDLE : begin if (ReqValid) case ({ReqOP, ReqAddress}) inside - {`OP_WRITE,`DATA0} : State <= W_DATA; - {`OP_READ,`DATA0} : State <= R_DATA; - {`OP_WRITE,`DATA1} : State <= (P.LLEN >= 64) ? W_DATA : INVALID; - {`OP_READ,`DATA1} : State <= (P.LLEN >= 64) ? R_DATA : INVALID; - [{`OP_WRITE,`DATA2}:{`OP_WRITE,`DATA3}] : State <= (P.LLEN >= 128) ? W_DATA : INVALID; - [{`OP_READ,`DATA2}:{`OP_READ,`DATA3}] : State <= (P.LLEN >= 128) ? R_DATA : INVALID; - {`OP_WRITE,`DMCONTROL} : State <= W_DMCONTROL; - {`OP_READ,`DMCONTROL} : State <= R_DMCONTROL; - {`OP_READ,`DMSTATUS} : State <= DMSTATUS; - {`OP_WRITE,`ABSTRACTCS} : State <= W_ABSTRACTCS; - {`OP_READ,`ABSTRACTCS} : State <= R_ABSTRACTCS; - {`OP_WRITE,`COMMAND} : State <= ABST_COMMAND; - {`OP_READ,`COMMAND} : State <= READ_ZERO; - {`OP_WRITE,`SBCS} : State <= READ_ZERO; - {`OP_READ,`SBCS} : State <= R_SYSBUSCS; - {`OP_WRITE,`PROGBUF0} : State <= W_PROGBUF; - {`OP_READ,`PROGBUF0}, + {`OP_WRITE,`DATA0} : State <= W_DATA; + {`OP_READ,`DATA0} : State <= R_DATA; + {`OP_WRITE,`DATA1} : State <= (P.LLEN >= 64) ? W_DATA : INVALID; + {`OP_READ,`DATA1} : State <= (P.LLEN >= 64) ? R_DATA : INVALID; + [{`OP_WRITE,`DATA2}:{`OP_WRITE,`DATA3}] : State <= (P.LLEN >= 128) ? W_DATA : INVALID; + [{`OP_READ,`DATA2}:{`OP_READ,`DATA3}] : State <= (P.LLEN >= 128) ? R_DATA : INVALID; + {`OP_WRITE,`DMCONTROL} : State <= W_DMCONTROL; + {`OP_READ,`DMCONTROL} : State <= R_DMCONTROL; + {`OP_READ,`DMSTATUS} : State <= DMSTATUS; + {`OP_WRITE,`ABSTRACTCS} : State <= W_ABSTRACTCS; + {`OP_READ,`ABSTRACTCS} : State <= R_ABSTRACTCS; + {`OP_WRITE,`COMMAND} : State <= ABST_COMMAND; + {`OP_READ,`COMMAND} : State <= READ_ZERO; + {`OP_WRITE,`SBCS} : State <= READ_ZERO; + {`OP_READ,`SBCS} : State <= R_SYSBUSCS; + [{`OP_WRITE,`PROGBUF0}:{`OP_WRITE,`PROGBUF3}] : State <= W_PROGBUF; // TODO: update decode range dynamically using PROGBUF_RANGE + [{`OP_READ,`PROGBUF0}:{`OP_READ,`PROGBUFF}], {2'bx,`HARTINFO}, {2'bx,`ABSTRACTAUTO}, - {2'bx,`NEXTDM} : State <= READ_ZERO; - default : State <= READ_ZERO;//INVALID; + {2'bx,`NEXTDM} : State <= READ_ZERO; + default : State <= INVALID; endcase end @@ -369,8 +371,10 @@ module dm import cvw::*; #(parameter cvw_t P) ( W_PROGBUF : begin if (Busy) CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; - else + else begin NewAcState <= PROGBUFF_WRITE; + ProgBufAddr <= ReqAddress[$clog2(PROGBUF_SIZE)-1:0]; + end RspOP <= `OP_SUCCESS; State <= ACK; end @@ -441,7 +445,6 @@ module dm import cvw::*; #(parameter cvw_t P) ( // Program Buffer assign ProgBuffScanEn = (AcState == PROGBUFF_WRITE); - assign ProgBuffScanOut = ScanReg[0]; // Scan Chain assign DebugScanOut = ScanReg[0]; diff --git a/src/debug/dmc.sv b/src/debug/dmc.sv index 719e9f02e..c7e792ae9 100644 --- a/src/debug/dmc.sv +++ b/src/debug/dmc.sv @@ -27,12 +27,28 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// -// Note: This module controls all of the per-hart debug state. -// In a multihart system, this module should be instantiated under wallypipelinedcore +// On HaltReq/eBreak: +// store value of NextPC in DPC +// trigger trap (flush pipe) +// stall pipe + +// On Step: +// unstall pipe until instruction receaches M stage +// goto: HaltReq/eBreak + +// On exec_progbuf +// change NextPC to progbuf_address (using DPC?) +// goto: resume (implicic ebreak will return to debug mode) + +// On Resume: +// update NextPC from DPC +// Unstall pipe module dmc ( input logic clk, reset, input logic Step, + input logic ebreakM, // ebreak instruction + input logic ebreakEn, // DCSR: enter debug mode on ebreak input logic HaltReq, // Initiates core halt input logic ResumeReq, // Initiates core resume input logic HaltOnReset, // Halts core immediately on hart reset @@ -46,14 +62,14 @@ module dmc ( output logic EnterDebugMode, // Store PCNextF in DPC when entering Debug Mode output logic ExitDebugMode, // Updates PCNextF with the current value of DPC - output logic ForceNOP // Fills the pipeline with NOP + output logic ForceBreakPoint // Causes artificial ebreak that puts core in debug mode ); `include "debug.vh" - enum logic [1:0] {RUNNING, FLUSH, HALTED, RESUME} State; + enum logic [2:0] {RUNNING, HALTED, RESUME, STEP, PROGBUF} State; - localparam NOP_CYCLE_DURATION = 0; - logic [$clog2(NOP_CYCLE_DURATION+1)-1:0] Counter; + localparam E2M_CYCLE_COUNT = 3; + logic [$clog2(E2M_CYCLE_COUNT+1)-1:0] Counter; always_ff @(posedge clk) begin if (reset) @@ -62,12 +78,13 @@ module dmc ( HaveReset <= 0; end - assign DebugMode = (State != RUNNING); - assign DebugStall = (State == HALTED); + assign ForceBreakPoint = (State == RUNNING) & HaltReq | (State == STEP) & ~|Counter; - assign EnterDebugMode = (State == FLUSH) & ~|Counter; + assign DebugMode = (State != RUNNING); + assign DebugStall = (State == HALTED) | (State == RESUME); + + assign EnterDebugMode = (State == RUNNING) & (ebreakM & ebreakEn) | ForceBreakPoint; assign ExitDebugMode = (State == HALTED) & ResumeReq; - assign ForceNOP = (State == FLUSH); always_ff @(posedge clk) begin if (reset) begin @@ -77,34 +94,38 @@ module dmc ( case (State) RUNNING : begin if (HaltReq) begin - Counter <= NOP_CYCLE_DURATION; - State <= FLUSH; - DebugCause <= `CAUSE_HALTREQ; - end - //else if (eBreak) TODO: halt on ebreak if DCSR bit is set - // DebugCause <= `CAUSE_EBREAK; - end - - // fill the pipe with NOP before halting - FLUSH : begin - if (~|Counter) State <= HALTED; - else - Counter <= Counter - 1; + DebugCause <= `CAUSE_HALTREQ; + end else if (ebreakM & ebreakEn) begin + State <= HALTED; + DebugCause <= `CAUSE_EBREAK; + end end HALTED : begin - if (ResumeReq) begin - if (Step) begin - Counter <= NOP_CYCLE_DURATION; - State <= FLUSH; - DebugCause <= `CAUSE_STEP; - end else begin - State <= RUNNING; - ResumeAck <= 1; - end + if (ResumeReq) + State <= RESUME; + end + + // Wait a cycle to load PCF from DPC before resuming + // TODO: test without resume stage + RESUME : begin + if (Step) begin + Counter <= E2M_CYCLE_COUNT; + State <= STEP; + end else begin + State <= RUNNING; + ResumeAck <= 1; end end + + STEP : begin + if (~|Counter) begin + DebugCause <= `CAUSE_STEP; + State <= HALTED; + end else + Counter <= Counter - 1; + end endcase end end diff --git a/src/hazard/hazard.sv b/src/hazard/hazard.sv index ea63fc06e..08b08a83f 100644 --- a/src/hazard/hazard.sv +++ b/src/hazard/hazard.sv @@ -108,9 +108,8 @@ module hazard import cvw::*; #(parameter cvw_t P) ( assign LatestUnstalledW = ~StallW & StallM; // Each stage flushes if the previous stage is the last one stalled (for cause) or the system has reason to flush - // Do not flush if halted for Debug - assign FlushD = ~DebugStall & (LatestUnstalledD | FlushDCause); - assign FlushE = ~DebugStall & (LatestUnstalledE | FlushECause); - assign FlushM = ~DebugStall & (LatestUnstalledM | FlushMCause); - assign FlushW = ~DebugStall & (LatestUnstalledW | FlushWCause); + assign FlushD = (LatestUnstalledD | FlushDCause); + assign FlushE = (LatestUnstalledE | FlushECause); + assign FlushM = (LatestUnstalledM | FlushMCause); + assign FlushW = (LatestUnstalledW | FlushWCause); endmodule diff --git a/src/ifu/ifu.sv b/src/ifu/ifu.sv index 5e3aa8d36..9ba4fd5c9 100644 --- a/src/ifu/ifu.sv +++ b/src/ifu/ifu.sv @@ -98,11 +98,13 @@ module ifu import cvw::*; #(parameter cvw_t P) ( output logic ICacheAccess, // Report I$ read to performance counters output logic ICacheMiss, // Report I$ miss to performance counters // Debug Mode logic + output logic [P.XLEN-1:0] PCNextF, // Next PCF, selected from Branch predictor, Privilege, or PC+2/4 input logic ExitDebugMode, input logic [P.XLEN-1:0] DPC, - output logic [P.XLEN-1:0] PCNextF, // Next PCF, selected from Branch predictor, Privilege, or PC+2/4 - input logic ForceNOP, + input logic ProgBuffScanEn, // Debug scan chain + input logic [3:0] ProgBufAddr, + input logic ProgBufScanIn, input logic DebugScanEn, input logic DebugScanIn, output logic DebugScanOut @@ -111,7 +113,6 @@ module ifu import cvw::*; #(parameter cvw_t P) ( localparam [31:0] nop = 32'h00000013; // instruction for NOP localparam LINELEN = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS : P.XLEN; - logic [P.XLEN-1:0] PCNextFM; // (muxed for debug) Next PCF, selected from Branch predictor, Privilege, or PC+2/4 logic [P.XLEN-1:0] PC1NextF; // Branch predictor next PCF logic [P.XLEN-1:0] PC2NextF; // Selected PC between branch prediction and next valid PC if CSRWriteFence logic [P.XLEN-1:0] UnalignedPCNextF; // The next PCF, but not aligned to 2 bytes. @@ -128,6 +129,7 @@ module ifu import cvw::*; #(parameter cvw_t P) ( logic [31:0] IROMInstrF; // Instruction from the IROM logic [31:0] ICacheInstrF; // Instruction from the I$ logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus + logic [31:0] ProgBufInstrF; // Instruction from the ProgBuf logic CompressedF, CompressedE; // The fetched instruction is compressed logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage @@ -146,6 +148,7 @@ module ifu import cvw::*; #(parameter cvw_t P) ( logic BusCommittedF; // Bus memory operation in flight, delay interrupts logic CacheCommittedF; // I$ memory operation started, delay interrupts logic SelIROM; // PMA indicates instruction address is in the IROM + logic SelProgBuf; // PMA indicates instruction address is in Program Buffer logic [15:0] InstrRawE, InstrRawM; logic [LINELEN-1:0] FetchBuffer; logic [31:0] ShiftUncachedInstr; @@ -196,7 +199,7 @@ module ifu import cvw::*; #(parameter cvw_t P) ( .TLBFlush, .PhysicalAddress(PCPF), .TLBMiss(ITLBMissF), - .Cacheable(CacheableF), .Idempotent(), .SelTIM(SelIROM), + .Cacheable(CacheableF), .Idempotent(), .SelTIM(SelIROM), .SelProgBuf, .InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(), .InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(), .LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(), @@ -209,6 +212,7 @@ module ifu import cvw::*; #(parameter cvw_t P) ( assign PCPF = PCFExt[P.PA_BITS-1:0]; assign CacheableF = 1'b1; assign SelIROM = '0; + assign SelProgBuf = '0; end //////////////////////////////////////////////////////////////////////////////////////////////// @@ -218,7 +222,7 @@ module ifu import cvw::*; #(parameter cvw_t P) ( // CommittedM tells the CPU's privileged unit the current instruction // in the memory stage is a memory operaton and that memory operation is either completed // or is partially executed. Partially completed memory operations need to prevent an interrupts. - // There is not a clean way to restore back to a partial executed instruction. CommiteedM will + // There is not a clean way to restore back to a partial executed instruction. CommittedM will // delay the interrupt until the LSU is in a clean state. assign CommittedF = CacheCommittedF | BusCommittedF; @@ -314,7 +318,14 @@ module ifu import cvw::*; #(parameter cvw_t P) ( assign IFUStallF = IFUCacheBusStallF | SelSpillNextF; assign GatedStallD = StallD & ~SelSpillNextF; - flopenl #(32) AlignedInstrRawDFlop(clk, reset | FlushD, ~StallD, PostSpillInstrRawF, nop, InstrRawD); + if (P.DEBUG_SUPPORTED) begin + logic [31:0] PostSpillInstrRawFM; + progbuf #(P) progbuf(.clk, .reset, .Addr(PCNextF[3:0]), .ProgBufInstrF, .ScanAddr(ProgBufAddr), .Scan(ProgBuffScanEn), .ScanIn(ProgBufScanIn)); + assign PostSpillInstrRawFM = SelProgBuf ? ProgBufInstrF : PostSpillInstrRawF; + flopenl #(32) AlignedInstrRawDFlop(clk, reset | FlushD, ~StallD, PostSpillInstrRawFM, nop, InstrRawD); + end else begin + flopenl #(32) AlignedInstrRawDFlop(clk, reset | FlushD, ~StallD, PostSpillInstrRawF, nop, InstrRawD); + end //////////////////////////////////////////////////////////////////////////////////////////////// // PCNextF logic @@ -324,10 +335,11 @@ module ifu import cvw::*; #(parameter cvw_t P) ( mux2 #(P.XLEN) pcmux2(.d0(PC1NextF), .d1(NextValidPCE), .s(CSRWriteFenceM),.y(PC2NextF)); else assign PC2NextF = PC1NextF; + mux3 #(P.XLEN) pcmux3(PC2NextF, EPCM, TrapVectorM, {TrapM, RetM}, UnalignedPCNextF); + if (P.DEBUG_SUPPORTED) begin - mux2 #(P.XLEN) pcresetmux({UnalignedPCNextF[P.XLEN-1:1], 1'b0}, P.RESET_VECTOR[P.XLEN-1:0], reset, PCNextFM); - assign PCNextF = ExitDebugMode ? DPC : PCNextFM; + mux3 #(P.XLEN) pcresetmux(.d2(P.RESET_VECTOR[P.XLEN-1:0]), .d1(DPC), .d0({UnalignedPCNextF[P.XLEN-1:1], 1'b0}), .s({reset,ExitDebugMode}), .y(PCNextF)); flopen #(P.XLEN) pcreg(clk, ~StallF | reset | ExitDebugMode, PCNextF, PCF); end else begin mux2 #(P.XLEN) pcresetmux({UnalignedPCNextF[P.XLEN-1:1], 1'b0}, P.RESET_VECTOR[P.XLEN-1:0], reset, PCNextF); diff --git a/src/ifu/progbuf.sv b/src/ifu/progbuf.sv new file mode 100644 index 000000000..18023f9e2 --- /dev/null +++ b/src/ifu/progbuf.sv @@ -0,0 +1,69 @@ +/////////////////////////////////////////// +// progbuf.sv +// +// Written: matthew.n.otto@okstate.edu +// Created: 18 June 2024 +// +// Purpose: Holds small programs to be executed in debug mode +// This module acts like a small ROM except it can be written by serial Scanning via the Debug Module +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// https://github.com/openhwgroup/cvw +// +// Copyright (C) 2021-24 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License Version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module progbuf import cvw::*; #(parameter cvw_t P) ( + input logic clk, reset, + input logic [3:0] Addr, + output logic [31:0] ProgBufInstrF, + + input logic [3:0] ScanAddr, + input logic Scan, + input logic ScanIn +); + + localparam PROGBUF_SIZE = (P.PROGBUF_RANGE+1)/4; + localparam ADDR_WIDTH = $clog2(PROGBUF_SIZE); + + bit [31:0] RAM [PROGBUF_SIZE-1:0]; + + logic EnPrevClk; + logic WriteProgBuf; + logic [32:0] WriteData; + logic [ADDR_WIDTH-1:0] AddrM; + + flopr #(1) Scanenhist (.clk, .reset, .d(Scan), .q(EnPrevClk)); + assign WriteProgBuf = ~Scan & EnPrevClk; + + assign WriteData[32] = ScanIn; + genvar i; + for (i=0; i<32; i=i+1) begin + flopenr #(1) Scanreg (.clk, .reset, .en(Scan), .d(WriteData[i+1]), .q(WriteData[i])); + end + + assign AddrM = WriteProgBuf ? ScanAddr[ADDR_WIDTH-1:0] : Addr[ADDR_WIDTH-1:0]; + + always_ff @(posedge clk) begin + if (WriteProgBuf) + RAM[AddrM] <= WriteData; + if (reset) + ProgBufInstrF <= 0; + else + ProgBufInstrF <= RAM[AddrM]; + end + +endmodule \ No newline at end of file diff --git a/src/mmu/adrdecs.sv b/src/mmu/adrdecs.sv index d71fef82a..d8e6530d3 100644 --- a/src/mmu/adrdecs.sv +++ b/src/mmu/adrdecs.sv @@ -33,7 +33,7 @@ module adrdecs import cvw::*; #(parameter cvw_t P) ( input logic [P.PA_BITS-1:0] PhysicalAddress, input logic AccessRW, AccessRX, AccessRWXC, input logic [1:0] Size, - output logic [11:0] SelRegions + output logic [12:0] SelRegions ); localparam logic [3:0] SUPPORTED_SIZE = (P.LLEN == 32 ? 4'b0111 : 4'b1111); @@ -49,6 +49,7 @@ module adrdecs import cvw::*; #(parameter cvw_t P) ( adrdec #(P.PA_BITS) plicdec(PhysicalAddress, P.PLIC_BASE[P.PA_BITS-1:0], P.PLIC_RANGE[P.PA_BITS-1:0], P.PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[9]); adrdec #(P.PA_BITS) sdcdec(PhysicalAddress, P.SDC_BASE[P.PA_BITS-1:0], P.SDC_RANGE[P.PA_BITS-1:0], P.SDC_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE & 4'b1100, SelRegions[10]); adrdec #(P.PA_BITS) spidec(PhysicalAddress, P.SPI_BASE[P.PA_BITS-1:0], P.SPI_RANGE[P.PA_BITS-1:0], P.SPI_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[11]); + adrdec #(P.PA_BITS) progbufdec(PhysicalAddress, P.PROGBUF_BASE[P.PA_BITS-1:0], P.PROGBUF_RANGE[P.PA_BITS-1:0], P.DEBUG_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[12]); assign SelRegions[0] = ~|(SelRegions[11:1]); // none of the regions are selected endmodule diff --git a/src/mmu/mmu.sv b/src/mmu/mmu.sv index ec41773a8..e5e3ab5e5 100644 --- a/src/mmu/mmu.sv +++ b/src/mmu/mmu.sv @@ -50,6 +50,7 @@ module mmu import cvw::*; #(parameter cvw_t P, output logic Cacheable, // PMA indicates memory address is cachable output logic Idempotent, // PMA indicates memory address is idempotent output logic SelTIM, // Select a tightly integrated memory + output logic SelProgBuf, // Select ProgBuf // Faults output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, // access fault sources output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM, // page fault sources @@ -112,7 +113,7 @@ module mmu import cvw::*; #(parameter cvw_t P, pmachecker #(P) pmachecker(.PhysicalAddress, .Size, .CMOpM, .AtomicAccessM, .ExecuteAccessF, .WriteAccessM, .ReadAccessM, .PBMemoryType, - .Cacheable, .Idempotent, .SelTIM, + .Cacheable, .Idempotent, .SelTIM, .SelProgBuf, .PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM); if (P.PMP_ENTRIES > 0) begin : pmp diff --git a/src/mmu/pmachecker.sv b/src/mmu/pmachecker.sv index b1953cb9b..86faf190e 100644 --- a/src/mmu/pmachecker.sv +++ b/src/mmu/pmachecker.sv @@ -38,7 +38,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) ( input logic WriteAccessM, // Write access input logic ReadAccessM, // Read access input logic [1:0] PBMemoryType, // PBMT field of PTE during TLB hit, or 00 otherwise - output logic Cacheable, Idempotent, SelTIM, + output logic Cacheable, Idempotent, SelTIM, SelProgBuf, output logic PMAInstrAccessFaultF, output logic PMALoadAccessFaultM, output logic PMAStoreAmoAccessFaultM @@ -46,7 +46,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) ( logic PMAAccessFault; logic AccessRW, AccessRWXC, AccessRX; - logic [11:0] SelRegions; + logic [12:0] SelRegions; logic AtomicAllowed; logic CacheableRegion, IdempotentRegion; @@ -72,6 +72,9 @@ module pmachecker import cvw::*; #(parameter cvw_t P) ( // Check if tightly integrated memories are selected assign SelTIM = SelRegions[1] | SelRegions[2]; // exclusion-tag: unused-tim + // Debug program buffer + assign SelProgBuf = SelRegions[12]; + // Detect access faults assign PMAAccessFault = SelRegions[0] & AccessRWXC | AtomicAccessM & ~AtomicAllowed; assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault; diff --git a/src/privileged/csr.sv b/src/privileged/csr.sv index 26abfb137..48cd38268 100644 --- a/src/privileged/csr.sv +++ b/src/privileged/csr.sv @@ -96,9 +96,9 @@ module csr import cvw::*; #(parameter cvw_t P) ( // Debug Mode output input logic DebugMode, input logic [2:0] DebugCause, + output logic ebreakEn, output logic Step, output logic [P.XLEN-1:0] DPC, - input logic [P.XLEN-1:0] PCNextF, input logic EnterDebugMode, // Debug scan chain input logic DebugSel, @@ -215,10 +215,10 @@ module csr import cvw::*; #(parameter cvw_t P) ( /////////////////////////////////////////// assign CSRAdrM = InstrM[31:20]; - assign UnalignedNextEPCM = TrapM ? PCM : CSRWriteValDM; + assign UnalignedNextEPCM = TrapM ? PCM : CSRWriteValM; assign NextEPCM = P.ZCA_SUPPORTED ? {UnalignedNextEPCM[P.XLEN-1:1], 1'b0} : {UnalignedNextEPCM[P.XLEN-1:2], 2'b00}; // 3.1.15 alignment - assign NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValDM[P.XLEN-1], CSRWriteValDM[3:0]}; - assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValDM; + assign NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValM[P.XLEN-1], CSRWriteValM[3:0]}; + assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM; assign UngatedCSRMWriteM = CSRWriteDM & (PrivilegeModeW == P.M_MODE); assign CSRMWriteM = UngatedCSRMWriteM & InstrValidNotFlushedM; assign CSRSWriteM = CSRWriteDM & (|PrivilegeModeW) & InstrValidNotFlushedM; @@ -305,7 +305,7 @@ module csr import cvw::*; #(parameter cvw_t P) ( if (P.DEBUG_SUPPORTED) begin:csrd csrd #(P) csrd(.clk, .reset, .DebugMode, .PrivilegeModeW, .CSRWriteDM, .CSRAdrM(CSRAdrDM), .CSRWriteValM(CSRWriteValDM), .CSRDReadValM, .IllegalCSRDAccessM, - .DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode); + .DebugCause, .ebreakEn, .Step, .DPC, .PCM, .EnterDebugMode); end else begin assign CSRDReadValM = '0; assign IllegalCSRDAccessM = 1'b1; // Debug isn't supported diff --git a/src/privileged/csrd.sv b/src/privileged/csrd.sv index af8185791..29f77929a 100644 --- a/src/privileged/csrd.sv +++ b/src/privileged/csrd.sv @@ -35,12 +35,12 @@ module csrd import cvw::*; #(parameter cvw_t P) ( input logic [P.XLEN-1:0] CSRWriteValM, output logic [P.XLEN-1:0] CSRDReadValM, output logic IllegalCSRDAccessM, - + input logic [P.XLEN-1:0] PCM, + input logic EnterDebugMode, input logic [2:0] DebugCause, + output logic ebreakEn, output logic Step, - output logic [P.XLEN-1:0] DPC, - input logic [P.XLEN-1:0] PCNextF, - input logic EnterDebugMode + output logic [P.XLEN-1:0] DPC ); `include "debug.vh" @@ -58,8 +58,8 @@ module csrd import cvw::*; #(parameter cvw_t P) ( const logic ebreakVS = 0; const logic ebreakVU = 0; logic ebreakM; - logic ebreakS; - logic ebreakU; + const logic ebreakS = 0; + const logic ebreakU = 0; const logic StepIE = 0; const logic StopCount = 0; const logic StopTime = 0; @@ -69,7 +69,8 @@ module csrd import cvw::*; #(parameter cvw_t P) ( logic NMIP; // pending non-maskable interrupt logic [1:0] Prv; - + + assign ebreakEn = ebreakM; // Only support ebreak from M mode assign CSRDWriteM = CSRWriteDM & (PrivilegeModeW == P.M_MODE) & DebugMode; assign WriteDCSRM = CSRDWriteM & (CSRAdrM == DCSR_ADDR); @@ -85,15 +86,13 @@ module csrd import cvw::*; #(parameter cvw_t P) ( end end - flopenr #(4) DCSRreg (clk, reset, WriteDCSRM, - {CSRWriteValM[`EBREAKM], CSRWriteValM[`EBREAKS], CSRWriteValM[`EBREAKU], CSRWriteValM[`STEP]}, - {ebreakM, ebreakS, ebreakU, Step}); + flopenr #(4) DCSRreg (clk, reset, WriteDCSRM, {CSRWriteValM[`EBREAKM], CSRWriteValM[`STEP]}, {ebreakM, Step}); assign DCSR = {DebugVer, 10'b0, ebreakVS, ebreakVU, ebreakM, 1'b0, ebreakS, ebreakU, StepIE, StopCount, StopTime, Cause, V, MPrvEn, NMIP, Step, Prv}; - assign DPCWriteVal = EnterDebugMode ? PCNextF : CSRWriteValM; - flopenr #(P.XLEN) DPCreg (clk, reset, WriteDPCM | EnterDebugMode, DPCWriteVal, DPC); + assign DPCWriteVal = EnterDebugMode ? PCM : CSRWriteValM; + flopenr #(P.XLEN) DPCreg (clk, reset, WriteDPCM | EnterDebugMode, DPCWriteVal, DPC); // TODO: reset to something sane (0x80000000?) always_comb begin CSRDReadValM = '0; diff --git a/src/privileged/privdec.sv b/src/privileged/privdec.sv index 60828a3f2..756bc309c 100644 --- a/src/privileged/privdec.sv +++ b/src/privileged/privdec.sv @@ -30,7 +30,8 @@ module privdec import cvw::*; #(parameter cvw_t P) ( input logic clk, reset, - input logic StallW, FlushW, + input logic StallW, FlushW, + input logic ForceBreakPoint, // Debug Module initiated break to debug mode input logic [31:15] InstrM, // privileged instruction function field input logic PrivilegedM, // is this a privileged instruction (from IEU controller) input logic IllegalIEUFPUInstrM, // Not a legal IEU instruction @@ -40,13 +41,14 @@ module privdec import cvw::*; #(parameter cvw_t P) ( output logic IllegalInstrFaultM, // Illegal instruction output logic EcallFaultM, BreakpointFaultM, // Ecall or breakpoint; must retire, so don't flush it when the trap occurs output logic sretM, mretM, RetM, // return instructions - output logic wfiM, wfiW, sfencevmaM // wfi / sfence.vma / sinval.vma instructions + output logic wfiM, wfiW, sfencevmaM, // wfi / sfence.vma / sinval.vma instructions + output logic ebreakM // ebreak instruction ); logic rs1zeroM; // rs1 field = 0 logic IllegalPrivilegedInstrM; // privileged instruction isn't a legal one or in legal mode logic WFITimeoutM; // WFI reaches timeout threshold - logic ebreakM, ecallM; // ebreak / ecall instructions + logic ecallM; // ecall instructions logic sinvalvmaM; // sinval.vma logic sfencewinvalM, sfenceinvalirM; // sfence.w.inval, sfence.inval.ir logic invalM; // any of the svinval instructions @@ -94,7 +96,10 @@ module privdec import cvw::*; #(parameter cvw_t P) ( // Extract exceptions by name and handle them /////////////////////////////////////////// - assign BreakpointFaultM = ebreakM; // could have other causes from a debugger + if (P.DEBUG_SUPPORTED) + assign BreakpointFaultM = ebreakM | ForceBreakPoint; + else + assign BreakpointFaultM = ebreakM; assign EcallFaultM = ecallM; /////////////////////////////////////////// diff --git a/src/privileged/privileged.sv b/src/privileged/privileged.sv index fb7d56fc7..0aa23be7f 100644 --- a/src/privileged/privileged.sv +++ b/src/privileged/privileged.sv @@ -97,12 +97,14 @@ module privileged import cvw::*; #(parameter cvw_t P) ( output logic BigEndianM, // Use big endian in current privilege mode // Fault outputs output logic wfiM, IntPendingM, // Stall in Memory stage for WFI until interrupt pending or timeout + output logic ebreakM, // Notifies DM to enter debug mode // Debuge Mode + output logic ebreakEn, + input logic ForceBreakPoint, input logic DebugMode, input logic [2:0] DebugCause, output logic Step, output logic [P.XLEN-1:0] DPC, - input logic [P.XLEN-1:0] PCNextF, input logic EnterDebugMode, // Debug scan chain input logic DebugSel, @@ -142,9 +144,9 @@ module privileged import cvw::*; #(parameter cvw_t P) ( // decode privileged instructions privdec #(P) pmd(.clk, .reset, .StallW, .FlushW, .InstrM(InstrM[31:15]), - .PrivilegedM, .IllegalIEUFPUInstrM, .IllegalCSRAccessM, + .PrivilegedM, .IllegalIEUFPUInstrM, .IllegalCSRAccessM, .ForceBreakPoint, .PrivilegeModeW, .STATUS_TSR, .STATUS_TVM, .STATUS_TW, .IllegalInstrFaultM, - .EcallFaultM, .BreakpointFaultM, .sretM, .mretM, .RetM, .wfiM, .wfiW, .sfencevmaM); + .EcallFaultM, .BreakpointFaultM, .sretM, .mretM, .RetM, .wfiM, .wfiW, .sfencevmaM, .ebreakM); // Control and Status Registers csr #(P) csr(.clk, .reset, .FlushM, .FlushW, .StallE, .StallM, .StallW, @@ -163,7 +165,7 @@ module privileged import cvw::*; #(parameter cvw_t P) ( .SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .EPCM, .TrapVectorM, .CSRReadValW, .IllegalCSRAccessM, .BigEndianM, - .DebugMode, .DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode, + .DebugMode, .DebugCause, .ebreakEn, .Step, .DPC, .EnterDebugMode, .DebugSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn, .DebugScanIn, .DebugScanOut); // pipeline early-arriving trap sources diff --git a/src/wally/wallypipelinedcore.sv b/src/wally/wallypipelinedcore.sv index d9199f13c..ee6ec1d08 100644 --- a/src/wally/wallypipelinedcore.sv +++ b/src/wally/wallypipelinedcore.sv @@ -53,6 +53,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( output logic ResumeAck, output logic HaveReset, output logic DebugStall, + input logic ExecProgBuff, // Debug scan chain input logic DebugScanEn, // puts scannable flops into scan mode output logic DebugScanOut, // (misc) scan chain data out @@ -66,13 +67,16 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( input logic CSRSel, // selects CSR scan chain input logic [11:0] DebugRegAddr, // address for scanable regfiles (GPR, FPR, CSR) input logic DebugCapture, // latches values into scan register before scanning out - input logic DebugRegUpdate // writes values from scan register after scanning in + input logic DebugRegUpdate, // writes values from scan register after scanning in + input logic [3:0] ProgBufAddr, + input logic ProgBuffScanEn ); logic StallF, StallD, StallE, StallM, StallW; logic FlushD, FlushE, FlushM, FlushW; logic TrapM, RetM; logic DebugMode, Step; + logic ebreakEn; // signals that must connect through DP logic IntDivE, W64E; @@ -190,13 +194,14 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( logic BranchD, BranchE, JumpD, JumpE; logic DCacheStallM, ICacheStallF; logic wfiM, IntPendingM; + logic ebreakM; // Debug mode logic logic [P.XLEN-1:0] DPC, PCNextF; logic ExitDebugMode; logic EnterDebugMode; logic [2:0] DebugCause; - logic ForceNOP; + logic ForceBreakPoint; // Debug register scan chain interconnects logic [2:0] DebugScanReg; @@ -222,7 +227,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_ADUE, .ITLBWriteF, .sfencevmaM, .ITLBMissF, // pmp/pma (inside mmu) signals. .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF, .InstrUpdateDAF, - .ExitDebugMode, .DPC, .PCNextF, .ForceNOP, + .ExitDebugMode, .DPC, .PCNextF, .ProgBuffScanEn, .ProgBufAddr, .ProgBufScanIn(DebugScanIn), .DebugScanEn(DebugScanEn & MiscSel), .DebugScanIn(DebugScanReg[0]), .DebugScanOut(DebugScanReg[1])); // integer execution unit: integer register file, datapath and controller @@ -320,9 +325,9 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( if (P.DEBUG_SUPPORTED) begin dmc debugcontrol( .clk, .reset, - .Step, .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, + .Step, .ebreakM, .ebreakEn, .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .ResumeAck, .HaveReset, .DebugMode, .DebugCause, .DebugStall, - .EnterDebugMode, .ExitDebugMode, .ForceNOP); + .EnterDebugMode, .ExitDebugMode, .ForceBreakPoint); end else begin assign DebugStall = 1'b0; end @@ -349,8 +354,8 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .PrivilegeModeW, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, - .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .wfiM, .IntPendingM, .BigEndianM, - .DebugMode, .DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode, + .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .wfiM, .IntPendingM, .BigEndianM, .ebreakM, + .ebreakEn, .ForceBreakPoint, .DebugMode, .DebugCause, .Step, .DPC, .EnterDebugMode, .DebugSel(CSRSel), .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn(DebugScanEn & CSRSel), .DebugScanIn, .DebugScanOut(CSRScanOut)); if (P.DEBUG_SUPPORTED) begin flopenrs #(1) scantrapm (.clk, .reset, .en(DebugCapture), .d(TrapM), .q(), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanReg[0])); diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 118702b10..8b6188727 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -82,6 +82,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( logic ResumeAck; logic HaveReset; logic DebugStall; + logic ExecProgBuff; // Debug Module signals logic DebugScanEn; logic DebugScanIn; @@ -96,9 +97,8 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( logic [11:0] DebugRegAddr; logic DebugCapture; logic DebugRegUpdate; + logic [3:0] ProgBufAddr; logic ProgBuffScanEn; - logic ProgBuffScanOut; - logic ExecProgBuff; // synchronize reset to SOC clock domain synchronizer resetsync(.clk, .d(reset_ext), .q(reset)); @@ -108,9 +108,10 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( .MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT, .HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, - .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .ResumeAck, .HaveReset, .DebugStall, + .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .ResumeAck, .HaveReset, .DebugStall, .ExecProgBuff, .DebugScanEn, .DebugScanOut(DebugScanIn), .GPRScanOut(GPRScanIn), .FPRScanOut(FPRScanIn), .CSRScanOut(CSRScanIn), - .DebugScanIn(DebugScanOut), .MiscSel, .GPRSel, .FPRSel, .CSRSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate); + .DebugScanIn(DebugScanOut), .MiscSel, .GPRSel, .FPRSel, .CSRSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate, + .ProgBufAddr, .ProgBuffScanEn); // instantiate uncore if a bus interface exists if (P.BUS_SUPPORTED) begin : uncoregen // Hack to work around Verilator bug https://github.com/verilator/verilator/issues/4769 @@ -130,7 +131,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .ResumeAck, .HaveReset, .DebugStall, .DebugScanEn, .DebugScanIn, .GPRScanIn, .FPRScanIn, .CSRScanIn, .DebugScanOut, .MiscSel, .GPRSel, .FPRSel, .CSRSel, .RegAddr(DebugRegAddr), .DebugCapture, .DebugRegUpdate, - .ProgBuffScanEn, .ProgBuffScanOut, .ExecProgBuff); + .ProgBufAddr, .ProgBuffScanEn, .ExecProgBuff); end endmodule