Skip to content

Branch Prediction Unit #243

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions core/fetch/BPU.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@

#include "fetch/BPU.hpp"

namespace olympia
{
namespace BranchPredictor
{
const char* BPU::name = "BPU";

BPU::BPU(sparta::TreeNode* node, const BPUParameterSet* p) :
sparta::Unit(node),
ghr_size_(p->ghr_size),
ghr_hash_bits_(p->ghr_hash_bits),
pht_size_(p->pht_size),
ctr_bits_(p->ctr_bits),
btb_size_(p->btb_size),
ras_size_(p->ras_size),
ras_enable_overwrite_(p->ras_enable_overwrite),
tage_bim_table_size_(p->tage_bim_table_size),
tage_bim_ctr_bits_(p->tage_bim_ctr_bits),
tage_tagged_table_num_(p->tage_tagged_table_num),
logical_table_num_(p->logical_table_num),
loop_pred_table_size_(p->loop_pred_table_size),
loop_pred_table_way_(p->loop_pred_table_way),
base_predictor_(pht_size_, ctr_bits_, btb_size_, ras_size_)
{
in_fetch_predictionRequest_.registerConsumerHandler(
CREATE_SPARTA_HANDLER_WITH_DATA(BPU, recievePredictionRequest_, PredictionRequest));

in_fetch_predictionOutput_credits_.registerConsumerHandler(
CREATE_SPARTA_HANDLER_WITH_DATA(BPU, receivePredictionOutputCredits_, uint32_t));
}

PredictionOutput BPU::getPrediction(const PredictionRequest & pred)
{
PredictionOutput output;
output.predDirection_ = true;
output.predPC_ = 0x0220;

return output;
}

void BPU::updatePredictor(const UpdateInput & update) {}

BPU::~BPU() {}

void BPU::sendPredictionRequestCredits_(uint32_t credits)
{
ILOG("Send prediction request credits to Fetch");
out_fetch_predictionRequest_credits_.send(credits);
}

void BPU::sendInitialPredictionRequestCredits_()
{
ILOG("Sending initial prediction request credits to Fetch");
sendPredictionRequestCredits_(1);
}

void BPU::recievePredictionRequest_(const PredictionRequest & predReq)
{
ILOG("Received prediction request from Fetch");
predictionRequestBuffer_.push_back(predReq);
}

// void BPU::recievePredictionUpdate_()
//{}

void BPU::receivePredictionOutputCredits_(const uint32_t & credits)
{
ILOG("Recieve prediction output credits from Fetch");
predictionOutputCredits_ += credits;
}

void BPU::makePrediction_()
{
PredictionOutput output;
output.predDirection_ = true;
output.predPC_ = 100000;
generatedPredictionOutputBuffer_.push_back(output);
}

void BPU::sendPrediction_()
{
if (predictionOutputCredits_ > 0)
{
ILOG("Sending prediction output to fetch");
auto predOutput = generatedPredictionOutputBuffer_.front();
generatedPredictionOutputBuffer_.pop_front();
out_fetch_predictionOutput_.send(predOutput);
predictionOutputCredits_--;
}
}

} // namespace BranchPredictor
} // namespace olympia
215 changes: 215 additions & 0 deletions core/fetch/BPU.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
#pragma once

#include "sparta/ports/DataPort.hpp"
#include "sparta/events/SingleCycleUniqueEvent.hpp"
#include "sparta/simulation/Unit.hpp"
#include "sparta/simulation/TreeNode.hpp"
#include "sparta/simulation/ParameterSet.hpp"
#include "sparta/utils/LogUtils.hpp"

#include "BranchPredIF.hpp"
#include "BasePredictor.hpp"
#include "TAGE_SC_L.hpp"

#include <list>

namespace olympia
{
namespace BranchPredictor
{
class PredictionRequest
{
public:
PredictionRequest() {}

uint64_t PC_;
uint8_t instType_;

friend std::ostream & operator<<(std::ostream & os, const PredictionRequest &)
{
return os;
}
};

class PredictionOutput
{
public:
PredictionOutput() {}

bool predDirection_;
uint64_t predPC_;

friend std::ostream & operator<<(std::ostream & os, const PredictionOutput &)
{
return os;
}
};

class UpdateInput
{
public:
UpdateInput(uint64_t instrPC, bool correctedDirection, uint64_t correctedTargetPC) {}

uint64_t instrPC_;
bool correctedDirection_;
uint64_t correctedTargetPC_;

friend std::ostream & operator<<(std::ostream & os, const UpdateInput &) { return os; }
};

class BPU :
public BranchPredictorIF<PredictionOutput, UpdateInput, PredictionRequest>,
public sparta::Unit
{
public:
class BPUParameterSet : public sparta::ParameterSet
{
public:
BPUParameterSet(sparta::TreeNode* n) : sparta::ParameterSet(n) {}

// TODO: choose default values properly
// currently values were chosen randomly
PARAMETER(uint32_t, ghr_size, 1024, "Number of branch history bits stored in GHR");
PARAMETER(uint32_t, ghr_hash_bits, 4,
"Number of bits from GHR used for hashing with PC, to index PHT")
PARAMETER(uint32_t, pht_size, 1024, "Number of entries stored in PHT")
PARAMETER(uint32_t, ctr_bits, 8,
"Number of bits used by counter in PHT to make prediction")
PARAMETER(uint32_t, btb_size, 512, "Maximum possible number of entries in BTB")
PARAMETER(uint32_t, ras_size, 128, "Maximum possible number of entries in RAS")
PARAMETER(bool, ras_enable_overwrite, true,
"New entries on maximum capacity overwrite")
PARAMETER(uint32_t, tage_bim_table_size, 1024, "Size of TAGE bimodal table")
PARAMETER(uint32_t, tage_bim_ctr_bits, 8,
"Number of bits used by TAGE bimodal table to make prediction")
PARAMETER(uint32_t, tage_tagged_table_num, 6,
"Number of tagged components in TAGE predictor")
PARAMETER(uint32_t, logical_table_num, 8, "Number of logical table in SC")
PARAMETER(uint32_t, loop_pred_table_size, 64,
"Maximum possible entries in loop predictor table")
PARAMETER(uint32_t, loop_pred_table_way, 4, "Way size of loop predictor table")
};

BPU(sparta::TreeNode* node, const BPUParameterSet* p);

PredictionOutput getPrediction(const PredictionRequest &);
void updatePredictor(const UpdateInput &);

~BPU();

//! \brief Name of this resource. Required by sparta::UnitFactory
static const char* name;

private:
void sendPredictionRequestCredits_(uint32_t credits);
void sendInitialPredictionRequestCredits_();
void recievePredictionRequest_(const PredictionRequest & predReq);
// void recievePredictionUpdate_();
void receivePredictionOutputCredits_(const uint32_t & credits);
void makePrediction_();
void sendPrediction_();

uint32_t ghr_size_;
uint32_t ghr_hash_bits_;
uint32_t pht_size_;
uint32_t ctr_bits_;
uint32_t btb_size_;
uint32_t ras_size_;
bool ras_enable_overwrite_;
uint32_t tage_bim_table_size_;
uint32_t tage_bim_ctr_bits_;
uint32_t tage_tagged_table_num_;
uint32_t logical_table_num_;
uint32_t loop_pred_table_size_;
uint32_t loop_pred_table_way_;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide default initializations OR make these const


std::list<PredictionRequest> predictionRequestBuffer_;
std::list<PredictionOutput> generatedPredictionOutputBuffer_;
uint32_t predictionRequestCredits_ = 0;
uint32_t predictionOutputCredits_ = 0;

BasePredictor base_predictor_;

///////////////////////////////////////////////////////////////////////////////
// Ports
///////////////////////////////////////////////////////////////////////////////

// Internal DataInPort from fetch unit for prediction request
sparta::DataInPort<PredictionRequest> in_fetch_predictionRequest_{
&unit_port_set_, "in_fetch_predictionRequest", sparta::SchedulingPhase::Tick, 0};

// Internal DataInPort from fetch unit for credits to indicate
// availabilty of slots for sending prediction output
sparta::DataInPort<uint32_t> in_fetch_predictionOutput_credits_{
&unit_port_set_, "in_fetch_predictionOutput_credits", sparta::SchedulingPhase::Tick,
0};

// TODO

// DataOutPort to fetch unit to send credits to indicate availability
// of slots to receive prediction request
sparta::DataOutPort<uint32_t> out_fetch_predictionRequest_credits_{
&unit_port_set_, "out_fetch_predictionRequest_credits"};

// DataOutPort to fetch unit to send prediction output
sparta::DataOutPort<PredictionOutput> out_fetch_predictionOutput_{
&unit_port_set_, "out_fetch_predictionOutput"};

//////////////////////////////////////////////////////////////////////////////
// Events
//////////////////////////////////////////////////////////////////////////////
/***sparta::PayloadEvent<PredictionOutput> ev_sendPrediction_{
&unit_event_set_, "ev_sendPrediction",
CREATE_SPARTA_HANDLER_WITH_DATA(BPU, sendPrediction_, PredictionOutput)};
***/

//////////////////////////////////////////////////////////////////////////////
// Counters
//////////////////////////////////////////////////////////////////////////////
sparta::Counter pred_req_num_{getStatisticSet(), "pred_req_num",
"Number of prediction requests",
sparta::Counter::COUNT_NORMAL};
sparta::Counter mispred_num_{getStatisticSet(), "mispred_num",
"Number of mis-predictions",
sparta::Counter::COUNT_NORMAL};
sparta::StatisticDef mispred_ratio_{getStatisticSet(), "mispred_ratio",
"Percenatge of mis-prediction", getStatisticSet(),
"mispred_num/pred_req_num"};
sparta::Counter branch_req_num_{getStatisticSet(), "branch_req_num",
"Number of branch requests",
sparta::Counter::COUNT_NORMAL};
sparta::Counter call_req_num_{getStatisticSet(), "call_req_num",
"Number of call requests", sparta::Counter::COUNT_NORMAL};
sparta::Counter return_req_num_{getStatisticSet(), "return_req_num",
"Number of return requests",
sparta::Counter::COUNT_NORMAL};
sparta::Counter pht_req_num_{getStatisticSet(), "pht_req_num",
"Number of requests made to PHT",
sparta::Counter::COUNT_NORMAL};
sparta::Counter pht_hit_num_{getStatisticSet(), "pht_hit_num", "Number of hits on PHT",
sparta::Counter::COUNT_NORMAL};
sparta::Counter pht_miss_num_{getStatisticSet(), "pht_miss_num",
"Number of misses on PHT", sparta::Counter::COUNT_NORMAL};
sparta::StatisticDef pht_mispred_ratio_{getStatisticSet(), "pht_mispred_ratio",
"Percentage of PHT mis-prediction",
getStatisticSet(), "pht_miss_num/pht_req_num"};
sparta::Counter btb_req_num_{getStatisticSet(), "btb_req_num",
"Number of requests to BTB",
sparta::Counter::COUNT_NORMAL};
sparta::Counter btb_hit_num_{getStatisticSet(), "btb_hit_num", "NUmber of BTB hits",
sparta::Counter::COUNT_NORMAL};
sparta::Counter btb_miss_num_{getStatisticSet(), "btb_miss_num", "Number of BTB misses",
sparta::Counter::COUNT_NORMAL};
sparta::StatisticDef btb_hit_rate_{getStatisticSet(), "btb_hit_rate",
"Rate of BTB hits", getStatisticSet(),
"btb_hit_num/btb_req_num"};
sparta::StatisticDef btb_miss_rate_{getStatisticSet(), "btb_miss_rate",
"Rate of BTB misses", getStatisticSet(),
"btb_miss_num/btb_req_num"};
sparta::Counter ras_high_mark_{getStatisticSet(), "ras_high_mark", "RAS high mark",
sparta::Counter::COUNT_NORMAL};
sparta::Counter ras_low_mark_{getStatisticSet(), "ras_low_mark", "RAS low mark",
sparta::Counter::COUNT_NORMAL};
};
} // namespace BranchPredictor
} // namespace olympia
Loading
Loading