Implement progbuf and attempt to halt/resume using existing trap logic (very broken)

This commit is contained in:
Matthew 2024-06-19 23:06:16 -05:00
parent 5c593c3321
commit 9514eab75e
20 changed files with 282 additions and 123 deletions

View File

@ -38,7 +38,13 @@ random_order = False
def prog_buff_test(cvw): def prog_buff_test(cvw):
cvw.halt() 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() print()
@ -46,10 +52,13 @@ def flow_control_test(cvw):
#time.sleep(70) # wait for OpenSBI #time.sleep(70) # wait for OpenSBI
cvw.halt() cvw.halt()
cvw.read_data("DCSR") time.sleep(1)
#cvw.read_data("DCSR")
for _ in range(50): for _ in range(50):
cvw.step() cvw.resume()
print(cvw.read_data("PCM")) cvw.halt()
#cvw.step()
#print(cvw.read_data("PCM"))
cvw.resume() cvw.resume()
@ -154,11 +163,11 @@ def random_hex(reg_name):
with OpenOCD() as cvw: with OpenOCD() as cvw:
print(cvw.read_dmi("0x16")) #cvw.trst()
cvw.trst()
cvw.reset_dm() cvw.reset_dm()
time.sleep(1)
cvw.reset_hart() cvw.reset_hart()
quit() time.sleep(1)
#register_rw_test(cvw) #register_rw_test(cvw)
flow_control_test(cvw) #flow_control_test(cvw)
#prog_buff_test(cvw) prog_buff_test(cvw)

View File

@ -114,6 +114,12 @@ class OpenOCD:
raise Exception("Error: Hart failed to reset") raise Exception("Error: Hart failed to reset")
self.write_dmi("0x10", "0x10000001") # ack HaveReset 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): def set_haltonreset(self):
self.write_dmi("0x10", "0x9") self.write_dmi("0x10", "0x9")
@ -139,7 +145,7 @@ class OpenOCD:
dcsr |= 0x4 dcsr |= 0x4
self.write_data("DCSR", hex(dcsr)) self.write_data("DCSR", hex(dcsr))
# Resume once # Resume once
self.resume() self.write_dmi("0x10", "0x40000001")
# Unset step bit # Unset step bit
dcsr &= ~0x4 dcsr &= ~0x4
self.write_data("DCSR", hex(dcsr)) self.write_data("DCSR", hex(dcsr))

View File

@ -186,6 +186,9 @@ localparam logic [63:0] SDC_RANGE = 64'h0000007F;
localparam logic SPI_SUPPORTED = 1; localparam logic SPI_SUPPORTED = 1;
localparam logic [63:0] SPI_BASE = 64'h10040000; localparam logic [63:0] SPI_BASE = 64'h10040000;
localparam logic [63:0] SPI_RANGE = 64'h00000FFF; 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 // Bus Interface width
localparam AHBW = (XLEN); localparam AHBW = (XLEN);

View File

@ -48,6 +48,21 @@
`define ABSTRACTAUTO `ADDR_WIDTH'h18 `define ABSTRACTAUTO `ADDR_WIDTH'h18
`define NEXTDM `ADDR_WIDTH'h1d `define NEXTDM `ADDR_WIDTH'h1d
`define PROGBUF0 `ADDR_WIDTH'h20 `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 dmcs2 `ADDR_WIDTH'h32
`define SBCS `ADDR_WIDTH'h38 `define SBCS `ADDR_WIDTH'h38

View File

@ -85,6 +85,8 @@ localparam cvw_t P = '{
SPI_SUPPORTED : SPI_SUPPORTED, SPI_SUPPORTED : SPI_SUPPORTED,
SPI_BASE : SPI_BASE, SPI_BASE : SPI_BASE,
SPI_RANGE : SPI_RANGE, SPI_RANGE : SPI_RANGE,
PROGBUF_BASE : PROGBUF_BASE,
PROGBUF_RANGE : PROGBUF_RANGE,
GPIO_LOOPBACK_TEST : GPIO_LOOPBACK_TEST, GPIO_LOOPBACK_TEST : GPIO_LOOPBACK_TEST,
SPI_LOOPBACK_TEST : SPI_LOOPBACK_TEST, SPI_LOOPBACK_TEST : SPI_LOOPBACK_TEST,
UART_PRESCALE : UART_PRESCALE , UART_PRESCALE : UART_PRESCALE ,

View File

@ -140,6 +140,9 @@ typedef struct packed {
logic SPI_SUPPORTED; logic SPI_SUPPORTED;
logic [63:0] SPI_BASE; logic [63:0] SPI_BASE;
logic [63:0] SPI_RANGE; 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 // Test modes

View File

@ -74,12 +74,14 @@ module dm import cvw::*; #(parameter cvw_t P) (
output logic DebugRegUpdate, // writes values from scan register after scanning in output logic DebugRegUpdate, // writes values from scan register after scanning in
// Program Buffer // Program Buffer
output logic [3:0] ProgBufAddr,
output logic ProgBuffScanEn, output logic ProgBuffScanEn,
output logic ProgBuffScanOut,
output logic ExecProgBuff output logic ExecProgBuff
); );
`include "debug.vh" `include "debug.vh"
localparam PROGBUF_SIZE = (P.PROGBUF_RANGE+1)/4;
// DMI Signals // DMI Signals
logic ReqReady; logic ReqReady;
logic ReqValid; logic ReqValid;
@ -93,7 +95,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
// JTAG ID for Wally: // JTAG ID for Wally:
// Version [31:28] = 0x1 : 0001 // 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) // JEDEC number [11:1] = 0x602 : Bank 13 (1100) Open HW Group (0000010)
// [0] = 1 // [0] = 1
localparam JTAG_DEVICE_ID = 32'h1002AC05; localparam JTAG_DEVICE_ID = 32'h1002AC05;
@ -151,7 +153,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
// DMStatus // DMStatus
const logic NdmResetPending = 0; const logic NdmResetPending = 0;
const logic StickyUnavail = 0; const logic StickyUnavail = 0;
const logic ImpEBreak = 1; const logic ImpEBreak = 0;
logic AllHaveReset; logic AllHaveReset;
logic AnyHaveReset; logic AnyHaveReset;
logic AllResumeAck; logic AllResumeAck;
@ -170,7 +172,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
const logic ConfStrPtrValid = 0; // Used with SysBusAccess const logic ConfStrPtrValid = 0; // Used with SysBusAccess
const logic [3:0] Version = 3; // DM Version const logic [3:0] Version = 3; // DM Version
// AbstractCS // AbstractCS
const logic [4:0] ProgBufSize = 1; const logic [4:0] ProgBufSize = PROGBUF_SIZE;
logic Busy; logic Busy;
const logic RelaxedPriv = 1; const logic RelaxedPriv = 1;
logic [2:0] CmdErr; logic [2:0] CmdErr;
@ -233,27 +235,27 @@ module dm import cvw::*; #(parameter cvw_t P) (
IDLE : begin IDLE : begin
if (ReqValid) if (ReqValid)
case ({ReqOP, ReqAddress}) inside case ({ReqOP, ReqAddress}) inside
{`OP_WRITE,`DATA0} : State <= W_DATA; {`OP_WRITE,`DATA0} : State <= W_DATA;
{`OP_READ,`DATA0} : State <= R_DATA; {`OP_READ,`DATA0} : State <= R_DATA;
{`OP_WRITE,`DATA1} : State <= (P.LLEN >= 64) ? W_DATA : INVALID; {`OP_WRITE,`DATA1} : State <= (P.LLEN >= 64) ? W_DATA : INVALID;
{`OP_READ,`DATA1} : State <= (P.LLEN >= 64) ? R_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_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_READ,`DATA2}:{`OP_READ,`DATA3}] : State <= (P.LLEN >= 128) ? R_DATA : INVALID;
{`OP_WRITE,`DMCONTROL} : State <= W_DMCONTROL; {`OP_WRITE,`DMCONTROL} : State <= W_DMCONTROL;
{`OP_READ,`DMCONTROL} : State <= R_DMCONTROL; {`OP_READ,`DMCONTROL} : State <= R_DMCONTROL;
{`OP_READ,`DMSTATUS} : State <= DMSTATUS; {`OP_READ,`DMSTATUS} : State <= DMSTATUS;
{`OP_WRITE,`ABSTRACTCS} : State <= W_ABSTRACTCS; {`OP_WRITE,`ABSTRACTCS} : State <= W_ABSTRACTCS;
{`OP_READ,`ABSTRACTCS} : State <= R_ABSTRACTCS; {`OP_READ,`ABSTRACTCS} : State <= R_ABSTRACTCS;
{`OP_WRITE,`COMMAND} : State <= ABST_COMMAND; {`OP_WRITE,`COMMAND} : State <= ABST_COMMAND;
{`OP_READ,`COMMAND} : State <= READ_ZERO; {`OP_READ,`COMMAND} : State <= READ_ZERO;
{`OP_WRITE,`SBCS} : State <= READ_ZERO; {`OP_WRITE,`SBCS} : State <= READ_ZERO;
{`OP_READ,`SBCS} : State <= R_SYSBUSCS; {`OP_READ,`SBCS} : State <= R_SYSBUSCS;
{`OP_WRITE,`PROGBUF0} : State <= W_PROGBUF; [{`OP_WRITE,`PROGBUF0}:{`OP_WRITE,`PROGBUF3}] : State <= W_PROGBUF; // TODO: update decode range dynamically using PROGBUF_RANGE
{`OP_READ,`PROGBUF0}, [{`OP_READ,`PROGBUF0}:{`OP_READ,`PROGBUFF}],
{2'bx,`HARTINFO}, {2'bx,`HARTINFO},
{2'bx,`ABSTRACTAUTO}, {2'bx,`ABSTRACTAUTO},
{2'bx,`NEXTDM} : State <= READ_ZERO; {2'bx,`NEXTDM} : State <= READ_ZERO;
default : State <= READ_ZERO;//INVALID; default : State <= INVALID;
endcase endcase
end end
@ -369,8 +371,10 @@ module dm import cvw::*; #(parameter cvw_t P) (
W_PROGBUF : begin W_PROGBUF : begin
if (Busy) if (Busy)
CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr;
else else begin
NewAcState <= PROGBUFF_WRITE; NewAcState <= PROGBUFF_WRITE;
ProgBufAddr <= ReqAddress[$clog2(PROGBUF_SIZE)-1:0];
end
RspOP <= `OP_SUCCESS; RspOP <= `OP_SUCCESS;
State <= ACK; State <= ACK;
end end
@ -441,7 +445,6 @@ module dm import cvw::*; #(parameter cvw_t P) (
// Program Buffer // Program Buffer
assign ProgBuffScanEn = (AcState == PROGBUFF_WRITE); assign ProgBuffScanEn = (AcState == PROGBUFF_WRITE);
assign ProgBuffScanOut = ScanReg[0];
// Scan Chain // Scan Chain
assign DebugScanOut = ScanReg[0]; assign DebugScanOut = ScanReg[0];

View File

@ -27,12 +27,28 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
// Note: This module controls all of the per-hart debug state. // On HaltReq/eBreak:
// In a multihart system, this module should be instantiated under wallypipelinedcore // 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 ( module dmc (
input logic clk, reset, input logic clk, reset,
input logic Step, 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 HaltReq, // Initiates core halt
input logic ResumeReq, // Initiates core resume input logic ResumeReq, // Initiates core resume
input logic HaltOnReset, // Halts core immediately on hart reset 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 EnterDebugMode, // Store PCNextF in DPC when entering Debug Mode
output logic ExitDebugMode, // Updates PCNextF with the current value of DPC 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" `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; localparam E2M_CYCLE_COUNT = 3;
logic [$clog2(NOP_CYCLE_DURATION+1)-1:0] Counter; logic [$clog2(E2M_CYCLE_COUNT+1)-1:0] Counter;
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
if (reset) if (reset)
@ -62,12 +78,13 @@ module dmc (
HaveReset <= 0; HaveReset <= 0;
end end
assign DebugMode = (State != RUNNING); assign ForceBreakPoint = (State == RUNNING) & HaltReq | (State == STEP) & ~|Counter;
assign DebugStall = (State == HALTED);
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 ExitDebugMode = (State == HALTED) & ResumeReq;
assign ForceNOP = (State == FLUSH);
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
if (reset) begin if (reset) begin
@ -77,34 +94,38 @@ module dmc (
case (State) case (State)
RUNNING : begin RUNNING : begin
if (HaltReq) 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; State <= HALTED;
else DebugCause <= `CAUSE_HALTREQ;
Counter <= Counter - 1; end else if (ebreakM & ebreakEn) begin
State <= HALTED;
DebugCause <= `CAUSE_EBREAK;
end
end end
HALTED : begin HALTED : begin
if (ResumeReq) begin if (ResumeReq)
if (Step) begin State <= RESUME;
Counter <= NOP_CYCLE_DURATION; end
State <= FLUSH;
DebugCause <= `CAUSE_STEP; // Wait a cycle to load PCF from DPC before resuming
end else begin // TODO: test without resume stage
State <= RUNNING; RESUME : begin
ResumeAck <= 1; if (Step) begin
end Counter <= E2M_CYCLE_COUNT;
State <= STEP;
end else begin
State <= RUNNING;
ResumeAck <= 1;
end end
end end
STEP : begin
if (~|Counter) begin
DebugCause <= `CAUSE_STEP;
State <= HALTED;
end else
Counter <= Counter - 1;
end
endcase endcase
end end
end end

View File

@ -108,9 +108,8 @@ module hazard import cvw::*; #(parameter cvw_t P) (
assign LatestUnstalledW = ~StallW & StallM; 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 // 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 = (LatestUnstalledD | FlushDCause);
assign FlushD = ~DebugStall & (LatestUnstalledD | FlushDCause); assign FlushE = (LatestUnstalledE | FlushECause);
assign FlushE = ~DebugStall & (LatestUnstalledE | FlushECause); assign FlushM = (LatestUnstalledM | FlushMCause);
assign FlushM = ~DebugStall & (LatestUnstalledM | FlushMCause); assign FlushW = (LatestUnstalledW | FlushWCause);
assign FlushW = ~DebugStall & (LatestUnstalledW | FlushWCause);
endmodule endmodule

View File

@ -98,11 +98,13 @@ module ifu import cvw::*; #(parameter cvw_t P) (
output logic ICacheAccess, // Report I$ read to performance counters output logic ICacheAccess, // Report I$ read to performance counters
output logic ICacheMiss, // Report I$ miss to performance counters output logic ICacheMiss, // Report I$ miss to performance counters
// Debug Mode logic // 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 ExitDebugMode,
input logic [P.XLEN-1:0] DPC, 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 ProgBuffScanEn,
input logic ForceNOP,
// Debug scan chain // Debug scan chain
input logic [3:0] ProgBufAddr,
input logic ProgBufScanIn,
input logic DebugScanEn, input logic DebugScanEn,
input logic DebugScanIn, input logic DebugScanIn,
output logic DebugScanOut 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 [31:0] nop = 32'h00000013; // instruction for NOP
localparam LINELEN = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS : P.XLEN; 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] 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] 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. 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] IROMInstrF; // Instruction from the IROM
logic [31:0] ICacheInstrF; // Instruction from the I$ logic [31:0] ICacheInstrF; // Instruction from the I$
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus 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 CompressedF, CompressedE; // The fetched instruction is compressed
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage 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 BusCommittedF; // Bus memory operation in flight, delay interrupts
logic CacheCommittedF; // I$ memory operation started, delay interrupts logic CacheCommittedF; // I$ memory operation started, delay interrupts
logic SelIROM; // PMA indicates instruction address is in the IROM 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 [15:0] InstrRawE, InstrRawM;
logic [LINELEN-1:0] FetchBuffer; logic [LINELEN-1:0] FetchBuffer;
logic [31:0] ShiftUncachedInstr; logic [31:0] ShiftUncachedInstr;
@ -196,7 +199,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
.TLBFlush, .TLBFlush,
.PhysicalAddress(PCPF), .PhysicalAddress(PCPF),
.TLBMiss(ITLBMissF), .TLBMiss(ITLBMissF),
.Cacheable(CacheableF), .Idempotent(), .SelTIM(SelIROM), .Cacheable(CacheableF), .Idempotent(), .SelTIM(SelIROM), .SelProgBuf,
.InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(), .InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(),
.InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(), .InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(),
.LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(), .LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(),
@ -209,6 +212,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
assign PCPF = PCFExt[P.PA_BITS-1:0]; assign PCPF = PCFExt[P.PA_BITS-1:0];
assign CacheableF = 1'b1; assign CacheableF = 1'b1;
assign SelIROM = '0; assign SelIROM = '0;
assign SelProgBuf = '0;
end end
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
@ -218,7 +222,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
// CommittedM tells the CPU's privileged unit the current instruction // 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 // 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. // 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. // delay the interrupt until the LSU is in a clean state.
assign CommittedF = CacheCommittedF | BusCommittedF; assign CommittedF = CacheCommittedF | BusCommittedF;
@ -314,7 +318,14 @@ module ifu import cvw::*; #(parameter cvw_t P) (
assign IFUStallF = IFUCacheBusStallF | SelSpillNextF; assign IFUStallF = IFUCacheBusStallF | SelSpillNextF;
assign GatedStallD = StallD & ~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 // 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)); mux2 #(P.XLEN) pcmux2(.d0(PC1NextF), .d1(NextValidPCE), .s(CSRWriteFenceM),.y(PC2NextF));
else assign PC2NextF = PC1NextF; else assign PC2NextF = PC1NextF;
mux3 #(P.XLEN) pcmux3(PC2NextF, EPCM, TrapVectorM, {TrapM, RetM}, UnalignedPCNextF); mux3 #(P.XLEN) pcmux3(PC2NextF, EPCM, TrapVectorM, {TrapM, RetM}, UnalignedPCNextF);
if (P.DEBUG_SUPPORTED) begin 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); 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));
assign PCNextF = ExitDebugMode ? DPC : PCNextFM;
flopen #(P.XLEN) pcreg(clk, ~StallF | reset | ExitDebugMode, PCNextF, PCF); flopen #(P.XLEN) pcreg(clk, ~StallF | reset | ExitDebugMode, PCNextF, PCF);
end else begin end else begin
mux2 #(P.XLEN) pcresetmux({UnalignedPCNextF[P.XLEN-1:1], 1'b0}, P.RESET_VECTOR[P.XLEN-1:0], reset, PCNextF); mux2 #(P.XLEN) pcresetmux({UnalignedPCNextF[P.XLEN-1:1], 1'b0}, P.RESET_VECTOR[P.XLEN-1:0], reset, PCNextF);

69
src/ifu/progbuf.sv Normal file
View File

@ -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

View File

@ -33,7 +33,7 @@ module adrdecs import cvw::*; #(parameter cvw_t P) (
input logic [P.PA_BITS-1:0] PhysicalAddress, input logic [P.PA_BITS-1:0] PhysicalAddress,
input logic AccessRW, AccessRX, AccessRWXC, input logic AccessRW, AccessRX, AccessRWXC,
input logic [1:0] Size, 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); 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) 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) 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) 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 assign SelRegions[0] = ~|(SelRegions[11:1]); // none of the regions are selected
endmodule endmodule

View File

@ -50,6 +50,7 @@ module mmu import cvw::*; #(parameter cvw_t P,
output logic Cacheable, // PMA indicates memory address is cachable output logic Cacheable, // PMA indicates memory address is cachable
output logic Idempotent, // PMA indicates memory address is idempotent output logic Idempotent, // PMA indicates memory address is idempotent
output logic SelTIM, // Select a tightly integrated memory output logic SelTIM, // Select a tightly integrated memory
output logic SelProgBuf, // Select ProgBuf
// Faults // Faults
output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, // access fault sources output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, // access fault sources
output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM, // page 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, pmachecker #(P) pmachecker(.PhysicalAddress, .Size, .CMOpM,
.AtomicAccessM, .ExecuteAccessF, .WriteAccessM, .ReadAccessM, .PBMemoryType, .AtomicAccessM, .ExecuteAccessF, .WriteAccessM, .ReadAccessM, .PBMemoryType,
.Cacheable, .Idempotent, .SelTIM, .Cacheable, .Idempotent, .SelTIM, .SelProgBuf,
.PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM); .PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM);
if (P.PMP_ENTRIES > 0) begin : pmp if (P.PMP_ENTRIES > 0) begin : pmp

View File

@ -38,7 +38,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
input logic WriteAccessM, // Write access input logic WriteAccessM, // Write access
input logic ReadAccessM, // Read access input logic ReadAccessM, // Read access
input logic [1:0] PBMemoryType, // PBMT field of PTE during TLB hit, or 00 otherwise 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 PMAInstrAccessFaultF,
output logic PMALoadAccessFaultM, output logic PMALoadAccessFaultM,
output logic PMAStoreAmoAccessFaultM output logic PMAStoreAmoAccessFaultM
@ -46,7 +46,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
logic PMAAccessFault; logic PMAAccessFault;
logic AccessRW, AccessRWXC, AccessRX; logic AccessRW, AccessRWXC, AccessRX;
logic [11:0] SelRegions; logic [12:0] SelRegions;
logic AtomicAllowed; logic AtomicAllowed;
logic CacheableRegion, IdempotentRegion; logic CacheableRegion, IdempotentRegion;
@ -72,6 +72,9 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
// Check if tightly integrated memories are selected // Check if tightly integrated memories are selected
assign SelTIM = SelRegions[1] | SelRegions[2]; // exclusion-tag: unused-tim assign SelTIM = SelRegions[1] | SelRegions[2]; // exclusion-tag: unused-tim
// Debug program buffer
assign SelProgBuf = SelRegions[12];
// Detect access faults // Detect access faults
assign PMAAccessFault = SelRegions[0] & AccessRWXC | AtomicAccessM & ~AtomicAllowed; assign PMAAccessFault = SelRegions[0] & AccessRWXC | AtomicAccessM & ~AtomicAllowed;
assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault; assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault;

