Added BRANCH support

This commit is contained in:
Sven Stucki 2015-04-13 16:08:27 +02:00
parent 20b51d01b4
commit 902badaf3b
6 changed files with 67 additions and 18 deletions

View file

@ -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

View file

@ -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];
////////////////////////////
// _ _ _ _ //

View file

@ -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 ),

View file

@ -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

View file

@ -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

View file

@ -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