mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-22 21:17:59 -04:00
Added BRANCH support
This commit is contained in:
parent
20b51d01b4
commit
902badaf3b
6 changed files with 67 additions and 18 deletions
|
@ -138,6 +138,9 @@ module controller
|
|||
// Jump target calcuation done detection
|
||||
input logic jump_in_ex_i, // 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
|
||||
|
@ -346,6 +349,30 @@ module controller
|
|||
end
|
||||
end
|
||||
|
||||
`OPCODE_BRANCH: begin // Branch
|
||||
rega_used = 1'b1;
|
||||
regb_used = 1'b1;
|
||||
|
||||
unique case (instr_rdata_i) inside
|
||||
`INSTR_BEQ: alu_operator = `ALU_EQ;
|
||||
`INSTR_BNE: alu_operator = `ALU_NE;
|
||||
`INSTR_BLT: alu_operator = `ALU_LTS;
|
||||
`INSTR_BGE: alu_operator = `ALU_GES;
|
||||
`INSTR_BLTU: alu_operator = `ALU_LTU;
|
||||
`INSTR_BGEU: alu_operator = `ALU_GEU;
|
||||
|
||||
default: begin
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase // case (instr_rdata_i)
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
|
||||
`OPCODE_JR:
|
||||
|
@ -1246,10 +1273,10 @@ module controller
|
|||
deassert_we = 1'b1;
|
||||
end
|
||||
|
||||
// Stall because of JAL/JALR
|
||||
// Stall until jump target is calculated in EX (1 cycle, then fetch instruction)
|
||||
if ( (instr_rdata_i[6:0] == `OPCODE_JAL || instr_rdata_i[6:0] == `OPCODE_JALR) &&
|
||||
(jump_in_ex_i == 1'b0) )
|
||||
// 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;
|
||||
|
@ -1265,6 +1292,7 @@ module controller
|
|||
|
||||
end
|
||||
|
||||
// NOTE: current_pc_id_i is wrong after drop instruction !
|
||||
`ifdef BRANCH_PREDICTION
|
||||
assign drop_instruction_o = wrong_branch_taken | j_stall;
|
||||
`else
|
||||
|
@ -1365,7 +1393,8 @@ module controller
|
|||
(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));
|
||||
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));
|
||||
|
||||
|
||||
// update registers
|
||||
|
|
|
@ -122,7 +122,10 @@ module ex_stage
|
|||
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
|
||||
output logic [31:0] jump_target_o,
|
||||
|
||||
// Branch decision (to controller)
|
||||
output logic branch_taken_o
|
||||
|
||||
`ifdef TCDM_ADDR_PRECAL
|
||||
,
|
||||
|
@ -189,6 +192,9 @@ module ex_stage
|
|||
// 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];
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// _ _ _ _ //
|
||||
|
|
|
@ -41,6 +41,8 @@ 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,
|
||||
|
@ -297,7 +299,7 @@ module id_stage
|
|||
assign imm_i_type = { {20 {instr_rdata_i[31]}}, instr_rdata_i[31:20] };
|
||||
assign imm_s_type = { {20 {instr_rdata_i[31]}}, instr_rdata_i[31:25], instr_rdata_i[11:7] };
|
||||
assign imm_sb_type = { {20 {instr_rdata_i[31]}}, instr_rdata_i[31], instr_rdata_i[7],
|
||||
instr_rdata_i[30:25], instr_rdata_i[11:8] };
|
||||
instr_rdata_i[30:25], instr_rdata_i[11:8], 1'b0 };
|
||||
assign imm_u_type = { instr_rdata_i[31:12], {12 {1'b0}} };
|
||||
assign imm_uj_type = { {20 {instr_rdata_i[31]}}, instr_rdata_i[19:12],
|
||||
instr_rdata_i[20], instr_rdata_i[30:21], 1'b0 };
|
||||
|
@ -344,6 +346,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?
|
||||
|
||||
// PC Mux
|
||||
always_comb
|
||||
|
@ -550,6 +553,8 @@ module id_stage
|
|||
.eoc_o ( eoc ),
|
||||
.core_busy_o ( core_busy_o ),
|
||||
|
||||
.branch_taken_i ( branch_taken_i ),
|
||||
|
||||
// Signal from-to PC pipe (instr rdata) and instr mem system (req and ack)
|
||||
.instr_rdata_i ( instr_rdata_i ),
|
||||
.instr_req_o ( instr_req_o ),
|
||||
|
|
|
@ -53,7 +53,7 @@ module if_stage
|
|||
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_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
|
||||
|
@ -94,7 +94,7 @@ module if_stage
|
|||
// Address to fetch the instruction
|
||||
assign instr_addr_o = next_pc;
|
||||
|
||||
//assign branch_taken = current_pc_id_o + pc_from_immediate_i;
|
||||
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
|
||||
|
@ -103,9 +103,9 @@ module if_stage
|
|||
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_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_IMM: begin next_pc = branch_taken; end // PC is taken from current PC in id + the immediate displacement
|
||||
`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
|
||||
|
|
|
@ -363,7 +363,8 @@ endfunction // prettyPrintInstruction
|
|||
// PC mux selector defines
|
||||
`define INCR_PC 3'b000
|
||||
`define NO_INCR 3'b001
|
||||
`define PC_FROM_REGFILE 3'b010
|
||||
//`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_EXCEPTION 3'b100
|
||||
|
|
|
@ -90,10 +90,14 @@ module riscv_core
|
|||
|
||||
// Forwarding
|
||||
//logic [31:0] pc_from_immediate_id; //take PC from immediate in case of Jump
|
||||
logic [31:0] pc_from_immediate_id; //take PC from immediate in case of branch (RiscV)
|
||||
|
||||
// Jump handling
|
||||
logic [31:0] jump_target;
|
||||
|
||||
// Branch decision from EX
|
||||
logic branch_taken;
|
||||
|
||||
// Stalling
|
||||
logic stall_if; // Stall instruction fetch(deassert request)
|
||||
logic stall_id; // Stall PC stage and instr memory and data memo
|
||||
|
@ -281,7 +285,7 @@ module riscv_core
|
|||
.force_nop_i ( force_nop_id ), // select incoming instr or NOP
|
||||
.exception_pc_reg_i ( epcr ), // Exception PC register
|
||||
.pc_from_regfile_i ( pc_from_regfile_id ), // pc from reg file
|
||||
//.pc_from_immediate_i ( pc_from_immediate_id ), // pc from immediate
|
||||
.pc_from_immediate_i ( pc_from_immediate_id ), // pc from immediate
|
||||
.pc_from_alu_i ( jump_target ), // calculated jump target from ALU (EX)
|
||||
.pc_from_hwloop_i ( hwloop_targ_addr ), // pc from hwloop start address
|
||||
.pc_mux_sel_i ( pc_mux_sel_id ), // sel for pc multiplexer
|
||||
|
@ -350,6 +354,8 @@ module riscv_core
|
|||
// Processor Enable
|
||||
.fetch_enable_i ( fetch_enable_i ),
|
||||
|
||||
.branch_taken_i ( branch_taken ),
|
||||
|
||||
.core_busy_o ( core_busy_o ),
|
||||
|
||||
// Interface to instruction memory
|
||||
|
@ -366,7 +372,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 ),
|
||||
|
||||
.sr_flag_fw_i ( sr_flag_fw ),
|
||||
.sr_flag_i ( sr_flag ),
|
||||
|
@ -570,6 +576,9 @@ module riscv_core
|
|||
// Jump target address
|
||||
.jump_target_o ( jump_target ),
|
||||
|
||||
// Branch decision
|
||||
.branch_taken_o ( branch_taken ),
|
||||
|
||||
// To ID stage: Forwarding signals
|
||||
.regfile_alu_waddr_fw_o ( regfile_alu_waddr_fw ),
|
||||
.regfile_alu_we_fw_o ( regfile_alu_we_fw ),
|
||||
|
@ -818,7 +827,6 @@ module riscv_core
|
|||
// log execution
|
||||
always @(posedge clk)
|
||||
begin
|
||||
#1
|
||||
r = id_stage_i.registers_i.MemContentxDP;
|
||||
instr = id_stage_i.instr_rdata_i[31:0];
|
||||
pc = id_stage_i.current_pc_id_i;
|
||||
|
@ -827,7 +835,7 @@ module riscv_core
|
|||
begin
|
||||
//$display("%h", instr);
|
||||
$fwrite(f, "%t:\t0x%h\t0x%h\t", $time, pc, instr);
|
||||
casex (instr)
|
||||
unique case (instr) inside
|
||||
`INSTR_LUI: printIInstr("LUI");
|
||||
`INSTR_AUIPC: printIInstr("AUIPC");
|
||||
`INSTR_JAL: printUJInstr("JAL");
|
||||
|
@ -912,7 +920,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%d (0x%h), 0x%h (imm)", mnemonic,
|
||||
$fdisplay(f, "%s x%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
|
||||
|
@ -922,7 +930,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%d (0x%h), 0x%h (imm)", mnemonic,
|
||||
$fdisplay(f, "%s x%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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue