Fixed Jumps and Branches (jump target now calculated in ID, up for debate) and some general code cleanups

This commit is contained in:
Sven Stucki 2015-04-15 18:27:51 +02:00
parent c974349bbc
commit af8b208029
7 changed files with 334 additions and 449 deletions

16
alu.sv
View file

@ -36,7 +36,7 @@ module alu
input logic [`ALU_OP_WIDTH-1:0] operator_i,
input logic [31:0] operand_a_i,
input logic [31:0] operand_b_i,
input logic [31:0] operand_c_i, // for jump target calculation
input logic [31:0] operand_c_i,
input logic carry_i,
input logic flag_i,
@ -45,15 +45,12 @@ module alu
input logic [1:0] vec_ext_i,
output logic [31:0] result_o,
output logic [31:0] jump_target_o,
output logic overflow_o,
output logic carry_o,
output logic flag_o
);
logic [31:0] pc_after_jal;
logic [31:0] operand_a_rev; // bit reversed signal of operand_a_i
// bit reverse operand_a for left shifts
@ -144,9 +141,6 @@ module alu
assign {carry_out[2], adder_result[23:16]} = adder_op_a[23:16] + adder_op_b[23:16] + carry_in[2];
assign {carry_out[3], adder_result[31:24]} = adder_op_a[31:24] + adder_op_b[31:24] + carry_in[3];
// additional 32 bit adder for PC after JAL(R) instruction
assign pc_after_jal = operand_c_i + 32'd4;
// averaging by right shifting of one bit
logic [31:0] result_avg;
@ -549,7 +543,6 @@ module alu
shift_left = 1'b0;
shift_amt = operand_b_i;
result_o = 'x;
jump_target_o = 1'b0;
carry_o = 1'b0;
overflow_o = 1'b0;
flag_o = 1'b0;
@ -567,13 +560,6 @@ module alu
`ALU_OR: result_o = operand_a_i | operand_b_i;
`ALU_XOR: result_o = operand_a_i ^ operand_b_i;
// Jump Target Calculation
`ALU_JAL:
begin
result_o = pc_after_jal;
jump_target_o = adder_result;
end
// Shift Operations
`ALU_MOVHI:
begin

View file

@ -40,6 +40,8 @@ module controller
output logic eoc_o, // End of computation: triggered by a special instruction
output logic core_busy_o, // Core is busy processing instructions
output logic force_nop_o,
input logic [31:0] instr_rdata_i, // Instruction read from instr memory/cache: (sampled in the if stage)
output logic instr_req_o, // Fetch instruction Request:
input logic instr_gnt_i, // grant from icache
@ -103,7 +105,7 @@ module controller
input logic irq_present_i, // there is an IRQ, so if we are sleeping we should wake up now
// Exception Controller Signals
output logic jump_in_id_o, // jump instruction in ID stage
//output logic jump_in_id_o, // jump instruction in ID stage
output logic illegal_insn_o, // illegal instruction encountered
output logic trap_insn_o, // trap instruction encountered
output logic pipe_flush_o, // pipe flush requested by controller
@ -136,16 +138,9 @@ module controller
output logic [1:0] operand_c_fw_mux_sel_o, // regfile rc data selector form ID stage
// Jump target calcuation done detection
input logic jump_in_ex_i, // jump is being calculated in ALU
input logic [1:0] jump_in_ex_i, // jump is being calculated in ALU
output logic [1:0] jump_in_id_o, // jump is being calculated in ALU
// Branch result from ALU
input logic branch_taken_i,
output logic drop_instruction_o, // prevent instruction to enter ID stage
`ifdef BRANCH_PREDICTION
output logic wrong_branch_taken_o, // 1 if the wrong branch was selected
output logic take_branch_o, // 1 if branch should be taken
`endif
output logic stall_if_o, // Stall IF stage (deassert requests)
output logic stall_id_o, // Stall ID stage (and instr and data memory interface) ( ID_STAGE )
output logic stall_ex_o, // Stall ex stage ( EX_STAGE )
@ -182,7 +177,7 @@ module controller
logic mfspr_stall;
logic instr_ack_stall;
logic load_stall;
logic j_stall;
logic jr_stall;
logic set_npc;
`ifdef BRANCH_PREDICTION
@ -207,8 +202,9 @@ module controller
instr_req_o = 1'b1;
pc_mux_sel_o = `INCR_PC;
pc_mux_sel_o = `PC_INCR;
pc_mux_boot_o = 1'b0;
jump_in_id_o = 2'b00;
alu_operator = `ALU_NOP;
extend_immediate_o = 1'b0;
@ -287,7 +283,7 @@ module controller
// we begin execution when either fetch_enable is high or an
// interrupt has arrived
instr_req_o = fetch_enable_i || irq_present_i;
pc_mux_sel_o = `NO_INCR;
pc_mux_sel_o = `PC_NO_INCR;
if (fetch_enable_i || irq_present_i)
begin
@ -323,13 +319,17 @@ module controller
`OPCODE_JAL: begin // Jump and Link
if (instr_rdata_i ==? `INSTR_JAL) begin
pc_mux_sel_o = `PC_FROM_ALU;
// Insert bubbles
pc_mux_sel_o = `PC_NO_INCR;
jump_in_id_o = 2'b01;
// Calculate and store PC+4
alu_op_a_mux_sel_o = `OP_A_CURRPC;
alu_op_b_mux_sel_o = `OP_B_IMM;
alu_op_c_mux_sel_o = `OP_C_CURRPC;
immediate_mux_sel_o = `IMM_UJ;
alu_operator = `ALU_JAL;
immediate_mux_sel_o = `IMM_HEX4;
alu_operator = `ALU_ADD;
regfile_alu_we = 1'b1;
// Calculate jump target (= PC + UJ imm)
alu_op_c_mux_sel_o = `OP_C_JT;
end else begin
illegal_insn_o = 1'b1;
end
@ -337,21 +337,29 @@ module controller
`OPCODE_JALR: begin // Jump and Link Register
if (instr_rdata_i ==? `INSTR_JALR) begin
pc_mux_sel_o = `PC_FROM_ALU;
// Insert bubbles
pc_mux_sel_o = `PC_NO_INCR;
jump_in_id_o = 2'b01;
// Calculate and store PC+4
alu_op_a_mux_sel_o = `OP_A_CURRPC;
alu_op_b_mux_sel_o = `OP_B_IMM;
alu_op_c_mux_sel_o = `OP_C_CURRPC;
immediate_mux_sel_o = `IMM_I;
alu_operator = `ALU_JAL;
immediate_mux_sel_o = `IMM_HEX4;
alu_operator = `ALU_ADD;
regfile_alu_we = 1'b1;
// Calculate jump target (= RS1 + I imm)
rega_used = 1'b1;
alu_op_c_mux_sel_o = `OP_C_JT;
end else begin
illegal_insn_o = 1'b1;
end
end
`OPCODE_BRANCH: begin // Branch
rega_used = 1'b1;
regb_used = 1'b1;
pc_mux_sel_o = `PC_NO_INCR;
jump_in_id_o = 2'b10;
alu_op_c_mux_sel_o = `OP_C_JT;
rega_used = 1'b1;
regb_used = 1'b1;
unique case (instr_rdata_i) inside
`INSTR_BEQ: alu_operator = `ALU_EQ;
@ -366,32 +374,15 @@ module controller
end
endcase // case (instr_rdata_i)
if (branch_taken_i == 1'b1) begin
/*if (branch_taken_i == 1'b1) begin
pc_mux_sel_o = `PC_FROM_IMM; // TODO: Think about clever adder use
end else begin
pc_mux_sel_o = `INCR_PC;
end
end*/
end
/*
`OPCODE_JR:
begin // Jump Register
pc_mux_sel_o = `PC_FROM_REGFILE;
regb_used = 1'b1;
end
`OPCODE_JALR: begin // Jump and Link Register
pc_mux_sel_o = `PC_FROM_REGFILE;
alu_op_a_mux_sel_o = `OP_A_CURRPC;
alu_op_b_mux_sel_o = `OP_B_IMM;
immediate_mux_sel_o = `IMM_HEX4;
alu_operator = `ALU_ADD;
regfile_alu_waddr_mux_sel_o = 2'b10; // select r9 to write back return address
regfile_alu_we = 1'b1;
regb_used = 1'b1;
end
`ifndef BRANCH_PREDICTION
`OPCODE_BNF:
begin // Branch if No Flag
@ -448,7 +439,7 @@ module controller
`OPCODE_EOC: begin // End of Computation (Custom Instruction 1)
eoc_o = 1'b1;
pc_mux_sel_o = `NO_INCR;
pc_mux_sel_o = `PC_NO_INCR;
end
`OPCODE_RFE:
@ -619,9 +610,9 @@ module controller
data_sign_extension_o = instr_rdata_i[1];
end
*/
//////////////////////////
// _ _ _ _ //
// / \ | | | | | | //
@ -671,19 +662,7 @@ module controller
endcase // unique case (instr_rdata_i)
end // case: `OPCODE_OPIMM
/*
`OPCODE_ADDIC: begin // Add Immediate and Carry
alu_op_b_mux_sel_o = `OP_B_IMM;
immediate_mux_sel_o = `IMM_16;
alu_operator = `ALU_ADDC;
regfile_alu_we = 1'b1;
set_overflow = 1'b1;
set_carry = 1'b1;
rega_used = 1'b1;
end
*/
`OPCODE_OP: begin // ALU register-register operation
`OPCODE_OP: begin // Register-Register ALU operation
regfile_alu_we = 1'b1;
rega_used = 1'b1;
regb_used = 1'b1;
@ -712,24 +691,6 @@ module controller
/*
`OPCODE_MOVHI:
begin
if (instr_rdata_i[16] == 1'b0)
begin // Move Immediate High
extend_immediate_o = 1'b1;
alu_op_a_mux_sel_o = `OP_A_IMM16;
alu_operator = `ALU_MOVHI;
regfile_alu_we = 1'b1;
end
else
begin
// synopsys translate_off
$display("%t: Illegal l.movhi received.", $time);
// synopsys translate_on
illegal_insn_o = 1'b1;
end
end
`OPCODE_MULI: begin // Multiply Immediate Signed
alu_op_b_mux_sel_o = `OP_B_IMM;
immediate_mux_sel_o = `IMM_16;
@ -911,37 +872,6 @@ module controller
endcase
end
`OPCODE_SFI: begin // Set Flag Immediate-Instructions
if (instr_rdata_i[25] == 1'b0) begin
alu_op_b_mux_sel_o = `OP_B_IMM;
immediate_mux_sel_o = `IMM_16;
alu_operator = {2'b10, instr_rdata_i[24:21]};
set_flag = 1'b1;
rega_used = 1'b1;
end
else begin
// synopsys translate_off
$display("%t: Illegal Set Flag Immediate instruction received.", $time);
// synopsys translate_on
illegal_insn_o = 1'b1;
end
end
`OPCODE_SF: begin // Set Flag Instruction
if (instr_rdata_i[25] == 1'b0) begin
alu_operator = {2'b10, instr_rdata_i[24:21]};
set_flag = 1'b1;
rega_used = 1'b1;
regb_used = 1'b1;
end
else begin
// synopsys translate_off
$display("%t: Illegal Set Flag instruction received.", $time);
// synopsys translate_on
illegal_insn_o = 1'b1;
end
end
`OPCODE_VEC: begin // vectorial alu operations
rega_used = 1'b1;
regfile_alu_we = 1'b1;
@ -1168,11 +1098,10 @@ module controller
*/
default: begin
illegal_insn_o = 1'b1;
// TODO: Replace with exception
pc_mux_sel_o = `NO_INCR;
illegal_insn_o = 1'b1;
pc_mux_sel_o = `PC_NO_INCR;
end
endcase; // case (instr_rdata_i[6:0])
// synopsys translate_off
@ -1203,7 +1132,7 @@ module controller
end
if ( set_npc == 1'b1 )
pc_mux_sel_o = `NO_INCR;
pc_mux_sel_o = `PC_NO_INCR;
// hwloop detected, jump to start address!
if (hwloop_jump_i == 1'b1)
@ -1218,184 +1147,153 @@ module controller
ctrl_fsm_ns = IDLE;
end
endcase
end
end
assign core_busy_o = (ctrl_fsm_cs != IDLE);
assign core_busy_o = (ctrl_fsm_cs != IDLE);
////////////////////////////////////////////////////////////////////////////////////////////
// Generate Stall Signals! //
////////////////////////////////////////////////////////////////////////////////////////////
always_comb
begin
mfspr_stall = 1'b0;
mtspr_stall = 1'b0;
load_stall = 1'b0;
j_stall = 1'b0;
deassert_we = 1'b0;
////////////////////////////////////////////////////////////////////////////////////////////
// Generate Stall Signals! //
////////////////////////////////////////////////////////////////////////////////////////////
always_comb
begin
mfspr_stall = 1'b0;
mtspr_stall = 1'b0;
load_stall = 1'b0;
jr_stall = 1'b0;
deassert_we = 1'b0;
/*
// Stall because of l.mfspr with dependency
if ((regfile_wdata_mux_sel_ex_i == 1'b0) && (regfile_we_ex_i == 1'b1) &&
((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) )
begin
deassert_we = 1'b1;
mfspr_stall = 1'b1;
end
// Stall because of l.mtspr (always...)
// mtspr in ex stage, normal instruction in id stage which can change an spr reg
if ((sp_we_ex_i == 1'b1) && (instr_rdata_i[31:26] != `OPCODE_MTSPR))
begin
deassert_we = 1'b1;
mtspr_stall = 1'b1;
end
*/
// Stall because of load operation
if ((data_req_ex_i == 1'b1) && (regfile_we_ex_i == 1'b1) &&
((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) )
begin
deassert_we = 1'b1;
load_stall = 1'b1;
end
// TODO: check JALR/JR
// Stall because of jr path
// - Load results cannot directly be forwarded to PC
// - Multiplication results cannot be forwarded to PC
if ((instr_rdata_i[6:0] == `OPCODE_JALR) &&
(((regfile_we_wb_i == 1'b1) && (reg_d_wb_is_reg_b_id == 1'b1) && (data_rvalid_i == 1'b1)) ||
((regfile_we_ex_i == 1'b1) && (reg_d_ex_is_reg_b_id == 1'b1)) ||
((regfile_alu_we_fw_i == 1'b1) && (reg_d_alu_is_reg_b_id == 1'b1) && (mult_is_running_ex_i == 1'b1))) )
begin
jr_stall = 1'b1;
deassert_we = 1'b1;
end
end
// Stall because of IF miss
assign instr_ack_stall = ~instr_ack_i;
// Stall if TCDM contention has been detected
assign lsu_stall = ~data_ack_i;
assign misalign_stall = data_misaligned_i;
// deassert we signals (in case of stalls)
assign alu_operator_o = (deassert_we) ? `ALU_NOP : alu_operator;
assign mult_is_running_o = (deassert_we) ? 1'b0 : mult_is_running;
assign regfile_we_o = (deassert_we) ? 1'b0 : regfile_we;
assign regfile_alu_we_o = (deassert_we) ? 1'b0 : regfile_alu_we;
assign data_we_o = (deassert_we) ? 1'b0 : data_we;
assign data_req_o = (deassert_we) ? 1'b0 : data_req;
assign set_flag_o = (deassert_we) ? 1'b0 : set_flag;
assign set_overflow_o = (deassert_we) ? 1'b0 : set_overflow;
assign set_carry_o = (deassert_we) ? 1'b0 : set_carry;
/*
// Stall because of l.mfspr with dependency
if ((regfile_wdata_mux_sel_ex_i == 1'b0) && (regfile_we_ex_i == 1'b1) &&
((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) )
begin
deassert_we = 1'b1;
mfspr_stall = 1'b1;
end
////////////////////////////////////////////////////////////////////////////////////////////
// Jump and Branch handling //
////////////////////////////////////////////////////////////////////////////////////////////
// Stall because of l.mtspr (always...)
// mtspr in ex stage, normal instruction in id stage which can change an spr reg
if ((sp_we_ex_i == 1'b1) && (instr_rdata_i[31:26] != `OPCODE_MTSPR))
begin
deassert_we = 1'b1;
mtspr_stall = 1'b1;
end
*/
assign force_nop_o = (jump_in_id_o != 2'b00 || jump_in_ex_i != 2'b00)? 1'b1 : 1'b0;
assign drop_instruction_o = 1'b0;
// Stall because of load operation
if ((data_req_ex_i == 1'b1) && (regfile_we_ex_i == 1'b1) &&
((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) )
begin
deassert_we = 1'b1;
load_stall = 1'b1;
end
// TODO: check JALR/JR
// Stall because of jr path
// - Load results cannot directly be forwarded to PC
// - Multiplication results cannot be forwarded to PC
if ((instr_rdata_i[6:0] == `OPCODE_JALR) &&
(((regfile_we_wb_i == 1'b1) && (reg_d_wb_is_reg_b_id == 1'b1) && (data_rvalid_i == 1'b1)) ||
((regfile_we_ex_i == 1'b1) && (reg_d_ex_is_reg_b_id == 1'b1)) ||
((regfile_alu_we_fw_i == 1'b1) && (reg_d_alu_is_reg_b_id == 1'b1) && (mult_is_running_ex_i == 1'b1))) )
begin
j_stall = 1'b1;
deassert_we = 1'b1;
end
// Stall because of JAL/JALR/branch
// Stall until jump target or branch decision is calculated in EX (1 cycle, then fetch instruction)
if ( (instr_rdata_i[6:0] == `OPCODE_JAL || instr_rdata_i[6:0] == `OPCODE_JALR
|| instr_rdata_i[6:0] == `OPCODE_BRANCH) && (jump_in_ex_i == 1'b0) )
begin
j_stall = 1'b1;
//deassert_we = 1'b1;
end
`ifdef BRANCH_PREDICTION
// Stall because of set_flag path
if (wrong_branch_taken)
begin
deassert_we = 1'b1;
end
`endif
end
// NOTE: current_pc_id_i is wrong after drop instruction !
`ifdef BRANCH_PREDICTION
assign drop_instruction_o = wrong_branch_taken | j_stall;
`else
assign drop_instruction_o = j_stall;
`endif
// Stall because of IF miss
assign instr_ack_stall = ~instr_ack_i;
// Stall if TCDM contention has been detected
assign lsu_stall = ~data_ack_i;
assign misalign_stall = data_misaligned_i;
// deassert we signals (in case of stalls)
assign alu_operator_o = (deassert_we) ? `ALU_NOP : alu_operator;
assign mult_is_running_o = (deassert_we) ? 1'b0 : mult_is_running;
assign regfile_we_o = (deassert_we) ? 1'b0 : regfile_we;
assign regfile_alu_we_o = (deassert_we) ? 1'b0 : regfile_alu_we;
assign data_we_o = (deassert_we) ? 1'b0 : data_we;
assign data_req_o = (deassert_we) ? 1'b0 : data_req;
assign set_flag_o = (deassert_we) ? 1'b0 : set_flag;
assign set_overflow_o = (deassert_we) ? 1'b0 : set_overflow;
assign set_carry_o = (deassert_we) ? 1'b0 : set_carry;
////////////////////////////////////////////////////////////////////////////////////////////
// Freeze Unit. This unit controls the pipeline stages //
////////////////////////////////////////////////////////////////////////////////////////////
always_comb
begin
// we unstall the if_stage if the debug unit wants to set a new
// pc, so that the new value gets written into current_pc_if and is
// used by the instr_core_interface
stall_if_o = (instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_stall_i | (~pc_valid_i));
stall_id_o = instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_stall_i;
stall_ex_o = instr_ack_stall | lsu_stall | dbg_stall_i;
stall_wb_o = lsu_stall | dbg_stall_i;
end
////////////////////////////////////////////////////////////////////////////////////////////
// Freeze Unit. This unit controls the pipeline stages //
////////////////////////////////////////////////////////////////////////////////////////////
always_comb
begin
// we unstall the if_stage if the debug unit wants to set a new
// pc, so that the new value gets written into current_pc_if and is
// used by the instr_core_interface
stall_if_o = (instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | j_stall | lsu_stall | misalign_stall | dbg_stall_i | (~pc_valid_i));
stall_id_o = instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | j_stall | lsu_stall | misalign_stall | dbg_stall_i;
stall_ex_o = instr_ack_stall | lsu_stall | dbg_stall_i;
stall_wb_o = lsu_stall | dbg_stall_i;
end
////////////////////////////////////////////////////////////////////////////////////////////
// Forwarding control unit. (Forwarding from wb and ex stage to id stage) //
// RiscV register encoding: rs1 is [19:15], rs2 is [24:20], rd is [11:7] //
// Or10n register encoding: ra is [20:16], rb is [15:11], rd is [25:21] //
////////////////////////////////////////////////////////////////////////////////////////////
assign reg_d_ex_is_reg_a_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1);
assign reg_d_ex_is_reg_b_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1);
assign reg_d_ex_is_reg_c_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_D]) && (regc_used == 1'b1);
assign reg_d_wb_is_reg_a_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1);
assign reg_d_wb_is_reg_b_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1);
assign reg_d_wb_is_reg_c_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_D]) && (regc_used == 1'b1);
assign reg_d_alu_is_reg_a_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1);
assign reg_d_alu_is_reg_b_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1);
//assign reg_d_alu_is_reg_c_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_RD]) && (regc_used == 1'b1);
always_comb
begin
// default assignements
operand_a_fw_mux_sel_o = `SEL_REGFILE;
operand_b_fw_mux_sel_o = `SEL_REGFILE;
operand_c_fw_mux_sel_o = `SEL_REGFILE;
////////////////////////////////////////////////////////////////////////////////////////////
// Forwarding control unit. (Forwarding from wb and ex stage to id stage) //
// RiscV register encoding: rs1 is [19:15], rs2 is [24:20], rd is [11:7] //
// Or10n register encoding: ra is [20:16], rb is [15:11], rd is [25:21] //
////////////////////////////////////////////////////////////////////////////////////////////
assign reg_d_ex_is_reg_a_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1);
assign reg_d_ex_is_reg_b_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1);
assign reg_d_ex_is_reg_c_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_D]) && (regc_used == 1'b1);
assign reg_d_wb_is_reg_a_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1);
assign reg_d_wb_is_reg_b_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1);
assign reg_d_wb_is_reg_c_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_D]) && (regc_used == 1'b1);
assign reg_d_alu_is_reg_a_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1);
assign reg_d_alu_is_reg_b_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1);
//assign reg_d_alu_is_reg_c_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_RD]) && (regc_used == 1'b1);
// Forwarding WB -> ID
if (regfile_we_wb_i == 1'b1)
begin
if (reg_d_wb_is_reg_a_id == 1'b1)
operand_a_fw_mux_sel_o = `SEL_FW_WB;
if (reg_d_wb_is_reg_b_id == 1'b1)
operand_b_fw_mux_sel_o = `SEL_FW_WB;
if (reg_d_wb_is_reg_c_id == 1'b1)
operand_c_fw_mux_sel_o = `SEL_FW_WB;
end
always_comb
begin
// default assignements
operand_a_fw_mux_sel_o = `SEL_REGFILE;
operand_b_fw_mux_sel_o = `SEL_REGFILE;
operand_c_fw_mux_sel_o = `SEL_REGFILE;
// Forwarding WB -> ID
if (regfile_we_wb_i == 1'b1)
begin
if (reg_d_wb_is_reg_a_id == 1'b1)
operand_a_fw_mux_sel_o = `SEL_FW_WB;
if (reg_d_wb_is_reg_b_id == 1'b1)
operand_b_fw_mux_sel_o = `SEL_FW_WB;
if (reg_d_wb_is_reg_c_id == 1'b1)
operand_c_fw_mux_sel_o = `SEL_FW_WB;
end
// Forwarding EX -> ID
if (regfile_alu_we_fw_i == 1'b1)
begin
if (reg_d_alu_is_reg_a_id == 1'b1)
operand_a_fw_mux_sel_o = `SEL_FW_EX;
if (reg_d_alu_is_reg_b_id == 1'b1)
operand_b_fw_mux_sel_o = `SEL_FW_EX;
if (reg_d_alu_is_reg_c_id == 1'b1)
operand_c_fw_mux_sel_o = `SEL_FW_EX;
end
if (data_misaligned_i == 1'b1)
begin
operand_a_fw_mux_sel_o = `SEL_FW_EX;
operand_b_fw_mux_sel_o = `SEL_REGFILE;
end
end
// check if jump or branch in pipeline
/*
assign jump_in_id_o = ((instr_rdata_i[31:26] == `OPCODE_BF) || (instr_rdata_i[31:26] == `OPCODE_BNF) ||
(instr_rdata_i[31:26] == `OPCODE_J) || (instr_rdata_i[31:26] == `OPCODE_JR) ||
(instr_rdata_i[31:26] == `OPCODE_JAL) || (instr_rdata_i[31:26] == `OPCODE_JALR) ||
(instr_rdata_i[31:26] == `OPCODE_RFE) );
*/
// TODO: FIXME
assign jump_in_id_o = ((instr_rdata_i[6:0] == `OPCODE_JAL) || (instr_rdata_i[6:0] == `OPCODE_JALR) ||
(instr_rdata_i[6:0] == `OPCODE_BRANCH));
// Forwarding EX -> ID
if (regfile_alu_we_fw_i == 1'b1)
begin
if (reg_d_alu_is_reg_a_id == 1'b1)
operand_a_fw_mux_sel_o = `SEL_FW_EX;
if (reg_d_alu_is_reg_b_id == 1'b1)
operand_b_fw_mux_sel_o = `SEL_FW_EX;
if (reg_d_alu_is_reg_c_id == 1'b1)
operand_c_fw_mux_sel_o = `SEL_FW_EX;
end
if (data_misaligned_i == 1'b1)
begin
operand_a_fw_mux_sel_o = `SEL_FW_EX;
operand_b_fw_mux_sel_o = `SEL_REGFILE;
end
end
// update registers
always_ff @(posedge clk , negedge rst_n)
@ -1426,20 +1324,4 @@ module controller
end
end
`ifdef BRANCH_PREDICTION
// Wrong branch was taken!
always_ff @(posedge clk , negedge rst_n)
begin : WRONG_BRANCH
if ( rst_n == 1'b0 )
begin
wrong_branch_taken <= 1'b0;
end
else
begin
if (stall_if_o == 1'b0)
wrong_branch_taken <= wrong_branch_taken_o;
end
end
`endif
endmodule // controller

View file

@ -121,11 +121,13 @@ module ex_stage
output logic [31:0] regfile_alu_wdata_fw_o, // forward to RF and ID/EX pipe, ALU & MUL
output logic [31:0] regfile_alu_wdata_fw_pc_o, // forward to PC, no multiplication
// JAL/JALR jumpt target calculation (to IF)
output logic [31:0] jump_target_o,
// From ID: Jump and branch indication
input logic [1:0] jump_in_id_i,
// Branch decision (to controller)
output logic branch_taken_o
// To IF: Jump and branch target and decision
output logic [31:0] jump_target_o,
output logic [1:0] jump_in_ex_o,
output logic branch_decision_o
`ifdef TCDM_ADDR_PRECAL
,
@ -140,7 +142,6 @@ module ex_stage
// Internal output of the LU
logic [31:0] alu_result;
logic [31:0] alu_jump_target_int;
logic [31:0] alu_adder_lsu_int; // to LS unit
@ -183,17 +184,17 @@ module ex_stage
// NOTE a dedicated adder, no carry is considered , just op_a + op_b from id stage
`ifdef TCDM_ADDR_PRECAL
assign alu_adder_lsu_int = alu_adder_i;
$stop("TCDM_ADDR_PRECAL unsupported in RiscV! (jump/branch target calculation not implemented yet");
`else
assign alu_adder_lsu_int = alu_operand_a_i + alu_operand_b_i;
`endif
assign data_addr_ex_o = (prepost_useincr_i == 1'b1) ? alu_adder_lsu_int : alu_operand_a_i;
// PC calculation for JAL/JALR
assign jump_target_o = alu_jump_target_int;
// Branch is taken when result == 1'b1
assign branch_taken_o = alu_result[0];
assign branch_decision_o = alu_result[0];
assign jump_target_o = alu_operand_c_i;
////////////////////////////
@ -218,7 +219,6 @@ module ex_stage
.vec_ext_i ( alu_vec_ext_i ),
.result_o ( alu_result ),
.jump_target_o ( alu_jump_target_int ),
.overflow_o ( alu_overflow_int ), // Internal signal
.carry_o ( alu_carry_int ), // Internal signal
.flag_o ( alu_flag_o )
@ -269,6 +269,7 @@ module ex_stage
regfile_rb_data_wb_o <= 32'h0000_0000;
sp_we_wb_o <= 1'b0;
eoc_o <= 1'b0;
jump_in_ex_o <= '0;
end
else
begin
@ -281,6 +282,7 @@ module ex_stage
regfile_rb_data_wb_o <= regfile_rb_data_i;
sp_we_wb_o <= sp_we_i;
eoc_o <= eoc_i;
jump_in_ex_o <= jump_in_id_i;
end
end
end

View file

@ -41,16 +41,18 @@ module id_stage
input logic fetch_enable_i,
output logic core_busy_o,
input logic branch_taken_i,
// Interface to instruction memory
input logic [31:0] instr_rdata_i, // comes from pipeline of IF stage
output logic instr_req_o,
input logic instr_gnt_i,
input logic instr_ack_i,
// Jumps and branches
output logic [1:0] jump_in_id_o,
input logic [1:0] jump_in_ex_i,
// IF and ID stage signals
output logic [31:0] pc_from_immediate_o,
//output logic [31:0] pc_from_immediate_o, // TODO: remove
output logic [2:0] pc_mux_sel_o,
output logic pc_mux_boot_o,
@ -61,12 +63,6 @@ module id_stage
input logic [31:0] current_pc_if_i,
input logic [31:0] current_pc_id_i,
// branch prediction
output logic drop_instruction_o,
`ifdef BRANCH_PREDICTION
output logic wrong_branch_taken_o,
output logic take_branch_o,
`endif
// STALLS
output logic stall_if_o,
output logic stall_id_o,
@ -189,15 +185,19 @@ module id_stage
logic [31:0] current_pc; // PC to be used in ALU (either IF or ID)
logic [31:0] jump_target; // calculated jump target (-> EX -> IF)
logic exc_pc_sel;
logic [2:0] pc_mux_sel_int; // selects next PC in if stage
//logic pc_from_immediate_mux_sel = 1'b0; // TODO: FIXME (remove)
logic force_nop_controller;
logic irq_present;
// Signals running between controller and exception controller
logic jump_in_id;
logic jump_in_ex; // registered copy of jump_in_id
//logic jump_in_id;
//logic jump_in_ex; // registered copy of jump_in_id
logic illegal_insn;
logic trap_insn;
logic pipe_flush;
@ -308,7 +308,6 @@ module id_stage
assign regfile_addr_ra_id = instr_rdata_i[`REG_S1];
assign regfile_addr_rb_id = instr_rdata_i[`REG_S2];
//assign regfile_addr_rc_id = instr_rdata_i[25:21];
assign regfile_addr_rc_id = 32'd0;
// destination registers
assign regfile_waddr_id = instr_rdata_i[`REG_D];
@ -346,7 +345,7 @@ module id_stage
// 1'b1: pc_from_immediate_o = imm_i_type; // JALR
// endcase // case (pc_from_immediate_mux_sel)
//end
assign pc_from_immediate_o = imm_sb_type; // TODO: Remove/Replace?
//assign pc_from_immediate_o = imm_sb_type; // TODO: Remove/Replace?
// PC Mux
always_comb
@ -384,6 +383,26 @@ module id_stage
*/
//////////////////////////////////////////////////////////////////
// _ _____ _ //
// | |_ _ _ __ ___ _ __ |_ _|_ _ _ __ __ _ ___| |_ //
// _ | | | | | '_ ` _ \| '_ \ | |/ _` | '__/ _` |/ _ \ __| //
// | |_| | |_| | | | | | | |_) | | | (_| | | | (_| | __/ |_ //
// \___/ \__,_|_| |_| |_| .__/ |_|\__,_|_| \__, |\___|\__| //
// |_| |___/ //
//////////////////////////////////////////////////////////////////
always_comb
begin
unique case (instr_rdata_i[6:0])
`OPCODE_JAL: jump_target = current_pc_id_i + imm_uj_type;
`OPCODE_JALR: jump_target = operand_a_fw_id + imm_i_type;
`OPCODE_BRANCH: jump_target = current_pc_id_i + imm_sb_type;
default: jump_target = '0;
endcase // unique case (instr_rdata_i[6:0])
end
////////////////////////////////////////////////////////
// ___ _ _ //
// / _ \ _ __ ___ _ __ __ _ _ __ __| | / \ //
@ -429,13 +448,12 @@ module id_stage
always_comb
begin : immediate_mux
case (immediate_mux_sel)
default: immediate_b = 32'h4;
//`IMM_VEC: immediate_b = immediate_vec_id;
`IMM_I: immediate_b = imm_i_type;
`IMM_S: immediate_b = imm_s_type;
//`IMM_SB: immediate_b = imm_sb_type;
`IMM_U: immediate_b = imm_u_type;
`IMM_UJ: immediate_b = imm_uj_type;
`IMM_I: immediate_b = imm_i_type;
`IMM_S: immediate_b = imm_s_type;
`IMM_U: immediate_b = imm_u_type;
`IMM_HEX4: immediate_b = 32'h4;
default: immediate_b = 32'h4;
endcase; // case (immediate_mux_sel)
end
@ -482,8 +500,9 @@ module id_stage
always_comb
begin : alu_operand_c_mux
case (alu_op_c_mux_sel)
`OP_C_CURRPC: operand_c = current_pc;
default: operand_c = regfile_data_rc_id;
`OP_C_JT: operand_c = jump_target;
//`OP_C_CURRPC: operand_c = current_pc;
default: operand_c = regfile_data_rc_id;
endcase // case (alu_op_c_mux_sel)
end
@ -553,7 +572,7 @@ module id_stage
.eoc_o ( eoc ),
.core_busy_o ( core_busy_o ),
.branch_taken_i ( branch_taken_i ),
.force_nop_o ( force_nop_controller ),
// Signal from-to PC pipe (instr rdata) and instr mem system (req and ack)
.instr_rdata_i ( instr_rdata_i ),
@ -620,7 +639,7 @@ module id_stage
.irq_present_i ( irq_present ),
// Exception Controller Signals
.jump_in_id_o ( jump_in_id ),
//.jump_in_id_o ( jump_in_id ),
.illegal_insn_o ( illegal_insn ),
.trap_insn_o ( trap_insn ),
.pipe_flush_o ( pipe_flush ),
@ -656,14 +675,12 @@ module id_stage
.operand_b_fw_mux_sel_o ( operand_b_fw_mux_sel ),
.operand_c_fw_mux_sel_o ( operand_c_fw_mux_sel ),
.jump_in_ex_i ( jump_in_ex ),
// To controller (TODO: Remove when control/decode separated and moved)
.jump_in_ex_i ( jump_in_ex_i ),
// To EX: Jump/Branch indication
.jump_in_id_o ( jump_in_id_o ),
// branch prediction
.drop_instruction_o ( drop_instruction_o ),
`ifdef BRANCH_PREDICTION
.wrong_branch_taken_o ( wrong_branch_taken_o ),
.take_branch_o ( take_branch_o ),
`endif
// Stall signals
.stall_if_o ( stall_if_o ),
.stall_id_o ( stall_id_o ),
@ -680,7 +697,8 @@ module id_stage
// //
///////////////////////////////////////////////////////////////////////
assign force_nop_o = 1'b0;
assign force_nop_o = force_nop_controller;
/*
exc_controller exc_controller_i
(
@ -823,8 +841,6 @@ module id_stage
hwloop_wb_mux_sel_ex_o <= 1'b0;
hwloop_cnt_o <= 32'b0;
jump_in_ex <= 1'b0;
eoc_ex_o <= 1'b0;
`ifdef TCDM_ADDR_PRECAL
@ -898,14 +914,11 @@ module id_stage
hwloop_wb_mux_sel_ex_o <= hwloop_wb_mux_sel;
hwloop_cnt_o <= hwloop_cnt;
jump_in_ex <= jump_in_id;
eoc_ex_o <= eoc;
`ifdef TCDM_ADDR_PRECAL
alu_adder_o <= alu_operand_a + alu_operand_b;
`endif
end
end

View file

@ -40,42 +40,39 @@ module if_stage
input logic [31:0] boot_addr_i,
// Output of IF Pipeline stage
output logic [31:0] instr_rdata_id_o, // read instruction is sampled and sent to ID stage for decoding
output logic [31:0] current_pc_if_o, // current pc program counter
output logic [31:0] current_pc_id_o, // current pc program counter
output logic [31:0] instr_rdata_id_o, // read instruction is sampled and sent to ID stage for decoding
output logic [31:0] current_pc_if_o, // "current" pc program counter
output logic [31:0] current_pc_id_o, // current pc program counter
// From to Instr memory
input logic [31:0] instr_rdata_i, // Instruction read from instruction memory /cache
output logic [31:0] instr_addr_o, // address for instruction fetch
input logic [31:0] instr_rdata_i, // Instruction read from instruction memory /cache
output logic [31:0] instr_addr_o, // address for instruction fetch
// Forwarding ports - control signals
input logic force_nop_i, // insert a NOP in the pipe
input logic [31:0] exception_pc_reg_i, // address used to restore the program counter when the interrupt/exception is served
input logic [31:0] pc_from_regfile_i, // pc from reg file
input logic [31:0] pc_from_alu_i, // calculated jump target form ALU
input logic [31:0] pc_from_immediate_i, // pc from immediate
input logic [31:0] pc_from_hwloop_i, // pc from hwloop start addr
input logic [2:0] pc_mux_sel_i, // sel for pc multiplexer
input logic pc_mux_boot_i, // load boot address as PC
input logic [1:0] exc_pc_mux_i, // select which exception to execute
input logic force_nop_i, // insert a NOP in the pipe
input logic [31:0] exception_pc_reg_i, // address used to restore the program counter when the interrupt/exception is served
input logic [31:0] pc_from_regfile_i, // pc from reg file
//input logic [31:0] pc_from_immediate_i, // pc from immediate
input logic [31:0] pc_from_hwloop_i, // pc from hwloop start addr
input logic [2:0] pc_mux_sel_i, // sel for pc multiplexer
input logic pc_mux_boot_i, // load boot address as PC
input logic [1:0] exc_pc_mux_i, // select which exception to execute
// jump and branch target and decision
input logic [31:0] jump_target_i, // jump target
input logic [1:0] jump_in_ex_i, // jump in EX -> get PC from jump target (could also be branch)
input logic branch_decision_i,
// from debug unit
input logic [31:0] dbg_pc_from_npc,
input logic dbg_set_npc,
// branch prediction
input logic drop_instruction_i,
`ifdef BRANCH_PREDICTION
input logic wrong_branch_taken_i,
input logic take_branch_i,
`endif
// pipeline stall
input logic stall_if_i,
input logic stall_id_i // Stall in the id stage: here (if_stage) freeze the registers
);
////////////////////////////////////
// Instruction Fetch (IF) signals //
////////////////////////////////////
@ -83,29 +80,18 @@ module if_stage
logic [31:0] exc_pc; // Exception PC
logic [31:0] instr_rdata_int; // The instruction read from instr memory/cache is forwarded to ID stage, and the controller can force this forwarding to a nop (BUBBLE)
`ifdef BRANCH_PREDICTION
logic [31:0] correct_branch;
`endif
logic [31:0] branch_taken;
logic [31:0] branch_not_taken;
// Address to fetch the instruction
assign instr_addr_o = next_pc;
assign branch_taken = current_pc_id_o + pc_from_immediate_i;
//assign branch_not_taken = current_pc_if_o + 32'd4;
// Next PC Selection: pc_mux_sel_i comes from id_stage.controller
always_comb
/*always_comb
begin : PC_MUX
case (pc_mux_sel_i)
`INCR_PC: begin next_pc = current_pc_if_o + 32'd4; end // PC is incremented and points the next instruction
`NO_INCR: begin next_pc = current_pc_if_o; end // PC is not incremented
//`PC_FROM_REGFILE: begin next_pc = pc_from_regfile_i; end // PC is taken from the regfile
`PC_FROM_ALU: begin next_pc = pc_from_alu_i; end // use calculated jump target from ALU
`PC_FROM_IMM: begin next_pc = branch_taken; end // PC is taken from current PC in id + the immediate displacement
//`PC_FROM_ALU: begin next_pc = pc_from_alu_i; end // use calculated jump target from ALU
`PC_EXCEPTION: begin next_pc = exc_pc; end // PC that points to the exception
`EXC_PC_REG: begin next_pc = exception_pc_reg_i; end // restore the PC when exiting from interr/ecpetions
`HWLOOP_ADDR: begin next_pc = pc_from_hwloop_i; end // PC is taken from hwloop start addr
@ -114,8 +100,7 @@ module if_stage
`endif
default: begin next_pc = current_pc_if_o + 32'd4; end
endcase //~case (pc_mux_sel_i)
end
end */
// Exception PC selection
always_comb
@ -128,8 +113,45 @@ module if_stage
endcase //~case (exc_pc_mux_i)
end
// NOP = addi x0, x0, 0
assign instr_rdata_int = (force_nop_i == 1'b1) ? { {25 {1'b0}}, `OPCODE_OPIMM } : instr_rdata_i;
// PC selection and force NOP logic
always_comb
begin
next_pc = current_pc_if_o;
instr_rdata_int = instr_rdata_i;
unique case (pc_mux_sel_i)
`PC_INCR: next_pc = current_pc_if_o + 32'd4; // PC is incremented and points the next instruction
`PC_NO_INCR: next_pc = current_pc_if_o; // PC is not incremented
`PC_EXCEPTION: next_pc = exc_pc; // PC that points to the exception
`EXC_PC_REG: next_pc = exception_pc_reg_i; // restore the PC when exiting from interr/ecpetions
`HWLOOP_ADDR: next_pc = pc_from_hwloop_i; // PC is taken from hwloop start addr
default:
begin
next_pc = current_pc_if_o;
// synopsis translate off
$display("%t: Illegal pc_mux_sel value (%0d)!", $time, pc_mux_sel_i);
// synopsis translate on
end
endcase // unique case (pc_mux_sel_i)
// if force NOP, do not increase PC
if (force_nop_i == 1'b1) begin
instr_rdata_int = { 25'b0, `OPCODE_OPIMM }; // addi x0 = x0 + 0
next_pc = current_pc_if_o;
end
if (jump_in_ex_i == 2'b01) begin
next_pc = jump_target_i;
end else if (jump_in_ex_i == 2'b10) begin
if (branch_decision_i == 1'b1)
next_pc = jump_target_i;
else
next_pc = current_pc_if_o;// + 32'd4; // TODO: Check if merged with previous adder (from PC mux)
end
end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IF PC register //
@ -159,24 +181,6 @@ module if_stage
end
end
`ifdef BRANCH_PREDICTION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Save branch targets in case of a misprediction //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
always_ff @(posedge clk, negedge rst_n)
begin : SAVE_BRANCH_TARGET
if (rst_n == 1'b0)
begin : ASSERT_RESET
correct_branch <= 32'b0;
end
else
begin : DEASSERT_RESET
if (wrong_branch_taken_i)
correct_branch <= (take_branch_i) ? branch_taken : branch_not_taken;
end
end
`endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IF-ID PIPE: Pipeline that is frozen when the ID stage is stalled //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -184,15 +188,15 @@ module if_stage
begin : IF_ID_PIPE_REGISTERS
if (rst_n == 1'b0)
begin : ASSERT_RESET
instr_rdata_id_o <= '0;
current_pc_id_o <= '0;
instr_rdata_id_o <= '0;
current_pc_id_o <= '0;
end
else
begin : DEASSERT_RESET
if((stall_id_i == 1'b0) & (drop_instruction_i == 1'b0))
if (stall_id_i == 1'b0)
begin : ENABLED_PIPE
instr_rdata_id_o <= instr_rdata_int;
current_pc_id_o <= current_pc_if_o;
instr_rdata_id_o <= instr_rdata_int;
current_pc_id_o <= current_pc_if_o;
end
end
end

View file

@ -170,6 +170,8 @@
// synopsis translate off
`define TRACE_EXECUTION
function void prettyPrintInstruction(input [31:0] instr, input [31:0] pc);
string opcode;
begin
@ -268,9 +270,6 @@ endfunction // prettyPrintInstruction
`define ALU_FL1 6'b11_0011
`define ALU_CLB 6'b11_0001
// next PC and PC+4 computation for JAL/JALR in RiscV
`define ALU_JAL 6'b11_1000
// Vector Mode
`define VEC_MODE32 2'b00
@ -341,32 +340,22 @@ endfunction // prettyPrintInstruction
// operand c selection
`define OP_C_REGC_OR_FWD 1'b0
`define OP_C_CURRPC 1'b1
`define OP_C_JT 1'b1
// immediate selection
// - `define IMM_5N11 4'b0000
// - `define IMM_21S 4'b0001
// - `define IMM_8Z 4'b0010
// - `define IMM_16Z 4'b0011
// - `define IMM_16 4'b0100
// - `define IMM_11S 4'b0101
// - `define IMM_5N6S 4'b0110
// - `define IMM_VEC 4'b0111
// - `define IMM_HEX4 4'b1000
`define IMM_I 3'b000
`define IMM_S 3'b010
// operand b immediate selection
`define IMM_I 2'b00
`define IMM_S 2'b01
`define IMM_U 2'b10
`define IMM_HEX4 2'b11
/* not used:
`define IMM_SB 3'b011
`define IMM_U 3'b100
`define IMM_UJ 3'b101
`define IMM_C4 3'b110
*/
// PC mux selector defines
`define INCR_PC 3'b000
`define NO_INCR 3'b001
//`define PC_FROM_REGFILE 3'b010 Removed in RiscV
`define PC_FROM_IMM 3'b010
//`define PC_FROM_IMM 3'b011 Replaced in RiscV
`define PC_FROM_ALU 3'b011
`define PC_INCR 3'b000
`define PC_NO_INCR 3'b001
`define PC_EXCEPTION 3'b100
`define EXC_PC_REG 3'b101
`define HWLOOP_ADDR 3'b110
@ -409,4 +398,4 @@ endfunction // prettyPrintInstruction
// TCDM_ADDRES PRE CALCULATION --> Bring part of the alu_adder_o calculation in the ID stage
//`define TCDM_ADDR_PRECAL
//`define BRANCH_PREDICTION
//`define BRANCH_PREDICTION

View file

@ -93,8 +93,8 @@ module riscv_core
// Jump and branch target and decision (EX->IF)
logic [31:0] jump_target;
logic jump_in_ex;
logic branch_in_ex;
logic [1:0] jump_in_id;
logic [1:0] jump_in_ex;
logic branch_decision;
@ -289,6 +289,11 @@ module riscv_core
.dbg_pc_from_npc ( dbg_npc ),
.dbg_set_npc ( dbg_set_npc ),
// Jump and branch target and decision
.jump_in_ex_i ( jump_in_ex ),
.branch_decision_i ( branch_decision ),
.jump_target_i ( jump_target ),
// pipeline stalls
.stall_if_i ( stall_if ),
.stall_id_i ( stall_id )
@ -341,6 +346,9 @@ module riscv_core
// Processor Enable
.fetch_enable_i ( fetch_enable_i ),
.jump_in_id_o ( jump_in_id ),
.jump_in_ex_i ( jump_in_ex ),
.core_busy_o ( core_busy_o ),
// Interface to instruction memory
@ -357,7 +365,7 @@ module riscv_core
.pc_from_regfile_o ( pc_from_regfile_id ),
.current_pc_if_i ( current_pc_if ),
.current_pc_id_i ( current_pc_id ),
//.pc_from_immediate_o ( pc_from_immediate_id ),
//.pc_from_immediate_o ( pc_from_immediate_id ), //TODO
.sr_flag_fw_i ( sr_flag_fw ),
.sr_flag_i ( sr_flag ),
@ -535,7 +543,6 @@ module riscv_core
.regfile_rb_data_i ( regfile_rb_data_ex ),
.sp_we_i ( sp_we_ex ),
// Output of ex stage pipeline
.regfile_wdata_wb_o ( result_wb ),
.regfile_waddr_wb_o ( regfile_waddr_fw_wb_o ),
@ -553,10 +560,12 @@ module riscv_core
.sp_we_wb_o ( sp_we_wb ),
.eoc_o ( eoc_wb ),
// From ID: Jump and Branch detection
.jump_in_id_i ( jump_in_id ),
// To IF: Jump and branch target and decision
.jump_target_o ( jump_target ),
.jump_in_ex_o ( jump_in_ex ),
.branch_in_ex_o ( branch_in_ex ),
.branch_decision_o ( branch_decision ),
// To ID stage: Forwarding signals
@ -812,7 +821,7 @@ module riscv_core
instr = id_stage_i.instr_rdata_i[31:0];
pc = id_stage_i.current_pc_id_i;
if (fetch_enable_i == 1'b1 && id_stage_i.stall_id_o == 1'b0)
if (fetch_enable_i == 1'b1 && id_stage_i.stall_id_o == 1'b0 && id_stage_i.controller_i.ctrl_fsm_cs == id_stage_i.controller_i.DECODE)
begin
//$display("%h", instr);
$fwrite(f, "%t:\t0x%h\t0x%h\t", $time, pc, instr);
@ -883,7 +892,7 @@ module riscv_core
function void printRInstr(input string mnemonic);
begin
$fdisplay(f, "%s x%0d, x%d (0x%h), x%0d (0x%h)", mnemonic, instr[`REG_D],
$fdisplay(f, "%s\tx%0d, x%d (0x%h), x%0d (0x%h)", mnemonic, instr[`REG_D],
instr[`REG_S1], r[instr[`REG_S1]], instr[`REG_S2], r[instr[`REG_S2]]);
end
endfunction // printRInstr
@ -892,7 +901,7 @@ module riscv_core
logic [31:0] i_imm;
begin
i_imm = { {20 {instr[31]}}, instr[31:20] };
$fdisplay(f, "%s x%0d, x%0d (0x%h), 0x%0d (imm)", mnemonic, instr[`REG_D],
$fdisplay(f, "%s\tx%0d, x%0d (0x%h), 0x%0d (imm)", mnemonic, instr[`REG_D],
instr[`REG_S1], r[instr[`REG_S1]], i_imm);
end
endfunction // printIInstr
@ -901,7 +910,7 @@ module riscv_core
logic [31:0] s_imm;
begin
s_imm = { {20 {instr[31]}}, instr[31:25], instr[11:7] };
$fdisplay(f, "%s x%0d (0x%h), x%0d (0x%h), 0x%h (imm)", mnemonic,
$fdisplay(f, "%s\tx%0d (0x%h), x%0d (0x%h), 0x%h (imm)", mnemonic,
instr[`REG_S1], r[instr[`REG_S1]], instr[`REG_S2], r[instr[`REG_S2]],
s_imm);
end
@ -911,7 +920,7 @@ module riscv_core
logic [31:0] sb_imm;
begin
sb_imm = { {20 {instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8] };
$fdisplay(f, "%s x%0d (0x%h), x%0d (0x%h), 0x%h (imm)", mnemonic,
$fdisplay(f, "%s\tx%0d (0x%h), x%0d (0x%h), 0x%h (imm)", mnemonic,
instr[`REG_S1], r[instr[`REG_S1]], instr[`REG_S2], r[instr[`REG_S2]],
sb_imm);
end
@ -921,13 +930,13 @@ module riscv_core
logic [31:0] uj_imm;
begin
uj_imm = { {20 {instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 };
$fdisplay(f, "%s x%0d, 0x%h", mnemonic, instr[`REG_D], uj_imm);
$fdisplay(f, "%s\tx%0d, 0x%h", mnemonic, instr[`REG_D], uj_imm);
end
endfunction // printUJInstr
function void printRDInstr(input string mnemonic);
begin
$fdisplay(f, "%s x%0d", mnemonic, instr[`REG_D]);
$fdisplay(f, "%s\tx%0d", mnemonic, instr[`REG_D]);
end
endfunction // printRDInstr