
4 changed files with 307 additions and 174 deletions
@ -1,173 +0,0 @@
@@ -1,173 +0,0 @@
|
||||
// simple verilator top |
||||
// uses a2owb with sim mem interface |
||||
|
||||
#define TRACING |
||||
|
||||
#include <cstddef> |
||||
#include <iostream> |
||||
#include <iomanip> |
||||
|
||||
#include "verilated.h" |
||||
#include "Vc.h" |
||||
|
||||
#ifdef TRACING |
||||
#include "verilated_vcd_c.h" |
||||
VerilatedVcdC *t; |
||||
#else |
||||
unsigned int t = 0; |
||||
#endif |
||||
|
||||
/* |
||||
#include "uart/uartsim.h" |
||||
*/ |
||||
|
||||
Vc* m; |
||||
|
||||
vluint64_t main_time = 0; // in units of timeprecision used in verilog or --timescale-override |
||||
// what is it? it changed to 941621251 after calling loadmem() |
||||
|
||||
double sc_time_stamp() { // $time in verilog |
||||
return main_time; |
||||
} |
||||
|
||||
const int resetCycle = 10; |
||||
const int threadRunCycle = 200; |
||||
const int runCycles = 1000; |
||||
const int hbCycles = 500; |
||||
const int threads = 1; // needs a more realistic a2l2 data return to work in smt |
||||
|
||||
int mem[16384][4]; // 16K QW |
||||
|
||||
void loadmem(void) { |
||||
int adr; |
||||
mem[0x0000/4] = 0x48000400; |
||||
adr = 0x400/4; |
||||
|
||||
mem[adr++] = threads == 1 ? 0x38200001 : 0x38200003; |
||||
mem[adr++] = 0x7C366BA6; |
||||
mem[adr++] = 0x7C366BA6; |
||||
mem[adr++] = 0x7C3E6AA6; |
||||
mem[adr++] = 0x4C00012C; |
||||
mem[adr++] = 0x2C010000; |
||||
mem[adr++] = 0x38200660; |
||||
mem[adr++] = 0x41820008; |
||||
mem[adr++] = 0x38210100; |
||||
mem[adr++] = 0x7C2903A6; |
||||
mem[adr++] = 0x4E800420; |
||||
|
||||
} |
||||
|
||||
// nclk = (clk,reset,clk2x,clk4x,-,-) |
||||
|
||||
int main(int argc, char **argv) { |
||||
using namespace std; |
||||
|
||||
loadmem(); |
||||
|
||||
cout << setfill('0'); |
||||
|
||||
Verilated::commandArgs(argc, argv); |
||||
m = new Vc; |
||||
|
||||
#ifdef TRACING |
||||
Verilated::traceEverOn(true); |
||||
t = new VerilatedVcdC; |
||||
m->trace(t, 99); |
||||
t->open("wtf.vcd"); |
||||
cout << "Tracing enabled." << endl; |
||||
#endif |
||||
|
||||
bool resetDone = false; |
||||
unsigned int threadStop = 0x3; |
||||
|
||||
unsigned int tick = 0; |
||||
unsigned int cycle = 1; |
||||
unsigned int readPending = 0; |
||||
unsigned int readAddr = 0; |
||||
unsigned int readTag = 0; |
||||
unsigned int readTID = 0; |
||||
unsigned int countReads = 0; |
||||
|
||||
m->nclk = 0x3C; // run 2x,4x = 1x |
||||
cout << setw(8) << cycle << "Resetting..." << endl; |
||||
|
||||
m->an_ac_pm_thread_stop = threadStop; |
||||
cout << setw(8) << cycle << "Thread stop=" << threadStop << endl; |
||||
|
||||
// can skip 4x with new gpr array |
||||
// 1x=4/4 2x=2/2 4x=1/1 |
||||
// 1 1 1 7 |
||||
// 1 1 0 6 |
||||
// 1 0 1 5 |
||||
// 1 0 0 4 |
||||
// 0 1 1 3 |
||||
// 0 1 0 2 |
||||
// 0 0 1 1 |
||||
// 0 0 0 0 |
||||
// (insert reset) |
||||
//const int clocks[8] = {11, 0, 11, 0, 11, 0, 11, 0}; // 2x,4x == 1x |
||||
//const int clocks[8] = {11, 10, 9, 8, 3, 2, 1, 0}; // 1x, 2x, 4x |
||||
//const int ticks1x = 8; |
||||
const int clocks[4] = {10, 8, 2, 0}; // 1x, 2x |
||||
const int ticks1x = 4; |
||||
|
||||
while (!Verilated::gotFinish()) { |
||||
|
||||
if (!resetDone && (cycle > resetCycle)) { |
||||
m->nclk &= 0x2F; |
||||
cout << setw(8) << cycle << "Releasing reset." << endl; |
||||
resetDone = true; |
||||
} |
||||
|
||||
if (threadStop && (cycle > threadRunCycle)) { |
||||
threadStop = 0x0; |
||||
m->an_ac_pm_thread_stop = threadStop; |
||||
cout << setw(8) << cycle << "Thread stop=" << threadStop << endl; |
||||
} |
||||
|
||||
m->nclk = (m->nclk & 0x10) | (clocks[tick % 8] << 2); |
||||
tick++; |
||||
m->eval(); |
||||
|
||||
// bus is 1x clock |
||||
if ((tick % ticks1x) == 0) { |
||||
|
||||
/* |
||||
cout << setw(8) << cycle << " an_ac_rsp: data="<< hex << uppercase << setw(8) << m->an_ac_reld_data[3] |
||||
<< hex << uppercase << setw(8) << m->an_ac_reld_data[2] |
||||
<< hex << uppercase << setw(8) << m->an_ac_reld_data[1] |
||||
<< hex << uppercase << setw(8) << m->an_ac_reld_data[0] |
||||
<< dec << nouppercase << endl; |
||||
*/ |
||||
|
||||
} |
||||
|
||||
// finish clock stuff |
||||
if ((tick % ticks1x) == 0) { |
||||
cycle++; |
||||
if ((cycle % hbCycles) == 0) { |
||||
cout << setw(8) << cycle << " ...tick..." << endl; |
||||
} |
||||
} |
||||
#ifdef TRACING |
||||
t->dump(tick); |
||||
t->flush(); |
||||
#endif |
||||
|
||||
// check for fails |
||||
|
||||
// hit limit |
||||
if (cycle > runCycles) { |
||||
break; |
||||
} |
||||
|
||||
} |
||||
|
||||
#ifdef TRACING |
||||
t->close(); |
||||
#endif |
||||
m->final(); |
||||
|
||||
exit(EXIT_SUCCESS); |
||||
|
||||
} |
@ -0,0 +1,305 @@
@@ -0,0 +1,305 @@
|
||||
// simple verilator top |
||||
// uses a2owb with sim mem interface |
||||
|
||||
#define TRACING |
||||
|
||||
#include <cstddef> |
||||
#include <iostream> |
||||
#include <fstream> |
||||
#include <iomanip> |
||||
|
||||
#include "verilated.h" |
||||
#include "Va2owb.h" |
||||
|
||||
// internal nets |
||||
#include "Va2owb___024root.h" |
||||
#include "Va2owb_a2owb.h" |
||||
#include "Va2owb_a2l2wb.h" |
||||
|
||||
#ifdef TRACING |
||||
#include "verilated_vcd_c.h" |
||||
VerilatedVcdC *t; |
||||
#else |
||||
unsigned int t = 0; |
||||
#endif |
||||
|
||||
/* |
||||
#include "uart/uartsim.h" |
||||
*/ |
||||
|
||||
Va2owb* m; |
||||
|
||||
vluint64_t main_time = 0; // in units of timeprecision used in verilog or --timescale-override |
||||
// what is it? it changed to 941621251 after calling loadmem() |
||||
|
||||
double sc_time_stamp() { // $time in verilog |
||||
return main_time; |
||||
} |
||||
|
||||
const int resetCycle = 10; |
||||
const int threadRunCycle = 25; |
||||
const int runCycles = 500; |
||||
const int hbCycles = 500; |
||||
const int threads = 1; |
||||
|
||||
// Cythonize this and use it for cocotb too... |
||||
|
||||
class Memory { |
||||
std::unordered_map<unsigned int, unsigned int> mem; |
||||
public: |
||||
bool le; |
||||
bool logStores; |
||||
int defaultVal; |
||||
Memory(); |
||||
void loadFile(std::string filename, unsigned int adr=0, bool le=false, std::string format="ascii"); |
||||
int read(unsigned int adr); |
||||
void write(unsigned int adr, unsigned int dat); |
||||
void write(unsigned int adr, unsigned int be, unsigned int dat); |
||||
}; |
||||
|
||||
Memory::Memory() { |
||||
|
||||
this->defaultVal = 0; |
||||
this->le = false; |
||||
this->logStores = true; |
||||
|
||||
} |
||||
|
||||
void Memory::loadFile(std::string filename, unsigned int adr, bool le, std::string format) { |
||||
|
||||
unsigned int dat; |
||||
std::ifstream f; |
||||
f.open(filename, std::fstream::in); |
||||
// "ascii" |
||||
//while (f.peek()!=EOF) { |
||||
//f >> std::hex >> dat; |
||||
// f >> dat; |
||||
while (f >> std::hex >> dat) { |
||||
this->write(adr, dat); |
||||
adr += 4; |
||||
} |
||||
|
||||
} |
||||
|
||||
// adr is word-aligned byte address |
||||
int Memory::read(unsigned int adr) { |
||||
if (this->mem.find(adr) != this->mem.end()) { |
||||
return this->mem[adr]; |
||||
} else { |
||||
return this->defaultVal; |
||||
} |
||||
} |
||||
|
||||
// adr is word-aligned byte address |
||||
void Memory::write(unsigned int adr, unsigned int dat) { |
||||
unsigned int startDat = this->read(adr); |
||||
this->mem[adr] = dat; |
||||
if (this->logStores) { |
||||
std::cout << std::setw(8) << std::hex << " * Mem Update @" << adr << " " << startDat << "->" << dat << std::endl; |
||||
} |
||||
} |
||||
|
||||
void Memory::write(unsigned int adr, unsigned int be, unsigned int dat) { |
||||
if (be == 0) return; |
||||
|
||||
int mask, startDat; |
||||
if (be >= 8) { |
||||
be = be - 8; |
||||
mask = 0xFF000000; |
||||
} else { |
||||
mask = 0; |
||||
} |
||||
if (be >= 4) { |
||||
be = be - 4; |
||||
mask |= 0x00FF0000; |
||||
} |
||||
if (be >= 2) { |
||||
be = be - 2; |
||||
mask |= 0x0000FF00; |
||||
} |
||||
if (be = 1) { |
||||
mask |= 0x000000FF; |
||||
} |
||||
|
||||
startDat = this->read(adr); |
||||
this->mem[adr] = (startDat & ~mask) | (dat & mask); |
||||
if (this->logStores) { |
||||
std::cout << std::setw(8) << std::hex << " * Mem Update @" << adr << " " << startDat << "->" << dat << std::endl; |
||||
} |
||||
|
||||
} |
||||
|
||||
Memory mem; |
||||
|
||||
int main(int argc, char **argv) { |
||||
using namespace std; |
||||
|
||||
cout << setfill('0'); |
||||
|
||||
Verilated::commandArgs(argc, argv); |
||||
m = new Va2owb; |
||||
|
||||
#ifdef TRACING |
||||
Verilated::traceEverOn(true); |
||||
t = new VerilatedVcdC; |
||||
m->trace(t, 99); |
||||
t->open("a2onode.vcd"); |
||||
cout << "Tracing enabled." << endl; |
||||
#endif |
||||
|
||||
bool resetDone = false; |
||||
unsigned int threadStop = 0x3; |
||||
|
||||
unsigned int tick = 0; |
||||
unsigned int cycle = 1; |
||||
unsigned int readPending = 0; |
||||
unsigned int readAddr = 0; |
||||
unsigned int readTag = 0; |
||||
unsigned int readTID = 0; |
||||
unsigned int countReads = 0; |
||||
|
||||
//unsigned int iu0Comp = m->rootp->a2owb->c0->iu_lq_i0_completed; |
||||
//unsigned int iu0Comp = m->rootp->a2owb__DOT__c0__DOT__lq0__DOT__lsq__DOT__odq__DOT__iu_lq_i0_completed_itag_int; |
||||
/* |
||||
iu0CompIFAR = sim.a2o.root.iuq0.iuq_cpl_top0.iuq_cpl0.cp2_i0_ifar |
||||
iu1Comp = sim.a2o.root.iu_lq_i1_completed |
||||
iu1CompIFAR = sim.a2o.root.iuq0.iuq_cpl_top0.iuq_cpl0.cp2_i1_ifar |
||||
iuCompFlushIFAR = sim.a2o.root.cp_t0_flush_ifar |
||||
cp3NIA = sim.a2o.root.iuq0.iuq_cpl_top0.iuq_cpl0.iuq_cpl_ctrl.cp3_nia_q # nia after last cycle's completions |
||||
*/ |
||||
|
||||
mem.write(0xFFFFFFFC, 0x48000002); |
||||
mem.loadFile("../mem/test3/rom.init"); |
||||
|
||||
m->nclk = 0x38; |
||||
cout << setw(8) << cycle << "Resetting..." << endl; |
||||
|
||||
m->an_ac_pm_thread_stop = threadStop; |
||||
cout << setw(8) << cycle << "Thread stop=" << threadStop << endl; |
||||
|
||||
const int clocks[4] = {0xA, 0x8, 0x2, 0x0}; // 1x, 2x |
||||
const int ticks1x = 4; |
||||
//const int clocks[8] = {11, 10, 9, 8, 3, 2, 1, 0}; // 1x, 2x, 4x |
||||
//const int ticks1x = 8; |
||||
|
||||
while (!Verilated::gotFinish()) { |
||||
|
||||
if (!resetDone && (cycle > resetCycle)) { |
||||
m->nclk &= 0x2F; |
||||
cout << setw(8) << cycle << "Releasing reset." << endl; |
||||
resetDone = true; |
||||
} |
||||
|
||||
if (threadStop && (cycle > threadRunCycle)) { |
||||
threadStop = 0x0; |
||||
m->an_ac_pm_thread_stop = threadStop; |
||||
cout << setw(8) << cycle << "Thread stop=" << threadStop << endl; |
||||
} |
||||
|
||||
m->nclk = (m->nclk & 0x10) | (clocks[tick % ticks1x] << 2); |
||||
tick++; |
||||
m->eval(); |
||||
|
||||
// bus is 1x clock |
||||
if ((tick % ticks1x) == 0) { |
||||
|
||||
/* |
||||
cout << setw(8) << cycle << " an_ac_rsp: data="<< hex << uppercase << setw(8) << m->an_ac_reld_data[3] |
||||
<< hex << uppercase << setw(8) << m->an_ac_reld_data[2] |
||||
<< hex << uppercase << setw(8) << m->an_ac_reld_data[1] |
||||
<< hex << uppercase << setw(8) << m->an_ac_reld_data[0] |
||||
<< dec << nouppercase << endl; |
||||
*/ |
||||
|
||||
/* 16B BE read/write interface and sparse mem |
||||
|
||||
[0:31] mem_adr |
||||
[0:127] mem_dat |
||||
mem_wr_val |
||||
[0:15] mem_wr_be |
||||
[0:127] mem_wr_dat |
||||
|
||||
|
||||
addr = dut.mem_adr.value.integer |
||||
w0 = sim.mem.read(addr) |
||||
w1 = sim.mem.read(addr+4) |
||||
w2 = sim.mem.read(addr+8) |
||||
w3 = sim.mem.read(addr+12) |
||||
v = cocotb.binary.BinaryValue() |
||||
v.assign(f'{w0:0>32b}{w1:0>32b}{w2:0>32b}{w3:0>32b}') |
||||
dut.mem_dat.value = v.value |
||||
|
||||
if dut.mem_wr_val.value: |
||||
addr = dut.mem_adr.value.integer |
||||
dat = hex(dut.mem_wr_dat, 32) |
||||
be = f'{dut.mem_wr_be.value.integer:016b}' |
||||
for i in range(4): |
||||
sim.mem.write(addr, dat[i*8:i*8+8], be[i*4:i*4+4]) |
||||
addr += 4 |
||||
*/ |
||||
// update read dat |
||||
unsigned int adr = m->mem_adr; |
||||
m->mem_dat[3] = mem.read(adr); |
||||
adr += 4; |
||||
m->mem_dat[2] = mem.read(adr); |
||||
adr += 4; |
||||
m->mem_dat[1] = mem.read(adr); |
||||
adr += 4; |
||||
m->mem_dat[0] = mem.read(adr); |
||||
|
||||
// update mem[] if write |
||||
unsigned int mem_we = m->mem_wr_val; |
||||
unsigned int mem_be = m->mem_wr_be; |
||||
//unsigned int mem_datw[8] = m->mem_wr_dat; |
||||
|
||||
// check can access - ok |
||||
//m->rootp->a2owb->ac_an_req = 1; |
||||
//m->rootp->a2owb->ac_an_req = 0; |
||||
//m->rootp->a2owb->n0->cmdseq_q = 0; |
||||
/* |
||||
if (m->ac_an_req) { |
||||
readAddr = m->ac_an_req_ra; |
||||
readTag = m->ac_an_req_ld_core_tag; |
||||
readTID = m->ac_an_req_thread; |
||||
readPending = cycle + 3; |
||||
cout << setw(8) << cycle << " ac_an_req: T" << readTID << " ra=" << hex << uppercase << setw(8) << readAddr << dec << nouppercase << endl; |
||||
m->an_ac_req_ld_pop = 1; |
||||
} |
||||
*/ |
||||
|
||||
} |
||||
|
||||
if (m->rootp->a2owb->ac_an_req == 1) { |
||||
cout << dec << setw(8) << cycle << "A2L2 Req RA=" << hex << m->rootp->a2owb->ac_an_ra << endl; |
||||
} |
||||
) |
||||
|
||||
// finish clock stuff |
||||
if ((tick % ticks1x) == 0) { |
||||
cycle++; |
||||
if ((cycle % hbCycles) == 0) { |
||||
cout << dec << setw(8) << cycle << " ...tick..." << endl; |
||||
} |
||||
} |
||||
#ifdef TRACING |
||||
t->dump(tick); |
||||
t->flush(); |
||||
#endif |
||||
|
||||
// check for fails |
||||
|
||||
// hit limit |
||||
if (cycle > runCycles) { |
||||
break; |
||||
} |
||||
|
||||
} |
||||
|
||||
#ifdef TRACING |
||||
t->close(); |
||||
#endif |
||||
m->final(); |
||||
|
||||
exit(EXIT_SUCCESS); |
||||
|
||||
} |
Loading…
Reference in new issue