diff --git a/core/BPTypes.hpp b/core/BPTypes.hpp index a9945f43..e9642982 100644 --- a/core/BPTypes.hpp +++ b/core/BPTypes.hpp @@ -24,4 +24,10 @@ namespace olympia uint64_t correctedPC; }; + enum class branchType { + CONDITIONAL_BRANCH, + JMP, + RET + }; + } \ No newline at end of file diff --git a/core/BPU.cpp b/core/BPU.cpp index 21b704a9..cbfc9c41 100644 --- a/core/BPU.cpp +++ b/core/BPU.cpp @@ -7,7 +7,8 @@ namespace olympia { BPU::name = "bpu"; BPU::BPU(sparta::TreeNode* node, BPUParameterSet* p) : - sparta::Unit(node) + sparta::Unit(node), + ghr_size_(p->ghr_size) { in_fetch_prediction_credits_.createConsumerHandler( @@ -24,6 +25,16 @@ namespace olympia void BPU::recievePredictionInput(PredictionInput) { std::cout << "hello" << std::endl; } + + void BPU::updateGHRTaken() { + ghr_ = ghr_ << 1; + ghr_ = ghr_ | 0b1; + } + + void BPU::updateGHRNotTaken() { + ghr_ = ghr_ << 1; + ghr_ = ghr_ & 0b0; + } } diff --git a/core/BPU.hpp b/core/BPU.hpp index 61fd8fc6..814e8962 100644 --- a/core/BPU.hpp +++ b/core/BPU.hpp @@ -12,8 +12,6 @@ #include namespace olympia -{ -namespace BPU { class BPU : public sparta::Unit { @@ -24,6 +22,8 @@ namespace BPU BPUParameterSet(sparta::TreeNode* n) : sparta::ParameterSet(n) {} // Parameters for the Branch Prediction Unit + PARAMETER(uint32_t, ghr_size, 1024, "Number of history bits in GHR"); + }; static const char name[]; @@ -33,6 +33,16 @@ namespace BPU void receivePredictionCredits_(uint32_t); void recievePredictionInput(PredictionInput); + // update GHR when last branch is taken + void updateGHRTaken(); + // update GHR when last branch is not taken + void updateGHRNotTaken(); + + // Number of history bits in GHR + uint32_t ghr_size_; + + // Global History Register(GHR) + uint32_t ghr_ = 0;; // input ports // verify cycle delay required @@ -65,5 +75,4 @@ namespace BPU "misprediction/total_prediction", getStatisticSet(), "pred_req_num/mispred_num"}; }; -} } \ No newline at end of file diff --git a/core/BasePredictor.cpp b/core/BasePredictor.cpp index 846125ac..5fcc307a 100644 --- a/core/BasePredictor.cpp +++ b/core/BasePredictor.cpp @@ -1,35 +1,41 @@ -// -// Created by shobhit on 12/1/24. -// - #include "BasePredictor.hpp" namespace olympia { -// PHT +// Pattern History Table void PatternHistoryTable::incrementCounter(uint32_t idx) { - if(pattern_history_table_[idx] == ctr_bits_val_) { + if(pattern_history_table_.at(idx) == ctr_bits_val_) { return; } else { - pattern_history_table_[idx]++; + pattern_history_table_.at(idx)++; } } void PatternHistoryTable::decrementCounter(uint32_t idx) { - if(pattern_history_table_[idx] == 0) { + if(pattern_history_table_.at(idx) == 0) { return; } else { - pattern_history_table_[idx]--; + pattern_history_table_.at(idx)--; } } uint8_t PatternHistoryTable::getPrediction(uint32_t idx) { - return pattern_history_table_[idx]; + return pattern_history_table_.at(idx); +} + +// Branch Target Buffer +bool BranchTargetBuffer::isHit(uint64_t PC) { + if(branch_target_buffer_.count(PC)) { + return true; + } + else { + return false; + } } -// BTB + uint64_t BranchTargetBuffer::getPredictedPC(uint64_t PC) { if(branch_target_buffer_.count(PC)) { return branch_target_buffer_[PC]; @@ -60,7 +66,7 @@ bool BranchTargetBuffer::removeEntry(uint64_t PC) { } } -// RAS +// Return Address Stack bool ReturnAddressStack::pushAddress(uint64_t address) { if(return_address_stack_.size() == ras_size_) { return false; @@ -83,28 +89,32 @@ uint64_t ReturnAddressStack::popAddress() { } // BasePredictor -void BasePredictor::handlePredictionReq() { - return; +void BasePredictor::handlePredictionReq(PredictionInput predIn) { + if(predIn.instType == branchType.JMP) { + handleJMP(predIn); + } + else if(predIn.instType == branchType.RET || + predIn.instType == branchType.CONDITIONAL_BRANCH) { + // make prediction + // event to send prediction to fetch + } } -PredictionOutput BasePredictor::makePrediction(PredictionInput predInput) { - - PredictionOutput predOutput; +void BasePredictor::handleJMP(PredictionInput predInput) { + // push PC to RAS + returnAddressStack.pushAddress(predInput.PC); - // branch instruction - if(predInput.instType == 1) { - predOutput.predDirection = false; - predOutput.predPC = 5; + // PC hit on BTB? + if(branchTargetBuffer.isHit(predInput.PC)) { + // event to send PC } - // call instructions - //else if(predInput.instType == 2) { - // in this case no prediction is made, only data is stored for future reference - //} - // ret instruction - else if(predInput.instType == 3) { - predOutput.predDirection = true; - predOutput.predPC = returnAddressStack.popAddress(); + else { + // allocate entry in BTB } - return predOutput; + } + +void BasePredictor::handleRET(PredictionInput predInput); +void BasePredictor::handleBRANCH(PredictionInput predInput); + } diff --git a/core/BasePredictor.hpp b/core/BasePredictor.hpp index b27dcbae..28e56fa4 100644 --- a/core/BasePredictor.hpp +++ b/core/BasePredictor.hpp @@ -1,5 +1,8 @@ #pragma once +#include +#include "BPTypes.hpp" + namespace olympia { class PatternHistoryTable @@ -21,7 +24,7 @@ namespace olympia const uint8_t ctr_bits_; const uint8_t ctr_bits_val_; - uint8_t pattern_history_table_[pht_size_]; + std::map pattern_history_table_; }; @@ -30,13 +33,14 @@ namespace olympia public: BranchTargetBuffer(uint32_t btb_size) : btb_size_(btb_size) {} + bool isHit(uint64_t PC); uint64_t getPredictedPC(uint64_t PC); bool addEntry(uint64_t PC, uint64_t targetPC); bool removeEntry(uint64_t PC); private: const uint32_t btb_size_; - std::map branch_target_buffer_; // define size of this map too + std::map branch_target_buffer_; }; class ReturnAddressStack @@ -58,15 +62,21 @@ namespace olympia { public: BasePredictor(uint32_t pht_size, uint8_t ctr_bits, - uint32_t btb_size, uint32_t ras_size) - { - PatternHistoryTable patternHistoryTable(pht_size, ctr_bits); - BranchTargetBuffer branchTargetBuffer(btb_size); - ReturnAddressStack returnAddressStack(ras_size); - } + uint32_t btb_size, uint32_t ras_size) : + patternHistoryTable(pht_size, ctr_bits), + branchTargetBuffer(bht_size), + returnAddressStack(ras_size); + {} + + PatternHistoryTable patternHistoryTable; + BranchTargetBuffer branchTargetBuffer; + ReturnAddressStack returnAddressStack; void receivedPredictionReq(); PredictionOutput makePrediction(PredictionInput predInput); + void handleJMP(PredictionInput predInput); + void handleRET(PredictionInput predInput); + void handleBRANCH(PredictionInput predInput); }; }