Skip to content

Commit

Permalink
bpu testbench structure
Browse files Browse the repository at this point in the history
  • Loading branch information
dragon540 committed Dec 16, 2024
1 parent f217cd7 commit 04d9778
Show file tree
Hide file tree
Showing 10 changed files with 433 additions and 13 deletions.
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ add_subdirectory(core/lsu)
add_subdirectory(core/issue_queue)
add_subdirectory(core/icache)
add_subdirectory(core/branch_pred)
add_subdirectory(core/bpu)
add_subdirectory(core/dcache)
add_subdirectory(core/vector)
add_subdirectory(fusion)
33 changes: 33 additions & 0 deletions test/core/bpu/BPTypes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

namespace olympia
{
class PredictionInput
{
public:
uint64_t PC;
uint8_t instType;
};

class PredictionOutput
{
public:
bool predDirection;
uint64_t predPC;
};

class UpdateInput
{
public:
uint64_t instrPC;
bool correctedDirection;
uint64_t correctedPC;
};

enum class branchType {
CONDITIONAL_BRANCH,
JMP,
RET
};

}
115 changes: 102 additions & 13 deletions test/core/bpu/BPU_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,16 @@

#include <string>

TEST_INIT
olympia::InstAllocator inst_allocator(2000, 1000);

class BPUSim : public class sparta::app::Simulation
{
using BPUFactory = sparta::ResourceFactory<olympia::BPU, olympia::BPU::BPUParameterSet>;
public:
BPUSim(sparta::Scheduler *sched) : sparta::app::Simulatiuon("BPUSim", sched)
input_file_(input_file),
test_tap_(getRoot(), "info", output_file)
{}

virtual ~ICacheSim(){
Expand All @@ -19,34 +25,117 @@ class BPUSim : public class sparta::app::Simulation

private:
void buildTree_() override {
continue;
auto rtn = getRoot();

allocators_tn.reset(new olympia::OlympiaAllocators(rtn));

tns_to_delete_.emplace_back(new sparta::ResourceTreeNode(rtn,
olympia::MavisUnit::name, sparta::TreeNode::GROUP_NAME_NONE,
sparta::TreeNode::GROUP_IDX_NONE, "Mavis Unit",
&mavis_fact));

// Create a Source Unit
sparta::ResourceTreeNode* src_unit = new sparta::ResourceTreeNode(
rtn, "src", sparta::TreeNode::GROUP_NAME_NONE, sparta::TreeNode::GROUP_IDX_NONE,
"Source Unit", &source_fact);

tns_to_delete_.emplace_back(src_unit);

auto* src_params = src_unit->getParameterSet();
src_params->getParameter("input_file")->setValueFromString(input_file_);

// Create the device under test
sparta::ResourceTreeNode* dut =
new sparta::ResourceTreeNode(rtn, "dut", sparta::TreeNode::GROUP_NAME_NONE,
sparta::TreeNode::GROUP_IDX_NONE, "DUT", &dut_fact);

tns_to_delete_.emplace_back(dut);

// Create the Sink unit
sparta::ResourceTreeNode* sink =
new sparta::ResourceTreeNode(rtn, "sink", sparta::TreeNode::GROUP_NAME_NONE,
sparta::TreeNode::GROUP_IDX_NONE, "Sink Unit", &sink_fact);

tns_to_delete_.emplace_back(sink);

auto* sink_params = sink->getParameterSet();
sink_params->getParameter("purpose")->setValueFromString("grp");
}

void configureTree_() override {};

void bindTree_() override {
continue;
auto* root_node = getRoot();

// set all ports appropriately
sparta::bind(root_node->getChildAs<sparta::Port>(), root_node->getChildAs<sparta::Port>());

sparta::bind(root_node->getChildAs<sparta::Port>(), root_node->getChildAs<sparta::Port>());

sparta::bind(root_node->getChildAs<sparta::Port>(), root_node->getChildAs<sparta::Port>());

sparta::bind(root_node->getChildAs<sparta::Port>(), root_node->getChildAs<sparta::Port>());

}

std::unique_ptr<olympia::OlympiaAllocators> allocators_tn_;

olympia::MavisFactory mavis_fact;
BPUFactory bpu_fact;

core_test::SrcFactory source_fact;
core_test::SinkFactory sink_fact;

std::vector<unique_ptr<sparta::TreeNode>> tns_to_delete_;
std::vector<sparta::ResourceTreeNode*> exe_units_;

const std::string input_file_;
sparta::log::Tap test_tap_;

};

int main(int argc, char **argv) {
std::string testname;

const char USAGE[] = "Usage:\n\n"
"Testbench options \n"
" [ --input_file ] : json or stf input file\n"
" [ --output_file ] : output file for results checking\n"
" \n"
"Commonly used options \n"
" [-i insts] [-r RUNTIME] [--show-tree] [--show-dag]\n"
" [-p PATTERN VAL] [-c FILENAME]\n"
" [-l PATTERN CATEGORY DEST]\n"
" [-h,--help] <workload [stf trace or JSON]>\n"
"\n";

sparta::app::DefaultValues DEFAULTS;

bool runTest(int argc, char** argv) {
DEFAULTS.auto_summary_default = "off";
std::vector<std::string> datafiles;
std::string input_file;

sparta::app::CommandLineSimulator cls(USAGE, DEFAULTS);
auto & app_opts = cls.getApplicationOptions();
app_opts.add_options()
("testname",
sparta::app::named_value<std::string>("TESTNAME", &testname)->default_value(""),
"Provide a testname to run",
"Test to run");

sparta::app::named_value<vector<string>>("output_file", &datafiles), "Specifies the output file")("input_file",
sparta::app::named_value<string>("INPUT_FILE", &input_file)->default_value(""),
"Provide a JSON or STF instruction stream");

po::positional_options_description & pos_opts = cls.getPositionalOptions();

pos_opts.add("output_file", -1);

int err_code = 0;
if(!cls.parse(argc, argv, err_code)){
sparta_assert(false, "Command line parsing failed"); // Any errors already printed to cerr
}
}

int main(int argc, char **argv) {
if(!runTest(argc, argv)) {
return 1;
}

sparta::Scheduler sched;
BPUSim sim(&sched);
cls.populateSimulation(&sim);
sparta::RootTreeNode* root = sim.getRoot();
REPORT_ERROR;
return (int)ERROR_CODE;
}
42 changes: 42 additions & 0 deletions test/core/bpu/Bpu_unit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "Bpu_unit.hpp"
#include "sparta/utils/LogUtils.hpp"

namespace olympia
{
Bpu_unit::Bpu_unit(sparta::TreeNode* node, const Bpu_unitParameterSet* p) :
sparta::Unit(node),
ghr_size_(p->ghr_size),
pht_size_(p->pht_size),
pht_ctr_bits_(p->pht_ctr_bits)
{
in_bpu_predInput_.registerConsumerHandler(CREATE_SPARTA_HANDLER_WITH_DATA(receivePredictionInput_, PredictionInput));
in_bpu_sinkCredits_.registerConsumerHandler(CREATE_SPARTA_HANDLER_WITH_DATA(receiveSinkCredits_, uint32_t));
in_dut_flush_.registerConsumerHandler(CREATE_SPARTA_HANDLER_WITH_DATA());

sparta::StartupEvent(node, CREATE_SPARTA_HANDLER());
}
// function definitions below
void Bpu_unit::sendInitialCredits_() {
out_src_credits_.send(1);
}
void Bpu_unit::receivePredictionInput_(const PredictionInput & pred_input) {
predInput_buffer_.push_back(pred_input);
}
uint8_t Bpu_unit::predictBranch(int idx) {

}

PredictionOutput genOutput(uint8_t pred) {
PredictionOutput temp;
temp.predDirection = pred;
}

void Bpu_unit::receiveSinkCredits_(const uint32_t & credits) {
sink_credits_ += credits;

// put some mechanism to send prediction output to sink below this
}
void sendPrediction_() {

}
}
74 changes: 74 additions & 0 deletions test/core/bpu/Bpu_unit.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#pragma once

#include "FlushManager.hpp"
#include "InstGroup.hpp"
#include "BPTypes.hpp"

#include "sparta/ports/DataPort.hpp"
#include "sparta/events/UniqueEvent.hpp"
#include "sparta/simulation/Unit.hpp"
#include "sparta/simulation/TreeNode.hpp"
#include "sparta/simulation/ParameterSet.hpp"

#include <vector>
#include <map>

namespace olympia
{
class Bpu_unit : public sparta::Unit
{
public:
class Bpu_unitParameterSet : public sparta::ParameterSet
{
public:
Bpu_unitParameterSet(sparta::TreeNode *n) : sparta::ParameterSet(n)
{}

PARAMETER(uint32_t, ghr_size, 1000, "Size of GHR")
PARAMETER(uint32_t, pht_size, 1024, "Size of PHT")
PARAMETER(uint32_t, pht_ctr_bits, 2, "Counter bits of PHT")
};
Bpu_unit(sparta::TreeNode* node, const Bpu_unitParameterSet* p);

static constexpr char name[] = "Bpu_unit";

private:
// Input port to BPU from source
sparta::DataInPort<PredictionInput> in_bpu_predInput_{&unit_port_set_, "in_bpu_predInput", 1};
// Output port of BPU to send credit to source
sparta::DataOutPort<uint32_t> out_src_credits_{&unit_port_set_, "out_src_credits"};

// output port to sink from BPU
sparta::DataOutPort<PredictionOutput> out_sink_predOutput_{&unit_port_set_, "out_sink_predOutput"};
// input port of BPU to receive credit from sink
sparta::DataInPort<uint32_t> in_bpu_sinkCredits_{&unit_port_set_, "in_bpu_sinkCredits", sparta::SchedulingPhase::Tick, 0};

// for flush
sparta::DataInPort<FlushManager::FlushingCriteria> in_dut_flush_{&unit_port_set_, "in_dut_flush", sparta::SchedulingPhase::Flush, 1};

// TODO: put events here

// send credits from BPU to source
void sendInitialCredits_();
// receive prediction input from source
void receivePredictionInput_(const PredictionInput & pred_input);
// mechanism to make prediction
uint8_t predictBranch(int idx);
// generate prediction output
PredictionOutput genOutput(uint8_t pred);
// receive credits from sink
void receiveSinkCredits_(const uint32_t & credits);
// send prediction output to sink
void sendPrediction_();

uint32_t sink_credits_ = 0;
uint32_t ghr_size_;
uint32_t pht_size_;
uint32_t pht_ctr_bits_;
std::vector<PredictionInput> predInput_buffer_;

std::map<uint32_t idx, uint8_t ctr> pattern_history_table_;


}
}
33 changes: 33 additions & 0 deletions test/core/bpu/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
set(PRJ "Bpu_test")
set(EXE "${PRJ}_exec")

# sanity check
set(TST1, "${PRJ}_test")
#zstf input file
set(TST2, "${PRJ}_stf_test")

# test args
set(STF ./traces/bpu_basic_test.stf)

# configuration
set(CFG config/config.yaml)

project(${PRJ})

add_executable(${EXE} Bpu_test.cpp Bpu_unit.cpp src.cpp sink.cpp)
target_include_directories(${EXE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

target_link_libraries(${EXE} core common_test ${STF_LINK_LIBS} mavis SPARTA::sparta)


file(CREATE_LINK ${SIM_BASE}/mavis/json ${CMAKE_CURRENT_BINARY_DIR}/mavis_isa_files SYMBOLIC)
file(CREATE_LINK ${SIM_BASE}/arches ${CMAKE_CURRENT_BINARY_DIR}/arches SYMBOLIC)
file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/config ${CMAKE_CURRENT_BINARY_DIR}/config SYMBOLIC)
file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/json ${CMAKE_CURRENT_BINARY_DIR}/json SYMBOLIC)
file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/traces ${CMAKE_CURRENT_BINARY_DIR}/traces SYMBOLIC)
file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/expected_output ${CMAKE_CURRENT_BINARY_DIR}/expected_output SYMBOLIC)

sparta_named_test(${TST1} ${EXE} tb.out -c ${CFG})
sparta_named_test(${TST2} ${EXE} tb_stf.out --input_file ${STF} -c ${CFG})


19 changes: 19 additions & 0 deletions test/core/bpu/sink.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "sink.hpp"

namespace olympia
{
sink::sink(sparta::TreeNode* n, const sinkParameterSet* p) :
sparta::Unit(n),
{
// register handle all ports
in_bpu_predOutput_.registerConsumerHandler(CREATE_SPARTA_HANDLER_WITH_DATA(receivePrediction_, PredictionOutput));
}

void sink::sendCreditsToBPU_() {
out_bpu_sinkCredits_.send(1);
}

void sink::receivePrediction_(const PredictionOutput & pred_output) {
pred_output_buffer_.push_back(pred_output);
}
}
Loading

0 comments on commit 04d9778

Please sign in to comment.