Skip to content

Commit

Permalink
Rework testbench
Browse files Browse the repository at this point in the history
  • Loading branch information
RootCubed committed Jul 2, 2024
1 parent e6d6da4 commit 9273a95
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 90 deletions.
18 changes: 18 additions & 0 deletions jobs/backend_r_axi_w_obi/simple.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defaults:
src: OBI
dst: AXI
max_src_burst: 256
max_dst_burst: 256
jobs:
- length: 16384
src_addr: 0x0
dst_addr: 0x10000000
- length: 4096
src_addr: 0x2000
dst_addr: 0x18000000
- length: 8
src_addr: 0x4000
dst_addr: 0x1c000000
- length: 256
src_addr: 0x8000
dst_addr: 0x20000000
2 changes: 1 addition & 1 deletion src/idma_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ package idma_pkg;
TILELINK = 'd3,
INIT = 'd4,
AXI_STREAM = 'd5
} protocol_e;
} protocol_e /* verilator public */;

/// Supported Protocols type
typedef logic[1:0] protocol_t;
Expand Down
2 changes: 1 addition & 1 deletion src/include/idma/typedef.svh
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
axi_addr_t src_addr; \
axi_addr_t dst_addr; \
options_t opt; \
} idma_req_t;
} idma_req_t /* verilator public */;
`define IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) \
typedef struct packed { \
logic last; \
Expand Down
1 change: 1 addition & 0 deletions test/backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ obj_dir
*.vcd
*.fst
*.gtkw
third_party
127 changes: 95 additions & 32 deletions test/backend/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,85 +5,148 @@
// Authors:
// - Liam Braun <[email protected]>

#define STR(x) #x
#define EXPAND(x) x
#define STRINGIFY_MACRO(x) STR(x)
#define CONCAT(n1, n2) STRINGIFY_MACRO(EXPAND(n1)EXPAND(n2))

#define HDR_NAME_STR CONCAT(VNAME,.h)
#define DPI_HDR_STR CONCAT(VNAME,__Dpi.h)
#define SYMS_HDR_STR CONCAT(VNAME,__Syms.h)

#include <verilated.h>
#include HDR_NAME_STR
#include DPI_HDR_STR
#include SYMS_HDR_STR
#include <verilated_dpi.h>
#include "Vtb_idma_backend.h"
#include "Vtb_idma_backend__Dpi.h"
#include "Vtb_idma_backend__Syms.h"

#define RYML_SINGLE_HDR_DEFINE_NOW
#include "third_party/rapidyaml.hpp"

#include <stdio.h>
#include <stdlib.h>
#include <deque>
#include <map>
#include <iostream>

typedef Vtb_idma_backend_idma_req_t__struct__0 idma_req_t;

std::map<uint32_t, uint32_t> memory_accesses;
uint32_t curr_access_id = 0xA5A50000;
size_t invalid_writes = 0;
uint32_t invalid_writes = 0;

uint32_t copy_from = 0x1000;
uint32_t copy_to = 0x5000;
uint32_t copy_size = 256;
uint32_t copy_to = 0x20000;
uint32_t copy_size = 1024 * 16;

std::deque<idma_req_t> pendingIdmaRequests;

std::string vNameStr = STRINGIFY_MACRO(VNAME);
const idma_req_t &currentIdmaRequest() {
return pendingIdmaRequests.front();
}

unsigned int num_reads = 0;
unsigned int num_writes = 0;

void idma_read(int addr, int *data, int *delay) {
printf("[DRIVER] Read from %08x: %08x\n", addr, curr_access_id);
*data = curr_access_id;
*delay = 5000;
memory_accesses.insert({addr, curr_access_id});
curr_access_id++;
num_reads++;
}

void idma_write(int w_addr, int w_data) {
uint32_t orig_addr = w_addr + copy_from - copy_to;
uint32_t orig_addr = w_addr + currentIdmaRequest().src_addr - currentIdmaRequest().dst_addr;
printf("[DRIVER] Write %08x to %08x (original address: %08x)\n", w_data, w_addr, orig_addr);
if (memory_accesses.count(orig_addr) == 0) {
printf("[DRIVER] Write is invalid (never read from there)\n");
invalid_writes++;
} else if (memory_accesses.at(orig_addr) != w_data) {
printf("[DRIVER] Write is invalid (wrong value)\n");
invalid_writes++;
} else {
memory_accesses.erase(orig_addr);
}
num_writes++;
}

typedef struct {
unsigned int dst_addr;
unsigned int src_addr;
unsigned int length;
} idma_req_t;
void idma_request_done() {
printf("[DRIVER] Request done\n");
pendingIdmaRequests.pop_front();
}

Vtb_idma_backend_idma_pkg::protocol_e strToProtocol(std::string str) {
if (str == "OBI") return Vtb_idma_backend_idma_pkg::protocol_e::OBI;
if (str == "AXI") return Vtb_idma_backend_idma_pkg::protocol_e::AXI;
return Vtb_idma_backend_idma_pkg::protocol_e::OBI;
}

int main(int argc, char **argv) {
// Verilated::debug(1);
Verilated::debug(1);

Verilated::commandArgs(argc, argv);
VNAME *idma = new VNAME();
Vtb_idma_backend *idma = new Vtb_idma_backend();
Verilated::traceEverOn(true);
svSetScope(svGetScopeFromName(("TOP." + vNameStr.substr(1)).c_str()));
int cycs = 0;
while (!Verilated::gotFinish() && cycs++ < 100000) {
if (cycs == 100) {
printf("Pushing request\n");
idma->add_request(copy_size, copy_from, copy_to);
}
svSetScope(svGetScopeFromName("TOP.tb_idma_backend"));

std::string jobFile = argv[1];

// printf("Loading job file %s\n", jobFile.c_str());
FILE *jobFp = fopen(jobFile.c_str(), "r");
if (jobFp == NULL) {
printf("Failed to open job file\n");
return 1;
}
std::string jobStr;
char c;
while ((c = fgetc(jobFp)) != EOF) {
jobStr += c;
}

ryml::Tree jobYaml = ryml::parse_in_place(ryml::to_substr(jobStr));

int reqCount = jobYaml["jobs"].num_children();

Vtb_idma_backend_idma_pkg::protocol_e defaultSrcProtocol = strToProtocol(jobYaml["defaults"]["src"].val().str);
Vtb_idma_backend_idma_pkg::protocol_e defaultDstProtocol = strToProtocol(jobYaml["defaults"]["dst"].val().str);
int defaultMaxSrcBurst = std::stoi(jobYaml["defaults"]["max_src_burst"].val().str);
int defaultMaxDstBurst = std::stoi(jobYaml["defaults"]["max_dst_burst"].val().str);

for (int i = 0; i < reqCount; i++) {
idma_req_t idmaRequest;
idmaRequest.dst_addr = std::stoul(jobYaml["jobs"][i]["dst_addr"].val().str, nullptr, 0);
idmaRequest.src_addr = std::stoul(jobYaml["jobs"][i]["src_addr"].val().str, nullptr, 0);
idmaRequest.length = std::stoul(jobYaml["jobs"][i]["length" ].val().str, nullptr, 0);

idmaRequest.opt.src_protocol = defaultSrcProtocol;
idmaRequest.opt.src.burst = 0b01; // INCR
idmaRequest.opt.dst_protocol = defaultDstProtocol;
idmaRequest.opt.dst.burst = 0b01; // INCR

idmaRequest.opt.beo.decouple_aw = 0;
idmaRequest.opt.beo.decouple_rw = 0;
idmaRequest.opt.beo.src_max_llen = defaultMaxSrcBurst;
idmaRequest.opt.beo.dst_max_llen = defaultMaxDstBurst;
idmaRequest.opt.beo.src_reduce_len = 1;
idmaRequest.opt.beo.dst_reduce_len = 1;

idmaRequest.opt.last = (i == reqCount - 1);

// printf("Pushing request\n");
pendingIdmaRequests.push_back(idmaRequest);
idma->tb_idma_backend->trigger_request(idmaRequest.get());
}

int cycs = 0;
while (!Verilated::gotFinish()) {
idma->eval();
if (!idma->eventsPending()) break;
Verilated::time(idma->nextTimeSlot());

cycs++;
}

idma->final();
delete idma;

printf("Testbench terminated. Invalid writes: %ld\n", invalid_writes);
printf("Testbench terminated. Statistics:\n");
printf(" Reads: %u\n", num_reads);
printf(" Writes: %u\n", num_writes);
printf(" Invalid writes: %u\n", invalid_writes);
printf("Outstanding writes: %lu\n", memory_accesses.size());

return 0;
}
4 changes: 4 additions & 0 deletions test/backend/idma.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
# Authors:
# - Liam Braun <[email protected]>

if [ ! -f third_party/rapidyaml.hpp ]; then
wget https://github.com/biojppm/rapidyaml/releases/download/v0.7.0/rapidyaml-0.7.0.hpp -O third_party/rapidyaml.hpp
fi

verilator -f idma.f --timing --trace --trace-structs --trace-fst --build --exe -j `nproc` \
-Wno-UNOPTFLAT -Wno-PINMISSING -Wno-WIDTH \
--top tb_idma_backend \
Expand Down
96 changes: 40 additions & 56 deletions test/backend/tb_idma_backend.sv
Original file line number Diff line number Diff line change
Expand Up @@ -232,68 +232,52 @@ module tb_idma_backend #(
.busy_o ( idma_busy_o )
);

export "DPI-C" function add_request;
idma_req_t new_idma_req;
function add_request(input int length, input int src_addr, input int dst_addr);
new_idma_req = '0;
new_idma_req.length = length;
new_idma_req.src_addr = src_addr;
new_idma_req.dst_addr = dst_addr;
idma_req.push_back(new_idma_req);
import "DPI-C" function void idma_request_done();

// Not using regular DPI-C export here because it makes working with the idma_req_t struct much less of a hassle
function trigger_request;
// verilator public
input idma_req_t request;
idma_req.push_back(request);
endfunction

always @(posedge clk) begin
if (idma_req.size() > 0) begin
curr_idma_req = '0;
curr_idma_req.dst_addr = idma_req[0].dst_addr;
curr_idma_req.src_addr = idma_req[0].src_addr;
curr_idma_req.length = idma_req[0].length;
`ifdef PORT_R_AXI4
curr_idma_req.opt.src_protocol = idma_pkg::AXI;
`elsif PORT_R_OBI
curr_idma_req.opt.src_protocol = idma_pkg::OBI;
`endif
`ifdef PORT_W_AXI4
curr_idma_req.opt.dst_protocol = idma_pkg::AXI;
`elsif PORT_W_OBI
curr_idma_req.opt.dst_protocol = idma_pkg::OBI;
`endif
curr_idma_req.opt.beo.decouple_aw = '0;
curr_idma_req.opt.beo.decouple_rw = '0;
curr_idma_req.opt.beo.src_max_llen = 32;
curr_idma_req.opt.beo.dst_max_llen = 32;
curr_idma_req.opt.beo.src_reduce_len = '1;
curr_idma_req.opt.beo.dst_reduce_len = '1;

eh_req_i = '0;
eh_req_valid_i = '0;

req_valid = 1;

idma_req.pop_back();

$display("Sending request");
while (req_ready != '1) #TA;
#TA req_valid = 0;
$display("Request sent");

rsp_ready = '1;

while (rsp_valid != '1) #TA;
$display("Request complete.");
initial begin
$dumpfile("idma_trace.fst");
$dumpvars(0);

$finish;
end
end
eh_req_i = '0;
eh_req_valid_i = '0;

wait (rst_n);

#100ns;

while (idma_req.size() > 0) begin
curr_idma_req = idma_req[0];
idma_req.pop_front();

$display("Sending request...");
req_valid <= #TA '1;
#TT;
while (req_ready != '1) begin @(posedge clk); #TT; end
@(posedge clk);
$display("Sent request. Waiting for response...");

req_valid <= #TA '0;
rsp_ready <= #TA '1;
#TT;
while (rsp_valid != '1) begin @(posedge clk); #TT; end
@(posedge clk);

rsp_ready <= #TA '0;
@(posedge clk);

initial begin
#10ns rst_n = '0;
#10ns rst_n = '1;
$display("Request complete.");

$dumpfile("idma_trace.vcd");
$dumpvars(0);
idma_request_done();
end

#500000ns $display("Terminating, no response received in time.");
#100ns;
$finish;
end

Expand Down

0 comments on commit 9273a95

Please sign in to comment.