Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
7b65f6ba0This file is pinned to the selected release. Download the original to open it in your design tool.
// Copyright 2019- RSD contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
//
// Branch target buffer
//
import BasicTypes::*;
import MemoryMapTypes::*;
import FetchUnitTypes::*;
module BTB(
NextPCStageIF.BTB port,
FetchStageIF.BTB next
);
// BTB access
logic btbWE[INT_ISSUE_WIDTH];
BTB_IndexPath btbWA[INT_ISSUE_WIDTH];
BTB_Entry btbWV[INT_ISSUE_WIDTH];
BTB_IndexPath btbRA[FETCH_WIDTH];
BTB_Entry btbRV[FETCH_WIDTH];
// Output
PC_Path btbOut[FETCH_WIDTH];
logic btbHit[FETCH_WIDTH];
logic readIsCondBr[FETCH_WIDTH];
PC_Path pcIn;
PC_Path [FETCH_WIDTH-1 : 0] tagReg;
PC_Path [FETCH_WIDTH-1 : 0] nextTagReg;
logic pushBtbQueue, popBtbQueue;
logic full, empty;
BTBQueueEntry btbQueue[BTB_QUEUE_SIZE];
BTBQueuePointerPath headPtr, tailPtr;
logic updateBtb;
generate
BlockMultiBankRAM #(
.ENTRY_NUM( BTB_ENTRY_NUM ),
.ENTRY_BIT_SIZE( $bits( BTB_Entry ) ),
.READ_NUM( FETCH_WIDTH ),
.WRITE_NUM( INT_ISSUE_WIDTH )
)
btbEntryArray(
.clk(port.clk),
.we(btbWE),
.wa(btbWA),
.wv(btbWV),
.ra(btbRA),
.rv(btbRV)
);
QueuePointer #(
.SIZE( BTB_QUEUE_SIZE )
)
btbQueuePointer(
.clk(port.clk),
.rst(port.rst),
.push(pushBtbQueue),
.pop(popBtbQueue),
.full(full),
.empty(empty),
.headPtr(headPtr),
.tailPtr(tailPtr)
);
endgenerate
// Counter for reset sequence.
BTB_IndexPath resetIndex;
always_ff @(posedge port.clk) begin
if(port.rstStart) begin
resetIndex <= 0;
end
else begin
resetIndex <= resetIndex + 1;
end
if (port.rst) begin
tagReg <= '0;
end
else begin
tagReg <= nextTagReg;
end
end
always_ff @(posedge port.clk) begin
// Push btb Queue
if (port.rst) begin
btbQueue[resetIndex % BTB_QUEUE_SIZE].btbWA <= '0;
btbQueue[resetIndex % BTB_QUEUE_SIZE].btbWV <= '0;
end
else if (pushBtbQueue) begin
btbQueue[headPtr].btbWA <= btbWA[INT_ISSUE_WIDTH-1];
btbQueue[headPtr].btbWV <= btbWV[INT_ISSUE_WIDTH-1];
end
end
always_comb begin
pcIn = port.predNextPC;
// Address inputs for read entry.
for (int i = 0; i < FETCH_WIDTH; i++) begin
btbRA[i] = ToBTB_Index(pcIn + i*INSN_BYTE_WIDTH);
nextTagReg[i] = pcIn + i*INSN_BYTE_WIDTH;
end
// Make logic for using at other module.
for (int i = 0; i < FETCH_WIDTH; i++) begin
btbHit[i] = btbRV[i].valid && (btbRV[i].tag == ToBTB_Tag(tagReg[i]));
btbOut[i] = ToRawAddrFromBTB_Addr(btbRV[i].data, tagReg[i]);
readIsCondBr[i] = btbRV[i].isCondBr;
end
for (int i = 0; i < INT_ISSUE_WIDTH; i++) begin
btbWE[i] = FALSE;
end
updateBtb = FALSE;
pushBtbQueue = FALSE;
// Write to BTB.
for (int i = 0; i < INT_ISSUE_WIDTH; i++) begin
// Make BTB entry when branch is Taken.
if (updateBtb) begin
pushBtbQueue = port.brResult[i].valid && port.brResult[i].execTaken;
end
else begin
btbWE[i] = port.brResult[i].valid && port.brResult[i].execTaken;
updateBtb |= btbWE[i];
end
btbWA[i] = ToBTB_Index(port.brResult[i].brAddr);
btbWV[i].tag = ToBTB_Tag(port.brResult[i].brAddr);
btbWV[i].data = ToBTB_Addr(port.brResult[i].nextAddr);
btbWV[i].valid = TRUE;
btbWV[i].isCondBr = port.brResult[i].isCondBr;
end
// Pop btb Queue
if (!empty && !updateBtb) begin
popBtbQueue = TRUE;
btbWE[0] = TRUE;
btbWA[0] = btbQueue[tailPtr].btbWA;
btbWV[0] = btbQueue[tailPtr].btbWV;
end
else begin
popBtbQueue = FALSE;
end
// In reset sequence, the write port 0 is used for initializing, and
// the other write ports are disabled.
if (port.rst) begin
for (int i = 0; i < INT_ISSUE_WIDTH; i++) begin
btbWE[i] = (i == 0) ? TRUE : FALSE;
btbWA[i] = resetIndex;
btbWV[i].tag = 0;
btbWV[i].data = 0;
btbWV[i].valid = FALSE;
end
// To avoid writing to the same bank (avoid error message)
for (int i = 0; i < FETCH_WIDTH; i++) begin
btbRA[i] = i;
end
pushBtbQueue = FALSE;
popBtbQueue = FALSE;
end
next.readIsCondBr = readIsCondBr;
next.btbOut = btbOut;
next.btbHit = btbHit;
end
endmodule : BTB