cvw/src/ifu/bpred/icpred.sv

108 lines
5.3 KiB
Systemverilog
Raw Normal View History

///////////////////////////////////////////
// icpred.sv
//
// Written: Ross Thomposn ross1728@gmail.com
// Created: February 26, 2023
// Modified: February 26, 2023
//
// Purpose: Partial decode of instructions into control flow instructions (cfi)P
// Call, Return, Jump, and Branch
//
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
// may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work 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.
////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
`define INSTR_CLASS_PRED 1
module icpred (
input logic clk, reset,
input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW,
2023-02-27 03:28:36 +00:00
input logic [31:0] PostSpillInstrRawF, InstrD, // Instruction
input logic BranchD, BranchE,
input logic JumpD, JumpE,
output logic BranchM, BranchW,
output logic JumpM, JumpW,
output logic CallD, CallE, CallM, CallW,
output logic ReturnD, ReturnE, ReturnM, ReturnW,
input logic BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF,
output logic BPCallF, BPReturnF, BPJumpF, BPBranchF,
output logic PredictionInstrClassWrongM, WrongBPReturnD
);
logic AnyWrongPredInstrClassD, AnyWrongPredInstrClassE;
logic BPBranchD, BPJumpD, BPReturnD, BPCallD;
if (!`INSTR_CLASS_PRED) begin : DirectClassDecode
// This section is mainly for testing, verification, and PPA comparison.
// An alternative to using the BTB to store the instruction class is to partially decode
// the instructions in the Fetch stage into, Call, Return, Jump, and Branch instructions.
// This logic is not described in the text book as of 23 February 2023.
logic ccall, cj, cjr, ccallr, CJumpF, CBranchF;
logic NCJumpF, NCBranchF;
if(`C_SUPPORTED) begin
logic [4:0] CompressedOpcF;
assign CompressedOpcF = {PostSpillInstrRawF[1:0], PostSpillInstrRawF[15:13]};
assign ccall = CompressedOpcF == 5'h09 & `XLEN == 32;
assign cj = CompressedOpcF == 5'h0d;
assign cjr = CompressedOpcF == 5'h14 & ~PostSpillInstrRawF[12] & PostSpillInstrRawF[6:2] == 5'b0 & PostSpillInstrRawF[11:7] != 5'b0;
assign ccallr = CompressedOpcF == 5'h14 & PostSpillInstrRawF[12] & PostSpillInstrRawF[6:2] == 5'b0 & PostSpillInstrRawF[11:7] != 5'b0;
assign CJumpF = ccall | cj | cjr | ccallr;
assign CBranchF = CompressedOpcF[4:1] == 4'h7;
end else begin
assign {ccall, cj, cjr, ccallr, CJumpF, CBranchF} = '0;
end
assign NCJumpF = PostSpillInstrRawF[6:0] == 7'h67 | PostSpillInstrRawF[6:0] == 7'h6F;
assign NCBranchF = PostSpillInstrRawF[6:0] == 7'h63;
assign BPBranchF = NCBranchF | (`C_SUPPORTED & CBranchF);
assign BPJumpF = NCJumpF | (`C_SUPPORTED & (CJumpF));
assign BPReturnF = (NCJumpF & (PostSpillInstrRawF[19:15] & 5'h1B) == 5'h01) | // returnurn must returnurn to ra or r5
(`C_SUPPORTED & (ccallr | cjr) & ((PostSpillInstrRawF[11:7] & 5'h1B) == 5'h01));
assign BPCallF = (NCJumpF & (PostSpillInstrRawF[11:07] & 5'h1B) == 5'h01) | // call(r) must link to ra or x5
(`C_SUPPORTED & (ccall | (ccallr & (PostSpillInstrRawF[11:7] & 5'h1b) == 5'h01)));
end else begin
// This section connects the BTB's instruction class prediction.
assign {BPCallF, BPReturnF, BPJumpF, BPBranchF} = {BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF};
end
assign ReturnD = JumpD & (InstrD[19:15] & 5'h1B) == 5'h01; // returnurn must returnurn to ra or x5
assign CallD = JumpD & (InstrD[11:7] & 5'h1B) == 5'h01; // call(r) must link to ra or x5
flopenrc #(2) InstrClassRegE(clk, reset, FlushE, ~StallE, {CallD, ReturnD}, {CallE, ReturnE});
flopenrc #(4) InstrClassRegM(clk, reset, FlushM, ~StallM, {CallE, ReturnE, JumpE, BranchE}, {CallM, ReturnM, JumpM, BranchM});
flopenrc #(4) InstrClassRegW(clk, reset, FlushM, ~StallW, {CallM, ReturnM, JumpM, BranchM}, {CallW, ReturnW, JumpW, BranchW});
// branch predictor
flopenrc #(1) BPClassWrongRegM(clk, reset, FlushM, ~StallM, AnyWrongPredInstrClassE, PredictionInstrClassWrongM);
flopenrc #(1) WrongInstrClassRegE(clk, reset, FlushE, ~StallE, AnyWrongPredInstrClassD, AnyWrongPredInstrClassE);
// pipeline the predicted class
flopenrc #(4) PredInstrClassRegD(clk, reset, FlushD, ~StallD, {BPCallF, BPReturnF, BPJumpF, BPBranchF}, {BPCallD, BPReturnD, BPJumpD, BPBranchD});
// branch class prediction wrong.
assign AnyWrongPredInstrClassD = |({BPCallD, BPReturnD, BPJumpD, BPBranchD} ^ {CallD, ReturnD, JumpD, BranchD});
assign WrongBPReturnD = BPReturnD ^ ReturnD;
endmodule