Initial Debug Module commit

This commit is contained in:
Zavier 2018-07-16 13:29:54 -07:00
parent 0002d36eac
commit d54a684966
6 changed files with 1109 additions and 0 deletions

View file

@ -0,0 +1,171 @@
package debug_cfg_types;
parameter DTMCS_USER_REG = 3;
parameter DMI_USER_REG = 4;
parameter HARTSELLEN = 9; //hartselo + hartselhi
parameter NUM_CPUS = 4;
//parameter integer ASYNC_CPU [NUM_CPUS-1 : 0] = {1,1,1,0};
typedef struct packed{
logic [31:29] zero1;
logic [28:24] progsize;
logic [23:13] zero2;
logic busy;
logic zero3;
logic[10:8] cmderr;
logic [7:4] zero4;
logic [3:0] datacount;
} abstract_control_and_status_t;
typedef struct packed{
logic [13:0] zero1;
logic dmihardreset;
logic dmireset;
logic zero2;
logic [2:0] idle;
logic [1:0] dmistat;
logic [5:0] abits;
logic [3:0] version;
} dtmcs_t;
typedef struct packed{
logic [6:0] address;
logic [31:0] data;
logic [1:0] op;
} dmi_t;
typedef struct packed{
logic [7:0] cmdtype;
logic zero1;
logic [2:0] size;
logic zero2;
logic postexec;
logic transfer;
logic write;
logic [15:0] regno;
} abstract_command_t;
//Address map
typedef enum bit [6:0] {
ABSTRACT_DATA0 = 7'h04,
ABSTRACT_DATA1 = 7'h05,
ABSTRACT_DATA2 = 7'h06,
DEBUG_MODULE_CONTROL = 7'h10,
DEBUG_MODULE_STATUS = 7'h11,
HART_INFO = 7'h12,
HALT_SUMMARY = 7'h13,
HART_ARRAY_WINDOW_SELECT = 7'h14,
HART_ARRAY_WINDOW = 7'h15,
ABSTRACT_CONTROL_AND_STATUS = 7'h16,
ABSTRACT_COMMAND = 7'h17,
ABSTRACT_COMMAND_AUTOEXEC = 7'h18,
CONFIG_STRING_ADDR0 = 7'h19,
CONFIG_STRING_ADDR1 = 7'h1a,
CONFIG_STRING_ADDR2 = 7'h1b,
CONFIG_STRING_ADDR3 = 7'h1c,
PROGRAM_BUFFER0 = 7'h20,
PROGRAM_BUFFER1 = 7'h21,
PROGRAM_BUFFER2 = 7'h22,
PROGRAM_BUFFER3 = 7'h23,
PROGRAM_BUFFER4 = 7'h24,
PROGRAM_BUFFER5 = 7'h25,
PROGRAM_BUFFER6 = 7'h26,
PROGRAM_BUFFER7 = 7'h27,
PROGRAM_BUFFER8 = 7'h28,
PROGRAM_BUFFER9 = 7'h29,
PROGRAM_BUFFER10 = 7'h2a,
PROGRAM_BUFFER11 = 7'h2b,
PROGRAM_BUFFER12 = 7'h2c,
PROGRAM_BUFFER13 = 7'h2d,
PROGRAM_BUFFER14 = 7'h2e,
PROGRAM_BUFFER15 = 7'h2f
//auth, serial, system bus unused
} dm_addr_map_t;
typedef enum bit [15:0] {
DEBUG_CSR = 16'h7b0,
DEBUG_PC = 16'h7b1,
DEBUG_SCRATCH1 = 16'h7b2,
DEBUG_SCRATCH2 = 16'h7b3
} riscv_debug_addr_map_t;
typedef enum bit [1:0] {
DMI_OP_NOP = 2'b00,
DMI_OP_READ = 2'b01,
DMI_OP_WRITE = 2'b10,
DMI_OP_RESERVED = 2'b11
} dmi_jtag_op_t;
typedef enum bit [1:0] {
DMI_STATUS_SUCCESS = 2'b00,
DMI_STATUS_RESERVED = 2'b01,
DMI_STATUS_FAILED = 2'b10,
DMI_STATUS_BUSY = 2'b11
} dmi_response_op_t;
//Read only status register
typedef struct packed{
logic[31:23] zero1;
logic impebreak;
logic[21:20] zero2;
logic allhavereset;
logic anyhavereset;
logic allresumeack;
logic anyresumeack;
logic allnonexistent;
logic anynonexistent;
logic allunavail;
logic anyunavail;
logic allrunning;
logic anyrunning;
logic allhalted;
logic anyhalted;
logic authenticated;
logic authbusy;
logic zero3;//5
logic cfgstrvalid;
logic [3:0] version;
} DM_Status_t;
//read-write register
typedef struct packed{
logic haltreq;
logic resumereq;
logic hartreset;
logic ackhavereset;
logic zero1;
logic hasel;
logic [25:16] hartsello;
logic [15:6] hartselhi;
logic [5:2] zero2;
logic ndmreset;
logic dmactive;
} DM_control_t;
typedef struct packed{
logic [31:24] zero1;
logic [23:20] nscratch;
logic [19:17] zero2;
logic dataaccess;
logic [15:12] datasize;
logic [11:0] dataaddr;
} hart_info_t;
typedef struct packed {
logic [6:0] address;
logic [31:0] jtag_data;
logic [31:0] dmi_data;
logic new_request;
logic rnw;
logic handled;
logic [1:0] response;
}dmi_interface_t;
typedef struct packed{
logic [6:0] address;
logic [31:0] jtag_data;
logic new_request;
logic rnw;
} jtag_commands_t;
endpackage

View file

@ -0,0 +1,45 @@
interface dmi_interface;
logic [6:0] address;
logic [31:0] jtag_data;
logic [31:0] dmi_data;
logic new_request;
logic rnw;
logic handled;
logic [1:0] response;
modport jtag (
input handled, response, dmi_data,
output address, jtag_data, new_request, rnw);
modport dmi (
output handled, response, dmi_data,
input address, jtag_data, new_request, rnw);
endinterface
interface dmi_cpu_interface;
logic halt;
logic resume;
logic reset;
logic halt_ack;
logic resume_ack;
logic reset_ack;
logic halt_ack_recv;
logic resume_ack_recv;
logic running;
logic [31:0] read_data;
logic [31:0] write_data;
logic [31:0] read_write_addr;
logic [3:0] program_buffer_addr;
logic [31:0] program_buffer_data;
logic rnw;
logic rnw_ack;
logic rnw_new_request;
modport dmi (
input halt_ack, resume_ack,program_buffer_addr, reset_ack,running,halt_ack_recv,resume_ack_recv,read_data,rnw_ack,
output halt, resume,program_buffer_data,reset,write_data,rnw_new_request,rnw,read_write_addr);
modport cpu (
output halt_ack, resume_ack,program_buffer_addr, reset_ack,running,halt_ack_recv,resume_ack_recv,read_data,rnw_ack,
input halt, resume, program_buffer_data,reset,write_data,rnw_new_request,rnw,read_write_addr);
endinterface

View file

@ -0,0 +1,627 @@
import debug_cfg_types::*;
module debug_module (
input logic rst,
input logic clk,
dmi_cpu_interface.dmi debug[NUM_CPUS-1:0],
dmi_interface.dmi jtag,
//SIMULATION ONLY:
output DM_Status_t DMS_out,
output DM_control_t DMC_out,
output abstract_control_and_status_t ACS_out
);
genvar index;
DM_Status_t DMS;
assign DMS.zero1 = 0;
assign DMS.zero2 = 0;
assign DMS.zero3 = 0;
assign DMS.cfgstrvalid = 0;
assign DMS.impebreak = 0;
//DMS Constants
assign DMS.authenticated = 1;//no authentication
assign DMS.authbusy = 0;
assign DMS.version = 2; //version 0.13
assign DMS_out = DMS;
DM_control_t DMC;
//assign DMC.zero1 = 0;
//assign DMC.zero2 = 0;
//read-only reg
//same for all Taiga cores
hart_info_t hart_info;
assign hart_info.zero1 = 0;
assign hart_info.zero2 = 0;
assign hart_info.nscratch = 2;
assign hart_info.dataaccess = 0;
assign hart_info.datasize = 3;
assign hart_info.dataaddr = 0;
assign DMC_out = DMC;
//read-only reg
//Only support < 32 cores
logic [31:0] halt_summary;
assign halt_summary[31:1] = '0;
assign halt_summary[0] = DMS.anyhalted;
//read-write reg
//Only support < 32 cores
logic [31:0] hart_array_window_select;
//assign hart_array_window_select = 0;
//read-write reg
logic [31:0] hart_array_window;
//read-only and read-write reg
abstract_control_and_status_t ABS_CS;
assign ABS_CS.zero1 = 0;
assign ABS_CS.zero2 = 0;
assign ABS_CS.zero3 = 0;
assign ABS_CS.zero4 = 0;
assign ABS_CS.datacount = 2;
assign ABS_CS.progsize = 16;
assign ACS_out = ABS_CS;
//write-only reg
typedef struct packed{
logic [31:24] cmdtype;
logic [23:0] control;
} abstract_command_t;
abstract_command_t ABS_COMMAND;
//abstract command autoexec, unused
//read-only
logic[31:0] cfg_addr0;
//read-write
logic[31:0] abstract_data [2:0];
//LUT-RAM
logic[31:0] program_buffer [7:0];
logic[31:0] program_buffer_output;
logic [31:0] data_out;
logic write_request;
logic new_DMC_req;
//Implementation
//////////////////////////////////////////////////////////////////
assign write_request = jtag.new_request & ~jtag.rnw;
//DMC
always_ff @ (posedge clk) begin
if (rst) begin
DMC.dmactive <= 0;
DMC <= 0;
new_DMC_req <= 0;
end
else begin
DMC.dmactive <= 1;
if (write_request) begin
if (jtag.address == DEBUG_MODULE_CONTROL) begin
DMC <= jtag.jtag_data;
new_DMC_req <= 1;
end
end
else begin
new_DMC_req <= 0;
end
end;
end
//Write to registers
//////////////////
//HART_ARRAY_WINDOW_SELECT
always_ff @ (posedge clk) begin
if (rst)
hart_array_window_select <= 0;
else
if(write_request & jtag.address == HART_ARRAY_WINDOW_SELECT)
hart_array_window_select <= jtag.jtag_data;
end
//HART_ARRAY_WINDOW
always_ff @ (posedge clk) begin
if (rst)
hart_array_window <= 0;
else
if(write_request & jtag.address == HART_ARRAY_WINDOW)
hart_array_window <= jtag.jtag_data;
end
//Selected Harts (hasel,hartsel)-----------------------------------------
logic[31:0] hartsel_mask;
logic[HARTSELLEN:0] selected_hart;
assign selected_hart = {DMC.hartselhi,DMC.hartsello}; //Index-based
generate
//for (index = 0; index < NUM_CPUS; index=index+1) begin
for (index = 0; index < 32; index=index+1) begin
always_comb begin
if(selected_hart == index)
hartsel_mask[index] <= 1; //convert index to mask
else
hartsel_mask[index] <= 0;
end
end
endgenerate
logic[31:0] selected_harts;
always_comb begin
if(~DMC.hasel)
selected_harts <= hartsel_mask;
else
selected_harts <= hartsel_mask | hart_array_window;
end
//ABS_COMMAND
always_ff @ (posedge clk) begin
if (rst)
ABS_COMMAND <= 0;
else
if(write_request & jtag.address == ABSTRACT_COMMAND)
ABS_COMMAND <= jtag.jtag_data;
end
//ABS_DATA0------------return data for abstract commands
logic[31:0][NUM_CPUS-1:0] abs_cmd_return;
logic[NUM_CPUS-1:0] abs_cmd_sig;
generate
for (index = 0; index < NUM_CPUS; index=index+1) begin
always_ff @(posedge clk) begin
if (rst) begin
abs_cmd_return[index] <= 0;
abs_cmd_sig[index] <= 0;
end
else begin
if(debug[index].rnw_ack && debug[index].rnw) begin
abs_cmd_return[index] <= debug[index].read_data;
abs_cmd_sig[index] <= 1;
end
else begin
abs_cmd_return[index] <= 0;
abs_cmd_sig[index] <= 0;
end
end
end
end
endgenerate
always_ff @ (posedge clk) begin
if (rst)
abstract_data[0] <= 0;
else
if(write_request & jtag.address == ABSTRACT_DATA0)
abstract_data[0] <= jtag.jtag_data;
else if(|abs_cmd_sig)
abstract_data[0] <= abs_cmd_return[selected_hart]; //PROBLEM: THIS NEEDS TO BE OBTAINED FROM THE CORRECT PROCESSOR
end
//ABS_DATA1
always_ff @ (posedge clk) begin
if (rst)
abstract_data[1] <= 0;
else
if(write_request & jtag.address == ABSTRACT_DATA1)
abstract_data[1] <= jtag.jtag_data;
end
//ABS_DATA2
always_ff @ (posedge clk) begin
if (rst)
abstract_data[2] <= 0;
else
if(write_request & jtag.address == ABSTRACT_DATA2)
abstract_data[2] <= jtag.jtag_data;
end
//////////////////
//program_buffer
always_ff @ (posedge clk) begin
if (write_request && jtag.address >= 7'h20 && jtag.address < 7'h30)
program_buffer[jtag.address[3:0]] <= jtag.jtag_data;
end
assign program_buffer_output = program_buffer[jtag.address[3:0]];
//read mux
always_comb begin
case(jtag.address)
ABSTRACT_DATA0 : data_out <= abstract_data[0];
ABSTRACT_DATA1 : data_out <= abstract_data[1];
ABSTRACT_DATA2 : data_out <= abstract_data[2];
DEBUG_MODULE_CONTROL : data_out <= DMC;
DEBUG_MODULE_STATUS : data_out <= DMS;
HART_INFO : data_out <= hart_info;
HALT_SUMMARY : data_out <= halt_summary;
HART_ARRAY_WINDOW_SELECT : data_out <= hart_array_window_select;
HART_ARRAY_WINDOW : data_out <= hart_array_window;
ABSTRACT_CONTROL_AND_STATUS : data_out <= ABS_CS;
ABSTRACT_COMMAND : data_out <= ABS_COMMAND;
ABSTRACT_COMMAND_AUTOEXEC : data_out <= '0;
CONFIG_STRING_ADDR0 : data_out <= '0;
CONFIG_STRING_ADDR1 : data_out <= '0;
CONFIG_STRING_ADDR2 : data_out <= '0;
CONFIG_STRING_ADDR3 : data_out <= '0;
PROGRAM_BUFFER0 : data_out <= program_buffer_output;
PROGRAM_BUFFER1 : data_out <= program_buffer_output;
PROGRAM_BUFFER2 : data_out <= program_buffer_output;
PROGRAM_BUFFER3 : data_out <= program_buffer_output;
PROGRAM_BUFFER4 : data_out <= program_buffer_output;
PROGRAM_BUFFER5 : data_out <= program_buffer_output;
PROGRAM_BUFFER6 : data_out <= program_buffer_output;
PROGRAM_BUFFER7 : data_out <= program_buffer_output;
PROGRAM_BUFFER8 : data_out <= program_buffer_output;
PROGRAM_BUFFER9 : data_out <= program_buffer_output;
PROGRAM_BUFFER10 : data_out <= program_buffer_output;
PROGRAM_BUFFER11 : data_out <= program_buffer_output;
PROGRAM_BUFFER12 : data_out <= program_buffer_output;
PROGRAM_BUFFER13 : data_out <= program_buffer_output;
PROGRAM_BUFFER14 : data_out <= program_buffer_output;
PROGRAM_BUFFER15 : data_out <= program_buffer_output;
default : data_out <= '0;
endcase
end
always_ff @ (posedge clk) begin
jtag.handled <= jtag.new_request;
end
assign jtag.response = DMI_STATUS_SUCCESS;
always_ff @ (posedge clk) begin
jtag.dmi_data <= data_out;
end
//Are Cores Running Check-------------------------------------------------------------------------
logic [NUM_CPUS-1:0] all_running_array;
generate
for (index = 0; index < NUM_CPUS; index=index+1) begin
always_comb begin
all_running_array[index] <= debug[index].running;
end
end
endgenerate
always_ff @ (posedge clk) begin
if (rst) begin
DMS.allrunning <= 0;
DMS.anyrunning <= 0;
end
else
DMS.allrunning <= &(all_running_array | ~selected_harts) && |selected_harts;
DMS.anyrunning <= |(all_running_array & selected_harts);
end
//Hart Resets Requests-------------------------------------------------------------------------
//Requests & Acknowledgements-----------------
generate
for (index = 0; index < NUM_CPUS; index=index+1) begin
always_ff @(posedge clk) begin
if (rst)
debug[index].reset <= 0;
else begin
if(DMC.hartreset && new_DMC_req) begin //Send New Requests
debug[index].reset <= selected_harts[index];
end
else if(debug[index].reset_ack == 1 || DMC.hartreset == 0) begin //Wait for Ack OR Debugger has unset the reset bit
debug[index].reset <= 0;
end
end
end
end
endgenerate
//Status Register Updates-----------------
always_ff @ (posedge clk) begin
if (rst) begin
DMS.allhavereset <= 0;
DMS.anyhavereset <= 0;
end
else
if(DMC.hartreset) begin
DMS.allhavereset <= 1;
DMS.anyhavereset <= 1;
end
else if(DMC.ackhavereset)begin //clear only if Debugger has acknowledge the reset
DMS.allhavereset <= 0;
DMS.anyhavereset <= 0;
end
end
//Halt RequestsRequests-------------------------------------------------------------------------
//Requests & Acknowledgements-----------------
generate
for (index = 0; index < NUM_CPUS; index=index+1) begin
always_ff @(posedge clk) begin
if (rst)
debug[index].halt <= 0;
else begin
if(DMC.haltreq && new_DMC_req) begin //Send New Requests
debug[index].halt <= selected_harts[index];
end
else if(ABS_COMMAND.cmdtype == 1 && debug[index].running) //From Abstract Command
debug[index].halt <= hartsel_mask[index];
else if(debug[index].halt_ack == 1) begin //Wait for Ack
debug[index].halt <= 0;
end
end
end
end
endgenerate
//Status Register Updates--------------------
always_ff @ (posedge clk) begin
if (rst) begin
DMS.allhalted <= 0;
DMS.anyhalted <= 0;
end
else
DMS.allhalted <= &(~all_running_array | ~selected_harts) && |selected_harts;
DMS.anyhalted <= |(~all_running_array & selected_harts);
end
//Resume Requests-------------------------------------------------------------------------
//Requests & Acknowledgements-----------------
generate
for (index = 0; index < NUM_CPUS; index=index+1) begin
always_ff @(posedge clk) begin
if (rst)
debug[index].resume <= 0;
else begin
if(DMC.resumereq && new_DMC_req && ~DMC.haltreq) begin //Send New Requests
debug[index].resume <= selected_harts[index];
end
else if(debug[index].resume_ack == 1) begin //Wait for Ack
debug[index].resume <= 0;
end
end
end
end
endgenerate
//Status Register Updates--------------------NOTE: This checks for the ACKS not the current status
logic [NUM_CPUS-1:0] all_resume_ack_array;
generate
for (index = 0; index < NUM_CPUS; index=index+1) begin
always_comb begin
if(DMC.resumereq && selected_harts[index] && ~DMC.haltreq && new_DMC_req) //if a new request is sent, reset the bit
all_resume_ack_array[index] <= 0;
if(debug[index].resume_ack) //only set bit if the ack has been recieved
all_resume_ack_array[index] <= 1;
end
end
endgenerate
always_ff @ (posedge clk) begin
if (rst) begin
DMS.allresumeack <= 0;
DMS.anyresumeack <= 0;
end
else
if(DMC.resumereq) begin
DMS.allresumeack <= &(all_resume_ack_array|~selected_harts) && |selected_harts;
DMS.anyresumeack <= |(all_resume_ack_array & selected_harts);
end
else begin // Do I need to set this to 0?
DMS.allresumeack <= 0;
DMS.anyresumeack <= 0;
end
end
//ALL/ANY nonexistent,allunavailallunavail------------
logic [31:0] non_exist_array;
generate
for (index = 0; index < 32; index=index+1) begin
always_comb begin
if(index > NUM_CPUS)
non_exist_array[index] <= 1;
else
non_exist_array[index] <= 0;
end
end
endgenerate
always_ff @ (posedge clk) begin
if (rst) begin
DMS.allnonexistent <= 0;
DMS.anynonexistent <= 0;
DMS.allunavail <= 0;
DMS.anyunavail <= 0;
end
else begin
DMS.allnonexistent <= &(non_exist_array|~selected_harts) && |selected_harts;
DMS.anynonexistent <= |(non_exist_array & selected_harts);
//DMS.allunavail <= &(non_exist_array|~selected_harts) && |selected_harts;
//DMS.anyunavail <= |(non_exist_array & selected_harts);
end
end
//Abtract Commands----------------------------------------------------------------
//TO-DO: DID WE IMPLEMENT POSTEXEC
logic new_ABSTRACT_req;
always_ff @ (posedge clk) begin
if (rst) begin
new_ABSTRACT_req <= 0;
end
else begin
if (write_request && jtag.address == ABSTRACT_COMMAND) begin
new_ABSTRACT_req <= 1;
end
else begin
new_ABSTRACT_req <= 0;
end
end
end
logic [NUM_CPUS-1:0] abstract_ack_array;
generate
for (index = 0; index < NUM_CPUS; index=index+1) begin
always_comb begin
if(new_ABSTRACT_req && hartsel_mask[index]) //if a new request is sent, reset the bit
abstract_ack_array[index] <= 0;
if(debug[index].rnw_ack) //only set bit if the ack has been recieved
abstract_ack_array[index] <= 1;
end
end
endgenerate
//Requests-----------------
logic[31:0][NUM_CPUS-1:0] program_buffer_addr;
logic execute_program_buffer;
logic [NUM_CPUS-1:0]execute_program_buffer_postexec;
logic [NUM_CPUS-1:0]execute_program_buffer_auto;
logic [NUM_CPUS-1:0]new_execute_program_buffer_req;
assign execute_program_buffer = |execute_program_buffer_postexec | |execute_program_buffer_auto; //note do we need a hartsel_mask here?
generate
for (index = 0; index < NUM_CPUS; index=index+1) begin
always_comb begin
program_buffer_addr[index] <= debug[index].program_buffer_addr;
end
end
endgenerate
logic halted_hartsel;
assign halted_hartsel = |(hartsel_mask && ~all_running_array);
always_ff @ (posedge clk) begin
if (rst) begin
ABS_CS.busy <= 0;
ABS_CS.cmderr <= 0;
end
else begin
if(ABS_COMMAND.cmdtype == 0 && ABS_COMMAND[22:20] != 2 && new_ABSTRACT_req) begin //If the size of the command is > 32
ABS_CS.busy <= 0;
ABS_CS.cmderr <= 2;
end
else if(ABS_COMMAND.cmdtype == 0 && (ABS_COMMAND[15:0] != DEBUG_CSR && ABS_COMMAND[15:0] != DEBUG_PC && ABS_COMMAND[15:0] != DEBUG_SCRATCH1 && ABS_COMMAND[15:0] != DEBUG_SCRATCH2) && new_ABSTRACT_req) begin //Address not readable
ABS_CS.busy <= 0;
ABS_CS.cmderr <= 2;
end
else if(ABS_COMMAND.cmdtype == 1 && halted_hartsel) begin //If quick access is the abstract command, but the core is already halted
ABS_CS.busy <= 0;
ABS_CS.cmderr <= 2;
end
else if(ABS_COMMAND.cmdtype == 0 && ABS_COMMAND[17] && ~ABS_COMMAND[16] && new_ABSTRACT_req) begin //Transfer
ABS_CS.busy <= 1;
ABS_CS.cmderr <= 0;
end
else if(ABS_COMMAND.cmdtype == 0 && ABS_COMMAND[17] && ABS_COMMAND[16] && new_ABSTRACT_req) begin //Write
ABS_CS.busy <= 1;
ABS_CS.cmderr <= 0;
end
else if(ABS_COMMAND.cmdtype == 1 && ABS_COMMAND[17] && ABS_COMMAND[16] && new_ABSTRACT_req) begin //Write
ABS_CS.busy <= 1;
ABS_CS.cmderr <= 0;
end
else if(|abstract_ack_array && ~ABS_COMMAND[18]) begin //CASE 1: no execution of program buffer
ABS_CS.busy <= 0;
ABS_CS.cmderr <= 0;
end
else if(|abstract_ack_array && ABS_COMMAND[18] && program_buffer_addr[selected_hart] == 31'h2F) begin //CASE 2: execution of program buffer. WE have finished the Program Buffer
ABS_CS.busy <= 0;
ABS_CS.cmderr <= 0;
end
end
end
generate
for (index = 0; index < NUM_CPUS; index=index+1) begin
always_ff @ (posedge clk) begin
if (rst) begin
debug[index].rnw <= 0;
debug[index].rnw_new_request <= 0;
execute_program_buffer_postexec[index] <= 0;
execute_program_buffer_auto [index] <= 0;
debug[index].write_data <= 0;
debug[index].read_write_addr <= 0;
end
else begin
execute_program_buffer_postexec[index] <= 0; //Only 1 when rnw_ack has been recieved for the first time and postexec is true
if(execute_program_buffer) begin //happens in the next cycle after directly above code
debug[index].write_data <= 31'h20; //write data always comes from data0 register for 32-bits
debug[index].read_write_addr <= 16'h7b1;
debug[index].rnw <= 0;
debug[index].rnw_new_request <= hartsel_mask[index];
new_execute_program_buffer_req[index] <= 0;
end
else if(ABS_COMMAND.cmdtype == 0 && ABS_COMMAND[17] && ~ABS_COMMAND[16] && new_ABSTRACT_req) begin //Read/Transfer
debug[index].rnw <= 1;
debug[index].rnw_new_request <= hartsel_mask[index]; //WE HAVE TO USE ONLY THE HARTSEL MASK AND NOT THE ARRAY MASK
debug[index].write_data <= abstract_data[0]; //write data always comes from data0 register for 32-bits
debug[index].read_write_addr <= ABS_COMMAND[15:0];
if(ABS_COMMAND[18])
new_execute_program_buffer_req[index] <= 1;
end
else if(ABS_COMMAND.cmdtype == 0 && ABS_COMMAND[17] && ABS_COMMAND[16] && new_ABSTRACT_req) begin //Write
debug[index].rnw <= 0;
debug[index].rnw_new_request <= hartsel_mask[index]; //WE HAVE TO USE ONLY THE HARTSEL MASK AND NOT THE ARRAY MASK
debug[index].write_data <= abstract_data[0]; //write data always comes from data0 register for 32-bits
debug[index].read_write_addr <= ABS_COMMAND[15:0];
if(ABS_COMMAND[18])
new_execute_program_buffer_req[index] <= 1;
end
else if(debug[index].rnw_ack) begin
debug[index].rnw_new_request <= 0;
if(ABS_COMMAND[18]) begin //postexec
if(execute_program_buffer_postexec[index] == 0 && execute_program_buffer_auto [index]== 0 && new_execute_program_buffer_req[index]) begin
execute_program_buffer_postexec[index] <= 1; // activation signal
new_execute_program_buffer_req[index] <= 0;
//execute_program_buffer <= 1; //CANT DO THIS SINCE IT'S A FOR LOOP
end
else begin
//execute_program_buffer <= 1; //CAN'T DO THIS SINCE IT'S A FOR LOOP
execute_program_buffer_postexec[index]<= 0; //program bufer execution started
end
end
else if(ABS_COMMAND.cmdtype == 1) begin //Quick access
execute_program_buffer_auto[index]<= 0; //program bufer execution started //ERROR ITS IN A FOR LOOP
//execute_program_buffer <= 1;
end
end
else if(ABS_COMMAND.cmdtype == 1 && ~debug[index].running && new_ABSTRACT_req) begin
execute_program_buffer_auto[index] <= 1;
end
end
end
end
endgenerate
//Program Buffer - Processor Interface
generate
for (index = 0; index < NUM_CPUS; index=index+1) begin
always_ff @ (posedge clk) begin
if (rst) begin
debug[index].program_buffer_data <= 0;
end
else begin
case(debug[index].program_buffer_addr)
31'h20 : debug[index].program_buffer_data <= PROGRAM_BUFFER0;
31'h21 : debug[index].program_buffer_data <= PROGRAM_BUFFER1;
31'h22 : debug[index].program_buffer_data <= PROGRAM_BUFFER2;
31'h23 : debug[index].program_buffer_data <= PROGRAM_BUFFER3;
31'h24 : debug[index].program_buffer_data <= PROGRAM_BUFFER4;
31'h25 : debug[index].program_buffer_data <= PROGRAM_BUFFER5;
31'h26 : debug[index].program_buffer_data <= PROGRAM_BUFFER6;
31'h27 : debug[index].program_buffer_data <= PROGRAM_BUFFER7;
31'h28 : debug[index].program_buffer_data <= PROGRAM_BUFFER8;
31'h29 : debug[index].program_buffer_data <= PROGRAM_BUFFER9;
31'h2A : debug[index].program_buffer_data <= PROGRAM_BUFFER10;
31'h2B : debug[index].program_buffer_data <= PROGRAM_BUFFER11;
31'h2C : debug[index].program_buffer_data <= PROGRAM_BUFFER12;
31'h2D : debug[index].program_buffer_data <= PROGRAM_BUFFER13;
31'h2E : debug[index].program_buffer_data <= PROGRAM_BUFFER14;
31'h2F : debug[index].program_buffer_data <= PROGRAM_BUFFER15;
default : debug[index].program_buffer_data <= 0;
endcase
end
end
end
endgenerate
endmodule

125
debug_module/jtag_module.sv Normal file
View file

@ -0,0 +1,125 @@
import debug_cfg_types::*;
module jtag_module (
input logic clk,
output logic reset,
dmi_interface.jtag dm
);
dtmcs_t dtmcs, dtmcs_jtag;
dmi_t dmi, dmi_jtag;
logic dtmcs_write;
logic dmi_write;
logic dmi_busy;
logic dmi_error;
jtag_registers jtag_regs(
.clk(clk),
.reset(reset),
.current_dtmcs(dtmcs),
.updated_dtmcs(dtmcs_jtag),
.update_dtmcs(dtmcs_write),
.current_dmi(dmi),
.updated_dmi(dmi_jtag),
.update_dmi(dmi_write)
);
//dtmcs register
assign dtmcs.zero1 = 0;
assign dtmcs.dmihardreset = 0;
assign dtmcs.dmireset = 0;
assign dtmcs.zero2 = 0;
assign dtmcs.idle = 20;
//dmistat
assign dtmcs.abits = 7;
assign dtmcs.version = 1;
always_ff @ (posedge clk) begin
if (reset)
dtmcs.dmistat <= DMI_STATUS_SUCCESS;
else if (dtmcs_write & (dtmcs_jtag.dmireset | dtmcs_jtag.dmihardreset)) //clear error status
dtmcs.dmistat <= DMI_STATUS_SUCCESS;
else if (dmi_write & dmi_busy)
dtmcs.dmistat <= DMI_STATUS_BUSY;
else if (dm.handled & ~dmi_error)
dtmcs.dmistat <= dm.response;
end
////////////////////////////////////////
always_ff @ (posedge clk) begin
if (reset)
dmi_busy <= 0;
else if (dtmcs_write & (dtmcs_jtag.dmireset | dtmcs_jtag.dmihardreset))
dmi_busy <= 0;
else if (dmi_write & ~dmi_busy)
dmi_busy <= 1;
else if (dm.handled)
dmi_busy <= 0;
end
always_ff @ (posedge clk) begin
if (reset)
dmi_error <= 0;
else if (dtmcs_write & (dtmcs_jtag.dmireset | dtmcs_jtag.dmihardreset))
dmi_error <= 0;
else if ((dmi_write & dmi_busy) ||
(dm.handled && dm.response == DMI_STATUS_FAILED))
dmi_error <= 1;
//dmi_error <= 0; //Test
end
//dmi reg
always_ff @ (posedge clk) begin
if (reset)
dmi.address <= 0;
else if (dmi_write & ~(dmi_busy | dmi_error))
dmi.address <= dmi_jtag.address;
end
always_ff @ (posedge clk) begin
if (reset)
dmi.data <= 0;
else if (dmi_write & ~(dmi_busy | dmi_error) && (dmi_jtag.op == DMI_OP_WRITE))
dmi.data <= dmi_jtag.data;
else if (dm.handled)
dmi.data <= dm.dmi_data;
end
always_ff @ (posedge clk) begin
if (reset)
dmi.op <= DMI_STATUS_SUCCESS;
else if (dtmcs_write & (dtmcs_jtag.dmireset | dtmcs_jtag.dmihardreset))
dmi.op <= DMI_STATUS_SUCCESS;
else if (dmi_write & ~(dmi_busy | dmi_error))
dmi.op <= dmi_jtag.op;
else if (dmi_write & dmi_busy & ~dmi_error)
dmi.op <= DMI_STATUS_BUSY;
else if (dm.handled & ~dmi_error)
dmi.op <= dm.response;
end
//Output logic
assign dm.address = dmi.address;
assign dm.jtag_data = dmi.data;
always_ff @ (posedge clk) begin
if (dmi_write & ~(dmi_busy | dmi_error))
dm.rnw <= (dmi_jtag.op == DMI_OP_READ) || (dmi_jtag.op == DMI_OP_NOP);
end
always_ff @ (posedge clk) begin
if (reset)
dm.new_request <= 0;
else if (dmi_write & ~(dmi_busy | dmi_error))
dm.new_request <= (dmi_jtag.op == DMI_OP_READ) || (dmi_jtag.op == DMI_OP_WRITE) || (dmi_jtag.op == DMI_OP_NOP);
else
dm.new_request <= 0;
end
endmodule

View file

@ -0,0 +1,101 @@
module jtag_register
#(
parameter C_WIDTH = 32,
parameter C_ID = 3
)
(
input logic clk,
output logic reset_out,
input logic [C_WIDTH-1:0] data_in,
output logic [C_WIDTH-1:0] data_out,
output logic new_data
);
logic capture, drck_i, tck, drck, reset, sel, shift, tdi, update, tdo;
logic [C_WIDTH-1:0] captured_data;
logic [C_WIDTH-1:0] jtag_data;
logic ack;
localparam SYNC_STAGES = 3;
logic new_data_sync [SYNC_STAGES-1:0];
///////////////////////////////////////////////////////////////////
BUFG drck_bufg (.O(drck), .I(drck_i));
BSCANE2 #( .JTAG_CHAIN(C_ID))
bscan (
.CAPTURE (capture),
.DRCK (drck_i),
.RESET (reset),
.RUNTEST (),
.SEL (sel),
.SHIFT (shift),
.TCK (tck),
.TDI (tdi),
.TMS (),
.UPDATE (update),
.TDO (tdo)
);
assign reset_out = reset;
//X stage Synchronizers for handshaking
always_ff @(posedge update or posedge reset or posedge ack) begin
if (reset | ack)
new_data_sync[0] <= 0;
else begin
if (sel)
new_data_sync[0] <= 1;
end
end
genvar i;
generate
for (i=1; i < SYNC_STAGES; i++) begin
always_ff @(posedge clk or posedge reset) begin
if (reset)
new_data_sync[i] <= 0;
else begin
new_data_sync[i] <= new_data_sync[i-1];
end
end
end
endgenerate
always_ff @(posedge clk or posedge reset) begin
if (reset)
ack <= 0;
else begin
ack <= new_data_sync[SYNC_STAGES-1];
end
end
assign new_data = ack & ~new_data_sync[SYNC_STAGES-1];
//JTAG Data Register logic as per XAPP139
always_ff @(posedge drck or posedge reset) begin
if (reset)
captured_data <= '0;
else begin
if (capture & sel)
captured_data <= data_in;
else if (shift & sel)
captured_data <= {tdi, captured_data[C_WIDTH-1:1]};
end
end
always @(posedge update or posedge reset) begin
if (reset)
jtag_data <= 0;
else begin
if (sel)
jtag_data <= captured_data;
end
end
assign data_out = jtag_data;
assign tdo = captured_data[0];
endmodule

View file

@ -0,0 +1,40 @@
import debug_cfg_types::*;
module jtag_registers (
input logic clk,
output logic reset,
input dtmcs_t current_dtmcs,
output dtmcs_t updated_dtmcs,
output update_dtmcs,
input dmi_t current_dmi,
output dmi_t updated_dmi,
output update_dmi
);
jtag_register
#( .C_WIDTH($bits(dtmcs_t)), .C_ID(DTMCS_USER_REG))
dtmcs_jtag_block
(
.clk (clk),
.reset_out(reset),
.data_in(current_dtmcs),
.data_out(updated_dtmcs),
.new_data(update_dtmcs)
);
jtag_register
#( .C_WIDTH($bits(dmi_t)), .C_ID(DMI_USER_REG))
dmi_jtag_block
(
.clk (clk),
.reset_out(),
.data_in(current_dmi),
.data_out(updated_dmi),
.new_data(update_dmi)
);
endmodule