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 ...@@ -32,27 +32,42 @@ module urv_cpu
parameter g_debug_breakpoints = 6 parameter g_debug_breakpoints = 6
) )
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
input irq_i, input irq_i,
// instruction mem I/F // instruction mem I/F
output [31:0] im_addr_o, output [31:0] im_addr_o,
input [31:0] im_data_i, input [31:0] im_data_i,
input im_valid_i, input im_valid_i,
// data mem I/F // data mem I/F
output [31:0] dm_addr_o, output [31:0] dm_addr_o,
output [31:0] dm_data_s_o, output [31:0] dm_data_s_o,
input [31:0] dm_data_l_i, input [31:0] dm_data_l_i,
output [3:0] dm_data_select_o, output [3:0] dm_data_select_o,
input dm_ready_i, input dm_ready_i,
output dm_store_o, output dm_store_o,
output dm_load_o, output dm_load_o,
input dm_load_done_i, input dm_load_done_i,
input dm_store_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 ...@@ -71,6 +86,7 @@ module urv_cpu
// X1->F stage interface // X1->F stage interface
wire [31:0] x2f_pc_bra; wire [31:0] x2f_pc_bra;
wire x2f_bra; wire x2f_bra;
wire x2f_dbg_toggle;
// F->D stage interface // F->D stage interface
wire [31:0] f2d_pc, f2d_ir; wire [31:0] f2d_pc, f2d_ir;
...@@ -105,7 +121,7 @@ module urv_cpu ...@@ -105,7 +121,7 @@ module urv_cpu
wire d2x_rd_write; wire d2x_rd_write;
wire [11:0] d2x_csr_sel; wire [11:0] d2x_csr_sel;
wire [4:0] d2x_csr_imm; 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 [31:0] d2x_alu_op1, d2x_alu_op2;
wire d2x_use_op1, d2x_use_op2; wire d2x_use_op1, d2x_use_op2;
...@@ -150,7 +166,13 @@ module urv_cpu ...@@ -150,7 +166,13 @@ module urv_cpu
// from X1 stage (jumps) // from X1 stage (jumps)
.x_pc_bra_i(x2f_pc_bra), .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 ...@@ -197,6 +219,7 @@ module urv_cpu
.x_csr_imm_o (d2x_csr_imm), .x_csr_imm_o (d2x_csr_imm),
.x_is_csr_o (d2x_is_csr), .x_is_csr_o (d2x_is_csr),
.x_is_mret_o (d2x_is_mret), .x_is_mret_o (d2x_is_mret),
.x_is_ebreak_o (d2x_is_ebreak),
.x_alu_op1_o(d2x_alu_op1), .x_alu_op1_o(d2x_alu_op1),
.x_alu_op2_o(d2x_alu_op2), .x_alu_op2_o(d2x_alu_op2),
.x_use_op1_o(d2x_use_op1), .x_use_op1_o(d2x_use_op1),
...@@ -249,6 +272,7 @@ module urv_cpu ...@@ -249,6 +272,7 @@ module urv_cpu
.d_valid_i(d2x_valid), .d_valid_i(d2x_valid),
.d_is_csr_i (d2x_is_csr), .d_is_csr_i (d2x_is_csr),
.d_is_mret_i (d2x_is_mret), .d_is_mret_i (d2x_is_mret),
.d_is_ebreak_i (d2x_is_ebreak),
.d_csr_imm_i (d2x_csr_imm), .d_csr_imm_i (d2x_csr_imm),
.d_csr_sel_i (d2x_csr_sel), .d_csr_sel_i (d2x_csr_sel),
.d_pc_i(d2x_pc), .d_pc_i(d2x_pc),
...@@ -273,8 +297,9 @@ module urv_cpu ...@@ -273,8 +297,9 @@ module urv_cpu
.d_shifter_sign_i(d2x_shifter_sign), .d_shifter_sign_i(d2x_shifter_sign),
// to F stage (branches) // to F stage (branches)
.f_branch_target_o (x2f_pc_bra), // fixme: consistent naming .f_branch_target_o(x2f_pc_bra), // fixme: consistent naming
.f_branch_take_o (x2f_bra), .f_branch_take_o(x2f_bra),
.f_dbg_toggle_o(x2f_dbg_toggle),
// to X2/W stage // to X2/W stage
.w_fun_o(x2w_fun), .w_fun_o(x2w_fun),
......
...@@ -25,52 +25,53 @@ ...@@ -25,52 +25,53 @@
module urv_decode module urv_decode
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
// pipeline control // pipeline control
input d_stall_i, input d_stall_i,
input d_kill_i, input d_kill_i,
output d_stall_req_o, output d_stall_req_o,
// from Fetch stage // from Fetch stage
input [31:0] f_ir_i, input [31:0] f_ir_i,
input [31:0] f_pc_i, input [31:0] f_pc_i,
input f_valid_i, input f_valid_i,
// to Register File (not registered: direct from fetch stage). // to Register File (not registered: direct from fetch stage).
output [4:0] rf_rs1_o, output [4:0] rf_rs1_o,
output [4:0] rf_rs2_o, output [4:0] rf_rs2_o,
// to Execute 1 stage // to Execute 1 stage
output x_valid_o, output x_valid_o,
output reg [31:0] x_pc_o, output reg [31:0] x_pc_o,
output [4:0] x_rs1_o, output [4:0] x_rs1_o,
output [4:0] x_rs2_o, output [4:0] x_rs2_o,
output [4:0] x_rd_o, output [4:0] x_rd_o,
output reg [4:0] x_shamt_o, output reg [4:0] x_shamt_o,
output reg [2:0] x_fun_o, output reg [2:0] x_fun_o,
output [4:0] x_opcode_o, output [4:0] x_opcode_o,
output reg x_shifter_sign_o, output reg x_shifter_sign_o,
output reg x_is_signed_compare_o, output reg x_is_signed_compare_o,
output reg x_is_signed_alu_op_o, output reg x_is_signed_alu_op_o,
output reg x_is_add_o, output reg x_is_add_o,
output x_is_shift_o, output x_is_shift_o,
output reg x_is_load_o, output reg x_is_load_o,
output reg x_is_store_o, output reg x_is_store_o,
output reg x_is_undef_o, output reg x_is_undef_o,
output reg [2:0] x_rd_source_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 [11:0] x_csr_sel_o,
output reg [4:0] x_csr_imm_o, output reg [4:0] x_csr_imm_o,
output reg x_is_csr_o, output reg x_is_csr_o,
output reg x_is_mret_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_imm_o,
output reg [31:0] x_alu_op1_o, output reg [31:0] x_alu_op1_o,
output reg [31:0] x_alu_op2_o, output reg [31:0] x_alu_op2_o,
output reg x_use_op1_o, output reg x_use_op1_o,
output reg x_use_op2_o output reg x_use_op2_o
); );
wire [4:0] f_rs1 = f_ir_i[19:15]; wire [4:0] f_rs1 = f_ir_i[19:15];
...@@ -142,7 +143,7 @@ module urv_decode ...@@ -142,7 +143,7 @@ module urv_decode
assign x_valid_o = x_valid; assign x_valid_o = x_valid;
always@(posedge clk_i) always@(posedge clk_i)
if(rst_i || d_kill_i ) if(rst_i || d_kill_i)
begin begin
x_pc_o <= 0; x_pc_o <= 0;
x_valid <= 0; x_valid <= 0;
...@@ -179,7 +180,7 @@ module urv_decode ...@@ -179,7 +180,7 @@ module urv_decode
if(!d_stall_i) if(!d_stall_i)
x_shifter_sign_o <= f_ir_i[30]; 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_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_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 }; 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 ...@@ -322,6 +323,7 @@ module urv_decode
x_csr_sel_o <= f_ir_i[31:20]; x_csr_sel_o <= f_ir_i[31:20];
x_is_csr_o <= (d_opcode == `OPC_SYSTEM) && (d_fun != 0); 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_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 end
assign x_is_shift_o = x_is_shift; assign x_is_shift_o = x_is_shift;
......
...@@ -49,6 +49,7 @@ module urv_exec ...@@ -49,6 +49,7 @@ module urv_exec
input d_is_csr_i, input d_is_csr_i,
input d_is_mret_i, input d_is_mret_i,
input d_is_ebreak_i,
input [4:0] d_csr_imm_i, input [4:0] d_csr_imm_i,
input [11:0] d_csr_sel_i, input [11:0] d_csr_sel_i,
...@@ -74,6 +75,7 @@ module urv_exec ...@@ -74,6 +75,7 @@ module urv_exec
output reg [31:0] f_branch_target_o, output reg [31:0] f_branch_target_o,
output f_branch_take_o, output f_branch_take_o,
output reg f_dbg_toggle_o,
input irq_i, input irq_i,
...@@ -452,7 +454,8 @@ module urv_exec ...@@ -452,7 +454,8 @@ module urv_exec
if (rst_i) if (rst_i)
begin begin
f_branch_take <= 0; f_branch_take <= 0;
w_load_o <= 0; f_dbg_toggle_o <= 0;
w_load_o <= 0;
w_store_o <= 0; w_store_o <= 0;
w_valid_o <= 0; w_valid_o <= 0;
...@@ -461,7 +464,8 @@ module urv_exec ...@@ -461,7 +464,8 @@ module urv_exec
begin begin
f_branch_target_o <= branch_target; f_branch_target_o <= branch_target;
f_branch_take <= branch_take && !x_kill_i && d_valid_i; 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_value_o <= rd_value;
w_rd_write_o <= d_rd_write_i && !x_kill_i && d_valid_i && !x_exception; w_rd_write_o <= d_rd_write_i && !x_kill_i && d_valid_i && !x_exception;
......
...@@ -40,7 +40,14 @@ module urv_fetch ...@@ -40,7 +40,14 @@ module urv_fetch
// Branch control // Branch control
input [31:0] x_pc_bra_i, 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; reg [31:0] pc;
...@@ -48,6 +55,8 @@ module urv_fetch ...@@ -48,6 +55,8 @@ module urv_fetch
reg [31:0] pc_next; reg [31:0] pc_next;
reg [31:0] pc_plus_4; reg [31:0] pc_plus_4;
reg dbg_mode;
reg [2:0] pipeline_cnt;
always@* always@*
if( x_bra_i ) if( x_bra_i )
...@@ -60,6 +69,8 @@ module urv_fetch ...@@ -60,6 +69,8 @@ module urv_fetch
// Start fetching the next instruction // Start fetching the next instruction
assign im_addr_o = pc_next; assign im_addr_o = pc_next;
assign dbg_enabled_o = dbg_mode;
always@(posedge clk_i) always@(posedge clk_i)
if (rst_i) if (rst_i)
begin begin
...@@ -70,6 +81,12 @@ module urv_fetch ...@@ -70,6 +81,12 @@ module urv_fetch
f_ir_o <= 0; f_ir_o <= 0;
f_valid_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 // The instruction won't be valid on the next cycle, as the
// instruction memory is registered. // instruction memory is registered.
rst_d <= 0; rst_d <= 0;
...@@ -82,7 +99,40 @@ module urv_fetch ...@@ -82,7 +99,40 @@ module urv_fetch
begin begin
f_pc_o <= pc; 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 begin
pc_plus_4 <= (x_bra_i ? x_pc_bra_i : pc_plus_4) + 4; pc_plus_4 <= (x_bra_i ? x_pc_bra_i : pc_plus_4) + 4;
f_ir_o <= im_data_i; f_ir_o <= im_data_i;
......
...@@ -137,7 +137,13 @@ module main; ...@@ -137,7 +137,13 @@ module main;
.dm_load_o(), .dm_load_o(),
.dm_store_done_i(1'b1), .dm_store_done_i(1'b1),
.dm_load_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; always #5ns clk <= ~clk;
......
This diff is collapsed.
...@@ -117,7 +117,13 @@ module main; ...@@ -117,7 +117,13 @@ module main;
.dm_load_o(), .dm_load_o(),
.dm_store_done_i(1'b1), .dm_store_done_i(1'b1),
.dm_load_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