blob: eb592e76affd7a96cd9a2fde98f54c32f06853a3 [file] [log] [blame]
#include <elf.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <systemc.h>
#include <unistd.h>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include "tests/systemc/Xbar.h"
#include "tests/verilator_sim/elf.h"
#include "top.h"
/* clang-format off */
#include <tlm>
#include <tlm_utils/simple_initiator_socket.h>
#include <tlm_utils/simple_target_socket.h>
#include "checkers/pc-axi.h"
#include "tlm-bridges/tlm2axi-bridge.h"
#include "tlm-bridges/axi2tlm-bridge.h"
#include "traffic-generators/tg-tlm.h"
#include "traffic-generators/traffic-desc.h"
#include "tests/test-modules/signals-axi.h"
#include "tests/test-modules/utils.h"
/* clang-format on */
std::unique_ptr<TrafficDesc> bin_transfer;
std::unique_ptr<TrafficDesc> disable_cg_transfer;
std::unique_ptr<TrafficDesc> release_reset_transfer;
std::unique_ptr<TrafficDesc> status_read_transfer;
static void disable_cg_transfer_done_cb(TLMTrafficGenerator* gen,
int threadId) {
gen->addTransfers(release_reset_transfer.get(), 0);
}
static void bin_transfer_done_cb(TLMTrafficGenerator* gen, int threadId) {
gen->addTransfers(disable_cg_transfer.get(), 0, disable_cg_transfer_done_cb);
}
int sc_main(int argc, char** argv) {
sc_top top("top");
sc_clock clock("clock", 100, SC_NS);
Xbar xbar("xbar");
tlm2axi_bridge<KP_axi2AddrBits, KP_lsuDataBits, KP_axi2IdBits, 8, 2, 0, 0, 0,
0, 0>
tlm2axi_bridge("tlm2axi_bridge");
axi2tlm_bridge<KP_axi2AddrBits, KP_lsuDataBits, KP_axi2IdBits, 8, 2, 0, 0, 0,
0, 0>
axi2tlm_bridge("axi2tlm_bridge");
typedef AXIProtocolChecker<KP_axi2AddrBits, KP_lsuDataBits, KP_axi2IdBits, 8,
2, 0, 0, 0, 0, 0>
CoreMiniAxiProtocolChecker;
CoreMiniAxiProtocolChecker tlm2axi_checker("tlm2axi_checker");
CoreMiniAxiProtocolChecker axi2tlm_checker("axi2tlm_checker");
typedef AXISignals<KP_axi2AddrBits, // ADDR_WIDTH
KP_lsuDataBits, // DATA_WIDTH
KP_axi2IdBits, // ID_WIDTH
8, // AxLEN_WIDTH
2, // AxLOCK_WIDTH
0, 0, 0, 0, 0 // User
>
CoreMiniAxiSignals;
top.clock(clock);
tlm2axi_bridge.clk(clock);
tlm2axi_bridge.resetn(top.resetn);
tlm2axi_checker.clk(clock);
tlm2axi_checker.resetn(top.resetn);
axi2tlm_bridge.clk(clock);
axi2tlm_bridge.resetn(top.resetn);
axi2tlm_checker.clk(clock);
axi2tlm_checker.resetn(top.resetn);
CoreMiniAxiSignals tlm2axi_signals("tlm2axi_signals");
tlm2axi_signals.connect(tlm2axi_bridge);
tlm2axi_signals.connect(tlm2axi_checker);
top.slave_rready(tlm2axi_signals.rready);
top.slave_rvalid(tlm2axi_signals.rvalid);
top.slave_rdata(tlm2axi_signals.rdata);
top.slave_rid(tlm2axi_signals.rid);
top.slave_rresp(tlm2axi_signals.rresp);
top.slave_rlast(tlm2axi_signals.rlast);
top.slave_arready(tlm2axi_signals.arready);
top.slave_arvalid(tlm2axi_signals.arvalid);
top.slave_araddr(tlm2axi_signals.araddr);
top.slave_arprot(tlm2axi_signals.arprot);
top.slave_arid(tlm2axi_signals.arid);
top.slave_arlen(tlm2axi_signals.arlen);
top.slave_arsize(tlm2axi_signals.arsize);
top.slave_arburst(tlm2axi_signals.arburst);
top.slave_arlock(tlm2axi_signals.arlock);
top.slave_arcache(tlm2axi_signals.arcache);
top.slave_arqos(tlm2axi_signals.arqos);
top.slave_arregion(tlm2axi_signals.arregion);
top.slave_awready(tlm2axi_signals.awready);
top.slave_awvalid(tlm2axi_signals.awvalid);
top.slave_awaddr(tlm2axi_signals.awaddr);
top.slave_awprot(tlm2axi_signals.awprot);
top.slave_awid(tlm2axi_signals.awid);
top.slave_awlen(tlm2axi_signals.awlen);
top.slave_awsize(tlm2axi_signals.awsize);
top.slave_awburst(tlm2axi_signals.awburst);
top.slave_awlock(tlm2axi_signals.awlock);
top.slave_awcache(tlm2axi_signals.awcache);
top.slave_awqos(tlm2axi_signals.awqos);
top.slave_awregion(tlm2axi_signals.awregion);
top.slave_wready(tlm2axi_signals.wready);
top.slave_wvalid(tlm2axi_signals.wvalid);
top.slave_wdata(tlm2axi_signals.wdata);
top.slave_wlast(tlm2axi_signals.wlast);
top.slave_wstrb(tlm2axi_signals.wstrb);
top.slave_bready(tlm2axi_signals.bready);
top.slave_bvalid(tlm2axi_signals.bvalid);
top.slave_bid(tlm2axi_signals.bid);
top.slave_bresp(tlm2axi_signals.bresp);
CoreMiniAxiSignals axi2tlm_signals("axi2tlm_signals");
axi2tlm_signals.connect(axi2tlm_bridge);
axi2tlm_signals.connect(axi2tlm_checker);
top.master_rready(axi2tlm_signals.rready);
top.master_rvalid(axi2tlm_signals.rvalid);
top.master_rdata(axi2tlm_signals.rdata);
top.master_rid(axi2tlm_signals.rid);
top.master_rresp(axi2tlm_signals.rresp);
top.master_rlast(axi2tlm_signals.rlast);
top.master_arready(axi2tlm_signals.arready);
top.master_arvalid(axi2tlm_signals.arvalid);
top.master_araddr(axi2tlm_signals.araddr);
top.master_arprot(axi2tlm_signals.arprot);
top.master_arid(axi2tlm_signals.arid);
top.master_arlen(axi2tlm_signals.arlen);
top.master_arsize(axi2tlm_signals.arsize);
top.master_arburst(axi2tlm_signals.arburst);
top.master_arlock(axi2tlm_signals.arlock);
top.master_arcache(axi2tlm_signals.arcache);
top.master_arqos(axi2tlm_signals.arqos);
top.master_arregion(axi2tlm_signals.arregion);
top.master_awready(axi2tlm_signals.awready);
top.master_awvalid(axi2tlm_signals.awvalid);
top.master_awaddr(axi2tlm_signals.awaddr);
top.master_awprot(axi2tlm_signals.awprot);
top.master_awid(axi2tlm_signals.awid);
top.master_awlen(axi2tlm_signals.awlen);
top.master_awsize(axi2tlm_signals.awsize);
top.master_awburst(axi2tlm_signals.awburst);
top.master_awlock(axi2tlm_signals.awlock);
top.master_awcache(axi2tlm_signals.awcache);
top.master_awqos(axi2tlm_signals.awqos);
top.master_awregion(axi2tlm_signals.awregion);
top.master_wready(axi2tlm_signals.wready);
top.master_wvalid(axi2tlm_signals.wvalid);
top.master_wdata(axi2tlm_signals.wdata);
top.master_wlast(axi2tlm_signals.wlast);
top.master_wstrb(axi2tlm_signals.wstrb);
top.master_bready(axi2tlm_signals.bready);
top.master_bvalid(axi2tlm_signals.bvalid);
top.master_bid(axi2tlm_signals.bid);
top.master_bresp(axi2tlm_signals.bresp);
TLMTrafficGenerator tg("tg");
tg.socket.bind(tlm2axi_bridge.tgt_socket);
tg.setStartDelay(sc_time(1, SC_US));
axi2tlm_bridge.socket.bind(xbar.socket());
constexpr int kRetNoFilename = -1;
constexpr int kRetFileNotExist = -2;
constexpr int kRetFstatError = -3;
constexpr int kRetMmapFailed = -4;
if (!hdl_elaboration_only()) {
const char* kKeyFilename = "--filename";
std::optional<std::string> filename;
for (int i = 0; i < argc; ++i) {
if (strncmp(kKeyFilename, argv[i], strlen(kKeyFilename)) == 0) {
if (i + 1 < argc) {
filename = std::string(argv[i + 1]);
break;
}
}
}
if (!filename) {
printf("Usage: $s --filename <bin|elf>\n", argv[0]);
return kRetNoFilename;
}
int fd = open(filename.value().c_str(), 0);
if (fd <= 0) {
return kRetFileNotExist;
}
struct stat sb;
if (fstat(fd, &sb) != 0) {
return kRetFstatError;
}
auto file_size_ = sb.st_size;
auto file_data_ = mmap(nullptr, file_size_, PROT_READ, MAP_PRIVATE, fd, 0);
if (file_data_ == MAP_FAILED) {
return kRetMmapFailed;
}
close(fd);
uint32_t elf_magic = 0x464c457f;
uint8_t* data8 = reinterpret_cast<uint8_t*>(file_data_);
if (memcmp(file_data_, &elf_magic, sizeof(elf_magic)) == 0) {
std::vector<DataTransfer> elf_transfers;
const Elf32_Ehdr* elf_header = reinterpret_cast<Elf32_Ehdr*>(file_data_);
elf_transfers.reserve(3 * elf_header->e_phnum + 1);
LoadElf(data8,
[&elf_transfers](void* dest, const void* src, size_t count) {
elf_transfers.push_back(utils::Write(
reinterpret_cast<uint64_t>(dest),
reinterpret_cast<uint8_t*>(const_cast<void*>(src)), count));
elf_transfers.push_back(
utils::Read(reinterpret_cast<uint64_t>(dest), count));
elf_transfers.push_back(utils::Expect(
reinterpret_cast<uint8_t*>(const_cast<void*>(src)), count));
return dest;
});
bin_transfer = std::make_unique<TrafficDesc>(utils::merge(elf_transfers));
} else {
// Transaction to fill ITCM with the provided binary.
bin_transfer =
std::make_unique<TrafficDesc>(utils::merge(std::vector<DataTransfer>(
{utils::Write(0, data8, file_size_), utils::Read(0, file_size_),
utils::Expect(data8, file_size_)})));
}
auto csr_addr_ = 0x30000;
disable_cg_transfer =
std::make_unique<TrafficDesc>(utils::merge(std::vector<DataTransfer>(
{utils::Write(csr_addr_, DATA(1, 0, 0, 0)),
utils::Read(csr_addr_, 4), utils::Expect(DATA(1, 0, 0, 0), 4)})));
release_reset_transfer =
std::make_unique<TrafficDesc>(utils::merge(std::vector<DataTransfer>(
{utils::Write(csr_addr_, DATA(0, 0, 0, 0)),
utils::Read(csr_addr_, 4), utils::Expect(DATA(0, 0, 0, 0), 4)})));
status_read_transfer = std::make_unique<TrafficDesc>(utils::merge(
std::vector<DataTransfer>({utils::Read(csr_addr_ + 0x8, 4),
utils::Expect(DATA(1, 0, 0, 0), 4)})));
tg.addTransfers(bin_transfer.get(), 0, bin_transfer_done_cb);
}
sc_start(1000000, SC_NS);
return 0;
}