mirror of
https://github.com/vortexgpgpu/vortex.git
synced 2025-04-24 05:47:35 -04:00
320 lines
8.3 KiB
C++
320 lines
8.3 KiB
C++
#include "cachesim.h"
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <bitset>
|
|
|
|
uint64_t timestamp = 0;
|
|
|
|
double sc_time_stamp() {
|
|
return timestamp;
|
|
}
|
|
|
|
CacheSim::CacheSim() {
|
|
// force random values for uninitialized signals
|
|
Verilated::randReset(2);
|
|
|
|
ram_ = nullptr;
|
|
cache_ = new VVX_cache();
|
|
|
|
mem_rsp_active_ = false;
|
|
snp_req_active_ = false;
|
|
|
|
//#ifdef VCD_OUTPUT
|
|
Verilated::traceEverOn(true);
|
|
trace_ = new VerilatedVcdC;
|
|
cache_->trace(trace_, 99);
|
|
trace_->open("trace.vcd");
|
|
//#endif
|
|
}
|
|
|
|
CacheSim::~CacheSim() {
|
|
//#ifdef VCD_OUTPUT
|
|
trace_->close();
|
|
//#endif
|
|
delete cache_;
|
|
//need to delete the req and rsp vectors
|
|
}
|
|
|
|
void CacheSim::attach_ram(RAM* ram) {
|
|
ram_ = ram;
|
|
mem_rsp_vec_.clear();
|
|
}
|
|
|
|
void CacheSim::reset() {
|
|
#ifndef NDEBUG
|
|
std::cout << timestamp << ": [sim] reset()" << std::endl;
|
|
#endif
|
|
|
|
cache_->reset = 1;
|
|
this->step();
|
|
cache_->reset = 0;
|
|
this->step();
|
|
|
|
mem_rsp_vec_.clear();
|
|
//clear req and rsp vecs
|
|
|
|
}
|
|
|
|
void CacheSim::step() {
|
|
//std::cout << timestamp << ": [sim] step()" << std::endl;
|
|
//toggle clock
|
|
cache_->clk = 0;
|
|
this->eval();
|
|
|
|
cache_->clk = 1;
|
|
this->eval();
|
|
|
|
//handle core and memory reqs and rsps
|
|
this->eval_reqs();
|
|
this->eval_rsps();
|
|
this->eval_mem_bus();
|
|
timestamp++;
|
|
}
|
|
|
|
void CacheSim::eval() {
|
|
cache_->eval();
|
|
//#ifdef VCD_OUTPUT
|
|
trace_->dump(timestamp);
|
|
//#endif
|
|
++timestamp;
|
|
}
|
|
|
|
void CacheSim::run(){
|
|
//#ifndef NDEBUG
|
|
|
|
//#endif
|
|
this->step();
|
|
|
|
int valid = 300;
|
|
int stalls = 20 + 10;
|
|
|
|
while (valid > -1) {
|
|
|
|
this->step();
|
|
display_miss();
|
|
if(cache_->core_rsp_valid){
|
|
get_core_rsp();
|
|
}
|
|
|
|
if(!cache_->core_req_valid && !cache_->core_rsp_valid){
|
|
valid--;
|
|
|
|
}
|
|
stalls--;
|
|
if (stalls == 20){
|
|
//stall_mem();
|
|
//send_snoop_req();
|
|
stalls--;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CacheSim::clear_req(){
|
|
cache_->core_req_valid = 0;
|
|
}
|
|
|
|
|
|
void CacheSim::send_req(core_req_t *req){
|
|
core_req_vec_.push(req);
|
|
unsigned int *data = new unsigned int[4];
|
|
core_rsp_vec_.insert(std::pair<unsigned int, unsigned int*>(req->tag, data));
|
|
}
|
|
|
|
bool CacheSim::get_core_req_ready(){
|
|
return cache_->core_req_ready;
|
|
}
|
|
|
|
bool CacheSim::get_core_rsp_ready(){
|
|
return cache_->core_rsp_ready;
|
|
}
|
|
|
|
void CacheSim::eval_reqs(){
|
|
//check to see if cache is accepting reqs
|
|
if(!core_req_vec_.empty() && cache_->core_req_ready){
|
|
core_req_t *req = core_req_vec_.front();
|
|
|
|
cache_->core_req_valid = req->valid;
|
|
cache_->core_req_rw = req->rw;
|
|
cache_->core_req_byteen = req->byteen;
|
|
|
|
cache_->core_req_addr[0] = req->addr[0];
|
|
cache_->core_req_addr[1] = req->addr[1];
|
|
cache_->core_req_addr[2] = req->addr[2];
|
|
cache_->core_req_addr[3] = req->addr[3];
|
|
|
|
cache_->core_req_data[0] = req->data[0];
|
|
cache_->core_req_data[1] = req->data[1];
|
|
cache_->core_req_data[2] = req->data[2];
|
|
cache_->core_req_data[3] = req->data[3];
|
|
|
|
cache_->core_req_tag = req->tag;
|
|
|
|
core_req_vec_.pop();
|
|
|
|
} else {
|
|
clear_req();
|
|
}
|
|
}
|
|
|
|
void CacheSim::eval_rsps(){
|
|
//check to see if a request has been responded to
|
|
if (cache_->core_rsp_valid){
|
|
core_rsp_vec_.at(cache_->core_rsp_tag)[0] = cache_->core_rsp_data[0];
|
|
core_rsp_vec_.at(cache_->core_rsp_tag)[1] = cache_->core_rsp_data[1];
|
|
core_rsp_vec_.at(cache_->core_rsp_tag)[2] = cache_->core_rsp_data[2];
|
|
core_rsp_vec_.at(cache_->core_rsp_tag)[3] = cache_->core_rsp_data[3];
|
|
}
|
|
}
|
|
|
|
void CacheSim::stall_mem(){
|
|
cache_->mem_req_ready = 0;
|
|
}
|
|
|
|
void CacheSim::send_snoop_req(){
|
|
/*cache_->snp_req_valid = 1;
|
|
cache_->snp_req_addr = 0x12222222;
|
|
cache_->snp_req_invalidate = 1;
|
|
cache_->snp_req_tag = 0xff; */
|
|
}
|
|
|
|
void CacheSim::eval_mem_bus() {
|
|
if (ram_ == nullptr) {
|
|
cache_->mem_req_ready = 0;
|
|
return;
|
|
}
|
|
|
|
// schedule memory responses
|
|
int dequeue_index = -1;
|
|
for (int i = 0; i < mem_rsp_vec_.size(); i++) {
|
|
if (mem_rsp_vec_[i].cycles_left > 0) {
|
|
mem_rsp_vec_[i].cycles_left -= 1;
|
|
}
|
|
if ((dequeue_index == -1)
|
|
&& (mem_rsp_vec_[i].cycles_left == 0)) {
|
|
dequeue_index = i;
|
|
}
|
|
}
|
|
|
|
// send memory response
|
|
if (mem_rsp_active_
|
|
&& cache_->mem_rsp_valid
|
|
&& cache_->mem_rsp_ready) {
|
|
mem_rsp_active_ = false;
|
|
}
|
|
if (!mem_rsp_active_) {
|
|
if (dequeue_index != -1) { //time to respond to the request
|
|
cache_->mem_rsp_valid = 1;
|
|
|
|
//copy data from the rsp queue to the cache module
|
|
memcpy((uint8_t*)cache_->mem_rsp_data, mem_rsp_vec_[dequeue_index].data, MEM_BLOCK_SIZE);
|
|
|
|
cache_->mem_rsp_tag = mem_rsp_vec_[dequeue_index].tag;
|
|
free(mem_rsp_vec_[dequeue_index].data); //take data out of the queue
|
|
mem_rsp_vec_.erase(mem_rsp_vec_.begin() + dequeue_index);
|
|
mem_rsp_active_ = true;
|
|
} else {
|
|
cache_->mem_rsp_valid = 0;
|
|
}
|
|
}
|
|
|
|
// handle memory stalls
|
|
bool mem_stalled = false;
|
|
#ifdef ENABLE_MEM_STALLS
|
|
if (0 == ((timestamp/2) % MEM_STALLS_MODULO)) {
|
|
mem_stalled = true;
|
|
} else
|
|
if (mem_rsp_vec_.size() >= MEM_RQ_SIZE) {
|
|
mem_stalled = true;
|
|
}
|
|
#endif
|
|
|
|
// process memory requests
|
|
if (!mem_stalled) {
|
|
if (cache_->mem_req_valid) {
|
|
if (cache_->mem_req_rw) { //write = 1
|
|
uint64_t byteen = cache_->mem_req_byteen;
|
|
unsigned base_addr = (cache_->mem_req_addr * MEM_BLOCK_SIZE);
|
|
uint8_t* data = (uint8_t*)(cache_->mem_req_data);
|
|
for (int i = 0; i < MEM_BLOCK_SIZE; i++) {
|
|
if ((byteen >> i) & 0x1) {
|
|
(*ram_)[base_addr + i] = data[i];
|
|
}
|
|
}
|
|
} else {
|
|
mem_req_t mem_req;
|
|
mem_req.cycles_left = MEM_LATENCY;
|
|
mem_req.data = (uint8_t*)malloc(MEM_BLOCK_SIZE);
|
|
mem_req.tag = cache_->mem_req_tag;
|
|
ram_->read(cache_->mem_req_addr * MEM_BLOCK_SIZE, MEM_BLOCK_SIZE, mem_req.data);
|
|
mem_rsp_vec_.push_back(mem_req);
|
|
}
|
|
}
|
|
}
|
|
|
|
cache_->mem_req_ready = ~mem_stalled;
|
|
}
|
|
|
|
bool CacheSim::assert_equal(unsigned int* data, unsigned int tag){
|
|
int check = 0;
|
|
unsigned int *rsp = core_rsp_vec_.at(tag);
|
|
for (int i = 0; i < 4; ++i){
|
|
for (int j = 0; j < 4; ++j){
|
|
if (data[i] == rsp[j]){
|
|
check++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return check;
|
|
|
|
}
|
|
|
|
//DEBUG
|
|
|
|
void CacheSim::display_miss(){
|
|
//int i = (unsigned int)cache_->miss_vec;
|
|
//std::bitset<8> x(i);
|
|
//if (i) std::cout << "Miss Vec " << x << std::endl;
|
|
//std::cout << "Miss Vec 0" << cache_->miss_vec[0] << std::endl;
|
|
}
|
|
|
|
void CacheSim::get_core_req(unsigned int (&rsp)[4]){
|
|
rsp[0] = cache_->core_rsp_data[0];
|
|
rsp[1] = cache_->core_rsp_data[1];
|
|
rsp[2] = cache_->core_rsp_data[2];
|
|
rsp[3] = cache_->core_rsp_data[3];
|
|
|
|
//std::cout << std::hex << "core_rsp_valid: " << cache_->core_rsp_valid << std::endl;
|
|
//std::cout << std::hex << "core_rsp_data: " << cache_->core_rsp_data << std::endl;
|
|
//std::cout << std::hex << "core_rsp_tag: " << cache_->core_rsp_tag << std::endl;
|
|
}
|
|
|
|
void CacheSim::get_core_rsp(){
|
|
//std::cout << cache_->genblk5_BRA_0_KET_->bank->is_fill_in_pipe<< std::endl;
|
|
char check = cache_->core_rsp_valid;
|
|
std::cout << std::hex << "core_rsp_valid: " << (unsigned int) check << std::endl;
|
|
std::cout << std::hex << "core_rsp_data[0]: " << cache_->core_rsp_data[0] << std::endl;
|
|
std::cout << std::hex << "core_rsp_data[1]: " << cache_->core_rsp_data[1] << std::endl;
|
|
std::cout << std::hex << "core_rsp_data[2]: " << cache_->core_rsp_data[2] << std::endl;
|
|
std::cout << std::hex << "core_rsp_data[3]: " << cache_->core_rsp_data[3] << std::endl;
|
|
std::cout << std::hex << "core_rsp_tag: " << cache_->core_rsp_tag << std::endl;
|
|
}
|
|
|
|
void CacheSim::get_mem_req(){
|
|
std::cout << std::hex << "mem_req_valid: " << cache_->mem_req_valid << std::endl;
|
|
std::cout << std::hex << "mem_req_rw: " << cache_->mem_req_rw << std::endl;
|
|
std::cout << std::hex << "mem_req_byteen: " << cache_->mem_req_byteen << std::endl;
|
|
std::cout << std::hex << "mem_req_addr: " << cache_->mem_req_addr << std::endl;
|
|
std::cout << std::hex << "mem_req_data: " << cache_->mem_req_data << std::endl;
|
|
std::cout << std::hex << "mem_req_tag: " << cache_->mem_req_tag << std::endl;
|
|
}
|
|
|
|
void CacheSim::get_mem_rsp(){
|
|
std::cout << std::hex << "mem_rsp_valid: " << cache_->mem_rsp_valid << std::endl;
|
|
std::cout << std::hex << "mem_rsp_data: " << cache_->mem_rsp_data << std::endl;
|
|
std::cout << std::hex << "mem_rsp_tag: " << cache_->mem_rsp_tag << std::endl;
|
|
std::cout << std::hex << "mem_rsp_ready: " << cache_->mem_rsp_ready << std::endl;
|
|
}
|
|
|