Commit 9e3389aa authored by Antoine Kaufmann's avatar Antoine Kaufmann
Browse files

checkpoint

parent 273e229a
...@@ -5,13 +5,13 @@ VFLAGS = +1364-2005ext+v \ ...@@ -5,13 +5,13 @@ VFLAGS = +1364-2005ext+v \
-Wno-WIDTH -Wno-PINMISSING -Wno-LITENDIAN -Wno-IMPLICIT -Wno-SELRANGE \ -Wno-WIDTH -Wno-PINMISSING -Wno-LITENDIAN -Wno-IMPLICIT -Wno-SELRANGE \
-Wno-CASEINCOMPLETE -Wno-UNSIGNED -Wno-CASEINCOMPLETE -Wno-UNSIGNED
SRCS = corundum_verilator.cpp SRCS = corundum_verilator.cpp dma.cpp mem.cpp
all: corundum_verilator all: corundum_verilator
obj_dir/Vinterface.cpp: rtl/interface.v obj_dir/Vinterface.cpp: rtl/interface.v
$(VERILATOR) $(VFLAGS) --cc -O3 \ $(VERILATOR) $(VFLAGS) --cc -O3 \
-CFLAGS "-I$(PWD)/../nicsim_common/include -I$(PWD)/../proto -O3" \ -CFLAGS "-I$(PWD)/../nicsim_common/include -I$(PWD)/../proto -O3 -g -Wall" \
-y rtl \ -y rtl \
-y lib/axi/rtl \ -y lib/axi/rtl \
-y lib/eth/lib/axis/rtl/ \ -y lib/eth/lib/axis/rtl/ \
......
#ifndef CORUNDUM_H_
#define CORUNDUM_H_
#include "dma.h"
void pci_dma_issue(DMAOp *op);
#endif /* ndef CORUNDUM_H_ */
...@@ -11,12 +11,15 @@ extern "C" { ...@@ -11,12 +11,15 @@ extern "C" {
#include "verilated.h" #include "verilated.h"
#include "verilated_vcd_c.h" #include "verilated_vcd_c.h"
#include "corundum.h"
#include "dma.h"
#include "mem.h"
struct DMAOp; struct DMAOp;
static volatile int exiting = 0; static volatile int exiting = 0;
static uint64_t main_time = 0; static uint64_t main_time = 0;
static void pci_dma_issue(DMAOp *op);
static void sigint_handler(int dummy) static void sigint_handler(int dummy)
...@@ -319,6 +322,7 @@ class MMIOInterface { ...@@ -319,6 +322,7 @@ class MMIOInterface {
}; };
#if 0
class MemAccessor { class MemAccessor {
protected: protected:
Vinterface ⊤ Vinterface ⊤
...@@ -359,100 +363,11 @@ class MemAccessor { ...@@ -359,100 +363,11 @@ class MemAccessor {
{ {
} }
}; };
#endif
static const size_t MAX_DMA_LEN = 2048;
class DMAEngine;
struct DMAOp {
DMAEngine *engine;
uint64_t dma_addr;
size_t len;
uint64_t ram_addr;
bool write;
uint8_t ram_sel;
uint8_t tag;
uint8_t data[MAX_DMA_LEN];
};
class DMAEngine {
protected:
Vinterface ⊤
std::set<DMAOp *> pending;
const char *label;
bool read;
MemAccessor &ma;
/* inputs to DMA engine */
vluint64_t &p_dma_addr;
vluint8_t &p_dma_ram_sel;
vluint32_t &p_dma_ram_addr;
vluint16_t &p_dma_len;
vluint8_t &p_dma_tag;
vluint8_t &p_dma_valid;
/* outputs of DMA engine */
vluint8_t &p_dma_ready;
vluint8_t &p_dma_status_tag;
vluint8_t &p_dma_status_valid;
public:
DMAEngine(Vinterface &top_, const char *label_, bool dma_read,
MemAccessor &ma_,
vluint64_t &p_dma_addr_,
vluint8_t &p_dma_ram_sel_,
vluint32_t &p_dma_ram_addr_,
vluint16_t &p_dma_len_,
vluint8_t &p_dma_tag_,
vluint8_t &p_dma_valid_,
vluint8_t &p_dma_ready_,
vluint8_t &p_dma_status_tag_,
vluint8_t &p_dma_status_valid_)
: top(top_), label(label_), read(dma_read), ma(ma_),
p_dma_addr(p_dma_addr_),
p_dma_ram_sel(p_dma_ram_sel_), p_dma_ram_addr(p_dma_ram_addr_),
p_dma_len(p_dma_len_), p_dma_tag(p_dma_tag_),
p_dma_valid(p_dma_valid_), p_dma_ready(p_dma_ready_),
p_dma_status_tag(p_dma_status_tag_),
p_dma_status_valid(p_dma_status_valid_)
{
}
void pci_op_complete(DMAOp *op)
{
std::cout << "dma pci complete " << op->dma_addr << std::endl;
}
void step()
{
p_dma_ready = 1;
if (p_dma_valid) {
DMAOp *op = new DMAOp;
op->engine = this;
op->dma_addr = p_dma_addr;
op->ram_sel = p_dma_ram_sel;
op->ram_addr = p_dma_ram_addr;
op->len = p_dma_len;
op->tag = p_dma_tag;
pending.insert(op);
std::cout << "dma op " << op->dma_addr << " -> " <<
op->ram_sel << ":" << op->ram_addr <<
" len=" << op->len << " tag=" << (int) op->tag << std::endl;
if (read) {
pci_dma_issue(op);
} else {
std::cerr << "TODO: DMA write" << std::endl;
}
}
}
};
std::set<DMAOp *> pci_dma_pending; std::set<DMAOp *> pci_dma_pending;
static void pci_dma_issue(DMAOp *op) void pci_dma_issue(DMAOp *op)
{ {
volatile union cosim_pcie_proto_d2h *msg = nicsim_d2h_alloc(); volatile union cosim_pcie_proto_d2h *msg = nicsim_d2h_alloc();
uint8_t ty; uint8_t ty;
...@@ -494,6 +409,13 @@ static void h2d_readcomp(volatile struct cosim_pcie_proto_h2d_readcomp *rc) ...@@ -494,6 +409,13 @@ static void h2d_readcomp(volatile struct cosim_pcie_proto_h2d_readcomp *rc)
pci_dma_pending.erase(op); pci_dma_pending.erase(op);
memcpy(op->data, (void *) rc->data, op->len); memcpy(op->data, (void *) rc->data, op->len);
std::cerr << "dma read comp: ";
for (size_t i = 0; i < op->len; i++)
std::cerr << (unsigned) op->data[i] << " ";
std::cerr << std::endl;
op->engine->pci_op_complete(op); op->engine->pci_op_complete(op);
} }
...@@ -624,6 +546,28 @@ static void poll_h2d(MMIOInterface &mmio) ...@@ -624,6 +546,28 @@ static void poll_h2d(MMIOInterface &mmio)
} }
class EthernetTx {
protected:
Vinterface &top;
public:
EthernetTx(Vinterface &top_)
: top(top_)
{
}
void step()
{
top.tx_axis_tready = 1;
if (top.tx_axis_tvalid) {
std::cerr << "valid data: keep=" << (uintptr_t) top.tx_axis_tkeep <<
" last=" << (bool) top.tx_axis_tlast << " " << top.tx_axis_tdata << std::endl;
}
}
};
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Verilated::commandArgs(argc, argv); Verilated::commandArgs(argc, argv);
...@@ -651,18 +595,38 @@ int main(int argc, char *argv[]) ...@@ -651,18 +595,38 @@ int main(int argc, char *argv[])
Vinterface *top = new Vinterface; Vinterface *top = new Vinterface;
MMIOInterface mmio(*top); MemWritePort p_mem_write_ctrl_dma(
MemAccessor mem_writer(*top, false,
top->ctrl_dma_ram_wr_cmd_sel, top->ctrl_dma_ram_wr_cmd_sel,
&top->ctrl_dma_ram_wr_cmd_be /*14 */, top->ctrl_dma_ram_wr_cmd_be,
top->ctrl_dma_ram_wr_cmd_addr, top->ctrl_dma_ram_wr_cmd_addr,
top->ctrl_dma_ram_wr_cmd_valid,
(vluint8_t *) 0,
top->ctrl_dma_ram_wr_cmd_data, top->ctrl_dma_ram_wr_cmd_data,
top->ctrl_dma_ram_wr_cmd_ready, top->ctrl_dma_ram_wr_cmd_valid,
(vluint8_t *) 0); top->ctrl_dma_ram_wr_cmd_ready);
MemReadPort p_mem_read_ctrl_dma(
DMAEngine dma_read_ctrl(*top, "read ctrl", true, mem_writer, top->ctrl_dma_ram_rd_cmd_sel,
top->ctrl_dma_ram_rd_cmd_addr,
top->ctrl_dma_ram_rd_cmd_valid,
top->ctrl_dma_ram_rd_cmd_ready,
top->ctrl_dma_ram_rd_resp_data,
top->ctrl_dma_ram_rd_resp_valid,
top->ctrl_dma_ram_rd_resp_ready);
MemWritePort p_mem_write_data_dma(
top->data_dma_ram_wr_cmd_sel,
top->data_dma_ram_wr_cmd_be,
top->data_dma_ram_wr_cmd_addr,
top->data_dma_ram_wr_cmd_data,
top->data_dma_ram_wr_cmd_valid,
top->data_dma_ram_wr_cmd_ready);
MemReadPort p_mem_read_data_dma(
top->data_dma_ram_rd_cmd_sel,
top->data_dma_ram_rd_cmd_addr,
top->data_dma_ram_rd_cmd_valid,
top->data_dma_ram_rd_cmd_ready,
top->data_dma_ram_rd_resp_data,
top->data_dma_ram_rd_resp_valid,
top->data_dma_ram_rd_resp_ready);
DMAPorts p_dma_read_ctrl(
top->m_axis_ctrl_dma_read_desc_dma_addr, top->m_axis_ctrl_dma_read_desc_dma_addr,
top->m_axis_ctrl_dma_read_desc_ram_sel, top->m_axis_ctrl_dma_read_desc_ram_sel,
top->m_axis_ctrl_dma_read_desc_ram_addr, top->m_axis_ctrl_dma_read_desc_ram_addr,
...@@ -672,7 +636,7 @@ int main(int argc, char *argv[]) ...@@ -672,7 +636,7 @@ int main(int argc, char *argv[])
top->m_axis_ctrl_dma_read_desc_ready, top->m_axis_ctrl_dma_read_desc_ready,
top->s_axis_ctrl_dma_read_desc_status_tag, top->s_axis_ctrl_dma_read_desc_status_tag,
top->s_axis_ctrl_dma_read_desc_status_valid); top->s_axis_ctrl_dma_read_desc_status_valid);
DMAEngine dma_write_ctrl(*top, "write ctrl", false, mem_writer/*should be reader*/, DMAPorts p_dma_write_ctrl(
top->m_axis_ctrl_dma_write_desc_dma_addr, top->m_axis_ctrl_dma_write_desc_dma_addr,
top->m_axis_ctrl_dma_write_desc_ram_sel, top->m_axis_ctrl_dma_write_desc_ram_sel,
top->m_axis_ctrl_dma_write_desc_ram_addr, top->m_axis_ctrl_dma_write_desc_ram_addr,
...@@ -682,6 +646,37 @@ int main(int argc, char *argv[]) ...@@ -682,6 +646,37 @@ int main(int argc, char *argv[])
top->m_axis_ctrl_dma_write_desc_ready, top->m_axis_ctrl_dma_write_desc_ready,
top->s_axis_ctrl_dma_write_desc_status_tag, top->s_axis_ctrl_dma_write_desc_status_tag,
top->s_axis_ctrl_dma_write_desc_status_valid); top->s_axis_ctrl_dma_write_desc_status_valid);
DMAPorts p_dma_read_data(
top->m_axis_data_dma_read_desc_dma_addr,
top->m_axis_data_dma_read_desc_ram_sel,
top->m_axis_data_dma_read_desc_ram_addr,
top->m_axis_data_dma_read_desc_len,
top->m_axis_data_dma_read_desc_tag,
top->m_axis_data_dma_read_desc_valid,
top->m_axis_data_dma_read_desc_ready,
top->s_axis_data_dma_read_desc_status_tag,
top->s_axis_data_dma_read_desc_status_valid);
DMAPorts p_dma_write_data(
top->m_axis_data_dma_write_desc_dma_addr,
top->m_axis_data_dma_write_desc_ram_sel,
top->m_axis_data_dma_write_desc_ram_addr,
top->m_axis_data_dma_write_desc_len,
top->m_axis_data_dma_write_desc_tag,
top->m_axis_data_dma_write_desc_valid,
top->m_axis_data_dma_write_desc_ready,
top->s_axis_data_dma_write_desc_status_tag,
top->s_axis_data_dma_write_desc_status_valid);
MMIOInterface mmio(*top);
MemReader mem_control_reader(p_mem_read_ctrl_dma);
MemWriter mem_control_writer(p_mem_write_ctrl_dma);
MemWriter mem_data_writer(p_mem_write_data_dma);
DMAReader dma_read_ctrl("read ctrl", p_dma_read_ctrl, mem_control_writer);
DMAReader dma_read_data("read data", p_dma_read_data, mem_data_writer);
//DMAEngine dma_write_ctrl(*top, "write ctrl", false, mem_writer/*should be reader*/,
EthernetTx tx(*top);
reset_inputs(top); reset_inputs(top);
top->rst = 1; top->rst = 1;
...@@ -703,7 +698,11 @@ int main(int argc, char *argv[]) ...@@ -703,7 +698,11 @@ int main(int argc, char *argv[])
mmio.step(); mmio.step();
dma_read_ctrl.step(); dma_read_ctrl.step();
dma_write_ctrl.step(); dma_read_data.step();
mem_control_writer.step();
mem_data_writer.step();
//dma_write_ctrl.step();
tx.step();
/* raising edge */ /* raising edge */
top->clk = !top->clk; top->clk = !top->clk;
......
#include <iostream>
#include "corundum.h"
#include "dma.h"
#include "mem.h"
void DMAReader::step()
{
p.dma_ready = 1;
if (p.dma_valid) {
DMAOp *op = new DMAOp;
op->engine = this;
op->dma_addr = p.dma_addr;
op->ram_sel = p.dma_ram_sel;
op->ram_addr = p.dma_ram_addr;
op->len = p.dma_len;
op->tag = p.dma_tag;
op->write = false;
pending.insert(op);
std::cout << "dma[" << label << "] op " << op->dma_addr << " -> " <<
op->ram_sel << ":" << op->ram_addr <<
" len=" << op->len << " tag=" << (int) op->tag << std::endl;
pci_dma_issue(op);
}
p.dma_status_valid = 0;
if (!completed.empty()) {
DMAOp *op = completed.front();
completed.pop_front();
std::cout << "dma[" << label << "] status complete " << op->dma_addr << std::endl;
p.dma_status_valid = 1;
p.dma_status_tag = op->tag;
pending.erase(op);
delete op;
}
}
void DMAReader::pci_op_complete(DMAOp *op)
{
mw.op_issue(op);
}
void DMAReader::mem_op_complete(DMAOp *op)
{
completed.push_back(op);
std::cout << "dma[" << label << "] mem complete " << op->dma_addr << std::endl;
}
#ifndef MEM_H_
#define MEM_H_
#include <set>
#include <deque>
#include "Vinterface.h"
#include "verilated.h"
#define MAX_DMA_LEN 2048
class DMAEngine;
class MemWriter;
struct DMAPorts {
/* inputs to DMA engine */
vluint64_t &dma_addr;
vluint8_t &dma_ram_sel;
vluint32_t &dma_ram_addr;
vluint16_t &dma_len;
vluint8_t &dma_tag;
vluint8_t &dma_valid;
/* outputs of DMA engine */
vluint8_t &dma_ready;
vluint8_t &dma_status_tag;
vluint8_t &dma_status_valid;
DMAPorts(vluint64_t &dma_addr_, vluint8_t &dma_ram_sel_,
vluint32_t &dma_ram_addr_, vluint16_t &dma_len_,
vluint8_t &dma_tag_, vluint8_t &dma_valid_,
vluint8_t &dma_ready_, vluint8_t &dma_status_tag_,
vluint8_t &dma_status_valid_)
: dma_addr(dma_addr_), dma_ram_sel(dma_ram_sel_),
dma_ram_addr(dma_ram_addr_), dma_len(dma_len_),
dma_tag(dma_tag_), dma_valid(dma_valid_),
dma_ready(dma_ready_), dma_status_tag(dma_status_tag_),
dma_status_valid(dma_status_valid_)
{
}
};
struct DMAOp {
DMAEngine *engine;
uint64_t dma_addr;
size_t len;
uint64_t ram_addr;
bool write;
uint8_t ram_sel;
uint8_t tag;
uint8_t data[MAX_DMA_LEN];
};
class DMAEngine {
protected:
DMAPorts &p;
DMAEngine(DMAPorts &p_)
: p(p_) { }
public:
virtual void pci_op_complete(DMAOp *op) = 0;
virtual void mem_op_complete(DMAOp *op) = 0;
};
class DMAReader : public DMAEngine {
protected:
std::set<DMAOp *> pending;
std::deque<DMAOp *> completed;
const char *label;
MemWriter &mw;
public:
DMAReader(const char *label_, DMAPorts &p_, MemWriter &mw_)
: DMAEngine(p_), label(label_), mw(mw_)
{
}
virtual void pci_op_complete(DMAOp *op);
virtual void mem_op_complete(DMAOp *op);
void step();
};
#endif /* ndef DMA_H_ */
#include <iostream>
#include "mem.h"
#include "dma.h"
/*
* 1024 bits total data width
* = 128 bytes total
*
* 1024 / 8 = 128 bit per segment
* = 16 bytes / segment
*/
#define DATA_WIDTH (512 * 2)
#define SEG_COUNT 8
#define SEG_WIDTH (DATA_WIDTH / SEG_COUNT)
void MemWriter::step()
{
if (cur && p.mem_ready) {
std::cerr << "completed write to: " << cur->ram_addr << std::endl;
p.mem_valid = 0;
p.mem_be[0] = p.mem_be[1] = p.mem_be[2] = p.mem_be[3] = 0;
cur->engine->mem_op_complete(cur);
cur = 0;
}
if (!cur && !pending.empty()) {
cur = pending.front();
pending.pop_front();
std::cerr << "issuing write to " << cur->ram_addr << std::endl;
size_t data_byte_width = DATA_WIDTH / 8;
size_t data_offset = cur->ram_addr % data_byte_width;
if (cur->len > data_byte_width - data_offset) {
std::cerr << "MemWriter::step: cannot be written in one cycle TODO" << std::endl;
throw "unsupported";
}
/* first reset everything */
p.mem_sel = 0;
p.mem_addr[0] = p.mem_addr[1] = p.mem_addr[2] = 0;
p.mem_be[0] = p.mem_be[1] = p.mem_be[2] = p.mem_be[3] = 0;
p.mem_valid = 0;
/* put data bytes in the right places */
size_t off = data_offset;
for (size_t i = 0; i < cur->len; i++, off++) {
size_t byte_off = off % 4;
// first clear data byte
p.mem_data[off / 4] &= ~(0xffu << (byte_off * 8));
// then set data byte
p.mem_data[off / 4] |= (((uint32_t) cur->data[i]) << (byte_off * 8));
p.mem_be[off / 32] |= (1 << (off % 32));
p.mem_valid |= (1 << (off / (SEG_WIDTH / 8)));
}
uint64_t seg_addr = cur->ram_addr / data_byte_width;
size_t seg_addr_bits = 12;
// iterate over the address bit by bit
for (size_t i = 0; i < seg_addr_bits; i++) {
uint32_t bit = ((seg_addr >> i) & 0x1);
// iterate over the segments
for (size_t j = 0; j < SEG_COUNT; j++) {
size_t dst_bit = j * seg_addr_bits + i;
p.mem_addr[dst_bit / 32] |= (bit << (dst_bit % 32));
}
}
}
}
void MemWriter::op_issue(DMAOp *op)
{
std::cerr << "enqueued write to " << op->ram_addr << std::endl;
pending.push_back(op);
}
#ifndef DMA_H_
#define DMA_H_
#include <deque>
#include "Vinterface.h"
#include "verilated.h"
class DMAOp;
struct MemReadPort {
/* outputs to memory */
vluint8_t &mem_sel;
vluint32_t (&mem_addr)[3];
vluint8_t &mem_valid;
vluint8_t &mem_resready;
/* inputs from memory */
vluint32_t (&mem_data)[32];
vluint8_t &mem_ready;
vluint8_t &mem_resvalid; /* for read only */
MemReadPort(vluint8_t &mem_sel_, vluint32_t (&mem_addr_)[3],
vluint8_t &mem_valid_, vluint8_t &mem_resready_,
vluint32_t (&mem_data_)[32], vluint8_t &mem_ready_,
vluint8_t &mem_resvalid_)
: mem_sel(mem_sel_), mem_addr(mem_addr_), mem_valid(mem_valid_),
mem_resready(mem_resready_), mem_data(mem_data_), mem_ready(mem_ready_),
mem_resvalid(mem_resvalid_)
{
}
};
struct MemWritePort {
/* outputs to memory */
vluint8_t &mem_sel;
vluint32_t (&mem_be)[4]; /* for write only */
vluint32_t (&mem_addr)[3];
vluint32_t (&mem_data)[32];
vluint8_t &mem_valid;
/* inputs from memory */
vluint8_t &mem_ready;
MemWritePort(vluint8_t &mem_sel_, vluint32_t (&mem_be_)[4],
vluint32_t (&mem_addr_)[3], vluint32_t (&mem_data_)[32],
vluint8_t &mem_valid_, vluint8_t &mem_ready_)
: mem_sel(mem_sel_), mem_be(mem_be_), mem_addr(mem_addr_),
mem_data(mem_data_), mem_valid(mem_valid_), mem_ready(mem_ready_)
{
}
};
class MemReader {
protected:
MemReadPort &p;
public:
MemReader(MemReadPort &p_)
: p(p_)
{
}
};
class MemWriter {
protected:
MemWritePort &p;
std::deque<DMAOp *> pending;
DMAOp *cur;
size_t cur_off;
public:
MemWriter(MemWritePort &p_)
: p(p_), cur(0), cur_off(0)
{
}
void step();
void op_issue(DMAOp *op);
};
#endif /* ndef MEM_H_ */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment