mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 05:07:21 -04:00
🚧 Remove dm_ctrl and move logic to dm_memory
This commit is contained in:
parent
54bbced94f
commit
04902ce01e
12 changed files with 389 additions and 143 deletions
1
Makefile
1
Makefile
|
@ -193,6 +193,7 @@ verilate:
|
|||
-Werror-IMPLICIT \
|
||||
-Wno-fatal \
|
||||
-Wno-PINCONNECTEMPTY \
|
||||
-Wno-ASSIGNDLY \
|
||||
-Wno-DECLFILENAME \
|
||||
-Wno-UNOPTFLAT \
|
||||
-Wno-UNUSED \
|
||||
|
|
|
@ -44,7 +44,7 @@ module bootrom (
|
|||
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (req_i) begin
|
||||
addr_q = addr_i[$clog2(RomSize)-1+3:3];
|
||||
addr_q <= addr_i[$clog2(RomSize)-1+3:3];
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ module $filename (
|
|||
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (req_i) begin
|
||||
addr_q = addr_i[$$clog2(RomSize)-1+3:3];
|
||||
addr_q <= addr_i[$$clog2(RomSize)-1+3:3];
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -47,9 +47,16 @@ package ariane_pkg;
|
|||
|
||||
// 32 registers + 1 bit for re-naming = 6
|
||||
localparam REG_ADDR_SIZE = 6;
|
||||
|
||||
// static debug hartinfo
|
||||
// for the moment nothing of this is implemented
|
||||
parameter dm::hartinfo_t DebugHartInfo = '{zero1: '0, nscratch: 1, zero0: '0, dataaccess: 1'b1, datasize: '0, dataaddr: '0};
|
||||
parameter dm::hartinfo_t DebugHartInfo = '{
|
||||
zero1: '0,
|
||||
nscratch: 1, // DTM currently needs at least one scratch register
|
||||
zero0: '0,
|
||||
dataaccess: 1'b1, // data registers are memory mapped in the debugger
|
||||
datasize: dm::DataCount,
|
||||
dataaddr: dm::DataAddr
|
||||
};
|
||||
// ---------------
|
||||
// Fetch Stage
|
||||
// ---------------
|
||||
|
@ -300,4 +307,5 @@ package ariane_pkg;
|
|||
function automatic logic [63:0] sb_imm (logic [31:0] instruction_i);
|
||||
return { {51 {instruction_i[31]}}, instruction_i[31], instruction_i[7], instruction_i[30:25], instruction_i[11:8], 1'b0 };
|
||||
endfunction
|
||||
|
||||
endpackage
|
||||
|
|
|
@ -129,24 +129,24 @@ package riscv;
|
|||
// --------------------
|
||||
// Opcodes
|
||||
// --------------------
|
||||
localparam OpcodeSystem = 7'h73;
|
||||
localparam OpcodeFence = 7'h0f;
|
||||
localparam OpcodeOp = 7'h33;
|
||||
localparam OpcodeOp32 = 7'h3B;
|
||||
localparam OpcodeOpimm = 7'h13;
|
||||
localparam OpcodeOpimm32 = 7'h1B;
|
||||
localparam OpcodeStore = 7'h23;
|
||||
localparam OpcodeLoad = 7'h03;
|
||||
localparam OpcodeBranch = 7'h63;
|
||||
localparam OpcodeJalr = 7'h67;
|
||||
localparam OpcodeJal = 7'h6f;
|
||||
localparam OpcodeAuipc = 7'h17;
|
||||
localparam OpcodeLui = 7'h37;
|
||||
localparam OpcodeAmo = 7'h2F;
|
||||
parameter OpcodeSystem = 7'h73;
|
||||
parameter OpcodeFence = 7'h0f;
|
||||
parameter OpcodeOp = 7'h33;
|
||||
parameter OpcodeOp32 = 7'h3B;
|
||||
parameter OpcodeOpimm = 7'h13;
|
||||
parameter OpcodeOpimm32 = 7'h1B;
|
||||
parameter OpcodeStore = 7'h23;
|
||||
parameter OpcodeLoad = 7'h03;
|
||||
parameter OpcodeBranch = 7'h63;
|
||||
parameter OpcodeJalr = 7'h67;
|
||||
parameter OpcodeJal = 7'h6f;
|
||||
parameter OpcodeAuipc = 7'h17;
|
||||
parameter OpcodeLui = 7'h37;
|
||||
parameter OpcodeAmo = 7'h2F;
|
||||
|
||||
localparam OpcodeCJ = 3'b101;
|
||||
localparam OpcodeCBeqz = 3'b110;
|
||||
localparam OpcodeCBnez = 3'b111;
|
||||
parameter OpcodeCJ = 3'b101;
|
||||
parameter OpcodeCBeqz = 3'b110;
|
||||
parameter OpcodeCBnez = 3'b111;
|
||||
|
||||
// -----
|
||||
// CSRs
|
||||
|
@ -238,4 +238,28 @@ package riscv;
|
|||
csr_addr_t csr_decode;
|
||||
} csr_t;
|
||||
|
||||
// Instruction Generation *incomplete*
|
||||
function automatic logic [31:0] jal (logic[4:0] rd, logic [20:0] imm);
|
||||
// OpCode Jal
|
||||
return {imm[20], imm[10:1], imm[11], imm[19:12], rd, 7'h6f};
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] load (logic [2:0] size, logic[4:0] rd, logic[4:0] rs1, logic [11:0] imm);
|
||||
// OpCode Load
|
||||
return {imm[11:0], rs1, size, rd, 7'h03};
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] store (logic [2:0] size, logic[4:0] rs1, logic[4:0] rs2, logic [11:0] imm);
|
||||
// OpCode Store
|
||||
return {imm[11:5], rs2, rs1, size, imm[4:0], 7'h23};
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] ebreak ();
|
||||
return 32'h00100073;
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] nop ();
|
||||
return 32'h00000013;
|
||||
endfunction
|
||||
|
||||
endpackage
|
||||
|
|
|
@ -728,6 +728,11 @@ module csr_regfile #(
|
|||
trap_vector_base_o = {stvec_q[63:2], 2'b0};
|
||||
end
|
||||
|
||||
// if we are in debug mode jump to a specific address
|
||||
if (debug_mode_q) begin
|
||||
trap_vector_base_o = dm::ExceptionAddress;
|
||||
end
|
||||
|
||||
// check if we are in vectored mode, if yes then do BASE + 4 * cause
|
||||
// we are imposing an additional alignment-constraint of 64 * 4 bytes since
|
||||
// we want to spare the costly addition
|
||||
|
|
|
@ -41,7 +41,7 @@ module debug_rom (
|
|||
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (req_i) begin
|
||||
addr_q = addr_i[$clog2(RomSize)-1+3:3];
|
||||
addr_q <= addr_i[$clog2(RomSize)-1+3:3];
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ module dm_csrs #(
|
|||
// hart status
|
||||
input dm::hartinfo_t [NrHarts-1:0] hartinfo_i, // static hartinfo
|
||||
input logic [NrHarts-1:0] halted_i, // hart is halted
|
||||
input logic [NrHarts-1:0] running_i, // hart is running
|
||||
input logic [NrHarts-1:0] unavailable_i, // e.g.: powered down
|
||||
input logic [NrHarts-1:0] havereset_i, // hart has reset
|
||||
input logic [NrHarts-1:0] resumeack_i, // hart acknowledged resume request
|
||||
|
@ -45,13 +44,18 @@ module dm_csrs #(
|
|||
output logic [NrHarts-1:0] haltreq_o, // request to halt a hart
|
||||
output logic [NrHarts-1:0] resumereq_o, // request hart to resume
|
||||
output logic [NrHarts-1:0] ackhavereset_o, // DM acknowledges reset
|
||||
output logic command_write_o, // debugger is writing to the command field
|
||||
output dm::command_t command_o, // abstract command
|
||||
input logic [NrHarts-1:0] set_cmderror_i, // an error occured
|
||||
input dm::cmderr_t [NrHarts-1:0] cmderror_i, // this error occured
|
||||
input logic [NrHarts-1:0] cmdbusy_i, // cmd is currently busy executing
|
||||
|
||||
output logic cmd_valid_o, // debugger is writing to the command field
|
||||
output dm::command_t cmd_o, // abstract command
|
||||
input logic [NrHarts-1:0] cmderror_valid_i, // an error occured
|
||||
input dm::cmderr_t [NrHarts-1:0] cmderror_i, // this error occured
|
||||
input logic [NrHarts-1:0] cmdbusy_i, // cmd is currently busy executing
|
||||
|
||||
output logic [dm::ProgBufSize-1:0][31:0] progbuf_o, // to system bus
|
||||
output logic [dm::DataCount-1:0][31:0] data_o // optional data register (to system bus)
|
||||
output logic [dm::DataCount-1:0][31:0] data_o,
|
||||
|
||||
output logic [dm::DataCount-1:0][31:0] data_i,
|
||||
output logic data_valid_i
|
||||
);
|
||||
// the amount of bits we need to represent all harts
|
||||
localparam HartSelLen = (NrHarts == 1) ? 1 : $clog2(NrHarts);
|
||||
|
@ -122,8 +126,8 @@ module dm_csrs #(
|
|||
dmstatus.allhalted = halted_i[hartsel[HartSelLen-1:0]];
|
||||
dmstatus.anyhalted = halted_i[hartsel[HartSelLen-1:0]];
|
||||
|
||||
dmstatus.allrunning = running_i[hartsel[HartSelLen-1:0]];
|
||||
dmstatus.anyrunning = running_i[hartsel[HartSelLen-1:0]];
|
||||
dmstatus.allrunning = ~halted_i[hartsel[HartSelLen-1:0]];
|
||||
dmstatus.anyrunning = ~halted_i[hartsel[HartSelLen-1:0]];
|
||||
|
||||
// abstractcs
|
||||
abstractcs = '0;
|
||||
|
@ -140,7 +144,7 @@ module dm_csrs #(
|
|||
data_d = data_q;
|
||||
|
||||
resp_queue_data = 32'0;
|
||||
command_write_o = 1'b0;
|
||||
cmd_valid_o = 1'b0;
|
||||
ackhavereset_o = 'b0;
|
||||
|
||||
// read
|
||||
|
@ -154,7 +158,8 @@ module dm_csrs #(
|
|||
dm::DMStatus: resp_queue_data = dmstatus;
|
||||
dm::Hartinfo: resp_queue_data = hartinfo_i[selected_hart];
|
||||
dm::AbstractCS: resp_queue_data = abstractcs;
|
||||
dm::Command: resp_queue_data = command_q;
|
||||
// command is read-only
|
||||
dm::Command: resp_queue_data = '0;
|
||||
[(dm::ProgBuf0):(dm::ProgBuf0 + dm::ProgBufSize)]: begin
|
||||
resp_queue_data = progbuf_q[dmi_req_bits_addr_i[4:0]];
|
||||
end
|
||||
|
@ -184,14 +189,31 @@ module dm_csrs #(
|
|||
dm::DMStatus:; // write are ignored to R/O register
|
||||
dm::Hartinfo:; // hartinfo is R/O
|
||||
// only command error is write-able
|
||||
dm::AbstractCS: begin
|
||||
dm::AbstractCS: begin // W1C
|
||||
// Gets set if an abstract command fails. The bits in this
|
||||
// field remain set until they are cleared by writing 1 to
|
||||
// them. No abstract command is started until the value is
|
||||
// reset to 0.
|
||||
automatic dm::abstractcs_t abstractcs;
|
||||
abstractcs = dm::abstractcs_t'(dmi_req_bits_data_i);
|
||||
cmderr_d = abstractcs.cmderr;
|
||||
// reads during abstract command execution are not allowed
|
||||
if (!cmdbusy_i) begin
|
||||
cmderr_d = ~abstractcs.cmderr & cmderr_q;
|
||||
end else if (cmderr_q == dm::CmdErrNone) begin
|
||||
cmderr_d = dm::CmdErrBusy;
|
||||
end
|
||||
|
||||
end
|
||||
dm::Command: begin
|
||||
command_write_o = 1'b1;
|
||||
command_d = dmi_req_bits_data_i;
|
||||
// writes are ignored if a command is already busy
|
||||
if (!cmdbusy_i) begin
|
||||
cmd_valid_o = 1'b1;
|
||||
command_d = dmi_req_bits_data_i;
|
||||
// if there was an attempted to write during a busy execution
|
||||
// and the cmderror field is zero set the busy error
|
||||
end else if (cmderr_q == dm::CmdErrNone) begin
|
||||
cmderr_d = dm::CmdErrBusy;
|
||||
end
|
||||
end
|
||||
[(dm::ProgBuf0):(dm::ProgBuf0 + dm::ProgBufSize)]: begin
|
||||
// attempts to write them while busy is set does not change their value
|
||||
|
@ -203,9 +225,14 @@ module dm_csrs #(
|
|||
endcase
|
||||
end
|
||||
// hart threw a command error and has precedence over bus writes
|
||||
if (set_cmderror_i[selected_hart]) begin
|
||||
if (cmderror_valid_i[selected_hart]) begin
|
||||
cmderr_d = cmderror_i[selected_hart];
|
||||
end
|
||||
|
||||
// update data registers
|
||||
if (data_valid_i)
|
||||
data_d = data_i;
|
||||
|
||||
// dmcontrol
|
||||
// TODO(zarubaf) we currently do not implement the hartarry mask
|
||||
dmcontrol_d.hasel = 1'b0;
|
||||
|
@ -232,7 +259,7 @@ module dm_csrs #(
|
|||
assign dmactive_o = dmcontrol_q.dmactive;
|
||||
// if the PoR is set we want to re-set the other system as well
|
||||
assign ndmreset_o = dmcontrol_q.ndmreset | (~rst_ni);
|
||||
assign command_o = command_q;
|
||||
assign cmd_o = command_q;
|
||||
assign progbuf_o = progbuf_q;
|
||||
assign data_o = data_q;
|
||||
// response FIFO
|
||||
|
|
|
@ -39,6 +39,7 @@ module dm_ctrl (
|
|||
output logic cmdbusy_o,
|
||||
// from hart communication module
|
||||
input logic halted_i // hart is halted
|
||||
// input logic command_finished_i
|
||||
);
|
||||
|
||||
logic havereset_d, havereset_q;
|
||||
|
@ -47,7 +48,7 @@ module dm_ctrl (
|
|||
assign havereset_o = havereset_q;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
kRunning, kHaltReq, kHalted
|
||||
kRunning, kHaltReq, kHalted, kCommandExec
|
||||
} state_t;
|
||||
|
||||
state_t state_d, state_q;
|
||||
|
@ -55,7 +56,6 @@ module dm_ctrl (
|
|||
always_comb begin
|
||||
state_d = state_q;
|
||||
|
||||
|
||||
halted_o = 1'b0;
|
||||
running_o = 1'b0;
|
||||
unavailable_o = 1'b0;
|
||||
|
@ -78,8 +78,15 @@ module dm_ctrl (
|
|||
end
|
||||
|
||||
kHalted: begin
|
||||
|
||||
halted_o = 1'b1;
|
||||
// if (command_write_i) state_d = kHalted;
|
||||
end
|
||||
|
||||
kCommandExec: begin
|
||||
// halted_o = 1'b1;
|
||||
// if (command_finished_i) state_d = kHalted;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
|
|
|
@ -19,72 +19,243 @@
|
|||
module dm_mem #(
|
||||
parameter int NrHarts = -1
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic dmactive_i, // debug module reset
|
||||
input logic clk_i, // Clock
|
||||
input logic dmactive_i, // debug module reset
|
||||
|
||||
output logic [NrHarts-1:0] halted_o, // hart acknowledge halt
|
||||
output logic [NrHarts-1:0] going_o, // hart is running
|
||||
output logic [NrHarts-1:0] resuming_o, // hart is resuming
|
||||
output logic [NrHarts-1:0] exception_o, // hart ran into an exception
|
||||
output logic debug_req_o,
|
||||
// from Ctrl and Status register
|
||||
input logic [NrHarts-1:0] haltreq_i,
|
||||
input logic [NrHarts-1:0] resumereq_i,
|
||||
|
||||
// state bits
|
||||
output logic [NrHarts-1:0] halted_o, // hart acknowledge halt
|
||||
output logic [NrHarts-1:0] resuming_o, // hart is resuming
|
||||
|
||||
input logic [dm::ProgBufSize-1:0][31:0] progbuf_i, // program buffer to expose
|
||||
|
||||
output logic [dm::DataCount-1:0][31:0] data_i, // data in
|
||||
output logic [dm::DataCount-1:0][31:0] data_o, // data out
|
||||
output logic data_valid_o, // data out is valid
|
||||
// abstract command interface
|
||||
input logic cmd_valid_i,
|
||||
input dm::command_t cmd_i,
|
||||
output logic cmderror_valid_o,
|
||||
output dm::cmderr_t cmderror_o,
|
||||
output logic cmdbusy_o,
|
||||
// data interface
|
||||
|
||||
input logic [dm::ProgBufSize-1:0][31:0] progbuf_i, // program buffer to expose
|
||||
input logic [dm::DataCount-1:0][31:0] data_i, // data in
|
||||
// SRAM interface
|
||||
input logic req_i,
|
||||
input logic we_i,
|
||||
input logic [63:0] addr_i,
|
||||
input logic [63:0] wdata_i,
|
||||
input logic [7:0] be_i,
|
||||
output logic [63:0] rdata_o
|
||||
input logic req_i,
|
||||
input logic we_i,
|
||||
input logic [63:0] addr_i,
|
||||
input logic [63:0] wdata_i,
|
||||
input logic [7:0] be_i,
|
||||
output logic [63:0] rdata_o
|
||||
);
|
||||
localparam HartSelLen = (NrHarts == 1) ? 1 : $clog2(NrHarts);
|
||||
|
||||
localparam DbgAddressBits = 12;
|
||||
localparam HartSelLen = (NrHarts == 1) ? 1 : $clog2(NrHarts);
|
||||
localparam DataAddr = dm::DataAddr;
|
||||
localparam ProgBufBase = dm::DataAddr - 4*dm::DataCount;
|
||||
localparam AbstractCmdBase = ProgBufBase - 4*dm::ProgBufSize;
|
||||
|
||||
localparam logic [DbgAddressBits-1:0] Halted = 'h100;
|
||||
localparam logic [DbgAddressBits-1:0] Going = 'h104;
|
||||
localparam logic [DbgAddressBits-1:0] Resuming = 'h108;
|
||||
localparam logic [DbgAddressBits-1:0] Exception = 'h10C;
|
||||
localparam logic [DbgAddressBits-1:0] WhereTo = 'h300;
|
||||
localparam logic [DbgAddressBits-1:0] Flags = 'h400;
|
||||
localparam logic [7:0] FlagGo = 7'b0;
|
||||
localparam logic [7:0] FlagResume = 7'b1;
|
||||
|
||||
logic [NrHarts-1:0] halted_d, halted_q;
|
||||
logic [NrHarts-1:0] resuming_d, resuming_q;
|
||||
logic cmdbusy_d, cmdbusy_q;
|
||||
|
||||
logic [HartSelLen-1:0] hart_sel;
|
||||
logic going, exception, halted;
|
||||
logic unsupported_command;
|
||||
|
||||
logic [63:0] rom_rdata;
|
||||
logic [63:0] rdata_d, rdata_q;
|
||||
// distinguish whether we need to forward data from the ROM or the FSM
|
||||
// latch the address for this
|
||||
logic fwd_rom_d, fwd_rom_q;
|
||||
|
||||
assign hart_sel = wdata_i[HartSelLen-1:0];
|
||||
assign debug_req_o = haltreq_i;
|
||||
assign halted_o = halted_q;
|
||||
assign resuming_o = resuming_q;
|
||||
assign cmdbusy_o = cmdbusy_q;
|
||||
|
||||
// abstract command ctrl
|
||||
always_comb begin
|
||||
cmderror_valid_o = 1'b0;
|
||||
cmderror_o = '0;
|
||||
cmdbusy_d = cmdbusy_q;
|
||||
|
||||
if (exception) begin
|
||||
cmderror_valid_o = 1'b1;
|
||||
cmderror_o = dm::CmdErrorException;
|
||||
end
|
||||
|
||||
// we've got a new command
|
||||
if (cmd_valid_i && halted_q) begin
|
||||
cmdbusy_d = 1'b1;
|
||||
// release the go flag
|
||||
end else if (cmd_valid_i) begin
|
||||
// hart must be halted for all requests
|
||||
cmderror_valid_o = 1'b1;
|
||||
cmderror_o = dm::CmdErrorHaltResume;
|
||||
end
|
||||
|
||||
// we've halted again ~> clear the busy flag
|
||||
if (halted) begin
|
||||
cmdbusy_d = 1'b0;
|
||||
end
|
||||
|
||||
if (unsupported_command) begin
|
||||
cmderror_valid_o = 1'b1;
|
||||
cmderror_o = dm::CmdErrNotSupported;
|
||||
end
|
||||
end
|
||||
|
||||
// read/write logic
|
||||
always_comb begin
|
||||
halted_d = halted_q;
|
||||
resuming_d = resuming_q;
|
||||
rdata_o = fwd_rom_q ? rom_rdata : rdata_q;
|
||||
rdata_d = rdata_q;
|
||||
data_o = data_i;
|
||||
// write data in csr register
|
||||
data_valid_o = 1'b0;
|
||||
exception = 1'b0;
|
||||
halted = 1'b0;
|
||||
unsupported_command = 1'b0;
|
||||
// we've got a new request
|
||||
if (req_i) begin
|
||||
// this is a write
|
||||
if (we_i) begin
|
||||
unique case (addr_i[DbgAddressBits-1:0]) inside
|
||||
Halted: begin
|
||||
halted = 1'b1;
|
||||
halted_d[hart_sel] = 1'b1;
|
||||
resuming_d[hart_sel] = 1'b0;
|
||||
end
|
||||
Going:;
|
||||
Resuming: begin
|
||||
halted_d[hart_sel] = 1'b0;
|
||||
resuming_d[hart_sel] = 1'b1;
|
||||
end
|
||||
// an exception occurred during execution
|
||||
Exception: exception = 1'b1;
|
||||
// core can write data registers
|
||||
// TODO(zarubaf) Remove hard-coded values
|
||||
(dm::DataAddr || dm::DataAddr+4): begin
|
||||
// data_valid_o = 1'b1;
|
||||
for (int i = 0; i < $bits(be_i); i++) begin
|
||||
if (be_i[i]) begin
|
||||
// data_o = wdata_i[i*8+:8];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// harts are polling for flags here
|
||||
[Flags:AbstractCmdBase] begin
|
||||
|
||||
end
|
||||
endcase
|
||||
|
||||
// this is a read
|
||||
end else begin
|
||||
unique case (addr_i[DbgAddressBits-1:0]) inside
|
||||
// variable ROM content
|
||||
WhereTo: begin
|
||||
// variable jump to abstract cmd, program_buffer or resume
|
||||
if (resumereq_i) begin
|
||||
rdata_d = {32'b0, riscv::jal(0, dm::ResumeAddress)};
|
||||
end
|
||||
|
||||
// there is a command active so jump there
|
||||
if (cmdbusy_q) begin
|
||||
rdata_d = {32'b0, riscv::jal(0, AbstractCmdBase)};
|
||||
end
|
||||
end
|
||||
|
||||
// TODO(zarubaf) change hard-coded values
|
||||
// TODO(zarubaf) submit verilator bug report
|
||||
// %Error: Internal Error: src/debug/dm_mem.sv:129: ../V3Hashed.cpp:73: sameHash function undefined (returns 0) for node under CFunc.
|
||||
(dm::DataAddr || dm::DataAddr+4): begin
|
||||
rdata_d = {data_i[1], data_i[0]};
|
||||
end
|
||||
|
||||
[ProgBufBase:(dm::DataAddr-4)]: begin
|
||||
// TODO(zarubaf) change hard-coded values
|
||||
rdata_d = {progbuf_i[1], progbuf_i[0]};
|
||||
end
|
||||
// two slots for abstract command
|
||||
[AbstractCmdBase:AbstractCmdBase+4]: begin
|
||||
rdata_d = '0;
|
||||
// this depends on the command being executed
|
||||
unique case (cmd_i.cmdtype)
|
||||
// --------------------
|
||||
// Access Register
|
||||
// --------------------
|
||||
dm::AccessRegister: begin
|
||||
automatic dm::ac_ar_cmd_t ac_ar;
|
||||
ac_ar = dm::ac_ar_cmd_t'(cmd_i.control);
|
||||
|
||||
if (ac_ar.transfer && ac_ar.write) begin
|
||||
rdata_d[0] = riscv::store(ac_ar.aarsize, ac_ar.regno[4:0], 0, dm::DataAddr);
|
||||
end else if (ac_ar.transfer) begin
|
||||
rdata_d[0] = riscv::load(ac_ar.aarsize, ac_ar.regno[4:0], 0, dm::DataAddr);
|
||||
end
|
||||
// check whether we need to execute the program buffer
|
||||
if (ac_ar.postexec) begin
|
||||
// issue a nop, we will automatically run into the program buffer
|
||||
rdata_d[1] = riscv::nop();
|
||||
end else begin
|
||||
// transfer control back to idle loop
|
||||
rdata_d[1] = riscv::ebreak();
|
||||
end
|
||||
end
|
||||
// not supported at the moment
|
||||
// dm::QuickAccess:;
|
||||
// dm::AccessMemory:;
|
||||
default: begin
|
||||
unsupported_command = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
debug_rom i_debug_rom (
|
||||
.clk_i,
|
||||
.req_i,
|
||||
.addr_i,
|
||||
.rdata_o (rom_rdata)
|
||||
);
|
||||
logic [HartSelLen-1:0] hart_sel;
|
||||
assign hart_sel = wdata_i[HartSelLen-1:0];
|
||||
// read/write logic
|
||||
always_comb begin
|
||||
halted_o = '0;
|
||||
going_o = '0;
|
||||
resuming_o = '0;
|
||||
exception_o = '0;
|
||||
rdata_o = fwd_rom_q ? rom_rdata : '0;
|
||||
// we've got a new request
|
||||
if (req_i) begin
|
||||
// this is a write
|
||||
if (we_i) begin
|
||||
case (addr_i[dm::DbgAddressBits-1:0])
|
||||
dm::Halted: halted_o[hart_sel] = 1'b1;
|
||||
dm::Going: going_o[hart_sel] = 1'b1;
|
||||
dm::Resuming: resuming_o[hart_sel] = 1'b1;
|
||||
dm::Exception: exception_o[hart_sel] = 1'b1;
|
||||
endcase
|
||||
// this is a read
|
||||
end else begin
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// ROM starts at the HaltAddress of the core e.g.: it immediately jumps to
|
||||
// the ROM base address
|
||||
assign fwd_rom_d = (addr_i[dm::DbgAddressBits-1:0] >= dm::HaltAddress) ? 1'b1 : 1'b0;
|
||||
assign fwd_rom_d = (addr_i[DbgAddressBits-1:0] >= dm::HaltAddress) ? 1'b1 : 1'b0;
|
||||
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (~dmactive_i) begin
|
||||
fwd_rom_q <= 1'b0;
|
||||
fwd_rom_q <= 1'b0;
|
||||
rdata_q <= '0;
|
||||
halted_q <= 1'b0;
|
||||
resuming_q <= 1'b0;
|
||||
cmdbusy_q <= 1'b0;
|
||||
end else begin
|
||||
fwd_rom_q <= fwd_rom_d;
|
||||
fwd_rom_q <= fwd_rom_d;
|
||||
rdata_q <= rdata_d;
|
||||
halted_q <= halted_d;
|
||||
resuming_q <= resuming_d;
|
||||
cmdbusy_q <= cmdbusy_d;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -19,23 +19,20 @@
|
|||
package dm;
|
||||
parameter logic [3:0] DbgVersion013 = 4'h2;
|
||||
// size of program buffer in junks of 32-bit words
|
||||
parameter logic [4:0] ProgBufSize = 5'h4;
|
||||
parameter logic [4:0] ProgBufSize = 5'h2;
|
||||
|
||||
// TODO(zarubaf) This is hard-coded to two at the moment
|
||||
// amount of data count registers implemented
|
||||
parameter logic [3:0] DataCount = 5'h0;
|
||||
parameter logic [3:0] DataCount = 5'h2;
|
||||
|
||||
// address to which a hart should jump when it was requested to halt
|
||||
parameter logic [63:0] HaltAddress = 64'h800;
|
||||
parameter logic [63:0] ResumeAddress = HaltAddress + 4;
|
||||
parameter logic [63:0] ExceptionAddress = HaltAddress + 8;
|
||||
|
||||
parameter DbgAddressBits = 12;
|
||||
|
||||
parameter logic [DbgAddressBits-1:0] Halted = 'h100;
|
||||
parameter logic [DbgAddressBits-1:0] Going = 'h104;
|
||||
parameter logic [DbgAddressBits-1:0] Resuming = 'h108;
|
||||
parameter logic [DbgAddressBits-1:0] Exception = 'h10C;
|
||||
|
||||
// #define FLAGS 0x400
|
||||
// #define FLAG_GO 0
|
||||
// #define FLAG_RESUME 1
|
||||
// address where data0-15 is shadowed or if shadowed in a CSR
|
||||
// address of the first CSR used for shadowing the data
|
||||
parameter logic [11:0] DataAddr = 12'h380; // we are aligned with Rocket here
|
||||
|
||||
// debug registers
|
||||
typedef enum logic [7:0] {
|
||||
|
@ -153,6 +150,16 @@ package dm;
|
|||
logic [23:0] control;
|
||||
} command_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic zero1;
|
||||
logic [22:20] aarsize;
|
||||
logic zero0;
|
||||
logic postexec;
|
||||
logic transfer;
|
||||
logic write;
|
||||
logic [15:0] regno;
|
||||
} ac_ar_cmd_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:28] xdebugver;
|
||||
logic [27:16] zero2;
|
||||
|
|
|
@ -55,13 +55,16 @@ module dm_top #(
|
|||
logic [NrHarts-1:0] haltreq;
|
||||
logic [NrHarts-1:0] resumereq;
|
||||
logic [NrHarts-1:0] ackhavereset;
|
||||
logic command_write;
|
||||
dm::command_t command;
|
||||
logic [NrHarts-1:0] set_cmderror;
|
||||
logic cmd_valid;
|
||||
dm::command_t cmd;
|
||||
|
||||
logic [NrHarts-1:0] cmderror_valid;
|
||||
dm::cmderr_t [NrHarts-1:0] cmderror;
|
||||
logic [NrHarts-1:0] cmdbusy;
|
||||
logic [dm::ProgBufSize-1:0][31:0] progbuf;
|
||||
logic [dm::DataCount-1:0][31:0] data;
|
||||
logic [dm::DataCount-1:0][31:0] data_csrs_mem;
|
||||
logic [dm::DataCount-1:0][31:0] data_mem_csrs;
|
||||
logic data_valid;
|
||||
|
||||
dm_csrs #(
|
||||
.NrHarts(NrHarts)
|
||||
|
@ -82,48 +85,30 @@ module dm_top #(
|
|||
.dmactive_o ( dmactive_o ),
|
||||
.hartinfo_i ( hartinfo ),
|
||||
.halted_i ( halted ),
|
||||
.running_i ( running ),
|
||||
.unavailable_i ( unavailable ),
|
||||
.havereset_i ( havereset ),
|
||||
.resumeack_i ( resumeack ),
|
||||
.haltreq_o ( haltreq ),
|
||||
.resumereq_o ( resumereq ),
|
||||
.ackhavereset_o ( ackhavereset ),
|
||||
.command_write_o ( command_write ),
|
||||
.command_o ( command ),
|
||||
.set_cmderror_i ( set_cmderror ),
|
||||
.cmd_valid_o ( cmd_valid ),
|
||||
.cmd_o ( cmd ),
|
||||
.cmderror_valid_i ( cmderror_valid ),
|
||||
.cmderror_i ( cmderror ),
|
||||
.cmdbusy_i ( cmdbusy ),
|
||||
.progbuf_o ( progbuf ),
|
||||
.data_o ( data )
|
||||
.data_i ( data_mem_csrs ),
|
||||
.data_valid_i ( data_valid ),
|
||||
.data_o ( data_csrs_mem )
|
||||
);
|
||||
|
||||
logic [NrHarts-1:0] ackhalt;
|
||||
// TODO(zarubaf) take care of resetting
|
||||
assign havereset = '1;
|
||||
assign unavailable = '0;
|
||||
|
||||
// Debug Ctrl for each hart
|
||||
for (genvar i = 0; i < NrHarts; i++) begin : dm_hart_ctrl
|
||||
|
||||
assign hartinfo[i] = ariane_pkg::DebugHartInfo;
|
||||
|
||||
dm_ctrl i_dm_ctrl (
|
||||
.clk_i ( clk_i ),
|
||||
.dmactive_i ( dmactive_o ),
|
||||
.ndmreset_i ( ndmreset_o ),
|
||||
.debug_req_o ( debug_req_o [i] ),
|
||||
.halted_o ( halted [i] ),
|
||||
.running_o ( running [i] ),
|
||||
.unavailable_o ( unavailable [i] ),
|
||||
.havereset_o ( havereset [i] ),
|
||||
.resumeack_o ( resumeack [i] ),
|
||||
.haltreq_i ( haltreq ),
|
||||
.resumereq_i ( resumereq ),
|
||||
.ackhavereset_i ( ackhavereset ),
|
||||
.command_write_i ( command_write ),
|
||||
.command_i ( command ),
|
||||
.set_cmderror_o ( set_cmderror [i] ),
|
||||
.cmderror_o ( cmderror [i] ),
|
||||
.cmdbusy_o ( cmdbusy [i] ),
|
||||
.halted_i ( ackhalt [i] )
|
||||
);
|
||||
end
|
||||
|
||||
logic req;
|
||||
|
@ -137,20 +122,31 @@ module dm_top #(
|
|||
dm_mem #(
|
||||
.NrHarts (NrHarts)
|
||||
) i_dm_mem (
|
||||
.clk_i ( clk_i ),
|
||||
.dmactive_i ( dmactive_o),
|
||||
.halted_o ( ackhalt ),
|
||||
.going_o ( ),
|
||||
.resuming_o ( ),
|
||||
.exception_o ( ),
|
||||
.progbuf_i ( progbuf ), // program buffer to expose
|
||||
.data_i ( data ), // data in
|
||||
.req_i ( req ),
|
||||
.we_i ( we ),
|
||||
.addr_i ( addr ),
|
||||
.wdata_i ( wdata ),
|
||||
.be_i ( be ),
|
||||
.rdata_o ( rdata )
|
||||
.clk_i ( clk_i ),
|
||||
.dmactive_i ( dmactive_o ),
|
||||
.debug_req_o ( debug_req_o ),
|
||||
|
||||
.haltreq_i ( haltreq ),
|
||||
.resumereq_i ( resumereq ),
|
||||
.halted_o ( halted ),
|
||||
.resuming_o ( resumeack ),
|
||||
.cmd_valid_i ( cmd_valid ),
|
||||
.cmd_i ( cmd ),
|
||||
.cmderror_valid_o ( cmderror_valid ),
|
||||
.cmderror_o ( cmderror ),
|
||||
.cmdbusy_o ( cmdbusy ),
|
||||
|
||||
.progbuf_i ( progbuf ),
|
||||
.data_i ( data_csrs_mem ),
|
||||
.data_o ( data_mem_csrs ),
|
||||
.data_valid_o ( data_valid ),
|
||||
|
||||
.req_i ( req ),
|
||||
.we_i ( we ),
|
||||
.addr_i ( addr ),
|
||||
.wdata_i ( wdata ),
|
||||
.be_i ( be ),
|
||||
.rdata_o ( rdata )
|
||||
);
|
||||
|
||||
axi2mem #(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue