// C++ libraries #include #include #include #include #include #include #include #include #include #include #include "VX_define.h" #include "VVX_d_cache_encapsulate.h" #include "verilated.h" #include "d_cache_test_bench_debug.h" #ifdef VCD_OUTPUT #include #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); }