356 lines
11 KiB
C++
356 lines
11 KiB
C++
// C++ libraries
|
|
#include <utility>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <iterator>
|
|
#include <iomanip>
|
|
#include <fstream>
|
|
#include <unistd.h>
|
|
#include <vector>
|
|
#include <math.h>
|
|
#include <algorithm>
|
|
|
|
#include "VX_define.h"
|
|
#include "VVX_d_cache_encapsulate.h"
|
|
#include "verilated.h"
|
|
|
|
#include "d_cache_test_bench_debug.h"
|
|
|
|
|
|
#ifdef VCD_OUTPUT
|
|
#include <verilated_vcd_c.h>
|
|
#endif
|
|
|
|
// void set_Index (auto & var, int index, int size, auto val)
|
|
// {
|
|
// int real_shift
|
|
// }
|
|
|
|
class VX_d_cache
|
|
{
|
|
public:
|
|
VX_d_cache();
|
|
~VX_d_cache();
|
|
bool simulate();
|
|
bool operation(int, bool);
|
|
|
|
VVX_d_cache_encapsulate * vx_d_cache_;
|
|
long int curr_cycle;
|
|
int stats_total_cycles = 0;
|
|
int stats_dram_accesses = 0;
|
|
#ifdef VCD_OUTPUT
|
|
VerilatedVcdC *m_trace;
|
|
#endif
|
|
};
|
|
|
|
|
|
|
|
VX_d_cache::VX_d_cache() : curr_cycle(0), stats_total_cycles(0), stats_dram_accesses(0)
|
|
{
|
|
|
|
this->vx_d_cache_ = new VVX_d_cache_encapsulate;
|
|
#ifdef VCD_OUTPUT
|
|
this->m_trace = new VerilatedVcdC;
|
|
this->vx_d_cache_->trace(m_trace, 99);
|
|
this->m_trace->open("trace.vcd");
|
|
#endif
|
|
//this->results.open("../results.txt");
|
|
}
|
|
|
|
VX_d_cache::~VX_d_cache()
|
|
{
|
|
|
|
|
|
delete this->vx_d_cache_;
|
|
#ifdef VCD_OUTPUT
|
|
m_trace->close();
|
|
#endif
|
|
}
|
|
|
|
bool VX_d_cache::operation(int counter_value, bool do_op) {
|
|
if (do_op) {
|
|
vx_d_cache_->i_p_initial_request = 1;
|
|
} else {
|
|
vx_d_cache_->i_p_initial_request = 0;
|
|
}
|
|
|
|
if (counter_value == 0 && do_op) { // Write to bank 1-4 at index 64
|
|
vx_d_cache_->i_p_initial_request = 1;
|
|
vx_d_cache_->i_p_read_or_write = 1;
|
|
vx_d_cache_->i_m_ready = 0;
|
|
for (int j = 0; j < NT; j++) {
|
|
vx_d_cache_->i_p_valid[j] = 1;
|
|
vx_d_cache_->i_p_writedata[j] = 0x7f6f8f6f;
|
|
vx_d_cache_->i_m_readdata[j][0] = 1;
|
|
if (j == 0) {
|
|
vx_d_cache_->i_p_addr[0] = 0x30001004; // bank 1
|
|
} else if (j == 1) {
|
|
vx_d_cache_->i_p_addr[1] = 0x30001008; // bank 2
|
|
} else if (j == 2) {
|
|
vx_d_cache_->i_p_addr[2] = 0x3000100c; // bank 3
|
|
} else {
|
|
vx_d_cache_->i_p_addr[3] = 0x30010010; // bank 4 -- This is serviced 1st, then the other 3 banks are at once
|
|
}
|
|
}
|
|
|
|
} else if (counter_value == 1 && do_op) { // Write to bank 4-7 at index 108
|
|
vx_d_cache_->i_p_initial_request = 1;
|
|
vx_d_cache_->i_p_read_or_write = 1;
|
|
vx_d_cache_->i_m_ready = 0;
|
|
for (int j = 0; j < NT; j++) {
|
|
vx_d_cache_->i_p_valid[j] = 1;
|
|
vx_d_cache_->i_p_writedata[j] = 0xd1d2d2d3;
|
|
vx_d_cache_->i_m_readdata[j][0] = 1;
|
|
if (j == 0) {
|
|
vx_d_cache_->i_p_addr[0] = 0x30001c14; // bank 5
|
|
} else if (j == 1) {
|
|
vx_d_cache_->i_p_addr[1] = 0x30001c18; // bank 6
|
|
} else if (j == 2) {
|
|
vx_d_cache_->i_p_addr[2] = 0x30001c1c; // bank 7
|
|
} else {
|
|
vx_d_cache_->i_p_addr[3] = 0x30001c10; // bank 4
|
|
}
|
|
}
|
|
|
|
} else if (counter_value == 2 && do_op) { // Read from bank 1-4 at those indexes
|
|
for (int j = 0; j < NT; j++) {
|
|
vx_d_cache_->i_p_initial_request = 1;
|
|
vx_d_cache_->i_p_read_or_write = 0;
|
|
vx_d_cache_->i_m_ready = 0;
|
|
for (int j = 0; j < NT; j++) {
|
|
vx_d_cache_->i_p_valid[j] = 1;
|
|
vx_d_cache_->i_p_writedata[j] = 0x23232332;
|
|
vx_d_cache_->i_m_readdata[j][0] = 1;
|
|
if (j == 0) {
|
|
vx_d_cache_->i_p_addr[0] = 0x30001004; // bank 1
|
|
} else if (j == 1) {
|
|
vx_d_cache_->i_p_addr[1] = 0x30001c18; // bank 5
|
|
} else if (j == 2) {
|
|
vx_d_cache_->i_p_addr[2] = 0x3000100c; // bank 3
|
|
} else {
|
|
vx_d_cache_->i_p_addr[3] = 0x30001c1c;; // bank 7
|
|
}
|
|
}
|
|
}
|
|
} else if (counter_value == 3 && do_op) { // Write to Bank 1-5 (evictions will need to take place)
|
|
vx_d_cache_->i_p_initial_request = 1;
|
|
vx_d_cache_->i_p_read_or_write = 1;
|
|
vx_d_cache_->i_m_ready = 0;
|
|
for (int j = 0; j < NT; j++) {
|
|
vx_d_cache_->i_p_valid[j] = 1;
|
|
vx_d_cache_->i_m_readdata[j][0] = 1;
|
|
if (j == 0) {
|
|
vx_d_cache_->i_p_addr[0] = 0x20001004; // bank 1
|
|
vx_d_cache_->i_p_writedata[j] = 0xaaaabbb0;
|
|
} else if (j == 1) {
|
|
vx_d_cache_->i_p_addr[1] = 0x20001008; // bank 2
|
|
vx_d_cache_->i_p_writedata[j] = 0xaaaabbb1;
|
|
} else if (j == 2) {
|
|
vx_d_cache_->i_p_addr[2] = 0x2000100c; // bank 3
|
|
vx_d_cache_->i_p_writedata[j] = 0xaaaabbb2;
|
|
} else {
|
|
vx_d_cache_->i_p_addr[3] = 0x20001c14; // bank 5
|
|
vx_d_cache_->i_p_writedata[j] = 0xaaaabbb3;
|
|
}
|
|
}
|
|
} else if (counter_value == 4 && do_op) { // Read from addresses that were just overwritten above ^^^
|
|
vx_d_cache_->i_p_initial_request = 1;
|
|
vx_d_cache_->i_p_read_or_write = 0;
|
|
vx_d_cache_->i_m_ready = 0;
|
|
for (int j = 0; j < NT; j++) {
|
|
vx_d_cache_->i_p_valid[j] = 1;
|
|
vx_d_cache_->i_p_writedata[j] = 0x23232332;
|
|
vx_d_cache_->i_m_readdata[j][0] = 1;
|
|
if (j == 0) {
|
|
vx_d_cache_->i_p_addr[0] = 0x20001004; // bank 1
|
|
} else if (j == 1) {
|
|
vx_d_cache_->i_p_addr[1] = 0x20001008; // bank 2
|
|
} else if (j == 2) {
|
|
vx_d_cache_->i_p_addr[2] = 0x2000100c; // bank 3
|
|
} else {
|
|
vx_d_cache_->i_p_addr[3] = 0x20001c14; // bank 5
|
|
}
|
|
}
|
|
}
|
|
/* These will check writing multiple threads writing to the same block
|
|
} else if (counter_value == 3 && do_op) { // Write to Bank 0
|
|
vx_d_cache_->i_p_initial_request = 1;
|
|
vx_d_cache_->i_p_read_or_write = 1;
|
|
vx_d_cache_->i_m_ready = 0;
|
|
for (int j = 0; j < NT; j++) {
|
|
vx_d_cache_->i_p_valid[j] = 1;
|
|
vx_d_cache_->i_m_readdata[j][0] = 1;
|
|
if (j == 0) {
|
|
vx_d_cache_->i_p_addr[0] = 0x30001f00; // bank 0
|
|
vx_d_cache_->i_p_writedata[j] = 0xaaaabbb0;
|
|
} else if (j == 1) {
|
|
vx_d_cache_->i_p_addr[1] = 0x30001c00; // bank 0
|
|
vx_d_cache_->i_p_writedata[j] = 0xaaaabbb1;
|
|
} else if (j == 2) {
|
|
vx_d_cache_->i_p_addr[2] = 0x30001a00; // bank 0
|
|
vx_d_cache_->i_p_writedata[j] = 0xaaaabbb2;
|
|
} else {
|
|
vx_d_cache_->i_p_addr[3] = 0x30001904; // bank 1
|
|
vx_d_cache_->i_p_writedata[j] = 0xaaaabbb3;
|
|
}
|
|
}
|
|
} else if (counter_value == 4 && do_op) { // Read from Bank 0
|
|
vx_d_cache_->i_p_initial_request = 1;
|
|
vx_d_cache_->i_p_read_or_write = 0;
|
|
vx_d_cache_->i_m_ready = 0;
|
|
for (int j = 0; j < NT; j++) {
|
|
vx_d_cache_->i_p_valid[j] = 1;
|
|
vx_d_cache_->i_p_writedata[j] = 0x23232332;
|
|
vx_d_cache_->i_m_readdata[j][0] = 1;
|
|
if (j == 0) {
|
|
vx_d_cache_->i_p_addr[0] = 0x30001f00; // bank 0
|
|
} else if (j == 1) {
|
|
vx_d_cache_->i_p_addr[1] = 0x30001c00; // bank 0
|
|
} else if (j == 2) {
|
|
vx_d_cache_->i_p_addr[2] = 0x30001a00; // bank 0
|
|
} else {
|
|
vx_d_cache_->i_p_addr[3] = 0x30001904; // bank 1
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
// Handle Memory Accesses
|
|
unsigned int read_data_from_mem = 0x1111 + counter_value + this->stats_total_cycles;
|
|
|
|
if (vx_d_cache_->o_m_valid) {
|
|
this->stats_dram_accesses = this->stats_dram_accesses + 1; // (assuming memory access takes 20 cycles)
|
|
|
|
this->stats_total_cycles += 1;
|
|
vx_d_cache_->clk = 0;
|
|
vx_d_cache_->eval();
|
|
#ifdef VCD_OUTPUT
|
|
m_trace->dump(2*this->stats_total_cycles);
|
|
#endif
|
|
vx_d_cache_->clk = 1;
|
|
vx_d_cache_->eval();
|
|
#ifdef VCD_OUTPUT
|
|
m_trace->dump((2*this->stats_total_cycles)+1);
|
|
#endif
|
|
|
|
vx_d_cache_->i_m_ready = 1;
|
|
for (int j1 = 0; j1 < 8; j1++) {
|
|
for (int j2 = 0; j2 < 4; j2++) {
|
|
vx_d_cache_->i_m_readdata[j1][j2] = read_data_from_mem;
|
|
}
|
|
}
|
|
} else {
|
|
vx_d_cache_->i_m_ready = 0;
|
|
}
|
|
|
|
|
|
if (vx_d_cache_->o_p_waitrequest == 0) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
bool VX_d_cache::simulate()
|
|
{
|
|
|
|
// this->instruction_file_name = file_to_simulate;
|
|
// this->results << "\n****************\t" << file_to_simulate << "\t****************\n";
|
|
|
|
// this->ProcessFile();
|
|
|
|
// auto start_time = std::chrono::high_resolution_clock::now();
|
|
|
|
|
|
//static bool stop = false;
|
|
//static int counter = 0;
|
|
//counter = 0;
|
|
//stop = false;
|
|
|
|
// auto start_time = clock();
|
|
|
|
|
|
vx_d_cache_->clk = 0;
|
|
vx_d_cache_->rst = 1;
|
|
//vortex->eval();
|
|
//counter = 0;
|
|
vx_d_cache_->rst = 0;
|
|
|
|
bool cont = false;
|
|
bool out_operation = false;
|
|
bool do_operation = true;
|
|
int other_counter = 0;
|
|
//while (this->stop && ((other_counter < 5)))
|
|
while (other_counter < 5)
|
|
{
|
|
|
|
// std::cout << "************* Cycle: " << (this->stats_total_cycles) << "\n";
|
|
// istop = ibus_driver();
|
|
// dstop = !dbus_driver();
|
|
|
|
vx_d_cache_->clk = 1;
|
|
vx_d_cache_->eval();
|
|
#ifdef VCD_OUTPUT
|
|
m_trace->dump(2*this->stats_total_cycles);
|
|
#endif
|
|
|
|
//vortex->eval();
|
|
//dstop = !dbus_driver();
|
|
|
|
out_operation = operation(other_counter, do_operation);
|
|
vx_d_cache_->clk = 0;
|
|
vx_d_cache_->eval();
|
|
#ifdef VCD_OUTPUT
|
|
m_trace->dump((2*this->stats_total_cycles)+1);
|
|
#endif
|
|
//vortex->eval();
|
|
|
|
/*
|
|
// stop = istop && dstop;
|
|
stop = vortex->out_ebreak;
|
|
if (stop || cont)
|
|
{
|
|
cont = true;
|
|
counter++;
|
|
} else
|
|
{
|
|
counter = 0;
|
|
}
|
|
*/
|
|
if (out_operation) {
|
|
other_counter++;
|
|
do_operation = true;
|
|
} else {
|
|
do_operation = false;
|
|
}
|
|
++(this->stats_total_cycles);
|
|
|
|
if (this->stats_total_cycles > 5000) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
std::cerr << "New Total Cycles: " << (this->stats_total_cycles + (this->stats_dram_accesses * 20)) << "\n";
|
|
|
|
//uint32_t status;
|
|
//ram.getWord(0, &status);
|
|
|
|
//this->print_stats();
|
|
|
|
|
|
|
|
return (true);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|