提交 bc1445fc 编写于 作者: Y Yinan Xu

ram,axi4: move axi things out of ram.cpp and fix some bugs

上级 ae850398
#include <cassert>
#include <cstdio>
#include <cstring>
#include "axi4.h"
// ar channel: (1) read raddr; (2) try to accept the address; (3) check raddr fire
bool axi_get_raddr(const axi_channel &axi, axi_addr_t &addr) {
if (axi.ar.valid) {
addr = axi.ar.addr;
return true;
}
return false;
}
void axi_accept_raddr(axi_channel &axi) {
axi.ar.ready = 1;
}
bool axi_check_raddr_fire(const axi_channel &axi) {
if (axi.ar.valid && axi.ar.ready) {
#ifdef DEBUG_LOG_AXI4
printf("axi ar channel fired addr = 0x%lx, id = %d\n", axi.ar.addr, axi.ar.id);
#endif
return true;
}
return false;
}
// r channel: (1) put rdata; (2) check rdata fire
void axi_put_rdata(axi_channel &axi, void *src, size_t n, bool last, uint8_t id) {
memcpy(axi.r.data, src, n);
axi.r.valid = 1;
axi.r.last = (last) ? 1 : 0;
axi.r.id = id;
}
bool axi_check_rdata_fire(const axi_channel &axi) {
if (axi.r.ready && axi.r.valid) {
#ifdef DEBUG_LOG_AXI4
printf("axi r channel fired data = %lx, id = %d\n", axi.r.data[0], axi.r.id);
#endif
return true;
}
return false;
}
// aw channel: (1) read waddr; (2) try to accept the address; (3) check waddr fire
bool axi_get_waddr(const axi_channel &axi, axi_addr_t &addr) {
if (axi.aw.valid) {
addr = axi.aw.addr;
return true;
}
return false;
}
void axi_accept_waddr(axi_channel &axi) {
axi.aw.ready = 1;
}
bool axi_check_waddr_fire(const axi_channel &axi) {
if (axi.aw.valid && axi.aw.ready) {
assert(axi.aw.burst == 1 || (axi.aw.burst == 2 && ((axi.aw.addr & 0x3f) == 0)));
#ifdef DEBUG_LOG_AXI4
printf("axi aw channel fired\n");
#endif
return true;
}
return false;
}
// w channel: (1) accept wdata; (2) get wdata; (3) check wdata fire
void axi_accept_wdata(axi_channel &axi) {
axi.w.ready = 1;
}
bool axi_check_wdata_fire(const axi_channel &axi) {
if (axi.w.valid && axi.w.ready) {
#ifdef DEBUG_LOG_AXI4
printf("axi w channel fired\n");
#endif
return true;
}
return false;
}
void axi_get_wdata(const axi_channel &axi, void *dest, size_t n) {
memcpy(dest, axi.w.data, n);
}
// b channel: (1) put response; (2) check response fire
void axi_put_wack(axi_channel &axi, uint8_t id) {
axi.b.valid = 1;
axi.b.id = id;
}
bool axi_check_wack_fire(const axi_channel &axi) {
if (axi.b.valid && axi.b.ready) {
#ifdef DEBUG_LOG_AXI4
printf("axi b channel fired\n");
#endif
return true;
}
return false;
}
#ifndef __AXI4_H
#define __AXI4_h
#include <stdint.h>
// #define DEBUG_LOG_AXI4
// 4*64 bits
#define AXI_DATA_WIDTH_64 4
typedef uint64_t axi_addr_t;
typedef uint64_t axi_data_t[AXI_DATA_WIDTH_64];
#define axi_copy_data(dest, src) \
memcpy(dest, src, sizeof(uint64_t)*AXI_DATA_WIDTH_64);
struct axi_aw_channel {
uint8_t ready;
uint8_t valid;
axi_addr_t addr;
uint8_t prot;
uint8_t id;
uint8_t user;
uint8_t len;
uint8_t size;
uint8_t burst;
uint8_t lock;
uint8_t cache;
uint8_t qos;
};
struct axi_w_channel {
uint8_t ready;
uint8_t valid;
axi_data_t data;
uint8_t strb;
uint8_t last;
};
struct axi_b_channel {
uint8_t ready;
uint8_t valid;
uint8_t resp;
uint8_t id;
uint8_t user;
};
struct axi_ar_channel {
uint8_t ready;
uint8_t valid;
axi_addr_t addr;
uint8_t prot;
uint8_t id;
uint8_t user;
uint8_t len;
uint8_t size;
uint8_t burst;
uint8_t lock;
uint8_t cache;
uint8_t qos;
};
struct axi_r_channel {
uint8_t ready;
uint8_t valid;
uint8_t resp;
axi_data_t data;
uint8_t last;
uint8_t id;
uint8_t user;
};
struct axi_channel {
struct axi_aw_channel aw;
struct axi_w_channel w;
struct axi_b_channel b;
struct axi_ar_channel ar;
struct axi_r_channel r;
};
// dut helper for AXI
// NOTE: change this when migrating between different hardware designs
#define DUT_AXI(name) auto_axi_mem_out_##name
#define axi_aw_copy_from_dut_ptr(dut_ptr, aw) \
do { \
aw.ready = dut_ptr->DUT_AXI(aw_ready); \
aw.valid = dut_ptr->DUT_AXI(aw_valid); \
aw.addr = dut_ptr->DUT_AXI(aw_bits_addr); \
aw.prot = dut_ptr->DUT_AXI(aw_bits_prot); \
aw.id = dut_ptr->DUT_AXI(aw_bits_id); \
aw.len = dut_ptr->DUT_AXI(aw_bits_len); \
aw.size = dut_ptr->DUT_AXI(aw_bits_size); \
aw.burst = dut_ptr->DUT_AXI(aw_bits_burst); \
aw.lock = dut_ptr->DUT_AXI(aw_bits_lock); \
aw.cache = dut_ptr->DUT_AXI(aw_bits_cache); \
aw.qos = dut_ptr->DUT_AXI(aw_bits_qos); \
} while (0);
#define axi_aw_set_dut_ptr(dut_ptr, aw) \
do { \
dut_ptr->DUT_AXI(aw_ready) = aw.ready; \
} while (0);
#define axi_w_copy_from_dut_ptr(dut_ptr, w) \
do { \
w.ready = dut_ptr->DUT_AXI(w_ready); \
w.valid = dut_ptr->DUT_AXI(w_valid); \
axi_copy_data(w.data, dut_ptr->DUT_AXI(w_bits_data)) \
w.strb = dut_ptr->DUT_AXI(w_bits_strb); \
w.last = dut_ptr->DUT_AXI(w_bits_last); \
} while (0);
#define axi_w_set_dut_ptr(dut_ptr, w) \
do { \
dut_ptr->DUT_AXI(w_ready) = w.ready; \
} while (0);
#define axi_b_copy_from_dut_ptr(dut_ptr, b) \
do { \
b.ready = dut_ptr->DUT_AXI(b_ready); \
b.valid = dut_ptr->DUT_AXI(b_valid); \
b.resp = dut_ptr->DUT_AXI(b_bits_resp); \
b.id = dut_ptr->DUT_AXI(b_bits_id); \
} while (0);
#define axi_b_set_dut_ptr(dut_ptr, b) \
do { \
dut_ptr->DUT_AXI(b_valid) = b.valid; \
dut_ptr->DUT_AXI(b_bits_resp) = b.resp; \
dut_ptr->DUT_AXI(b_bits_id) = b.id; \
} while (0);
#define axi_ar_copy_from_dut_ptr(dut_ptr, ar) \
do { \
ar.ready = dut_ptr->DUT_AXI(ar_ready); \
ar.valid = dut_ptr->DUT_AXI(ar_valid); \
ar.addr = dut_ptr->DUT_AXI(ar_bits_addr); \
ar.prot = dut_ptr->DUT_AXI(ar_bits_prot); \
ar.id = dut_ptr->DUT_AXI(ar_bits_id); \
ar.len = dut_ptr->DUT_AXI(ar_bits_len); \
ar.size = dut_ptr->DUT_AXI(ar_bits_size); \
ar.burst = dut_ptr->DUT_AXI(ar_bits_burst); \
ar.lock = dut_ptr->DUT_AXI(ar_bits_lock); \
ar.cache = dut_ptr->DUT_AXI(ar_bits_cache); \
ar.qos = dut_ptr->DUT_AXI(ar_bits_qos); \
} while (0);
#define axi_ar_set_dut_ptr(dut_ptr, ar) \
do { \
dut_ptr->DUT_AXI(ar_ready) = ar.ready; \
} while (0);
#define axi_r_copy_from_dut_ptr(dut_ptr, r) \
do { \
r.ready = dut_ptr->DUT_AXI(r_ready); \
r.valid = dut_ptr->DUT_AXI(r_valid); \
r.resp = dut_ptr->DUT_AXI(r_bits_resp); \
axi_copy_data(r.data, dut_ptr->DUT_AXI(r_bits_data)) \
r.last = dut_ptr->DUT_AXI(r_bits_last); \
r.id = dut_ptr->DUT_AXI(r_bits_id); \
} while (0);
#define axi_r_set_dut_ptr(dut_ptr, r) \
do { \
dut_ptr->DUT_AXI(r_valid) = r.valid; \
dut_ptr->DUT_AXI(r_bits_resp) = r.resp; \
axi_copy_data(dut_ptr->DUT_AXI(r_bits_data), r.data) \
dut_ptr->DUT_AXI(r_bits_last) = r.last; \
dut_ptr->DUT_AXI(r_bits_id) = r.id; \
} while (0);
#define axi_copy_from_dut_ptr(dut_ptr, axi) \
do { \
axi_aw_copy_from_dut_ptr(dut_ptr, axi.aw) \
axi_w_copy_from_dut_ptr(dut_ptr, axi.w) \
axi_b_copy_from_dut_ptr(dut_ptr, axi.b) \
axi_ar_copy_from_dut_ptr(dut_ptr, axi.ar) \
axi_r_copy_from_dut_ptr(dut_ptr, axi.r) \
} while (0);
#define axi_set_dut_ptr(dut_ptr, axi) \
do { \
axi_aw_set_dut_ptr(dut_ptr, axi.aw) \
axi_w_set_dut_ptr(dut_ptr, axi.w) \
axi_b_set_dut_ptr(dut_ptr, axi.b) \
axi_ar_set_dut_ptr(dut_ptr, axi.ar) \
axi_r_set_dut_ptr(dut_ptr, axi.r) \
} while (0);
// ar channel: (1) read raddr; (2) try to accept the address; (3) check raddr fire
bool axi_get_raddr(const axi_channel &axi, axi_addr_t &addr);
void axi_accept_raddr(axi_channel &axi);
bool axi_check_raddr_fire(const axi_channel &axi);
// r channel: (1) put rdata; (2) check rdata fire
void axi_put_rdata(axi_channel &axi, void *src, size_t n, bool last, uint8_t id);
bool axi_check_rdata_fire(const axi_channel &axi);
// aw channel: (1) read waddr; (2) try to accept the address; (3) check waddr fire
bool axi_get_waddr(const axi_channel &axi, axi_addr_t &addr);
void axi_accept_waddr(axi_channel &axi);
bool axi_check_waddr_fire(const axi_channel &axi);
// w channel: (1) accept wdata; (2) get wdata; (3) check wdata fire
void axi_accept_wdata(axi_channel &axi);
void axi_get_wdata(const axi_channel &axi, void *dest, size_t n);
bool axi_check_wdata_fire(const axi_channel &axi);
// b channel: (1) put response; (2) check response fire
void axi_put_wack(axi_channel &axi, uint8_t id);
bool axi_check_wack_fire(const axi_channel &axi);
#endif
......@@ -204,22 +204,27 @@ inline void Emulator::reset_ncycles(size_t cycles) {
inline void Emulator::single_cycle() {
dut_ptr->clock = 0;
dut_ptr->eval();
#ifdef WITH_DRAMSIM3
axi_channel axi;
axi_copy_from_dut_ptr(dut_ptr, axi);
axi.aw.addr -= 0x80000000UL;
axi.ar.addr -= 0x80000000UL;
dramsim3_helper(axi);
axi.aw.addr += 0x80000000UL;
axi.ar.addr += 0x80000000UL;
axi_set_dut_ptr(dut_ptr, axi);
dramsim3_helper_rising(axi);
#endif
dut_ptr->eval();
dut_ptr->clock = 1;
dut_ptr->eval();
#ifdef WITH_DRAMSIM3
axi_copy_from_dut_ptr(dut_ptr, axi);
axi.aw.addr -= 0x80000000UL;
axi.ar.addr -= 0x80000000UL;
dramsim3_helper_falling(axi);
axi_set_dut_ptr(dut_ptr, axi);
#endif
#if VM_TRACE == 1
if (enable_waveform) {
uint64_t cycle = dut_ptr->io_trap_cycleCnt;
......
......@@ -154,7 +154,8 @@ void init_ram(const char *img) {
#error DRAMSIM3_CONFIG or DRAMSIM3_OUTDIR is not defined
#endif
assert(dram == NULL);
dram = new CoDRAMsim3(DRAMSIM3_CONFIG, DRAMSIM3_OUTDIR);
// dram = new CoDRAMsim3(DRAMSIM3_CONFIG, DRAMSIM3_OUTDIR);
dram = new SimpleCoDRAMsim3(90);
#endif
pthread_mutex_init(&ram_mutex, 0);
......@@ -258,6 +259,7 @@ CoDRAMRequest *dramsim3_request(const axi_channel &axi, bool is_write) {
// WRITE
if (is_write) {
meta->len = axi.aw.len + 1;
meta->size = 1 << axi.aw.size;
meta->offset = 0;
meta->id = axi.aw.id;
}
......@@ -271,34 +273,26 @@ CoDRAMRequest *dramsim3_request(const axi_channel &axi, bool is_write) {
return req;
}
void dramsim3_helper(axi_channel &axi) {
static CoDRAMResponse *wait_resp_r = NULL;
static CoDRAMResponse *wait_resp_b = NULL;
static CoDRAMRequest *wait_req_w = NULL;
// currently only accept one in-flight read + one in-flight write
static uint64_t raddr, roffset = 0, rlen;
static uint64_t waddr, woffset = 0, wlen;
void dramsim3_helper_rising(const axi_channel &axi) {
// ticks DRAMsim3 according to CPU_FREQ:DRAM_FREQ
dram->tick();
static CoDRAMResponse *wait_resp_r = NULL;
static CoDRAMResponse *wait_resp_b = NULL;
static CoDRAMRequest *wait_req_w = NULL;
// currently only accept one in-flight read + one in-flight write
static uint64_t raddr, roffset = 0, rlen;
static uint64_t waddr, woffset = 0, wlen;
// default branch to avoid wrong handshake
axi.aw.ready = 0;
axi.w.ready = 1;
axi.b.valid = 0;
axi.ar.ready = 0;
// axi.r.valid = 0;
// AXI read
// first, check rdata in the last cycle
if (axi.r.ready && axi.r.valid) {
// printf("axi r channel fired data = %lx\n", axi.r.data[0]);
// read data fire: check the last read request
if (axi_check_rdata_fire(axi)) {
if (wait_resp_r == NULL) {
printf("ERROR: There's no in-flight read request.\n");
assert(wait_resp_r != NULL);
}
dramsim3_meta *meta = static_cast<dramsim3_meta *>(wait_resp_r->req->meta);
meta->offset++;
axi.r.valid = 0;
}
if (wait_resp_r) {
dramsim3_meta *meta = static_cast<dramsim3_meta *>(wait_resp_r->req->meta);
// check whether the last rdata response has finished
if (meta->offset == meta->len) {
delete meta;
delete wait_resp_r->req;
......@@ -306,68 +300,111 @@ void dramsim3_helper(axi_channel &axi) {
wait_resp_r = NULL;
}
}
// second, check whether we response data in this cycle
if (!wait_resp_r)
wait_resp_r = dram->check_read_response();
if (wait_resp_r) {
dramsim3_meta *meta = static_cast<dramsim3_meta *>(wait_resp_r->req->meta);
// axi.r.data = meta->data[meta->offset];
// printf("meta->size %d offset %d\n", meta->size, meta->offset*meta->size/sizeof(uint64_t));
memcpy(axi.r.data, meta->data + meta->offset*meta->size/sizeof(uint64_t), meta->size);
axi.r.valid = 1;
axi.r.last = (meta->offset == meta->len - 1) ? 1 : 0;
axi.r.id = meta->id;
}
// third, check ar for next request's address
// put ar in the last since it should be at least one-cycle latency
if (axi.ar.valid && dram->will_accept(axi.ar.addr, false)) {
// printf("axi ar channel fired %lx\n", axi.ar.addr);
// read address fire: accept a new request
if (axi_check_raddr_fire(axi)) {
dram->add_request(dramsim3_request(axi, false));
axi.ar.ready = 1;
}
// AXI write
// first, check wdata in the last cycle
// aw channel
if (axi.aw.valid && dram->will_accept(axi.aw.addr, true)) {
assert(wait_req_w == NULL); // the last request has not finished
// the last write transaction is acknowledged
if (axi_check_wack_fire(axi)) {
if (wait_resp_b == NULL) {
printf("ERROR: write response fire for nothing in-flight.\n");
assert(wait_resp_b != NULL);
}
// flush data to memory
uint64_t waddr = wait_resp_b->req->address % EMU_RAM_SIZE;
dramsim3_meta *meta = static_cast<dramsim3_meta *>(wait_resp_b->req->meta);
void *start_addr = ram + (waddr / sizeof(uint64_t));
memcpy(start_addr, meta->data, meta->len * meta->size);
for (int i = 0; i < meta->len; i++) {
// uint64_t address = wait_resp_b->req->address % EMU_RAM_SIZE;
// ram[address / sizeof(uint64_t) + i] = meta->data[i];
// printf("flush write to memory[0x%ld] = 0x%lx\n", address)
}
delete meta;
delete wait_resp_b->req;
delete wait_resp_b;
wait_resp_b = NULL;
}
// write address fire: accept a new write request
if (axi_check_waddr_fire(axi)) {
if (wait_req_w != NULL) {
printf("ERROR: The last write request has not finished.\n");
assert(wait_req_w == NULL);
}
wait_req_w = dramsim3_request(axi, true);
axi.aw.ready = 1;
// printf("axi aw channel fired %lx\n", axi.aw.addr);
assert(axi.aw.burst == 1 || (axi.aw.burst == 2 && ((axi.aw.addr & 0x3f) == 0)));
// printf("accept a new write request to addr = 0x%lx, len = %d\n", axi.aw.addr, axi.aw.len);
}
// w channel: ack write data
if (axi.w.valid && axi.w.ready) {
// printf("axi w channel fired\n");
assert(wait_req_w);
// write data fire: for the last write transaction
if (axi_check_wdata_fire(axi)) {
if (wait_req_w == NULL) {
printf("ERROR: wdata fire for nothing in-flight.\n");
assert(wait_req_w != NULL);
}
dramsim3_meta *meta = static_cast<dramsim3_meta *>(wait_req_w->meta);
// meta->data[meta->offset] = axi.w.data;
void *data_start = meta->data + meta->offset * meta->size / sizeof(uint64_t);
axi_get_wdata(axi, data_start, meta->size);
meta->offset++;
// if this is the last beat
if (meta->offset == meta->len) {
assert(dram->will_accept(wait_req_w->address, true));
dram->add_request(wait_req_w);
wait_req_w = NULL;
}
// printf("accept a new write data\n");
}
}
void dramsim3_helper_falling(axi_channel &axi) {
// default branch to avoid wrong handshake
axi.aw.ready = 0;
axi.w.ready = 0;
axi.b.valid = 0;
axi.ar.ready = 0;
axi.r.valid = 0;
// b channel: ack write
// RDATA: if finished, we try the next rdata response
if (!wait_resp_r)
wait_resp_r = dram->check_read_response();
// if there's some data response, put it onto axi bus
if (wait_resp_r) {
dramsim3_meta *meta = static_cast<dramsim3_meta *>(wait_resp_r->req->meta);
// printf("meta->size %d offset %d\n", meta->size, meta->offset*meta->size/sizeof(uint64_t));
void *data_start = meta->data + meta->offset*meta->size / sizeof(uint64_t);
axi_put_rdata(axi, data_start, meta->size, meta->offset == meta->len - 1, meta->id);
}
// RADDR: check whether the read request can be accepted
axi_addr_t raddr;
if (axi_get_raddr(axi, raddr) && dram->will_accept(raddr, false)) {
axi_accept_raddr(axi);
// printf("try to accept read request to 0x%lx\n", raddr);
}
// WREQ: check whether the write request can be accepted
// Note: block the next write here to simplify logic
axi_addr_t waddr;
if (wait_req_w == NULL && axi_get_waddr(axi, waddr) && dram->will_accept(waddr, false)) {
axi_accept_waddr(axi);
axi_accept_wdata(axi);
// printf("try to accept write request to 0x%lx\n", waddr);
}
// WDATA: check whether the write data can be accepted
if (wait_req_w != NULL) {
axi_accept_wdata(axi);
}
// WRESP: if finished, we try the next write response
if (!wait_resp_b)
wait_resp_b = dram->check_write_response();
// if there's some write response, put it onto axi bus
if (wait_resp_b) {
dramsim3_meta *meta = static_cast<dramsim3_meta *>(wait_resp_b->req->meta);
axi.b.valid = 1;
axi.b.id = meta->id;
// assert(axi.b.ready == 1);
for (int i = 0; i < meta->len; i++) {
uint64_t address = wait_resp_b->req->address % EMU_RAM_SIZE;
ram[address / sizeof(uint64_t) + i] = meta->data[i];
}
// printf("axi b channel fired\n");
delete meta;
delete wait_resp_b->req;
delete wait_resp_b;
wait_resp_b = NULL;
axi_put_wack(axi, meta->id);
}
}
......
......@@ -12,191 +12,11 @@ void* get_ram_start();
long get_ram_size();
#ifdef WITH_DRAMSIM3
// 4*64 bits
#define AXI_DATA_WIDTH_64 4
typedef uint64_t axi_addr_t;
typedef uint64_t axi_data_t[AXI_DATA_WIDTH_64];
#define axi_copy_data(dest, src) \
memcpy(dest, src, sizeof(uint64_t)*AXI_DATA_WIDTH_64);
struct axi_aw_channel {
uint8_t ready;
uint8_t valid;
axi_addr_t addr;
uint8_t prot;
uint8_t id;
uint8_t user;
uint8_t len;
uint8_t size;
uint8_t burst;
uint8_t lock;
uint8_t cache;
uint8_t qos;
};
struct axi_w_channel {
uint8_t ready;
uint8_t valid;
axi_data_t data;
uint8_t strb;
uint8_t last;
};
struct axi_b_channel {
uint8_t ready;
uint8_t valid;
uint8_t resp;
uint8_t id;
uint8_t user;
};
struct axi_ar_channel {
uint8_t ready;
uint8_t valid;
axi_addr_t addr;
uint8_t prot;
uint8_t id;
uint8_t user;
uint8_t len;
uint8_t size;
uint8_t burst;
uint8_t lock;
uint8_t cache;
uint8_t qos;
};
struct axi_r_channel {
uint8_t ready;
uint8_t valid;
uint8_t resp;
axi_data_t data;
uint8_t last;
uint8_t id;
uint8_t user;
};
struct axi_channel {
struct axi_aw_channel aw;
struct axi_w_channel w;
struct axi_b_channel b;
struct axi_ar_channel ar;
struct axi_r_channel r;
};
// dut helper for AXI
// NOTE: change this when migrating between different hardware designs
#define DUT_AXI(name) auto_axi_mem_out_##name
#define axi_aw_copy_from_dut_ptr(dut_ptr, aw) \
do { \
aw.ready = dut_ptr->DUT_AXI(aw_ready); \
aw.valid = dut_ptr->DUT_AXI(aw_valid); \
aw.addr = dut_ptr->DUT_AXI(aw_bits_addr); \
aw.prot = dut_ptr->DUT_AXI(aw_bits_prot); \
aw.id = dut_ptr->DUT_AXI(aw_bits_id); \
aw.len = dut_ptr->DUT_AXI(aw_bits_len); \
aw.size = dut_ptr->DUT_AXI(aw_bits_size); \
aw.burst = dut_ptr->DUT_AXI(aw_bits_burst); \
aw.lock = dut_ptr->DUT_AXI(aw_bits_lock); \
aw.cache = dut_ptr->DUT_AXI(aw_bits_cache); \
aw.qos = dut_ptr->DUT_AXI(aw_bits_qos); \
} while (0);
#define axi_aw_set_dut_ptr(dut_ptr, aw) \
do { \
dut_ptr->DUT_AXI(aw_ready) = aw.ready; \
} while (0);
#define axi_w_copy_from_dut_ptr(dut_ptr, w) \
do { \
w.ready = dut_ptr->DUT_AXI(w_ready); \
w.valid = dut_ptr->DUT_AXI(w_valid); \
axi_copy_data(w.data, dut_ptr->DUT_AXI(w_bits_data)) \
w.strb = dut_ptr->DUT_AXI(w_bits_strb); \
w.last = dut_ptr->DUT_AXI(w_bits_last); \
} while (0);
#define axi_w_set_dut_ptr(dut_ptr, w) \
do { \
dut_ptr->DUT_AXI(w_ready) = w.ready; \
} while (0);
#define axi_b_copy_from_dut_ptr(dut_ptr, b) \
do { \
b.ready = dut_ptr->DUT_AXI(b_valid); \
b.valid = dut_ptr->DUT_AXI(b_valid); \
b.resp = dut_ptr->DUT_AXI(b_bits_resp); \
b.id = dut_ptr->DUT_AXI(b_bits_id); \
} while (0);
#define axi_b_set_dut_ptr(dut_ptr, b) \
do { \
dut_ptr->DUT_AXI(b_valid) = b.valid; \
dut_ptr->DUT_AXI(b_bits_resp) = b.resp; \
dut_ptr->DUT_AXI(b_bits_id) = b.id; \
} while (0);
#define axi_ar_copy_from_dut_ptr(dut_ptr, ar) \
do { \
ar.ready = dut_ptr->DUT_AXI(ar_ready); \
ar.valid = dut_ptr->DUT_AXI(ar_valid); \
ar.addr = dut_ptr->DUT_AXI(ar_bits_addr); \
ar.prot = dut_ptr->DUT_AXI(ar_bits_prot); \
ar.id = dut_ptr->DUT_AXI(ar_bits_id); \
ar.len = dut_ptr->DUT_AXI(ar_bits_len); \
ar.size = dut_ptr->DUT_AXI(ar_bits_size); \
ar.burst = dut_ptr->DUT_AXI(ar_bits_burst); \
ar.lock = dut_ptr->DUT_AXI(ar_bits_lock); \
ar.cache = dut_ptr->DUT_AXI(ar_bits_cache); \
ar.qos = dut_ptr->DUT_AXI(ar_bits_qos); \
} while (0);
#define axi_ar_set_dut_ptr(dut_ptr, ar) \
do { \
dut_ptr->DUT_AXI(ar_ready) = ar.ready; \
} while (0);
#define axi_r_copy_from_dut_ptr(dut_ptr, r) \
do { \
r.ready = dut_ptr->DUT_AXI(r_ready); \
r.valid = dut_ptr->DUT_AXI(r_valid); \
r.resp = dut_ptr->DUT_AXI(r_bits_resp); \
axi_copy_data(r.data, dut_ptr->DUT_AXI(r_bits_data)) \
r.last = dut_ptr->DUT_AXI(r_bits_last); \
r.id = dut_ptr->DUT_AXI(r_bits_id); \
} while (0);
#define axi_r_set_dut_ptr(dut_ptr, r) \
do { \
dut_ptr->DUT_AXI(r_valid) = r.valid; \
dut_ptr->DUT_AXI(r_bits_resp) = r.resp; \
axi_copy_data(dut_ptr->DUT_AXI(r_bits_data), r.data) \
dut_ptr->DUT_AXI(r_bits_last) = r.last; \
dut_ptr->DUT_AXI(r_bits_id) = r.id; \
} while (0);
#define axi_copy_from_dut_ptr(dut_ptr, axi) \
do { \
axi_aw_copy_from_dut_ptr(dut_ptr, axi.aw) \
axi_w_copy_from_dut_ptr(dut_ptr, axi.w) \
axi_b_copy_from_dut_ptr(dut_ptr, axi.b) \
axi_ar_copy_from_dut_ptr(dut_ptr, axi.ar) \
axi_r_copy_from_dut_ptr(dut_ptr, axi.r) \
} while (0);
#define axi_set_dut_ptr(dut_ptr, axi) \
do { \
axi_aw_set_dut_ptr(dut_ptr, axi.aw) \
axi_w_set_dut_ptr(dut_ptr, axi.w) \
axi_b_set_dut_ptr(dut_ptr, axi.b) \
axi_ar_set_dut_ptr(dut_ptr, axi.ar) \
axi_r_set_dut_ptr(dut_ptr, axi.r) \
} while (0);
#include "axi4.h"
void dramsim3_finish();
void dramsim3_helper(struct axi_channel &axi);
void dramsim3_helper_rising(const struct axi_channel &axi);
void dramsim3_helper_falling(struct axi_channel &axi);
#endif
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册