mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-24 05:57:28 -04:00
Started work on MMIO debug
This commit is contained in:
parent
74fed0d5ea
commit
5e30493243
8 changed files with 569 additions and 302 deletions
|
@ -72,15 +72,15 @@ module riscv_controller
|
|||
input logic exc_req_i,
|
||||
output logic exc_ack_o,
|
||||
|
||||
input logic trap_hit_i, // a trap was hit, so we have to flush EX and WB
|
||||
|
||||
output logic exc_save_id_o,
|
||||
output logic exc_restore_id_o,
|
||||
|
||||
// Debug Unit Signals
|
||||
// Debug Signals
|
||||
input logic dbg_req_i, // a trap was hit, so we have to flush EX and WB
|
||||
output logic dbg_ack_o, // we stopped and give control to debug now
|
||||
|
||||
input logic dbg_stall_i, // Pipeline stall is requested
|
||||
input logic dbg_set_npc_i, // Change PC to value from debug unit
|
||||
output logic dbg_trap_o, // trap hit, inform debug unit
|
||||
input logic dbg_jump_req_i, // Change PC to value from debug unit
|
||||
|
||||
// Forwarding signals from regfile
|
||||
input logic [4:0] regfile_waddr_ex_i, // FW: write address from EX stage
|
||||
|
@ -179,7 +179,7 @@ module riscv_controller
|
|||
|
||||
halt_if_o = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
dbg_trap_o = 1'b0;
|
||||
dbg_ack_o = 1'b0;
|
||||
|
||||
unique case (ctrl_fsm_cs)
|
||||
// We were just reset, wait for fetch_enable
|
||||
|
@ -303,7 +303,7 @@ module riscv_controller
|
|||
|
||||
// take care of debug
|
||||
// branch conditional will be handled in next state
|
||||
if (trap_hit_i)
|
||||
if (dbg_req_i)
|
||||
begin
|
||||
// halt pipeline immediately
|
||||
halt_if_o = 1'b1;
|
||||
|
@ -332,7 +332,7 @@ module riscv_controller
|
|||
// if we want to debug, flush the pipeline
|
||||
// the current_pc_if will take the value of the next instruction to
|
||||
// be executed (NPC)
|
||||
if (trap_hit_i)
|
||||
if (dbg_req_i)
|
||||
begin
|
||||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
end
|
||||
|
@ -357,7 +357,7 @@ module riscv_controller
|
|||
// can examine our current state
|
||||
DBG_SIGNAL:
|
||||
begin
|
||||
dbg_trap_o = 1'b1;
|
||||
dbg_ack_o = 1'b1;
|
||||
halt_if_o = 1'b1;
|
||||
|
||||
ctrl_fsm_ns = DBG_WAIT;
|
||||
|
@ -369,13 +369,13 @@ module riscv_controller
|
|||
begin
|
||||
halt_if_o = 1'b1;
|
||||
|
||||
if(dbg_set_npc_i == 1'b1) begin
|
||||
if (dbg_jump_req_i) begin
|
||||
pc_mux_o = `PC_DBG_NPC;
|
||||
pc_set_o = 1'b1;
|
||||
ctrl_fsm_ns = DBG_WAIT;
|
||||
end
|
||||
|
||||
if(dbg_stall_i == 1'b0) begin
|
||||
if (dbg_stall_i == 1'b0) begin
|
||||
ctrl_fsm_ns = DECODE;
|
||||
end
|
||||
end
|
||||
|
@ -385,7 +385,7 @@ module riscv_controller
|
|||
begin
|
||||
halt_if_o = 1'b1;
|
||||
|
||||
if(ex_valid_i)
|
||||
if (ex_valid_i)
|
||||
ctrl_fsm_ns = FLUSH_WB;
|
||||
end
|
||||
|
||||
|
|
553
debug_unit.sv
553
debug_unit.sv
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2015 ETH Zurich and University of Bologna.
|
||||
// Copyright 2016 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the “License”); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
|
||||
|
@ -9,11 +9,7 @@
|
|||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Engineer: Florian Glaser - glaserf@ethz.ch //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// Andreas Traber - atraber@student.ethz.ch //
|
||||
// Sven Stucki - svstucki@student.ethz.ch //
|
||||
// Engineer: Andreas Traber - atraber@iis.ee.ethz.ch //
|
||||
// //
|
||||
// Design Name: Debug Unit //
|
||||
// Project Name: RI5CY //
|
||||
|
@ -31,31 +27,42 @@ module riscv_debug_unit
|
|||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
// signals to Debug Interface
|
||||
input logic dbginf_stall_i,
|
||||
output logic dbginf_bp_o,
|
||||
input logic dbginf_strobe_i,
|
||||
output logic dbginf_ack_o,
|
||||
input logic dbginf_we_i,
|
||||
input logic [15:0] dbginf_addr_i,
|
||||
input logic [31:0] dbginf_data_i,
|
||||
output logic [31:0] dbginf_data_o,
|
||||
// Debug Interface
|
||||
input logic debug_req_i,
|
||||
output logic debug_gnt_o,
|
||||
output logic debug_rvalid_o,
|
||||
input logic [14:0] debug_addr_i,
|
||||
input logic debug_we_i,
|
||||
input logic [31:0] debug_wdata_i,
|
||||
output logic [31:0] debug_rdata_o,
|
||||
output logic debug_halted_o,
|
||||
input logic debug_halt_i,
|
||||
|
||||
// signals to core
|
||||
output logic dbg_step_en_o, // Single-step trace mode enabled
|
||||
output logic [1:0] dbg_dsr_o, // debug stop register
|
||||
output logic [`DBG_SETS_W-1:0] settings_o,
|
||||
|
||||
output logic stall_core_o,
|
||||
output logic stop_req_o,
|
||||
input logic trap_i,
|
||||
input logic trap_i, // trap found, need to stop the core now
|
||||
output logic stall_o, // after we got control, we control the stall signal
|
||||
output logic dbg_req_o,
|
||||
input logic dbg_ack_i,
|
||||
|
||||
output logic sp_mux_o,
|
||||
output logic regfile_mux_o,
|
||||
output logic regfile_we_o,
|
||||
output logic [11:0] regfile_addr_o,
|
||||
output logic [31:0] regfile_wdata_o,
|
||||
// register file read port
|
||||
output logic regfile_rreq_o,
|
||||
output logic [ 4:0] regfile_raddr_o,
|
||||
input logic [31:0] regfile_rdata_i,
|
||||
|
||||
// register file write port
|
||||
output logic regfile_wreq_o,
|
||||
output logic [ 4:0] regfile_waddr_o,
|
||||
output logic [31:0] regfile_wdata_o,
|
||||
|
||||
// CSR read/write port
|
||||
output logic csr_req_o,
|
||||
output logic [11:0] csr_addr_o,
|
||||
output logic csr_we_o,
|
||||
output logic [31:0] csr_wdata_o,
|
||||
input logic [31:0] csr_rdata_i,
|
||||
|
||||
// Signals for PPC & NPC register
|
||||
input logic [31:0] curr_pc_if_i,
|
||||
input logic [31:0] curr_pc_id_i,
|
||||
|
@ -64,158 +71,328 @@ module riscv_debug_unit
|
|||
input logic branch_in_ex_i,
|
||||
input logic branch_taken_i,
|
||||
|
||||
output logic [31:0] npc_o,
|
||||
output logic set_npc_o
|
||||
output logic jump_req_o,
|
||||
output logic [31:0] jump_addr_o
|
||||
);
|
||||
|
||||
enum logic [2:0] {RD_NONE, RD_CSR, RD_GPR, RD_DBGA, RD_DBGS} rdata_sel_q, rdata_sel_n;
|
||||
|
||||
// registers for debug control
|
||||
logic [1:0] dsr_q, dsr_n; // Debug Stop Register: IIE, INTE
|
||||
logic [1:0] dmr1_q, dmr1_n; // only single step trace and branch trace bits
|
||||
enum logic [0:0] {FIRST, SECOND} state_q, state_n;
|
||||
|
||||
logic [`DBG_SETS_W-1:0] settings_q, settings_n;
|
||||
|
||||
// for timing critical register file access we need to keep those in FFs
|
||||
logic [14:0] addr_q;
|
||||
logic [31:0] wdata_q; // mainly for jumps
|
||||
logic regfile_rreq_q, regfile_rreq_n;
|
||||
logic jump_req_q, jump_req_n;
|
||||
|
||||
// not timing critical
|
||||
logic csr_req_q, csr_req_n;
|
||||
logic regfile_wreq;
|
||||
|
||||
|
||||
enum logic [1:0] {RUNNING, HALT_REQ, HALT} stall_cs, stall_ns;
|
||||
logic [31:0] dbg_rdata;
|
||||
logic dbg_resume;
|
||||
logic dbg_halt;
|
||||
|
||||
// BP control FSM
|
||||
enum logic [1:0] {Idle, Trap, DebugStall, StallCore} bp_fsm_cs, bp_fsm_ns;
|
||||
|
||||
// ppc/npc tracking
|
||||
enum logic [1:0] {IFID, IFEX, IDEX} pc_tracking_fsm_cs, pc_tracking_fsm_ns;
|
||||
logic [31:0] ppc_int, npc_int;
|
||||
|
||||
// ack to debug interface
|
||||
assign dbginf_ack_o = dbginf_strobe_i && ((bp_fsm_cs == StallCore) || (dbginf_addr_i[15:11] == 5'b00110));
|
||||
|
||||
|
||||
always_comb
|
||||
begin
|
||||
bp_fsm_ns = bp_fsm_cs;
|
||||
stall_core_o = 1'b0;
|
||||
dbginf_bp_o = 1'b0;
|
||||
stop_req_o = 1'b0;
|
||||
|
||||
case (bp_fsm_cs)
|
||||
Idle:
|
||||
begin
|
||||
if(trap_i == 1'b1)
|
||||
begin
|
||||
dbginf_bp_o = 1'b1;
|
||||
stall_core_o = 1'b1;
|
||||
bp_fsm_ns = StallCore;
|
||||
end
|
||||
else if(dbginf_stall_i)
|
||||
begin
|
||||
stop_req_o = 1'b1;
|
||||
bp_fsm_ns = DebugStall;
|
||||
end
|
||||
end
|
||||
|
||||
// A stall from adv dbg unit was seen, flush the pipeline and wait for unstalling
|
||||
DebugStall:
|
||||
begin
|
||||
stop_req_o = 1'b1;
|
||||
|
||||
if(trap_i == 1'b1)
|
||||
begin
|
||||
stall_core_o = 1'b1;
|
||||
bp_fsm_ns = StallCore;
|
||||
end
|
||||
end
|
||||
|
||||
StallCore:
|
||||
begin
|
||||
stall_core_o = 1'b1;
|
||||
|
||||
if(~dbginf_stall_i)
|
||||
bp_fsm_ns = Idle;
|
||||
end
|
||||
|
||||
default: bp_fsm_ns = Idle;
|
||||
endcase // case (bp_fsm_cs)
|
||||
end
|
||||
|
||||
|
||||
// data to GPRs and SPRs
|
||||
assign regfile_wdata_o = dbginf_data_i;
|
||||
|
||||
assign dbg_step_en_o = dmr1_q[0];
|
||||
assign dbg_dsr_o = dsr_q;
|
||||
|
||||
assign npc_o = dbginf_data_i;
|
||||
|
||||
|
||||
// address decoding, write and read controller
|
||||
always_comb
|
||||
begin
|
||||
dmr1_n = dmr1_q;
|
||||
dsr_n = dsr_q;
|
||||
dbginf_data_o = 32'b0;
|
||||
regfile_we_o = 1'b0;
|
||||
regfile_addr_o = '0;
|
||||
regfile_mux_o = 1'b0;
|
||||
sp_mux_o = 1'b0;
|
||||
set_npc_o = 1'b0;
|
||||
rdata_sel_n = RD_NONE;
|
||||
state_n = FIRST;
|
||||
|
||||
if(dbginf_strobe_i == 1'b1) begin
|
||||
// address decoding, first stage: evaluate higher 5 Bits to detect if debug regs are accessed
|
||||
if(dbginf_addr_i[15:11] == 5'b00110) begin
|
||||
// second stage: evaluate Bits 10:0 to detect which part of debug registers is accessed
|
||||
case (dbginf_addr_i[10:0])
|
||||
11'd0: begin // NPC
|
||||
set_npc_o = dbginf_we_i;
|
||||
debug_gnt_o = 1'b0;
|
||||
|
||||
dbginf_data_o = npc_int;
|
||||
regfile_rreq_n = 1'b0;
|
||||
regfile_wreq = 1'b0;
|
||||
csr_req_n = 1'b0;
|
||||
csr_we_o = 1'b0;
|
||||
jump_req_n = 1'b0;
|
||||
|
||||
dbg_resume = 1'b0;
|
||||
dbg_halt = 1'b0;
|
||||
settings_n = settings_q;
|
||||
|
||||
if (debug_req_i) begin
|
||||
if (debug_we_i) begin
|
||||
//----------------------------------------------------------------------------
|
||||
// write access
|
||||
//----------------------------------------------------------------------------
|
||||
if (debug_addr_i[14]) begin
|
||||
// CSR access
|
||||
if (state_q == FIRST) begin
|
||||
// only grant in second cycle, address and data have been latched by then
|
||||
debug_gnt_o = 1'b1; // grant it even when invalid access to not block
|
||||
state_n = SECOND;
|
||||
|
||||
if (debug_halted_o) begin
|
||||
// access to internal registers are only allowed when the core is halted
|
||||
csr_req_n = 1'b1;
|
||||
end
|
||||
end else begin
|
||||
state_n = FIRST;
|
||||
csr_we_o = 1'b1;
|
||||
end
|
||||
end else begin
|
||||
// non-CSR access
|
||||
unique case (debug_addr_i[13:8])
|
||||
6'b00_0000: begin // Debug Registers, always accessible
|
||||
debug_gnt_o = 1'b1;
|
||||
|
||||
11'd1: begin // PPC
|
||||
dbginf_data_o = ppc_int;
|
||||
end
|
||||
unique case (debug_addr_i[6:2])
|
||||
5'b0_0000: begin // DBG_CTRL
|
||||
// RESUME takes precedence over HALT
|
||||
if (debug_wdata_i[31]) begin
|
||||
// RESUME set
|
||||
if (debug_halted_o) begin
|
||||
dbg_resume = 1'b1;
|
||||
end
|
||||
end else if (debug_wdata_i[16]) begin
|
||||
// HALT set
|
||||
if (~debug_halted_o) begin
|
||||
// not halt, so STOP
|
||||
dbg_halt = 1'b1;
|
||||
end
|
||||
end
|
||||
settings_n[`DBG_SETS_SSTE] = debug_wdata_i[0];
|
||||
end
|
||||
5'b0_0001: begin // DBG_HIT
|
||||
if (debug_wdata_i[0]) begin
|
||||
// TODO: clear SSTH sticky bit
|
||||
end
|
||||
end
|
||||
5'b0_0010: begin // DBG_IE
|
||||
settings_n[`DBG_SETS_ECALL] = debug_wdata_i[11];
|
||||
settings_n[`DBG_SETS_ELSU] = debug_wdata_i[7] | debug_wdata_i[5];
|
||||
settings_n[`DBG_SETS_EBRK] = debug_wdata_i[3];
|
||||
settings_n[`DBG_SETS_EILL] = debug_wdata_i[2];
|
||||
end
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
||||
11'd16: begin // SP_DMR1
|
||||
if(dbginf_we_i == 1'b1)
|
||||
dmr1_n = dbginf_data_i[`DMR1_ST+1:`DMR1_ST];
|
||||
else
|
||||
dbginf_data_o[`DMR1_ST+1:`DMR1_ST] = dmr1_q;
|
||||
end
|
||||
6'b01_0010: begin // Debug Registers, only accessible when in debug
|
||||
debug_gnt_o = 1'b1; // grant it even when invalid access to not block
|
||||
|
||||
11'd20: begin // SP_DSR
|
||||
// currently we only handle IIE and INTE
|
||||
if(dbginf_we_i == 1'b1)
|
||||
dsr_n = dbginf_data_i[7:6];
|
||||
else
|
||||
dbginf_data_o[7:6] = dsr_q[1:0];
|
||||
end
|
||||
if (debug_halted_o) begin
|
||||
unique case (debug_addr_i[6:2])
|
||||
5'b0_0001: jump_req_n = 1'b1; // DNPC
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
// check if internal registers (GPR or SPR) are accessed
|
||||
else if(bp_fsm_cs == StallCore)
|
||||
begin
|
||||
// check if GPRs are accessed
|
||||
if(dbginf_addr_i[15:10] == 6'b000001)
|
||||
begin
|
||||
regfile_mux_o = 1'b1;
|
||||
regfile_addr_o[4:0] = dbginf_addr_i[4:0];
|
||||
6'b01_0000: begin // General-Purpose Registers
|
||||
debug_gnt_o = 1'b1; // grant it even when invalid access to not block
|
||||
|
||||
if(dbginf_we_i == 1'b1)
|
||||
regfile_we_o = 1'b1;
|
||||
else
|
||||
dbginf_data_o = regfile_rdata_i;
|
||||
if (debug_halted_o) begin
|
||||
regfile_wreq = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
// some other SPR is accessed
|
||||
else
|
||||
begin
|
||||
sp_mux_o = 1'b1;
|
||||
regfile_addr_o = dbginf_addr_i[11:0];
|
||||
end else begin
|
||||
//----------------------------------------------------------------------------
|
||||
// read access
|
||||
//----------------------------------------------------------------------------
|
||||
if (debug_addr_i[14]) begin
|
||||
debug_gnt_o = 1'b1; // grant it even when invalid access to not block
|
||||
|
||||
if(dbginf_we_i == 1'b1)
|
||||
regfile_we_o = 1'b1;
|
||||
else
|
||||
dbginf_data_o = regfile_rdata_i;
|
||||
// CSR access
|
||||
if (debug_halted_o) begin
|
||||
// access to internal registers are only allowed when the core is halted
|
||||
csr_req_n = 1'b1;
|
||||
rdata_sel_n = RD_CSR;
|
||||
end
|
||||
end else begin
|
||||
// non-CSR access
|
||||
unique case (debug_addr_i[13:8])
|
||||
6'b00_0000: begin // Debug Registers, always accessible
|
||||
debug_gnt_o = 1'b1;
|
||||
|
||||
rdata_sel_n = RD_DBGA;
|
||||
end
|
||||
|
||||
6'b01_0010: begin // Debug Registers, only accessible when in debug
|
||||
debug_gnt_o = 1'b1; // grant it even when invalid access to not block
|
||||
|
||||
if (debug_halted_o) begin
|
||||
rdata_sel_n = RD_DBGS;
|
||||
end
|
||||
end
|
||||
|
||||
6'b01_0000: begin // General-Purpose Registers
|
||||
debug_gnt_o = 1'b1; // grant it even when invalid access to not block
|
||||
|
||||
if (debug_halted_o) begin
|
||||
regfile_rreq_n = 1'b1;
|
||||
rdata_sel_n = RD_GPR;
|
||||
end
|
||||
end
|
||||
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// debug register read access
|
||||
//
|
||||
// Since those are combinational, we can do it in the cycle where we set
|
||||
// rvalid. The address has been latched into addr_q
|
||||
//----------------------------------------------------------------------------
|
||||
always_comb
|
||||
begin
|
||||
dbg_rdata = '0;
|
||||
|
||||
case (rdata_sel_q)
|
||||
RD_DBGA: begin
|
||||
unique case (addr_q[6:2])
|
||||
5'h00: dbg_rdata[31:0] = {31'b0, settings_q[`DBG_SETS_SSTE]}; // DBG_CTRL
|
||||
5'h01: dbg_rdata[31:0] = {15'b0, debug_halted_o, 16'b0}; // DBG_HIT, TODO: SSTH is missing
|
||||
5'h02: begin // DBG_IE
|
||||
dbg_rdata[31:16] = '0;
|
||||
dbg_rdata[15:12] = '0;
|
||||
dbg_rdata[11] = settings_q[`DBG_SETS_ECALL];
|
||||
dbg_rdata[10: 8] = '0;
|
||||
dbg_rdata[ 7] = settings_q[`DBG_SETS_ELSU];
|
||||
dbg_rdata[ 6] = 1'b0;
|
||||
dbg_rdata[ 5] = settings_q[`DBG_SETS_ELSU];
|
||||
dbg_rdata[ 4] = 1'b0;
|
||||
dbg_rdata[ 3] = settings_q[`DBG_SETS_EBRK];
|
||||
dbg_rdata[ 2] = settings_q[`DBG_SETS_EILL];
|
||||
dbg_rdata[ 1: 0] = '0;
|
||||
end
|
||||
5'h03: dbg_rdata = '1; // DBG_CAUSE. TODO: maybe take from exc controller directly?
|
||||
5'h10: dbg_rdata = '0; // DBG_BPCTRL0
|
||||
5'h12: dbg_rdata = '0; // DBG_BPCTRL1
|
||||
5'h14: dbg_rdata = '0; // DBG_BPCTRL2
|
||||
5'h16: dbg_rdata = '0; // DBG_BPCTRL3
|
||||
5'h18: dbg_rdata = '0; // DBG_BPCTRL4
|
||||
5'h1A: dbg_rdata = '0; // DBG_BPCTRL5
|
||||
5'h1C: dbg_rdata = '0; // DBG_BPCTRL6
|
||||
5'h1E: dbg_rdata = '0; // DBG_BPCTRL7
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
||||
RD_DBGS: begin
|
||||
unique case (debug_addr_i[2:2])
|
||||
1'b0: dbg_rdata = npc_int; // DBG_NPC
|
||||
1'b1: dbg_rdata = ppc_int; // DBG_PPC
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// read data mux
|
||||
//----------------------------------------------------------------------------
|
||||
always_comb
|
||||
begin
|
||||
debug_rdata_o = '0;
|
||||
|
||||
case (rdata_sel_q)
|
||||
RD_CSR: debug_rdata_o = csr_rdata_i;
|
||||
RD_GPR: debug_rdata_o = regfile_rdata_i;
|
||||
RD_DBGA: debug_rdata_o = dbg_rdata;
|
||||
RD_DBGS: debug_rdata_o = dbg_rdata;
|
||||
endcase
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// rvalid generation
|
||||
//----------------------------------------------------------------------------
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (~rst_n) begin
|
||||
debug_rvalid_o <= 1'b0;
|
||||
end else begin
|
||||
debug_rvalid_o <= debug_gnt_o; // always give the rvalid one cycle after gnt
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// stall control
|
||||
//----------------------------------------------------------------------------
|
||||
always_comb
|
||||
begin
|
||||
stall_ns = stall_cs;
|
||||
dbg_req_o = 1'b0;
|
||||
stall_o = 1'b0;
|
||||
debug_halted_o = 1'b0;
|
||||
|
||||
case (stall_cs)
|
||||
RUNNING: begin
|
||||
if (dbg_halt)
|
||||
stall_ns = HALT_REQ;
|
||||
end
|
||||
|
||||
HALT_REQ: begin
|
||||
dbg_req_o = 1'b1;
|
||||
|
||||
if (dbg_ack_i) // TODO: check if we need to set stall already
|
||||
stall_ns = HALT;
|
||||
|
||||
if (dbg_resume)
|
||||
stall_ns = RUNNING;
|
||||
end
|
||||
|
||||
HALT: begin
|
||||
stall_o = 1'b1;
|
||||
debug_halted_o = 1'b1;
|
||||
|
||||
if (dbg_resume)
|
||||
stall_ns = RUNNING;
|
||||
end
|
||||
endcase
|
||||
|
||||
// if a trap is found, halt immediately
|
||||
if (trap_i) begin
|
||||
dbg_req_o = 1'b1;
|
||||
stall_ns = HALT;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (~rst_n) begin
|
||||
stall_cs <= RUNNING;
|
||||
end else begin
|
||||
stall_cs <= stall_ns;
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// rvalid generation
|
||||
//----------------------------------------------------------------------------
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (~rst_n) begin
|
||||
debug_rvalid_o <= 1'b0;
|
||||
end else begin
|
||||
debug_rvalid_o <= debug_gnt_o; // always give the rvalid one cycle after gnt
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// NPC/PPC selection
|
||||
//----------------------------------------------------------------------------
|
||||
always_comb
|
||||
begin
|
||||
pc_tracking_fsm_ns = pc_tracking_fsm_cs;
|
||||
|
@ -239,7 +416,7 @@ module riscv_debug_unit
|
|||
ppc_int = branch_pc_i;
|
||||
npc_int = curr_pc_id_i;
|
||||
|
||||
if (set_npc_o)
|
||||
if (jump_req_o)
|
||||
pc_tracking_fsm_ns = IFEX;
|
||||
end
|
||||
|
||||
|
@ -249,7 +426,7 @@ module riscv_debug_unit
|
|||
endcase
|
||||
|
||||
// set state if trap is encountered
|
||||
if (stall_core_o && (bp_fsm_cs != StallCore)) begin
|
||||
if (dbg_ack_i) begin
|
||||
pc_tracking_fsm_ns = IFID;
|
||||
|
||||
if (branch_in_ex_i) begin
|
||||
|
@ -262,20 +439,74 @@ module riscv_debug_unit
|
|||
end
|
||||
|
||||
|
||||
always_ff@(posedge clk, negedge rst_n)
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0) begin
|
||||
dmr1_q <= '0;
|
||||
dsr_q <= '0;
|
||||
bp_fsm_cs <= Idle;
|
||||
if (~rst_n) begin
|
||||
pc_tracking_fsm_cs <= IFID;
|
||||
end
|
||||
else begin
|
||||
dmr1_q <= dmr1_n;
|
||||
dsr_q <= dsr_n;
|
||||
bp_fsm_cs <= bp_fsm_ns;
|
||||
|
||||
addr_q <= '0;
|
||||
wdata_q <= '0;
|
||||
state_q <= FIRST;
|
||||
rdata_sel_q <= RD_NONE;
|
||||
regfile_rreq_q <= 1'b0;
|
||||
csr_req_q <= 1'b0;
|
||||
jump_req_q <= 1'b0;
|
||||
|
||||
settings_q <= 1'b0;
|
||||
end else begin
|
||||
pc_tracking_fsm_cs <= pc_tracking_fsm_ns;
|
||||
|
||||
// settings
|
||||
settings_q <= settings_n;
|
||||
|
||||
// for the actual interface
|
||||
if (debug_req_i) begin
|
||||
addr_q <= debug_addr_i;
|
||||
wdata_q <= debug_wdata_i;
|
||||
state_q <= FIRST;
|
||||
end
|
||||
|
||||
if (debug_req_i | debug_rvalid_o) begin
|
||||
// wait for either req or rvalid to set those FFs
|
||||
// This makes sure that they are only triggered once when there is
|
||||
// only one request, and the FFs can be properly clock gated otherwise
|
||||
regfile_rreq_q <= regfile_rreq_n;
|
||||
csr_req_q <= csr_req_n;
|
||||
jump_req_q <= jump_req_n;
|
||||
rdata_sel_q <= rdata_sel_n;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign regfile_rreq_o = regfile_rreq_q;
|
||||
assign regfile_raddr_o = addr_q[6:2];
|
||||
|
||||
assign regfile_wreq_o = regfile_wreq;
|
||||
assign regfile_waddr_o = debug_addr_i[6:2];
|
||||
assign regfile_wdata_o = debug_wdata_i;
|
||||
|
||||
assign csr_req_o = csr_req_q;
|
||||
assign csr_addr_o = addr_q[13:2];
|
||||
assign csr_wdata_o = wdata_q;
|
||||
|
||||
assign jump_req_o = jump_req_q;
|
||||
assign jump_addr_o = wdata_q;
|
||||
|
||||
assign settings_o = settings_q;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Assertions
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// check that no registers are accessed when we are not in debug mode
|
||||
assert property (
|
||||
@(posedge clk) (debug_req_i) |-> ((debug_halted_o == 1'b1) ||
|
||||
((debug_addr_i[14] != 1'b1) &&
|
||||
(debug_addr_i[13:7] != 5'b0_1001) &&
|
||||
(debug_addr_i[13:7] != 5'b0_1000)) ) );
|
||||
|
||||
// check that all accesses are word-aligned
|
||||
assert property (
|
||||
@(posedge clk) (debug_req_i) |-> (debug_addr_i[1:0] == 2'b00) );
|
||||
|
||||
endmodule // debug_unit
|
||||
|
|
10
decoder.sv
10
decoder.sv
|
@ -34,7 +34,7 @@ module riscv_decoder
|
|||
input logic mult_multicycle_i, // multiplier taking multiple cycles, using op c as storage
|
||||
|
||||
output logic illegal_insn_o, // illegal instruction encountered
|
||||
output logic trap_insn_o, // trap instruction encountered
|
||||
output logic ebrk_insn_o, // trap instruction encountered
|
||||
output logic eret_insn_o, // return from exception instruction encountered
|
||||
output logic ecall_insn_o, // environment call (syscall) instruction encountered
|
||||
output logic pipe_flush_o, // pipeline flush is requested
|
||||
|
@ -107,7 +107,7 @@ module riscv_decoder
|
|||
logic data_req;
|
||||
logic [2:0] hwloop_we;
|
||||
|
||||
logic trap_insn;
|
||||
logic ebrk_insn;
|
||||
logic eret_insn;
|
||||
logic pipe_flush;
|
||||
|
||||
|
@ -170,7 +170,7 @@ module riscv_decoder
|
|||
data_load_event_o = 1'b0;
|
||||
|
||||
illegal_insn_o = 1'b0;
|
||||
trap_insn = 1'b0;
|
||||
ebrk_insn = 1'b0;
|
||||
eret_insn = 1'b0;
|
||||
ecall_insn_o = 1'b0;
|
||||
pipe_flush = 1'b0;
|
||||
|
@ -831,7 +831,7 @@ module riscv_decoder
|
|||
32'h00_10_00_73: // ebreak
|
||||
begin
|
||||
// debugger trap
|
||||
trap_insn = 1'b1;
|
||||
ebrk_insn = 1'b1;
|
||||
end
|
||||
|
||||
32'h10_00_00_73: // eret
|
||||
|
@ -980,7 +980,7 @@ module riscv_decoder
|
|||
assign hwloop_we_o = (deassert_we_i) ? 3'b0 : hwloop_we;
|
||||
assign csr_op_o = (deassert_we_i) ? `CSR_OP_NONE : csr_op;
|
||||
assign jump_in_id_o = (deassert_we_i) ? `BRANCH_NONE : jump_in_id;
|
||||
assign trap_insn_o = (deassert_we_i) ? 1'b0 : trap_insn;
|
||||
assign ebrk_insn_o = (deassert_we_i) ? 1'b0 : ebrk_insn;
|
||||
assign eret_insn_o = (deassert_we_i) ? 1'b0 : eret_insn; // TODO: do not deassert?
|
||||
assign pipe_flush_o = (deassert_we_i) ? 1'b0 : pipe_flush; // TODO: do not deassert?
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ module riscv_exc_controller
|
|||
output logic req_o,
|
||||
input logic ack_i,
|
||||
|
||||
output logic trap_hit_o,
|
||||
output logic trap_o,
|
||||
|
||||
// to IF stage
|
||||
output logic [1:0] pc_mux_o, // selects target PC for exception
|
||||
|
@ -45,7 +45,7 @@ module riscv_exc_controller
|
|||
input logic irq_enable_i, // interrupt enable bit from CSR
|
||||
|
||||
// from decoder
|
||||
input logic trap_insn_i, // trap instruction encountered (EBREAK)
|
||||
input logic ebrk_insn_i, // ebrk instruction encountered (EBREAK)
|
||||
input logic illegal_insn_i, // illegal instruction encountered
|
||||
input logic ecall_insn_i, // ecall instruction encountered
|
||||
input logic eret_insn_i, // eret instruction encountered
|
||||
|
@ -58,9 +58,7 @@ module riscv_exc_controller
|
|||
output logic save_cause_o,
|
||||
|
||||
// from debug unit
|
||||
input logic dbg_stop_req_i,
|
||||
input logic dbg_step_en_i,
|
||||
input logic [1:0] dbg_dsr_i
|
||||
input logic [`DBG_SETS_W-1:0] dbg_settings_i
|
||||
);
|
||||
|
||||
|
||||
|
@ -80,18 +78,20 @@ module riscv_exc_controller
|
|||
// - illegal instruction exception and IIE bit is set
|
||||
// - IRQ and INTE bit is set and no exception is currently running
|
||||
// - Debuger requests halt
|
||||
assign trap_hit_o = trap_insn_i
|
||||
| dbg_stop_req_i
|
||||
| dbg_step_en_i
|
||||
| (illegal_insn_i & dbg_dsr_i[`DSR_IIE])
|
||||
| (irq_enable_i & (|irq_i) & dbg_dsr_i[`DSR_INTE]);
|
||||
assign trap_o = (dbg_settings_i[`DBG_SETS_SSTE])
|
||||
| (ecall_insn_i & dbg_settings_i[`DBG_SETS_ECALL])
|
||||
| (lsu_load_err_i & dbg_settings_i[`DBG_SETS_ELSU])
|
||||
| (lsu_store_err_i & dbg_settings_i[`DBG_SETS_ELSU])
|
||||
| (ebrk_insn_i & dbg_settings_i[`DBG_SETS_EBRK])
|
||||
| (illegal_insn_i & dbg_settings_i[`DBG_SETS_EILL])
|
||||
| (irq_enable_i & (|irq_i) & dbg_settings_i[`DBG_SETS_IRQ]);
|
||||
|
||||
// request for exception/interrupt
|
||||
assign req_int = ecall_insn_i
|
||||
| lsu_load_err_i
|
||||
| lsu_store_err_i
|
||||
| (illegal_insn_i & (~dbg_dsr_i[`DSR_IIE]))
|
||||
| (irq_enable_i & (|irq_i) & (~dbg_dsr_i[`DSR_INTE]));
|
||||
assign req_int = (ecall_insn_i & (~dbg_settings_i[`DBG_SETS_ECALL]))
|
||||
| (lsu_load_err_i & (~dbg_settings_i[`DBG_SETS_ELSU]))
|
||||
| (lsu_store_err_i & (~dbg_settings_i[`DBG_SETS_ELSU]))
|
||||
| (illegal_insn_i & (~dbg_settings_i[`DBG_SETS_EILL]))
|
||||
| (irq_enable_i & (|irq_i) & (~dbg_settings_i[`DBG_SETS_IRQ]));
|
||||
|
||||
|
||||
// Exception cause and ISR address selection
|
||||
|
@ -100,10 +100,10 @@ module riscv_exc_controller
|
|||
cause_int = 6'b0;
|
||||
pc_mux_int = 'x;
|
||||
|
||||
if (irq_enable_i & (~dbg_dsr_i[`DSR_INTE])) begin
|
||||
if (irq_enable_i & (~dbg_settings_i[`DBG_SETS_IRQ])) begin
|
||||
// pc_mux_int is a critical signal, so try to get it as soon as possible
|
||||
if (|irq_i)
|
||||
pc_mux_int = `EXC_PC_IRQ;
|
||||
pc_mux_int = `EXC_PC_IRQ;
|
||||
|
||||
for (i = 31; i >= 0; i--)
|
||||
begin
|
||||
|
@ -119,17 +119,17 @@ module riscv_exc_controller
|
|||
pc_mux_int = `EXC_PC_ECALL;
|
||||
end
|
||||
|
||||
if (illegal_insn_i & (~dbg_dsr_i[`DSR_IIE])) begin
|
||||
if (illegal_insn_i & (~dbg_settings_i[`DBG_SETS_EILL])) begin
|
||||
cause_int = 6'b0_00010;
|
||||
pc_mux_int = `EXC_PC_ILLINSN;
|
||||
end
|
||||
|
||||
if (lsu_load_err_i) begin
|
||||
if (lsu_load_err_i & (~dbg_settings_i[`DBG_SETS_ELSU])) begin
|
||||
cause_int = 6'b0_00101;
|
||||
pc_mux_int = `EXC_PC_LOAD;
|
||||
end
|
||||
|
||||
if (lsu_store_err_i) begin
|
||||
if (lsu_store_err_i & (~dbg_settings_i[`DBG_SETS_ELSU])) begin
|
||||
cause_int = 6'b0_00111;
|
||||
pc_mux_int = `EXC_PC_STORE;
|
||||
end
|
||||
|
|
49
id_stage.sv
49
id_stage.sv
|
@ -159,17 +159,21 @@ module riscv_id_stage
|
|||
input logic lsu_store_err_i,
|
||||
|
||||
// Debug Unit Signals
|
||||
input logic dbg_stop_req_i,
|
||||
input logic dbg_step_en_i,
|
||||
input logic [1:0] dbg_dsr_i,
|
||||
input logic [`DBG_SETS_W-1:0] dbg_settings_i,
|
||||
input logic dbg_req_i,
|
||||
output logic dbg_ack_o,
|
||||
input logic dbg_stall_i,
|
||||
output logic dbg_trap_o,
|
||||
input logic dbg_reg_mux_i,
|
||||
input logic dbg_reg_we_i,
|
||||
input logic [4:0] dbg_reg_addr_i,
|
||||
input logic [31:0] dbg_reg_wdata_i,
|
||||
|
||||
input logic dbg_reg_rreq_i,
|
||||
input logic [ 4:0] dbg_reg_raddr_i,
|
||||
output logic [31:0] dbg_reg_rdata_o,
|
||||
input logic dbg_set_npc_i,
|
||||
|
||||
input logic dbg_reg_wreq_i,
|
||||
input logic [ 4:0] dbg_reg_waddr_i,
|
||||
input logic [31:0] dbg_reg_wdata_i,
|
||||
|
||||
input logic dbg_jump_req_i,
|
||||
|
||||
// Forward Signals
|
||||
input logic [4:0] regfile_waddr_wb_i,
|
||||
|
@ -195,7 +199,7 @@ module riscv_id_stage
|
|||
logic deassert_we;
|
||||
|
||||
logic illegal_insn_dec;
|
||||
logic trap_insn;
|
||||
logic ebrk_insn;
|
||||
logic eret_insn_dec;
|
||||
logic ecall_insn_dec;
|
||||
logic pipe_flush_dec;
|
||||
|
@ -241,8 +245,6 @@ module riscv_id_stage
|
|||
// Signals running between controller and exception controller
|
||||
logic exc_req, exc_ack; // handshake
|
||||
|
||||
logic trap_hit;
|
||||
|
||||
// Register file interface
|
||||
logic [4:0] regfile_addr_ra_id;
|
||||
logic [4:0] regfile_addr_rb_id;
|
||||
|
@ -693,7 +695,7 @@ module riscv_id_stage
|
|||
.rdata_b_o ( regfile_data_rb_id ),
|
||||
|
||||
// Read port c
|
||||
.raddr_c_i ( (dbg_reg_mux_i == 1'b0) ? regfile_addr_rc_id : dbg_reg_addr_i ),
|
||||
.raddr_c_i ( (dbg_reg_rreq_i == 1'b0) ? regfile_addr_rc_id : dbg_reg_raddr_i ),
|
||||
.rdata_c_o ( regfile_data_rc_id ),
|
||||
|
||||
// Write port a
|
||||
|
@ -702,9 +704,9 @@ module riscv_id_stage
|
|||
.we_a_i ( regfile_we_wb_i ),
|
||||
|
||||
// Write port b
|
||||
.waddr_b_i ( (dbg_reg_mux_i == 1'b0) ? regfile_alu_waddr_fw_i : dbg_reg_addr_i ),
|
||||
.wdata_b_i ( (dbg_reg_mux_i == 1'b0) ? regfile_alu_wdata_fw_i : dbg_reg_wdata_i ),
|
||||
.we_b_i ( (dbg_reg_mux_i == 1'b0) ? regfile_alu_we_fw_i : dbg_reg_we_i )
|
||||
.waddr_b_i ( (dbg_reg_wreq_i == 1'b0) ? regfile_alu_waddr_fw_i : dbg_reg_waddr_i ),
|
||||
.wdata_b_i ( (dbg_reg_wreq_i == 1'b0) ? regfile_alu_wdata_fw_i : dbg_reg_wdata_i ),
|
||||
.we_b_i ( (dbg_reg_wreq_i == 1'b0) ? regfile_alu_we_fw_i : 1'b1 )
|
||||
);
|
||||
|
||||
assign dbg_reg_rdata_o = regfile_data_rc_id;
|
||||
|
@ -727,7 +729,7 @@ module riscv_id_stage
|
|||
.mult_multicycle_i ( mult_multicycle_i ),
|
||||
|
||||
.illegal_insn_o ( illegal_insn_dec ),
|
||||
.trap_insn_o ( trap_insn ),
|
||||
.ebrk_insn_o ( ebrk_insn ),
|
||||
.eret_insn_o ( eret_insn_dec ),
|
||||
.ecall_insn_o ( ecall_insn_dec ),
|
||||
.pipe_flush_o ( pipe_flush_dec ),
|
||||
|
@ -849,15 +851,15 @@ module riscv_id_stage
|
|||
// Exception Controller Signals
|
||||
.exc_req_i ( exc_req ),
|
||||
.exc_ack_o ( exc_ack ),
|
||||
.trap_hit_i ( trap_hit ),
|
||||
|
||||
.exc_save_id_o ( exc_save_id_o ),
|
||||
.exc_restore_id_o ( exc_restore_id_o ),
|
||||
|
||||
// Debug Unit Signals
|
||||
.dbg_req_i ( dbg_req_i ),
|
||||
.dbg_ack_o ( dbg_ack_o ),
|
||||
.dbg_stall_i ( dbg_stall_i ),
|
||||
.dbg_set_npc_i ( dbg_set_npc_i ),
|
||||
.dbg_trap_o ( dbg_trap_o ),
|
||||
.dbg_jump_req_i ( dbg_jump_req_i ),
|
||||
|
||||
// Forwarding signals from regfile
|
||||
.regfile_waddr_ex_i ( regfile_waddr_ex_o ), // Write address for register file from ex-wb- pipeline registers
|
||||
|
@ -922,7 +924,7 @@ module riscv_id_stage
|
|||
.req_o ( exc_req ),
|
||||
.ack_i ( exc_ack ),
|
||||
|
||||
.trap_hit_o ( trap_hit ),
|
||||
.trap_o ( dbg_trap_o ),
|
||||
|
||||
// to IF stage
|
||||
.pc_mux_o ( exc_pc_mux_o ),
|
||||
|
@ -932,7 +934,7 @@ module riscv_id_stage
|
|||
.irq_i ( irq_i ),
|
||||
.irq_enable_i ( irq_enable_i ),
|
||||
|
||||
.trap_insn_i ( is_decoding_o & trap_insn ),
|
||||
.ebrk_insn_i ( is_decoding_o & ebrk_insn ),
|
||||
.illegal_insn_i ( is_decoding_o & illegal_insn_dec ),
|
||||
.ecall_insn_i ( is_decoding_o & ecall_insn_dec ),
|
||||
.eret_insn_i ( is_decoding_o & eret_insn_dec ),
|
||||
|
@ -943,10 +945,7 @@ module riscv_id_stage
|
|||
.cause_o ( exc_cause_o ),
|
||||
.save_cause_o ( save_exc_cause_o ),
|
||||
|
||||
// Debug Signals
|
||||
.dbg_stop_req_i ( dbg_stop_req_i ),
|
||||
.dbg_step_en_i ( dbg_step_en_i ),
|
||||
.dbg_dsr_i ( dbg_dsr_i )
|
||||
.dbg_settings_i ( dbg_settings_i )
|
||||
);
|
||||
|
||||
|
||||
|
|
|
@ -78,8 +78,8 @@ module riscv_if_stage
|
|||
input logic [N_HWLP-1:0] [31:0] hwlp_cnt_i, // hardware loop counters
|
||||
|
||||
// from debug unit
|
||||
input logic [31:0] dbg_npc_i,
|
||||
input logic dbg_set_npc_i,
|
||||
input logic [31:0] dbg_jump_addr_i,
|
||||
input logic dbg_jump_req_i,
|
||||
|
||||
// pipeline stall
|
||||
input logic halt_if_i,
|
||||
|
@ -143,7 +143,7 @@ module riscv_if_stage
|
|||
`PC_BRANCH: fetch_addr_n = jump_target_ex_i;
|
||||
`PC_EXCEPTION: fetch_addr_n = exc_pc; // set PC to exception handler
|
||||
`PC_ERET: fetch_addr_n = exception_pc_reg_i; // PC is restored when returning from IRQ/exception
|
||||
`PC_DBG_NPC: fetch_addr_n = dbg_npc_i; // PC is taken from debug unit
|
||||
`PC_DBG_NPC: fetch_addr_n = dbg_jump_addr_i; // PC is taken from debug unit
|
||||
|
||||
default:;
|
||||
endcase
|
||||
|
|
|
@ -318,10 +318,14 @@
|
|||
|
||||
|
||||
// Debug module
|
||||
`define DMR1_ST 22
|
||||
`define DBG_SETS_W 6
|
||||
|
||||
`define DSR_IIE 0
|
||||
`define DSR_INTE 1
|
||||
`define DBG_SETS_IRQ 5
|
||||
`define DBG_SETS_ECALL 4
|
||||
`define DBG_SETS_EILL 3
|
||||
`define DBG_SETS_ELSU 2
|
||||
`define DBG_SETS_EBRK 1
|
||||
`define DBG_SETS_SSTE 0
|
||||
|
||||
|
||||
`endif
|
||||
|
|
179
riscv_core.sv
179
riscv_core.sv
|
@ -34,9 +34,10 @@ module riscv_core
|
|||
)
|
||||
(
|
||||
// Clock and Reset
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input logic clock_en_i, // enable clock, otherwise it is gated
|
||||
input logic test_en_i, // enable all clock gates for testing
|
||||
|
||||
// Core ID, Cluster ID and boot address are considered more or less static
|
||||
|
@ -66,14 +67,15 @@ module riscv_core
|
|||
input logic [31:0] irq_i, // level sensitive IR lines
|
||||
|
||||
// Debug Interface
|
||||
input logic dbginf_stall_i,
|
||||
output logic dbginf_bp_o,
|
||||
input logic dbginf_strobe_i,
|
||||
output logic dbginf_ack_o,
|
||||
input logic dbginf_we_i,
|
||||
input logic [15:0] dbginf_addr_i,
|
||||
input logic [31:0] dbginf_data_i,
|
||||
output logic [31:0] dbginf_data_o,
|
||||
input logic debug_req_i,
|
||||
output logic debug_gnt_o,
|
||||
output logic debug_rvalid_o,
|
||||
input logic [14:0] debug_addr_i,
|
||||
input logic debug_we_i,
|
||||
input logic [31:0] debug_wdata_i,
|
||||
output logic [31:0] debug_rdata_o,
|
||||
output logic debug_halted_o,
|
||||
input logic debug_halt_i,
|
||||
|
||||
// CPU Control Signals
|
||||
input logic fetch_enable_i,
|
||||
|
@ -85,7 +87,6 @@ module riscv_core
|
|||
localparam N_HWLP = 2;
|
||||
localparam N_HWLP_BITS = $clog2(N_HWLP);
|
||||
|
||||
|
||||
// IF/ID signals
|
||||
logic is_hwlp_id;
|
||||
logic [N_HWLP-1:0] hwlp_dec_cnt_id;
|
||||
|
@ -223,22 +224,30 @@ module riscv_core
|
|||
|
||||
|
||||
// Debug Unit
|
||||
logic [`DBG_SETS_W-1:0] dbg_settings;
|
||||
logic dbg_req;
|
||||
logic dbg_ack;
|
||||
logic dbg_stall;
|
||||
logic dbg_stop_req;
|
||||
logic dbg_trap;
|
||||
logic dbg_step_en; // single-step trace mode enabled
|
||||
logic [1:0] dbg_dsr; // Debug Stop Register
|
||||
|
||||
logic dbg_reg_mux;
|
||||
logic dbg_sp_mux;
|
||||
logic dbg_reg_we;
|
||||
logic [11:0] dbg_reg_addr;
|
||||
logic [31:0] dbg_reg_wdata;
|
||||
// Debug GPR Read Access
|
||||
logic dbg_reg_rreq;
|
||||
logic [ 4:0] dbg_reg_raddr;
|
||||
logic [31:0] dbg_reg_rdata;
|
||||
logic [31:0] dbg_rdata;
|
||||
|
||||
logic [31:0] dbg_npc;
|
||||
logic dbg_set_npc;
|
||||
// Debug GPR Write Access
|
||||
logic dbg_reg_wreq;
|
||||
logic [ 4:0] dbg_reg_waddr;
|
||||
logic [31:0] dbg_reg_wdata;
|
||||
|
||||
// Debug CSR Access
|
||||
logic dbg_csr_req;
|
||||
logic [11:0] dbg_csr_addr;
|
||||
logic dbg_csr_we;
|
||||
logic [31:0] dbg_csr_wdata;
|
||||
|
||||
logic [31:0] dbg_jump_addr;
|
||||
logic dbg_jump_req;
|
||||
|
||||
// Performance Counters
|
||||
logic perf_imiss;
|
||||
|
@ -246,12 +255,25 @@ module riscv_core
|
|||
logic perf_jr_stall;
|
||||
logic perf_ld_stall;
|
||||
|
||||
logic clk;
|
||||
|
||||
|
||||
// if we are sleeping on a barrier let's just wait on the instruction
|
||||
// interface to finish loading instructions
|
||||
assign core_busy_o = (data_load_event_ex && data_req_o) ? if_busy : (if_busy || core_busy || lsu_busy);
|
||||
|
||||
|
||||
// main clock gate of the core
|
||||
// generates all clocks except the one for the debug unit which is
|
||||
// independent
|
||||
cluster_clock_gating core_clock_gate_i
|
||||
(
|
||||
.clk_i ( clk_i ),
|
||||
.en_i ( clock_en_i ),
|
||||
.test_en_i ( test_en_i ),
|
||||
.clk_o ( clk )
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// ___ _____ ____ _____ _ ____ _____ //
|
||||
// |_ _| ___| / ___|_ _|/ \ / ___| ____| //
|
||||
|
@ -268,7 +290,7 @@ module riscv_core
|
|||
if_stage_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.rst_n ( rst_ni ),
|
||||
|
||||
// boot address (trap vector location)
|
||||
.boot_addr_i ( boot_addr_i ),
|
||||
|
@ -307,8 +329,8 @@ module riscv_core
|
|||
.hwlp_cnt_i ( hwlp_cnt ),
|
||||
|
||||
// from debug unit
|
||||
.dbg_npc_i ( dbg_npc ),
|
||||
.dbg_set_npc_i ( dbg_set_npc ),
|
||||
.dbg_jump_addr_i ( dbg_jump_addr ),
|
||||
.dbg_jump_req_i ( dbg_jump_req ),
|
||||
|
||||
// Jump targets
|
||||
.jump_target_id_i ( jump_target_id ),
|
||||
|
@ -340,7 +362,7 @@ module riscv_core
|
|||
id_stage_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.rst_n ( rst_ni ),
|
||||
|
||||
.test_en_i ( test_en_i ),
|
||||
|
||||
|
@ -458,17 +480,21 @@ module riscv_core
|
|||
.lsu_store_err_i ( lsu_store_err ),
|
||||
|
||||
// Debug Unit Signals
|
||||
.dbg_stop_req_i ( dbg_stop_req ),
|
||||
.dbg_step_en_i ( dbg_step_en ),
|
||||
.dbg_dsr_i ( dbg_dsr ),
|
||||
.dbg_settings_i ( dbg_settings ),
|
||||
.dbg_req_i ( dbg_req ),
|
||||
.dbg_ack_o ( dbg_ack ),
|
||||
.dbg_stall_i ( dbg_stall ),
|
||||
.dbg_trap_o ( dbg_trap ),
|
||||
.dbg_reg_mux_i ( dbg_reg_mux ),
|
||||
.dbg_reg_we_i ( dbg_reg_we ),
|
||||
.dbg_reg_addr_i ( dbg_reg_addr[4:0] ),
|
||||
.dbg_reg_wdata_i ( dbg_reg_wdata ),
|
||||
|
||||
.dbg_reg_rreq_i ( dbg_reg_rreq ),
|
||||
.dbg_reg_raddr_i ( dbg_reg_raddr ),
|
||||
.dbg_reg_rdata_o ( dbg_reg_rdata ),
|
||||
.dbg_set_npc_i ( dbg_set_npc ),
|
||||
|
||||
.dbg_reg_wreq_i ( dbg_reg_wreq ),
|
||||
.dbg_reg_waddr_i ( dbg_reg_waddr ),
|
||||
.dbg_reg_wdata_i ( dbg_reg_wdata ),
|
||||
|
||||
.dbg_jump_req_i ( dbg_jump_req ),
|
||||
|
||||
// Forward Signals
|
||||
.regfile_waddr_wb_i ( regfile_waddr_fw_wb_o), // Write address ex-wb pipeline
|
||||
|
@ -501,7 +527,7 @@ module riscv_core
|
|||
(
|
||||
// Global signals: Clock and active low asynchronous reset
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.rst_n ( rst_ni ),
|
||||
|
||||
// Alu signals from ID stage
|
||||
.alu_operator_i ( alu_operator_ex ), // from ID/EX pipe registers
|
||||
|
@ -575,7 +601,7 @@ module riscv_core
|
|||
riscv_load_store_unit load_store_unit_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.rst_n ( rst_ni ),
|
||||
|
||||
//output to data memory
|
||||
.data_req_o ( data_req_o ),
|
||||
|
@ -637,14 +663,14 @@ module riscv_core
|
|||
cs_registers_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.rst_n ( rst_ni ),
|
||||
|
||||
// Core and Cluster ID from outside
|
||||
.core_id_i ( core_id_i ),
|
||||
.cluster_id_i ( cluster_id_i ),
|
||||
|
||||
// Interface to CSRs (SRAM like)
|
||||
.csr_access_i ( csr_access_ex ),
|
||||
.csr_access_i ( csr_access ),
|
||||
.csr_addr_i ( csr_addr ),
|
||||
.csr_wdata_i ( csr_wdata ),
|
||||
.csr_op_i ( csr_op ),
|
||||
|
@ -692,14 +718,12 @@ module riscv_core
|
|||
);
|
||||
|
||||
// Mux for CSR access through Debug Unit
|
||||
assign csr_access = (dbg_sp_mux == 1'b0) ? csr_access_ex : 1'b1;
|
||||
assign csr_addr = (dbg_sp_mux == 1'b0) ? csr_addr_int : dbg_reg_addr;
|
||||
assign csr_wdata = (dbg_sp_mux == 1'b0) ? alu_operand_a_ex : dbg_reg_wdata;
|
||||
assign csr_op = (dbg_sp_mux == 1'b0) ? csr_op_ex
|
||||
: (dbg_reg_we == 1'b1 ? `CSR_OP_WRITE
|
||||
: `CSR_OP_NONE );
|
||||
assign dbg_rdata = (dbg_sp_mux == 1'b0) ? dbg_reg_rdata : csr_rdata;
|
||||
|
||||
assign csr_access = (dbg_csr_req == 1'b0) ? csr_access_ex : 1'b1;
|
||||
assign csr_addr = (dbg_csr_req == 1'b0) ? csr_addr_int : dbg_csr_addr;
|
||||
assign csr_wdata = (dbg_csr_req == 1'b0) ? alu_operand_a_ex : dbg_csr_wdata;
|
||||
assign csr_op = (dbg_csr_req == 1'b0) ? csr_op_ex
|
||||
: (dbg_csr_we == 1'b1 ? `CSR_OP_WRITE
|
||||
: `CSR_OP_NONE );
|
||||
assign csr_addr_int = csr_access_ex ? alu_operand_b_ex[11:0] : '0;
|
||||
|
||||
|
||||
|
@ -714,34 +738,43 @@ module riscv_core
|
|||
|
||||
riscv_debug_unit debug_unit_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.clk ( clk_i ), // always-running clock for debug
|
||||
.rst_n ( rst_ni ),
|
||||
|
||||
// Debug Interface
|
||||
.dbginf_stall_i ( dbginf_stall_i ),
|
||||
.dbginf_bp_o ( dbginf_bp_o ),
|
||||
.dbginf_strobe_i ( dbginf_strobe_i ),
|
||||
.dbginf_ack_o ( dbginf_ack_o ),
|
||||
.dbginf_we_i ( dbginf_we_i ),
|
||||
.dbginf_addr_i ( dbginf_addr_i ),
|
||||
.dbginf_data_i ( dbginf_data_i ),
|
||||
.dbginf_data_o ( dbginf_data_o ),
|
||||
.debug_req_i ( debug_req_i ),
|
||||
.debug_gnt_o ( debug_gnt_o ),
|
||||
.debug_rvalid_o ( debug_rvalid_o ),
|
||||
.debug_addr_i ( debug_addr_i ),
|
||||
.debug_we_i ( debug_we_i ),
|
||||
.debug_wdata_i ( debug_wdata_i ),
|
||||
.debug_rdata_o ( debug_rdata_o ),
|
||||
.debug_halt_i ( debug_halt_i ),
|
||||
.debug_halted_o ( debug_halted_o ),
|
||||
|
||||
// To/From Core
|
||||
.dbg_step_en_o ( dbg_step_en ),
|
||||
.dbg_dsr_o ( dbg_dsr ),
|
||||
|
||||
.stall_core_o ( dbg_stall ),
|
||||
.stop_req_o ( dbg_stop_req ),
|
||||
.settings_o ( dbg_settings ),
|
||||
.stall_o ( dbg_stall ),
|
||||
.dbg_req_o ( dbg_req ),
|
||||
.dbg_ack_i ( dbg_ack ),
|
||||
.trap_i ( dbg_trap ),
|
||||
|
||||
// register file access
|
||||
.sp_mux_o ( dbg_sp_mux ),
|
||||
.regfile_mux_o ( dbg_reg_mux ),
|
||||
.regfile_we_o ( dbg_reg_we ),
|
||||
.regfile_addr_o ( dbg_reg_addr ),
|
||||
// register file read port
|
||||
.regfile_rreq_o ( dbg_reg_rreq ),
|
||||
.regfile_raddr_o ( dbg_reg_raddr ),
|
||||
.regfile_rdata_i ( dbg_reg_rdata ),
|
||||
|
||||
// register file write port
|
||||
.regfile_wreq_o ( dbg_reg_wreq ),
|
||||
.regfile_waddr_o ( dbg_reg_waddr ),
|
||||
.regfile_wdata_o ( dbg_reg_wdata ),
|
||||
.regfile_rdata_i ( dbg_rdata ),
|
||||
|
||||
// CSR read/write port
|
||||
.csr_req_o ( dbg_csr_req ),
|
||||
.csr_addr_o ( dbg_csr_addr ),
|
||||
.csr_we_o ( dbg_csr_we ),
|
||||
.csr_wdata_o ( dbg_csr_wdata ),
|
||||
.csr_rdata_i ( csr_rdata ),
|
||||
|
||||
// signals for PPC and NPC
|
||||
.curr_pc_if_i ( pc_if ), // from IF stage
|
||||
|
@ -751,16 +784,16 @@ module riscv_core
|
|||
.branch_in_ex_i ( branch_in_ex ),
|
||||
.branch_taken_i ( branch_decision ),
|
||||
|
||||
.npc_o ( dbg_npc ), // PC from debug unit
|
||||
.set_npc_o ( dbg_set_npc ) // set PC to new value
|
||||
.jump_addr_o ( dbg_jump_addr ), // PC from debug unit
|
||||
.jump_req_o ( dbg_jump_req ) // set PC to new value
|
||||
);
|
||||
|
||||
|
||||
`ifdef TRACE_EXECUTION
|
||||
riscv_tracer riscv_tracer_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.clk ( clk_i ), // always-running clock for tracing
|
||||
.rst_n ( rst_ni ),
|
||||
|
||||
.fetch_enable ( fetch_enable_i ),
|
||||
.core_id ( core_id_i ),
|
||||
|
@ -817,8 +850,8 @@ module riscv_core
|
|||
|
||||
riscv_simchecker riscv_simchecker_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.clk ( clk_i ), // always-running clock for tracing
|
||||
.rst_n ( rst_ni ),
|
||||
|
||||
.fetch_enable ( fetch_enable_i ),
|
||||
.boot_addr ( boot_addr_i ),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue