mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-20 12:07:53 -04:00
L/S output now shared with CSRs
This commit is contained in:
parent
e4299bba99
commit
4e35ee52f6
6 changed files with 159 additions and 115 deletions
|
@ -31,6 +31,7 @@ module csr_regs (
|
|||
//GC unit
|
||||
input csr_inputs_t csr_inputs,
|
||||
input new_request,
|
||||
input commit,
|
||||
input exception_packet_t gc_exception,
|
||||
output exception_packet_t csr_exception,
|
||||
output logic [1:0] current_privilege,
|
||||
|
@ -58,7 +59,7 @@ module csr_regs (
|
|||
input logic interrupt,
|
||||
input logic timer_interrupt,
|
||||
|
||||
output logic [XLEN-1:0] selected_csr,
|
||||
output logic [XLEN-1:0] wb_csr,
|
||||
output logic [31:0] trap_pc,
|
||||
output logic [31:0] csr_mepc,
|
||||
output logic [31:0] csr_sepc
|
||||
|
@ -123,6 +124,9 @@ module csr_regs (
|
|||
csr_addr_t csr_addr;
|
||||
logic privilege_exception;
|
||||
|
||||
logic [XLEN-1:0] selected_csr;
|
||||
logic [XLEN-1:0] selected_csr_r;
|
||||
|
||||
logic [31:0] updated_csr;
|
||||
|
||||
logic invalid_addr;
|
||||
|
@ -162,10 +166,10 @@ module csr_regs (
|
|||
|
||||
//convert addr into packed struct form
|
||||
assign csr_addr = csr_inputs.csr_addr;
|
||||
assign privilege_exception = new_request && (csr_addr.privilege > privilege_level);
|
||||
assign privilege_exception = new_request & (csr_addr.privilege > privilege_level);
|
||||
|
||||
assign supervisor_write = new_request && !privilege_exception && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == SUPERVISOR_PRIVILEGE);
|
||||
assign machine_write = new_request && !privilege_exception && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == MACHINE_PRIVILEGE);
|
||||
assign supervisor_write = commit && !privilege_exception && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == SUPERVISOR_PRIVILEGE);
|
||||
assign machine_write = commit && !privilege_exception && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == MACHINE_PRIVILEGE);
|
||||
|
||||
logic illegal_instruction;
|
||||
assign illegal_instruction = invalid_addr | privilege_exception;
|
||||
|
@ -177,8 +181,8 @@ module csr_regs (
|
|||
always_comb begin
|
||||
case (csr_inputs.csr_op)
|
||||
CSR_RW : updated_csr = csr_inputs.rs1;
|
||||
CSR_RS : updated_csr = selected_csr | csr_inputs.rs1;
|
||||
CSR_RC : updated_csr = selected_csr & ~csr_inputs.rs1;
|
||||
CSR_RS : updated_csr = selected_csr_r | csr_inputs.rs1;
|
||||
CSR_RC : updated_csr = selected_csr_r & ~csr_inputs.rs1;
|
||||
default : updated_csr = csr_inputs.rs1;
|
||||
endcase
|
||||
end
|
||||
|
@ -525,4 +529,10 @@ endgenerate
|
|||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
selected_csr_r <= selected_csr;
|
||||
end
|
||||
|
||||
assign wb_csr = selected_csr_r;
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -97,6 +97,7 @@ module decode(
|
|||
|
||||
logic mult_div_op;
|
||||
|
||||
logic [NUM_WB_UNITS-1:0] new_request_for_id_gen;
|
||||
logic [NUM_UNITS-1:0] new_request;
|
||||
logic [WB_UNITS_WIDTH-1:0] new_request_int;
|
||||
logic [NUM_UNITS-1:0] issue_ready;
|
||||
|
@ -147,7 +148,13 @@ module decode(
|
|||
assign ti.inflight_packet.rd_addr = future_rd_addr;
|
||||
assign ti.inflight_packet.rd_addr_nzero = ~rd_zero;
|
||||
assign ti.issued = instruction_issued & (uses_rd | new_request[LS_UNIT_WB_ID]);
|
||||
one_hot_to_integer #(NUM_WB_UNITS) new_request_to_int (.*, .one_hot(new_request[NUM_WB_UNITS-1:0]), .int_out(ti.inflight_packet.unit_id));
|
||||
|
||||
always_comb begin
|
||||
new_request_for_id_gen = new_request[NUM_WB_UNITS-1:0];
|
||||
new_request_for_id_gen[LS_UNIT_WB_ID] |= new_request[GC_UNIT_ID];
|
||||
end
|
||||
|
||||
one_hot_to_integer #(NUM_WB_UNITS) new_request_to_int (.*, .one_hot(new_request_for_id_gen), .int_out(ti.inflight_packet.unit_id));
|
||||
////////////////////////////////////////////////////
|
||||
//Unit Determination
|
||||
assign mult_div_op = fb.instruction[25];
|
||||
|
@ -155,7 +162,7 @@ module decode(
|
|||
assign new_request[BRANCH_UNIT_ID] = opcode_trim inside {BRANCH_T, JAL_T, JALR_T};
|
||||
assign new_request[ALU_UNIT_WB_ID] = fb.alu_request;
|
||||
assign new_request[LS_UNIT_WB_ID] = opcode_trim inside {LOAD_T, STORE_T, AMO_T};
|
||||
assign new_request[GC_UNIT_WB_ID] = opcode_trim inside {SYSTEM_T, FENCE_T};
|
||||
assign new_request[GC_UNIT_ID] = opcode_trim inside {SYSTEM_T, FENCE_T};
|
||||
|
||||
generate if (USE_MUL)
|
||||
assign new_request[MUL_UNIT_WB_ID] = (opcode_trim == ARITH_T) && mult_div_op && ~fn3[2];
|
||||
|
@ -172,7 +179,7 @@ module decode(
|
|||
assign issue_ready[BRANCH_UNIT_ID] = new_request[BRANCH_UNIT_ID] & branch_ex.ready;
|
||||
assign issue_ready[ALU_UNIT_WB_ID] = new_request[ALU_UNIT_WB_ID] & alu_ex.ready;
|
||||
assign issue_ready[LS_UNIT_WB_ID] = new_request[LS_UNIT_WB_ID] & ls_ex.ready;
|
||||
assign issue_ready[GC_UNIT_WB_ID] = new_request[GC_UNIT_WB_ID] & gc_ex.ready;
|
||||
assign issue_ready[GC_UNIT_ID] = new_request[GC_UNIT_ID] & gc_ex.ready;
|
||||
generate if (USE_MUL)
|
||||
assign issue_ready[MUL_UNIT_WB_ID] = new_request[MUL_UNIT_WB_ID] & mul_ex.ready;
|
||||
endgenerate
|
||||
|
@ -191,7 +198,7 @@ module decode(
|
|||
assign issue[BRANCH_UNIT_ID] = issue_valid & operands_ready & issue_ready[BRANCH_UNIT_ID];
|
||||
assign issue[ALU_UNIT_WB_ID] = issue_valid & operands_ready & issue_ready[ALU_UNIT_WB_ID];
|
||||
assign issue[LS_UNIT_WB_ID] = issue_valid & load_store_operands_ready & issue_ready[LS_UNIT_WB_ID];
|
||||
assign issue[GC_UNIT_WB_ID] = issue_valid & operands_ready & issue_ready[GC_UNIT_WB_ID];
|
||||
assign issue[GC_UNIT_ID] = issue_valid & operands_ready & issue_ready[GC_UNIT_ID];
|
||||
generate if (USE_MUL)
|
||||
assign issue[MUL_UNIT_WB_ID] = issue_valid & operands_ready & issue_ready[MUL_UNIT_WB_ID];
|
||||
endgenerate
|
||||
|
@ -324,21 +331,21 @@ module decode(
|
|||
assign environment_op = (opcode_trim == SYSTEM_T) && (fn3 == 0);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue_ready[GC_UNIT_WB_ID]) begin
|
||||
if (issue_ready[GC_UNIT_ID]) begin
|
||||
gc_inputs.pc <= fb.pc;
|
||||
gc_inputs.instruction <= fb.instruction;
|
||||
gc_inputs.rs1 <= rf_decode.rs1_data;
|
||||
gc_inputs.rs2 <= rf_decode.rs2_data;
|
||||
gc_inputs.rd_is_zero <= rd_zero;
|
||||
gc_inputs.is_fence <= (opcode_trim == FENCE_T) && ~fn3[0];
|
||||
gc_inputs.is_csr <= (opcode_trim == SYSTEM_T) && (fn3 != 0);
|
||||
end
|
||||
gc_inputs.is_ecall <= issue[GC_UNIT_WB_ID] && environment_op && (fb.instruction[21:20] == 0);
|
||||
gc_inputs.is_ebreak <= issue[GC_UNIT_WB_ID] && environment_op && (fb.instruction[21:20] == 2'b01);
|
||||
gc_inputs.is_ret <= issue[GC_UNIT_WB_ID] && environment_op && (fb.instruction[21:20] == 2'b10);
|
||||
gc_inputs.is_i_fence <= issue[GC_UNIT_WB_ID] && ifence;
|
||||
gc_inputs.is_csr <= (opcode_trim == SYSTEM_T) && (fn3 != 0);
|
||||
gc_inputs.is_ecall <= issue[GC_UNIT_ID] && environment_op && (fb.instruction[21:20] == 0);
|
||||
gc_inputs.is_ebreak <= issue[GC_UNIT_ID] && environment_op && (fb.instruction[21:20] == 2'b01);
|
||||
gc_inputs.is_ret <= issue[GC_UNIT_ID] && environment_op && (fb.instruction[21:20] == 2'b10);
|
||||
gc_inputs.is_i_fence <= issue[GC_UNIT_ID] && ifence;
|
||||
end
|
||||
assign gc_flush_required = issue[GC_UNIT_WB_ID] && (environment_op | ifence);
|
||||
assign gc_flush_required = issue[GC_UNIT_ID] && (environment_op | ifence);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -405,13 +412,13 @@ module decode(
|
|||
assign alu_ex.new_request_dec = issue[ALU_UNIT_WB_ID];
|
||||
assign ls_ex.new_request_dec = issue[LS_UNIT_WB_ID];
|
||||
assign branch_ex.new_request_dec = issue[BRANCH_UNIT_ID];
|
||||
assign gc_ex.new_request_dec = issue[GC_UNIT_WB_ID];
|
||||
assign gc_ex.new_request_dec = issue[GC_UNIT_ID];
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
alu_ex.new_request <= issue[ALU_UNIT_WB_ID];
|
||||
ls_ex.new_request <= issue[LS_UNIT_WB_ID];
|
||||
branch_ex.new_request <= issue[BRANCH_UNIT_ID];
|
||||
gc_ex.new_request <= issue[GC_UNIT_WB_ID];
|
||||
gc_ex.new_request <= issue[GC_UNIT_ID];
|
||||
end
|
||||
|
||||
assign branch_ex.instruction_id_one_hot = ti.issue_id_one_hot;
|
||||
|
@ -443,7 +450,7 @@ module decode(
|
|||
assign branch_ex.possible_issue = new_request[BRANCH_UNIT_ID] & ti.id_available;
|
||||
assign alu_ex.possible_issue = new_request[ALU_UNIT_WB_ID] & ti.id_available;
|
||||
assign ls_ex.possible_issue = new_request[LS_UNIT_WB_ID] & ti.id_available;
|
||||
assign gc_ex.possible_issue = new_request[GC_UNIT_WB_ID] & ti.id_available;
|
||||
assign gc_ex.possible_issue = new_request[GC_UNIT_ID] & ti.id_available;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -475,7 +482,7 @@ module decode(
|
|||
assign tr_unit_stall = ~(|issue_ready) & issue_valid & load_store_operands_ready;
|
||||
assign tr_no_id_stall = (|issue_ready) & (fb_valid & ~ti.id_available & ~gc_issue_hold & ~gc_fetch_flush) & load_store_operands_ready;
|
||||
assign tr_no_instruction_stall = ~fb_valid;
|
||||
assign tr_other_stall = ~instruction_issued & ~(tr_operand_stall | tr_unit_stall | tr_no_id_stall | tr_no_instruction_stall);
|
||||
assign tr_other_stall = fb_valid & ~instruction_issued & ~(tr_operand_stall | tr_unit_stall | tr_no_id_stall | tr_no_instruction_stall) & ~gc_fetch_flush;
|
||||
|
||||
assign tr_instruction_issued_dec = instruction_issued;
|
||||
assign tr_instruction_pc_dec = fb.pc;
|
||||
|
|
187
core/gc_unit.sv
187
core/gc_unit.sv
|
@ -55,7 +55,7 @@ module gc_unit(
|
|||
input logic instruction_complete,
|
||||
input logic instruction_queue_empty,
|
||||
input instruction_id_t oldest_id,
|
||||
unit_writeback_interface.unit gc_wb,
|
||||
//unit_writeback_interface.unit gc_wb,
|
||||
|
||||
//External
|
||||
input logic interrupt,
|
||||
|
@ -71,7 +71,13 @@ module gc_unit(
|
|||
output logic inorder,
|
||||
output logic inuse_clear,
|
||||
|
||||
output logic [31:0] gc_fetch_pc
|
||||
output logic [31:0] gc_fetch_pc,
|
||||
|
||||
//Write-back to Load-Store Unit
|
||||
output logic[31:0] csr_rd,
|
||||
output instruction_id_t csr_id,
|
||||
output instruction_id_one_hot_t csr_id_done,
|
||||
output logic csr_done
|
||||
);
|
||||
|
||||
//Largest depth for TLBs
|
||||
|
@ -82,8 +88,6 @@ module gc_unit(
|
|||
logic [CLEAR_DEPTH-1:0] clear_shift_count;
|
||||
logic [TLB_CLEAR_DEPTH-1:0] tlb_clear_shift_count;
|
||||
////////////////////////////////////////////////////
|
||||
enum {OP_ECALL, OP_EBREAK, OP_SRET, OP_MRET, OP_SFENCE, OP_FENCE, OP_FENCEI} operation;
|
||||
|
||||
//Instructions
|
||||
//All instructions are processed only if in IDLE state, meaning there can be no exceptions caused by instructions already further in the pipeline.
|
||||
//FENCE:
|
||||
|
@ -141,7 +145,7 @@ module gc_unit(
|
|||
//CSR
|
||||
logic mret;
|
||||
logic sret;
|
||||
logic [XLEN-1:0] selected_csr;
|
||||
logic [XLEN-1:0] wb_csr;
|
||||
csr_inputs_t csr_inputs;
|
||||
exception_packet_t gc_exception;
|
||||
exception_packet_t csr_exception;
|
||||
|
@ -151,8 +155,6 @@ module gc_unit(
|
|||
logic [31:0] csr_sepc;
|
||||
|
||||
//Write-back handshaking
|
||||
logic processing;
|
||||
|
||||
logic [2:0] fn3;
|
||||
logic [6:0] opcode;
|
||||
logic [4:0] opcode_trim;
|
||||
|
@ -161,6 +163,9 @@ module gc_unit(
|
|||
logic [4:0] rs2_addr;
|
||||
logic [4:0] future_rd_addr;
|
||||
instruction_id_one_hot_t id;
|
||||
|
||||
logic is_csr;
|
||||
logic processing_csr;
|
||||
//implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
|
@ -171,60 +176,14 @@ module gc_unit(
|
|||
assign fn3 = gc_inputs.instruction[14:12];
|
||||
assign rs1_addr = gc_inputs.instruction[19:15];
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst)
|
||||
state <= RST_STATE;
|
||||
else
|
||||
state <= next_state;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
next_state = state;
|
||||
case (state)
|
||||
RST_STATE : next_state = PRE_CLEAR_STATE;
|
||||
PRE_CLEAR_STATE : next_state = CLEAR_STATE;
|
||||
CLEAR_STATE : if (clear_shift_count[CLEAR_DEPTH-1]) next_state = IDLE_STATE;
|
||||
IDLE_STATE : if (load_store_issue) next_state = LS_EXCEPTION_POSSIBLE;
|
||||
TLB_CLEAR_STATE : if (tlb_clear_shift_count[TLB_CLEAR_DEPTH-1]) next_state = IDLE_STATE;
|
||||
LS_EXCEPTION_POSSIBLE :
|
||||
if (load_store_FIFO_emptying)
|
||||
next_state = IDLE_STATE;
|
||||
else if (ls_exception_valid) begin
|
||||
if (ls_exception.id == oldest_id)
|
||||
next_state = IQ_DISCARD;
|
||||
else
|
||||
next_state = IQ_DRAIN;
|
||||
end
|
||||
IQ_DRAIN :
|
||||
if (ls_exception.id == oldest_id)
|
||||
next_state = IQ_DISCARD;
|
||||
IQ_DISCARD :
|
||||
if (instruction_queue_empty)
|
||||
next_state = IDLE_STATE;
|
||||
default : next_state = RST_STATE;
|
||||
endcase
|
||||
end
|
||||
|
||||
logic ls_exception_first_cycle;
|
||||
logic ls_exception_second_cycle;
|
||||
|
||||
assign ls_exception_first_cycle = ls_exception_valid && (state == LS_EXCEPTION_POSSIBLE);
|
||||
always_ff @ (posedge clk) begin
|
||||
ls_exception_second_cycle <= ls_exception_first_cycle;
|
||||
end
|
||||
|
||||
assign gc_exception.code =
|
||||
ls_exception_second_cycle ? ls_exception.code :
|
||||
gc_inputs.is_ecall ? ecall_code : BREAK;
|
||||
assign gc_exception.pc = ls_exception_second_cycle ? ls_exception.pc : gc_inputs.pc;
|
||||
assign gc_exception.tval = ls_exception_second_cycle ? ls_exception.tval : '0;
|
||||
assign gc_exception.valid = gc_inputs.is_ecall | gc_inputs.is_ebreak | ls_exception_second_cycle;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//GC Operation
|
||||
assign is_csr = gc_ex.new_request & gc_inputs.is_csr;
|
||||
|
||||
assign gc_fetch_flush = branch_flush | gc_fetch_pc_override;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
gc_issue_hold <= gc_ex.new_request_dec || processing || (next_state inside {PRE_CLEAR_STATE, CLEAR_STATE, TLB_CLEAR_STATE, IQ_DRAIN, IQ_DISCARD});
|
||||
gc_issue_hold <= gc_ex.new_request_dec || is_csr || processing_csr || (next_state inside {PRE_CLEAR_STATE, CLEAR_STATE, TLB_CLEAR_STATE, IQ_DRAIN, IQ_DISCARD});
|
||||
inuse_clear <= (next_state == CLEAR_STATE);
|
||||
inorder <= 0;//(next_state inside {LS_EXCEPTION_POSSIBLE, IQ_DRAIN});
|
||||
end
|
||||
|
@ -237,14 +196,39 @@ module gc_unit(
|
|||
gc_supress_writeback <= next_state inside {PRE_CLEAR_STATE, CLEAR_STATE, TLB_CLEAR_STATE, IQ_DISCARD} ? 1 : 0;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//GC State Machine
|
||||
always @(posedge clk) begin
|
||||
if (rst)
|
||||
state <= RST_STATE;
|
||||
else
|
||||
state <= next_state;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
second_cycle_flush <= gc_flush_required;
|
||||
gc_fetch_pc_override <= gc_flush_required | second_cycle_flush | ls_exception_first_cycle;
|
||||
gc_fetch_pc <=
|
||||
gc_inputs.is_i_fence ? gc_inputs.pc + 4 :
|
||||
gc_inputs.is_ret ? csr_mepc :
|
||||
trap_pc;
|
||||
gc_state ls_exception_next_state;
|
||||
always_comb begin
|
||||
ls_exception_next_state = state;
|
||||
if (load_store_FIFO_emptying)
|
||||
ls_exception_next_state = IDLE_STATE;
|
||||
else if (ls_exception_valid) begin
|
||||
if (ls_exception.id == oldest_id)
|
||||
ls_exception_next_state = IQ_DISCARD;
|
||||
else
|
||||
ls_exception_next_state = IQ_DRAIN;
|
||||
end
|
||||
|
||||
next_state = state;
|
||||
case (state)
|
||||
RST_STATE : next_state = PRE_CLEAR_STATE;
|
||||
PRE_CLEAR_STATE : next_state = CLEAR_STATE;
|
||||
CLEAR_STATE : if (clear_shift_count[CLEAR_DEPTH-1]) next_state = IDLE_STATE;
|
||||
IDLE_STATE : if (load_store_issue) next_state = LS_EXCEPTION_POSSIBLE;
|
||||
TLB_CLEAR_STATE : if (tlb_clear_shift_count[TLB_CLEAR_DEPTH-1]) next_state = IDLE_STATE;
|
||||
LS_EXCEPTION_POSSIBLE : next_state = ls_exception_next_state;
|
||||
IQ_DRAIN : if (ls_exception.id == oldest_id) next_state = IQ_DISCARD;
|
||||
IQ_DISCARD : if (instruction_queue_empty) next_state = IDLE_STATE;
|
||||
default : next_state = RST_STATE;
|
||||
endcase
|
||||
end
|
||||
|
||||
//CLEAR state shift reg
|
||||
|
@ -259,12 +243,14 @@ module gc_unit(
|
|||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//CSR registers
|
||||
assign csr_inputs.rs1 = fn3[2] ? {27'b0, rs1_addr} : gc_inputs.rs1;
|
||||
assign csr_inputs.csr_addr = gc_inputs.instruction[31:20];
|
||||
assign csr_inputs.csr_op = fn3[1:0];
|
||||
assign csr_inputs.rs1_is_zero = (rs1_addr == 0);
|
||||
assign csr_inputs.rd_is_zero = gc_inputs.rd_is_zero;
|
||||
//Exception handling
|
||||
logic ls_exception_first_cycle;
|
||||
logic ls_exception_second_cycle;
|
||||
|
||||
assign ls_exception_first_cycle = ls_exception_valid && (state == LS_EXCEPTION_POSSIBLE);
|
||||
always_ff @ (posedge clk) begin
|
||||
ls_exception_second_cycle <= ls_exception_first_cycle;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
case (current_privilege)
|
||||
|
@ -275,34 +261,63 @@ module gc_unit(
|
|||
endcase
|
||||
end
|
||||
|
||||
csr_regs csr_registers (.*, .new_request(gc_inputs.is_csr & gc_ex.new_request));
|
||||
assign gc_exception.code =
|
||||
ls_exception_second_cycle ? ls_exception.code :
|
||||
gc_inputs.is_ecall ? ecall_code : BREAK;
|
||||
assign gc_exception.pc = ls_exception_second_cycle ? ls_exception.pc : gc_inputs.pc;
|
||||
assign gc_exception.tval = ls_exception_second_cycle ? ls_exception.tval : '0;
|
||||
assign gc_exception.valid = gc_inputs.is_ecall | gc_inputs.is_ebreak | ls_exception_second_cycle;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
second_cycle_flush <= gc_flush_required;
|
||||
gc_fetch_pc_override <= gc_flush_required | second_cycle_flush | ls_exception_first_cycle;
|
||||
gc_fetch_pc <=
|
||||
gc_inputs.is_i_fence ? gc_inputs.pc + 4 :
|
||||
gc_inputs.is_ret ? csr_mepc :
|
||||
trap_pc;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//CSR registers
|
||||
assign csr_inputs.rs1 = fn3[2] ? {27'b0, rs1_addr} : gc_inputs.rs1;
|
||||
assign csr_inputs.csr_addr = gc_inputs.instruction[31:20];
|
||||
assign csr_inputs.csr_op = fn3[1:0];
|
||||
assign csr_inputs.rs1_is_zero = (rs1_addr == 0);
|
||||
assign csr_inputs.rd_is_zero = gc_inputs.rd_is_zero;
|
||||
|
||||
csr_regs csr_registers (.*, .new_request(is_csr), .commit(csr_ready_to_complete_r));
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Decode / Write-back Handshaking
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
processing <= 0;
|
||||
else if (gc_ex.new_request_dec)
|
||||
processing <= 1;
|
||||
else if ((state == IDLE_STATE) && instruction_queue_empty)
|
||||
processing <= 0;
|
||||
end
|
||||
|
||||
//gc_issue_hold prevents further instructions from being issued until processing returns to zero
|
||||
logic csr_ready_to_complete;
|
||||
logic csr_ready_to_complete_r;
|
||||
//CSR reads are passed through the Load-Store unit
|
||||
//A CSR write is only committed once it is the oldest instruction in the pipeline
|
||||
//while processing a csr operation, gc_issue_hold prevents further instructions from being issued
|
||||
assign gc_ex.ready = 1;
|
||||
|
||||
//Write_back
|
||||
always_ff @(posedge clk) begin
|
||||
id <= gc_ex.instruction_id_one_hot;
|
||||
gc_wb.done_next_cycle <= id & {MAX_INFLIGHT_COUNT{(gc_ex.new_request & gc_inputs.is_csr)}};
|
||||
if (rst)
|
||||
processing_csr <= 0;
|
||||
else if (csr_ready_to_complete)
|
||||
processing_csr <= 0;
|
||||
else if (is_csr)
|
||||
processing_csr <= 1;
|
||||
end
|
||||
|
||||
assign csr_ready_to_complete = (is_csr | processing_csr) && (oldest_id == csr_id);
|
||||
always_ff @(posedge clk) begin
|
||||
if (gc_ex.new_request) begin
|
||||
gc_wb.rd <= selected_csr;
|
||||
csr_ready_to_complete_r <= csr_ready_to_complete;
|
||||
csr_id_done <= id & {MAX_INFLIGHT_COUNT{csr_ready_to_complete}};
|
||||
if (gc_ex.new_request_dec) begin
|
||||
id <= gc_ex.instruction_id_one_hot;
|
||||
csr_id <= gc_ex.instruction_id;
|
||||
end
|
||||
end
|
||||
|
||||
assign csr_done = csr_ready_to_complete_r;
|
||||
assign csr_rd = wb_csr;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
|
||||
|
|
|
@ -46,6 +46,11 @@ module load_store_unit (
|
|||
|
||||
local_memory_interface.master data_bram,
|
||||
|
||||
input logic[31:0] csr_rd,
|
||||
input instruction_id_one_hot_t csr_id_done,
|
||||
input instruction_id_t csr_id,
|
||||
input logic csr_done,
|
||||
|
||||
output logic store_committed,
|
||||
output instruction_id_t store_id,
|
||||
|
||||
|
@ -328,8 +333,8 @@ module load_store_unit (
|
|||
////////////////////////////////////////////////////
|
||||
//Output bank
|
||||
always_ff @ (posedge clk) begin
|
||||
if (load_complete)
|
||||
rd_bank[stage2_attr.instruction_id] <= final_load_data;
|
||||
if (load_complete | csr_done)
|
||||
rd_bank[csr_done ? csr_id : stage2_attr.instruction_id] <= csr_done ? csr_rd : final_load_data;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
|
@ -340,11 +345,13 @@ module load_store_unit (
|
|||
assign ls_wb.rd = rd_bank[ls_wb.writeback_instruction_id];
|
||||
|
||||
logic exception_complete;
|
||||
logic ls_done;
|
||||
always_ff @ (posedge clk) begin
|
||||
exception_complete <= (input_fifo.valid & ls_exception_valid & stage1.load);
|
||||
end
|
||||
assign ls_done = load_complete | exception_complete;
|
||||
|
||||
assign ls_wb.done_next_cycle = stage2_attr.instruction_id_one_hot & {MAX_INFLIGHT_COUNT{(load_complete | exception_complete)}};
|
||||
assign ls_wb.done_next_cycle = csr_id_done | (stage2_attr.instruction_id_one_hot & {MAX_INFLIGHT_COUNT{ls_done}});
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -113,6 +113,11 @@ module taiga (
|
|||
logic store_committed;
|
||||
instruction_id_t store_id;
|
||||
|
||||
logic[31:0] csr_rd;
|
||||
instruction_id_t csr_id;
|
||||
instruction_id_one_hot_t csr_id_done;
|
||||
logic csr_done;
|
||||
|
||||
//Branch Unit and Fetch Unit
|
||||
logic branch_taken;
|
||||
logic [31:0] pc_offset;
|
||||
|
@ -189,7 +194,7 @@ module taiga (
|
|||
assign dtlb.physical_address = dtlb.virtual_address;
|
||||
end
|
||||
endgenerate
|
||||
gc_unit gc_unit_block (.*, .gc_wb(unit_wb[GC_UNIT_WB_ID]));
|
||||
gc_unit gc_unit_block (.*);
|
||||
|
||||
generate if (USE_MUL)
|
||||
mul_unit mul_unit_block (.*, .mul_wb(unit_wb[MUL_UNIT_WB_ID]));
|
||||
|
|
|
@ -184,17 +184,17 @@ package taiga_config;
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Write-Back Unit IDs
|
||||
parameter NUM_WB_UNITS = 3 + USE_MUL + USE_DIV;
|
||||
parameter NUM_WB_UNITS = 2 + USE_MUL + USE_DIV;
|
||||
parameter WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS);
|
||||
parameter NUM_UNITS = NUM_WB_UNITS + 1;
|
||||
parameter NUM_UNITS = NUM_WB_UNITS + 2;
|
||||
|
||||
parameter ALU_UNIT_WB_ID = 0;
|
||||
parameter GC_UNIT_WB_ID = 1;
|
||||
parameter LS_UNIT_WB_ID = 2;
|
||||
parameter LS_UNIT_WB_ID = 1;
|
||||
parameter DIV_UNIT_WB_ID = LS_UNIT_WB_ID + USE_DIV;
|
||||
parameter MUL_UNIT_WB_ID = DIV_UNIT_WB_ID + USE_MUL;
|
||||
//Non-writeback units
|
||||
parameter BRANCH_UNIT_ID = MUL_UNIT_WB_ID + 1;
|
||||
parameter GC_UNIT_ID = BRANCH_UNIT_ID + 1;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue