mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-23 21:47:15 -04:00
initial ID rework for processor front end
This commit is contained in:
parent
a31320a79f
commit
06f3c14115
17 changed files with 588 additions and 221 deletions
|
@ -29,6 +29,7 @@ module branch_comparator(
|
|||
input logic less_than,
|
||||
input logic [31:0] a,
|
||||
input logic [31:0] b,
|
||||
input logic xor_result,
|
||||
output logic result
|
||||
);
|
||||
|
||||
|
@ -45,6 +46,7 @@ module branch_comparator(
|
|||
logic [15:0] sub_eq_a;
|
||||
|
||||
logic [15:0] sub_toss;
|
||||
logic carry_out;
|
||||
|
||||
logic eq_carry_in;
|
||||
logic ls_carry_in;
|
||||
|
@ -87,6 +89,11 @@ module branch_comparator(
|
|||
|
||||
sub_eq_a[i] = (eq_a[2*i] | eq_b[2*i]) & (eq_a[2*i + 1] | eq_b[2*i + 1]); //bits are equal
|
||||
end
|
||||
//branch_inputs.fn3[0] is xor_result and selects the inverse result
|
||||
//i.e. (not eq, greater than). Included here to reduce the number of inputs
|
||||
//in the branch target adder
|
||||
sub_ls_a[15] ^= xor_result;
|
||||
sub_eq_a[15] ^= xor_result;
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -27,7 +27,10 @@ import taiga_types::*;
|
|||
module branch_predictor (
|
||||
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
|
||||
);
|
||||
|
||||
|
@ -62,24 +65,25 @@ module branch_predictor (
|
|||
branch_table_entry_t if_entry [BRANCH_PREDICTOR_WAYS-1:0];
|
||||
branch_table_entry_t ex_entry;
|
||||
|
||||
logic branch_predictor_direction_changed;
|
||||
logic [31:0] new_jump_addr;
|
||||
logic [31:0] predicted_pc [BRANCH_PREDICTOR_WAYS-1:0];
|
||||
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] tag_matches;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] replacement_way;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] update_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 tag_match;
|
||||
logic use_predicted_pc;
|
||||
/////////////////////////////////////////
|
||||
|
||||
cycler #(BRANCH_PREDICTOR_WAYS) replacement_policy (.*, .en(1'b1), .one_hot(replacement_way));
|
||||
|
||||
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))
|
||||
tag_bank (.*,
|
||||
.write_addr(br_results.pc_ex[2 +: BRANCH_ADDR_W]), .write_en(update_way[i]), .write_data(ex_entry),
|
||||
.write_addr(br_results.pc_ex[2 +: BRANCH_ADDR_W]), .write_en(tag_update_way[i]), .write_data(ex_entry),
|
||||
.read_addr(bp.next_pc[2 +: BRANCH_ADDR_W]), .read_en(bp.new_mem_request), .read_data(if_entry[i]));
|
||||
end
|
||||
endgenerate
|
||||
|
@ -88,7 +92,7 @@ module 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))
|
||||
addr_table (.*,
|
||||
.write_addr(br_results.pc_ex[2 +: BRANCH_ADDR_W]), .write_en(update_way[i]), .write_data(new_jump_addr),
|
||||
.write_addr(br_results.pc_ex[2 +: BRANCH_ADDR_W]), .write_en(target_update_way[i]), .write_data(br_results.new_pc),
|
||||
.read_addr(bp.next_pc[2 +: BRANCH_ADDR_W]), .read_en(bp.new_mem_request), .read_data(predicted_pc[i]));
|
||||
end
|
||||
endgenerate
|
||||
|
@ -99,6 +103,8 @@ module branch_predictor (
|
|||
end
|
||||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instruction Fetch Response
|
||||
generate if (BRANCH_PREDICTOR_WAYS > 1)
|
||||
one_hot_to_integer #(BRANCH_PREDICTOR_WAYS) hit_way_conv (.*, .one_hot(tag_matches), .int_out(hit_way));
|
||||
else
|
||||
|
@ -106,38 +112,46 @@ module branch_predictor (
|
|||
endgenerate
|
||||
assign tag_match = |tag_matches;
|
||||
|
||||
assign bp.predicted_pc = predicted_pc[hit_way];
|
||||
assign bp.metadata = if_entry[hit_way].metadata;
|
||||
assign bp.use_ras = if_entry[hit_way].use_ras;
|
||||
assign bp.update_way = tag_matches;
|
||||
assign use_predicted_pc = USE_BRANCH_PREDICTOR & tag_match;
|
||||
|
||||
//Predict next branch to same location/direction as current
|
||||
//Predicted PC and whether the prediction is valid
|
||||
assign bp.predicted_pc = predicted_pc[hit_way];
|
||||
assign bp.use_prediction = use_predicted_pc;
|
||||
assign bp.use_ras = if_entry[hit_way].use_ras;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Execution stage update
|
||||
assign ex_entry.valid = 1;
|
||||
assign ex_entry.tag = get_tag(br_results.pc_ex);
|
||||
assign ex_entry.use_ras = br_results.is_return_ex;
|
||||
|
||||
assign new_jump_addr = ex_entry.metadata[1] ? br_results.jump_pc : br_results.njump_pc;
|
||||
|
||||
//2-bit saturating counter
|
||||
always_comb begin
|
||||
case(br_results.branch_ex_metadata)
|
||||
case(branch_metadata_ex.branch_predictor_metadata)
|
||||
2'b00 : ex_entry.metadata = br_results.branch_taken ? 2'b01 : 2'b00;
|
||||
2'b01 : ex_entry.metadata = br_results.branch_taken ? 2'b10 : 2'b00;
|
||||
2'b10 : ex_entry.metadata = br_results.branch_taken ? 2'b11 : 2'b01;
|
||||
2'b11 : ex_entry.metadata = br_results.branch_taken ? 2'b11 : 2'b10;
|
||||
endcase
|
||||
if (~br_results.branch_prediction_used)
|
||||
if (~branch_metadata_ex.branch_prediction_used)
|
||||
ex_entry.metadata = br_results.branch_taken ? 2'b11 : 2'b00;
|
||||
end
|
||||
assign branch_predictor_direction_changed =
|
||||
(~branch_metadata_ex.branch_prediction_used) |
|
||||
(branch_metadata_ex.branch_predictor_metadata[1] ^ ex_entry.metadata[1]);
|
||||
|
||||
assign update_way = {BRANCH_PREDICTOR_WAYS{br_results.branch_ex}} & (br_results.branch_prediction_used ? br_results.bp_update_way : replacement_way);
|
||||
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;
|
||||
////////////////////////////////////////////////////
|
||||
//Target PC if branch flush occured
|
||||
assign bp.branch_flush_pc = br_results.new_pc;
|
||||
|
||||
assign bp.branch_flush_pc = br_results.branch_taken ? br_results.jump_pc : br_results.njump_pc;
|
||||
////////////////////////////////////////////////////
|
||||
//Instruction Fetch metadata
|
||||
cycler #(BRANCH_PREDICTOR_WAYS) replacement_policy (.*, .en(1'b1), .one_hot(replacement_way));
|
||||
|
||||
generate if (USE_BRANCH_PREDICTOR) begin
|
||||
assign bp.use_prediction = tag_match;
|
||||
end else begin
|
||||
assign bp.use_prediction = 0;
|
||||
end endgenerate
|
||||
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;
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -30,10 +30,14 @@ module branch_unit(
|
|||
|
||||
unit_issue_interface.unit issue,
|
||||
input branch_inputs_t branch_inputs,
|
||||
input logic [31:0] dec_pc_plus_4,//Sourced from ALU datapath on jal/jalr
|
||||
output branch_results_t br_results,
|
||||
ras_interface.branch_unit ras,
|
||||
output logic branch_flush,
|
||||
|
||||
output logic branch_complete,
|
||||
output id_t branch_id,
|
||||
|
||||
output logic potential_branch_exception,
|
||||
output logic branch_exception_is_jump,
|
||||
output exception_packet_t br_exception,
|
||||
|
@ -47,13 +51,7 @@ module branch_unit(
|
|||
|
||||
logic branch_issued_r;
|
||||
|
||||
logic[19:0] jal_imm;
|
||||
logic[11:0] jalr_imm;
|
||||
logic[11:0] br_imm;
|
||||
|
||||
logic [31:0] pc_offset;
|
||||
logic [31:0] jump_base;
|
||||
logic [31:0] jump_pc_dec;
|
||||
|
||||
logic result;
|
||||
logic result_ex;
|
||||
|
@ -63,10 +61,15 @@ module branch_unit(
|
|||
|
||||
//Branch Predictor
|
||||
logic branch_taken;
|
||||
logic branch_taken_ex;
|
||||
logic branch_correctly_taken;
|
||||
logic branch_correclty_not_taken;
|
||||
logic miss_predict;
|
||||
|
||||
id_t id_ex;
|
||||
logic [31:0] new_pc;
|
||||
logic [31:0] new_pc_ex;
|
||||
|
||||
logic [31:0] pc_ex;
|
||||
logic [31:0] jump_pc;
|
||||
logic [31:0] njump_pc;
|
||||
|
@ -102,23 +105,11 @@ module branch_unit(
|
|||
.less_than(branch_inputs.fn3[2]),
|
||||
.a(branch_inputs.rs1),
|
||||
.b(branch_inputs.rs2),
|
||||
.xor_result(branch_inputs.fn3[0]),
|
||||
.result(result)
|
||||
);
|
||||
|
||||
assign branch_taken = (~jump_ex & (result_ex ^ fn3_ex[0])) | jump_ex;
|
||||
|
||||
assign jal_imm = {branch_inputs.instruction[31], branch_inputs.instruction[19:12], branch_inputs.instruction[20], branch_inputs.instruction[30:21]};
|
||||
assign jalr_imm = branch_inputs.instruction[31:20];
|
||||
assign br_imm = {branch_inputs.instruction[31], branch_inputs.instruction[7], branch_inputs.instruction[30:25], branch_inputs.instruction[11:8]};
|
||||
|
||||
always_comb begin
|
||||
unique if (branch_inputs.jalr)
|
||||
pc_offset = 32'(signed'(jalr_imm));
|
||||
else if (branch_inputs.jal)
|
||||
pc_offset = 32'(signed'({jal_imm, 1'b0}));
|
||||
else
|
||||
pc_offset = 32'(signed'({br_imm, 1'b0}));
|
||||
end
|
||||
assign branch_taken = result | branch_inputs.jalr | branch_inputs.jal;
|
||||
|
||||
always_comb begin
|
||||
if (branch_inputs.jalr)
|
||||
|
@ -127,13 +118,17 @@ module branch_unit(
|
|||
jump_base = branch_inputs.dec_pc;
|
||||
end
|
||||
|
||||
assign jump_pc_dec = jump_base + pc_offset;
|
||||
assign new_pc = jump_base + (branch_taken ? 32'(signed'(branch_inputs.pc_offset)) : 4);
|
||||
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (instruction_is_completing | ~branch_issued_r) begin
|
||||
branch_taken_ex <= branch_taken;
|
||||
new_pc_ex <= new_pc;
|
||||
fn3_ex <= branch_inputs.fn3;
|
||||
result_ex <= result;
|
||||
jump_ex <= (branch_inputs.jal | branch_inputs.jalr);
|
||||
id_ex <= issue.id;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -147,50 +142,42 @@ module branch_unit(
|
|||
jmp_instruction_id <= issue.instruction_id;
|
||||
end
|
||||
|
||||
assign potential_branch_exception = jump_pc_dec[1] & issue.new_request;
|
||||
assign potential_branch_exception = 0;// jump_pc_dec[1] & issue.new_request;
|
||||
|
||||
assign br_exception.valid = (jump_pc[1] & branch_taken) & branch_issued_r;
|
||||
assign br_exception.valid = 0;//(jump_pc[1] & branch_taken) & branch_issued_r;
|
||||
assign br_exception.code = INST_ADDR_MISSALIGNED;
|
||||
assign br_exception.pc = pc_ex;
|
||||
assign br_exception.tval = jump_pc;
|
||||
assign br_exception.tval = new_pc_ex;
|
||||
assign br_exception.id = jmp_instruction_id;
|
||||
|
||||
assign branch_exception_is_jump = (branch_inputs.jal | branch_inputs.jalr);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID Management
|
||||
assign branch_complete = instruction_is_completing;
|
||||
assign branch_id = id_ex;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Predictor support
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue.new_request)
|
||||
njump_pc <= dec_pc_plus_4;
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
if (instruction_is_completing | ~branch_issued_r) begin
|
||||
pc_ex <= branch_inputs.dec_pc;
|
||||
jump_pc <= {jump_pc_dec[31:1], 1'b0};
|
||||
njump_pc <= branch_inputs.dec_pc + 4;
|
||||
branch_metadata <= branch_inputs.branch_metadata;
|
||||
branch_prediction_used <= branch_inputs.branch_prediction_used;
|
||||
bp_update_way <= branch_inputs.bp_update_way;
|
||||
end
|
||||
end
|
||||
|
||||
assign br_results.pc_ex = pc_ex;
|
||||
assign br_results.jump_pc = jump_pc;
|
||||
assign br_results.njump_pc = njump_pc;
|
||||
assign br_results.branch_ex_metadata = branch_metadata;
|
||||
|
||||
assign br_results.branch_taken = branch_taken;
|
||||
assign br_results.new_pc = new_pc_ex;
|
||||
assign br_results.branch_taken = branch_taken_ex;
|
||||
assign br_results.branch_ex = instruction_is_completing;
|
||||
assign br_results.is_return_ex = is_return;
|
||||
assign br_results.branch_prediction_used = branch_prediction_used;
|
||||
assign br_results.bp_update_way = bp_update_way;
|
||||
|
||||
|
||||
assign branch_correctly_taken = {branch_taken, branch_inputs.dec_pc[31:1]} == {1'b1, jump_pc[31:1]};
|
||||
assign branch_correclty_not_taken = {branch_taken, branch_inputs.dec_pc[31:1]} == {1'b0, njump_pc[31:1]};
|
||||
assign miss_predict = ~(branch_correctly_taken | branch_correclty_not_taken);
|
||||
|
||||
assign branch_flush = USE_BRANCH_PREDICTOR ?
|
||||
instruction_is_completing & miss_predict:
|
||||
instruction_is_completing & branch_taken;
|
||||
assign branch_flush = instruction_is_completing && (branch_inputs.dec_pc[31:1] != new_pc_ex[31:1]);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//RAS support
|
||||
|
@ -217,10 +204,10 @@ module branch_unit(
|
|||
////////////////////////////////////////////////////
|
||||
//Trace Interface
|
||||
generate if (ENABLE_TRACE_INTERFACE) begin
|
||||
assign tr_branch_correct = instruction_is_completing & ~is_return & ~miss_predict;
|
||||
assign tr_branch_misspredict = instruction_is_completing & ~is_return & miss_predict;
|
||||
assign tr_return_correct = instruction_is_completing & is_return & ~miss_predict;
|
||||
assign tr_return_misspredict = instruction_is_completing & is_return & miss_predict;
|
||||
assign tr_branch_correct = instruction_is_completing & ~is_return & ~branch_flush;
|
||||
assign tr_branch_misspredict = instruction_is_completing & ~is_return & branch_flush;
|
||||
assign tr_return_correct = instruction_is_completing & is_return & ~branch_flush;
|
||||
assign tr_return_misspredict = instruction_is_completing & is_return & branch_flush;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ module csr_regs
|
|||
mmu_interface.csr dmmu,
|
||||
|
||||
//WB
|
||||
input logic instruction_complete,
|
||||
input logic instruction_retired,
|
||||
|
||||
|
||||
//External
|
||||
|
@ -490,13 +490,13 @@ endgenerate
|
|||
////////////////////////////////////////////////////
|
||||
//Timers and Counters
|
||||
//Register increment for instructions completed
|
||||
logic instruction_retired;
|
||||
assign instruction_retired = instruction_complete & ~gc_supress_writeback;
|
||||
logic instruction_completed;
|
||||
assign instruction_completed = instruction_retired & ~gc_supress_writeback;
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
inst_ret_inc <= 0;
|
||||
else
|
||||
inst_ret_inc <= INST_RET_INC_W'(instruction_retired) + INST_RET_INC_W'(instruction_issued_no_rd);
|
||||
inst_ret_inc <= INST_RET_INC_W'(instruction_completed) + INST_RET_INC_W'(instruction_issued_no_rd);
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
|
|
|
@ -28,9 +28,12 @@ module decode_and_issue (
|
|||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
output logic pre_decode_pop,
|
||||
input logic fb_valid,
|
||||
input fetch_buffer_packet_t fb,
|
||||
//ID Management
|
||||
output logic decode_advance,
|
||||
input id_t decode_id,
|
||||
input logic decode_id_valid,
|
||||
input logic [31:0] decode_pc,
|
||||
input logic [31:0] decode_instruction,
|
||||
|
||||
tracking_interface.decode ti,
|
||||
register_file_issue_interface.issue rf_issue,
|
||||
|
@ -51,6 +54,10 @@ module decode_and_issue (
|
|||
|
||||
|
||||
output logic instruction_issued,
|
||||
output id_t issue_id,
|
||||
output logic issue_stage_valid,
|
||||
output logic id_issued,
|
||||
output logic dummy_id_complete,
|
||||
output logic instruction_issued_no_rd,
|
||||
output logic instruction_issued_with_rd,
|
||||
output logic illegal_instruction,
|
||||
|
@ -111,8 +118,7 @@ module decode_and_issue (
|
|||
|
||||
logic illegal_instruction_pattern;
|
||||
|
||||
logic dec_advance;
|
||||
logic issue_stage_valid;
|
||||
logic issue_stage_ready;
|
||||
|
||||
logic [2:0] fn3_issue_stage;
|
||||
logic [6:0] opcode_issue_stage;
|
||||
|
@ -126,42 +132,37 @@ module decode_and_issue (
|
|||
genvar i;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
assign dec_advance = (~issue_stage_valid) | instruction_issued;
|
||||
assign issue_stage_ready = (~issue_stage_valid) | instruction_issued;
|
||||
assign decode_advance = decode_id_valid & issue_stage_ready;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst | gc_fetch_flush)
|
||||
issue_stage_valid <= 0;
|
||||
else if (dec_advance)
|
||||
issue_stage_valid <= fb_valid & ~gc_fetch_flush & ~illegal_instruction_pattern;
|
||||
else if (issue_stage_ready)
|
||||
issue_stage_valid <= decode_id_valid;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (dec_advance) begin
|
||||
pc_issue_stage <= fb.pc;
|
||||
instruction_issue_stage <= fb.instruction;
|
||||
if (issue_stage_ready) begin
|
||||
pc_issue_stage <= decode_pc;
|
||||
instruction_issue_stage <= decode_instruction;
|
||||
fn3_issue_stage <= fn3;
|
||||
opcode_issue_stage <= opcode;
|
||||
rs1_addr_issue_stage <= rs1_addr;
|
||||
rs2_addr_issue_stage <= rs2_addr;
|
||||
rd_addr_issue_stage <= rd_addr;
|
||||
uses_rd_issue_stage <= uses_rd;
|
||||
issue_id <= decode_id;
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instruction Buffer
|
||||
assign pre_decode_pop = fb_valid & dec_advance;
|
||||
|
||||
|
||||
|
||||
//Instruction aliases
|
||||
assign opcode = fb.instruction[6:0];
|
||||
assign opcode = decode_instruction[6:0];
|
||||
assign opcode_trim = opcode[6:2];
|
||||
assign fn3 = fb.instruction[14:12];
|
||||
assign rs1_addr = fb.instruction[19:15];
|
||||
assign rs2_addr = fb.instruction[24:20];
|
||||
assign rd_addr = fb.instruction[11:7];
|
||||
assign fn3 = decode_instruction[14:12];
|
||||
assign rs1_addr = decode_instruction[19:15];
|
||||
assign rs2_addr = decode_instruction[24:20];
|
||||
assign rd_addr = decode_instruction[11:7];
|
||||
|
||||
assign csr_imm_op = (opcode_trim == SYSTEM_T) && fn3[2];
|
||||
assign environment_op = (opcode_trim == SYSTEM_T) && (fn3 == 0);
|
||||
|
@ -182,7 +183,7 @@ module decode_and_issue (
|
|||
assign rf_issue.rd_addr = rd_addr_issue_stage;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (dec_advance) begin
|
||||
if (issue_stage_ready) begin
|
||||
rf_issue.uses_rs1 <= uses_rs1;
|
||||
rf_issue.uses_rs2 <= uses_rs2;
|
||||
end
|
||||
|
@ -200,7 +201,7 @@ module decode_and_issue (
|
|||
one_hot_to_integer #(NUM_WB_UNITS) unit_id_gen (.*, .one_hot(unit_needed_for_id_gen), .int_out(unit_needed_for_id_gen_int));
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (dec_advance) begin
|
||||
if (issue_stage_ready) begin
|
||||
ti.inflight_packet.is_store <= is_store;
|
||||
ti.issue_unit_id <= unit_needed_for_id_gen_int;
|
||||
ti.exception_possible <= opcode_trim inside {LOAD_T, STORE_T, AMO_T};
|
||||
|
@ -212,11 +213,11 @@ 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_WB_ID] = ((opcode_trim == ARITH_T) && ~fb.instruction[25]) || (opcode_trim inside {ARITH_IMM_T, AUIPC_T, LUI_T, JAL_T, JALR_T});
|
||||
assign unit_needed[ALU_UNIT_WB_ID] = ((opcode_trim == ARITH_T) && ~decode_instruction[25]) || (opcode_trim inside {ARITH_IMM_T, AUIPC_T, LUI_T, JAL_T, JALR_T});
|
||||
assign unit_needed[LS_UNIT_WB_ID] = opcode_trim inside {LOAD_T, STORE_T, AMO_T};
|
||||
assign unit_needed[GC_UNIT_ID] = opcode_trim inside {SYSTEM_T, FENCE_T};
|
||||
|
||||
assign mult_div_op = (opcode_trim == ARITH_T) && fb.instruction[25];
|
||||
assign mult_div_op = (opcode_trim == ARITH_T) && decode_instruction[25];
|
||||
generate if (USE_MUL)
|
||||
assign unit_needed[MUL_UNIT_WB_ID] = mult_div_op && ~fn3[2];
|
||||
endgenerate
|
||||
|
@ -226,7 +227,7 @@ module decode_and_issue (
|
|||
endgenerate
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (dec_advance)
|
||||
if (issue_stage_ready)
|
||||
unit_needed_issue_stage <= unit_needed;
|
||||
end
|
||||
|
||||
|
@ -255,7 +256,8 @@ module decode_and_issue (
|
|||
assign instruction_issued_no_rd = instruction_issued & ~uses_rd_issue_stage;
|
||||
assign instruction_issued_with_rd = instruction_issued & uses_rd_issue_stage;
|
||||
|
||||
|
||||
assign id_issued = instruction_issued;
|
||||
assign dummy_id_complete = instruction_issued & ~unit_needed_issue_stage[BRANCH_UNIT_ID];
|
||||
////////////////////////////////////////////////////
|
||||
//ALU unit inputs
|
||||
logic [XLEN-1:0] alu_rs1_data;
|
||||
|
@ -286,7 +288,7 @@ module decode_and_issue (
|
|||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (dec_advance) begin
|
||||
if (issue_stage_ready) begin
|
||||
alu_rs1_sel_r <= alu_rs1_sel;
|
||||
alu_rs2_sel_r <= alu_rs2_sel;
|
||||
end
|
||||
|
@ -310,7 +312,7 @@ module decode_and_issue (
|
|||
//Add cases: JAL, JALR, LUI, AUIPC, ADD[I], all logic ops
|
||||
//sub cases: SUB, SLT[U][I]
|
||||
logic sub_instruction;
|
||||
assign sub_instruction = (fn3 == ADD_SUB_fn3) && fb.instruction[30] && opcode[5];//If ARITH instruction
|
||||
assign sub_instruction = (fn3 == ADD_SUB_fn3) && decode_instruction[30] && opcode[5];//If ARITH instruction
|
||||
|
||||
alu_logic_op_t alu_logic_op;
|
||||
always_comb begin
|
||||
|
@ -335,7 +337,7 @@ module decode_and_issue (
|
|||
logic alu_slt_path;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (dec_advance) begin
|
||||
if (issue_stage_ready) begin
|
||||
alu_logic_op_r <= alu_logic_op;
|
||||
alu_subtract <= ~opcode[2] & (fn3 inside {SLTU_fn3, SLT_fn3} || sub_instruction);//opcode[2] covers LUI,AUIPC,JAL,JALR
|
||||
alu_lshift <= ~fn3[2];
|
||||
|
@ -366,7 +368,7 @@ module decode_and_issue (
|
|||
logic [4:0] amo_type;
|
||||
|
||||
assign amo_op = USE_AMO ? (opcode_trim == AMO_T) : 1'b0;
|
||||
assign amo_type = fb.instruction[31:27];
|
||||
assign amo_type = decode_instruction[31:27];
|
||||
assign store_conditional = (amo_type == AMO_SC);
|
||||
assign load_reserve = (amo_type == AMO_LR);
|
||||
|
||||
|
@ -388,8 +390,8 @@ module decode_and_issue (
|
|||
logic is_load_r;
|
||||
logic is_store_r;
|
||||
always_ff @(posedge clk) begin
|
||||
if (dec_advance) begin
|
||||
ls_offset <= opcode[5] ? {fb.instruction[31:25], fb.instruction[11:7]} : fb.instruction[31:20];
|
||||
if (issue_stage_ready) begin
|
||||
ls_offset <= opcode[5] ? {decode_instruction[31:25], decode_instruction[11:7]} : decode_instruction[31:20];
|
||||
is_load_r <= is_load;
|
||||
is_store_r <= is_store;
|
||||
end
|
||||
|
@ -420,31 +422,43 @@ module decode_and_issue (
|
|||
assign rs1_eq_rd = (rs1_addr == rd_addr);
|
||||
|
||||
logic br_use_signed;
|
||||
branch_predictor_metadata_t branch_metadata;
|
||||
logic branch_prediction_used;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (dec_advance) begin
|
||||
if (issue_stage_ready) begin
|
||||
is_return <= (opcode_trim == JALR_T) && ((rs1_link & ~rd_link) | (rs1_link & rd_link & ~rs1_eq_rd));
|
||||
is_call <= (opcode_trim inside {JAL_T, JALR_T}) && rd_link;
|
||||
br_use_signed <= !(fn3 inside {BLTU_fn3, BGEU_fn3});
|
||||
|
||||
//Branch Predictor support
|
||||
branch_metadata <= fb.branch_metadata;
|
||||
branch_prediction_used <= fb.branch_prediction_used;
|
||||
bp_update_way <= fb.bp_update_way;
|
||||
end
|
||||
end
|
||||
|
||||
assign branch_inputs.branch_metadata = branch_metadata;
|
||||
assign branch_inputs.branch_prediction_used = branch_prediction_used;
|
||||
assign branch_inputs.bp_update_way = bp_update_way;
|
||||
logic[19:0] jal_imm;
|
||||
logic[11:0] jalr_imm;
|
||||
logic[11:0] br_imm;
|
||||
|
||||
logic [20:0] pc_offset;
|
||||
logic [20:0] pc_offset_r;
|
||||
assign jal_imm = {decode_instruction[31], decode_instruction[19:12], decode_instruction[20], decode_instruction[30:21]};
|
||||
assign jalr_imm = decode_instruction[31:20];
|
||||
assign br_imm = {decode_instruction[31], decode_instruction[7], decode_instruction[30:25], decode_instruction[11:8]};
|
||||
|
||||
|
||||
always_comb begin
|
||||
unique if (~opcode[3] & opcode[2])
|
||||
pc_offset = 21'(signed'(jalr_imm));
|
||||
else if (opcode[3])
|
||||
pc_offset = 21'(signed'({jal_imm, 1'b0}));
|
||||
else
|
||||
pc_offset = 21'(signed'({br_imm, 1'b0}));
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue_stage_ready)
|
||||
pc_offset_r <= pc_offset;
|
||||
end
|
||||
assign branch_inputs.is_return = is_return;
|
||||
assign branch_inputs.is_call = is_call;
|
||||
assign branch_inputs.fn3 = fn3_issue_stage;
|
||||
assign branch_inputs.instruction = instruction_issue_stage;
|
||||
assign branch_inputs.pc_offset = pc_offset_r;
|
||||
assign branch_inputs.use_signed = br_use_signed;
|
||||
assign branch_inputs.jal = opcode_issue_stage[3];//(opcode == JAL);
|
||||
assign branch_inputs.jalr = ~opcode_issue_stage[3] & opcode_issue_stage[2];//(opcode == JALR);
|
||||
|
@ -463,7 +477,7 @@ module decode_and_issue (
|
|||
logic is_csr;
|
||||
logic is_csr_r;
|
||||
logic potential_flush;
|
||||
assign sfence = fb.instruction[25];
|
||||
assign sfence = decode_instruction[25];
|
||||
assign ifence = (opcode_trim == FENCE_T) && fn3[0];
|
||||
assign is_csr = (opcode_trim == SYSTEM_T) && (fn3 != 0);
|
||||
|
||||
|
@ -474,11 +488,11 @@ module decode_and_issue (
|
|||
logic is_ifence_r;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (dec_advance) begin
|
||||
if (issue_stage_ready) begin
|
||||
is_csr_r <= is_csr;
|
||||
is_ecall <= ENABLE_M_MODE && environment_op && (fb.instruction[21:20] == 0);
|
||||
is_ebreak <= ENABLE_M_MODE && environment_op && (fb.instruction[21:20] == 2'b01);
|
||||
is_ret <= ENABLE_M_MODE && environment_op && (fb.instruction[21:20] == 2'b10);
|
||||
is_ecall <= ENABLE_M_MODE && environment_op && (decode_instruction[21:20] == 0);
|
||||
is_ebreak <= ENABLE_M_MODE && environment_op && (decode_instruction[21:20] == 2'b01);
|
||||
is_ret <= ENABLE_M_MODE && environment_op && (decode_instruction[21:20] == 2'b10);
|
||||
is_fence <= ENABLE_M_MODE && (opcode_trim == FENCE_T) && ~fn3[0];
|
||||
is_ifence_r <= ifence;
|
||||
potential_flush <= (environment_op | ifence);
|
||||
|
@ -548,6 +562,7 @@ module decode_and_issue (
|
|||
assign unit_issue[i].possible_issue = unit_needed_issue_stage[i] & unit_operands_ready[i] & issue_stage_valid & ti.id_available & ~gc_issue_hold;
|
||||
assign unit_issue[i].new_request = issue[i];
|
||||
assign unit_issue[i].instruction_id = ti.issue_id;
|
||||
assign unit_issue[i].id = issue_id;
|
||||
always_ff @(posedge clk) begin
|
||||
unit_issue[i].new_request_r <= issue[i];
|
||||
end
|
||||
|
@ -558,12 +573,12 @@ module decode_and_issue (
|
|||
logic illegal_instruction_pattern_r;
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
illegal_instruction_checker illegal_op_check (
|
||||
.instruction(fb.instruction), .illegal_instruction(illegal_instruction_pattern)
|
||||
.instruction(decode_instruction), .illegal_instruction(illegal_instruction_pattern)
|
||||
);
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
illegal_instruction_pattern_r <= 0;
|
||||
else if (dec_advance)
|
||||
else if (issue_stage_ready)
|
||||
illegal_instruction_pattern_r <= illegal_instruction_pattern;
|
||||
end
|
||||
|
||||
|
@ -593,7 +608,7 @@ module decode_and_issue (
|
|||
|
||||
//Instruction Mix
|
||||
always_ff @(posedge clk) begin
|
||||
if (dec_advance) begin
|
||||
if (issue_stage_ready) begin
|
||||
tr_alu_op <= instruction_issued && (opcode_trim inside {ARITH_T, ARITH_IMM_T, AUIPC_T, LUI_T} && ~tr_mul_op && ~tr_div_op);
|
||||
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});
|
||||
|
|
|
@ -34,23 +34,23 @@ module fetch(
|
|||
input logic exception,
|
||||
input logic [31:0] gc_fetch_pc,
|
||||
|
||||
//ID Support
|
||||
input logic pc_id_available,
|
||||
output logic pc_id_assigned,
|
||||
output logic fetch_complete,
|
||||
|
||||
branch_predictor_interface.fetch bp,
|
||||
ras_interface.fetch ras,
|
||||
|
||||
//Instruction Metadata
|
||||
output logic [31:0] if_pc,
|
||||
output logic [31:0] fetch_instruction,
|
||||
|
||||
tlb_interface.mem tlb,
|
||||
local_memory_interface.master instruction_bram,
|
||||
input logic icache_on,
|
||||
l1_arbiter_request_interface.master l1_request,
|
||||
l1_arbiter_return_interface.master l1_response,
|
||||
|
||||
input logic pre_decode_pop,
|
||||
|
||||
output logic [31:0] pre_decode_instruction,
|
||||
output logic [31:0] pre_decode_pc,
|
||||
output branch_predictor_metadata_t branch_metadata,
|
||||
output logic branch_prediction_used,
|
||||
output logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way,
|
||||
output logic pre_decode_push
|
||||
l1_arbiter_return_interface.master l1_response
|
||||
);
|
||||
|
||||
localparam NUM_SUB_UNITS = USE_I_SCRATCH_MEM + USE_ICACHE;
|
||||
|
@ -59,7 +59,6 @@ module fetch(
|
|||
localparam BRAM_ID = 0;
|
||||
localparam ICACHE_ID = USE_I_SCRATCH_MEM;
|
||||
|
||||
localparam FETCH_BUFFER_DEPTH_W = $clog2(FETCH_BUFFER_DEPTH);
|
||||
localparam NEXT_ID_DEPTH = USE_ICACHE ? 2 : 1;
|
||||
|
||||
//Subunit signals
|
||||
|
@ -76,9 +75,8 @@ module fetch(
|
|||
logic [31:0] pc;
|
||||
|
||||
logic flush_or_rst;
|
||||
logic [FETCH_BUFFER_DEPTH_W:0] inflight_count;
|
||||
fifo_interface #(.DATA_WIDTH(NUM_SUB_UNITS_W)) next_unit();
|
||||
logic space_in_inst_buffer;
|
||||
|
||||
logic new_mem_request;
|
||||
|
||||
//Cache related
|
||||
|
@ -109,7 +107,6 @@ module fetch(
|
|||
|
||||
assign bp.new_mem_request = new_mem_request | gc_fetch_flush;
|
||||
assign bp.next_pc = next_pc;
|
||||
|
||||
assign bp.if_pc = pc;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -127,15 +124,8 @@ module fetch(
|
|||
//Issue Control Signals
|
||||
assign flush_or_rst = (rst | gc_fetch_flush);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (flush_or_rst)
|
||||
inflight_count <= '1;
|
||||
else
|
||||
inflight_count <= inflight_count - (FETCH_BUFFER_DEPTH_W+1)'(new_mem_request) + (FETCH_BUFFER_DEPTH_W+1)'(pre_decode_pop);
|
||||
end
|
||||
|
||||
assign space_in_inst_buffer = inflight_count[FETCH_BUFFER_DEPTH_W];
|
||||
assign new_mem_request = tlb.complete & space_in_inst_buffer & units_ready;
|
||||
assign new_mem_request = tlb.complete & pc_id_available & units_ready;
|
||||
assign pc_id_assigned = new_mem_request & ~gc_fetch_flush;
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//Subunit Tracking
|
||||
|
@ -147,6 +137,9 @@ module fetch(
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Subunit Interfaces
|
||||
//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.
|
||||
logic cache_address_match;
|
||||
generate
|
||||
for (i = 0; i < NUM_SUB_UNITS; i++) begin
|
||||
|
@ -175,17 +168,9 @@ module fetch(
|
|||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Pre-Decode Output
|
||||
assign pre_decode_instruction = unit_data_array[next_unit.data_out];
|
||||
assign pre_decode_pc = stage2_phys_address;
|
||||
assign pre_decode_push = units_data_valid;//FIFO is cleared on gc_fetch_flush
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (new_mem_request) begin
|
||||
branch_metadata <= bp.metadata;
|
||||
branch_prediction_used <= bp.use_prediction;
|
||||
bp_update_way <= bp.update_way;
|
||||
end
|
||||
end
|
||||
//Instruction metada updates
|
||||
assign if_pc = pc;
|
||||
assign fetch_instruction = unit_data_array[next_unit.data_out];
|
||||
assign fetch_complete = units_data_valid;
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -56,8 +56,12 @@ module gc_unit(
|
|||
mmu_interface.csr immu,
|
||||
mmu_interface.csr dmmu,
|
||||
|
||||
//ID Management
|
||||
output logic system_op_complete,
|
||||
output id_t system_op_id,
|
||||
|
||||
//WB
|
||||
input logic instruction_complete,
|
||||
input logic instruction_retired,
|
||||
input logic instruction_queue_empty,
|
||||
input instruction_id_t oldest_id,
|
||||
//unit_writeback_interface.unit gc_wb,
|
||||
|
@ -184,6 +188,11 @@ module gc_unit(
|
|||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID Management
|
||||
assign system_op_complete = issue.new_request & (gc_inputs.is_fence | gc_inputs.is_i_fence);
|
||||
assign system_op_id = issue.id;
|
||||
|
||||
//Instruction decode
|
||||
assign opcode = stage1.instruction[6:0];
|
||||
assign opcode_trim = opcode[6:2];
|
||||
|
|
213
core/id_management.sv
Normal file
213
core/id_management.sv
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright © 2020 Eric Matthews, Lesley Shannon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Initial code developed under the supervision of Dr. Lesley Shannon,
|
||||
* Reconfigurable Computing Lab, Simon Fraser University.
|
||||
*
|
||||
* Author(s):
|
||||
* Eric Matthews <ematthew@sfu.ca>
|
||||
*/
|
||||
|
||||
module id_management
|
||||
|
||||
import taiga_config::*;
|
||||
import taiga_types::*;
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
input logic gc_fetch_flush,
|
||||
|
||||
//ID issuing
|
||||
output id_t pc_id,
|
||||
output logic pc_id_available,
|
||||
input logic pc_id_assigned,
|
||||
|
||||
//Fetch stage
|
||||
output id_t fetch_id,
|
||||
input logic fetch_complete,
|
||||
|
||||
//Decode stage
|
||||
input logic decode_advance,
|
||||
output id_t decode_id,
|
||||
output logic decode_id_valid,
|
||||
|
||||
//Issue stage
|
||||
input id_t issue_id,
|
||||
input logic issue_stage_valid,
|
||||
input logic dummy_id_complete,
|
||||
input logic id_issued,
|
||||
|
||||
//ID freeing
|
||||
input logic store_complete,
|
||||
input id_t store_id,
|
||||
|
||||
input logic branch_complete,
|
||||
input id_t branch_id,
|
||||
|
||||
input logic system_op_complete,
|
||||
input id_t system_op_id,
|
||||
|
||||
input logic instruction_retired,
|
||||
input id_t retired_id
|
||||
);
|
||||
//////////////////////////////////////////
|
||||
id_t pc_id_i;
|
||||
localparam LOG2_MAX_IDS = $clog2(MAX_IDS);
|
||||
|
||||
//FIFO to store IDs that have been fetched but not yet decoded
|
||||
fifo_interface #(.DATA_WIDTH(LOG2_MAX_IDS)) fetch_fifo();
|
||||
|
||||
//Toggle memory blocks for tracking completion after issue
|
||||
logic decoded_toggle_mem [MAX_IDS];
|
||||
logic decoded_issued_toggle_mem [MAX_IDS];
|
||||
logic issued_toggle_mem [MAX_IDS];
|
||||
logic dummy_toggle_mem [MAX_IDS];
|
||||
logic branch_complete_toggle_mem [MAX_IDS];
|
||||
logic store_complete_toggle_mem [MAX_IDS];
|
||||
logic system_op_complete_toggle_mem [MAX_IDS];
|
||||
logic retired_toggle_mem [MAX_IDS];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
//Next ID always increases, even on a fetch buffer flush
|
||||
//If this leads to a temporary shortage of IDs, the oldest non-issued
|
||||
//ID can be found and pc_id could be reset to that.
|
||||
assign pc_id_i = pc_id + LOG2_MAX_IDS'(pc_id_assigned);
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
pc_id <= 0;
|
||||
else
|
||||
pc_id <= pc_id_i;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
fetch_id <= 0;
|
||||
else if (gc_fetch_flush)
|
||||
fetch_id <= pc_id;
|
||||
else
|
||||
fetch_id <= fetch_id + LOG2_MAX_IDS'(fetch_complete);
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Fetch buffer
|
||||
assign fetch_fifo.data_in = fetch_id;
|
||||
assign fetch_fifo.push = fetch_complete;
|
||||
assign fetch_fifo.pop = decode_advance;
|
||||
assign fetch_fifo.supress_push = 0;
|
||||
|
||||
taiga_fifo #(.DATA_WIDTH(LOG2_MAX_IDS), .FIFO_DEPTH(MAX_IDS)) fetch_fifo_block (
|
||||
.fifo(fetch_fifo),
|
||||
.rst(rst | gc_fetch_flush),
|
||||
.clk
|
||||
);
|
||||
|
||||
assign decode_id = fetch_fifo.data_out;
|
||||
assign decode_id_valid = fetch_fifo.valid;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Issue Tracking
|
||||
//As there are multiple completion sources, each source toggles a bit in its own LUTRAM.
|
||||
//All LUTRAMs are then xor-ed together to produce the status of the ID.
|
||||
//TODO: support arbitrary rst assertion (clear signal from global control)
|
||||
|
||||
//Instruction decoded and (issued or flushed) pair
|
||||
initial decoded_toggle_mem = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (decode_advance & ~gc_fetch_flush)
|
||||
decoded_toggle_mem[decode_id] <= ~decoded_toggle_mem[decode_id];
|
||||
end
|
||||
|
||||
initial decoded_issued_toggle_mem = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (id_issued | (gc_fetch_flush & issue_stage_valid))
|
||||
decoded_issued_toggle_mem[issue_id] <= ~decoded_issued_toggle_mem[issue_id];
|
||||
end
|
||||
|
||||
//Post issue status tracking
|
||||
initial issued_toggle_mem = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (id_issued)
|
||||
issued_toggle_mem[issue_id] <= ~issued_toggle_mem[issue_id];
|
||||
end
|
||||
|
||||
initial dummy_toggle_mem = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (dummy_id_complete)
|
||||
dummy_toggle_mem[issue_id] <= ~dummy_toggle_mem[issue_id];
|
||||
end
|
||||
|
||||
initial branch_complete_toggle_mem = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (branch_complete)
|
||||
branch_complete_toggle_mem[branch_id] <= ~branch_complete_toggle_mem[branch_id];
|
||||
end
|
||||
|
||||
initial store_complete_toggle_mem = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (store_complete)
|
||||
store_complete_toggle_mem[store_id] <= ~store_complete_toggle_mem[store_id];
|
||||
end
|
||||
|
||||
initial system_op_complete_toggle_mem = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (system_op_complete)
|
||||
system_op_complete_toggle_mem[system_op_id] <= ~system_op_complete_toggle_mem[system_op_id];
|
||||
end
|
||||
|
||||
initial retired_toggle_mem = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (instruction_retired)
|
||||
retired_toggle_mem[retired_id] <= ~retired_toggle_mem[retired_id];
|
||||
end
|
||||
|
||||
//Computed one cycle in advance using pc_id_i
|
||||
logic id_not_in_decode_issue;
|
||||
logic id_not_inflight;
|
||||
assign id_not_in_decode_issue = ~(decoded_toggle_mem[pc_id_i] ^ decoded_issued_toggle_mem[pc_id_i]);
|
||||
assign id_not_inflight =
|
||||
~(issued_toggle_mem[pc_id_i] ^
|
||||
branch_complete_toggle_mem[pc_id_i] ^
|
||||
dummy_toggle_mem[pc_id_i]
|
||||
);// ^
|
||||
//store_complete_toggle_mem[pc_id_i] ^
|
||||
//system_op_complete_toggle_mem[pc_id_i] ^
|
||||
//retired_toggle_mem[pc_id_i]);
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
pc_id_available <= 1;
|
||||
else
|
||||
pc_id_available <= id_not_in_decode_issue & id_not_inflight;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
pc_id_assigned_without_pc_id_available_assertion:
|
||||
assert property (@(posedge clk) disable iff (rst) !(~pc_id_available & pc_id_assigned))
|
||||
else $error("ID assigned without any ID available");
|
||||
|
||||
decode_advanced_without_id_assertion:
|
||||
assert property (@(posedge clk) disable iff (rst) !(~decode_id_valid & decode_advance))
|
||||
else $error("Decode advanced without ID");
|
||||
|
||||
endmodule
|
106
core/instruction_metadata.sv
Normal file
106
core/instruction_metadata.sv
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright © 2020 Eric Matthews, Lesley Shannon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Initial code developed under the supervision of Dr. Lesley Shannon,
|
||||
* Reconfigurable Computing Lab, Simon Fraser University.
|
||||
*
|
||||
* Author(s):
|
||||
* Eric Matthews <ematthew@sfu.ca>
|
||||
*/
|
||||
|
||||
module instruction_metadata
|
||||
|
||||
import taiga_config::*;
|
||||
import taiga_types::*;
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
//Fetch
|
||||
input id_t pc_id,
|
||||
input logic [31:0] if_pc,
|
||||
input logic pc_id_assigned,
|
||||
|
||||
input id_t fetch_id,
|
||||
input logic fetch_complete,
|
||||
input logic [31:0] fetch_instruction,
|
||||
|
||||
|
||||
//Decode ID
|
||||
input id_t decode_id,
|
||||
output logic [31:0] decode_pc,
|
||||
output logic [31:0] decode_instruction,
|
||||
|
||||
//Branch Predictor
|
||||
input branch_metadata_t branch_metadata_if,
|
||||
input id_t branch_id,
|
||||
output branch_metadata_t branch_metadata_ex
|
||||
|
||||
//Exception
|
||||
//input id_t exception_id,
|
||||
//output logic [31:0] exception_pc,
|
||||
//output logic [31:0] exception_instruction
|
||||
|
||||
);
|
||||
//////////////////////////////////////////
|
||||
logic [31:0] pc_table [MAX_IDS];
|
||||
logic [31:0] instruction_table [MAX_IDS];
|
||||
logic [$bits(branch_metadata_t)-1:0] branch_metadata_table [MAX_IDS];
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
//pc table
|
||||
always_ff @ (posedge clk) begin
|
||||
if (pc_id_assigned)
|
||||
pc_table[pc_id] <= if_pc;
|
||||
end
|
||||
|
||||
//branch metadata table
|
||||
always_ff @ (posedge clk) begin
|
||||
if (pc_id_assigned)
|
||||
branch_metadata_table[pc_id] <= branch_metadata_if;
|
||||
end
|
||||
|
||||
//instruction table
|
||||
always_ff @ (posedge clk) begin
|
||||
if (fetch_complete)
|
||||
instruction_table[fetch_id] <= fetch_instruction;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Outputs
|
||||
|
||||
//Decode
|
||||
assign decode_pc = pc_table[decode_id];
|
||||
assign decode_instruction = instruction_table[decode_id];
|
||||
|
||||
//Branch Predictor
|
||||
assign branch_metadata_ex = branch_metadata_table[branch_id];
|
||||
|
||||
//Exception Support
|
||||
// generate if (ENABLE_M_MODE) begin
|
||||
// assign exception_pc = pc_table[exception_id];
|
||||
// assign exception_instruction = instruction_table[exception_id];
|
||||
// end endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
|
||||
endmodule
|
|
@ -28,6 +28,7 @@ import l2_config_and_types::*;
|
|||
interface branch_predictor_interface;
|
||||
//Fetch signals
|
||||
logic [31:0] if_pc;
|
||||
id_t if_id;
|
||||
logic new_mem_request;
|
||||
logic [31:0] next_pc;
|
||||
|
||||
|
@ -35,17 +36,15 @@ interface branch_predictor_interface;
|
|||
logic [31:0] branch_flush_pc;
|
||||
logic [31:0] predicted_pc;
|
||||
logic use_prediction;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] update_way;
|
||||
logic use_ras;
|
||||
branch_predictor_metadata_t metadata;
|
||||
|
||||
modport branch_predictor (
|
||||
input if_pc, new_mem_request, next_pc,
|
||||
output branch_flush_pc, predicted_pc, use_prediction, update_way, use_ras, metadata
|
||||
input if_pc, if_id, new_mem_request, next_pc,
|
||||
output branch_flush_pc, predicted_pc, use_prediction, use_ras
|
||||
);
|
||||
modport fetch (
|
||||
input branch_flush_pc, predicted_pc, use_prediction, update_way, use_ras, metadata,
|
||||
output if_pc, new_mem_request, next_pc
|
||||
input branch_flush_pc, predicted_pc, use_prediction, use_ras,
|
||||
output if_pc, if_id, new_mem_request, next_pc
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
@ -55,11 +54,12 @@ interface unit_issue_interface;
|
|||
logic new_request;
|
||||
logic new_request_r;
|
||||
instruction_id_t instruction_id;
|
||||
id_t id;
|
||||
|
||||
logic ready;
|
||||
|
||||
modport decode (input ready, output possible_issue, new_request, new_request_r, instruction_id);
|
||||
modport unit (output ready, input possible_issue, new_request, new_request_r, instruction_id);
|
||||
modport decode (input ready, output possible_issue, new_request, new_request_r, instruction_id, id);
|
||||
modport unit (output ready, input possible_issue, new_request, new_request_r, instruction_id, id);
|
||||
endinterface
|
||||
|
||||
interface ras_interface;
|
||||
|
|
|
@ -48,6 +48,10 @@ module load_store_unit (
|
|||
|
||||
local_memory_interface.master data_bram,
|
||||
|
||||
//ID Management
|
||||
output logic store_complete,
|
||||
output id_t store_id,
|
||||
|
||||
//Writeback-Store Interface
|
||||
writeback_store_interface.ls wb_store,
|
||||
|
||||
|
@ -208,6 +212,11 @@ endgenerate
|
|||
|
||||
assign lsq.accepted = lsq.transaction_ready & ready_for_issue;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID Management
|
||||
assign store_complete = (lsq.accepted & lsq.transaction_out.store) | (ls_exception_ack & exception_is_store);
|
||||
assign store_id = $clog2(MAX_IDS)'(wb_store.commit_id);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Writeback-Store interface
|
||||
assign wb_store.id_needed_at_issue = ls_inputs.store_forward_id;
|
||||
|
|
|
@ -83,16 +83,38 @@ module taiga (
|
|||
logic tlb_on;
|
||||
logic [ASIDLEN-1:0] asid;
|
||||
|
||||
//Pre-Decode
|
||||
logic pre_decode_push;
|
||||
logic pre_decode_pop;
|
||||
logic [31:0] pre_decode_instruction;
|
||||
logic [31:0] pre_decode_pc;
|
||||
branch_predictor_metadata_t branch_metadata;
|
||||
logic branch_prediction_used;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way;
|
||||
logic fb_valid;
|
||||
fetch_buffer_packet_t fb;
|
||||
//Instruction ID/Metadata
|
||||
//ID issuing
|
||||
id_t pc_id;
|
||||
logic pc_id_available;
|
||||
logic pc_id_assigned;
|
||||
logic [31:0] if_pc;
|
||||
//Fetch stage
|
||||
id_t fetch_id;
|
||||
logic fetch_complete;
|
||||
logic [31:0] fetch_instruction;
|
||||
//Decode stage
|
||||
logic decode_advance;
|
||||
id_t decode_id;
|
||||
logic decode_id_valid;
|
||||
logic [31:0] decode_pc;
|
||||
logic [31:0] decode_instruction;
|
||||
//Issue stage
|
||||
logic issue_stage_valid;
|
||||
logic dummy_id_complete;
|
||||
id_t issue_id;
|
||||
//Branch predictor
|
||||
branch_metadata_t branch_metadata_if;
|
||||
branch_metadata_t branch_metadata_ex;
|
||||
//ID freeing
|
||||
logic store_complete;
|
||||
id_t store_id;
|
||||
logic branch_complete;
|
||||
id_t branch_id;
|
||||
logic system_op_complete;
|
||||
id_t system_op_id;
|
||||
logic instruction_retired;
|
||||
id_t retired_id;
|
||||
|
||||
//Global Control
|
||||
logic gc_issue_hold;
|
||||
|
@ -112,10 +134,10 @@ module taiga (
|
|||
logic illegal_instruction;
|
||||
logic instruction_queue_empty;
|
||||
|
||||
logic id_issued;
|
||||
logic instruction_issued;
|
||||
logic instruction_issued_no_rd;
|
||||
logic instruction_issued_with_rd;
|
||||
logic instruction_complete;
|
||||
logic gc_flush_required;
|
||||
|
||||
//LS
|
||||
|
@ -171,7 +193,12 @@ module taiga (
|
|||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Fetch and Pre-Decode
|
||||
// ID support
|
||||
id_management id_management_block (.*);
|
||||
instruction_metadata id_metadata_block (.*);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Fetch
|
||||
fetch fetch_block (.*, .icache_on('1), .tlb(itlb), .l1_request(l1_request[L1_ICACHE_ID]), .l1_response(l1_response[L1_ICACHE_ID]), .exception(1'b0));
|
||||
branch_predictor bp_block (.*);
|
||||
ras ras_block(.*);
|
||||
|
@ -184,7 +211,6 @@ module taiga (
|
|||
assign itlb.physical_address = itlb.virtual_address;
|
||||
end
|
||||
endgenerate
|
||||
pre_decode pre_decode_block(.*);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Decode/Issue
|
||||
|
@ -193,7 +219,7 @@ module taiga (
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Execution Units
|
||||
branch_unit branch_unit_block (.*, .issue(unit_issue[BRANCH_UNIT_ID]));
|
||||
branch_unit branch_unit_block (.*, .issue(unit_issue[BRANCH_UNIT_ID]), .dec_pc_plus_4(unit_wb[ALU_UNIT_WB_ID].rd));
|
||||
alu_unit alu_unit_block (.*, .issue(unit_issue[ALU_UNIT_WB_ID]), .wb(unit_wb[ALU_UNIT_WB_ID]));
|
||||
load_store_unit load_store_unit_block (.*, .dcache_on(1'b1), .clear_reservation(1'b0), .tlb(dtlb), .issue(unit_issue[LS_UNIT_WB_ID]), .wb(unit_wb[LS_UNIT_WB_ID]), .l1_request(l1_request[L1_DCACHE_ID]), .l1_response(l1_response[L1_DCACHE_ID]));
|
||||
generate if (ENABLE_S_MODE) begin
|
||||
|
|
|
@ -29,7 +29,7 @@ package taiga_config;
|
|||
//Privileged ISA Options
|
||||
|
||||
//Enable Machine level privilege spec
|
||||
parameter ENABLE_M_MODE = 0;
|
||||
parameter ENABLE_M_MODE = 1;
|
||||
//Enable Supervisor level privilege spec
|
||||
parameter ENABLE_S_MODE = 0;
|
||||
//Enable User level privilege spec
|
||||
|
@ -158,13 +158,14 @@ package taiga_config;
|
|||
//Branch Predictor Options
|
||||
parameter USE_BRANCH_PREDICTOR = 1;
|
||||
parameter BRANCH_PREDICTOR_WAYS = 2;
|
||||
parameter BRANCH_TABLE_ENTRIES = 512;
|
||||
parameter BRANCH_TABLE_ENTRIES = 512;//min 512
|
||||
parameter RAS_DEPTH = 8;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//FIFO/Buffer Depths
|
||||
//All parameters restricted to powers of two
|
||||
parameter MAX_IDS = 16;
|
||||
parameter MAX_INFLIGHT_COUNT = 4;
|
||||
parameter FETCH_BUFFER_DEPTH = 4;
|
||||
|
||||
|
|
|
@ -41,16 +41,16 @@ module taiga_fifo #(parameter DATA_WIDTH = 70, parameter FIFO_DEPTH = 4)
|
|||
logic [LOG2_FIFO_DEPTH-1:0] write_index;
|
||||
logic [LOG2_FIFO_DEPTH-1:0] read_index;
|
||||
logic [LOG2_FIFO_DEPTH:0] inflight_count;
|
||||
logic supressed_push;
|
||||
logic potentially_supressed_push;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
assign supressed_push = fifo.push & ~fifo.supress_push;
|
||||
assign potentially_supressed_push = fifo.push & ~fifo.supress_push;
|
||||
generate if (FIFO_DEPTH == 1) begin
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
fifo.valid <= 0;
|
||||
else if (supressed_push)
|
||||
else if (potentially_supressed_push)
|
||||
fifo.valid <= 1;
|
||||
else if (fifo.pop)
|
||||
fifo.valid <= 0;
|
||||
|
@ -69,7 +69,7 @@ module taiga_fifo #(parameter DATA_WIDTH = 70, parameter FIFO_DEPTH = 4)
|
|||
if (rst)
|
||||
inflight_count <= 0;
|
||||
else
|
||||
inflight_count <= inflight_count + (LOG2_FIFO_DEPTH+1)'(fifo.pop) - (LOG2_FIFO_DEPTH+1)'(supressed_push);
|
||||
inflight_count <= inflight_count + (LOG2_FIFO_DEPTH+1)'(fifo.pop) - (LOG2_FIFO_DEPTH+1)'(potentially_supressed_push);
|
||||
end
|
||||
|
||||
assign fifo.valid = inflight_count[LOG2_FIFO_DEPTH];
|
||||
|
@ -82,7 +82,7 @@ module taiga_fifo #(parameter DATA_WIDTH = 70, parameter FIFO_DEPTH = 4)
|
|||
end
|
||||
else begin
|
||||
read_index <= read_index + LOG2_FIFO_DEPTH'(fifo.pop);
|
||||
write_index <= write_index + LOG2_FIFO_DEPTH'(supressed_push);
|
||||
write_index <= write_index + LOG2_FIFO_DEPTH'(potentially_supressed_push);
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -96,10 +96,8 @@ module taiga_fifo #(parameter DATA_WIDTH = 70, parameter FIFO_DEPTH = 4)
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
always_ff @ (posedge clk) begin
|
||||
assert (!(~rst & fifo.full & supressed_push & ~fifo.pop)) else $error("overflow");
|
||||
//assert (!(~rst & ~fifo.valid & ~supressed_push & fifo.pop)) else $error("underflow");
|
||||
end
|
||||
fifo_overflow_assertion:
|
||||
assert property (@(posedge clk) disable iff (rst) !(fifo.full & potentially_supressed_push & ~fifo.pop)) else $error("overflow");
|
||||
fifo_underflow_assertion:
|
||||
assert property (@(posedge clk) disable iff (rst) !(~fifo.valid & fifo.pop)) else $error("underflow");
|
||||
endmodule
|
||||
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ package taiga_types;
|
|||
localparam ID_W = $clog2(MAX_INFLIGHT_COUNT);
|
||||
localparam WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS);
|
||||
|
||||
typedef logic[$clog2(MAX_IDS)-1:0] id_t;
|
||||
|
||||
typedef logic[ID_W-1:0] instruction_id_t;
|
||||
typedef logic[WB_UNITS_WIDTH-1:0] unit_id_t;
|
||||
typedef logic[1:0] branch_predictor_metadata_t;
|
||||
|
@ -82,20 +84,17 @@ package taiga_types;
|
|||
typedef struct packed{
|
||||
branch_predictor_metadata_t branch_predictor_metadata;
|
||||
logic branch_prediction_used;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way;
|
||||
} branch_unit_metadata_t;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] branch_predictor_update_way;
|
||||
} branch_metadata_t;
|
||||
|
||||
|
||||
typedef struct packed{
|
||||
logic id_assigned;
|
||||
instruction_id_t pc_id;
|
||||
id_t pc_id;
|
||||
logic [31:0] pc;
|
||||
branch_unit_metadata_t branch_unit_metadata;
|
||||
|
||||
logic complete;
|
||||
instruction_id_t instruction_id;
|
||||
id_t instruction_id;
|
||||
logic [31:0] instruction;
|
||||
|
||||
} fetch_instruction_metadata_t;
|
||||
|
||||
typedef struct packed{
|
||||
|
@ -128,22 +127,15 @@ package taiga_types;
|
|||
logic jalr;
|
||||
logic is_call;
|
||||
logic is_return;
|
||||
logic [31:0] instruction;
|
||||
branch_predictor_metadata_t branch_metadata;
|
||||
logic branch_prediction_used;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way;
|
||||
logic [20:0] pc_offset;
|
||||
} branch_inputs_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic[31:0] pc_ex;
|
||||
logic [31:0] jump_pc;
|
||||
logic [31:0] njump_pc;
|
||||
logic [31:0] new_pc;
|
||||
logic branch_taken;
|
||||
logic branch_ex;
|
||||
logic is_return_ex;
|
||||
branch_predictor_metadata_t branch_ex_metadata;
|
||||
logic branch_prediction_used;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way;
|
||||
} branch_results_t;
|
||||
|
||||
typedef struct packed{
|
||||
|
|
|
@ -34,7 +34,8 @@ module write_back(
|
|||
input unit_writeback_t unit_wb[NUM_WB_UNITS-1:0],
|
||||
register_file_writeback_interface.writeback rf_wb,
|
||||
tracking_interface.wb ti,
|
||||
output logic instruction_complete,
|
||||
output logic instruction_retired,
|
||||
output id_t retired_id,
|
||||
output logic instruction_queue_empty,
|
||||
|
||||
output instruction_id_t oldest_id,
|
||||
|
@ -209,11 +210,12 @@ module write_back(
|
|||
end
|
||||
|
||||
//Instruction completion tracking for retired instruction count
|
||||
assign instruction_complete = retiring & ~retiring_instruction_packet.is_store;
|
||||
assign instruction_retired = retiring & ~retiring_instruction_packet.is_store;
|
||||
assign retired_id = $clog2(MAX_IDS)'(id_retiring);
|
||||
|
||||
assign rf_wb.rd_addr = retiring_instruction_packet.rd_addr;
|
||||
assign rf_wb.id = id_retiring;
|
||||
assign rf_wb.retiring = instruction_complete;
|
||||
assign rf_wb.retiring = instruction_retired;
|
||||
assign rf_wb.rd_nzero = |retiring_instruction_packet.rd_addr;
|
||||
assign rf_wb.rd_data = results_by_id[id_retiring];
|
||||
|
||||
|
|
|
@ -93,8 +93,8 @@
|
|||
../core/ras.sv
|
||||
../core/branch_predictor_ram.sv
|
||||
../core/branch_predictor.sv
|
||||
../core/fetch.sv
|
||||
../core/pre_decode.sv
|
||||
../core/fetch.sv
|
||||
|
||||
../core/illegal_instruction_checker.sv
|
||||
../core/decode_and_issue.sv
|
||||
|
||||
|
@ -112,5 +112,8 @@
|
|||
../l2_arbiter/l2_round_robin.sv
|
||||
../l2_arbiter/l2_arbiter.sv
|
||||
|
||||
../core/id_management.sv
|
||||
../core/instruction_metadata.sv
|
||||
|
||||
../core/taiga.sv
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue