-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CLIC: Spec chapter 5.1 #485
Changes from 3 commits
f491057
2547fd2
38b6ce9
2e66627
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,15 +53,15 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
// MTVEC | ||
output logic [24:0] mtvec_addr_o, | ||
output logic [1:0] mtvec_mode_o, | ||
|
||
// Cycle Count | ||
output logic [MHPMCOUNTER_WIDTH-1:0] mcycle_o, | ||
|
||
// Used for mtvec address | ||
input logic [31:0] mtvec_addr_i, | ||
input logic csr_mtvec_init_i, | ||
|
||
// ID/EX pipeline | ||
// ID/EX pipeline | ||
input id_ex_pipe_t id_ex_pipe_i, | ||
|
||
// EX/WB pipeline | ||
|
@@ -72,7 +72,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
|
||
// To controller bypass logic | ||
output logic csr_counter_read_o, | ||
|
||
// Interface to registers (SRAM like) | ||
output logic [31:0] csr_rdata_o, | ||
|
||
|
@@ -83,7 +83,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
output logic [31:0] mie_o, | ||
input logic [31:0] mip_i, | ||
output logic m_irq_enable_o, | ||
|
||
output logic [31:0] mepc_o, | ||
|
||
// debug | ||
|
@@ -93,7 +93,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
|
||
input logic [31:0] pc_if_i | ||
); | ||
|
||
localparam logic [31:0] CORE_MISA = | ||
(32'(A_EXT) << 0) // A - Atomic Instructions extension | ||
| (32'(1) << 2) // C - Compressed extension | ||
|
@@ -224,7 +224,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
|
||
// CSR write operations in WB, actual csr_we_int may still become 1'b0 in case of CSR_OP_READ | ||
assign csr_en_gated = ex_wb_pipe_i.csr_en && instr_valid; | ||
|
||
// mip CSR | ||
assign mip = mip_i; | ||
|
||
|
@@ -306,7 +306,20 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
CSR_MEPC: csr_rdata_int = mepc_q; | ||
|
||
// mcause: exception cause | ||
CSR_MCAUSE: csr_rdata_int = mcause_q; | ||
CSR_MCAUSE: begin | ||
if (SMCLIC) begin | ||
// For CLIC, the mpp and mpie bits from mstatus | ||
// are readable via mcause | ||
csr_rdata_int = { | ||
mcause_q[31:30], | ||
mstatus_q.mpp, // 29:28 | ||
mstatus_q.mpie, // 27 | ||
mcause_q[26:0] | ||
}; | ||
end else begin | ||
csr_rdata_int = mcause_q; | ||
end | ||
end | ||
|
||
// mip: interrupt pending | ||
CSR_MIP: csr_rdata_int = mip; | ||
|
@@ -503,7 +516,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
mepc_n = csr_wdata_int & ~32'b1; | ||
mepc_we = 1'b0; | ||
dpc_n = csr_wdata_int & ~32'b1; | ||
dpc_we = 1'b0; | ||
dpc_we = 1'b0; | ||
|
||
dcsr_n = '{ | ||
xdebugver : dcsr_q.xdebugver, | ||
|
@@ -521,16 +534,36 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
dscratch1_n = csr_wdata_int; | ||
dscratch1_we = 1'b0; | ||
|
||
mstatus_n = '{ | ||
tw: 1'b0, | ||
mprv: 1'b0, | ||
mpp: PRIV_LVL_M, | ||
mpie: csr_wdata_int[MSTATUS_MPIE_BIT], | ||
mie: csr_wdata_int[MSTATUS_MIE_BIT], | ||
default: 'b0 | ||
}; | ||
if (SMCLIC) begin | ||
// SMCLIC: A write to mcause.mpp or mcause.mpie is stored in mstatus | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same remark as above: 'CLIC mode is assumed when SMCLIC = 1'. |
||
if(mcause_we) begin | ||
mstatus_n = mstatus_q; | ||
mstatus_n.mpp = PRIV_LVL_M; | ||
mstatus_n.mpie = csr_wdata_int[MCAUSE_MPIE_BIT]; | ||
end else begin | ||
// TODO: add support for SD/XS/FS/VS | ||
mstatus_n = '{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reorganize code to avoid this code duplication. Simply first do the original mstatus_n assignment and then a if (SMCLIC) if (mcause_we) |
||
tw: 1'b0, | ||
mprv: 1'b0, | ||
mpp: PRIV_LVL_M, | ||
mpie: csr_wdata_int[MSTATUS_MPIE_BIT], | ||
mie: csr_wdata_int[MSTATUS_MIE_BIT], | ||
default: 'b0 | ||
}; | ||
end | ||
end else begin | ||
mstatus_n = '{ | ||
tw: 1'b0, | ||
mprv: 1'b0, | ||
mpp: PRIV_LVL_M, | ||
mpie: csr_wdata_int[MSTATUS_MPIE_BIT], | ||
mie: csr_wdata_int[MSTATUS_MIE_BIT], | ||
default: 'b0 | ||
}; | ||
end // SMCLIC | ||
mstatus_we = 1'b0; | ||
|
||
// SMCLIC: Not setting mpp or mpie, as these are stored in mstatus | ||
mcause_n = '{ | ||
irq: csr_wdata_int[31], | ||
exception_code: csr_wdata_int[10:0], | ||
|
@@ -559,7 +592,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
mscratchcswl_we = 1'b0; | ||
mie_n = csr_wdata_int & IRQ_MASK; | ||
mie_we = 1'b0; | ||
|
||
if (csr_we_int) begin | ||
case (csr_waddr) | ||
// jvt: Jump vector table | ||
|
@@ -598,8 +631,13 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
mepc_we = 1'b1; | ||
end | ||
// mcause | ||
CSR_MCAUSE: begin | ||
mcause_we = 1'b1; | ||
CSR_MCAUSE: begin | ||
mcause_we = 1'b1; | ||
// For CLIC, a write to mcause.mpp or mcause.mpie will write to the | ||
// corresponding bits in mstatus as well. | ||
if (SMCLIC) begin | ||
mstatus_we = 1'b1; | ||
end | ||
end | ||
CSR_MNXTI: begin | ||
if (SMCLIC) begin | ||
|
@@ -638,7 +676,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
CSR_DSCRATCH1: begin | ||
dscratch1_we = 1'b1; | ||
end | ||
|
||
endcase | ||
end | ||
|
||
|
@@ -842,7 +880,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
.rd_error_o (mcause_rd_error) | ||
); | ||
|
||
|
||
|
||
cv32e40x_csr #( | ||
.WIDTH (32), | ||
|
@@ -953,16 +991,16 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
|
||
// IRQ enable | ||
assign m_irq_enable_o = mstatus_q.mie; | ||
|
||
assign mtvec_addr_o = mtvec_q.addr; | ||
assign mtvec_mode_o = mtvec_q.mode; | ||
|
||
assign mepc_o = mepc_q; | ||
assign dpc_o = dpc_q; | ||
assign dcsr_o = dcsr_q; | ||
|
||
assign mie_o = mie_q; | ||
|
||
// dcsr_rdata factors in the flop outputs and the nmip bit from the controller | ||
assign dcsr_rdata = {dcsr_q[31:4], ctrl_fsm_i.pending_nmi, dcsr_q[2:0]}; | ||
|
||
|
@@ -975,7 +1013,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
// |___/ |___/ |___/ // | ||
//////////////////////////////////////////////////////////////////////// | ||
|
||
|
||
// Write select | ||
assign tmatch_control_we = csr_we_int && ctrl_fsm_i.debug_mode && (csr_waddr == CSR_TDATA1); | ||
assign tmatch_value_we = csr_we_int && ctrl_fsm_i.debug_mode && (csr_waddr == CSR_TDATA2); | ||
|
@@ -1005,7 +1043,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
1'b0, // store : not supported | ||
1'b0}; // load : not supported | ||
|
||
assign tmatch_value_n = csr_wdata_int; | ||
assign tmatch_value_n = csr_wdata_int; | ||
|
||
cv32e40x_csr #( | ||
.WIDTH (32), | ||
|
@@ -1018,8 +1056,8 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
.wr_en_i (tmatch_control_we), | ||
.rd_data_o (tmatch_control_q), | ||
.rd_error_o (tmatch_control_rd_error) | ||
); | ||
); | ||
|
||
cv32e40x_csr #( | ||
.WIDTH (32), | ||
.SHADOWCOPY (1'b0), | ||
|
@@ -1031,7 +1069,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
.wr_en_i (tmatch_value_we), | ||
.rd_data_o (tmatch_value_q), | ||
.rd_error_o (tmatch_value_rd_error) | ||
); | ||
); | ||
|
||
|
||
// Breakpoint matching | ||
|
@@ -1060,10 +1098,10 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
// Flop certain events to ease timing | ||
localparam bit [15:0] HPM_EVENT_FLOP = 16'b1111_1111_1100_0000; | ||
localparam bit [31:0] MCOUNTINHIBIT_MASK = {{(29-NUM_MHPMCOUNTERS){1'b0}},{(NUM_MHPMCOUNTERS){1'b1}},3'b101}; | ||
|
||
logic [15:0] hpm_events_raw; | ||
logic all_counters_disabled; | ||
|
||
assign all_counters_disabled = &(mcountinhibit_n | ~MCOUNTINHIBIT_MASK); | ||
|
||
genvar hpm_idx; | ||
|
@@ -1159,7 +1197,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
mcountinhibit_n = mcountinhibit_q; | ||
mhpmevent_n = mhpmevent_q; | ||
|
||
|
||
// Inhibit Control | ||
if(mcountinhibit_we) | ||
mcountinhibit_n = csr_wdata_int & MCOUNTINHIBIT_MASK; | ||
|
@@ -1181,7 +1219,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
csr_we_int && (csr_waddr == (CSR_MCYCLEH + wcnt_gidx)) && (MHPMCOUNTER_WIDTH == 64); | ||
|
||
// Increment counter | ||
|
||
if (wcnt_gidx == 0) begin : gen_mhpmcounter_mcycle | ||
// mcycle = mhpmcounter[0] : count every cycle (if not inhibited) | ||
assign mhpmcounter_write_increment[wcnt_gidx] = !mhpmcounter_write_lower[wcnt_gidx] && | ||
|
@@ -1202,7 +1240,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*; | |
end else begin : gen_mhpmcounter_not_implemented | ||
assign mhpmcounter_write_increment[wcnt_gidx] = 1'b0; | ||
end | ||
|
||
end | ||
endgenerate | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add note that 'CLIC mode is assumed when SMCLIC = 1'. RTL should actually have checked on 'clic mode' instead of SMCLIC, but let's keep it like this as these two things are the same for our subset of the Smclic implementation (and your implementation is better for coverage reasons)