1
0

add FPGA test bench

The memory models now support back pressure on the response.
This commit is contained in:
Andrew Waterman
2013-05-02 04:58:43 -07:00
parent d2e1828714
commit cfa86dba4f
11 changed files with 87 additions and 72 deletions

View File

@ -60,17 +60,18 @@ int main(int argc, char** argv)
fprintf(vcdfile, "$upscope $end\n");
}
mm_t* mm = dramsim2 ? (mm_t*)(new mm_dramsim2_t) : (mm_t*)(new mm_magic_t);
mm->init(MEM_SIZE);
if (loadmem)
load_mem(mm->get_data(), loadmem);
// The chisel generated code
Top_t tile;
srand(random_seed);
tile.init(random_seed != 0);
// Instantiate and initialize main memory
mm_t* mm = dramsim2 ? (mm_t*)(new mm_dramsim2_t) : (mm_t*)(new mm_magic_t);
mm->init(MEM_SIZE, tile.Top__io_mem_resp_bits_data.width()/8, LINE_SIZE);
if (loadmem)
load_mem(mm->get_data(), loadmem);
// Instantiate HTIF
htif = new htif_emulator_t(std::vector<std::string>(argv + 1, argv + argc));
int htif_bits = tile.Top__io_host_in_bits.width();
@ -105,7 +106,9 @@ int main(int argc, char** argv)
tile.Top__io_mem_req_cmd_bits_tag.lo_word(),
tile.Top__io_mem_req_data_valid.lo_word(),
&tile.Top__io_mem_req_data_bits_data.values[0]
&tile.Top__io_mem_req_data_bits_data.values[0],
tile.Top__io_mem_resp_ready.to_bool()
);
if (tile.Top__io_host_clk_edge.to_bool())

View File

@ -5,8 +5,11 @@
#include <cstring>
#include <cassert>
void mm_t::init(size_t sz)
void mm_t::init(size_t sz, int wsz, int lsz)
{
assert(wsz > 0 && lsz > 0 && (lsz & (lsz-1)) == 0 && lsz % wsz == 0);
word_size = wsz;
line_size = lsz;
data = new char[sz];
size = sz;
}
@ -16,10 +19,10 @@ mm_t::~mm_t()
delete [] data;
}
void mm_magic_t::init(size_t sz)
void mm_magic_t::init(size_t sz, int wsz, int lsz)
{
mm_t::init(sz);
dummy_data.resize(MM_WORD_SIZE);
mm_t::init(sz, wsz, lsz);
dummy_data.resize(word_size);
}
void mm_magic_t::tick
@ -29,28 +32,30 @@ void mm_magic_t::tick
uint64_t req_cmd_addr,
uint64_t req_cmd_tag,
bool req_data_val,
void* req_data_bits
void* req_data_bits,
bool resp_rdy
)
{
bool req_cmd_fire = req_cmd_val && req_cmd_ready();
bool req_data_fire = req_data_val && req_data_ready();
bool resp_fire = resp_valid() && resp_rdy;
assert(!(req_cmd_fire && req_data_fire));
if (resp_valid())
if (resp_fire)
resp.pop();
if (req_data_fire)
{
memcpy(data + store_addr + store_count*MM_WORD_SIZE, req_data_bits, MM_WORD_SIZE);
memcpy(data + store_addr + store_count*word_size, req_data_bits, word_size);
store_count = (store_count + 1) % REFILL_COUNT;
store_count = (store_count + 1) % (line_size/word_size);
if (store_count == 0)
store_inflight = false;
}
if (req_cmd_fire)
{
auto byte_addr = req_cmd_addr*REFILL_COUNT*MM_WORD_SIZE;
auto byte_addr = req_cmd_addr * line_size;
assert(byte_addr < size);
if (req_cmd_store)
@ -58,10 +63,10 @@ void mm_magic_t::tick
store_inflight = true;
store_addr = byte_addr;
}
else for (int i = 0; i < REFILL_COUNT; i++)
else for (int i = 0; i < line_size/word_size; i++)
{
auto base = data + byte_addr + i*MM_WORD_SIZE;
auto dat = std::vector<char>(base, base + MM_WORD_SIZE);
auto base = data + byte_addr + i*word_size;
auto dat = std::vector<char>(base, base + word_size);
resp.push(std::make_pair(req_cmd_tag, dat));
}
}

View File

@ -1,17 +1,19 @@
#ifndef MM_EMULATOR_H
#define MM_EMULATOR_H
#include "mm_param.h"
#include <stdint.h>
#include <cstring>
#include <queue>
const int LINE_SIZE = 64; // all cores assume this.
const size_t MEM_SIZE = (sizeof(long) > 4 ? 4L : 1L) * 1024*1024*1024;
class mm_t
{
public:
mm_t() : data(0), size(0) {}
virtual void init(size_t sz);
virtual void init(size_t sz, int word_size, int line_size);
virtual bool req_cmd_ready() = 0;
virtual bool req_data_ready() = 0;
@ -26,17 +28,22 @@ class mm_t
uint64_t req_cmd_addr,
uint64_t req_cmd_tag,
bool req_data_val,
void* req_data_bits
void* req_data_bits,
bool resp_rdy
) = 0;
virtual void* get_data() { return data; }
virtual size_t get_size() { return size; }
virtual size_t get_word_size() { return word_size; }
virtual size_t get_line_size() { return line_size; }
virtual ~mm_t();
protected:
char* data;
size_t size;
int word_size;
int line_size;
};
class mm_magic_t : public mm_t
@ -44,7 +51,7 @@ class mm_magic_t : public mm_t
public:
mm_magic_t() : store_inflight(false), store_count(0) {}
virtual void init(size_t sz);
virtual void init(size_t sz, int word_size, int line_size);
virtual bool req_cmd_ready() { return !store_inflight; }
virtual bool req_data_ready() { return store_inflight; }
@ -59,7 +66,8 @@ class mm_magic_t : public mm_t
uint64_t req_cmd_addr,
uint64_t req_cmd_tag,
bool req_data_val,
void* req_data_bits
void* req_data_bits,
bool resp_rdy
);
protected:

View File

@ -19,10 +19,10 @@ void mm_dramsim2_t::read_complete(unsigned id, uint64_t address, uint64_t clock_
auto tag = req[address];
req.erase(address);
for (int i = 0; i < REFILL_COUNT; i++)
for (int i = 0; i < line_size/word_size; i++)
{
auto base = data + address + i*MM_WORD_SIZE;
auto dat = std::vector<char>(base, base + MM_WORD_SIZE);
auto base = data + address + i*word_size;
auto dat = std::vector<char>(base, base + word_size);
resp.push(std::make_pair(tag, dat));
}
@ -43,10 +43,12 @@ void power_callback(double a, double b, double c, double d)
//fprintf(stderr, "power callback: %0.3f, %0.3f, %0.3f, %0.3f\n",a,b,c,d);
}
void mm_dramsim2_t::init(size_t sz)
void mm_dramsim2_t::init(size_t sz, int wsz, int lsz)
{
mm_t::init(sz);
dummy_data.resize(MM_WORD_SIZE);
assert(lsz == 64); // assumed by dramsim2
mm_t::init(sz, wsz, lsz);
dummy_data.resize(word_size);
assert(size % (1024*1024) == 0);
mem = getMemorySystemInstance("DDR3_micron_64M_8B_x4_sg15.ini", "system.ini", "dramsim2_ini", "results", size/(1024*1024));
@ -67,20 +69,22 @@ void mm_dramsim2_t::tick
uint64_t req_cmd_addr,
uint64_t req_cmd_tag,
bool req_data_val,
void* req_data_bits
void* req_data_bits,
bool resp_rdy
)
{
bool req_cmd_fire = req_cmd_val && req_cmd_ready();
bool req_data_fire = req_data_val && req_data_ready();
bool resp_fire = resp_valid() && resp_rdy;
assert(!(req_cmd_fire && req_data_fire));
if (resp_valid())
if (resp_fire)
resp.pop();
if (req_cmd_fire)
{
// since the I$ can speculatively ask for address that are out of bounds
auto byte_addr = (req_cmd_addr*REFILL_COUNT*MM_WORD_SIZE) % size;
auto byte_addr = (req_cmd_addr * line_size) % size;
if (req_cmd_store)
{
@ -104,9 +108,9 @@ void mm_dramsim2_t::tick
if (req_data_fire)
{
memcpy(data + store_addr + store_count*MM_WORD_SIZE, req_data_bits, MM_WORD_SIZE);
memcpy(data + store_addr + store_count*word_size, req_data_bits, word_size);
store_count = (store_count + 1) % REFILL_COUNT;
store_count = (store_count + 1) % (line_size/word_size);
if (store_count == 0)
{ // last chunch of cache line arrived.
store_inflight = 0;

View File

@ -12,7 +12,7 @@ class mm_dramsim2_t : public mm_t
public:
mm_dramsim2_t() : store_inflight(false), store_count(0) {}
virtual void init(size_t sz);
virtual void init(size_t sz, int word_size, int line_size);
virtual bool req_cmd_ready() { return mem->willAcceptTransaction() && !store_inflight; }
virtual bool req_data_ready() { return mem->willAcceptTransaction() && store_inflight; }
@ -27,7 +27,8 @@ class mm_dramsim2_t : public mm_t
uint64_t req_cmd_addr,
uint64_t req_cmd_tag,
bool req_data_val,
void* req_data_bits
void* req_data_bits,
bool resp_rdy
);

View File

@ -26,23 +26,24 @@ void memory_tick(
vc_handle mem_req_data_bits,
vc_handle mem_resp_val,
vc_handle mem_resp_rdy,
vc_handle mem_resp_tag,
vc_handle mem_resp_data)
{
uint32_t req_data[MM_WORD_SIZE*REFILL_COUNT/sizeof(uint32_t)];
for (size_t i = 0; i < MM_WORD_SIZE*REFILL_COUNT/sizeof(uint32_t); i++)
uint32_t req_data[mm->get_word_size()/sizeof(uint32_t)];
for (size_t i = 0; i < mm->get_word_size()/sizeof(uint32_t); i++)
req_data[i] = vc_4stVectorRef(mem_req_data_bits)[i].d;
vc_putScalar(mem_req_rdy, mm->req_cmd_ready());
vc_putScalar(mem_req_data_rdy, mm->req_data_ready());
vc_putScalar(mem_resp_val, mm->resp_valid());
vec32 d[MM_WORD_SIZE*REFILL_COUNT/sizeof(uint32_t)];
vec32 d[mm->get_word_size()/sizeof(uint32_t)];
d[0].c = 0;
d[0].d = mm->resp_tag();
vc_put4stVector(mem_resp_tag, d);
for (size_t i = 0; i < MM_WORD_SIZE*REFILL_COUNT/sizeof(uint32_t); i++)
for (size_t i = 0; i < mm->get_word_size()/sizeof(uint32_t); i++)
{
d[i].c = 0;
d[i].d = ((uint32_t*)mm->resp_data())[i];
@ -56,22 +57,26 @@ void memory_tick(
vc_4stVectorRef(mem_req_addr)->d,
vc_4stVectorRef(mem_req_tag)->d,
vc_getScalar(mem_req_data_val),
req_data
req_data,
vc_getScalar(mem_resp_rdy)
);
}
void htif_init
(
vc_handle width,
vc_handle htif_width,
vc_handle mem_width,
vc_handle argv,
vc_handle loadmem,
vc_handle dramsim
)
{
int mw = vc_4stVectorRef(mem_width)->d;
mm = vc_getScalar(dramsim) ? (mm_t*)(new mm_dramsim2_t) : (mm_t*)(new mm_magic_t);
mm->init(MEM_SIZE);
assert(mw && (mw & (mw-1)) == 0);
mm->init(MEM_SIZE, mw/8, LINE_SIZE);
vec32* w = vc_4stVectorRef(width);
vec32* w = vc_4stVectorRef(htif_width);
assert(w->d <= 32 && w->d % 8 == 0); // htif_tick assumes data fits in a vec32
htif_bytes = w->d/8;
@ -134,7 +139,8 @@ void htif_tick
vc_put4stVector(htif_in_bits, &bits);
vc_putScalar(htif_in_valid, peek_in_valid);
vc_putScalar(exit, htif->done() ? (htif->exit_code() << 1 | 1) : 0);
bits.d = htif->done() ? (htif->exit_code() << 1 | 1) : 0;
vc_put4stVector(exit, &bits);
}
}