View File

@ -96,9 +96,9 @@ module csr import cvw::*; #(parameter cvw_t P) (
// Debug Mode output // Debug Mode output
input logic DebugMode, input logic DebugMode,
input logic [2:0] DebugCause, input logic [2:0] DebugCause,
output logic ebreakEn,
output logic Step, output logic Step,
output logic [P.XLEN-1:0] DPC, output logic [P.XLEN-1:0] DPC,
input logic [P.XLEN-1:0] PCNextF,
input logic EnterDebugMode, input logic EnterDebugMode,
// Debug scan chain // Debug scan chain
input logic DebugSel, input logic DebugSel,
@ -215,10 +215,10 @@ module csr import cvw::*; #(parameter cvw_t P) (
/////////////////////////////////////////// ///////////////////////////////////////////
assign CSRAdrM = InstrM[31:20]; 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 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 NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValM[P.XLEN-1], CSRWriteValM[3:0]};
assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValDM; assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM;
assign UngatedCSRMWriteM = CSRWriteDM & (PrivilegeModeW == P.M_MODE); assign UngatedCSRMWriteM = CSRWriteDM & (PrivilegeModeW == P.M_MODE);
assign CSRMWriteM = UngatedCSRMWriteM & InstrValidNotFlushedM; assign CSRMWriteM = UngatedCSRMWriteM & InstrValidNotFlushedM;
assign CSRSWriteM = CSRWriteDM & (|PrivilegeModeW) & InstrValidNotFlushedM; assign CSRSWriteM = CSRWriteDM & (|PrivilegeModeW) & InstrValidNotFlushedM;
@ -305,7 +305,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
if (P.DEBUG_SUPPORTED) begin:csrd if (P.DEBUG_SUPPORTED) begin:csrd
csrd #(P) csrd(.clk, .reset, .DebugMode, .PrivilegeModeW, csrd #(P) csrd(.clk, .reset, .DebugMode, .PrivilegeModeW,
.CSRWriteDM, .CSRAdrM(CSRAdrDM), .CSRWriteValM(CSRWriteValDM), .CSRDReadValM, .IllegalCSRDAccessM, .CSRWriteDM, .CSRAdrM(CSRAdrDM), .CSRWriteValM(CSRWriteValDM), .CSRDReadValM, .IllegalCSRDAccessM,
.DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode); .DebugCause, .ebreakEn, .Step, .DPC, .PCM, .EnterDebugMode);
end else begin end else begin
assign CSRDReadValM = '0; assign CSRDReadValM = '0;
assign IllegalCSRDAccessM = 1'b1; // Debug isn't supported assign IllegalCSRDAccessM = 1'b1; // Debug isn't supported

View File

@ -35,12 +35,12 @@ module csrd import cvw::*; #(parameter cvw_t P) (
input logic [P.XLEN-1:0] CSRWriteValM, input logic [P.XLEN-1:0] CSRWriteValM,
output logic [P.XLEN-1:0] CSRDReadValM, output logic [P.XLEN-1:0] CSRDReadValM,
output logic IllegalCSRDAccessM, output logic IllegalCSRDAccessM,
input logic [P.XLEN-1:0] PCM,
input logic EnterDebugMode,
input logic [2:0] DebugCause, input logic [2:0] DebugCause,
output logic ebreakEn,
output logic Step, output logic Step,
output logic [P.XLEN-1:0] DPC, output logic [P.XLEN-1:0] DPC
input logic [P.XLEN-1:0] PCNextF,
input logic EnterDebugMode
); );
`include "debug.vh" `include "debug.vh"
@ -58,8 +58,8 @@ module csrd import cvw::*; #(parameter cvw_t P) (
const logic ebreakVS = 0; const logic ebreakVS = 0;
const logic ebreakVU = 0; const logic ebreakVU = 0;
logic ebreakM; logic ebreakM;
logic ebreakS; const logic ebreakS = 0;
logic ebreakU; const logic ebreakU = 0;
const logic StepIE = 0; const logic StepIE = 0;
const logic StopCount = 0; const logic StopCount = 0;
const logic StopTime = 0; const logic StopTime = 0;
@ -70,6 +70,7 @@ module csrd import cvw::*; #(parameter cvw_t P) (
logic [1:0] Prv; logic [1:0] Prv;
assign ebreakEn = ebreakM; // Only support ebreak from M mode
assign CSRDWriteM = CSRWriteDM & (PrivilegeModeW == P.M_MODE) & DebugMode; assign CSRDWriteM = CSRWriteDM & (PrivilegeModeW == P.M_MODE) & DebugMode;
assign WriteDCSRM = CSRDWriteM & (CSRAdrM == DCSR_ADDR); assign WriteDCSRM = CSRDWriteM & (CSRAdrM == DCSR_ADDR);
@ -85,15 +86,13 @@ module csrd import cvw::*; #(parameter cvw_t P) (
end end
end end
flopenr #(4) DCSRreg (clk, reset, WriteDCSRM, flopenr #(4) DCSRreg (clk, reset, WriteDCSRM, {CSRWriteValM[`EBREAKM], CSRWriteValM[`STEP]}, {ebreakM, Step});
{CSRWriteValM[`EBREAKM], CSRWriteValM[`EBREAKS], CSRWriteValM[`EBREAKU], CSRWriteValM[`STEP]},
{ebreakM, ebreakS, ebreakU, Step});
assign DCSR = {DebugVer, 10'b0, ebreakVS, ebreakVU, ebreakM, 1'b0, ebreakS, ebreakU, StepIE, assign DCSR = {DebugVer, 10'b0, ebreakVS, ebreakVU, ebreakM, 1'b0, ebreakS, ebreakU, StepIE,
StopCount, StopTime, Cause, V, MPrvEn, NMIP, Step, Prv}; StopCount, StopTime, Cause, V, MPrvEn, NMIP, Step, Prv};
assign DPCWriteVal = EnterDebugMode ? PCNextF : CSRWriteValM; assign DPCWriteVal = EnterDebugMode ? PCM : CSRWriteValM;
flopenr #(P.XLEN) DPCreg (clk, reset, WriteDPCM | EnterDebugMode, DPCWriteVal, DPC); flopenr #(P.XLEN) DPCreg (clk, reset, WriteDPCM | EnterDebugMode, DPCWriteVal, DPC); // TODO: reset to something sane (0x80000000?)
always_comb begin always_comb begin
CSRDReadValM = '0; CSRDReadValM = '0;

