From bc1445fc76c3330ee2f47844c1267db07c953cf8 Mon Sep 17 00:00:00 2001 From: Yinan Xu Date: Tue, 5 Jan 2021 11:34:11 +0800 Subject: [PATCH] ram,axi4: move axi things out of ram.cpp and fix some bugs --- src/test/csrc/axi4.cpp | 109 +++++++++++++++++++++ src/test/csrc/axi4.h | 214 +++++++++++++++++++++++++++++++++++++++++ src/test/csrc/emu.cpp | 17 ++-- src/test/csrc/ram.cpp | 171 +++++++++++++++++++------------- src/test/csrc/ram.h | 186 +---------------------------------- 5 files changed, 441 insertions(+), 256 deletions(-) create mode 100644 src/test/csrc/axi4.cpp create mode 100644 src/test/csrc/axi4.h diff --git a/src/test/csrc/axi4.cpp b/src/test/csrc/axi4.cpp new file mode 100644 index 000000000..4f3dae092 --- /dev/null +++ b/src/test/csrc/axi4.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#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; +} diff --git a/src/test/csrc/axi4.h b/src/test/csrc/axi4.h new file mode 100644 index 000000000..a79aee61b --- /dev/null +++ b/src/test/csrc/axi4.h @@ -0,0 +1,214 @@ +#ifndef __AXI4_H +#define __AXI4_h + +#include + +// #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 diff --git a/src/test/csrc/emu.cpp b/src/test/csrc/emu.cpp index 909adfb5d..5766dce3d 100644 --- a/src/test/csrc/emu.cpp +++ b/src/test/csrc/emu.cpp @@ -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; diff --git a/src/test/csrc/ram.cpp b/src/test/csrc/ram.cpp index b01394fa5..573646c0e 100644 --- a/src/test/csrc/ram.cpp +++ b/src/test/csrc/ram.cpp @@ -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(wait_resp_r->req->meta); meta->offset++; - axi.r.valid = 0; - } - if (wait_resp_r) { - dramsim3_meta *meta = static_cast(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(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(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(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(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(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); } } diff --git a/src/test/csrc/ram.h b/src/test/csrc/ram.h index f6e224f22..5a94697c6 100644 --- a/src/test/csrc/ram.h +++ b/src/test/csrc/ram.h @@ -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 -- GitLab