-
Notifications
You must be signed in to change notification settings - Fork 52
Mcontrol6 #702
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
Mcontrol6 #702
Changes from 2 commits
17fe54f
b793ab9
bc29151
e2bf78c
4aa496f
3949629
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 |
---|---|---|
|
@@ -257,6 +257,11 @@ module cv32e40x_core import cv32e40x_pkg::*; | |
logic lsu_valid_wb; | ||
logic lsu_ready_1; | ||
|
||
// LSU signals to trigger module | ||
logic [31:0] lsu_addr_ex; | ||
logic lsu_we_ex; | ||
logic [1:0] lsu_size_ex; | ||
|
||
logic data_stall_wb; | ||
|
||
// Stage ready signals | ||
|
@@ -283,8 +288,10 @@ module cv32e40x_core import cv32e40x_pkg::*; | |
// From cs_registers | ||
dcsr_t dcsr; | ||
|
||
// trigger match detected in cs_registers (using ID timing) | ||
// trigger match detected in trigger module (using IF timing) | ||
logic trigger_match_if; | ||
// trigger match detected in trigger module (using EX/LSU timing) | ||
logic trigger_match_ex; | ||
|
||
// Controller <-> decoder | ||
logic alu_jmp_id; | ||
|
@@ -573,6 +580,9 @@ module cv32e40x_core import cv32e40x_pkg::*; | |
.csr_illegal_i ( csr_illegal ), | ||
.csr_mnxti_read_i ( csr_mnxti_read ), | ||
|
||
// trigger input | ||
.trigger_match_i ( trigger_match_ex ), | ||
|
||
// Branch decision | ||
.branch_decision_o ( branch_decision_ex ), | ||
.branch_target_o ( branch_target_ex ), | ||
|
@@ -634,11 +644,19 @@ module cv32e40x_core import cv32e40x_pkg::*; | |
.busy_o ( lsu_busy ), | ||
.interruptible_o ( lsu_interruptible ), | ||
|
||
// Trigger match | ||
.trigger_match_i ( trigger_match_ex ), | ||
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. Stick to naming conventions: .trigger_match_0_i ( trigger_match_ex ), 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. Renamed |
||
|
||
// Stage 0 outputs (EX) | ||
.lsu_split_0_o ( lsu_split_ex ), | ||
.lsu_first_op_0_o ( lsu_first_op_ex ), | ||
.lsu_last_op_0_o ( lsu_last_op_ex ), | ||
|
||
// Outputs to trigger module | ||
.lsu_addr_o ( lsu_addr_ex ), | ||
.lsu_we_o ( lsu_we_ex ), | ||
.lsu_size_o ( lsu_size_ex ), | ||
|
||
// Stage 1 outputs (WB) | ||
.lsu_err_1_o ( lsu_err_wb ), // To controller (has WB timing, but does not pass through WB stage) | ||
.lsu_rdata_1_o ( lsu_rdata_wb ), | ||
|
@@ -792,9 +810,14 @@ module cv32e40x_core import cv32e40x_pkg::*; | |
.csr_wr_in_wb_flush_o ( csr_wr_in_wb_flush ), | ||
|
||
// Debug | ||
.trigger_match_o ( trigger_match_if ), | ||
.trigger_match_if_o ( trigger_match_if ), | ||
.trigger_match_ex_o ( trigger_match_ex ), | ||
.pc_if_i ( pc_if ), | ||
.ptr_in_if_i ( ptr_in_if ) | ||
.ptr_in_if_i ( ptr_in_if ), | ||
.lsu_valid_ex_i ( lsu_valid_ex ), | ||
.lsu_addr_ex_i ( lsu_addr_ex ), | ||
.lsu_we_ex_i ( lsu_we_ex ), | ||
.lsu_size_ex_i ( lsu_size_ex ) | ||
); | ||
|
||
//////////////////////////////////////////////////////////////////// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,12 +58,21 @@ import cv32e40x_pkg::*; | |
// IF stage inputs | ||
input logic [31:0] pc_if_i, | ||
input logic ptr_in_if_i, | ||
input privlvl_t priv_lvl_if_i, | ||
|
||
// EX stage / LSU inputs | ||
input logic lsu_valid_ex_i, | ||
input logic [31:0] lsu_addr_ex_i, | ||
input logic lsu_we_ex_i, | ||
input logic [1:0] lsu_size_ex_i, | ||
input privlvl_t priv_lvl_ex_i, | ||
|
||
// Controller inputs | ||
input ctrl_fsm_t ctrl_fsm_i, | ||
|
||
// Trigger match output | ||
output logic trigger_match_o | ||
// Trigger match outputs | ||
output logic trigger_match_if_o, // Instruction address match | ||
output logic trigger_match_ex_o // Load/Store address match | ||
Silabs-ArjanB marked this conversation as resolved.
Show resolved
Hide resolved
|
||
); | ||
|
||
// CSR write data | ||
|
@@ -88,8 +97,23 @@ import cv32e40x_pkg::*; | |
logic [31:0] tdata2_q[DBG_NUM_TRIGGERS]; | ||
logic [31:0] tselect_q; | ||
|
||
// Fetch stage trigger match | ||
// IF and EX stages trigger match | ||
logic [DBG_NUM_TRIGGERS-1 : 0] trigger_match_if; | ||
logic [DBG_NUM_TRIGGERS-1 : 0] trigger_match_ex; | ||
Silabs-ArjanB marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Instruction address match | ||
logic [DBG_NUM_TRIGGERS-1 : 0] if_addr_match; | ||
|
||
// LSU address match signals | ||
logic [DBG_NUM_TRIGGERS-1 : 0] lsu_addr_match_en; | ||
logic [DBG_NUM_TRIGGERS-1 : 0] lsu_addr_match; | ||
|
||
// Enable matching based on privilege level per trigger | ||
logic [DBG_NUM_TRIGGERS-1 : 0] priv_lvl_match_en_if; | ||
logic [DBG_NUM_TRIGGERS-1 : 0] priv_lvl_match_en_ex; | ||
|
||
// Lower boundary of LSU address match checks, calculated for each trigger | ||
logic [31:0] tdata2_q_low[DBG_NUM_TRIGGERS]; | ||
|
||
|
||
// Write data | ||
|
@@ -108,7 +132,7 @@ import cv32e40x_pkg::*; | |
4'b0000, // zero, size (match any size) 19:16 | ||
4'b0001, // action, WARL(1), enter debug 15:12 | ||
1'b0, // zero, chain 11 | ||
4'b0000, // match, WARL(0,2,3) 10:7 todo: resolve WARL | ||
mcontrol6_match_resolve(tdata1_rdata_o[MCONTROL6_MATCH_H:MCONTROL6_MATCH_L], csr_wdata_i[MCONTROL6_MATCH_H:7]), // match, WARL(0,2,3) 10:7 | ||
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. Stick to _HIGH, _LOW naming convention as used for other bitfields 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. Replace '7' 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. Done |
||
csr_wdata_i[6], // M 6 | ||
1'b0, // zero 5 | ||
1'b0, // zero, S 4 | ||
|
@@ -125,18 +149,65 @@ import cv32e40x_pkg::*; | |
|
||
// Generate DBG_NUM_TRIGGERS instances of tdata1, tdata2 and match checks | ||
for (genvar idx=0; idx<DBG_NUM_TRIGGERS; idx++) begin : tmatch_csr | ||
// Breakpoint matching | ||
// We match against the next address, as the breakpoint must be taken before execution | ||
// Matching is disabled when ctrl_fsm_i.debug_mode == 1'b1 | ||
|
||
//////////////////////////////////// | ||
// Instruction address match (IF) | ||
//////////////////////////////////// | ||
|
||
// With timing=0 we enter debug before executing the instruction at the match address. We use the IF stage PC | ||
// for comparison, and any trigger match will cause the instruction to act as a NOP with no side effects until it | ||
// reaches WB where debug mode is entered. | ||
// | ||
// Trigger match is disabled while in debug mode. | ||
// | ||
// Trigger CSRs can only be written from debug mode, writes from any other privilege level are ignored. | ||
// Thus we do not have an issue where a write to the tdata2 CSR immediately before the matched instruction | ||
// could be missed since we must write in debug mode, then dret to machine mode (kills pipeline) before | ||
// returning to dpc. | ||
// Todo: There is no CLIC spec for trigger matches for pointers. | ||
// todo: use struct or parameters for indexing to make code more readable. | ||
// todo: Check tdata1[6] vs actual priv_lvl and add check for tdata1[3] (PRIV_LVL_U) | ||
assign trigger_match_if[idx] = tdata1_q[idx][2] && tdata1_q[idx][6] && !ctrl_fsm_i.debug_mode && !ptr_in_if_i && | ||
(pc_if_i[31:0] == tdata2_q[idx][31:0]); | ||
// No instruction address match on any pointer type (CLIC and Zc tablejumps). | ||
Silabs-ArjanB marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Check for address match using tdata2.match for checking rule | ||
assign if_addr_match[idx] = (tdata1_q[idx][MCONTROL6_MATCH_H:MCONTROL6_MATCH_L] == 4'h0) ? (pc_if_i == tdata2_q[idx]) : | ||
(tdata1_q[idx][MCONTROL6_MATCH_H:MCONTROL6_MATCH_L] == 4'h2) ? (pc_if_i >= tdata2_q[idx]) : (pc_if_i < tdata2_q[idx]); | ||
|
||
// Check if matching is enabled for the current privilege level from IF | ||
assign priv_lvl_match_en_if[idx] = (tdata1_q[idx][MCONTROL6_M] && (priv_lvl_if_i == PRIV_LVL_M)) || | ||
(tdata1_q[idx][MCONTROL6_U] && (priv_lvl_if_i == PRIV_LVL_U)); | ||
|
||
// Check for trigger match from IF | ||
assign trigger_match_if[idx] = tdata1_q[idx][MCONTROL6_EXECUTE] && priv_lvl_match_en_if[idx] && !ctrl_fsm_i.debug_mode && !ptr_in_if_i && | ||
if_addr_match[idx]; | ||
|
||
/////////////////////////////////////// | ||
// Load/Store address match (EX) | ||
/////////////////////////////////////// | ||
|
||
// As for instruction address match, the load/store address match happens before the instruction is executed. | ||
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. Is this complexity caused by how misaligned loads/stores are handled? Do you generate all compare values for a misaligned load/store during its first operation? If so, why, and would it help to treat each opeartion separately? 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. The adder to calculate boundaries came (partly) from checking all values, even for misaligned load/stores. I rewrote the code to check per-transaction, so two checks will be performed for misaligned. I also replaced the adder by logic to generate boundaries base on the byte enables instead. |
||
// Matching is detected from the EX stage, and upon a trigger match the corresponding bus request and | ||
// register file write (for loads) are suppressed. | ||
|
||
// Calculate lower boundary of address checks from tdata2 | ||
// Needed for LSU address matching, where halfwords check {A, A+1} | ||
// and words check {A, A+1, A+2, A+3}. | ||
// For timing reasons we check A vs (tdata_q - N) instead of (A+N) vs tdata_q. This avoids two adders (one in the LSU and one here) in the critical path. | ||
// - This comes at the cost of DBG_NUM_TRIGGERS adders instead of one common for all triggers. | ||
assign tdata2_q_low[idx] = (lsu_size_ex_i == 2'b10) ? tdata2_q[idx] - 32'h3 : | ||
(lsu_size_ex_i == 2'b01) ? tdata2_q[idx] - 32'h1 : tdata2_q[idx]; | ||
|
||
|
||
// Check if matching is enabled for the current privilege level from EX | ||
assign priv_lvl_match_en_ex[idx] = (tdata1_q[idx][MCONTROL6_M] && (priv_lvl_ex_i == PRIV_LVL_M)) || | ||
(tdata1_q[idx][MCONTROL6_U] && (priv_lvl_ex_i == PRIV_LVL_U)); | ||
|
||
// Enable LSU address matching | ||
assign lsu_addr_match_en[idx] = lsu_valid_ex_i && ((tdata1_q[idx][MCONTROL6_LOAD] && !lsu_we_ex_i) || (tdata1_q[idx][MCONTROL6_STORE] && lsu_we_ex_i)); | ||
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. Add todo to revisit this code when supporting Atomics 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. Done
Silabs-ArjanB marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// LSU address matching | ||
assign lsu_addr_match[idx] = (tdata1_q[idx][MCONTROL6_MATCH_H:MCONTROL6_MATCH_L] == 4'h2) ? (lsu_addr_ex_i >= tdata2_q[idx]) : | ||
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. I think that the _llow value should be used for match == 2 instead. Also, order match values 0, 2, 3 just like for the I-side comparisons 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. Done |
||
(tdata1_q[idx][MCONTROL6_MATCH_H:MCONTROL6_MATCH_L] == 4'h3) ? (lsu_addr_ex_i < tdata2_q_low[idx]) : | ||
(lsu_addr_ex_i >= tdata2_q_low[idx]) && (lsu_addr_ex_i <= tdata2_q[idx]); | ||
|
||
assign trigger_match_ex[idx] = priv_lvl_match_en_ex[idx] && lsu_addr_match_en[idx] && lsu_addr_match[idx] && !ctrl_fsm_i.debug_mode; | ||
|
||
|
||
cv32e40x_csr | ||
|
@@ -207,7 +278,10 @@ import cv32e40x_pkg::*; | |
assign tcontrol_rdata_o = 32'h00000000; | ||
|
||
// Set trigger match for IF | ||
assign trigger_match_o = |trigger_match_if; | ||
assign trigger_match_if_o = |trigger_match_if; | ||
|
||
// Set trigger match for EX | ||
assign trigger_match_ex_o = |trigger_match_ex; | ||
|
||
assign unused_signals = tinfo_we_i | tcontrol_we_i | tdata3_we_i | (|tinfo_n) | (|tdata3_n) | (|tcontrol_n); | ||
|
||
|
@@ -219,7 +293,8 @@ import cv32e40x_pkg::*; | |
assign tselect_rdata_o = '0; | ||
assign tinfo_rdata_o = '0; | ||
assign tcontrol_rdata_o = '0; | ||
assign trigger_match_o = '0; | ||
assign trigger_match_if_o = '0; | ||
assign trigger_match_ex_o = '0; | ||
assign tdata1_n = '0; | ||
assign tdata2_n = '0; | ||
assign tdata3_n = '0; | ||
|
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.
Is this change in itself SEC clean when ZC_EXT = 0?
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.
SEC is still running after four days