mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-22 04:57:18 -04:00
re-parameterization
This commit is contained in:
parent
2a77a76132
commit
14075c8f13
27 changed files with 849 additions and 637 deletions
|
@ -85,7 +85,7 @@ module axi_to_arb
|
|||
logic address_phase_complete;
|
||||
logic [31:0] amo_result;
|
||||
logic [31:0] amo_result_r;
|
||||
logic [DCACHE_SUB_LINE_ADDR_W-1:0] read_count;
|
||||
logic [$clog2(EXAMPLE_CONFIG.DCACHE.LINE_W)-1:0] read_count;
|
||||
logic amo_write_ready;
|
||||
logic[4:0] write_reference_burst_count;
|
||||
|
||||
|
@ -141,7 +141,7 @@ module axi_to_arb
|
|||
//TODO: assumption that all data caches have same line size, would have to update wrt the burst size to be safe if they have different line lengths
|
||||
//also update araddr
|
||||
always_ff @ (posedge clk) begin
|
||||
if (axi_rvalid && (read_count == l2.addr[DCACHE_SUB_LINE_ADDR_W-1:0]))
|
||||
if (axi_rvalid && (read_count == l2.addr[$clog2(EXAMPLE_CONFIG.DCACHE.LINE_W)-1:0]))
|
||||
amo_result_r <= amo_result;
|
||||
end
|
||||
|
||||
|
@ -150,7 +150,7 @@ module axi_to_arb
|
|||
amo_write_ready <= 0;
|
||||
else if (pop)
|
||||
amo_write_ready <= 0;
|
||||
else if (l2.is_amo && axi_rvalid && read_count == l2.addr[DCACHE_SUB_LINE_ADDR_W-1:0])
|
||||
else if (l2.is_amo && axi_rvalid && read_count == l2.addr[$clog2(EXAMPLE_CONFIG.DCACHE.LINE_W)-1:0])
|
||||
amo_write_ready <= 1;
|
||||
end
|
||||
//End AMO
|
||||
|
@ -166,7 +166,7 @@ module axi_to_arb
|
|||
assign axi_arprot = '0;
|
||||
assign axi_arid = 6'(l2.id);
|
||||
|
||||
assign axi_araddr ={l2.addr[29:DCACHE_SUB_LINE_ADDR_W], {DCACHE_SUB_LINE_ADDR_W{1'b0}}, 2'b00};
|
||||
assign axi_araddr ={l2.addr[29:$clog2(EXAMPLE_CONFIG.DCACHE.LINE_W)], {$clog2(EXAMPLE_CONFIG.DCACHE.LINE_W){1'b0}}, 2'b00};
|
||||
|
||||
assign write_reference_burst_count = read_modify_write ? 0 : burst_count;
|
||||
|
||||
|
|
|
@ -26,30 +26,33 @@ module branch_predictor
|
|||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
branch_predictor_interface.branch_predictor bp,
|
||||
output branch_metadata_t branch_metadata_if,
|
||||
input branch_metadata_t branch_metadata_ex,
|
||||
input branch_results_t br_results
|
||||
input branch_results_t br_results,
|
||||
ras_interface.branch_predictor ras
|
||||
);
|
||||
|
||||
//BP tag width can be reduced, based on memory size, when virtual address
|
||||
//support is not enabled
|
||||
localparam longint CACHE_RANGE = 64'(MEMORY_ADDR_H) - 64'(MEMORY_ADDR_L) + 1;
|
||||
localparam longint SCRATCH_RANGE = 64'(SCRATCH_ADDR_H) - 64'(SCRATCH_ADDR_L) + 1;
|
||||
localparam longint CACHE_RANGE = 64'(CONFIG.ICACHE_ADDR.H) - 64'(CONFIG.ICACHE_ADDR.L) + 1;
|
||||
localparam longint SCRATCH_RANGE = 64'(CONFIG.ILOCAL_MEM_ADDR.H) - 64'(CONFIG.ILOCAL_MEM_ADDR.L) + 1;
|
||||
|
||||
function int get_memory_width();
|
||||
if(ENABLE_S_MODE)
|
||||
if(CONFIG.INCLUDE_S_MODE)
|
||||
return 32;
|
||||
else if (USE_ICACHE && CACHE_RANGE > SCRATCH_RANGE)
|
||||
else if (CONFIG.INCLUDE_ICACHE && CACHE_RANGE > SCRATCH_RANGE)
|
||||
return $clog2(CACHE_RANGE);
|
||||
else
|
||||
return $clog2(SCRATCH_RANGE);
|
||||
endfunction
|
||||
|
||||
localparam BRANCH_ADDR_W = $clog2(BRANCH_TABLE_ENTRIES);
|
||||
localparam BRANCH_ADDR_W = $clog2(CONFIG.BP.ENTRIES);
|
||||
localparam BTAG_W = get_memory_width() - BRANCH_ADDR_W - 2;
|
||||
|
||||
function logic[BTAG_W-1:0] get_tag (input logic[31:0] pc);
|
||||
|
@ -65,31 +68,39 @@ module branch_predictor
|
|||
branch_predictor_metadata_t metadata;
|
||||
} branch_table_entry_t;
|
||||
|
||||
|
||||
branch_table_entry_t [BRANCH_PREDICTOR_WAYS-1:0] if_entry;
|
||||
branch_table_entry_t [CONFIG.BP.WAYS-1:0] if_entry;
|
||||
branch_table_entry_t ex_entry;
|
||||
|
||||
typedef struct packed{
|
||||
branch_predictor_metadata_t branch_predictor_metadata;
|
||||
logic branch_prediction_used;
|
||||
logic [CONFIG.BP.WAYS-1:0] branch_predictor_update_way;
|
||||
} branch_metadata_t;
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic [$bits(branch_metadata_t)-1:0] branch_metadata_table [MAX_IDS];
|
||||
branch_metadata_t branch_metadata_if;
|
||||
branch_metadata_t branch_metadata_ex;
|
||||
|
||||
logic branch_predictor_direction_changed;
|
||||
logic [31:0] new_jump_addr;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0][31:0] predicted_pc;
|
||||
logic [CONFIG.BP.WAYS-1:0][31:0] predicted_pc;
|
||||
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] tag_matches;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] replacement_way;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] tag_update_way;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] target_update_way;
|
||||
logic [$clog2(BRANCH_PREDICTOR_WAYS > 1 ? BRANCH_PREDICTOR_WAYS : 2)-1:0] hit_way;
|
||||
logic [CONFIG.BP.WAYS-1:0] tag_matches;
|
||||
logic [CONFIG.BP.WAYS-1:0] replacement_way;
|
||||
logic [CONFIG.BP.WAYS-1:0] tag_update_way;
|
||||
logic [CONFIG.BP.WAYS-1:0] target_update_way;
|
||||
logic [$clog2(CONFIG.BP.WAYS > 1 ? CONFIG.BP.WAYS : 2)-1:0] hit_way;
|
||||
logic tag_match;
|
||||
logic use_predicted_pc;
|
||||
/////////////////////////////////////////
|
||||
|
||||
genvar i;
|
||||
generate if (USE_BRANCH_PREDICTOR)
|
||||
for (i=0; i<BRANCH_PREDICTOR_WAYS; i++) begin : branch_tag_banks
|
||||
branch_predictor_ram #(.C_DATA_WIDTH($bits(branch_table_entry_t)), .C_DEPTH(BRANCH_TABLE_ENTRIES))
|
||||
generate if (CONFIG.INCLUDE_BRANCH_PREDICTOR)
|
||||
for (i=0; i<CONFIG.BP.WAYS; i++) begin : branch_tag_banks
|
||||
branch_predictor_ram #(.C_DATA_WIDTH($bits(branch_table_entry_t)), .C_DEPTH(CONFIG.BP.ENTRIES))
|
||||
tag_bank (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.write_addr (br_results.pc_ex[2 +: BRANCH_ADDR_W]),
|
||||
.write_addr (br_results.pc[2 +: BRANCH_ADDR_W]),
|
||||
.write_en (tag_update_way[i]),
|
||||
.write_data (ex_entry),
|
||||
.read_addr (bp.next_pc[2 +: BRANCH_ADDR_W]),
|
||||
|
@ -98,15 +109,15 @@ module branch_predictor
|
|||
end
|
||||
endgenerate
|
||||
|
||||
generate if (USE_BRANCH_PREDICTOR)
|
||||
for (i=0; i<BRANCH_PREDICTOR_WAYS; i++) begin : branch_table_banks
|
||||
branch_predictor_ram #(.C_DATA_WIDTH(32), .C_DEPTH(BRANCH_TABLE_ENTRIES))
|
||||
generate if (CONFIG.INCLUDE_BRANCH_PREDICTOR)
|
||||
for (i=0; i<CONFIG.BP.WAYS; i++) begin : branch_table_banks
|
||||
branch_predictor_ram #(.C_DATA_WIDTH(32), .C_DEPTH(CONFIG.BP.ENTRIES))
|
||||
addr_table (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.write_addr(br_results.pc_ex[2 +: BRANCH_ADDR_W]),
|
||||
.write_addr(br_results.pc[2 +: BRANCH_ADDR_W]),
|
||||
.write_en(target_update_way[i]),
|
||||
.write_data(br_results.new_pc),
|
||||
.write_data(br_results.target_pc),
|
||||
.read_addr(bp.next_pc[2 +: BRANCH_ADDR_W]),
|
||||
.read_en(bp.new_mem_request),
|
||||
.read_data(predicted_pc[i])
|
||||
|
@ -114,16 +125,16 @@ module branch_predictor
|
|||
end
|
||||
endgenerate
|
||||
|
||||
generate if (USE_BRANCH_PREDICTOR)
|
||||
for (i=0; i<BRANCH_PREDICTOR_WAYS; i++) begin : branch_hit_detection
|
||||
generate if (CONFIG.INCLUDE_BRANCH_PREDICTOR)
|
||||
for (i=0; i<CONFIG.BP.WAYS; i++) begin : branch_hit_detection
|
||||
assign tag_matches[i] = ({if_entry[i].valid, if_entry[i].tag} == {1'b1, get_tag(bp.if_pc)});
|
||||
end
|
||||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instruction Fetch Response
|
||||
generate if (BRANCH_PREDICTOR_WAYS > 1)
|
||||
one_hot_to_integer #(BRANCH_PREDICTOR_WAYS) hit_way_conv (
|
||||
generate if (CONFIG.BP.WAYS > 1)
|
||||
one_hot_to_integer #(CONFIG.BP.WAYS) hit_way_conv (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.one_hot(tag_matches),
|
||||
|
@ -134,7 +145,7 @@ module branch_predictor
|
|||
endgenerate
|
||||
assign tag_match = |tag_matches;
|
||||
|
||||
assign use_predicted_pc = USE_BRANCH_PREDICTOR & tag_match;
|
||||
assign use_predicted_pc = CONFIG.INCLUDE_BRANCH_PREDICTOR & tag_match;
|
||||
|
||||
//Predicted PC and whether the prediction is valid
|
||||
assign bp.predicted_pc = predicted_pc[hit_way];
|
||||
|
@ -143,13 +154,32 @@ module branch_predictor
|
|||
assign bp.is_return = if_entry[hit_way].is_return;
|
||||
assign bp.is_call = if_entry[hit_way].is_call;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instruction Fetch metadata
|
||||
cycler #(CONFIG.BP.WAYS)
|
||||
replacement_policy (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.en (1'b1),
|
||||
.one_hot (replacement_way)
|
||||
);
|
||||
assign branch_metadata_if.branch_predictor_metadata = if_entry[hit_way].metadata;
|
||||
assign branch_metadata_if.branch_prediction_used = use_predicted_pc;
|
||||
assign branch_metadata_if.branch_predictor_update_way = tag_match ? tag_matches : replacement_way;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (bp.pc_id_assigned)
|
||||
branch_metadata_table[bp.pc_id] <= branch_metadata_if;
|
||||
end
|
||||
assign branch_metadata_ex = branch_metadata_table[br_results.id];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Execution stage update
|
||||
assign ex_entry.valid = 1;
|
||||
assign ex_entry.tag = get_tag(br_results.pc_ex);
|
||||
assign ex_entry.is_branch = br_results.is_branch_ex;
|
||||
assign ex_entry.is_return = br_results.is_return_ex;
|
||||
assign ex_entry.is_call = br_results.is_call_ex;
|
||||
assign ex_entry.tag = get_tag(br_results.pc);
|
||||
assign ex_entry.is_branch = br_results.is_branch;
|
||||
assign ex_entry.is_return = br_results.is_return;
|
||||
assign ex_entry.is_call = br_results.is_call;
|
||||
|
||||
|
||||
//2-bit saturating counter
|
||||
|
@ -167,23 +197,14 @@ module branch_predictor
|
|||
(~branch_metadata_ex.branch_prediction_used) |
|
||||
(branch_metadata_ex.branch_predictor_metadata[1] ^ ex_entry.metadata[1]);
|
||||
|
||||
assign tag_update_way = {BRANCH_PREDICTOR_WAYS{br_results.branch_ex}} & (branch_metadata_ex.branch_predictor_update_way);
|
||||
assign target_update_way = {BRANCH_PREDICTOR_WAYS{branch_predictor_direction_changed}} & tag_update_way;
|
||||
assign tag_update_way = {CONFIG.BP.WAYS{br_results.valid}} & (branch_metadata_ex.branch_predictor_update_way);
|
||||
assign target_update_way = {CONFIG.BP.WAYS{branch_predictor_direction_changed}} & tag_update_way;
|
||||
////////////////////////////////////////////////////
|
||||
//Target PC if branch flush occured
|
||||
assign bp.branch_flush_pc = br_results.new_pc;
|
||||
assign bp.branch_flush_pc = br_results.target_pc;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instruction Fetch metadata
|
||||
cycler #(BRANCH_PREDICTOR_WAYS) replacement_policy (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.en (1'b1),
|
||||
.one_hot (replacement_way)
|
||||
);
|
||||
|
||||
assign branch_metadata_if.branch_predictor_metadata = if_entry[hit_way].metadata;
|
||||
assign branch_metadata_if.branch_prediction_used = use_predicted_pc;
|
||||
assign branch_metadata_if.branch_predictor_update_way = tag_match ? tag_matches : replacement_way;
|
||||
//RAS support
|
||||
assign ras.branch_retired = br_results.valid & br_results.is_branch & branch_metadata_ex.branch_prediction_used;
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -26,6 +26,10 @@ module branch_unit
|
|||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -33,12 +37,8 @@ module branch_unit
|
|||
unit_issue_interface.unit issue,
|
||||
input branch_inputs_t branch_inputs,
|
||||
output branch_results_t br_results,
|
||||
ras_interface.branch_unit ras,
|
||||
output logic branch_flush,
|
||||
|
||||
output id_t branch_id,
|
||||
input branch_metadata_t branch_metadata_ex,
|
||||
|
||||
output logic potential_branch_exception,
|
||||
output logic branch_exception_is_jump,
|
||||
output exception_packet_t br_exception,
|
||||
|
@ -115,7 +115,7 @@ module branch_unit
|
|||
//Exception support
|
||||
id_t jmp_id;
|
||||
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
generate if (CONFIG.INCLUDE_M_MODE) begin
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue.possible_issue) begin
|
||||
jmp_id <= issue.id;
|
||||
|
@ -131,15 +131,6 @@ module branch_unit
|
|||
end
|
||||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID Management
|
||||
assign branch_complete = instruction_is_completing & (~jal_jalr_ex) & (~br_exception.valid);
|
||||
assign branch_id = id_ex;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//RAS support
|
||||
assign ras.branch_retired = branch_complete & branch_metadata_ex.branch_prediction_used;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Predictor support
|
||||
logic is_return;
|
||||
|
@ -152,13 +143,14 @@ module branch_unit
|
|||
end
|
||||
end
|
||||
|
||||
assign br_results.pc_ex = pc_ex;
|
||||
assign br_results.new_pc = new_pc_ex;
|
||||
assign br_results.id = id_ex;
|
||||
assign br_results.valid = instruction_is_completing;
|
||||
assign br_results.pc = pc_ex;
|
||||
assign br_results.target_pc = new_pc_ex;
|
||||
assign br_results.branch_taken = branch_taken_ex;
|
||||
assign br_results.branch_ex = instruction_is_completing;
|
||||
assign br_results.is_branch_ex = ~jal_jalr_ex;
|
||||
assign br_results.is_return_ex = is_return;
|
||||
assign br_results.is_call_ex = is_call;
|
||||
assign br_results.is_branch = ~jal_jalr_ex;
|
||||
assign br_results.is_return = is_return;
|
||||
assign br_results.is_call = is_call;
|
||||
|
||||
assign branch_flush = instruction_is_completing && (branch_inputs.issue_pc[31:1] != new_pc_ex[31:1]);
|
||||
|
||||
|
|
176
core/csr_regs.sv
176
core/csr_regs.sv
|
@ -27,6 +27,10 @@ module csr_regs
|
|||
import taiga_types::*;
|
||||
import csr_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -89,9 +93,9 @@ module csr_regs
|
|||
|
||||
satp_t satp;
|
||||
|
||||
logic[COUNTER_W-1:0] mcycle;
|
||||
logic[COUNTER_W-1:0] mtime;
|
||||
logic[COUNTER_W-1:0] minst_ret;
|
||||
logic[CONFIG.CSRS.COUNTER_W-1:0] mcycle;
|
||||
logic[CONFIG.CSRS.COUNTER_W-1:0] mtime;
|
||||
logic[CONFIG.CSRS.COUNTER_W-1:0] minst_ret;
|
||||
localparam INST_RET_INC_W = 2;
|
||||
logic [INST_RET_INC_W-1:0] inst_ret_inc;
|
||||
|
||||
|
@ -152,14 +156,14 @@ module csr_regs
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Machine ISA register
|
||||
const misa_t misa = '{default:0, mxlen:1, A:(USE_AMO), I:1, M:(USE_MUL && USE_DIV), S:(ENABLE_S_MODE), U:(ENABLE_U_MODE)};
|
||||
const misa_t misa = '{default:0, mxlen:1, A:(CONFIG.INCLUDE_AMO), I:1, M:(CONFIG.INCLUDE_MUL && CONFIG.INCLUDE_DIV), S:(CONFIG.INCLUDE_S_MODE), U:(CONFIG.INCLUDE_U_MODE)};
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Machine Version Registers
|
||||
const logic [XLEN-1:0] mvendorid = 0;
|
||||
const logic [XLEN-1:0] marchid = 0;
|
||||
const logic [XLEN-1:0] mimpid = MACHINE_IMPLEMENTATION_ID;
|
||||
const logic [XLEN-1:0] mhartid = CPU_ID;
|
||||
const logic [XLEN-1:0] mimpid = CONFIG.CSRS.MACHINE_IMPLEMENTATION_ID;
|
||||
const logic [XLEN-1:0] mhartid = CONFIG.CSRS.CPU_ID;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//MSTATUS
|
||||
|
@ -185,14 +189,14 @@ module csr_regs
|
|||
//Virtualization support: TSR, TW, TVM unused
|
||||
//Extension context status: SD, FS, XS unused
|
||||
const mstatus_t mstatus_mask =
|
||||
'{default:0, mprv:(ENABLE_U_MODE | ENABLE_S_MODE), mxr:(ENABLE_S_MODE),
|
||||
sum:(ENABLE_U_MODE & ENABLE_S_MODE), mpp:'1, spp:(ENABLE_S_MODE),
|
||||
mpie:1, spie:(ENABLE_S_MODE), mie:1, sie:(ENABLE_S_MODE)};
|
||||
'{default:0, mprv:(CONFIG.INCLUDE_U_MODE | CONFIG.INCLUDE_S_MODE), mxr:(CONFIG.INCLUDE_S_MODE),
|
||||
sum:(CONFIG.INCLUDE_U_MODE & CONFIG.INCLUDE_S_MODE), mpp:'1, spp:(CONFIG.INCLUDE_S_MODE),
|
||||
mpie:1, spie:(CONFIG.INCLUDE_S_MODE), mie:1, sie:(CONFIG.INCLUDE_S_MODE)};
|
||||
|
||||
const mstatus_t sstatus_mask = '{default:0, mxr:1, sum:1, spp:1, spie:1, sie:1};
|
||||
|
||||
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
generate if (CONFIG.INCLUDE_M_MODE) begin
|
||||
|
||||
privilege_t trap_return_privilege_level;
|
||||
privilege_t exception_privilege_level;
|
||||
|
@ -207,7 +211,7 @@ generate if (ENABLE_M_MODE) begin
|
|||
always_comb begin
|
||||
exception_privilege_level = MACHINE_PRIVILEGE;
|
||||
interrupt_privilege_level = MACHINE_PRIVILEGE;
|
||||
if (ENABLE_S_MODE && privilege_level inside {SUPERVISOR_PRIVILEGE, USER_PRIVILEGE}) begin
|
||||
if (CONFIG.INCLUDE_S_MODE && privilege_level inside {SUPERVISOR_PRIVILEGE, USER_PRIVILEGE}) begin
|
||||
if (medeleg[gc_exception.code])
|
||||
exception_privilege_level = SUPERVISOR_PRIVILEGE;
|
||||
if (mideleg[gc_exception.code])
|
||||
|
@ -265,7 +269,7 @@ generate if (ENABLE_M_MODE) begin
|
|||
end else if (mret) begin
|
||||
mstatus_return.mie = mstatus.mpie;
|
||||
mstatus_return.mpie = 1;
|
||||
mstatus_return.mpp = ENABLE_U_MODE ? USER_PRIVILEGE : MACHINE_PRIVILEGE;
|
||||
mstatus_return.mpp = CONFIG.INCLUDE_U_MODE ? USER_PRIVILEGE : MACHINE_PRIVILEGE;
|
||||
if (mstatus.mpp != MACHINE_PRIVILEGE)
|
||||
mstatus_return.mprv = 0;
|
||||
end
|
||||
|
@ -307,7 +311,7 @@ generate if (ENABLE_M_MODE) begin
|
|||
logic [31:0] medeleg_mask;
|
||||
always_comb begin
|
||||
medeleg_mask = 0;
|
||||
if (ENABLE_S_MODE) begin
|
||||
if (CONFIG.INCLUDE_S_MODE) begin
|
||||
medeleg_mask[INST_ADDR_MISSALIGNED] = 1;
|
||||
medeleg_mask[INST_ACCESS_FAULT] = 1;
|
||||
medeleg_mask[ILLEGAL_INST] = 1;
|
||||
|
@ -335,10 +339,10 @@ generate if (ENABLE_M_MODE) begin
|
|||
logic [31:0] mideleg_mask;
|
||||
always_comb begin
|
||||
mideleg_mask = 0;
|
||||
if (ENABLE_S_MODE) begin
|
||||
mideleg_mask[S_SOFTWARE_INTERRUPT] = ENABLE_S_MODE;
|
||||
mideleg_mask[S_TIMER_INTERRUPT] = ENABLE_S_MODE;
|
||||
mideleg_mask[S_EXTERNAL_INTERRUPT] = ENABLE_S_MODE;
|
||||
if (CONFIG.INCLUDE_S_MODE) begin
|
||||
mideleg_mask[S_SOFTWARE_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
|
||||
mideleg_mask[S_TIMER_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
|
||||
mideleg_mask[S_EXTERNAL_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
|
@ -350,7 +354,7 @@ generate if (ENABLE_M_MODE) begin
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//MIP
|
||||
assign mip_mask = '{default:0, meip:1, seip:ENABLE_S_MODE, mtip:1, stip:ENABLE_S_MODE, msip:1, ssip:ENABLE_S_MODE};
|
||||
assign mip_mask = '{default:0, meip:1, seip:CONFIG.INCLUDE_S_MODE, mtip:1, stip:CONFIG.INCLUDE_S_MODE, msip:1, ssip:CONFIG.INCLUDE_S_MODE};
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
mip <= 0;
|
||||
|
@ -360,7 +364,7 @@ generate if (ENABLE_M_MODE) begin
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//MIE
|
||||
assign mie_mask = '{default:0, meie:1, seie:ENABLE_S_MODE, mtie:1, stie:ENABLE_S_MODE, msie:1, ssie:ENABLE_S_MODE};
|
||||
assign mie_mask = '{default:0, meie:1, seie:CONFIG.INCLUDE_S_MODE, mtie:1, stie:CONFIG.INCLUDE_S_MODE, msie:1, ssie:CONFIG.INCLUDE_S_MODE};
|
||||
assign sie_mask = '{default:0, seie:1, stie:1, ssie:1};
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
|
@ -389,40 +393,40 @@ generate if (ENABLE_M_MODE) begin
|
|||
//As the exception and interrupts codes are sparsely populated,
|
||||
//to ensure that only legal values are written, a ROM lookup
|
||||
//is used to validate the CSR write operation
|
||||
logic MCAUSE_EXCEPTION_MASKING_ROM [2**ECODE_W];
|
||||
logic MCAUSE_INTERRUPT_MASKING_ROM [2**ECODE_W];
|
||||
logic MCAINCLUDE_EXCEPTION_MASKING_ROM [2**ECODE_W];
|
||||
logic MCAINCLUDE_INTERRUPT_MASKING_ROM [2**ECODE_W];
|
||||
always_comb begin
|
||||
MCAUSE_EXCEPTION_MASKING_ROM = '{default: 0};
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[INST_ADDR_MISSALIGNED] = 1;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[INST_ACCESS_FAULT] = ENABLE_S_MODE;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[ILLEGAL_INST] = 1;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[BREAK] = 1;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[LOAD_ADDR_MISSALIGNED] = 1;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[LOAD_FAULT] = ENABLE_S_MODE;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[STORE_AMO_ADDR_MISSALIGNED] = 1;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[STORE_AMO_FAULT] = ENABLE_S_MODE;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[ECALL_U] = ENABLE_S_MODE;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[ECALL_S] = ENABLE_S_MODE;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[ECALL_M] = 1;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[INST_PAGE_FAULT] = ENABLE_S_MODE;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[LOAD_PAGE_FAULT] = ENABLE_S_MODE;
|
||||
MCAUSE_EXCEPTION_MASKING_ROM[STORE_OR_AMO_PAGE_FAULT] = ENABLE_S_MODE;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM = '{default: 0};
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[INST_ADDR_MISSALIGNED] = 1;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[INST_ACCESS_FAULT] = CONFIG.INCLUDE_S_MODE;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[ILLEGAL_INST] = 1;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[BREAK] = 1;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[LOAD_ADDR_MISSALIGNED] = 1;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[LOAD_FAULT] = CONFIG.INCLUDE_S_MODE;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[STORE_AMO_ADDR_MISSALIGNED] = 1;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[STORE_AMO_FAULT] = CONFIG.INCLUDE_S_MODE;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[ECALL_U] = CONFIG.INCLUDE_S_MODE;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[ECALL_S] = CONFIG.INCLUDE_S_MODE;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[ECALL_M] = 1;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[INST_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[LOAD_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE;
|
||||
MCAINCLUDE_EXCEPTION_MASKING_ROM[STORE_OR_AMO_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE;
|
||||
|
||||
MCAUSE_INTERRUPT_MASKING_ROM = '{default: 0};
|
||||
MCAUSE_INTERRUPT_MASKING_ROM[S_SOFTWARE_INTERRUPT] = ENABLE_S_MODE;
|
||||
MCAUSE_INTERRUPT_MASKING_ROM[M_SOFTWARE_INTERRUPT] = 1;
|
||||
MCAUSE_INTERRUPT_MASKING_ROM[S_TIMER_INTERRUPT] = ENABLE_S_MODE;
|
||||
MCAUSE_INTERRUPT_MASKING_ROM[M_TIMER_INTERRUPT] = 1;
|
||||
MCAUSE_INTERRUPT_MASKING_ROM[S_EXTERNAL_INTERRUPT] = ENABLE_S_MODE;
|
||||
MCAUSE_INTERRUPT_MASKING_ROM[M_EXTERNAL_INTERRUPT] = 1;
|
||||
MCAINCLUDE_INTERRUPT_MASKING_ROM = '{default: 0};
|
||||
MCAINCLUDE_INTERRUPT_MASKING_ROM[S_SOFTWARE_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
|
||||
MCAINCLUDE_INTERRUPT_MASKING_ROM[M_SOFTWARE_INTERRUPT] = 1;
|
||||
MCAINCLUDE_INTERRUPT_MASKING_ROM[S_TIMER_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
|
||||
MCAINCLUDE_INTERRUPT_MASKING_ROM[M_TIMER_INTERRUPT] = 1;
|
||||
MCAINCLUDE_INTERRUPT_MASKING_ROM[S_EXTERNAL_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
|
||||
MCAINCLUDE_INTERRUPT_MASKING_ROM[M_EXTERNAL_INTERRUPT] = 1;
|
||||
end
|
||||
|
||||
logic mcause_write_valid;
|
||||
always_comb begin
|
||||
if (updated_csr[XLEN-1]) //interrupt
|
||||
mcause_write_valid = MCAUSE_INTERRUPT_MASKING_ROM[updated_csr[ECODE_W-1:0]];
|
||||
mcause_write_valid = MCAINCLUDE_INTERRUPT_MASKING_ROM[updated_csr[ECODE_W-1:0]];
|
||||
else
|
||||
mcause_write_valid = MCAUSE_EXCEPTION_MASKING_ROM[updated_csr[ECODE_W-1:0]];
|
||||
mcause_write_valid = MCAINCLUDE_EXCEPTION_MASKING_ROM[updated_csr[ECODE_W-1:0]];
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
|
@ -474,11 +478,11 @@ endgenerate
|
|||
//BEGIN OF SUPERVISOR REGS
|
||||
////////////////////////////////////////////////////
|
||||
//TLB status --- used to mux physical/virtual address
|
||||
assign tlb_on = ENABLE_S_MODE & satp.mode;
|
||||
assign tlb_on = CONFIG.INCLUDE_S_MODE & satp.mode;
|
||||
assign asid = satp.asid;
|
||||
//******************
|
||||
|
||||
generate if (ENABLE_S_MODE) begin
|
||||
generate if (CONFIG.INCLUDE_S_MODE) begin
|
||||
////////////////////////////////////////////////////
|
||||
//MMU interface
|
||||
assign immu.mxr = mstatus.mxr;
|
||||
|
@ -498,7 +502,7 @@ generate if (ENABLE_S_MODE) begin
|
|||
logic [31:0] stvec_mask = '1;
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
stvec <= {RESET_VEC[XLEN-1:2], 2'b00};
|
||||
stvec <= {CONFIG.CSRS.RESET_VEC[XLEN-1:2], 2'b00};
|
||||
else if (swrite_decoder[STVEC[7:0]])
|
||||
stvec <= (updated_csr & stvec_mask);
|
||||
end
|
||||
|
@ -525,7 +529,7 @@ endgenerate
|
|||
////////////////////////////////////////////////////
|
||||
//Timers and Counters
|
||||
//Register increment for instructions completed
|
||||
logic[COUNTER_W-1:0] mcycle_next;
|
||||
logic[CONFIG.CSRS.COUNTER_W-1:0] mcycle_next;
|
||||
assign mcycle_next = mcycle + 1;
|
||||
|
||||
//As the CSR write takes effect after the instruction has otherwise completed,
|
||||
|
@ -535,23 +539,23 @@ endgenerate
|
|||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
mcycle[31:0] <= 0;
|
||||
mcycle[COUNTER_W-1:32] <= 0;
|
||||
mcycle[CONFIG.CSRS.COUNTER_W-1:32] <= 0;
|
||||
end else begin
|
||||
mcycle[31:0] <= mwrite_decoder[MCYCLE[7:0]] ? updated_csr : mcycle_next[31:0];
|
||||
mcycle[COUNTER_W-1:32] <= mwrite_decoder[MCYCLEH[7:0]] ? updated_csr[COUNTER_W-33:0] : mcycle_next[COUNTER_W-1:32];
|
||||
mcycle[CONFIG.CSRS.COUNTER_W-1:32] <= mwrite_decoder[MCYCLEH[7:0]] ? updated_csr[CONFIG.CSRS.COUNTER_W-33:0] : mcycle_next[CONFIG.CSRS.COUNTER_W-1:32];
|
||||
end
|
||||
end
|
||||
|
||||
logic[COUNTER_W-1:0] minst_ret_next;
|
||||
assign minst_ret_next = minst_ret + COUNTER_W'(retire.count);
|
||||
logic[CONFIG.CSRS.COUNTER_W-1:0] minst_ret_next;
|
||||
assign minst_ret_next = minst_ret + CONFIG.CSRS.COUNTER_W'(retire.count);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
minst_ret[31:0] <= 0;
|
||||
minst_ret[COUNTER_W-1:32] <= 0;
|
||||
minst_ret[CONFIG.CSRS.COUNTER_W-1:32] <= 0;
|
||||
end else begin
|
||||
minst_ret[31:0] <= mwrite_decoder[MINSTRET[7:0]] ? updated_csr : minst_ret_next[31:0];
|
||||
minst_ret[COUNTER_W-1:32] <= mwrite_decoder[MINSTRETH[7:0]] ? updated_csr[COUNTER_W-33:0] : minst_ret_next[COUNTER_W-1:32];
|
||||
minst_ret[CONFIG.CSRS.COUNTER_W-1:32] <= mwrite_decoder[MINSTRETH[7:0]] ? updated_csr[CONFIG.CSRS.COUNTER_W-33:0] : minst_ret_next[CONFIG.CSRS.COUNTER_W-1:32];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -559,51 +563,51 @@ endgenerate
|
|||
invalid_addr = 0;
|
||||
case (csr_addr) inside
|
||||
//Machine info
|
||||
MISA : selected_csr = ENABLE_M_MODE ? misa : 0;
|
||||
MVENDORID : selected_csr = ENABLE_M_MODE ? mvendorid : 0;
|
||||
MARCHID : selected_csr = ENABLE_M_MODE ? marchid : 0;
|
||||
MIMPID : selected_csr = ENABLE_M_MODE ? mimpid : 0;
|
||||
MHARTID : selected_csr = ENABLE_M_MODE ? mhartid : 0;
|
||||
MISA : selected_csr = CONFIG.INCLUDE_M_MODE ? misa : 0;
|
||||
MVENDORID : selected_csr = CONFIG.INCLUDE_M_MODE ? mvendorid : 0;
|
||||
MARCHID : selected_csr = CONFIG.INCLUDE_M_MODE ? marchid : 0;
|
||||
MIMPID : selected_csr = CONFIG.INCLUDE_M_MODE ? mimpid : 0;
|
||||
MHARTID : selected_csr = CONFIG.INCLUDE_M_MODE ? mhartid : 0;
|
||||
//Machine trap setup
|
||||
MSTATUS : selected_csr = ENABLE_M_MODE ? mstatus : 0;
|
||||
MEDELEG : selected_csr = ENABLE_M_MODE ? medeleg : 0;
|
||||
MIDELEG : selected_csr = ENABLE_M_MODE ? mideleg : 0;
|
||||
MIE : selected_csr = ENABLE_M_MODE ? mie_reg : 0;
|
||||
MTVEC : selected_csr = ENABLE_M_MODE ? mtvec : 0;
|
||||
MSTATUS : selected_csr = CONFIG.INCLUDE_M_MODE ? mstatus : 0;
|
||||
MEDELEG : selected_csr = CONFIG.INCLUDE_M_MODE ? medeleg : 0;
|
||||
MIDELEG : selected_csr = CONFIG.INCLUDE_M_MODE ? mideleg : 0;
|
||||
MIE : selected_csr = CONFIG.INCLUDE_M_MODE ? mie_reg : 0;
|
||||
MTVEC : selected_csr = CONFIG.INCLUDE_M_MODE ? mtvec : 0;
|
||||
MCOUNTEREN : selected_csr = 0;
|
||||
//Machine trap handling
|
||||
MSCRATCH : selected_csr = ENABLE_M_MODE ? scratch_out : 0;
|
||||
MEPC : selected_csr = ENABLE_M_MODE ? mepc : 0;
|
||||
MCAUSE : selected_csr = ENABLE_M_MODE ? mcause : 0;
|
||||
MTVAL : selected_csr = ENABLE_M_MODE ? mtval : 0;
|
||||
MIP : selected_csr = ENABLE_M_MODE ? mip : 0;
|
||||
MSCRATCH : selected_csr = CONFIG.INCLUDE_M_MODE ? scratch_out : 0;
|
||||
MEPC : selected_csr = CONFIG.INCLUDE_M_MODE ? mepc : 0;
|
||||
MCAUSE : selected_csr = CONFIG.INCLUDE_M_MODE ? mcause : 0;
|
||||
MTVAL : selected_csr = CONFIG.INCLUDE_M_MODE ? mtval : 0;
|
||||
MIP : selected_csr = CONFIG.INCLUDE_M_MODE ? mip : 0;
|
||||
//Machine Memory Protection
|
||||
[12'h3EF : 12'h3A0] : selected_csr = 0;
|
||||
//Machine Timers and Counters
|
||||
MCYCLE : selected_csr = ENABLE_M_MODE ? mcycle[XLEN-1:0] : 0;
|
||||
MINSTRET : selected_csr = ENABLE_M_MODE ? minst_ret[XLEN-1:0] : 0;
|
||||
MCYCLE : selected_csr = CONFIG.INCLUDE_M_MODE ? mcycle[XLEN-1:0] : 0;
|
||||
MINSTRET : selected_csr = CONFIG.INCLUDE_M_MODE ? minst_ret[XLEN-1:0] : 0;
|
||||
[12'hB03 : 12'hB1F] : selected_csr = 0;
|
||||
MCYCLEH : selected_csr = ENABLE_M_MODE ? 32'(mcycle[COUNTER_W-1:XLEN]) : 0;
|
||||
MINSTRETH : selected_csr = ENABLE_M_MODE ? 32'(minst_ret[COUNTER_W-1:XLEN]) : 0;
|
||||
MCYCLEH : selected_csr = CONFIG.INCLUDE_M_MODE ? 32'(mcycle[CONFIG.CSRS.COUNTER_W-1:XLEN]) : 0;
|
||||
MINSTRETH : selected_csr = CONFIG.INCLUDE_M_MODE ? 32'(minst_ret[CONFIG.CSRS.COUNTER_W-1:XLEN]) : 0;
|
||||
[12'hB83 : 12'hB9F] : selected_csr = 0;
|
||||
//Machine Counter Setup
|
||||
[12'h320 : 12'h33F] : selected_csr = 0;
|
||||
|
||||
//Supervisor Trap Setup
|
||||
SSTATUS : selected_csr = ENABLE_S_MODE ? (mstatus & sstatus_mask) : '0;
|
||||
SSTATUS : selected_csr = CONFIG.INCLUDE_S_MODE ? (mstatus & sstatus_mask) : '0;
|
||||
SEDELEG : selected_csr = 0; //No user-level interrupts/exception handling
|
||||
SIDELEG : selected_csr = 0;
|
||||
SIE : selected_csr = ENABLE_S_MODE ? (mie_reg & sie_mask) : '0;
|
||||
STVEC : selected_csr = ENABLE_S_MODE ? stvec : '0;
|
||||
SIE : selected_csr = CONFIG.INCLUDE_S_MODE ? (mie_reg & sie_mask) : '0;
|
||||
STVEC : selected_csr = CONFIG.INCLUDE_S_MODE ? stvec : '0;
|
||||
SCOUNTEREN : selected_csr = 0;
|
||||
//Supervisor trap handling
|
||||
SSCRATCH : selected_csr = ENABLE_S_MODE ? scratch_out : '0;
|
||||
SEPC : selected_csr = ENABLE_S_MODE ? scratch_out : '0;
|
||||
SCAUSE : selected_csr = ENABLE_S_MODE ? scratch_out : '0;
|
||||
STVAL : selected_csr = ENABLE_S_MODE ? scratch_out : '0;
|
||||
SIP : selected_csr = ENABLE_S_MODE ? (mip & sip_mask) : '0;
|
||||
SSCRATCH : selected_csr = CONFIG.INCLUDE_S_MODE ? scratch_out : '0;
|
||||
SEPC : selected_csr = CONFIG.INCLUDE_S_MODE ? scratch_out : '0;
|
||||
SCAUSE : selected_csr = CONFIG.INCLUDE_S_MODE ? scratch_out : '0;
|
||||
STVAL : selected_csr = CONFIG.INCLUDE_S_MODE ? scratch_out : '0;
|
||||
SIP : selected_csr = CONFIG.INCLUDE_S_MODE ? (mip & sip_mask) : '0;
|
||||
//Supervisor Protection and Translation
|
||||
SATP : selected_csr = ENABLE_S_MODE ? satp : '0;
|
||||
SATP : selected_csr = CONFIG.INCLUDE_S_MODE ? satp : '0;
|
||||
|
||||
//User status
|
||||
//Floating point
|
||||
|
@ -615,9 +619,9 @@ endgenerate
|
|||
TIME : selected_csr = mcycle[XLEN-1:0];
|
||||
INSTRET : selected_csr = minst_ret[XLEN-1:0];
|
||||
[12'hC03 : 12'hC1F] : selected_csr = 0;
|
||||
CYCLEH : selected_csr = 32'(mcycle[COUNTER_W-1:XLEN]);
|
||||
TIMEH : selected_csr = 32'(mcycle[COUNTER_W-1:XLEN]);
|
||||
INSTRETH : selected_csr = 32'(minst_ret[COUNTER_W-1:XLEN]);
|
||||
CYCLEH : selected_csr = 32'(mcycle[CONFIG.CSRS.COUNTER_W-1:XLEN]);
|
||||
TIMEH : selected_csr = 32'(mcycle[CONFIG.CSRS.COUNTER_W-1:XLEN]);
|
||||
INSTRETH : selected_csr = 32'(minst_ret[CONFIG.CSRS.COUNTER_W-1:XLEN]);
|
||||
[12'hC83 : 12'hC9F] : selected_csr = 0;
|
||||
|
||||
default : begin selected_csr = 0; invalid_addr = 1; end
|
||||
|
|
|
@ -25,7 +25,11 @@ module dcache
|
|||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -43,26 +47,27 @@ module dcache
|
|||
ls_sub_unit_interface.sub_unit ls
|
||||
);
|
||||
|
||||
localparam DCACHE_SIZE_IN_WORDS = DCACHE_LINES*DCACHE_LINE_W*DCACHE_WAYS;
|
||||
localparam DCACHE_SIZE_IN_WORDS = CONFIG.DCACHE.LINES*CONFIG.DCACHE.LINE_W*CONFIG.DCACHE.WAYS;
|
||||
localparam derived_cache_config_t SCONFIG = get_derived_cache_params(CONFIG, CONFIG.DCACHE, CONFIG.DCACHE_ADDR);
|
||||
|
||||
logic [$clog2(DCACHE_SIZE_IN_WORDS)-1:0] data_bank_addr_a;
|
||||
logic [$clog2(DCACHE_SIZE_IN_WORDS)-1:0] data_bank_addr_b;
|
||||
|
||||
logic tag_hit;
|
||||
logic [DCACHE_WAYS-1:0] tag_hit_way;
|
||||
logic [CONFIG.DCACHE.WAYS-1:0] tag_hit_way;
|
||||
|
||||
logic [$clog2(DCACHE_WAYS)-1:0] tag_hit_way_int;
|
||||
logic [$clog2(CONFIG.DCACHE.WAYS)-1:0] tag_hit_way_int;
|
||||
|
||||
logic tag_update;
|
||||
logic [DCACHE_WAYS-1:0] tag_update_way;
|
||||
logic [DCACHE_WAYS-1:0] replacement_way;
|
||||
logic [CONFIG.DCACHE.WAYS-1:0] tag_update_way;
|
||||
logic [CONFIG.DCACHE.WAYS-1:0] replacement_way;
|
||||
|
||||
logic [$clog2(DCACHE_WAYS)-1:0] replacement_way_int;
|
||||
logic [$clog2(DCACHE_WAYS)-1:0] tag_update_way_int;
|
||||
logic [$clog2(CONFIG.DCACHE.WAYS)-1:0] replacement_way_int;
|
||||
logic [$clog2(CONFIG.DCACHE.WAYS)-1:0] tag_update_way_int;
|
||||
|
||||
logic [DCACHE_SUB_LINE_ADDR_W-1:0] word_count;
|
||||
logic [DCACHE_SUB_LINE_ADDR_W-1:0] sc_write_index;
|
||||
logic [DCACHE_SUB_LINE_ADDR_W-1:0] update_word_index;
|
||||
logic [SCONFIG.SUB_LINE_ADDR_W-1:0] word_count;
|
||||
logic [SCONFIG.SUB_LINE_ADDR_W-1:0] sc_write_index;
|
||||
logic [SCONFIG.SUB_LINE_ADDR_W-1:0] update_word_index;
|
||||
|
||||
logic line_complete;
|
||||
logic reservation;
|
||||
|
@ -148,7 +153,7 @@ module dcache
|
|||
assign l1_request.data = stage2_data;
|
||||
assign l1_request.rnw = ~stage2_store;
|
||||
assign l1_request.be = stage2_be;
|
||||
assign l1_request.size = stage2_load ? (DCACHE_LINE_W-1) : 0;//LR and AMO ops are included in load
|
||||
assign l1_request.size = stage2_load ? 5'(CONFIG.DCACHE.LINE_W-1) : 0;//LR and AMO ops are included in load
|
||||
assign l1_request.is_amo = (stage2_amo.is_amo | stage2_amo.is_lr | stage2_amo.is_sc);
|
||||
assign l1_request.amo = stage2_amo.op;
|
||||
|
||||
|
@ -158,7 +163,7 @@ module dcache
|
|||
else if (l1_response.data_valid)
|
||||
word_count <= word_count + 1;
|
||||
end
|
||||
assign is_target_word = (stage2_addr[DCACHE_SUB_LINE_ADDR_W+1:2] == word_count);
|
||||
assign is_target_word = (stage2_addr[SCONFIG.SUB_LINE_ADDR_W+1:2] == word_count);
|
||||
|
||||
assign new_arb_request = second_cycle & (~(tag_hit & read_hit_allowed) | ~dcache_on);
|
||||
always_ff @ (posedge clk) begin
|
||||
|
@ -173,7 +178,7 @@ module dcache
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Replacement policy (free runing one-hot cycler, i.e. pseudo random)
|
||||
cycler #(DCACHE_WAYS) replacement_policy (
|
||||
cycler #(CONFIG.DCACHE.WAYS) replacement_policy (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.en (1'b1),
|
||||
|
@ -181,13 +186,13 @@ module dcache
|
|||
);
|
||||
|
||||
//One-hot tag hit / update logic to binary int
|
||||
one_hot_to_integer #(DCACHE_WAYS) hit_way_conv (
|
||||
one_hot_to_integer #(CONFIG.DCACHE.WAYS) hit_way_conv (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.one_hot(tag_hit_way),
|
||||
.int_out(tag_hit_way_int)
|
||||
);
|
||||
one_hot_to_integer #(DCACHE_WAYS) update_way_conv (
|
||||
one_hot_to_integer #(CONFIG.DCACHE.WAYS) update_way_conv (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.one_hot (replacement_way),
|
||||
|
@ -207,20 +212,21 @@ module dcache
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Tag banks
|
||||
dtag_banks dcache_tag_banks (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.stage1_addr (ls_inputs.addr),
|
||||
.stage2_addr (stage2_addr),
|
||||
.inv_addr ({l1_response.inv_addr, 2'b00}),
|
||||
.update_way (tag_update_way),
|
||||
.update (tag_update),
|
||||
.stage1_adv (ls.new_request),
|
||||
.stage1_inv (1'b0),//For software invalidation
|
||||
.extern_inv (l1_response.inv_valid),
|
||||
.extern_inv_complete (l1_response.inv_ack),
|
||||
.tag_hit (tag_hit),
|
||||
.tag_hit_way (tag_hit_way)
|
||||
dtag_banks #(.CONFIG(CONFIG), .SCONFIG(SCONFIG))
|
||||
dcache_tag_banks (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.stage1_addr (ls_inputs.addr),
|
||||
.stage2_addr (stage2_addr),
|
||||
.inv_addr ({l1_response.inv_addr, 2'b00}),
|
||||
.update_way (tag_update_way),
|
||||
.update (tag_update),
|
||||
.stage1_adv (ls.new_request),
|
||||
.stage1_inv (1'b0),//For software invalidation
|
||||
.extern_inv (l1_response.inv_valid),
|
||||
.extern_inv_complete (l1_response.inv_ack),
|
||||
.tag_hit (tag_hit),
|
||||
.tag_hit_way (tag_hit_way)
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -233,10 +239,10 @@ module dcache
|
|||
assign amo_alu_inputs.rs2 = amo_rs2;
|
||||
assign amo_alu_inputs.op = stage2_amo.op;
|
||||
|
||||
generate if (USE_AMO)
|
||||
generate if (CONFIG.INCLUDE_AMO)
|
||||
amo_alu amo_unit (
|
||||
.amo_alu_inputs (amo_alu_inputs),
|
||||
.result (amo_result)
|
||||
.result (amo_result)
|
||||
);
|
||||
endgenerate
|
||||
|
||||
|
@ -249,7 +255,7 @@ module dcache
|
|||
new_line_data = l1_response.data;
|
||||
end
|
||||
|
||||
assign sc_write_index = stage2_addr[DCACHE_SUB_LINE_ADDR_W+1:2];
|
||||
assign sc_write_index = stage2_addr[SCONFIG.SUB_LINE_ADDR_W+1:2];
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -259,8 +265,8 @@ module dcache
|
|||
assign write_hit_be = stage2_be & {4{tag_hit}};
|
||||
assign update_word_index = stage2_amo.is_sc ? sc_write_index : word_count;
|
||||
|
||||
assign data_bank_addr_a = {tag_hit_way_int, stage2_addr[DCACHE_LINE_ADDR_W+DCACHE_SUB_LINE_ADDR_W+2-1:2]};
|
||||
assign data_bank_addr_b = {tag_update_way_int, stage2_addr[DCACHE_LINE_ADDR_W+DCACHE_SUB_LINE_ADDR_W+2-1:DCACHE_SUB_LINE_ADDR_W+2], update_word_index};
|
||||
assign data_bank_addr_a = {tag_hit_way_int, stage2_addr[SCONFIG.LINE_ADDR_W+SCONFIG.SUB_LINE_ADDR_W+2-1:2]};
|
||||
assign data_bank_addr_b = {tag_update_way_int, stage2_addr[SCONFIG.LINE_ADDR_W+SCONFIG.SUB_LINE_ADDR_W+2-1:SCONFIG.SUB_LINE_ADDR_W+2], update_word_index};
|
||||
|
||||
ddata_bank #(.LINES(DCACHE_SIZE_IN_WORDS)) data_bank (
|
||||
.clk(clk),
|
||||
|
@ -287,7 +293,7 @@ module dcache
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Pipeline Advancement
|
||||
assign line_complete = (l1_response.data_valid && (word_count == $clog2(DCACHE_LINE_W)'(DCACHE_LINE_W-1))); //covers load, LR, AMO
|
||||
assign line_complete = (l1_response.data_valid && (word_count == $clog2(CONFIG.DCACHE.LINE_W)'(CONFIG.DCACHE.LINE_W-1))); //covers load, LR, AMO
|
||||
assign store_complete = l1_request.ack & stage2_store & ~stage2_amo.is_sc;
|
||||
|
||||
//read miss complete includes store conditional complete
|
||||
|
|
|
@ -25,7 +25,13 @@ module decode_and_issue
|
|||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG,
|
||||
parameter NUM_UNITS = 5,
|
||||
parameter unit_id_param_t UNIT_IDS = EXAMPLE_UNIT_IDS
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -108,8 +114,6 @@ module decode_and_issue
|
|||
logic operands_ready;
|
||||
logic mult_div_op;
|
||||
|
||||
logic [NUM_WB_UNITS-1:0] unit_needed_for_id_gen;
|
||||
logic [WB_UNITS_WIDTH-1:0] unit_needed_for_id_gen_int;
|
||||
logic [NUM_UNITS-1:0] unit_needed;
|
||||
logic [NUM_UNITS-1:0] unit_needed_issue_stage;
|
||||
logic [NUM_UNITS-1:0] unit_ready;
|
||||
|
@ -152,18 +156,18 @@ module decode_and_issue
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit Determination
|
||||
assign unit_needed[BRANCH_UNIT_ID] = opcode_trim inside {BRANCH_T, JAL_T, JALR_T};
|
||||
assign unit_needed[ALU_UNIT_ID] = (opcode_trim inside {ARITH_T, ARITH_IMM_T, AUIPC_T, LUI_T, JAL_T, JALR_T}) & ~mult_div_op;
|
||||
assign unit_needed[LS_UNIT_ID] = opcode_trim inside {LOAD_T, STORE_T, AMO_T};
|
||||
assign unit_needed[GC_UNIT_ID] = opcode_trim inside {SYSTEM_T, FENCE_T};
|
||||
assign unit_needed[UNIT_IDS.BR] = opcode_trim inside {BRANCH_T, JAL_T, JALR_T};
|
||||
assign unit_needed[UNIT_IDS.ALU] = (opcode_trim inside {ARITH_T, ARITH_IMM_T, AUIPC_T, LUI_T, JAL_T, JALR_T}) & ~mult_div_op;
|
||||
assign unit_needed[UNIT_IDS.LS] = opcode_trim inside {LOAD_T, STORE_T, AMO_T};
|
||||
assign unit_needed[UNIT_IDS.CSR] = opcode_trim inside {SYSTEM_T, FENCE_T};
|
||||
|
||||
assign mult_div_op = (opcode_trim == ARITH_T) && decode.instruction[25];
|
||||
generate if (USE_MUL)
|
||||
assign unit_needed[MUL_UNIT_ID] = mult_div_op && ~fn3[2];
|
||||
generate if (CONFIG.INCLUDE_MUL)
|
||||
assign unit_needed[UNIT_IDS.MUL] = mult_div_op && ~fn3[2];
|
||||
endgenerate
|
||||
|
||||
generate if (USE_DIV)
|
||||
assign unit_needed[DIV_UNIT_ID] = mult_div_op && fn3[2];
|
||||
generate if (CONFIG.INCLUDE_DIV)
|
||||
assign unit_needed[UNIT_IDS.DIV] = mult_div_op && fn3[2];
|
||||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -172,7 +176,7 @@ module decode_and_issue
|
|||
assign renamer.rs_addr[RS1] = rs1_addr;
|
||||
assign renamer.rs_addr[RS2] = rs2_addr;
|
||||
assign renamer.uses_rd = uses_rd;
|
||||
assign renamer.rd_wb_group = ~unit_needed[ALU_UNIT_ID];//TODO: automate generation of wb group logic
|
||||
assign renamer.rd_wb_group = ~unit_needed[UNIT_IDS.ALU];//TODO: automate generation of wb group logic
|
||||
assign renamer.id = decode.id;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -183,6 +187,8 @@ module decode_and_issue
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Issue
|
||||
logic [REGFILE_READ_PORTS-1:0][$clog2(CONFIG.NUM_WB_GROUPS)-1:0] issue_rs_wb_group;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue_stage_ready) begin
|
||||
issue.pc <= decode.pc;
|
||||
|
@ -194,10 +200,10 @@ module decode_and_issue
|
|||
issue.rs_addr[RS2] <= rs2_addr;
|
||||
issue.phys_rs_addr[RS1] <= renamer.phys_rs_addr[RS1];
|
||||
issue.phys_rs_addr[RS2] <= renamer.phys_rs_addr[RS2];
|
||||
issue.rs_wb_group <= renamer.rs_wb_group;
|
||||
issue_rs_wb_group <= renamer.rs_wb_group;
|
||||
issue.rd_addr <= rd_addr;
|
||||
issue.phys_rd_addr <= renamer.phys_rd_addr;
|
||||
issue.rd_wb_group <= ~unit_needed[ALU_UNIT_ID];
|
||||
issue.is_multicycle <= ~unit_needed[UNIT_IDS.ALU];
|
||||
issue.id <= decode.id;
|
||||
issue.uses_rs1 <= uses_rs1;
|
||||
issue.uses_rs2 <= uses_rs2;
|
||||
|
@ -241,9 +247,9 @@ module decode_and_issue
|
|||
assign rf.phys_rs_addr[RS1] = issue.phys_rs_addr[RS1];
|
||||
assign rf.phys_rs_addr[RS2] = issue.phys_rs_addr[RS2];
|
||||
assign rf.phys_rd_addr = issue.phys_rd_addr;
|
||||
assign rf.rs_wb_group[RS1] = issue.rs_wb_group[RS1];
|
||||
assign rf.rs_wb_group[RS2] = issue.rs_wb_group[RS2];
|
||||
assign rf.rd_wb_group = issue.rd_wb_group;
|
||||
assign rf.rs_wb_group[RS1] = issue_rs_wb_group[RS1];
|
||||
assign rf.rs_wb_group[RS2] = issue_rs_wb_group[RS2];
|
||||
assign rf.rd_wb_group = issue.is_multicycle;
|
||||
assign rf.issued = instruction_issued_with_rd;
|
||||
////////////////////////////////////////////////////
|
||||
//ALU unit inputs
|
||||
|
@ -319,12 +325,12 @@ module decode_and_issue
|
|||
logic load_reserve;
|
||||
logic [4:0] amo_type;
|
||||
|
||||
assign amo_op = USE_AMO ? (opcode_trim == AMO_T) : 1'b0;
|
||||
assign amo_op = CONFIG.INCLUDE_AMO ? (opcode_trim == AMO_T) : 1'b0;
|
||||
assign amo_type = decode.instruction[31:27];
|
||||
assign store_conditional = (amo_type == AMO_SC);
|
||||
assign load_reserve = (amo_type == AMO_LR);
|
||||
|
||||
generate if (USE_AMO) begin
|
||||
generate if (CONFIG.INCLUDE_AMO) begin
|
||||
assign ls_inputs.amo.is_lr = load_reserve;
|
||||
assign ls_inputs.amo.is_sc = store_conditional;
|
||||
assign ls_inputs.amo.is_amo = amo_op & ~(load_reserve | store_conditional);
|
||||
|
@ -459,12 +465,12 @@ module decode_and_issue
|
|||
always_comb begin
|
||||
sys_op_match = '0;
|
||||
case (decode.instruction[31:20]) inside
|
||||
ECALL_imm : sys_op_match[ECALL_i] = ENABLE_M_MODE;
|
||||
EBREAK_imm : sys_op_match[EBREAK_i] = ENABLE_M_MODE;
|
||||
URET_imm : sys_op_match[URET_i] = ENABLE_U_MODE;
|
||||
SRET_imm : sys_op_match[SRET_i] = ENABLE_S_MODE;
|
||||
MRET_imm : sys_op_match[MRET_i] = ENABLE_M_MODE;
|
||||
SFENCE_imm : sys_op_match[SFENCE_i] = ENABLE_S_MODE;
|
||||
ECALL_imm : sys_op_match[ECALL_i] = CONFIG.INCLUDE_M_MODE;
|
||||
EBREAK_imm : sys_op_match[EBREAK_i] = CONFIG.INCLUDE_M_MODE;
|
||||
URET_imm : sys_op_match[URET_i] = CONFIG.INCLUDE_U_MODE;
|
||||
SRET_imm : sys_op_match[SRET_i] = CONFIG.INCLUDE_S_MODE;
|
||||
MRET_imm : sys_op_match[MRET_i] = CONFIG.INCLUDE_M_MODE;
|
||||
SFENCE_imm : sys_op_match[SFENCE_i] = CONFIG.INCLUDE_S_MODE;
|
||||
default : sys_op_match = '0;
|
||||
endcase
|
||||
end
|
||||
|
@ -476,7 +482,7 @@ module decode_and_issue
|
|||
is_ecall <= environment_op & sys_op_match[ECALL_i];
|
||||
is_ebreak <= environment_op & sys_op_match[EBREAK_i];
|
||||
is_ret <= environment_op & (sys_op_match[URET_i] | sys_op_match[SRET_i] | sys_op_match[MRET_i]);
|
||||
is_fence <= ENABLE_M_MODE && (opcode_trim == FENCE_T) && ~fn3[0];
|
||||
is_fence <= CONFIG.INCLUDE_M_MODE && (opcode_trim == FENCE_T) && ~fn3[0];
|
||||
is_ifence_r <= (opcode_trim == FENCE_T) && fn3[0];
|
||||
potential_flush <= (environment_op | ifence);
|
||||
end
|
||||
|
@ -489,15 +495,15 @@ module decode_and_issue
|
|||
assign gc_inputs.instruction = issue.instruction;
|
||||
assign gc_inputs.is_csr = is_csr_r;
|
||||
assign gc_inputs.is_fence = is_fence;
|
||||
assign gc_inputs.is_i_fence = ENABLE_M_MODE & issue_to[GC_UNIT_ID] & is_ifence_r;
|
||||
assign gc_inputs.is_i_fence = CONFIG.INCLUDE_M_MODE & issue_to[UNIT_IDS.CSR] & is_ifence_r;
|
||||
|
||||
assign gc_inputs.rs1 = rf.data[RS1];
|
||||
assign gc_inputs.rs2 = rf.data[RS2];
|
||||
assign gc_flush_required = ENABLE_M_MODE && issue_to[GC_UNIT_ID] && potential_flush;
|
||||
assign gc_flush_required = CONFIG.INCLUDE_M_MODE && issue_to[UNIT_IDS.CSR] && potential_flush;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Mul unit inputs
|
||||
generate if (USE_MUL) begin
|
||||
generate if (CONFIG.INCLUDE_MUL) begin
|
||||
assign mul_inputs.rs1 = rf.data[RS1];
|
||||
assign mul_inputs.rs2 = rf.data[RS2];
|
||||
assign mul_inputs.op = issue.fn3[1:0];
|
||||
|
@ -505,7 +511,7 @@ module decode_and_issue
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Div unit inputs
|
||||
generate if (USE_DIV) begin
|
||||
generate if (CONFIG.INCLUDE_DIV) begin
|
||||
logic [4:0] prev_div_rs1_addr;
|
||||
logic [4:0] prev_div_rs2_addr;
|
||||
logic prev_div_result_valid;
|
||||
|
@ -513,7 +519,7 @@ module decode_and_issue
|
|||
logic div_op_reuse;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue_to[DIV_UNIT_ID]) begin
|
||||
if (issue_to[UNIT_IDS.DIV]) begin
|
||||
prev_div_rs1_addr <= rs1_addr;
|
||||
prev_div_rs2_addr <= rs2_addr;
|
||||
end
|
||||
|
@ -522,11 +528,11 @@ module decode_and_issue
|
|||
assign div_op_reuse = {prev_div_result_valid, prev_div_rs1_addr, prev_div_rs2_addr} == {1'b1, issue.rs_addr[RS1], issue.rs_addr[RS2]};
|
||||
|
||||
//If current div operation overwrites an input register OR any other instruction overwrites the last div operations input registers
|
||||
assign div_rs_overwrite = (issue.rd_addr == (unit_needed_issue_stage[DIV_UNIT_ID] ? issue.rs_addr[RS1] : prev_div_rs1_addr)) || (issue.rd_addr == (unit_needed_issue_stage[DIV_UNIT_ID] ? issue.rs_addr[RS2] : prev_div_rs2_addr));
|
||||
assign div_rs_overwrite = (issue.rd_addr == (unit_needed_issue_stage[UNIT_IDS.DIV] ? issue.rs_addr[RS1] : prev_div_rs1_addr)) || (issue.rd_addr == (unit_needed_issue_stage[UNIT_IDS.DIV] ? issue.rs_addr[RS2] : prev_div_rs2_addr));
|
||||
|
||||
set_clr_reg_with_rst #(.SET_OVER_CLR(0), .WIDTH(1), .RST_VALUE(0)) prev_div_result_valid_m (
|
||||
.clk, .rst,
|
||||
.set(instruction_issued & unit_needed_issue_stage[DIV_UNIT_ID]),
|
||||
.set(instruction_issued & unit_needed_issue_stage[UNIT_IDS.DIV]),
|
||||
.clr(instruction_issued & issue.uses_rd & div_rs_overwrite),
|
||||
.result(prev_div_result_valid)
|
||||
);
|
||||
|
@ -551,8 +557,9 @@ module decode_and_issue
|
|||
////////////////////////////////////////////////////
|
||||
//Illegal Instruction check
|
||||
logic illegal_instruction_pattern_r;
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
illegal_instruction_checker illegal_op_check (
|
||||
generate if (CONFIG.INCLUDE_M_MODE) begin
|
||||
illegal_instruction_checker # (.CONFIG(CONFIG))
|
||||
illegal_op_check (
|
||||
.instruction(decode.instruction), .illegal_instruction(illegal_instruction_pattern)
|
||||
);
|
||||
always_ff @(posedge clk) begin
|
||||
|
@ -586,10 +593,10 @@ module decode_and_issue
|
|||
assign tr_no_id_stall = (~issue.stage_valid & ~pc_id_available & ~gc_fetch_flush); //All instructions in execution pipeline
|
||||
assign tr_no_instruction_stall = (~tr_no_id_stall & ~issue.stage_valid) | gc_fetch_flush;
|
||||
assign tr_other_stall = issue.stage_valid & ~instruction_issued & ~(tr_operand_stall | tr_unit_stall | tr_no_id_stall | tr_no_instruction_stall);
|
||||
assign tr_branch_operand_stall = tr_operand_stall & unit_needed_issue_stage[BRANCH_UNIT_ID];
|
||||
assign tr_alu_operand_stall = tr_operand_stall & unit_needed_issue_stage[ALU_UNIT_ID] & ~unit_needed_issue_stage[BRANCH_UNIT_ID];
|
||||
assign tr_ls_operand_stall = tr_operand_stall & unit_needed_issue_stage[LS_UNIT_ID];
|
||||
assign tr_div_operand_stall = tr_operand_stall & unit_needed_issue_stage[DIV_UNIT_ID];
|
||||
assign tr_branch_operand_stall = tr_operand_stall & unit_needed_issue_stage[UNIT_IDS.BR];
|
||||
assign tr_alu_operand_stall = tr_operand_stall & unit_needed_issue_stage[UNIT_IDS.ALU] & ~unit_needed_issue_stage[UNIT_IDS.BR];
|
||||
assign tr_ls_operand_stall = tr_operand_stall & unit_needed_issue_stage[UNIT_IDS.LS];
|
||||
assign tr_div_operand_stall = tr_operand_stall & unit_needed_issue_stage[UNIT_IDS.DIV];
|
||||
|
||||
//Instruction Mix
|
||||
always_ff @(posedge clk) begin
|
||||
|
@ -598,8 +605,8 @@ module decode_and_issue
|
|||
tr_branch_or_jump_op <= instruction_issued && (opcode_trim inside {JAL_T, JALR_T, BRANCH_T});
|
||||
tr_load_op <= instruction_issued && (opcode_trim inside {LOAD_T, AMO_T});
|
||||
tr_store_op <= instruction_issued && (opcode_trim inside {STORE_T});
|
||||
tr_mul_op <= instruction_issued && unit_needed_issue_stage[MUL_UNIT_ID];
|
||||
tr_div_op <= instruction_issued && unit_needed_issue_stage[DIV_UNIT_ID];
|
||||
tr_mul_op <= instruction_issued && unit_needed_issue_stage[UNIT_IDS.MUL];
|
||||
tr_div_op <= instruction_issued && unit_needed_issue_stage[UNIT_IDS.DIV];
|
||||
tr_misc_op <= instruction_issued & ~(tr_alu_op | tr_branch_or_jump_op | tr_load_op | tr_store_op | tr_mul_op | tr_div_op);
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,6 +25,11 @@ module dtag_banks
|
|||
import taiga_config::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG,
|
||||
parameter derived_cache_config_t SCONFIG = '{default: 0}
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -33,7 +38,7 @@ module dtag_banks
|
|||
input logic[31:0] stage2_addr,
|
||||
input logic[31:0] inv_addr,
|
||||
|
||||
input logic[DCACHE_WAYS-1:0] update_way,
|
||||
input logic[CONFIG.DCACHE.WAYS-1:0] update_way,
|
||||
input logic update,
|
||||
|
||||
input logic stage1_adv,
|
||||
|
@ -43,36 +48,36 @@ module dtag_banks
|
|||
output logic extern_inv_complete,
|
||||
|
||||
output tag_hit,
|
||||
output logic[DCACHE_WAYS-1:0] tag_hit_way
|
||||
output logic[CONFIG.DCACHE.WAYS-1:0] tag_hit_way
|
||||
);
|
||||
|
||||
typedef struct packed{
|
||||
logic valid;
|
||||
logic [DCACHE_TAG_W-1:0] tag;
|
||||
logic [SCONFIG.TAG_W-1:0] tag;
|
||||
} dtag_entry_t;
|
||||
|
||||
function logic[DCACHE_TAG_W-1:0] getTag(logic[31:0] addr);
|
||||
return addr[2+DCACHE_SUB_LINE_ADDR_W+DCACHE_LINE_ADDR_W +: DCACHE_TAG_W];
|
||||
function logic[SCONFIG.TAG_W-1:0] getTag(logic[31:0] addr);
|
||||
return addr[2+SCONFIG.SUB_LINE_ADDR_W+SCONFIG.LINE_ADDR_W +: SCONFIG.TAG_W];
|
||||
endfunction
|
||||
|
||||
function logic[DCACHE_LINE_ADDR_W-1:0] getLineAddr(logic[31:0] addr);
|
||||
return addr[DCACHE_LINE_ADDR_W + DCACHE_SUB_LINE_ADDR_W + 1 : DCACHE_SUB_LINE_ADDR_W + 2];
|
||||
function logic[SCONFIG.LINE_ADDR_W-1:0] getLineAddr(logic[31:0] addr);
|
||||
return addr[SCONFIG.LINE_ADDR_W + SCONFIG.SUB_LINE_ADDR_W + 1 : SCONFIG.SUB_LINE_ADDR_W + 2];
|
||||
endfunction
|
||||
|
||||
dtag_entry_t tag_line [DCACHE_WAYS - 1:0];
|
||||
dtag_entry_t inv_tag_line [DCACHE_WAYS - 1:0];
|
||||
dtag_entry_t tag_line [CONFIG.DCACHE.WAYS - 1:0];
|
||||
dtag_entry_t inv_tag_line [CONFIG.DCACHE.WAYS - 1:0];
|
||||
|
||||
dtag_entry_t new_tagline;
|
||||
|
||||
logic miss_or_extern_invalidate;
|
||||
logic [DCACHE_WAYS - 1:0] update_tag_way;
|
||||
logic [CONFIG.DCACHE.WAYS - 1:0] update_tag_way;
|
||||
|
||||
logic inv_tags_accessed;
|
||||
|
||||
logic[DCACHE_WAYS-1:0] inv_hit_way;
|
||||
logic[DCACHE_WAYS-1:0] inv_hit_way_r;
|
||||
logic[CONFIG.DCACHE.WAYS-1:0] inv_hit_way;
|
||||
logic[CONFIG.DCACHE.WAYS-1:0] inv_hit_way_r;
|
||||
|
||||
logic [DCACHE_LINE_ADDR_W-1:0] update_port_addr;
|
||||
logic [SCONFIG.LINE_ADDR_W-1:0] update_port_addr;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
|
@ -106,10 +111,10 @@ module dtag_banks
|
|||
assign inv_hit_comparison_tagline.valid = 1;
|
||||
assign inv_hit_comparison_tagline.tag = getTag(inv_addr);
|
||||
|
||||
for (i=0; i < DCACHE_WAYS; i=i+1) begin : dtag_bank_gen
|
||||
for (i=0; i < CONFIG.DCACHE.WAYS; i=i+1) begin : dtag_bank_gen
|
||||
assign update_tag_way[i] = update_way[i] | (inv_hit_way[i] & extern_inv_complete);
|
||||
|
||||
tag_bank #($bits(dtag_entry_t), DCACHE_LINES) dtag_bank (
|
||||
tag_bank #($bits(dtag_entry_t), CONFIG.DCACHE.LINES) dtag_bank (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.en_a (stage1_adv),
|
||||
|
|
104
core/fetch.sv
104
core/fetch.sv
|
@ -26,6 +26,10 @@ module fetch
|
|||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -39,6 +43,7 @@ module fetch
|
|||
input logic [31:0] gc_fetch_pc,
|
||||
|
||||
//ID Support
|
||||
input id_t pc_id,
|
||||
input logic pc_id_available,
|
||||
output logic pc_id_assigned,
|
||||
output logic fetch_complete,
|
||||
|
@ -63,16 +68,18 @@ module fetch
|
|||
output logic tr_early_branch_correction
|
||||
);
|
||||
|
||||
localparam NUM_SUB_UNITS = USE_I_SCRATCH_MEM + USE_ICACHE;
|
||||
localparam NUM_SUB_UNITS = int'(CONFIG.INCLUDE_ILOCAL_MEM) + int'(CONFIG.INCLUDE_ICACHE);
|
||||
localparam NUM_SUB_UNITS_W = (NUM_SUB_UNITS == 1) ? 1 : $clog2(NUM_SUB_UNITS);
|
||||
|
||||
localparam BRAM_ID = 0;
|
||||
localparam ICACHE_ID = USE_I_SCRATCH_MEM;
|
||||
localparam ICACHE_ID = int'(CONFIG.INCLUDE_ILOCAL_MEM);
|
||||
|
||||
localparam NEXT_ID_DEPTH = USE_ICACHE ? 2 : 1;
|
||||
localparam NEXT_ID_DEPTH = CONFIG.INCLUDE_ICACHE ? 2 : 1;
|
||||
|
||||
//Subunit signals
|
||||
fetch_sub_unit_interface fetch_sub[NUM_SUB_UNITS-1:0]();
|
||||
fetch_sub_unit_interface #(.BASE_ADDR(CONFIG.ILOCAL_MEM_ADDR.L), .UPPER_BOUND(CONFIG.ILOCAL_MEM_ADDR.H)) bram();
|
||||
fetch_sub_unit_interface #(.BASE_ADDR(CONFIG.ICACHE_ADDR.L), .UPPER_BOUND(CONFIG.ICACHE_ADDR.H)) cache();
|
||||
|
||||
logic [NUM_SUB_UNITS-1:0] sub_unit_address_match;
|
||||
logic [NUM_SUB_UNITS-1:0] unit_ready;
|
||||
logic [NUM_SUB_UNITS-1:0] unit_data_valid;
|
||||
|
@ -117,7 +124,7 @@ module fetch
|
|||
assign update_pc = new_mem_request | gc_fetch_flush | early_branch_flush;
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
pc <= RESET_VEC;
|
||||
pc <= CONFIG.CSRS.RESET_VEC;
|
||||
else if (update_pc)
|
||||
pc <= {next_pc[31:2], 2'b0};
|
||||
end
|
||||
|
@ -148,6 +155,8 @@ module fetch
|
|||
assign bp.new_mem_request = update_pc;
|
||||
assign bp.next_pc = next_pc;
|
||||
assign bp.if_pc = pc;
|
||||
assign bp.pc_id = pc_id;
|
||||
assign bp.pc_id_assigned = pc_id_assigned;
|
||||
|
||||
assign ras.pop = bp.use_prediction & bp.is_return & ~branch_flush & ~gc_fetch_pc_override & new_mem_request & (~early_branch_flush);
|
||||
assign ras.push = bp.use_prediction & bp.is_call & ~branch_flush & ~gc_fetch_pc_override & new_mem_request & (~early_branch_flush);
|
||||
|
@ -159,8 +168,8 @@ module fetch
|
|||
assign tlb.virtual_address = pc;
|
||||
assign tlb.execute = 1;
|
||||
assign tlb.rnw = 0;
|
||||
assign tlb.new_request = tlb.ready & (ENABLE_S_MODE & tlb_on);
|
||||
assign translated_address = (ENABLE_S_MODE & tlb_on) ? tlb.physical_address : pc;
|
||||
assign tlb.new_request = tlb.ready & (CONFIG.INCLUDE_S_MODE & tlb_on);
|
||||
assign translated_address = (CONFIG.INCLUDE_S_MODE & tlb_on) ? tlb.physical_address : pc;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (new_mem_request)
|
||||
|
@ -193,11 +202,11 @@ module fetch
|
|||
assign fetch_attr_fifo.data_in = fetch_attr_next;
|
||||
|
||||
taiga_fifo #(.DATA_WIDTH($bits(fetch_attributes_t)), .FIFO_DEPTH(NEXT_ID_DEPTH))
|
||||
attributes_fifo (
|
||||
.clk (clk),
|
||||
.rst (flush_or_rst),
|
||||
.fifo (fetch_attr_fifo)
|
||||
);
|
||||
attributes_fifo (
|
||||
.clk (clk),
|
||||
.rst (flush_or_rst),
|
||||
.fifo (fetch_attr_fifo)
|
||||
);
|
||||
|
||||
assign fetch_attr = fetch_attr_fifo.data_out;
|
||||
|
||||
|
@ -206,43 +215,48 @@ module fetch
|
|||
//In the case of a gc_fetch_flush, a request may already be in progress
|
||||
//for any sub unit. That request can either be completed or aborted.
|
||||
//In either case, data_valid must NOT be asserted.
|
||||
generate
|
||||
for (i = 0; i < NUM_SUB_UNITS; i++) begin
|
||||
assign unit_ready[i] = fetch_sub[i].ready;
|
||||
assign unit_data_valid[i] = fetch_sub[i].data_valid;
|
||||
assign fetch_sub[i].new_request = new_mem_request & sub_unit_address_match[i];
|
||||
assign fetch_sub[i].stage1_addr = translated_address;
|
||||
assign fetch_sub[i].stage2_addr = stage2_phys_address;
|
||||
assign fetch_sub[i].flush = gc_fetch_flush;
|
||||
assign unit_data_array[i] = fetch_sub[i].data_out;
|
||||
end
|
||||
generate if (CONFIG.INCLUDE_ILOCAL_MEM) begin
|
||||
assign sub_unit_address_match[BRAM_ID] = bram.address_range_check(translated_address);
|
||||
assign unit_ready[BRAM_ID] = bram.ready;
|
||||
assign unit_data_valid[BRAM_ID] = bram.data_valid;
|
||||
assign bram.new_request = new_mem_request & sub_unit_address_match[BRAM_ID];
|
||||
assign bram.stage1_addr = translated_address;
|
||||
assign bram.stage2_addr = stage2_phys_address;
|
||||
assign bram.flush = gc_fetch_flush;
|
||||
assign unit_data_array[BRAM_ID] = bram.data_out;
|
||||
|
||||
ibram i_bram (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.fetch_sub (bram),
|
||||
.instruction_bram (instruction_bram)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
generate if (CONFIG.INCLUDE_ICACHE) begin
|
||||
assign sub_unit_address_match[ICACHE_ID] = cache.address_range_check(translated_address);
|
||||
assign unit_ready[ICACHE_ID] = cache.ready;
|
||||
assign unit_data_valid[ICACHE_ID] = cache.data_valid;
|
||||
assign cache.new_request = new_mem_request & sub_unit_address_match[ICACHE_ID];
|
||||
assign cache.stage1_addr = translated_address;
|
||||
assign cache.stage2_addr = stage2_phys_address;
|
||||
assign cache.flush = gc_fetch_flush;
|
||||
assign unit_data_array[ICACHE_ID] = cache.data_out;
|
||||
icache #(.CONFIG(CONFIG))
|
||||
i_cache (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.icache_on (icache_on),
|
||||
.l1_request (l1_request),
|
||||
.l1_response (l1_response),
|
||||
.fetch_sub (cache)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign units_ready = &unit_ready;
|
||||
assign address_valid = |sub_unit_address_match;
|
||||
|
||||
generate if (USE_I_SCRATCH_MEM) begin
|
||||
ibram i_bram (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.fetch_sub (fetch_sub[BRAM_ID]),
|
||||
.instruction_bram (instruction_bram)
|
||||
);
|
||||
assign sub_unit_address_match[BRAM_ID] = translated_address[31:32-SCRATCH_BIT_CHECK] == SCRATCH_ADDR_L[31:32-SCRATCH_BIT_CHECK];
|
||||
end
|
||||
endgenerate
|
||||
generate if (USE_ICACHE) begin
|
||||
icache i_cache (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.icache_on (icache_on),
|
||||
.l1_request (l1_request),
|
||||
.l1_response (l1_response),
|
||||
.fetch_sub (fetch_sub[ICACHE_ID])
|
||||
);
|
||||
assign sub_unit_address_match[ICACHE_ID] = translated_address[31:32-MEMORY_BIT_CHECK] == MEMORY_ADDR_L[31:32-MEMORY_BIT_CHECK];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instruction metada updates
|
||||
logic valid_fetch_result;
|
||||
|
|
|
@ -27,6 +27,10 @@ module gc_unit
|
|||
import taiga_types::*;
|
||||
import csr_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -89,9 +93,9 @@ module gc_unit
|
|||
);
|
||||
|
||||
//Largest depth for TLBs
|
||||
localparam int TLB_CLEAR_DEPTH = (DTLB_DEPTH > ITLB_DEPTH) ? DTLB_DEPTH : ITLB_DEPTH;
|
||||
localparam int TLB_CLEAR_DEPTH = (CONFIG.DTLB.DEPTH > CONFIG.ITLB.DEPTH) ? CONFIG.DTLB.DEPTH : CONFIG.ITLB.DEPTH;
|
||||
//For general reset clear, greater of TLB depth or id-flight memory blocks (MAX_IDS)
|
||||
localparam int INIT_CLEAR_DEPTH = ENABLE_S_MODE ? (TLB_CLEAR_DEPTH > 64 ? TLB_CLEAR_DEPTH : 64) : 64;
|
||||
localparam int INIT_CLEAR_DEPTH = CONFIG.INCLUDE_S_MODE ? (TLB_CLEAR_DEPTH > 64 ? TLB_CLEAR_DEPTH : 64) : 64;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instructions
|
||||
|
@ -301,7 +305,7 @@ module gc_unit
|
|||
end
|
||||
logic ecall_break_exception;
|
||||
assign ecall_break_exception = issue.new_request & (gc_inputs.is_ecall | gc_inputs.is_ebreak);
|
||||
assign gc_exception.valid = ENABLE_M_MODE & (ecall_break_exception | ls_exception.valid | br_exception.valid | illegal_instruction);
|
||||
assign gc_exception.valid = CONFIG.INCLUDE_M_MODE & (ecall_break_exception | ls_exception.valid | br_exception.valid | illegal_instruction);
|
||||
|
||||
//PC determination (trap, flush or return)
|
||||
//Two cycles: on first cycle the processor front end is flushed,
|
||||
|
@ -325,7 +329,8 @@ module gc_unit
|
|||
assign csr_inputs.rs1_is_zero = (rs1_addr == 0);
|
||||
assign csr_inputs.rd_is_zero = (rd_addr == 0);
|
||||
|
||||
csr_regs csr_registers (
|
||||
csr_regs # (.CONFIG(CONFIG))
|
||||
csr_registers (
|
||||
.clk(clk), .rst(rst),
|
||||
.csr_inputs(csr_inputs),
|
||||
.new_request(stage1.is_csr),
|
||||
|
|
|
@ -26,6 +26,10 @@ module icache
|
|||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -36,18 +40,20 @@ module icache
|
|||
fetch_sub_unit_interface.sub_unit fetch_sub
|
||||
);
|
||||
|
||||
localparam derived_cache_config_t SCONFIG = get_derived_cache_params(CONFIG, CONFIG.ICACHE, CONFIG.ICACHE_ADDR);
|
||||
|
||||
logic tag_hit;
|
||||
logic [ICACHE_WAYS-1:0] tag_hit_way;
|
||||
logic [CONFIG.ICACHE.WAYS-1:0] tag_hit_way;
|
||||
|
||||
logic tag_update;
|
||||
logic [ICACHE_WAYS-1:0] replacement_way;
|
||||
logic [ICACHE_WAYS-1:0] tag_update_way;
|
||||
logic [CONFIG.ICACHE.WAYS-1:0] replacement_way;
|
||||
logic [CONFIG.ICACHE.WAYS-1:0] tag_update_way;
|
||||
|
||||
logic [$clog2(ICACHE_LINE_W)-1:0] word_count;
|
||||
logic [SCONFIG.SUB_LINE_ADDR_W-1:0] word_count;
|
||||
logic is_target_word;
|
||||
logic line_complete;
|
||||
|
||||
logic [31:0] data_out [ICACHE_WAYS-1:0];
|
||||
logic [31:0] data_out [CONFIG.ICACHE.WAYS-1:0];
|
||||
logic [31:0] miss_data;
|
||||
|
||||
logic miss_in_progress;
|
||||
|
@ -92,7 +98,7 @@ module icache
|
|||
end
|
||||
|
||||
//Replacement policy is psuedo random
|
||||
cycler #(ICACHE_WAYS) replacement_policy (
|
||||
cycler #(CONFIG.ICACHE.WAYS) replacement_policy (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.en (1'b1),
|
||||
|
@ -112,7 +118,7 @@ module icache
|
|||
assign l1_request.data = 0;
|
||||
assign l1_request.rnw = 1;
|
||||
assign l1_request.be = 0;
|
||||
assign l1_request.size = (ICACHE_LINE_W-1);
|
||||
assign l1_request.size = 5'(CONFIG.ICACHE.LINE_W-1);
|
||||
assign l1_request.is_amo = 0;
|
||||
assign l1_request.amo = 0;
|
||||
|
||||
|
@ -143,7 +149,8 @@ module icache
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Tag banks
|
||||
itag_banks icache_tag_banks (
|
||||
itag_banks #(.CONFIG(CONFIG), .SCONFIG(SCONFIG))
|
||||
icache_tag_banks (
|
||||
.clk(clk),
|
||||
.rst(rst | fetch_sub.flush), //clears the read_hit_allowed flag
|
||||
.stage1_addr(fetch_sub.stage1_addr),
|
||||
|
@ -158,11 +165,11 @@ module icache
|
|||
////////////////////////////////////////////////////
|
||||
//Data Banks
|
||||
genvar i;
|
||||
generate for (i=0; i < ICACHE_WAYS; i++) begin : idata_bank_gen
|
||||
byte_en_BRAM #(ICACHE_LINES*ICACHE_LINE_W) idata_bank (
|
||||
generate for (i=0; i < CONFIG.ICACHE.WAYS; i++) begin : idata_bank_gen
|
||||
byte_en_BRAM #(CONFIG.ICACHE.LINES*CONFIG.ICACHE.LINE_W) idata_bank (
|
||||
.clk(clk),
|
||||
.addr_a(fetch_sub.stage1_addr[2 +: ICACHE_LINE_ADDR_W+ICACHE_SUB_LINE_ADDR_W]),
|
||||
.addr_b({fetch_sub.stage2_addr[(2+ICACHE_SUB_LINE_ADDR_W) +: ICACHE_LINE_ADDR_W], word_count}),
|
||||
.addr_a(fetch_sub.stage1_addr[2 +: SCONFIG.LINE_ADDR_W+SCONFIG.SUB_LINE_ADDR_W]),
|
||||
.addr_b({fetch_sub.stage2_addr[(2+SCONFIG.SUB_LINE_ADDR_W) +: SCONFIG.LINE_ADDR_W], word_count}),
|
||||
.en_a(fetch_sub.new_request),
|
||||
.en_b(tag_update_way[i] & l1_response.data_valid),
|
||||
.be_a('0),
|
||||
|
@ -183,7 +190,7 @@ module icache
|
|||
word_count <= word_count + 1;
|
||||
end
|
||||
|
||||
assign is_target_word = (fetch_sub.stage2_addr[2 +: ICACHE_SUB_LINE_ADDR_W] == word_count);
|
||||
assign is_target_word = (fetch_sub.stage2_addr[2 +: SCONFIG.SUB_LINE_ADDR_W] == word_count);
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (l1_response.data_valid & is_target_word)
|
||||
|
@ -199,7 +206,7 @@ module icache
|
|||
miss_data_valid <= (miss_in_progress & ~miss_aborted_by_flush) & l1_response.data_valid & is_target_word;
|
||||
end
|
||||
|
||||
assign line_complete = (l1_response.data_valid && (word_count == $clog2(ICACHE_LINE_W)'(ICACHE_LINE_W-1)));
|
||||
assign line_complete = (l1_response.data_valid && (word_count == SCONFIG.SUB_LINE_ADDR_W'(CONFIG.ICACHE.LINE_W-1)));
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
memory_complete <= 0;
|
||||
|
@ -211,7 +218,7 @@ module icache
|
|||
//Output muxing
|
||||
always_comb begin
|
||||
fetch_sub.data_out = miss_data;//zero if not a miss
|
||||
for (int i = 0; i < ICACHE_WAYS; i++) begin
|
||||
for (int i = 0; i < CONFIG.ICACHE.WAYS; i++) begin
|
||||
fetch_sub.data_out = fetch_sub.data_out | (data_out[i] & {32{tag_hit_way[i]}});
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,6 +24,10 @@ module illegal_instruction_checker
|
|||
|
||||
import taiga_config::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic [31:0] instruction,
|
||||
output logic illegal_instruction
|
||||
|
@ -153,11 +157,11 @@ module illegal_instruction_checker
|
|||
|
||||
assign illegal_instruction = ~(
|
||||
base_legal |
|
||||
(USE_MUL & mul_legal) |
|
||||
(USE_DIV & div_legal) |
|
||||
(USE_AMO & amo_legal) |
|
||||
(ENABLE_M_MODE & machine_legal) |
|
||||
(ENABLE_S_MODE & supervisor_legal)
|
||||
(CONFIG.INCLUDE_MUL & mul_legal) |
|
||||
(CONFIG.INCLUDE_DIV & div_legal) |
|
||||
(CONFIG.INCLUDE_AMO & amo_legal) |
|
||||
(CONFIG.INCLUDE_M_MODE & machine_legal) |
|
||||
(CONFIG.INCLUDE_S_MODE & supervisor_legal)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -26,6 +26,10 @@ module instruction_metadata_and_id_management
|
|||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -58,14 +62,9 @@ module instruction_metadata_and_id_management
|
|||
input logic instruction_issued,
|
||||
input logic instruction_issued_with_rd,
|
||||
|
||||
//Branch Predictor
|
||||
input branch_metadata_t branch_metadata_if,
|
||||
input id_t branch_id,
|
||||
output branch_metadata_t branch_metadata_ex,
|
||||
|
||||
//WB
|
||||
input wb_packet_t wb_packet [NUM_WB_GROUPS],
|
||||
output commit_packet_t commit_packet [NUM_WB_GROUPS],
|
||||
input wb_packet_t wb_packet [CONFIG.NUM_WB_GROUPS],
|
||||
output commit_packet_t commit_packet [CONFIG.NUM_WB_GROUPS],
|
||||
|
||||
//Retirer
|
||||
output retire_packet_t retire,
|
||||
|
@ -87,12 +86,11 @@ module instruction_metadata_and_id_management
|
|||
(* ramstyle = "MLAB, no_rw_check" *) phys_addr_t phys_addr_table [MAX_IDS];
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic [0:0] uses_rd_table [MAX_IDS];
|
||||
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic [$bits(branch_metadata_t)-1:0] branch_metadata_table [MAX_IDS];
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic [$bits(fetch_metadata_t)-1:0] fetch_metadata_table [MAX_IDS];
|
||||
|
||||
id_t decode_id;
|
||||
|
||||
logic [LOG2_MAX_IDS:0] fetched_count; //MSB used as valid for decode stage
|
||||
logic [LOG2_MAX_IDS:0] fetched_count;
|
||||
logic [LOG2_MAX_IDS:0] pre_issue_count;
|
||||
logic [LOG2_MAX_IDS:0] pre_issue_count_next;
|
||||
logic [LOG2_MAX_IDS:0] post_issue_count_next;
|
||||
|
@ -111,14 +109,6 @@ module instruction_metadata_and_id_management
|
|||
pc_table[pc_id] <= if_pc;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Branch metadata table
|
||||
//Number of read ports = 1 (branch unit)
|
||||
always_ff @ (posedge clk) begin
|
||||
if (pc_id_assigned)
|
||||
branch_metadata_table[pc_id] <= branch_metadata_if;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instruction table
|
||||
//Number of read ports = 1 (decode stage)
|
||||
|
@ -235,7 +225,7 @@ module instruction_metadata_and_id_management
|
|||
.clk (clk),
|
||||
.rst (rst),
|
||||
.init_clear (gc_init_clear),
|
||||
.toggle ('{(instruction_issued_with_rd & (issue.rd_wb_group == 1)), wb_packet[1].valid}),
|
||||
.toggle ('{(instruction_issued_with_rd & issue.is_multicycle), wb_packet[1].valid}),
|
||||
.toggle_addr ('{issue.id, wb_packet[1].id}),
|
||||
.read_addr (retire_ids),
|
||||
.in_use (id_inuse)
|
||||
|
@ -293,17 +283,14 @@ module instruction_metadata_and_id_management
|
|||
assign decode.instruction = instruction_table[decode_id];
|
||||
assign decode.fetch_metadata = fetch_metadata_table[decode_id];
|
||||
|
||||
//Branch Predictor
|
||||
assign branch_metadata_ex = branch_metadata_table[branch_id];
|
||||
|
||||
//Writeback/Commit support
|
||||
phys_addr_t commit_phys_addr [NUM_WB_GROUPS];
|
||||
phys_addr_t commit_phys_addr [CONFIG.NUM_WB_GROUPS];
|
||||
assign commit_phys_addr[0] = issue.phys_rd_addr;
|
||||
generate for (i = 1; i < NUM_WB_GROUPS; i++) begin
|
||||
generate for (i = 1; i < CONFIG.NUM_WB_GROUPS; i++) begin
|
||||
assign commit_phys_addr[i] = phys_addr_table[wb_packet[i].id];
|
||||
end endgenerate
|
||||
|
||||
generate for (i = 0; i < NUM_WB_GROUPS; i++) begin
|
||||
generate for (i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin
|
||||
assign commit_packet[i].id = wb_packet[i].id;
|
||||
assign commit_packet[i].phys_addr = commit_phys_addr[i];
|
||||
assign commit_packet[i].valid = wb_packet[i].valid & |commit_phys_addr[i];
|
||||
|
@ -311,7 +298,7 @@ module instruction_metadata_and_id_management
|
|||
end endgenerate
|
||||
|
||||
//Exception Support
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
generate if (CONFIG.INCLUDE_M_MODE) begin
|
||||
assign exception_pc = pc_table[exception_id];
|
||||
end endgenerate
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ interface branch_predictor_interface;
|
|||
id_t if_id;
|
||||
logic new_mem_request;
|
||||
logic [31:0] next_pc;
|
||||
|
||||
id_t pc_id;
|
||||
logic pc_id_assigned;
|
||||
|
||||
//Branch Predictor
|
||||
logic [31:0] branch_flush_pc;
|
||||
|
@ -38,12 +41,12 @@ interface branch_predictor_interface;
|
|||
logic is_branch;
|
||||
|
||||
modport branch_predictor (
|
||||
input if_pc, if_id, new_mem_request, next_pc,
|
||||
input if_pc, if_id, new_mem_request, next_pc, pc_id, pc_id_assigned,
|
||||
output branch_flush_pc, predicted_pc, use_prediction, is_return, is_call, is_branch
|
||||
);
|
||||
modport fetch (
|
||||
input branch_flush_pc, predicted_pc, use_prediction, is_return, is_call, is_branch,
|
||||
output if_pc, if_id, new_mem_request, next_pc
|
||||
output if_pc, if_id, new_mem_request, next_pc, pc_id, pc_id_assigned
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
@ -91,7 +94,7 @@ interface ras_interface;
|
|||
logic [31:0] new_addr;
|
||||
logic [31:0] addr;
|
||||
|
||||
modport branch_unit (output branch_retired);
|
||||
modport branch_predictor (output branch_retired);
|
||||
modport self (input push, pop, new_addr, branch_fetched, branch_retired, output addr);
|
||||
modport fetch (input addr, output pop, push, new_addr, branch_fetched);
|
||||
endinterface
|
||||
|
@ -239,13 +242,27 @@ interface writeback_store_interface;
|
|||
);
|
||||
endinterface
|
||||
|
||||
interface ls_sub_unit_interface #(parameter BASE_ADDR = 32'h00000000, parameter UPPER_BOUND = 32'hFFFFFFFF, parameter BIT_CHECK = 4);
|
||||
interface ls_sub_unit_interface #(parameter bit [31:0] BASE_ADDR = 32'h00000000, parameter bit [31:0] UPPER_BOUND = 32'hFFFFFFFF);
|
||||
logic data_valid;
|
||||
logic ready;
|
||||
logic new_request;
|
||||
|
||||
function address_range_check (input logic[31:0] addr);
|
||||
return (addr[31:32-BIT_CHECK] == BASE_ADDR[31:32-BIT_CHECK]);
|
||||
//Based on the lower and upper address ranges,
|
||||
//find the number of bits needed to uniquely identify this memory range.
|
||||
//Assumption: address range is aligned to its size
|
||||
function int unsigned bit_range ();
|
||||
int unsigned i = 0;
|
||||
for(; i < 32; i++) begin
|
||||
if (BASE_ADDR[i] == UPPER_BOUND[i])
|
||||
break;
|
||||
end
|
||||
return (32 - i);
|
||||
endfunction
|
||||
|
||||
localparam int unsigned BIT_RANGE = bit_range();
|
||||
|
||||
function address_range_check (input logic[31:0] addr);
|
||||
return (addr[31:32-BIT_RANGE] == BASE_ADDR[31:32-BIT_RANGE]);
|
||||
endfunction
|
||||
|
||||
modport sub_unit (input new_request, output data_valid, ready);
|
||||
|
@ -254,7 +271,7 @@ interface ls_sub_unit_interface #(parameter BASE_ADDR = 32'h00000000, parameter
|
|||
endinterface
|
||||
|
||||
|
||||
interface fetch_sub_unit_interface;
|
||||
interface fetch_sub_unit_interface #(parameter bit [31:0] BASE_ADDR = 32'h00000000, parameter bit [31:0] UPPER_BOUND = 32'hFFFFFFFF);
|
||||
logic [31:0] stage1_addr;
|
||||
logic [31:0] stage2_addr;
|
||||
|
||||
|
@ -264,6 +281,24 @@ interface fetch_sub_unit_interface;
|
|||
logic new_request;
|
||||
logic flush;
|
||||
|
||||
//Based on the lower and upper address ranges,
|
||||
//find the number of bits needed to uniquely identify this memory range.
|
||||
//Assumption: address range is aligned to its size
|
||||
function int unsigned bit_range ();
|
||||
int unsigned i = 0;
|
||||
for(; i < 32; i++) begin
|
||||
if (BASE_ADDR[i] == UPPER_BOUND[i])
|
||||
break;
|
||||
end
|
||||
return (32 - i);
|
||||
endfunction
|
||||
|
||||
localparam int unsigned BIT_RANGE = bit_range();
|
||||
|
||||
function address_range_check (input logic[31:0] addr);
|
||||
return (addr[31:32-BIT_RANGE] == BASE_ADDR[31:32-BIT_RANGE]);
|
||||
endfunction
|
||||
|
||||
modport sub_unit (input stage1_addr, stage2_addr, new_request, flush, output data_out, data_valid, ready);
|
||||
modport fetch (output stage1_addr, stage2_addr, new_request, flush, input data_out, data_valid, ready);
|
||||
|
||||
|
@ -284,21 +319,21 @@ interface unsigned_division_interface #(parameter DATA_WIDTH = 32);
|
|||
modport divider (output remainder, quotient, done, input dividend, dividend_CLZ, divisor, divisor_CLZ, divisor_is_zero, start);
|
||||
endinterface
|
||||
|
||||
interface renamer_interface;
|
||||
interface renamer_interface #(parameter NUM_WB_GROUPS = 2);
|
||||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
rs_addr_t rd_addr;
|
||||
rs_addr_t [REGFILE_READ_PORTS-1:0] rs_addr;
|
||||
rs_wb_group_t rd_wb_group;
|
||||
logic [$clog2(NUM_WB_GROUPS)-1:0] rd_wb_group;
|
||||
logic uses_rd;
|
||||
id_t id;
|
||||
|
||||
phys_addr_t [REGFILE_READ_PORTS-1:0] phys_rs_addr;
|
||||
phys_addr_t phys_rd_addr;
|
||||
|
||||
rs_wb_group_t [REGFILE_READ_PORTS-1:0] rs_wb_group;
|
||||
logic [REGFILE_READ_PORTS-1:0][$clog2(NUM_WB_GROUPS)-1:0] rs_wb_group;
|
||||
|
||||
modport renamer (
|
||||
input rd_addr, rs_addr, rd_wb_group, uses_rd, id,
|
||||
|
@ -310,20 +345,20 @@ interface renamer_interface;
|
|||
);
|
||||
endinterface
|
||||
|
||||
interface register_file_issue_interface;
|
||||
interface register_file_issue_interface #(parameter NUM_WB_GROUPS = 2);
|
||||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
//read interface
|
||||
phys_addr_t phys_rs_addr [REGFILE_READ_PORTS];
|
||||
logic [LOG2_COMMIT_PORTS-1:0] rs_wb_group [REGFILE_READ_PORTS];
|
||||
logic [$clog2(NUM_WB_GROUPS)-1:0] rs_wb_group [REGFILE_READ_PORTS];
|
||||
logic [31:0] data [REGFILE_READ_PORTS];
|
||||
logic inuse [REGFILE_READ_PORTS];
|
||||
|
||||
//write interface
|
||||
phys_addr_t phys_rd_addr;
|
||||
logic [LOG2_COMMIT_PORTS-1:0] rd_wb_group;
|
||||
logic [$clog2(NUM_WB_GROUPS)-1:0] rd_wb_group;
|
||||
logic issued;
|
||||
|
||||
modport register_file (
|
||||
|
|
|
@ -25,6 +25,11 @@ module itag_banks
|
|||
import taiga_config::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG,
|
||||
parameter derived_cache_config_t SCONFIG = '{default: 0}
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -32,27 +37,27 @@ module itag_banks
|
|||
input logic[31:0] stage1_addr,
|
||||
input logic[31:0] stage2_addr,
|
||||
|
||||
input logic[ICACHE_WAYS-1:0] update_way,
|
||||
input logic[CONFIG.ICACHE.WAYS-1:0] update_way,
|
||||
input logic update,
|
||||
|
||||
input logic stage1_adv,
|
||||
|
||||
output tag_hit,
|
||||
output logic[ICACHE_WAYS-1:0] tag_hit_way
|
||||
output logic[CONFIG.ICACHE.WAYS-1:0] tag_hit_way
|
||||
);
|
||||
|
||||
typedef logic [ICACHE_TAG_W : 0] itag_entry_t;
|
||||
typedef logic [SCONFIG.TAG_W : 0] itag_entry_t;
|
||||
|
||||
function logic[ICACHE_TAG_W-1:0] getTag(logic[31:0] addr);
|
||||
return addr[2+ICACHE_SUB_LINE_ADDR_W+ICACHE_LINE_ADDR_W +: ICACHE_TAG_W];
|
||||
function logic[SCONFIG.TAG_W-1:0] getTag(logic[31:0] addr);
|
||||
return addr[2+SCONFIG.SUB_LINE_ADDR_W+SCONFIG.LINE_ADDR_W +: SCONFIG.TAG_W];
|
||||
endfunction
|
||||
|
||||
function logic[ICACHE_LINE_ADDR_W-1:0] getLineAddr(logic[31:0] addr);
|
||||
return addr[ICACHE_LINE_ADDR_W + ICACHE_SUB_LINE_ADDR_W + 1 : ICACHE_SUB_LINE_ADDR_W + 2];
|
||||
function logic[SCONFIG.LINE_ADDR_W-1:0] getLineAddr(logic[31:0] addr);
|
||||
return addr[SCONFIG.LINE_ADDR_W + SCONFIG.SUB_LINE_ADDR_W + 1 : SCONFIG.SUB_LINE_ADDR_W + 2];
|
||||
endfunction
|
||||
|
||||
logic hit_allowed;
|
||||
itag_entry_t tag_line[ICACHE_WAYS-1:0];
|
||||
itag_entry_t tag_line[CONFIG.ICACHE.WAYS-1:0];
|
||||
|
||||
itag_entry_t stage2_tag;
|
||||
assign stage2_tag = {1'b1, getTag(stage2_addr)};
|
||||
|
@ -67,9 +72,9 @@ module itag_banks
|
|||
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i < ICACHE_WAYS; i++) begin : tag_bank_gen
|
||||
for (i=0; i < CONFIG.ICACHE.WAYS; i++) begin : tag_bank_gen
|
||||
|
||||
tag_bank #(ICACHE_TAG_W+1, ICACHE_LINES) itag_bank (.*,
|
||||
tag_bank #(SCONFIG.TAG_W+1, CONFIG.ICACHE.LINES) itag_bank (.*,
|
||||
.en_a(stage1_adv), .wen_a('0),
|
||||
.addr_a(getLineAddr(stage1_addr)),
|
||||
.data_in_a('0), .data_out_a(tag_line[i]),
|
||||
|
|
|
@ -27,6 +27,10 @@ module l1_arbiter
|
|||
import taiga_types::*;
|
||||
import l2_config_and_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -72,12 +76,12 @@ module l1_arbiter
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Dcache Specific
|
||||
assign l2.wr_data_push = USE_DCACHE & (push_ready & l1_request[L1_DCACHE_ID].request & ~l1_request[L1_DCACHE_ID].rnw); //Assumes data cache has highest priority
|
||||
assign l2.wr_data_push = CONFIG.INCLUDE_DCACHE & (push_ready & l1_request[L1_DCACHE_ID].request & ~l1_request[L1_DCACHE_ID].rnw); //Assumes data cache has highest priority
|
||||
assign l2.wr_data = l1_request[L1_DCACHE_ID].data;
|
||||
|
||||
assign l2.inv_ack = USE_DTAG_INVALIDATIONS ? l1_response[L1_DCACHE_ID].inv_ack : l2.inv_valid;
|
||||
assign l2.inv_ack = CONFIG.DCACHE.USE_EXTERNAL_INVALIDATIONS ? l1_response[L1_DCACHE_ID].inv_ack : l2.inv_valid;
|
||||
assign l1_response[L1_DCACHE_ID].inv_addr = l2.inv_addr;
|
||||
assign l1_response[L1_DCACHE_ID].inv_valid = USE_DTAG_INVALIDATIONS & l2.inv_valid;
|
||||
assign l1_response[L1_DCACHE_ID].inv_valid = CONFIG.DCACHE.USE_EXTERNAL_INVALIDATIONS & l2.inv_valid;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Interface mapping
|
||||
|
|
|
@ -124,7 +124,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
|
|||
|
||||
//Priority is for loads over stores.
|
||||
//A store will be selected only if either no loads are ready, OR if the store queue is full and a store is ready
|
||||
assign load_selected = lq_output_valid & ~store_conflict & ~(sq_full & sq_output_valid);
|
||||
assign load_selected = lq_output_valid & ~store_conflict;// & ~(sq_full & sq_output_valid);
|
||||
|
||||
assign lsq.transaction_ready = (lq_output_valid & ~store_conflict) | sq_output_valid;
|
||||
assign load_ack = lsq.accepted & load_selected;
|
||||
|
@ -150,7 +150,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
|
|||
////////////////////////////////////////////////////
|
||||
//Trace Interface
|
||||
generate if (ENABLE_TRACE_INTERFACE) begin
|
||||
assign tr_possible_load_conflict_delay = lq_output_valid & store_conflict;
|
||||
assign tr_possible_load_conflict_delay = lq_output_valid & (store_conflict | (sq_full & sq_output_valid));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
|
|
@ -26,6 +26,10 @@ module load_store_unit
|
|||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -69,20 +73,20 @@ module load_store_unit
|
|||
output logic tr_load_conflict_delay
|
||||
);
|
||||
|
||||
localparam NUM_SUB_UNITS = USE_D_SCRATCH_MEM+USE_BUS+USE_DCACHE;
|
||||
localparam NUM_SUB_UNITS = int'(CONFIG.INCLUDE_DLOCAL_MEM) + int'(CONFIG.INCLUDE_PERIPHERAL_BUS) + int'(CONFIG.INCLUDE_DCACHE);
|
||||
localparam NUM_SUB_UNITS_W = (NUM_SUB_UNITS == 1) ? 1 : $clog2(NUM_SUB_UNITS);
|
||||
|
||||
localparam BRAM_ID = 0;
|
||||
localparam BUS_ID = USE_D_SCRATCH_MEM;
|
||||
localparam DCACHE_ID = USE_D_SCRATCH_MEM+USE_BUS;
|
||||
localparam BUS_ID = int'(CONFIG.INCLUDE_DLOCAL_MEM);
|
||||
localparam DCACHE_ID = int'(CONFIG.INCLUDE_DLOCAL_MEM) + int'(CONFIG.INCLUDE_PERIPHERAL_BUS);
|
||||
|
||||
//Should be equal to pipeline depth of longest load/store subunit
|
||||
localparam ATTRIBUTES_DEPTH = USE_DCACHE ? 2 : 1;
|
||||
localparam ATTRIBUTES_DEPTH = CONFIG.INCLUDE_DCACHE ? 2 : 1;
|
||||
|
||||
data_access_shared_inputs_t shared_inputs;
|
||||
ls_sub_unit_interface #(.BASE_ADDR(SCRATCH_ADDR_L), .UPPER_BOUND(SCRATCH_ADDR_H), .BIT_CHECK(SCRATCH_BIT_CHECK)) bram();
|
||||
ls_sub_unit_interface #(.BASE_ADDR(BUS_ADDR_L), .UPPER_BOUND(BUS_ADDR_H), .BIT_CHECK(BUS_BIT_CHECK)) bus();
|
||||
ls_sub_unit_interface #(.BASE_ADDR(MEMORY_ADDR_L), .UPPER_BOUND(MEMORY_ADDR_H), .BIT_CHECK(MEMORY_BIT_CHECK)) cache();
|
||||
ls_sub_unit_interface #(.BASE_ADDR(CONFIG.DLOCAL_MEM_ADDR.L), .UPPER_BOUND(CONFIG.DLOCAL_MEM_ADDR.H)) bram();
|
||||
ls_sub_unit_interface #(.BASE_ADDR(CONFIG.PERIPHERAL_BUS_ADDR.L), .UPPER_BOUND(CONFIG.PERIPHERAL_BUS_ADDR.H)) bus();
|
||||
ls_sub_unit_interface #(.BASE_ADDR(CONFIG.DCACHE_ADDR.L), .UPPER_BOUND(CONFIG.DCACHE_ADDR.H)) cache();
|
||||
|
||||
logic units_ready;
|
||||
logic unit_switch_stall;
|
||||
|
@ -129,7 +133,7 @@ module load_store_unit
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Alignment Exception
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
generate if (CONFIG.INCLUDE_M_MODE) begin
|
||||
|
||||
always_comb begin
|
||||
case(ls_inputs.fn3)
|
||||
|
@ -261,7 +265,7 @@ endgenerate
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit Instantiation
|
||||
generate if (USE_D_SCRATCH_MEM) begin
|
||||
generate if (CONFIG.INCLUDE_DLOCAL_MEM) begin
|
||||
assign sub_unit_address_match[BRAM_ID] = bram.address_range_check(shared_inputs.addr);
|
||||
assign bram.new_request = sub_unit_address_match[BRAM_ID] & issue_request;
|
||||
|
||||
|
@ -279,14 +283,14 @@ endgenerate
|
|||
end
|
||||
endgenerate
|
||||
|
||||
generate if (USE_BUS) begin
|
||||
generate if (CONFIG.INCLUDE_PERIPHERAL_BUS) begin
|
||||
assign sub_unit_address_match[BUS_ID] = bus.address_range_check(shared_inputs.addr);
|
||||
assign bus.new_request = sub_unit_address_match[BUS_ID] & issue_request;
|
||||
|
||||
assign unit_ready[BUS_ID] = bus.ready;
|
||||
assign unit_data_valid[BUS_ID] = bus.data_valid;
|
||||
|
||||
if(BUS_TYPE == AXI_BUS)
|
||||
if(CONFIG.PERIPHERAL_BUS_TYPE == AXI_BUS)
|
||||
axi_master axi_bus (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
@ -297,7 +301,7 @@ endgenerate
|
|||
.ls (bus)
|
||||
); //Lower two bits of fn3 match AXI specification for request size (byte/halfword/word)
|
||||
|
||||
else if (BUS_TYPE == WISHBONE_BUS)
|
||||
else if (CONFIG.PERIPHERAL_BUS_TYPE == WISHBONE_BUS)
|
||||
wishbone_master wishbone_bus (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
@ -306,7 +310,7 @@ endgenerate
|
|||
.ls_inputs (shared_inputs),
|
||||
.ls (bus)
|
||||
);
|
||||
else if (BUS_TYPE == AVALON_BUS) begin
|
||||
else if (CONFIG.PERIPHERAL_BUS_TYPE == AVALON_BUS) begin
|
||||
avalon_master avalon_bus (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
@ -319,14 +323,15 @@ endgenerate
|
|||
end
|
||||
endgenerate
|
||||
|
||||
generate if (USE_DCACHE) begin
|
||||
generate if (CONFIG.INCLUDE_DCACHE) begin
|
||||
assign sub_unit_address_match[DCACHE_ID] = cache.address_range_check(shared_inputs.addr);
|
||||
assign cache.new_request = sub_unit_address_match[DCACHE_ID] & issue_request;
|
||||
|
||||
assign unit_ready[DCACHE_ID] = cache.ready;
|
||||
assign unit_data_valid[DCACHE_ID] = cache.data_valid;
|
||||
|
||||
dcache data_cache (
|
||||
dcache # (.CONFIG(CONFIG))
|
||||
data_cache (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.dcache_on (dcache_on),
|
||||
|
|
|
@ -26,6 +26,10 @@ module ras
|
|||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -34,9 +38,9 @@ module ras
|
|||
ras_interface.self ras
|
||||
);
|
||||
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic[31:0] lut_ram [RAS_DEPTH];
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic[31:0] lut_ram [CONFIG.BP.RAS_ENTRIES];
|
||||
|
||||
localparam RAS_DEPTH_W = $clog2(RAS_DEPTH);
|
||||
localparam RAS_DEPTH_W = $clog2(CONFIG.BP.RAS_ENTRIES);
|
||||
logic [RAS_DEPTH_W-1:0] read_index;
|
||||
logic [RAS_DEPTH_W-1:0] new_index;
|
||||
fifo_interface #(.DATA_WIDTH(RAS_DEPTH_W)) ri_fifo();
|
||||
|
|
|
@ -26,6 +26,10 @@ module register_file
|
|||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -36,13 +40,13 @@ module register_file
|
|||
register_file_issue_interface.register_file rf_issue,
|
||||
|
||||
//Writeback
|
||||
input commit_packet_t commit [NUM_WB_GROUPS]
|
||||
input commit_packet_t commit [CONFIG.NUM_WB_GROUPS]
|
||||
);
|
||||
typedef logic [31:0] rs_data_set_t [REGFILE_READ_PORTS];
|
||||
rs_data_set_t rs_data_set [NUM_WB_GROUPS];
|
||||
rs_data_set_t rs_data_set [CONFIG.NUM_WB_GROUPS];
|
||||
|
||||
typedef logic inuse_t [REGFILE_READ_PORTS];
|
||||
inuse_t phys_reg_inuse_set [NUM_WB_GROUPS];
|
||||
inuse_t phys_reg_inuse_set [CONFIG.NUM_WB_GROUPS];
|
||||
|
||||
genvar i;
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -82,7 +86,7 @@ module register_file
|
|||
//Register Banks
|
||||
//Implemented in seperate module as there is not universal tool support for inferring
|
||||
//arrays of memory blocks.
|
||||
generate for (i = 0; i < NUM_WB_GROUPS; i++) begin : register_file_gen
|
||||
generate for (i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin : register_file_gen
|
||||
register_bank #(.NUM_READ_PORTS(REGFILE_READ_PORTS)) reg_group (
|
||||
.clk, .rst,
|
||||
.write_addr(commit[i].phys_addr),
|
||||
|
@ -107,7 +111,7 @@ module register_file
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
for (genvar i = 0; i < NUM_WB_GROUPS; i++) begin : write_to_rd_zero_assertion
|
||||
for (genvar i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin : write_to_rd_zero_assertion
|
||||
assert property (@(posedge clk) disable iff (rst) (commit[i].valid) |-> (commit[i].phys_addr != 0)) else $error("write to register zero");
|
||||
end
|
||||
|
||||
|
|
|
@ -25,6 +25,10 @@ module renamer
|
|||
import taiga_config::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -86,7 +90,7 @@ module renamer
|
|||
//During post reset init, initialize rd_to_phys with in-use list (lower 32 registers)
|
||||
typedef struct packed{
|
||||
phys_addr_t phys_addr;
|
||||
rs_wb_group_t wb_group;
|
||||
logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] wb_group;
|
||||
} spec_table_t;
|
||||
spec_table_t spec_table_next;
|
||||
spec_table_t spec_table_old;
|
||||
|
|
164
core/taiga.sv
164
core/taiga.sv
|
@ -29,6 +29,10 @@ module taiga
|
|||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
#(
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
@ -48,6 +52,41 @@ module taiga
|
|||
input logic interrupt
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit ID Assignment
|
||||
//Generate Issue IDs based on configuration options
|
||||
//Then assigned to a struct for ease in passing to sub modules
|
||||
|
||||
//Units with writeback
|
||||
localparam int unsigned ALU_UNIT_ID = 32'd0;
|
||||
localparam int unsigned LS_UNIT_ID = 32'd1;
|
||||
localparam int unsigned GC_UNIT_ID = 32'd2;
|
||||
localparam int unsigned MUL_UNIT_ID = GC_UNIT_ID + int'(CONFIG.INCLUDE_MUL);
|
||||
localparam int unsigned DIV_UNIT_ID = MUL_UNIT_ID + int'(CONFIG.INCLUDE_DIV);
|
||||
//Non-writeback units
|
||||
localparam int unsigned BRANCH_UNIT_ID = DIV_UNIT_ID + 1;
|
||||
|
||||
//Total number of units
|
||||
localparam int unsigned NUM_UNITS = BRANCH_UNIT_ID + 1;
|
||||
|
||||
localparam unit_id_param_t UNIT_IDS = '{
|
||||
ALU : ALU_UNIT_ID,
|
||||
LS : LS_UNIT_ID,
|
||||
CSR : GC_UNIT_ID,
|
||||
MUL : MUL_UNIT_ID,
|
||||
DIV : DIV_UNIT_ID,
|
||||
BR : BRANCH_UNIT_ID
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Writeback Port Assignment
|
||||
//
|
||||
localparam int unsigned NUM_WB_UNITS_GROUP_1 = 1;//ALU
|
||||
localparam int unsigned NUM_WB_UNITS_GROUP_2 = 2 + int'(CONFIG.INCLUDE_MUL) + int'(CONFIG.INCLUDE_DIV);//LS + CSR
|
||||
localparam int unsigned NUM_WB_UNITS = NUM_WB_UNITS_GROUP_1 + NUM_WB_UNITS_GROUP_2;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Connecting Signals
|
||||
l1_arbiter_request_interface l1_request[L1_CONNECTIONS-1:0]();
|
||||
l1_arbiter_return_interface l1_response[L1_CONNECTIONS-1:0]();
|
||||
logic sc_complete;
|
||||
|
@ -63,7 +102,7 @@ module taiga
|
|||
ras_interface ras();
|
||||
|
||||
issue_packet_t issue;
|
||||
register_file_issue_interface rf_issue();
|
||||
register_file_issue_interface #(.NUM_WB_GROUPS(CONFIG.NUM_WB_GROUPS)) rf_issue();
|
||||
|
||||
|
||||
alu_inputs_t alu_inputs;
|
||||
|
@ -106,23 +145,19 @@ module taiga
|
|||
decode_packet_t decode;
|
||||
logic decode_uses_rd;
|
||||
rs_addr_t decode_rd_addr;
|
||||
phys_addr_t decode_phys_rd_addr;
|
||||
//Branch predictor
|
||||
id_t branch_id;
|
||||
branch_metadata_t branch_metadata_if;
|
||||
branch_metadata_t branch_metadata_ex;
|
||||
phys_addr_t decode_phys_rd_addr;
|
||||
//ID freeing
|
||||
retire_packet_t retire;
|
||||
id_t retire_ids [RETIRE_PORTS];
|
||||
logic retire_port_valid [RETIRE_PORTS];
|
||||
//Writeback
|
||||
wb_packet_t wb_packet [NUM_WB_GROUPS];
|
||||
commit_packet_t commit_packet [NUM_WB_GROUPS];
|
||||
wb_packet_t wb_packet [CONFIG.NUM_WB_GROUPS];
|
||||
commit_packet_t commit_packet [CONFIG.NUM_WB_GROUPS];
|
||||
//Exception
|
||||
id_t exception_id;
|
||||
logic [31:0] exception_pc;
|
||||
|
||||
renamer_interface decode_rename_interface ();
|
||||
renamer_interface #(.NUM_WB_GROUPS(CONFIG.NUM_WB_GROUPS)) decode_rename_interface ();
|
||||
|
||||
//Global Control
|
||||
logic gc_init_clear;
|
||||
|
@ -181,18 +216,16 @@ module taiga
|
|||
logic tr_rs2_forwarding_needed;
|
||||
logic tr_rs1_and_rs2_forwarding_needed;
|
||||
|
||||
unit_id_t tr_num_instructions_completing;
|
||||
id_t tr_num_instructions_in_flight;
|
||||
id_t tr_num_of_instructions_pending_writeback;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Memory Interface
|
||||
generate if (ENABLE_S_MODE || USE_ICACHE || USE_DCACHE)
|
||||
generate if (CONFIG.INCLUDE_S_MODE || CONFIG.INCLUDE_ICACHE || CONFIG.INCLUDE_DCACHE)
|
||||
|
||||
l1_arbiter arb(
|
||||
l1_arbiter #(.CONFIG(CONFIG))
|
||||
arb(
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.l2 (l2),
|
||||
|
@ -206,7 +239,8 @@ module taiga
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
// ID support
|
||||
instruction_metadata_and_id_management id_block (
|
||||
instruction_metadata_and_id_management #(.CONFIG(CONFIG))
|
||||
id_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_init_clear (gc_init_clear),
|
||||
|
@ -228,9 +262,6 @@ module taiga
|
|||
.issue (issue),
|
||||
.instruction_issued (instruction_issued),
|
||||
.instruction_issued_with_rd (instruction_issued_with_rd),
|
||||
.branch_metadata_if (branch_metadata_if),
|
||||
.branch_metadata_ex (branch_metadata_ex),
|
||||
.branch_id (branch_id),
|
||||
.wb_packet (wb_packet),
|
||||
.commit_packet (commit_packet),
|
||||
.retire (retire),
|
||||
|
@ -243,14 +274,16 @@ module taiga
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
// Fetch
|
||||
fetch fetch_block (
|
||||
fetch # (.CONFIG(CONFIG))
|
||||
fetch_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.branch_flush (branch_flush),
|
||||
.gc_fetch_hold (gc_fetch_hold),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.gc_fetch_pc_override (gc_fetch_pc_override),
|
||||
.gc_fetch_pc (gc_fetch_pc),
|
||||
.gc_fetch_pc (gc_fetch_pc),
|
||||
.pc_id (pc_id),
|
||||
.pc_id_available (pc_id_available),
|
||||
.pc_id_assigned (pc_id_assigned),
|
||||
.fetch_complete (fetch_complete),
|
||||
|
@ -271,16 +304,17 @@ module taiga
|
|||
.tr_early_branch_correction (tr_early_branch_correction)
|
||||
);
|
||||
|
||||
branch_predictor bp_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.bp (bp),
|
||||
.branch_metadata_if (branch_metadata_if),
|
||||
.branch_metadata_ex (branch_metadata_ex),
|
||||
.br_results (br_results)
|
||||
branch_predictor #(.CONFIG(CONFIG))
|
||||
bp_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.bp (bp),
|
||||
.br_results (br_results),
|
||||
.ras (ras)
|
||||
);
|
||||
|
||||
ras ras_block(
|
||||
ras # (.CONFIG(CONFIG))
|
||||
ras_block(
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
|
@ -288,9 +322,10 @@ module taiga
|
|||
.ras (ras)
|
||||
);
|
||||
|
||||
generate if (ENABLE_S_MODE) begin
|
||||
generate if (CONFIG.INCLUDE_S_MODE) begin
|
||||
|
||||
tlb_lut_ram #(ITLB_WAYS, ITLB_DEPTH) i_tlb (
|
||||
tlb_lut_ram #(.WAYS(CONFIG.ITLB.WAYS), .DEPTH(CONFIG.ITLB.DEPTH))
|
||||
i_tlb (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.abort_request (gc_fetch_flush | early_branch_flush),
|
||||
|
@ -319,7 +354,8 @@ module taiga
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Renamer
|
||||
renamer renamer_block (
|
||||
renamer #(.CONFIG(CONFIG))
|
||||
renamer_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_init_clear (gc_init_clear),
|
||||
|
@ -332,7 +368,12 @@ module taiga
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Decode/Issue
|
||||
decode_and_issue decode_and_issue_block (
|
||||
decode_and_issue #(
|
||||
.CONFIG (CONFIG),
|
||||
.NUM_UNITS (NUM_UNITS),
|
||||
.UNIT_IDS (UNIT_IDS)
|
||||
)
|
||||
decode_and_issue_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.pc_id_available (pc_id_available),
|
||||
|
@ -382,7 +423,8 @@ module taiga
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Register File
|
||||
register_file register_file_block (
|
||||
register_file #(.CONFIG(CONFIG))
|
||||
register_file_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_init_clear (gc_init_clear),
|
||||
|
@ -392,16 +434,14 @@ module taiga
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Execution Units
|
||||
branch_unit branch_unit_block (
|
||||
branch_unit #(.CONFIG(CONFIG))
|
||||
branch_unit_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.issue (unit_issue[BRANCH_UNIT_ID]),
|
||||
.issue (unit_issue[UNIT_IDS.BR]),
|
||||
.branch_inputs (branch_inputs),
|
||||
.br_results (br_results),
|
||||
.ras (ras),
|
||||
.branch_flush (branch_flush),
|
||||
.branch_id (branch_id),
|
||||
.branch_metadata_ex (branch_metadata_ex),
|
||||
.potential_branch_exception (potential_branch_exception),
|
||||
.branch_exception_is_jump (branch_exception_is_jump),
|
||||
.br_exception (br_exception),
|
||||
|
@ -416,15 +456,16 @@ module taiga
|
|||
.clk (clk),
|
||||
.rst (rst),
|
||||
.alu_inputs (alu_inputs),
|
||||
.issue (unit_issue[ALU_UNIT_ID]),
|
||||
.wb (unit_wb[ALU_UNIT_ID])
|
||||
.issue (unit_issue[UNIT_IDS.ALU]),
|
||||
.wb (unit_wb[UNIT_IDS.ALU])
|
||||
);
|
||||
|
||||
load_store_unit load_store_unit_block (
|
||||
load_store_unit #(.CONFIG(CONFIG))
|
||||
load_store_unit_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.ls_inputs (ls_inputs),
|
||||
.issue (unit_issue[LS_UNIT_ID]),
|
||||
.issue (unit_issue[UNIT_IDS.LS]),
|
||||
.dcache_on (1'b1),
|
||||
.clear_reservation (1'b0),
|
||||
.tlb (dtlb),
|
||||
|
@ -445,12 +486,13 @@ module taiga
|
|||
.ls_is_idle (ls_is_idle),
|
||||
.ls_exception (ls_exception),
|
||||
.ls_exception_is_store (ls_exception_is_store),
|
||||
.wb (unit_wb[LS_UNIT_ID]),
|
||||
.wb (unit_wb[UNIT_IDS.LS]),
|
||||
.tr_load_conflict_delay (tr_load_conflict_delay)
|
||||
);
|
||||
|
||||
generate if (ENABLE_S_MODE) begin
|
||||
tlb_lut_ram #(DTLB_WAYS, DTLB_DEPTH) d_tlb (
|
||||
generate if (CONFIG.INCLUDE_S_MODE) begin
|
||||
tlb_lut_ram #(.WAYS(CONFIG.DTLB.WAYS), .DEPTH(CONFIG.DTLB.DEPTH))
|
||||
d_tlb (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.abort_request (1'b0),
|
||||
|
@ -476,10 +518,11 @@ module taiga
|
|||
end
|
||||
endgenerate
|
||||
|
||||
gc_unit gc_unit_block (
|
||||
gc_unit #(.CONFIG(CONFIG))
|
||||
gc_unit_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.issue (unit_issue[GC_UNIT_ID]),
|
||||
.issue (unit_issue[UNIT_IDS.CSR]),
|
||||
.gc_inputs (gc_inputs),
|
||||
.gc_flush_required (gc_flush_required),
|
||||
.branch_flush (branch_flush),
|
||||
|
@ -509,33 +552,41 @@ module taiga
|
|||
.gc_fetch_pc (gc_fetch_pc),
|
||||
.ls_is_idle (ls_is_idle),
|
||||
.post_issue_count (post_issue_count),
|
||||
.wb (unit_wb[GC_UNIT_ID])
|
||||
.wb (unit_wb[UNIT_IDS.CSR])
|
||||
);
|
||||
|
||||
generate if (USE_MUL)
|
||||
generate if (CONFIG.INCLUDE_MUL)
|
||||
mul_unit mul_unit_block (.*,
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.mul_inputs (mul_inputs),
|
||||
.issue (unit_issue[MUL_UNIT_ID]),
|
||||
.wb (unit_wb[MUL_UNIT_ID])
|
||||
.issue (unit_issue[UNIT_IDS.MUL]),
|
||||
.wb (unit_wb[UNIT_IDS.MUL])
|
||||
);
|
||||
endgenerate
|
||||
|
||||
generate if (USE_DIV)
|
||||
generate if (CONFIG.INCLUDE_DIV)
|
||||
div_unit div_unit_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.div_inputs (div_inputs),
|
||||
.issue (unit_issue[DIV_UNIT_ID]),
|
||||
.wb (unit_wb[DIV_UNIT_ID])
|
||||
.issue (unit_issue[UNIT_IDS.DIV]),
|
||||
.wb (unit_wb[UNIT_IDS.DIV])
|
||||
);
|
||||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Writeback
|
||||
writeback writeback_block (
|
||||
//First writeback port: ALU
|
||||
//Second writeback port: LS, CSR, [MUL], [DIV]
|
||||
localparam int unsigned NUM_UNITS_PER_PORT [CONFIG.NUM_WB_GROUPS] = '{NUM_WB_UNITS_GROUP_1, NUM_WB_UNITS_GROUP_2};
|
||||
writeback #(
|
||||
.CONFIG (CONFIG),
|
||||
.NUM_UNITS (NUM_UNITS_PER_PORT),
|
||||
.NUM_WB_UNITS (NUM_WB_UNITS)
|
||||
)
|
||||
writeback_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.wb_packet (wb_packet),
|
||||
|
@ -587,9 +638,6 @@ module taiga
|
|||
tr.events.rs1_forwarding_needed <= tr_rs1_forwarding_needed;
|
||||
tr.events.rs2_forwarding_needed <= tr_rs2_forwarding_needed;
|
||||
tr.events.rs1_and_rs2_forwarding_needed <= tr_rs1_and_rs2_forwarding_needed;
|
||||
tr.events.num_instructions_completing <= tr_num_instructions_completing;
|
||||
tr.events.num_instructions_in_flight <= tr_num_instructions_in_flight;
|
||||
tr.events.num_of_instructions_pending_writeback <= tr_num_of_instructions_pending_writeback;
|
||||
tr.instruction_pc_dec <= tr_instruction_pc_dec;
|
||||
tr.instruction_data_dec <= tr_instruction_data_dec;
|
||||
end
|
||||
|
|
|
@ -25,126 +25,202 @@ package taiga_config;
|
|||
////////////////////////////////////////////////////
|
||||
//Vendor Selection
|
||||
localparam FPGA_VENDOR = "xilinx"; //xilinx or intel
|
||||
////////////////////////////////////////////////////
|
||||
//Privileged ISA Options
|
||||
|
||||
//Enable Machine level privilege spec
|
||||
localparam ENABLE_M_MODE = 1;
|
||||
//Enable Supervisor level privilege spec
|
||||
localparam ENABLE_S_MODE = 1;
|
||||
//Enable User level privilege spec
|
||||
localparam ENABLE_U_MODE = 1;
|
||||
|
||||
localparam MACHINE_IMPLEMENTATION_ID = 0;
|
||||
localparam CPU_ID = 0;//32-bicd ..t value
|
||||
|
||||
//CSR counter width (33-64 bits): 48-bits --> 32 days @ 100MHz
|
||||
localparam COUNTER_W = 33;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ISA Options
|
||||
|
||||
//Multiply and Divide Inclusion
|
||||
localparam USE_MUL = 1;
|
||||
localparam USE_DIV = 1;
|
||||
|
||||
//Enable Atomic extension (cache operations only)
|
||||
localparam USE_AMO = 0;
|
||||
|
||||
//CSR Options
|
||||
typedef struct packed {
|
||||
bit [31:0] MACHINE_IMPLEMENTATION_ID;
|
||||
bit [31:0] CPU_ID;
|
||||
bit [31:0] RESET_VEC; //PC value on reset
|
||||
int unsigned COUNTER_W; //CSR counter width (33-64 bits): 48-bits --> 32 days @ 100MHz
|
||||
} csr_config_t;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Memory Sources
|
||||
//Must select at least one source for instruction and data interfaces
|
||||
//Cache Options
|
||||
//Size in bytes: (LINES * WAYS * LINE_W * 4)
|
||||
//For optimal BRAM packing, LINES should not be less than 512
|
||||
typedef struct packed {
|
||||
int unsigned LINES;
|
||||
int unsigned LINE_W;// In words
|
||||
int unsigned WAYS;
|
||||
bit USE_EXTERNAL_INVALIDATIONS;
|
||||
} cache_config_t;
|
||||
|
||||
//Local memory
|
||||
localparam USE_I_SCRATCH_MEM = 1;
|
||||
localparam USE_D_SCRATCH_MEM = 1;
|
||||
typedef struct packed {
|
||||
int unsigned LINE_ADDR_W;
|
||||
int unsigned SUB_LINE_ADDR_W;
|
||||
int unsigned TAG_W;
|
||||
} derived_cache_config_t;
|
||||
|
||||
//Peripheral bus
|
||||
//Memory range [L, H]
|
||||
//Address range is inclusive and must be aligned to its size
|
||||
typedef struct packed {
|
||||
bit [31:0] L;
|
||||
bit [31:0] H;
|
||||
} memory_config_t;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Branch Predictor Options
|
||||
typedef struct packed {
|
||||
int unsigned WAYS;
|
||||
int unsigned ENTRIES;//min512
|
||||
int unsigned RAS_ENTRIES;
|
||||
} branch_predictor_config_t;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Bus Options
|
||||
typedef enum {
|
||||
AXI_BUS,
|
||||
AVALON_BUS,
|
||||
WISHBONE_BUS
|
||||
} bus_type_t;
|
||||
|
||||
localparam USE_BUS = 1;
|
||||
localparam bus_type_t BUS_TYPE = AXI_BUS;
|
||||
|
||||
//Caches
|
||||
localparam USE_DCACHE = 0;
|
||||
localparam USE_ICACHE = 0;
|
||||
|
||||
} peripheral_bus_type_t;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Address space
|
||||
localparam SCRATCH_ADDR_L = 32'h80000000;
|
||||
localparam SCRATCH_ADDR_H = 32'h8001FFFF;
|
||||
localparam SCRATCH_BIT_CHECK = 4;
|
||||
//TLB Options
|
||||
typedef struct packed {
|
||||
int unsigned WAYS;
|
||||
int unsigned DEPTH;
|
||||
} tlb_config_t;
|
||||
|
||||
localparam MEMORY_ADDR_L = 32'h40000000;
|
||||
localparam MEMORY_ADDR_H = 32'h4FFFFFFF;
|
||||
localparam MEMORY_BIT_CHECK = 4;
|
||||
typedef struct packed {
|
||||
//ISA options
|
||||
bit INCLUDE_M_MODE;
|
||||
bit INCLUDE_S_MODE;
|
||||
bit INCLUDE_U_MODE;
|
||||
bit INCLUDE_MUL;
|
||||
bit INCLUDE_DIV;
|
||||
bit INCLUDE_AMO; //Enable Atomic extension (cache operations only)
|
||||
csr_config_t CSRS;
|
||||
//Memory Options
|
||||
bit INCLUDE_ICACHE;
|
||||
cache_config_t ICACHE;
|
||||
memory_config_t ICACHE_ADDR;
|
||||
tlb_config_t ITLB;
|
||||
bit INCLUDE_DCACHE;
|
||||
cache_config_t DCACHE;
|
||||
memory_config_t DCACHE_ADDR;
|
||||
tlb_config_t DTLB;
|
||||
bit INCLUDE_ILOCAL_MEM;
|
||||
memory_config_t ILOCAL_MEM_ADDR;
|
||||
bit INCLUDE_DLOCAL_MEM;
|
||||
memory_config_t DLOCAL_MEM_ADDR;
|
||||
bit INCLUDE_PERIPHERAL_BUS;
|
||||
memory_config_t PERIPHERAL_BUS_ADDR;
|
||||
peripheral_bus_type_t PERIPHERAL_BUS_TYPE;
|
||||
//Branch Predictor Options
|
||||
bit INCLUDE_BRANCH_PREDICTOR;
|
||||
branch_predictor_config_t BP;
|
||||
//Writeback Options
|
||||
int unsigned NUM_WB_GROUPS;
|
||||
} cpu_config_t;
|
||||
|
||||
localparam BUS_ADDR_L = 32'h60000000;
|
||||
localparam BUS_ADDR_H = 32'h6FFFFFFF;
|
||||
localparam BUS_BIT_CHECK = 4;
|
||||
//Function to generate derived cache parameters
|
||||
//Tag width based off of memory size and cache parameters
|
||||
function derived_cache_config_t get_derived_cache_params (input cpu_config_t cpu, input cache_config_t cache, input memory_config_t addr);
|
||||
return '{
|
||||
LINE_ADDR_W : $clog2(cache.LINES),
|
||||
SUB_LINE_ADDR_W : $clog2(cache.LINE_W),
|
||||
TAG_W : $clog2(64'(addr.H)-64'(addr.L)+1) - $clog2(cache.LINES) - $clog2(cache.LINE_W) - 2
|
||||
};
|
||||
endfunction
|
||||
|
||||
//PC address on reset
|
||||
localparam bit[31:0] RESET_VEC = 32'h80000000;
|
||||
|
||||
localparam cpu_config_t EXAMPLE_CONFIG = '{
|
||||
//ISA options
|
||||
INCLUDE_M_MODE : 1,
|
||||
INCLUDE_S_MODE : 1,
|
||||
INCLUDE_U_MODE : 1,
|
||||
INCLUDE_MUL : 1,
|
||||
INCLUDE_DIV : 1,
|
||||
INCLUDE_AMO : 0,
|
||||
CSRS : '{
|
||||
MACHINE_IMPLEMENTATION_ID : 0,
|
||||
CPU_ID : 0,
|
||||
RESET_VEC : 32'h80000000,
|
||||
COUNTER_W : 33
|
||||
},
|
||||
//Memory Options
|
||||
INCLUDE_ICACHE : 0,
|
||||
ICACHE_ADDR : '{
|
||||
L: 32'h40000000,
|
||||
H: 32'h4FFFFFFF
|
||||
},
|
||||
ICACHE : '{
|
||||
LINES : 512,
|
||||
LINE_W : 4,
|
||||
WAYS : 2,
|
||||
USE_EXTERNAL_INVALIDATIONS : 0
|
||||
},
|
||||
ITLB : '{
|
||||
WAYS : 2,
|
||||
DEPTH : 64
|
||||
},
|
||||
INCLUDE_DCACHE : 0,
|
||||
DCACHE_ADDR : '{
|
||||
L: 32'h40000000,
|
||||
H: 32'h4FFFFFFF
|
||||
},
|
||||
DCACHE : '{
|
||||
LINES : 512,
|
||||
LINE_W : 4,
|
||||
WAYS : 2,
|
||||
USE_EXTERNAL_INVALIDATIONS : 0
|
||||
},
|
||||
DTLB : '{
|
||||
WAYS : 2,
|
||||
DEPTH : 64
|
||||
},
|
||||
INCLUDE_ILOCAL_MEM : 1,
|
||||
ILOCAL_MEM_ADDR : '{
|
||||
L : 32'h80000000,
|
||||
H : 32'h8FFFFFFF
|
||||
},
|
||||
INCLUDE_DLOCAL_MEM : 1,
|
||||
DLOCAL_MEM_ADDR : '{
|
||||
L : 32'h80000000,
|
||||
H : 32'h8FFFFFFF
|
||||
},
|
||||
INCLUDE_PERIPHERAL_BUS : 1,
|
||||
PERIPHERAL_BUS_ADDR : '{
|
||||
L : 32'h60000000,
|
||||
H : 32'h6FFFFFFF
|
||||
},
|
||||
PERIPHERAL_BUS_TYPE : AXI_BUS,
|
||||
//Branch Predictor Options
|
||||
INCLUDE_BRANCH_PREDICTOR : 1,
|
||||
BP : '{
|
||||
WAYS : 2,
|
||||
ENTRIES : 512,
|
||||
RAS_ENTRIES : 8
|
||||
},
|
||||
NUM_WB_GROUPS : 2
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit IDs
|
||||
typedef struct packed {
|
||||
int unsigned ALU;
|
||||
int unsigned LS;
|
||||
int unsigned CSR;
|
||||
int unsigned MUL;
|
||||
int unsigned DIV;
|
||||
int unsigned BR;
|
||||
} unit_id_param_t;
|
||||
|
||||
localparam unit_id_param_t EXAMPLE_UNIT_IDS = '{
|
||||
ALU : 0,
|
||||
LS : 1,
|
||||
CSR : 2,
|
||||
MUL : 3,
|
||||
DIV : 4,
|
||||
BR : 5
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Bus Options
|
||||
parameter C_M_AXI_ADDR_WIDTH = 32; //Kept as parameter, due to localparam failing with scripted IP packaging
|
||||
parameter C_M_AXI_DATA_WIDTH = 32; //Kept as parameter, due to localparam failing with scripted IP packaging
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instruction Cache Options
|
||||
//Size in bytes: (ICACHE_LINES * ICACHE_WAYS * ICACHE_LINE_W * 4)
|
||||
//For optimal BRAM packing, lines should not be less than 512
|
||||
localparam ICACHE_LINES = 512;
|
||||
localparam ICACHE_WAYS = 2;
|
||||
localparam ICACHE_LINE_ADDR_W = $clog2(ICACHE_LINES);
|
||||
localparam ICACHE_LINE_W = 4; //In words
|
||||
localparam ICACHE_SUB_LINE_ADDR_W = $clog2(ICACHE_LINE_W);
|
||||
localparam ICACHE_TAG_W = $clog2(64'(MEMORY_ADDR_H)-64'(MEMORY_ADDR_L)+1) - ICACHE_LINE_ADDR_W - ICACHE_SUB_LINE_ADDR_W - 2;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Data Cache Options
|
||||
//Size in bytes: (DCACHE_LINES * DCACHE_WAYS * DCACHE_LINE_W * 4)
|
||||
//For optimal BRAM packing, lines should not be less than 512
|
||||
localparam DCACHE_LINES = 512;
|
||||
localparam DCACHE_WAYS = 2;
|
||||
localparam DCACHE_LINE_ADDR_W = $clog2(DCACHE_LINES);
|
||||
localparam DCACHE_LINE_W = 4; //In words
|
||||
localparam DCACHE_SUB_LINE_ADDR_W = $clog2(DCACHE_LINE_W);
|
||||
localparam DCACHE_TAG_W = $clog2(64'(MEMORY_ADDR_H)-64'(MEMORY_ADDR_L)+1) - DCACHE_LINE_ADDR_W - DCACHE_SUB_LINE_ADDR_W - 2;
|
||||
|
||||
localparam USE_DTAG_INVALIDATIONS = 0;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instruction TLB Options
|
||||
localparam ITLB_WAYS = 2;
|
||||
localparam ITLB_DEPTH = 32;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Data TLB Options
|
||||
localparam DTLB_WAYS = 2;
|
||||
localparam DTLB_DEPTH = 32;
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Branch Predictor Options
|
||||
localparam USE_BRANCH_PREDICTOR = 1;
|
||||
localparam BRANCH_PREDICTOR_WAYS = 2;
|
||||
localparam BRANCH_TABLE_ENTRIES = 512; //min 512
|
||||
localparam RAS_DEPTH = 8;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID limit
|
||||
//MAX_IDS restricted to a power of 2
|
||||
|
@ -154,7 +230,7 @@ package taiga_config;
|
|||
//Number of commit ports
|
||||
localparam RETIRE_PORTS = 2; //min 1. (Non-powers of two supported) > 1 is recommended to allow stores to commit sooner
|
||||
localparam REGFILE_READ_PORTS = 2; //min 2, for RS1 and RS2. (Non-powers of two supported)
|
||||
typedef enum logic {
|
||||
typedef enum bit {
|
||||
RS1 = 0,
|
||||
RS2 = 1
|
||||
} rs1_index_t;
|
||||
|
@ -167,41 +243,13 @@ package taiga_config;
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//L1 Arbiter IDs
|
||||
localparam L1_CONNECTIONS = 4;//USE_ICACHE + USE_DCACHE + ENABLE_S_MODE*2;
|
||||
localparam L1_DCACHE_ID = 0;
|
||||
localparam L1_DMMU_ID = 1;//ENABLE_S_MODE;
|
||||
localparam L1_ICACHE_ID = 2;//ENABLE_S_MODE + USE_DCACHE;
|
||||
localparam L1_IMMU_ID = 3;//ENABLE_S_MODE + USE_DCACHE + USE_ICACHE;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Write-Back Unit IDs
|
||||
localparam NUM_WB_UNITS_GROUP_1 = 1;//ALU
|
||||
localparam NUM_WB_UNITS_GROUP_2 = 2 + USE_MUL + USE_DIV;//LS + CSR
|
||||
localparam NUM_WB_UNITS = NUM_WB_UNITS_GROUP_1 + NUM_WB_UNITS_GROUP_2;
|
||||
localparam NUM_UNITS = NUM_WB_UNITS + 1;//Branch
|
||||
|
||||
localparam NUM_WB_GROUPS = 2;
|
||||
localparam int NUM_WB_UNITS_GROUP [2] = '{NUM_WB_UNITS_GROUP_1, NUM_WB_UNITS_GROUP_2};
|
||||
localparam int CUMULATIVE_NUM_WB_UNITS_GROUP [2] = '{0, NUM_WB_UNITS_GROUP_1};
|
||||
|
||||
localparam ALU_UNIT_ID = 0;
|
||||
localparam LS_UNIT_ID = 1;
|
||||
localparam DIV_UNIT_ID = LS_UNIT_ID + USE_DIV;
|
||||
localparam MUL_UNIT_ID = DIV_UNIT_ID + USE_MUL;
|
||||
localparam GC_UNIT_ID = MUL_UNIT_ID + 1;
|
||||
//Non-writeback units
|
||||
localparam BRANCH_UNIT_ID = GC_UNIT_ID + 1;
|
||||
|
||||
//Writeback group 1
|
||||
localparam ALU_UNIT_WB1_ID = 0;
|
||||
|
||||
//Writeback group 2
|
||||
localparam LS_UNIT_WB2_ID = 0;
|
||||
localparam DIV_UNIT_WB2_ID = LS_UNIT_WB2_ID + USE_DIV;
|
||||
localparam MUL_UNIT_WB2_ID = DIV_UNIT_WB2_ID + USE_MUL;
|
||||
localparam GC_UNIT_WB2_ID = MUL_UNIT_WB2_ID + 1;
|
||||
|
||||
|
||||
localparam L1_CONNECTIONS = 4;
|
||||
typedef enum bit [1:0] {
|
||||
L1_DCACHE_ID = 0,
|
||||
L1_DMMU_ID = 1,
|
||||
L1_ICACHE_ID = 2,
|
||||
L1_IMMU_ID = 3
|
||||
} l1_id_t;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Debug Parameters
|
||||
|
|
|
@ -25,17 +25,13 @@ package taiga_types;
|
|||
import riscv_types::*;
|
||||
|
||||
localparam LOG2_RETIRE_PORTS = $clog2(RETIRE_PORTS);
|
||||
localparam WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS);
|
||||
localparam LOG2_COMMIT_PORTS = $clog2(NUM_WB_GROUPS);
|
||||
localparam LOG2_MAX_IDS = $clog2(MAX_IDS);
|
||||
|
||||
typedef logic[LOG2_MAX_IDS-1:0] id_t;
|
||||
typedef logic[WB_UNITS_WIDTH-1:0] unit_id_t;
|
||||
typedef logic[1:0] branch_predictor_metadata_t;
|
||||
|
||||
typedef logic [3:0] addr_hash_t;
|
||||
typedef logic [5:0] phys_addr_t;
|
||||
typedef logic [$clog2(NUM_WB_GROUPS)-1:0] rs_wb_group_t;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
ALU_CONSTANT = 2'b00,
|
||||
|
@ -58,12 +54,6 @@ package taiga_types;
|
|||
id_t id;
|
||||
} exception_packet_t;
|
||||
|
||||
typedef struct packed{
|
||||
branch_predictor_metadata_t branch_predictor_metadata;
|
||||
logic branch_prediction_used;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] branch_predictor_update_way;
|
||||
} branch_metadata_t;
|
||||
|
||||
typedef enum logic {
|
||||
FETCH_ACCESS_FAULT = 1'b0,
|
||||
FETCH_PAGE_FAULT = 1'b1
|
||||
|
@ -90,15 +80,14 @@ package taiga_types;
|
|||
|
||||
rs_addr_t [REGFILE_READ_PORTS-1:0] rs_addr;
|
||||
phys_addr_t [REGFILE_READ_PORTS-1:0] phys_rs_addr;
|
||||
rs_wb_group_t [REGFILE_READ_PORTS-1:0] rs_wb_group;
|
||||
|
||||
rs_addr_t rd_addr;
|
||||
phys_addr_t phys_rd_addr;
|
||||
rs_wb_group_t rd_wb_group;
|
||||
|
||||
logic uses_rs1;
|
||||
logic uses_rs2;
|
||||
logic uses_rd;
|
||||
logic is_multicycle;
|
||||
id_t id;
|
||||
logic stage_valid;
|
||||
fetch_metadata_t fetch_metadata;
|
||||
|
@ -133,13 +122,14 @@ package taiga_types;
|
|||
} branch_inputs_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic[31:0] pc_ex;
|
||||
logic [31:0] new_pc;
|
||||
id_t id;
|
||||
logic valid;
|
||||
logic [31:0] pc;
|
||||
logic [31:0] target_pc;
|
||||
logic branch_taken;
|
||||
logic branch_ex;
|
||||
logic is_branch_ex;
|
||||
logic is_return_ex;
|
||||
logic is_call_ex;
|
||||
logic is_branch;
|
||||
logic is_return;
|
||||
logic is_call;
|
||||
} branch_results_t;
|
||||
|
||||
typedef struct packed{
|
||||
|
@ -314,10 +304,6 @@ package taiga_types;
|
|||
logic rs2_forwarding_needed;
|
||||
logic rs1_and_rs2_forwarding_needed;
|
||||
|
||||
//Writeback
|
||||
unit_id_t num_instructions_completing;
|
||||
id_t num_instructions_in_flight;
|
||||
id_t num_of_instructions_pending_writeback;
|
||||
} taiga_trace_events_t;
|
||||
|
||||
typedef struct packed {
|
||||
|
|
|
@ -26,38 +26,58 @@ module writeback
|
|||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG,
|
||||
parameter int unsigned NUM_UNITS [CONFIG.NUM_WB_GROUPS] = '{1, 4},
|
||||
parameter int unsigned NUM_WB_UNITS = 5
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
//Unit writeback
|
||||
unit_writeback_interface.wb unit_wb[NUM_WB_UNITS],
|
||||
//WB output
|
||||
output wb_packet_t wb_packet [NUM_WB_GROUPS],
|
||||
output wb_packet_t wb_packet [CONFIG.NUM_WB_GROUPS],
|
||||
//Snoop interface (LS unit)
|
||||
output wb_packet_t wb_snoop
|
||||
);
|
||||
|
||||
//Writeback
|
||||
logic [NUM_WB_UNITS-1:0] unit_ack [NUM_WB_GROUPS];
|
||||
logic [NUM_WB_UNITS-1:0] unit_ack [CONFIG.NUM_WB_GROUPS];
|
||||
//aliases for write-back-interface signals
|
||||
id_t [NUM_WB_UNITS-1:0] unit_instruction_id [NUM_WB_GROUPS];
|
||||
logic [NUM_WB_UNITS-1:0] unit_done [NUM_WB_GROUPS];
|
||||
id_t [NUM_WB_UNITS-1:0] unit_instruction_id [CONFIG.NUM_WB_GROUPS];
|
||||
logic [NUM_WB_UNITS-1:0] unit_done [CONFIG.NUM_WB_GROUPS];
|
||||
|
||||
typedef logic [XLEN-1:0] unit_rd_t [NUM_WB_UNITS];
|
||||
unit_rd_t unit_rd [NUM_WB_GROUPS];
|
||||
unit_rd_t unit_rd [CONFIG.NUM_WB_GROUPS];
|
||||
//Per-ID muxes for commit buffer
|
||||
logic [$clog2(NUM_WB_UNITS)-1:0] unit_sel [NUM_WB_GROUPS];
|
||||
logic [$clog2(NUM_WB_UNITS)-1:0] unit_sel [CONFIG.NUM_WB_GROUPS];
|
||||
|
||||
typedef int unsigned unit_count_t [CONFIG.NUM_WB_GROUPS];
|
||||
|
||||
function unit_count_t get_cumulative_unit_count();
|
||||
unit_count_t counts;
|
||||
int unsigned cumulative_count = 0;
|
||||
for (int i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin
|
||||
counts[i] = cumulative_count;
|
||||
cumulative_count += NUM_UNITS[i];
|
||||
end
|
||||
return counts;
|
||||
endfunction
|
||||
|
||||
localparam unit_count_t CUMULATIVE_NUM_UNITS = get_cumulative_unit_count();
|
||||
|
||||
genvar i, j;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
//Re-assigning interface inputs to array types so that they can be dynamically indexed
|
||||
generate
|
||||
for (i = 0; i < NUM_WB_GROUPS; i++) begin
|
||||
for (j = 0; j < NUM_WB_UNITS_GROUP[i]; j++) begin
|
||||
assign unit_instruction_id[i][j] = unit_wb[CUMULATIVE_NUM_WB_UNITS_GROUP[i] + j].id;
|
||||
assign unit_done[i][j] = unit_wb[CUMULATIVE_NUM_WB_UNITS_GROUP[i] + j].done;
|
||||
assign unit_wb[CUMULATIVE_NUM_WB_UNITS_GROUP[i] + j].ack = unit_ack[i][j];
|
||||
for (i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin
|
||||
for (j = 0; j < NUM_UNITS[i]; j++) begin
|
||||
assign unit_instruction_id[i][j] = unit_wb[CUMULATIVE_NUM_UNITS[i] + j].id;
|
||||
assign unit_done[i][j] = unit_wb[CUMULATIVE_NUM_UNITS[i] + j].done;
|
||||
assign unit_wb[CUMULATIVE_NUM_UNITS[i] + j].ack = unit_ack[i][j];
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
@ -65,9 +85,9 @@ module writeback
|
|||
//As units are selected for commit ports based on their unit ID,
|
||||
//for each additional commit port one unit can be skipped for the commit mux
|
||||
generate
|
||||
for (i = 0; i < NUM_WB_GROUPS; i++) begin
|
||||
for (j = 0; j < NUM_WB_UNITS_GROUP[i]; j++) begin
|
||||
assign unit_rd[i][j] = unit_wb[CUMULATIVE_NUM_WB_UNITS_GROUP[i] + j].rd;
|
||||
for (i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin
|
||||
for (j = 0; j < NUM_UNITS[i]; j++) begin
|
||||
assign unit_rd[i][j] = unit_wb[CUMULATIVE_NUM_UNITS[i] + j].rd;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
@ -77,13 +97,13 @@ module writeback
|
|||
//Iterating through all commit ports:
|
||||
// Search for complete units (in fixed unit order)
|
||||
// Assign to a commit port, mask that unit and commit port
|
||||
generate for (i = 0; i < NUM_WB_GROUPS; i++) begin
|
||||
generate for (i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin
|
||||
priority_encoder
|
||||
#(.WIDTH(NUM_WB_UNITS_GROUP[i]))
|
||||
#(.WIDTH(NUM_UNITS[i]))
|
||||
unit_done_encoder
|
||||
(
|
||||
.priority_vector (unit_done[i][NUM_WB_UNITS_GROUP[i]-1 : 0]),
|
||||
.encoded_result (unit_sel[i][NUM_WB_UNITS_GROUP[i] == 1 ? 0 : ($clog2(NUM_WB_UNITS_GROUP[i])-1) : 0])
|
||||
.priority_vector (unit_done[i][NUM_UNITS[i]-1 : 0]),
|
||||
.encoded_result (unit_sel[i][NUM_UNITS[i] == 1 ? 0 : ($clog2(NUM_UNITS[i])-1) : 0])
|
||||
);
|
||||
assign wb_packet[i].valid = |unit_done[i];
|
||||
assign wb_packet [i].id = unit_instruction_id[i][unit_sel[i]];
|
||||
|
@ -91,7 +111,7 @@ module writeback
|
|||
end endgenerate
|
||||
|
||||
always_comb begin
|
||||
for (int i = 0; i < NUM_WB_GROUPS; i++) begin
|
||||
for (int i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin
|
||||
unit_ack[i] = '0;
|
||||
unit_ack[i][unit_sel[i]] = wb_packet[i].valid;
|
||||
end
|
||||
|
|
|
@ -235,7 +235,7 @@ module taiga_wrapper (
|
|||
//design_2 infra(.*);
|
||||
|
||||
generate
|
||||
if (ENABLE_S_MODE || USE_ICACHE || USE_DCACHE) begin
|
||||
if (EXAMPLE_CONFIG.INCLUDE_S_MODE || EXAMPLE_CONFIG.INCLUDE_ICACHE || EXAMPLE_CONFIG.INCLUDE_DCACHE) begin
|
||||
l2_arbiter l2_arb (.*, .request(l2));
|
||||
axi_to_arb l2_to_mem (.*, .l2(mem));
|
||||
end
|
||||
|
|
|
@ -68,10 +68,7 @@ static const char * const eventNames[] = {
|
|||
"load_conflict_delay",
|
||||
"rs1_forwarding_needed",
|
||||
"rs2_forwarding_needed",
|
||||
"rs1_and_rs2_forwarding_needed",
|
||||
"num_instructions_completing",
|
||||
"num_instructions_in_flight",
|
||||
"num_of_instructions_pending_writeback"
|
||||
"rs1_and_rs2_forwarding_needed"
|
||||
};
|
||||
static const int numEvents = arraySize(eventNames);
|
||||
|
||||
|
|
|
@ -286,7 +286,7 @@ module taiga_sim
|
|||
assign data_bram_data_in = data_bram.data_in;
|
||||
assign data_bram.data_out = data_bram_data_out;
|
||||
|
||||
taiga cpu(.*, .l2(l2[0]));
|
||||
taiga #(.CONFIG(EXAMPLE_CONFIG)) cpu(.*, .l2(l2[0]));
|
||||
|
||||
//read channel
|
||||
logic[3:0] read_counter;
|
||||
|
@ -436,13 +436,13 @@ module taiga_sim
|
|||
////////////////////////////////////////////////////
|
||||
//Performs the lookups to provide the speculative architectural register file with
|
||||
//standard register names for simulation purposes
|
||||
logic [31:0][31:0] sim_registers_unamed_groups[NUM_WB_GROUPS];
|
||||
logic [31:0][31:0] sim_registers_unamed_groups[EXAMPLE_CONFIG.NUM_WB_GROUPS];
|
||||
logic [31:0][31:0] sim_registers_unamed;
|
||||
|
||||
simulation_named_regfile sim_register;
|
||||
genvar i, j;
|
||||
generate for (i = 0; i < 32; i++) begin
|
||||
for (j = 0; j < NUM_WB_GROUPS; j++) begin
|
||||
for (j = 0; j < EXAMPLE_CONFIG.NUM_WB_GROUPS; j++) begin
|
||||
assign sim_registers_unamed_groups[j][i] =
|
||||
cpu.register_file_block.register_file_gen[j].reg_group.register_file_bank[cpu.renamer_block.spec_table[i].phys_addr];
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue