use better branch predictor

This commit is contained in:
2024-08-03 01:44:28 +00:00
parent 184417c0fe
commit 6ec3cc24a8

View File

@ -7,6 +7,7 @@
#ifndef CSU_H #ifndef CSU_H
#include <array> #include <array>
#include <functional> #include <functional>
#include <random>
#include <tuple> #include <tuple>
#include "tools.h" #include "tools.h"
namespace ZYM { namespace ZYM {
@ -100,6 +101,10 @@ struct CentralScheduleUnit
std::function<max_size_t(max_size_t)> instruction_fetcher; std::function<max_size_t(max_size_t)> instruction_fetcher;
bool instruction_fetcher_initialized = false; bool instruction_fetcher_initialized = false;
inline uint8_t ReadBit(uint32_t data, int pos) { return (data >> pos) & 1; } inline uint8_t ReadBit(uint32_t data, int pos) { return (data >> pos) & 1; }
long long total_predictions = 0;
long long incorrect_predictions = 0;
const unsigned int RndSeed = std::random_device{}();
std::mt19937 rnd;
inline void WriteBit(uint32_t &data, int pos, uint8_t bit) { inline void WriteBit(uint32_t &data, int pos, uint8_t bit) {
data &= ~(1 << pos); data &= ~(1 << pos);
data |= bit << pos; data |= bit << pos;
@ -202,7 +207,7 @@ struct CentralScheduleUnit
} }
public: public:
CentralScheduleUnit() { ; } CentralScheduleUnit() : rnd(RndSeed) { ; }
void SetInstructionFetcher(std::function<max_size_t(max_size_t)> fetcher) { void SetInstructionFetcher(std::function<max_size_t(max_size_t)> fetcher) {
if (instruction_fetcher_initialized) throw std::runtime_error("Instruction fetcher has been initialized"); if (instruction_fetcher_initialized) throw std::runtime_error("Instruction fetcher has been initialized");
instruction_fetcher = fetcher; instruction_fetcher = fetcher;
@ -263,15 +268,16 @@ struct CentralScheduleUnit
if (static_cast<max_size_t>(record.PC_mismatch_mark) == 1) { if (static_cast<max_size_t>(record.PC_mismatch_mark) == 1) {
force_clear_announcer <= 1; force_clear_announcer <= 1;
DEBUG_CERR << "[warning] csu is announcing rolling back due to PC mismatch" << std::endl; DEBUG_CERR << "[warning] csu is announcing rolling back due to PC mismatch" << std::endl;
incorrect_predictions++;
} }
ROB_next_remain_space++; ROB_next_remain_space++;
if (record.instruction == 0x0ff00513) { if (record.instruction == 0x0ff00513) {
halt_signal <= (0b100000000 | static_cast<max_size_t>(a0)); halt_signal <= (0b100000000 | static_cast<max_size_t>(a0));
DEBUG_CERR << "halting with code " << std::dec << int(halt_signal.peek()) << std::endl; DEBUG_CERR << "halting with code " << std::dec << int(halt_signal.peek()) << std::endl;
} std::cerr << "Total predictions: " << total_predictions << std::endl;
if (record.instruction == 0x1B07A503) { std::cerr << "Incorrect predictions: " << incorrect_predictions << std::endl;
DEBUG_CERR << "judgeResult loaded from memory is " << std::dec std::cerr << "Prediction rate: " << (1.0 - static_cast<double>(incorrect_predictions) / total_predictions)
<< static_cast<max_size_t>(record.resulting_register_value) << std::endl; << std::endl;
} }
} }
} }
@ -409,7 +415,14 @@ struct CentralScheduleUnit
case 0b1100011: case 0b1100011:
// branch // branch
ROB_records[tail].resulting_PC_ready <= 0; ROB_records[tail].resulting_PC_ready <= 0;
ROB_records[tail].resulting_PC <= static_cast<max_size_t>(predicted_PC) + decoded_imm; // just guess if (decoded_imm >> 31) { // this may be a long jump
ROB_records[tail].resulting_PC <= static_cast<max_size_t>(predicted_PC) + decoded_imm; // just guess
} else {
ROB_records[tail].resulting_PC <=
static_cast<max_size_t>(predicted_PC) +
4; // we bet the compiler will make the more possible destination nearer
}
total_predictions++;
break; break;
} }
} else { } else {