View File

@ -31,6 +31,7 @@
module privdec import cvw::*; #(parameter cvw_t P) ( module privdec import cvw::*; #(parameter cvw_t P) (
input logic clk, reset, 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 [31:15] InstrM, // privileged instruction function field
input logic PrivilegedM, // is this a privileged instruction (from IEU controller) input logic PrivilegedM, // is this a privileged instruction (from IEU controller)
input logic IllegalIEUFPUInstrM, // Not a legal IEU instruction 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 IllegalInstrFaultM, // Illegal instruction
output logic EcallFaultM, BreakpointFaultM, // Ecall or breakpoint; must retire, so don't flush it when the trap occurs 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 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 rs1zeroM; // rs1 field = 0
logic IllegalPrivilegedInstrM; // privileged instruction isn't a legal one or in legal mode logic IllegalPrivilegedInstrM; // privileged instruction isn't a legal one or in legal mode
logic WFITimeoutM; // WFI reaches timeout threshold logic WFITimeoutM; // WFI reaches timeout threshold
logic ebreakM, ecallM; // ebreak / ecall instructions logic ecallM; // ecall instructions
logic sinvalvmaM; // sinval.vma logic sinvalvmaM; // sinval.vma
logic sfencewinvalM, sfenceinvalirM; // sfence.w.inval, sfence.inval.ir logic sfencewinvalM, sfenceinvalirM; // sfence.w.inval, sfence.inval.ir
logic invalM; // any of the svinval instructions 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 // 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; assign EcallFaultM = ecallM;
/////////////////////////////////////////// ///////////////////////////////////////////

View File

@ -97,12 +97,14 @@ module privileged import cvw::*; #(parameter cvw_t P) (
output logic BigEndianM, // Use big endian in current privilege mode output logic BigEndianM, // Use big endian in current privilege mode
// Fault outputs // Fault outputs
output logic wfiM, IntPendingM, // Stall in Memory stage for WFI until interrupt pending or timeout 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 // Debuge Mode
output logic ebreakEn,
input logic ForceBreakPoint,
input logic DebugMode, input logic DebugMode,
input logic [2:0] DebugCause, input logic [2:0] DebugCause,
output logic Step, output logic Step,
output logic [P.XLEN-1:0] DPC, output logic [P.XLEN-1:0] DPC,
input logic [P.XLEN-1:0] PCNextF,
input logic EnterDebugMode, input logic EnterDebugMode,
// Debug scan chain // Debug scan chain
input logic DebugSel, input logic DebugSel,
@ -142,9 +144,9 @@ module privileged import cvw::*; #(parameter cvw_t P) (
// decode privileged instructions // decode privileged instructions
privdec #(P) pmd(.clk, .reset, .StallW, .FlushW, .InstrM(InstrM[31:15]), 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, .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 // Control and Status Registers
csr #(P) csr(.clk, .reset, .FlushM, .FlushW, .StallE, .StallM, .StallW, 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, .SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE,
.EPCM, .TrapVectorM, .EPCM, .TrapVectorM,
.CSRReadValW, .IllegalCSRAccessM, .BigEndianM, .CSRReadValW, .IllegalCSRAccessM, .BigEndianM,
.DebugMode, .DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode, .DebugMode, .DebugCause, .ebreakEn, .Step, .DPC, .EnterDebugMode,
.DebugSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn, .DebugScanIn, .DebugScanOut); .DebugSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn, .DebugScanIn, .DebugScanOut);
// pipeline early-arriving trap sources // pipeline early-arriving trap sources

View File

@ -53,6 +53,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
output logic ResumeAck, output logic ResumeAck,
output logic HaveReset, output logic HaveReset,
output logic DebugStall, output logic DebugStall,
input logic ExecProgBuff,
// Debug scan chain // Debug scan chain
input logic DebugScanEn, // puts scannable flops into scan mode input logic DebugScanEn, // puts scannable flops into scan mode
output logic DebugScanOut, // (misc) scan chain data out 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 CSRSel, // selects CSR scan chain
input logic [11:0] DebugRegAddr, // address for scanable regfiles (GPR, FPR, CSR) 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 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 StallF, StallD, StallE, StallM, StallW;
logic FlushD, FlushE, FlushM, FlushW; logic FlushD, FlushE, FlushM, FlushW;
logic TrapM, RetM; logic TrapM, RetM;
logic DebugMode, Step; logic DebugMode, Step;
logic ebreakEn;
// signals that must connect through DP // signals that must connect through DP
logic IntDivE, W64E; logic IntDivE, W64E;
@ -190,13 +194,14 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
logic BranchD, BranchE, JumpD, JumpE; logic BranchD, BranchE, JumpD, JumpE;
logic DCacheStallM, ICacheStallF; logic DCacheStallM, ICacheStallF;
logic wfiM, IntPendingM; logic wfiM, IntPendingM;
logic ebreakM;
// Debug mode logic // Debug mode logic
logic [P.XLEN-1:0] DPC, PCNextF; logic [P.XLEN-1:0] DPC, PCNextF;
logic ExitDebugMode; logic ExitDebugMode;
logic EnterDebugMode; logic EnterDebugMode;
logic [2:0] DebugCause; logic [2:0] DebugCause;
logic ForceNOP; logic ForceBreakPoint;
// Debug register scan chain interconnects // Debug register scan chain interconnects
logic [2:0] DebugScanReg; 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, .STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_ADUE, .ITLBWriteF, .sfencevmaM, .ITLBMissF,
// pmp/pma (inside mmu) signals. // pmp/pma (inside mmu) signals.
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF, .InstrUpdateDAF, .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])); .DebugScanEn(DebugScanEn & MiscSel), .DebugScanIn(DebugScanReg[0]), .DebugScanOut(DebugScanReg[1]));
// integer execution unit: integer register file, datapath and controller // 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 if (P.DEBUG_SUPPORTED) begin
dmc debugcontrol( dmc debugcontrol(
.clk, .reset, .clk, .reset,
.Step, .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .Step, .ebreakM, .ebreakEn, .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset,
.ResumeAck, .HaveReset, .DebugMode, .DebugCause, .DebugStall, .ResumeAck, .HaveReset, .DebugMode, .DebugCause, .DebugStall,
.EnterDebugMode, .ExitDebugMode, .ForceNOP); .EnterDebugMode, .ExitDebugMode, .ForceBreakPoint);
end else begin end else begin
assign DebugStall = 1'b0; assign DebugStall = 1'b0;
end end
@ -349,8 +354,8 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.PrivilegeModeW, .SATP_REGW, .PrivilegeModeW, .SATP_REGW,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS,
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .wfiM, .IntPendingM, .BigEndianM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .wfiM, .IntPendingM, .BigEndianM, .ebreakM,
.DebugMode, .DebugCause, .Step, .DPC, .PCNextF, .EnterDebugMode, .ebreakEn, .ForceBreakPoint, .DebugMode, .DebugCause, .Step, .DPC, .EnterDebugMode,
.DebugSel(CSRSel), .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn(DebugScanEn & CSRSel), .DebugScanIn, .DebugScanOut(CSRScanOut)); .DebugSel(CSRSel), .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn(DebugScanEn & CSRSel), .DebugScanIn, .DebugScanOut(CSRScanOut));
if (P.DEBUG_SUPPORTED) begin if (P.DEBUG_SUPPORTED) begin
flopenrs #(1) scantrapm (.clk, .reset, .en(DebugCapture), .d(TrapM), .q(), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanReg[0])); flopenrs #(1) scantrapm (.clk, .reset, .en(DebugCapture), .d(TrapM), .q(), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanReg[0]));

View File

@ -82,6 +82,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
logic ResumeAck; logic ResumeAck;
logic HaveReset; logic HaveReset;
logic DebugStall; logic DebugStall;
logic ExecProgBuff;
// Debug Module signals // Debug Module signals
logic DebugScanEn; logic DebugScanEn;
logic DebugScanIn; logic DebugScanIn;
@ -96,9 +97,8 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
logic [11:0] DebugRegAddr; logic [11:0] DebugRegAddr;
logic DebugCapture; logic DebugCapture;
logic DebugRegUpdate; logic DebugRegUpdate;
logic [3:0] ProgBufAddr;
logic ProgBuffScanEn; logic ProgBuffScanEn;
logic ProgBuffScanOut;
logic ExecProgBuff;
// synchronize reset to SOC clock domain // synchronize reset to SOC clock domain
synchronizer resetsync(.clk, .d(reset_ext), .q(reset)); 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, .MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT,
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB,
.HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .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), .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 // 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 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, .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .ResumeAck, .HaveReset, .DebugStall,
.DebugScanEn, .DebugScanIn, .GPRScanIn, .FPRScanIn, .CSRScanIn, .DebugScanOut, .DebugScanEn, .DebugScanIn, .GPRScanIn, .FPRScanIn, .CSRScanIn, .DebugScanOut,
.MiscSel, .GPRSel, .FPRSel, .CSRSel, .RegAddr(DebugRegAddr), .DebugCapture, .DebugRegUpdate, .MiscSel, .GPRSel, .FPRSel, .CSRSel, .RegAddr(DebugRegAddr), .DebugCapture, .DebugRegUpdate,
.ProgBuffScanEn, .ProgBuffScanOut, .ExecProgBuff); .ProgBufAddr, .ProgBuffScanEn, .ExecProgBuff);
end end
endmodule endmodule