Commit 2f6df067 authored by Tristan Gingold's avatar Tristan Gingold Committed by Dimitris Lampridis

Initial implementation of debug mode.

parent 87d2fe12
......@@ -32,27 +32,42 @@ module urv_cpu
parameter g_debug_breakpoints = 6
)
(
input clk_i,
input rst_i,
input clk_i,
input rst_i,
input irq_i,
input irq_i,
// instruction mem I/F
output [31:0] im_addr_o,
input [31:0] im_data_i,
input im_valid_i,
input im_valid_i,
// data mem I/F
output [31:0] dm_addr_o,
output [31:0] dm_data_s_o,
input [31:0] dm_data_l_i,
output [3:0] dm_data_select_o,
input dm_ready_i,
output dm_store_o,
output dm_load_o,
input dm_load_done_i,
input dm_store_done_i
input dm_ready_i,
output dm_store_o,
output dm_load_o,
input dm_load_done_i,
input dm_store_done_i,
// Debug I/F
// Debug mode is entered either when dbg_force_i is set, or when the ebreak
// instructions is executed. Debug mode is left when the ebreak instruction
// is executed (from the dbg_insn_i port).
// When debug mode is entered, dbg_enabled_o is set. This may not be
// immediate. Interrupts are disabled in debug mode.
// In debug mode, instructions are executed from dbg_insn_i. An instruction
// is fetched when dbg_insn_read_o is set. As instructions are always
// fetched, they must be always valid. Use a nop (0x19) if nothing should
// be executed.
input dbg_force_i,
output dbg_enabled_o,
input [31:0] dbg_insn_i,
output dbg_insn_ready_o
);
......@@ -71,6 +86,7 @@ module urv_cpu
// X1->F stage interface
wire [31:0] x2f_pc_bra;
wire x2f_bra;
wire x2f_dbg_toggle;
// F->D stage interface
wire [31:0] f2d_pc, f2d_ir;
......@@ -105,7 +121,7 @@ module urv_cpu
wire d2x_rd_write;
wire [11:0] d2x_csr_sel;
wire [4:0] d2x_csr_imm;
wire d2x_is_csr, d2x_is_mret, d2x_csr_load_en;
wire d2x_is_csr, d2x_is_mret, d2x_is_ebreak, d2x_csr_load_en;
wire [31:0] d2x_alu_op1, d2x_alu_op2;
wire d2x_use_op1, d2x_use_op2;
......@@ -150,7 +166,13 @@ module urv_cpu
// from X1 stage (jumps)
.x_pc_bra_i(x2f_pc_bra),
.x_bra_i(x2f_bra)
.x_bra_i(x2f_bra),
.dbg_force_i(dbg_force_i),
.dbg_enabled_o(dbg_enabled_o),
.dbg_insn_i(dbg_insn_i),
.dbg_insn_ready_o(dbg_insn_ready_o),
.x_dbg_toggle(x_dbg_toggle)
);
......@@ -197,6 +219,7 @@ module urv_cpu
.x_csr_imm_o (d2x_csr_imm),
.x_is_csr_o (d2x_is_csr),
.x_is_mret_o (d2x_is_mret),
.x_is_ebreak_o (d2x_is_ebreak),
.x_alu_op1_o(d2x_alu_op1),
.x_alu_op2_o(d2x_alu_op2),
.x_use_op1_o(d2x_use_op1),
......@@ -249,6 +272,7 @@ module urv_cpu
.d_valid_i(d2x_valid),
.d_is_csr_i (d2x_is_csr),
.d_is_mret_i (d2x_is_mret),
.d_is_ebreak_i (d2x_is_ebreak),
.d_csr_imm_i (d2x_csr_imm),
.d_csr_sel_i (d2x_csr_sel),
.d_pc_i(d2x_pc),
......@@ -273,8 +297,9 @@ module urv_cpu
.d_shifter_sign_i(d2x_shifter_sign),
// to F stage (branches)
.f_branch_target_o (x2f_pc_bra), // fixme: consistent naming
.f_branch_take_o (x2f_bra),
.f_branch_target_o(x2f_pc_bra), // fixme: consistent naming
.f_branch_take_o(x2f_bra),
.f_dbg_toggle_o(x2f_dbg_toggle),
// to X2/W stage
.w_fun_o(x2w_fun),
......
......@@ -25,52 +25,53 @@
module urv_decode
(
input clk_i,
input rst_i,
input clk_i,
input rst_i,
// pipeline control
input d_stall_i,
input d_kill_i,
output d_stall_req_o,
input d_stall_i,
input d_kill_i,
output d_stall_req_o,
// from Fetch stage
input [31:0] f_ir_i,
input [31:0] f_pc_i,
input f_valid_i,
input [31:0] f_ir_i,
input [31:0] f_pc_i,
input f_valid_i,
// to Register File (not registered: direct from fetch stage).
output [4:0] rf_rs1_o,
output [4:0] rf_rs2_o,
output [4:0] rf_rs1_o,
output [4:0] rf_rs2_o,
// to Execute 1 stage
output x_valid_o,
output x_valid_o,
output reg [31:0] x_pc_o,
output [4:0] x_rs1_o,
output [4:0] x_rs2_o,
output [4:0] x_rd_o,
output [4:0] x_rs1_o,
output [4:0] x_rs2_o,
output [4:0] x_rd_o,
output reg [4:0] x_shamt_o,
output reg [2:0] x_fun_o,
output [4:0] x_opcode_o,
output reg x_shifter_sign_o,
output reg x_is_signed_compare_o,
output reg x_is_signed_alu_op_o,
output reg x_is_add_o,
output x_is_shift_o,
output reg x_is_load_o,
output reg x_is_store_o,
output reg x_is_undef_o,
output [4:0] x_opcode_o,
output reg x_shifter_sign_o,
output reg x_is_signed_compare_o,
output reg x_is_signed_alu_op_o,
output reg x_is_add_o,
output x_is_shift_o,
output reg x_is_load_o,
output reg x_is_store_o,
output reg x_is_undef_o,
output reg [2:0] x_rd_source_o,
output x_rd_write_o,
output x_rd_write_o,
output reg [11:0] x_csr_sel_o,
output reg [4:0] x_csr_imm_o,
output reg x_is_csr_o,
output reg x_is_mret_o,
output reg x_is_csr_o,
output reg x_is_mret_o,
output reg x_is_ebreak_o,
output reg [31:0] x_imm_o,
output reg [31:0] x_alu_op1_o,
output reg [31:0] x_alu_op2_o,
output reg x_use_op1_o,
output reg x_use_op2_o
output reg x_use_op1_o,
output reg x_use_op2_o
);
wire [4:0] f_rs1 = f_ir_i[19:15];
......@@ -142,7 +143,7 @@ module urv_decode
assign x_valid_o = x_valid;
always@(posedge clk_i)
if(rst_i || d_kill_i )
if(rst_i || d_kill_i)
begin
x_pc_o <= 0;
x_valid <= 0;
......@@ -179,7 +180,7 @@ module urv_decode
if(!d_stall_i)
x_shifter_sign_o <= f_ir_i[30];
wire[31:0] d_imm_i = { {21{ f_ir_i[31] }}, f_ir_i[30:25], f_ir_i[24:21], f_ir_i[20] };
wire [31:0] d_imm_i = { {21{ f_ir_i[31] }}, f_ir_i[30:25], f_ir_i[24:21], f_ir_i[20] };
wire [31:0] d_imm_s = { {21{ f_ir_i[31] }}, f_ir_i[30:25], f_ir_i[11:8], f_ir_i[7] };
wire [31:0] d_imm_b = { {20{ f_ir_i[31] }}, f_ir_i[7], f_ir_i[30:25], f_ir_i[11:8], 1'b0 };
wire [31:0] d_imm_u = { f_ir_i[31], f_ir_i[30:20], f_ir_i[19:12], 12'h000 };
......@@ -322,6 +323,7 @@ module urv_decode
x_csr_sel_o <= f_ir_i[31:20];
x_is_csr_o <= (d_opcode == `OPC_SYSTEM) && (d_fun != 0);
x_is_mret_o <= (d_opcode == `OPC_SYSTEM) && (d_fun == 0) && (f_ir_i [31:20] == 12'b0011000_00010);
x_is_ebreak_o <= (d_opcode == `OPC_SYSTEM) && (d_fun == 0) && (f_ir_i [31:20] == 12'b0000000_00001);
end
assign x_is_shift_o = x_is_shift;
......
......@@ -49,6 +49,7 @@ module urv_exec
input d_is_csr_i,
input d_is_mret_i,
input d_is_ebreak_i,
input [4:0] d_csr_imm_i,
input [11:0] d_csr_sel_i,
......@@ -74,6 +75,7 @@ module urv_exec
output reg [31:0] f_branch_target_o,
output f_branch_take_o,
output reg f_dbg_toggle_o,
input irq_i,
......@@ -452,7 +454,8 @@ module urv_exec
if (rst_i)
begin
f_branch_take <= 0;
w_load_o <= 0;
f_dbg_toggle_o <= 0;
w_load_o <= 0;
w_store_o <= 0;
w_valid_o <= 0;
......@@ -461,7 +464,8 @@ module urv_exec
begin
f_branch_target_o <= branch_target;
f_branch_take <= branch_take && !x_kill_i && d_valid_i;
w_rd_o <= d_rd_i;
f_dbg_toggle_o <= d_is_ebreak_i && !x_kill_i && d_valid_i;
w_rd_o <= d_rd_i;
w_rd_value_o <= rd_value;
w_rd_write_o <= d_rd_write_i && !x_kill_i && d_valid_i && !x_exception;
......
......@@ -40,7 +40,14 @@ module urv_fetch
// Branch control
input [31:0] x_pc_bra_i,
input x_bra_i
input x_bra_i,
// Debug mode
input dbg_force_i,
output dbg_enabled_o,
input [31:0] dbg_insn_i,
output reg dbg_insn_ready_o,
input x_dbg_toggle
);
reg [31:0] pc;
......@@ -48,6 +55,8 @@ module urv_fetch
reg [31:0] pc_next;
reg [31:0] pc_plus_4;
reg dbg_mode;
reg [2:0] pipeline_cnt;
always@*
if( x_bra_i )
......@@ -60,6 +69,8 @@ module urv_fetch
// Start fetching the next instruction
assign im_addr_o = pc_next;
assign dbg_enabled_o = dbg_mode;
always@(posedge clk_i)
if (rst_i)
begin
......@@ -70,6 +81,12 @@ module urv_fetch
f_ir_o <= 0;
f_valid_o <= 0;
// Allow to start in debug mode.
dbg_mode <= dbg_force_i;
dbg_insn_ready_o <= dbg_force_i;
pipeline_cnt <= 0;
// The instruction won't be valid on the next cycle, as the
// instruction memory is registered.
rst_d <= 0;
......@@ -82,7 +99,40 @@ module urv_fetch
begin
f_pc_o <= pc;
if(im_valid_i)
if((dbg_force_i || x_dbg_toggle) && !dbg_mode)
begin
// Try to enter in debug mode.
f_valid_o <= 0;
if (pipeline_cnt == 5)
dbg_mode <= 1;
else
pipeline_cnt <= pipeline_cnt + 1;
end
else if(dbg_mode)
begin
// Default: insn not valid
f_valid_o <= 0;
if (x_dbg_toggle)
begin
// Leave debug mode
dbg_mode <= 0;
pipeline_cnt <= 0;
// dbg_insn_ready_o must be 0.
end
else if (dbg_insn_ready_o)
begin
f_ir_o <= dbg_insn_i;
f_valid_o <= 1;
dbg_insn_ready_o <= 0;
pipeline_cnt <= 0;
end
else if (pipeline_cnt == 5)
dbg_insn_ready_o <= 1;
else
pipeline_cnt <= pipeline_cnt + 1;
end
else if(im_valid_i)
begin
pc_plus_4 <= (x_bra_i ? x_pc_bra_i : pc_plus_4) + 4;
f_ir_o <= im_data_i;
......
......@@ -137,7 +137,13 @@ module main;
.dm_load_o(),
.dm_store_done_i(1'b1),
.dm_load_done_i(1'b1),
.dm_ready_i(dm_ready)
.dm_ready_i(dm_ready),
// Debug
.dbg_force_i(0),
.dbg_enabled_o(),
.dbg_insn_i(0),
.dbg_insn_ready_o()
);
always #5ns clk <= ~clk;
......
This diff is collapsed.
......@@ -117,7 +117,13 @@ module main;
.dm_load_o(),
.dm_store_done_i(1'b1),
.dm_load_done_i(1'b1),
.dm_ready_i(dm_ready)
.dm_ready_i(dm_ready),
// Debug
.dbg_force_i(1'b0),
.dbg_enabled_o(),
.dbg_insn_i(32'h0),
.dbg_insn_ready_o()
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment