mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Implement DCSR (Writes are broken)
This commit is contained in:
parent
d319703d75
commit
6ae7ac9a6d
@ -35,6 +35,7 @@ from openocd_tcl_wrapper import OpenOCD
|
|||||||
random_stimulus = True
|
random_stimulus = True
|
||||||
random_order = False
|
random_order = False
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
with OpenOCD() as cvw:
|
with OpenOCD() as cvw:
|
||||||
registers = dict.fromkeys(cvw.register_translations.keys(),[])
|
registers = dict.fromkeys(cvw.register_translations.keys(),[])
|
||||||
|
@ -131,14 +131,12 @@ class OpenOCD:
|
|||||||
dmstat = int(self.read_dmi("0x11"), 16) # Check resumeack bit
|
dmstat = int(self.read_dmi("0x11"), 16) # Check resumeack bit
|
||||||
if not ((dmstat >> 16) & 0x3):
|
if not ((dmstat >> 16) & 0x3):
|
||||||
raise Exception("Error: Hart failed to resume")
|
raise Exception("Error: Hart failed to resume")
|
||||||
self.write_dmi("0x10", "0x40000001") # Clear resumeack bit
|
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
self.write_dmi("0x10", "0xC0000001")
|
# Set halt bit #TODO save curent value of dcsr
|
||||||
# BOZO: checking resumeack after halt is pointless until sdext halt method is added
|
self.write_data("DCSR", "0x4")
|
||||||
dmstat = int(self.read_dmi("0x11"), 16)
|
# Resume
|
||||||
if not ((dmstat >> 16) & 0x3):
|
#self.resume()
|
||||||
raise Exception("Error: Hart failed to resume")
|
|
||||||
|
|
||||||
def access_register(self, write, regno, addr_size=None):
|
def access_register(self, write, regno, addr_size=None):
|
||||||
data = 1 << 17 # transfer bit always set
|
data = 1 << 17 # transfer bit always set
|
||||||
|
@ -101,6 +101,20 @@
|
|||||||
`define CMDTYPE 31:24
|
`define CMDTYPE 31:24
|
||||||
`define CONTROL 23:0
|
`define CONTROL 23:0
|
||||||
|
|
||||||
|
// DCSR
|
||||||
|
`define EBREAKVS 17
|
||||||
|
`define EBREAKVU 16
|
||||||
|
`define EBREAKM 15
|
||||||
|
`define EBREAKS 13
|
||||||
|
`define EBREAKU 12
|
||||||
|
`define STEPIE 11
|
||||||
|
`define STOPCOUNT 10
|
||||||
|
`define STOPTIME 9
|
||||||
|
`define V 5
|
||||||
|
`define MPRVEN 4
|
||||||
|
`define STEP 2
|
||||||
|
`define PRV 1:0
|
||||||
|
|
||||||
//// Abstract Commands
|
//// Abstract Commands
|
||||||
// cmderr
|
// cmderr
|
||||||
`define CMDERR_NONE 3'h0
|
`define CMDERR_NONE 3'h0
|
||||||
|
@ -26,14 +26,10 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// TODO List:
|
// TODO List:
|
||||||
// fix CSR scanning
|
|
||||||
// determine config/permissions of all CSRs
|
// determine config/permissions of all CSRs
|
||||||
// DCSR and DPC should exist even when not privileged_supported
|
|
||||||
// test all combinations of XLEN/FLEN
|
|
||||||
// improve halting / implement "debug mode"
|
// improve halting / implement "debug mode"
|
||||||
//// Debug Mode = M-mode with stalled pipe
|
//// Debug Mode = M-mode with stalled pipe
|
||||||
// Flush pipe with NOPs during halt?
|
// Flush pipe with NOPs during halt?
|
||||||
// implement better steps
|
|
||||||
// Alias DPC to PCF/PCNextF?
|
// Alias DPC to PCF/PCNextF?
|
||||||
|
|
||||||
// (stretch) add system bus access?
|
// (stretch) add system bus access?
|
||||||
@ -51,8 +47,14 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// Platform reset signal
|
// Platform reset signal
|
||||||
output logic NdmReset,
|
output logic NdmReset,
|
||||||
// Core hazard signal
|
// Core control signals
|
||||||
output logic DebugStall,
|
input logic ResumeAck, // Signals Hart has been resumed
|
||||||
|
input logic HaveReset, // Signals Hart has been reset
|
||||||
|
input logic DebugMode, // Signals core is halted
|
||||||
|
output logic HaltReq, // Initiates core halt
|
||||||
|
output logic ResumeReq, // Initiates core resume
|
||||||
|
output logic HaltOnReset, // Halts core immediately on hart reset
|
||||||
|
output logic AckHaveReset, // Clears HaveReset status
|
||||||
|
|
||||||
// Scan Chain
|
// Scan Chain
|
||||||
output logic DebugScanEn, // puts scannable flops into scan mode
|
output logic DebugScanEn, // puts scannable flops into scan mode
|
||||||
@ -83,28 +85,16 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [1:0] RspOP;
|
logic [1:0] RspOP;
|
||||||
|
|
||||||
// JTAG ID for Wally:
|
// JTAG ID for Wally:
|
||||||
// [31:27] = 1 (4 bits)
|
// Version [31:28] = 0x1 : 0001
|
||||||
// ver [27:12] = 0x2A (42)
|
// PartNumber [27:12] = 0x2A : 00000000_00101010
|
||||||
// JEDEC number [11:1] = 000_0000_0010 (Open HW Group)
|
// JEDEC number [11:1] = 0x602 : Bank 13 (1100) Open HW Group (0000010)
|
||||||
// [0] set to 1
|
// [0] = 1
|
||||||
localparam JTAG_DEVICE_ID = 32'h1002_A005;
|
localparam JTAG_DEVICE_ID = 32'h1002AC05;
|
||||||
|
|
||||||
dtm #(`ADDR_WIDTH, JTAG_DEVICE_ID) dtm (.clk, .tck, .tdi, .tms, .tdo,
|
dtm #(`ADDR_WIDTH, JTAG_DEVICE_ID) dtm (.clk, .tck, .tdi, .tms, .tdo,
|
||||||
.ReqReady, .ReqValid, .ReqAddress, .ReqData, .ReqOP, .RspReady,
|
.ReqReady, .ReqValid, .ReqAddress, .ReqData, .ReqOP, .RspReady,
|
||||||
.RspValid, .RspData, .RspOP);
|
.RspValid, .RspData, .RspOP);
|
||||||
|
|
||||||
// Core control signals
|
|
||||||
logic HaltReq;
|
|
||||||
logic ResumeReq;
|
|
||||||
logic HaltOnReset;
|
|
||||||
logic Halted;
|
|
||||||
logic AckHaveReset;
|
|
||||||
|
|
||||||
hartcontrol hartcontrol(.clk, .rst(rst | ~DmActive), .NdmReset, .AckHaveReset, .HaltReq,
|
|
||||||
.ResumeReq, .HaltOnReset, .DebugStall, .Halted, .AllRunning, .AnyRunning,
|
|
||||||
.AllHalted, .AnyHalted, .AllResumeAck, .AnyResumeAck, .AllHaveReset, .AnyHaveReset);
|
|
||||||
|
|
||||||
|
|
||||||
enum logic [3:0] {INACTIVE, IDLE, ACK, R_DATA, W_DATA, DMSTATUS, W_DMCONTROL, R_DMCONTROL,
|
enum logic [3:0] {INACTIVE, IDLE, ACK, R_DATA, W_DATA, DMSTATUS, W_DMCONTROL, R_DMCONTROL,
|
||||||
W_ABSTRACTCS, R_ABSTRACTCS, ABST_COMMAND, R_SYSBUSCS, READ_ZERO,
|
W_ABSTRACTCS, R_ABSTRACTCS, ABST_COMMAND, R_SYSBUSCS, READ_ZERO,
|
||||||
INVALID} State;
|
INVALID} State;
|
||||||
@ -149,7 +139,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
//// DM register fields
|
//// DM register fields
|
||||||
// DMControl
|
// DMControl
|
||||||
logic AckUnavail;
|
logic AckUnavail;
|
||||||
logic DmActive; // This bit is used to (de)activate the DM. Toggling acts as reset
|
logic DmActive; // This bit is used to (de)activate the DM. Toggling off/on acts as reset
|
||||||
// DMStatus
|
// DMStatus
|
||||||
logic StickyUnavail;
|
logic StickyUnavail;
|
||||||
logic ImpEBreak;
|
logic ImpEBreak;
|
||||||
@ -157,10 +147,10 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic AnyHaveReset;
|
logic AnyHaveReset;
|
||||||
logic AllResumeAck;
|
logic AllResumeAck;
|
||||||
logic AnyResumeAck;
|
logic AnyResumeAck;
|
||||||
logic AllNonExistent; // TODO
|
const logic AllNonExistent = 0;
|
||||||
logic AnyNonExistent;
|
const logic AnyNonExistent = 0;
|
||||||
logic AllUnavail; // TODO
|
const logic AllUnavail = 0;
|
||||||
logic AnyUnavail;
|
const logic AnyUnavail = 0;
|
||||||
logic AllRunning;
|
logic AllRunning;
|
||||||
logic AnyRunning;
|
logic AnyRunning;
|
||||||
logic AllHalted;
|
logic AllHalted;
|
||||||
@ -177,6 +167,18 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [2:0] CmdErr;
|
logic [2:0] CmdErr;
|
||||||
const logic [3:0] DataCount = (P.LLEN/32);
|
const logic [3:0] DataCount = (P.LLEN/32);
|
||||||
|
|
||||||
|
// Core control signals
|
||||||
|
assign AllHaveReset = HaveReset;
|
||||||
|
assign AnyHaveReset = HaveReset;
|
||||||
|
assign AnyHalted = DebugMode;
|
||||||
|
assign AllHalted = DebugMode;
|
||||||
|
assign AnyRunning = ~DebugMode;
|
||||||
|
assign AllRunning = ~DebugMode;
|
||||||
|
// I believe resumeack is used to determine when a resume is requested but never completes
|
||||||
|
// It's pretty worthless in this implementation (complain to the debug working group)
|
||||||
|
assign AllResumeAck = ResumeAck;
|
||||||
|
assign AnyResumeAck = ResumeAck;
|
||||||
|
|
||||||
// See spec 3.14.2
|
// See spec 3.14.2
|
||||||
assign DMControl = {2'b0, 1'b0, 2'b0, 1'b0, 10'b0, 10'b0, 4'b0, NdmReset, DmActive};
|
assign DMControl = {2'b0, 1'b0, 2'b0, 1'b0, 10'b0, 10'b0, 4'b0, NdmReset, DmActive};
|
||||||
|
|
||||||
@ -290,7 +292,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
// hartreset, ackhavereset, setresethaltreq, and clrresethaltreq. The others must be written 0
|
// hartreset, ackhavereset, setresethaltreq, and clrresethaltreq. The others must be written 0
|
||||||
case ({ReqData[`RESUMEREQ],ReqData[`ACKHAVERESET],ReqData[`SETRESETHALTREQ],ReqData[`CLRRESETHALTREQ]})
|
case ({ReqData[`RESUMEREQ],ReqData[`ACKHAVERESET],ReqData[`SETRESETHALTREQ],ReqData[`CLRRESETHALTREQ]})
|
||||||
4'b0000 :; // None
|
4'b0000 :; // None
|
||||||
4'b1000 : ResumeReq <= 1;
|
4'b1000 : ResumeReq <= ~ReqData[`HALTREQ]; // Ignore ResumeReq if HaltReq
|
||||||
4'b0100 : AckHaveReset <= 1;
|
4'b0100 : AckHaveReset <= 1;
|
||||||
4'b0010 : HaltOnReset <= 1;
|
4'b0010 : HaltOnReset <= 1;
|
||||||
4'b0001 : HaltOnReset <= 0;
|
4'b0001 : HaltOnReset <= 0;
|
||||||
@ -338,7 +340,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
if (CmdErr != `CMDERR_NONE); // If CmdErr, do nothing
|
if (CmdErr != `CMDERR_NONE); // If CmdErr, do nothing
|
||||||
else if (Busy)
|
else if (Busy)
|
||||||
CmdErr <= `CMDERR_BUSY; // If Busy, set CmdErr, do nothing
|
CmdErr <= `CMDERR_BUSY; // If Busy, set CmdErr, do nothing
|
||||||
else if (~Halted)
|
else if (~DebugMode)
|
||||||
CmdErr <= `CMDERR_HALTRESUME; // If not halted, set CmdErr, do nothing
|
CmdErr <= `CMDERR_HALTRESUME; // If not halted, set CmdErr, do nothing
|
||||||
else begin
|
else begin
|
||||||
case (ReqData[`CMDTYPE])
|
case (ReqData[`CMDTYPE])
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// hartcontrol.sv
|
// dmc.sv
|
||||||
//
|
//
|
||||||
// Written: matthew.n.otto@okstate.edu 10 May 2024
|
// Written: matthew.n.otto@okstate.edu 10 May 2024
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: Controls the state of connected hart
|
// Purpose: Controls pipeline during Debug Mode
|
||||||
//
|
//
|
||||||
// Documentation: RISC-V System on Chip Design
|
// Documentation: RISC-V System on Chip Design
|
||||||
//
|
//
|
||||||
@ -30,72 +30,43 @@
|
|||||||
// Note: This module controls all of the per-hart debug state.
|
// Note: This module controls all of the per-hart debug state.
|
||||||
// In a multihart system, this module should be instantiated under wallypipelinedcore
|
// In a multihart system, this module should be instantiated under wallypipelinedcore
|
||||||
|
|
||||||
module hartcontrol(
|
module dmc(
|
||||||
input logic clk, rst,
|
input logic clk, reset,
|
||||||
input logic NdmReset, // Triggers HaltOnReset behavior
|
input logic Step,
|
||||||
input logic AckHaveReset, // Clears *HaveReset status
|
input logic HaltReq, // Initiates core halt
|
||||||
|
|
||||||
input logic HaltReq, // Initiate 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
|
||||||
|
input logic AckHaveReset, // Clears HaveReset status
|
||||||
|
|
||||||
output logic DebugStall, // Stall signal goes to hazard unit
|
output logic DebugMode,
|
||||||
|
output logic ResumeAck, // Signals Hart has been resumed
|
||||||
// DMStatus bits
|
output logic HaveReset, // Signals Hart has been reset
|
||||||
output logic Halted,
|
output logic DebugStall // Stall signal goes to hazard unit
|
||||||
output logic AllRunning,
|
|
||||||
output logic AnyRunning,
|
|
||||||
output logic AllHalted,
|
|
||||||
output logic AnyHalted,
|
|
||||||
output logic AllResumeAck,
|
|
||||||
output logic AnyResumeAck,
|
|
||||||
output logic AllHaveReset,
|
|
||||||
output logic AnyHaveReset
|
|
||||||
);
|
);
|
||||||
enum logic {RUNNING, HALTED} State;
|
enum logic {RUNNING, HALTED} State;
|
||||||
|
|
||||||
assign AnyHaveReset = AllHaveReset;
|
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (NdmReset)
|
if (reset)
|
||||||
AllHaveReset <= 1;
|
HaveReset <= 1;
|
||||||
else if (AckHaveReset)
|
else if (AckHaveReset)
|
||||||
AllHaveReset <= 0;
|
HaveReset <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
assign Halted = DebugStall;
|
|
||||||
assign AllRunning = ~DebugStall;
|
|
||||||
assign AnyRunning = ~DebugStall;
|
|
||||||
assign AllHalted = DebugStall;
|
|
||||||
assign AnyHalted = DebugStall;
|
|
||||||
// BOZO: when sdext is implemented (proper step support is added)
|
|
||||||
// change ResumeReq to be ignored when HaltReq
|
|
||||||
// but ResumeReq should still always clear *ResumeAck
|
|
||||||
assign AnyResumeAck = AllResumeAck;
|
|
||||||
|
|
||||||
|
assign DebugMode = (State != RUNNING); // TODO: update this
|
||||||
assign DebugStall = (State == HALTED);
|
assign DebugStall = (State == HALTED);
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (rst)
|
if (reset)
|
||||||
State <= RUNNING;
|
|
||||||
else if (NdmReset)
|
|
||||||
State <= HaltOnReset ? HALTED : RUNNING;
|
State <= HaltOnReset ? HALTED : RUNNING;
|
||||||
else begin
|
else begin
|
||||||
case (State)
|
case (State)
|
||||||
RUNNING : begin
|
RUNNING : begin
|
||||||
if (HaltReq) begin
|
State <= Step | HaltReq ? HALTED : RUNNING;
|
||||||
State <= HALTED;
|
|
||||||
end else if (ResumeReq) begin
|
|
||||||
AllResumeAck <= 0;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
HALTED : begin
|
HALTED : begin
|
||||||
if (ResumeReq) begin
|
State <= ResumeReq ? RUNNING : HALTED;
|
||||||
State <= RUNNING;
|
ResumeAck <= ResumeReq ? 1 : ResumeAck;
|
||||||
AllResumeAck <= 1;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
@ -106,7 +106,7 @@ module rad import cvw::*; #(parameter cvw_t P) (
|
|||||||
`MIP_REGNO : begin
|
`MIP_REGNO : begin
|
||||||
ShiftCount = P.LLEN - 1;
|
ShiftCount = P.LLEN - 1;
|
||||||
CSRegNo = 1;
|
CSRegNo = 1;
|
||||||
RegReadOnly = 1; // TODO: eventually DCSR (any maybe others) will be RW
|
//RegReadOnly = 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
[`HPMCOUNTERBASE_REGNO:`TIME_REGNO],
|
[`HPMCOUNTERBASE_REGNO:`TIME_REGNO],
|
||||||
|
@ -145,7 +145,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [LINELEN-1:0] FetchBuffer;
|
logic [LINELEN-1:0] FetchBuffer;
|
||||||
logic [31:0] ShiftUncachedInstr;
|
logic [31:0] ShiftUncachedInstr;
|
||||||
// Debug scan chain
|
// Debug scan chain
|
||||||
logic DSCR; // Debug Scan Chain Register
|
logic DebugScanChainReg; // Debug Scan Chain Register
|
||||||
|
|
||||||
assign PCFExt = {2'b00, PCSpillF};
|
assign PCFExt = {2'b00, PCSpillF};
|
||||||
|
|
||||||
@ -411,22 +411,22 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
if (P.ZICSR_SUPPORTED | P.A_SUPPORTED) begin
|
if (P.ZICSR_SUPPORTED | P.A_SUPPORTED) begin
|
||||||
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
|
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
|
||||||
if (P.DEBUG_SUPPORTED)
|
if (P.DEBUG_SUPPORTED)
|
||||||
flopenrs #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM, DebugScanEn, DSCR, DebugScanOut);
|
flopenrs #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM, DebugScanEn, DebugScanChainReg, DebugScanOut);
|
||||||
else
|
else
|
||||||
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
|
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
|
||||||
end else begin
|
end else begin
|
||||||
assign InstrM = '0;
|
assign InstrM = '0;
|
||||||
assign DebugScanOut = DSCR;
|
assign DebugScanOut = DebugScanChainReg;
|
||||||
end
|
end
|
||||||
// PCM is only needed with CSRs or branch prediction
|
// PCM is only needed with CSRs or branch prediction
|
||||||
if (P.ZICSR_SUPPORTED | P.BPRED_SUPPORTED)
|
if (P.ZICSR_SUPPORTED | P.BPRED_SUPPORTED)
|
||||||
if (P.DEBUG_SUPPORTED)
|
if (P.DEBUG_SUPPORTED)
|
||||||
flopenrs #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM, DebugScanEn, DebugScanIn, DSCR);
|
flopenrs #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM, DebugScanEn, DebugScanIn, DebugScanChainReg);
|
||||||
else
|
else
|
||||||
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
|
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
|
||||||
else begin
|
else begin
|
||||||
assign PCM = '0;
|
assign PCM = '0;
|
||||||
assign DSCR = DebugScanIn;
|
assign DebugScanChainReg = DebugScanIn;
|
||||||
end
|
end
|
||||||
|
|
||||||
// If compressed instructions are supported, increment PCLink by 2 or 4 for a jal. Otherwise, just by 4
|
// If compressed instructions are supported, increment PCLink by 2 or 4 for a jal. Otherwise, just by 4
|
||||||
|
@ -93,6 +93,8 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR
|
output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR
|
||||||
output logic IllegalCSRAccessM, // Illegal CSR access: CSR doesn't exist or is inaccessible at this privilege level
|
output logic IllegalCSRAccessM, // Illegal CSR access: CSR doesn't exist or is inaccessible at this privilege level
|
||||||
output logic BigEndianM, // memory access is big-endian based on privilege mode and STATUS register endian fields
|
output logic BigEndianM, // memory access is big-endian based on privilege mode and STATUS register endian fields
|
||||||
|
// Debug Mode output
|
||||||
|
output logic Step,
|
||||||
// Debug scan chain
|
// Debug scan chain
|
||||||
input logic DebugSel,
|
input logic DebugSel,
|
||||||
input logic [11:0] DebugRegAddr,
|
input logic [11:0] DebugRegAddr,
|
||||||
@ -106,7 +108,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
localparam MIP = 12'h344;
|
localparam MIP = 12'h344;
|
||||||
localparam SIP = 12'h144;
|
localparam SIP = 12'h144;
|
||||||
|
|
||||||
logic [P.XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRCReadValM;
|
logic [P.XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRCReadValM, CSRDReadValM;
|
||||||
logic [P.XLEN-1:0] CSRReadValM;
|
logic [P.XLEN-1:0] CSRReadValM;
|
||||||
logic [P.XLEN-1:0] CSRSrcM;
|
logic [P.XLEN-1:0] CSRSrcM;
|
||||||
logic [P.XLEN-1:0] CSRRWM, CSRRSM, CSRRCM;
|
logic [P.XLEN-1:0] CSRRWM, CSRRSM, CSRRCM;
|
||||||
@ -116,13 +118,14 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [P.XLEN-1:0] MEPC_REGW, SEPC_REGW;
|
logic [P.XLEN-1:0] MEPC_REGW, SEPC_REGW;
|
||||||
logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW;
|
logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW;
|
||||||
logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM;
|
logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM;
|
||||||
logic CSRMWriteM, CSRSWriteM, CSRUWriteM;
|
logic CSRWriteDM;
|
||||||
|
logic CSRMWriteM, CSRSWriteM, CSRUWriteM, CSRDWriteM;
|
||||||
logic UngatedCSRMWriteM;
|
logic UngatedCSRMWriteM;
|
||||||
logic WriteFRMM, WriteFFLAGSM;
|
logic WriteFRMM, WriteFFLAGSM;
|
||||||
logic [P.XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM;
|
logic [P.XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM;
|
||||||
logic [4:0] NextCauseM;
|
logic [4:0] NextCauseM;
|
||||||
logic [11:0] CSRAdrM, CSRAdrDM;
|
logic [11:0] CSRAdrM, CSRAdrDM;
|
||||||
logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM;
|
logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM, IllegalCSRDAccessM;
|
||||||
logic InsufficientCSRPrivilegeM;
|
logic InsufficientCSRPrivilegeM;
|
||||||
logic IllegalCSRMWriteReadonlyM;
|
logic IllegalCSRMWriteReadonlyM;
|
||||||
logic [P.XLEN-1:0] CSRReadVal2M;
|
logic [P.XLEN-1:0] CSRReadVal2M;
|
||||||
@ -137,7 +140,6 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [P.XLEN-1:0] SENVCFG_REGW;
|
logic [P.XLEN-1:0] SENVCFG_REGW;
|
||||||
logic ENVCFG_STCE; // supervisor timer counter enable
|
logic ENVCFG_STCE; // supervisor timer counter enable
|
||||||
logic ENVCFG_FIOM; // fence implies io (presently not used)
|
logic ENVCFG_FIOM; // fence implies io (presently not used)
|
||||||
logic CSRMWriteDM;
|
|
||||||
|
|
||||||
// only valid unflushed instructions can access CSRs
|
// only valid unflushed instructions can access CSRs
|
||||||
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
|
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
|
||||||
@ -212,10 +214,11 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
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}: {CSRWriteValDM[P.XLEN-1], CSRWriteValDM[3:0]};
|
||||||
assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValDM;
|
assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValDM;
|
||||||
assign UngatedCSRMWriteM = CSRWriteM & (PrivilegeModeW == P.M_MODE);
|
assign UngatedCSRMWriteM = CSRWriteDM & (PrivilegeModeW == P.M_MODE);
|
||||||
assign CSRMWriteM = UngatedCSRMWriteM & InstrValidNotFlushedM;
|
assign CSRMWriteM = UngatedCSRMWriteM & InstrValidNotFlushedM;
|
||||||
assign CSRSWriteM = CSRWriteM & (|PrivilegeModeW) & InstrValidNotFlushedM;
|
assign CSRSWriteM = CSRWriteDM & (|PrivilegeModeW) & InstrValidNotFlushedM;
|
||||||
assign CSRUWriteM = CSRWriteM & InstrValidNotFlushedM;
|
assign CSRUWriteM = CSRWriteDM & InstrValidNotFlushedM;
|
||||||
|
assign CSRDWriteM = CSRWriteDM;
|
||||||
assign MTrapM = TrapM & (NextPrivilegeModeM == P.M_MODE);
|
assign MTrapM = TrapM & (NextPrivilegeModeM == P.M_MODE);
|
||||||
assign STrapM = TrapM & (NextPrivilegeModeM == P.S_MODE) & P.S_SUPPORTED;
|
assign STrapM = TrapM & (NextPrivilegeModeM == P.S_MODE) & P.S_SUPPORTED;
|
||||||
|
|
||||||
@ -283,7 +286,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
if (P.ZICNTR_SUPPORTED) begin:counters
|
if (P.ZICNTR_SUPPORTED) begin:counters
|
||||||
csrc #(P) counters(.clk, .reset, .StallE, .StallM, .FlushM,
|
csrc #(P) counters(.clk, .reset, .StallE, .StallM, .FlushM,
|
||||||
.InstrValidNotFlushedM, .LoadStallD, .StoreStallD, .CSRWriteM, .CSRMWriteM,
|
.InstrValidNotFlushedM, .LoadStallD, .StoreStallD, .CSRWriteM(CSRWriteDM), .CSRMWriteM,
|
||||||
.BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM, .BPWrongM,
|
.BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM, .BPWrongM,
|
||||||
.IClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .sfencevmaM,
|
.IClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .sfencevmaM,
|
||||||
.InterruptM, .ExceptionM, .InvalidateICacheM, .ICacheStallF, .DCacheStallM, .DivBusyE, .FDivBusyE,
|
.InterruptM, .ExceptionM, .InvalidateICacheM, .ICacheStallF, .DCacheStallM, .DivBusyE, .FDivBusyE,
|
||||||
@ -295,6 +298,16 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign IllegalCSRCAccessM = 1'b1; // counters aren't enabled
|
assign IllegalCSRCAccessM = 1'b1; // counters aren't enabled
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (P.DEBUG_SUPPORTED) begin:csrd
|
||||||
|
csrd #(P) csrd(.clk, .reset,
|
||||||
|
.CSRWriteDM, .CSRAdrM(CSRAdrDM), .CSRWriteValM(CSRWriteValDM), .CSRDReadValM, .IllegalCSRDAccessM,
|
||||||
|
.Step
|
||||||
|
);
|
||||||
|
end else begin
|
||||||
|
assign CSRDReadValM = '0;
|
||||||
|
assign IllegalCSRDAccessM = 1'b1; // Debug isn't supported
|
||||||
|
end
|
||||||
|
|
||||||
// Broadcast appropriate environment configuration based on privilege mode
|
// Broadcast appropriate environment configuration based on privilege mode
|
||||||
assign ENVCFG_STCE = MENVCFG_REGW[63]; // supervisor timer counter enable
|
assign ENVCFG_STCE = MENVCFG_REGW[63]; // supervisor timer counter enable
|
||||||
assign ENVCFG_PBMTE = MENVCFG_REGW[62]; // page-based memory types enable
|
assign ENVCFG_PBMTE = MENVCFG_REGW[62]; // page-based memory types enable
|
||||||
@ -308,7 +321,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
(MENVCFG_REGW[0] & SENVCFG_REGW[0]);
|
(MENVCFG_REGW[0] & SENVCFG_REGW[0]);
|
||||||
|
|
||||||
// merge CSR Reads
|
// merge CSR Reads
|
||||||
assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM;
|
assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM | CSRDReadValM;
|
||||||
flopenrc #(P.XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW);
|
flopenrc #(P.XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW);
|
||||||
|
|
||||||
// merge illegal accesses: illegal if none of the CSR addresses is legal or privilege is insufficient
|
// merge illegal accesses: illegal if none of the CSR addresses is legal or privilege is insufficient
|
||||||
@ -316,19 +329,19 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign InsufficientCSRPrivilegeM = (CSRAdrDM[9:8] == 2'b11 & PrivilegeModeW != P.M_MODE) |
|
assign InsufficientCSRPrivilegeM = (CSRAdrDM[9:8] == 2'b11 & PrivilegeModeW != P.M_MODE) |
|
||||||
(CSRAdrDM[9:8] == 2'b01 & PrivilegeModeW == P.U_MODE);
|
(CSRAdrDM[9:8] == 2'b01 & PrivilegeModeW == P.U_MODE);
|
||||||
assign IllegalCSRAccessM = ((IllegalCSRCAccessM & IllegalCSRMAccessM &
|
assign IllegalCSRAccessM = ((IllegalCSRCAccessM & IllegalCSRMAccessM &
|
||||||
IllegalCSRSAccessM & IllegalCSRUAccessM |
|
IllegalCSRSAccessM & IllegalCSRUAccessM /*& IllegalCSRDAccessM*/ |
|
||||||
InsufficientCSRPrivilegeM) & CSRReadM) | IllegalCSRMWriteReadonlyM;
|
InsufficientCSRPrivilegeM) & CSRReadM) | IllegalCSRMWriteReadonlyM;
|
||||||
|
|
||||||
// Debug module CSR access
|
// Debug module CSR access
|
||||||
// TODO: should DM be able to access CSRs when hart isn't in M mode?
|
// TODO: should DM be able to access CSRs when hart isn't in M mode?
|
||||||
if (P.DEBUG_SUPPORTED) begin
|
if (P.DEBUG_SUPPORTED) begin
|
||||||
assign CSRAdrDM = DebugSel ? DebugRegAddr : CSRAdrM;
|
assign CSRAdrDM = DebugSel ? DebugRegAddr : CSRAdrM;
|
||||||
//assign CSRMWriteDM = DebugSel ? DebugRegUpdate : CSRMWriteM; // TODO: add write support
|
assign CSRWriteDM = DebugSel ? DebugRegUpdate : CSRWriteM; // TODO: add write support
|
||||||
assign CSRWriteValDM = DebugSel ? DebugCSRScanVal : CSRWriteValM;
|
assign CSRWriteValDM = DebugSel ? DebugCSRScanVal : CSRWriteValM;
|
||||||
flopenrs #(P.XLEN) GPScanReg(.clk, .reset, .en(DebugCapture), .d(CSRReadValM), .q(DebugCSRScanVal), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanOut));
|
flopenrs #(P.XLEN) GPScanReg(.clk, .reset, .en(DebugCapture), .d(CSRReadValM), .q(DebugCSRScanVal), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanOut));
|
||||||
end else begin
|
end else begin
|
||||||
assign CSRAdrDM = CSRAdrM;
|
assign CSRAdrDM = CSRAdrM;
|
||||||
//assign CSRMWriteDM = CSRMWriteM;
|
assign CSRWriteDM = CSRWriteM;
|
||||||
assign CSRWriteValDM = CSRWriteValM;
|
assign CSRWriteValDM = CSRWriteValM;
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
99
src/privileged/csrd.sv
Normal file
99
src/privileged/csrd.sv
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
///////////////////////////////////////////
|
||||||
|
// csrd.sv
|
||||||
|
//
|
||||||
|
// Written: matthew.n.otto@okstate.edu
|
||||||
|
// Created: 13 June 2024
|
||||||
|
//
|
||||||
|
// Purpose: Debug Control and Status Registers
|
||||||
|
// See RISC-V Debug Specification (4.10)
|
||||||
|
//
|
||||||
|
// 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 csrd import cvw::*; #(parameter cvw_t P) (
|
||||||
|
input logic clk, reset,
|
||||||
|
input logic CSRWriteDM,
|
||||||
|
input logic [11:0] CSRAdrM,
|
||||||
|
input logic [P.XLEN-1:0] CSRWriteValM,
|
||||||
|
output logic [P.XLEN-1:0] CSRDReadValM,
|
||||||
|
output logic IllegalCSRDAccessM,
|
||||||
|
|
||||||
|
output logic Step
|
||||||
|
);
|
||||||
|
`include "debug.vh"
|
||||||
|
|
||||||
|
localparam DCSR = 12'h7B0; // Debug Control and Status Register
|
||||||
|
localparam DPC = 12'h7B1; // Debug PC
|
||||||
|
|
||||||
|
// TODO: these registers are only accessible from Debug Mode.
|
||||||
|
logic [31:0] DCSR_REGW;
|
||||||
|
logic [31:0] DPC_REGW;
|
||||||
|
logic WriteDCSRM;
|
||||||
|
logic WriteDPCM;
|
||||||
|
|
||||||
|
// DCSR fields
|
||||||
|
const logic [3:0] DebugVer = 4;
|
||||||
|
const logic ebreakVS = 0;
|
||||||
|
const logic ebreakVU = 0;
|
||||||
|
logic ebreakM;
|
||||||
|
logic ebreakS;
|
||||||
|
logic ebreakU;
|
||||||
|
const logic StepIE = 0;
|
||||||
|
const logic StopCount = 0;
|
||||||
|
const logic StopTime = 0;
|
||||||
|
logic [2:0] Cause; // TODO: give reason for entering debug mode
|
||||||
|
const logic V = 0;
|
||||||
|
const logic MPrvEn = 0;
|
||||||
|
logic NMIP; // pending non-maskable interrupt
|
||||||
|
logic [1:0] Prv;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assign WriteDCSRM = CSRWriteDM & (CSRAdrM == DCSR);
|
||||||
|
assign WriteDPCM = CSRWriteDM & (CSRAdrM == DPC);
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (reset)
|
||||||
|
Prv <= 3;
|
||||||
|
//else if (Halt) // TODO: trigger when hart enters debug mode
|
||||||
|
// Prv <= // hart priv mode
|
||||||
|
else if (WriteDCSRM)
|
||||||
|
Prv <= CSRWriteValM[`PRV]; // TODO: overwrite hart privilege mode
|
||||||
|
end
|
||||||
|
|
||||||
|
flopenr ebreakreg(clk, reset, WriteDCSRM,
|
||||||
|
{CSRWriteValM[`EBREAKM], CSRWriteValM[`EBREAKS], CSRWriteValM[`EBREAKU], CSRWriteValM[`STEP]},
|
||||||
|
{ebreakM, ebreakS, ebreakU, Step});
|
||||||
|
|
||||||
|
|
||||||
|
assign DCSR_REGW = {4'b0100, 10'b0, ebreakVS, ebreakVU, ebreakM, 1'b0, ebreakS, ebreakU, StepIE,
|
||||||
|
StopCount, StopTime, Cause, V, MPrvEn, NMIP, Step, Prv};
|
||||||
|
assign DPC_REGW = {32'hd099f00d};
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
CSRDReadValM = 0;
|
||||||
|
IllegalCSRDAccessM = 0;
|
||||||
|
case (CSRAdrM)
|
||||||
|
DCSR : CSRDReadValM = DCSR_REGW;
|
||||||
|
DPC : CSRDReadValM = DPC_REGW;
|
||||||
|
default: IllegalCSRDAccessM = 1'b1;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
@ -58,8 +58,6 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
||||||
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
||||||
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
||||||
logic [31:0] DCSR_REGW, DPC_REGW;
|
|
||||||
logic WriteDPCM, WriteDCSRM;
|
|
||||||
|
|
||||||
// Machine CSRs
|
// Machine CSRs
|
||||||
localparam MVENDORID = 12'hF11;
|
localparam MVENDORID = 12'hF11;
|
||||||
@ -91,10 +89,6 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
localparam TDATA1 = 12'h7A1;
|
localparam TDATA1 = 12'h7A1;
|
||||||
localparam TDATA2 = 12'h7A2;
|
localparam TDATA2 = 12'h7A2;
|
||||||
localparam TDATA3 = 12'h7A3;
|
localparam TDATA3 = 12'h7A3;
|
||||||
localparam DCSR = 12'h7B0; // Debug Control and Status Register
|
|
||||||
localparam DPC = 12'h7B1; // Debug PC
|
|
||||||
localparam DSCRATCH0 = 12'h7B2; // Debug Scratch Register 0 (opt)
|
|
||||||
localparam DSCRATCH1 = 12'h7B3; // Debug Scratch Register 1 (opt)
|
|
||||||
// Constants
|
// Constants
|
||||||
localparam ZERO = {(P.XLEN){1'b0}};
|
localparam ZERO = {(P.XLEN){1'b0}};
|
||||||
// when compressed instructions are supported, there can't be misaligned instructions
|
// when compressed instructions are supported, there can't be misaligned instructions
|
||||||
@ -132,9 +126,6 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// MISA is hardwired. Spec says it could be written to disable features, but this is not supported by Wally
|
// MISA is hardwired. Spec says it could be written to disable features, but this is not supported by Wally
|
||||||
assign MISA_REGW = {(P.XLEN == 32 ? 2'b01 : 2'b10), {(P.XLEN-28){1'b0}}, MISA_26[25:0]};
|
assign MISA_REGW = {(P.XLEN == 32 ? 2'b01 : 2'b10), {(P.XLEN-28){1'b0}}, MISA_26[25:0]};
|
||||||
// Debug registers (stubbed out)
|
|
||||||
assign DPC_REGW = {32'hd099f00d};
|
|
||||||
assign DCSR_REGW = {32'hdeadbeef};
|
|
||||||
|
|
||||||
// MHARTID is hardwired. It only exists as a signal so that the testbench can easily see it.
|
// MHARTID is hardwired. It only exists as a signal so that the testbench can easily see it.
|
||||||
assign MHARTID_REGW = '0;
|
assign MHARTID_REGW = '0;
|
||||||
@ -151,10 +142,8 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL));
|
assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL));
|
||||||
assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN);
|
assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN);
|
||||||
assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT);
|
assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT);
|
||||||
assign WriteDPCM = CSRMWriteM & (CSRAdrM == DPC);
|
|
||||||
assign WriteDCSRM = CSRMWriteM & (CSRAdrM == DCSR);
|
|
||||||
|
|
||||||
assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID | CSRAdrM == MCONFIGPTR); // TODO: add DPC
|
assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID | CSRAdrM == MCONFIGPTR);
|
||||||
|
|
||||||
// CSRs
|
// CSRs
|
||||||
flopenr #(P.XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW);
|
flopenr #(P.XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW);
|
||||||
@ -171,12 +160,6 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
if (P.U_SUPPORTED) begin: mcounteren // MCOUNTEREN only exists when user mode is supported
|
if (P.U_SUPPORTED) begin: mcounteren // MCOUNTEREN only exists when user mode is supported
|
||||||
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW);
|
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW);
|
||||||
end else assign MCOUNTEREN_REGW = '0;
|
end else assign MCOUNTEREN_REGW = '0;
|
||||||
if (P.DEBUG_SUPPORTED) begin
|
|
||||||
//flopenr #(32) DPCreg(clk, reset, WriteDPCM, CSRWriteValM[31:0], DPC_REGW); // TODO: update DPC from PC (M?)
|
|
||||||
//flopenr #(32) DCSRreg(clk, reset, WriteDCSRM, CSRWriteValM[31:0], DCSR_REGW); // TODO: control writes to DCSR
|
|
||||||
end else begin
|
|
||||||
assign {DPC_REGW,DCSR_REGW} = '0;
|
|
||||||
end
|
|
||||||
|
|
||||||
// MENVCFG register
|
// MENVCFG register
|
||||||
if (P.U_SUPPORTED) begin // menvcfg only exists if there is a lower privilege to control
|
if (P.U_SUPPORTED) begin // menvcfg only exists if there is a lower privilege to control
|
||||||
@ -253,10 +236,6 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
MENVCFGH: if (P.U_SUPPORTED & P.XLEN==32) CSRMReadValM = MENVCFGH_REGW;
|
MENVCFGH: if (P.U_SUPPORTED & P.XLEN==32) CSRMReadValM = MENVCFGH_REGW;
|
||||||
else IllegalCSRMAccessM = 1'b1;
|
else IllegalCSRMAccessM = 1'b1;
|
||||||
MCOUNTINHIBIT: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW};
|
MCOUNTINHIBIT: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW};
|
||||||
DCSR: if (P.DEBUG_SUPPORTED) CSRMReadValM = DCSR_REGW;
|
|
||||||
else IllegalCSRMAccessM = 1'b1;
|
|
||||||
DPC: if (P.DEBUG_SUPPORTED) CSRMReadValM = DPC_REGW;
|
|
||||||
else IllegalCSRMAccessM = 1'b1;
|
|
||||||
default: IllegalCSRMAccessM = 1'b1;
|
default: IllegalCSRMAccessM = 1'b1;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
@ -97,6 +97,8 @@ 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
|
||||||
|
// Debuge Mode
|
||||||
|
output logic Step,
|
||||||
// Debug scan chain
|
// Debug scan chain
|
||||||
input logic DebugSel,
|
input logic DebugSel,
|
||||||
input logic [11:0] DebugRegAddr,
|
input logic [11:0] DebugRegAddr,
|
||||||
@ -155,7 +157,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||||||
.SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
.SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
||||||
.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, .Step,
|
||||||
.DebugSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn, .DebugScanIn, .DebugScanOut);
|
.DebugSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn, .DebugScanIn, .DebugScanOut);
|
||||||
|
|
||||||
// pipeline early-arriving trap sources
|
// pipeline early-arriving trap sources
|
||||||
|
@ -45,7 +45,14 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
output logic [3:0] HPROT,
|
output logic [3:0] HPROT,
|
||||||
output logic [1:0] HTRANS,
|
output logic [1:0] HTRANS,
|
||||||
output logic HMASTLOCK,
|
output logic HMASTLOCK,
|
||||||
input logic DebugStall,
|
// Debug Mode Control
|
||||||
|
input logic HaltReq,
|
||||||
|
input logic ResumeReq,
|
||||||
|
input logic HaltOnReset,
|
||||||
|
input logic AckHaveReset,
|
||||||
|
output logic ResumeAck,
|
||||||
|
output logic HaveReset,
|
||||||
|
output logic DebugMode,
|
||||||
// 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
|
||||||
@ -65,6 +72,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
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 DebugStall, Step;
|
||||||
|
|
||||||
// signals that must connect through DP
|
// signals that must connect through DP
|
||||||
logic IntDivE, W64E;
|
logic IntDivE, W64E;
|
||||||
@ -184,7 +192,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic wfiM, IntPendingM;
|
logic wfiM, IntPendingM;
|
||||||
|
|
||||||
// Debug register scan chain interconnects
|
// Debug register scan chain interconnects
|
||||||
logic [2:0] ScanReg;
|
logic [2:0] DebugScanReg;
|
||||||
|
|
||||||
// instruction fetch unit: PC, branch prediction, instruction cache
|
// instruction fetch unit: PC, branch prediction, instruction cache
|
||||||
ifu #(P) ifu(.clk, .reset,
|
ifu #(P) ifu(.clk, .reset,
|
||||||
@ -208,7 +216,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,
|
||||||
.DebugScanEn(DebugScanEn & MiscSel), .DebugScanIn(ScanReg[0]), .DebugScanOut(ScanReg[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
|
||||||
ieu #(P) ieu(.clk, .reset,
|
ieu #(P) ieu(.clk, .reset,
|
||||||
@ -234,7 +242,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
.StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
|
.StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
|
||||||
.StructuralStallD, .LoadStallD, .StoreStallD, .PCSrcE,
|
.StructuralStallD, .LoadStallD, .StoreStallD, .PCSrcE,
|
||||||
.CSRReadM, .CSRWriteM, .PrivilegedM, .CSRWriteFenceM, .InvalidateICacheM,
|
.CSRReadM, .CSRWriteM, .PrivilegedM, .CSRWriteFenceM, .InvalidateICacheM,
|
||||||
.DebugScanEn, .DebugScanIn(ScanReg[1]), .GPRScanIn(DebugScanIn), .DebugScanOut(ScanReg[2]), .GPRScanOut,
|
.DebugScanEn, .DebugScanIn(DebugScanReg[1]), .GPRScanIn(DebugScanIn), .DebugScanOut(DebugScanReg[2]), .GPRScanOut,
|
||||||
.MiscSel, .GPRSel, .DebugCapture, .DebugRegUpdate, .DebugRegAddr(DebugRegAddr[4:0]));
|
.MiscSel, .GPRSel, .DebugCapture, .DebugRegUpdate, .DebugRegAddr(DebugRegAddr[4:0]));
|
||||||
|
|
||||||
lsu #(P) lsu(
|
lsu #(P) lsu(
|
||||||
@ -271,7 +279,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
.StoreAmoAccessFaultM, // connects to privilege
|
.StoreAmoAccessFaultM, // connects to privilege
|
||||||
.InstrUpdateDAF,
|
.InstrUpdateDAF,
|
||||||
.PCSpillF, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, .SelHPTW,
|
.PCSpillF, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, .SelHPTW,
|
||||||
.LSUStallM, .DebugCapture, .DebugScanEn(DebugScanEn & MiscSel), .DebugScanIn(ScanReg[2]), .DebugScanOut);
|
.LSUStallM, .DebugCapture, .DebugScanEn(DebugScanEn & MiscSel), .DebugScanIn(DebugScanReg[2]), .DebugScanOut);
|
||||||
|
|
||||||
if(P.BUS_SUPPORTED) begin : ebu
|
if(P.BUS_SUPPORTED) begin : ebu
|
||||||
ebu #(P) ebu(// IFU connections
|
ebu #(P) ebu(// IFU connections
|
||||||
@ -300,7 +308,17 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
.wfiM, .IntPendingM, .DebugStall,
|
.wfiM, .IntPendingM, .DebugStall,
|
||||||
// Stall & flush outputs
|
// Stall & flush outputs
|
||||||
.StallF, .StallD, .StallE, .StallM, .StallW,
|
.StallF, .StallD, .StallE, .StallM, .StallW,
|
||||||
.FlushD, .FlushE, .FlushM, .FlushW);
|
.FlushD, .FlushE, .FlushM, .FlushW);
|
||||||
|
|
||||||
|
if (P.DEBUG_SUPPORTED) begin
|
||||||
|
dmc debugcontrol(
|
||||||
|
.clk, .reset,
|
||||||
|
.Step, .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset,
|
||||||
|
.ResumeAck, .HaveReset, .DebugMode, .DebugStall
|
||||||
|
);
|
||||||
|
end else begin
|
||||||
|
assign DebugStall = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
// privileged unit
|
// privileged unit
|
||||||
if (P.ZICSR_SUPPORTED) begin:priv
|
if (P.ZICSR_SUPPORTED) begin:priv
|
||||||
@ -324,10 +342,10 @@ 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, .Step,
|
||||||
.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(ScanReg[0]));
|
flopenrs #(1) scantrapm (.clk, .reset, .en(DebugCapture), .d(TrapM), .q(), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanReg[0]));
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
assign {CSRReadValW, PrivilegeModeW,
|
assign {CSRReadValW, PrivilegeModeW,
|
||||||
@ -336,7 +354,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
ENVCFG_CBE, ENVCFG_PBMTE, ENVCFG_ADUE,
|
ENVCFG_CBE, ENVCFG_PBMTE, ENVCFG_ADUE,
|
||||||
EPCM, TrapVectorM, RetM, TrapM,
|
EPCM, TrapVectorM, RetM, TrapM,
|
||||||
sfencevmaM, BigEndianM, wfiM, IntPendingM} = '0;
|
sfencevmaM, BigEndianM, wfiM, IntPendingM} = '0;
|
||||||
assign ScanReg[0] = DebugScanIn;
|
assign DebugScanReg[0] = DebugScanIn;
|
||||||
end
|
end
|
||||||
|
|
||||||
// multiply/divide unit
|
// multiply/divide unit
|
||||||
|
@ -73,9 +73,17 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [63:0] MTIME_CLINT; // from CLINT to CSRs
|
logic [63:0] MTIME_CLINT; // from CLINT to CSRs
|
||||||
logic MExtInt,SExtInt; // from PLIC
|
logic MExtInt,SExtInt; // from PLIC
|
||||||
|
|
||||||
// Debug Module signals
|
// Debug Mode control signals
|
||||||
logic NdmReset;
|
logic NdmReset;
|
||||||
|
logic HaltReq;
|
||||||
|
logic ResumeReq;
|
||||||
|
logic HaltOnReset;
|
||||||
|
logic AckHaveReset;
|
||||||
|
logic ResumeAck;
|
||||||
|
logic HaveReset;
|
||||||
|
logic DebugMode;
|
||||||
logic DebugStall;
|
logic DebugStall;
|
||||||
|
// Debug Module signals
|
||||||
logic DebugScanEn;
|
logic DebugScanEn;
|
||||||
logic DebugScanIn;
|
logic DebugScanIn;
|
||||||
logic GPRScanIn;
|
logic GPRScanIn;
|
||||||
@ -98,7 +106,8 @@ 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,
|
||||||
.DebugStall, .DebugScanEn, .DebugScanOut(DebugScanIn), .GPRScanOut(GPRScanIn), .FPRScanOut(FPRScanIn), .CSRScanOut(CSRScanIn),
|
.HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .ResumeAck, .HaveReset, .DebugMode,
|
||||||
|
.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);
|
||||||
|
|
||||||
// instantiate uncore if a bus interface exists
|
// instantiate uncore if a bus interface exists
|
||||||
@ -115,7 +124,8 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// instantiate debug module
|
// instantiate debug module
|
||||||
if (P.DEBUG_SUPPORTED) begin : dm
|
if (P.DEBUG_SUPPORTED) begin : dm
|
||||||
dm #(P) dm (.clk, .rst(reset), .tck, .tdi, .tms, .tdo, .NdmReset, .DebugStall,
|
dm #(P) dm (.clk, .rst(reset), .tck, .tdi, .tms, .tdo, .NdmReset,
|
||||||
|
.HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .ResumeAck, .HaveReset, .DebugMode,
|
||||||
.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);
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user