Commit d7e300bd authored by Antoine Kaufmann's avatar Antoine Kaufmann
Browse files

corundum: checkpoint

parent 3db9ec7d
#ifndef COORD_H_
#define COORD_H_
#include <deque>
#include <map>
#include <iostream>
#include "debug.h"
class DMAOp;
void pci_dma_issue(DMAOp *op);
void pci_msi_issue(uint8_t vec);
class PCICoordinator {
protected:
struct PCIOp {
union {
DMAOp *dma_op;
uint32_t msi_vec;
};
bool isDma;
bool ready;
};
std::deque<PCIOp *> queue;
std::map<DMAOp *, PCIOp *> dmamap;
void process()
{
PCIOp *op;
while (!queue.empty()) {
op = queue.front();
if (!op->ready)
break;
queue.pop_front();
if (!op->isDma) {
#ifdef COORD_DEBUG
std::cout << "issuing msi " << op->msi_vec << std::endl;
#endif
pci_msi_issue(op->msi_vec);
} else {
#ifdef COORD_DEBUG
std::cout << "issuing dma " << op->dma_op << std::endl;
#endif
pci_dma_issue(op->dma_op);
dmamap.erase(op->dma_op);
}
delete op;
}
}
public:
void dma_register(DMAOp *dma_op, bool ready)
{
#ifdef COORD_DEBUG
std::cout << "registering dma op " << dma_op << " " << ready << std::endl;
#endif
PCIOp *op = new PCIOp;
op->dma_op = dma_op;
op->isDma = true;
op->ready = ready;
queue.push_back(op);
dmamap[dma_op] = op;
process();
}
void dma_mark_ready(DMAOp *op)
{
#ifdef COORD_DEBUG
std::cout << "readying dma op " << op << std::endl;
#endif
dmamap[op]->ready = true;
process();
}
void msi_enqueue(uint32_t vec)
{
#ifdef COORD_DEBUG
std::cout << "enqueuing MSI " << vec << std::endl;
#endif
PCIOp *op = new PCIOp;
op->msi_vec = vec;
op->isDma = false;
op->ready = true;
queue.push_back(op);
process();
}
};
#endif
......@@ -11,7 +11,9 @@ extern "C" {
#include "verilated.h"
#include "verilated_vcd_c.h"
#include "debug.h"
#include "corundum.h"
#include "coord.h"
#include "dma.h"
#include "mem.h"
......@@ -408,6 +410,7 @@ void pci_dma_issue(DMAOp *op)
pci_dma_pending.insert(op);
}
static void h2d_readcomp(volatile struct cosim_pcie_proto_h2d_readcomp *rc)
{
DMAOp *op = (DMAOp *) (uintptr_t) rc->req_id;
......@@ -591,11 +594,13 @@ class EthernetTx {
send->own_type = COSIM_ETH_PROTO_D2N_MSG_SEND |
COSIM_ETH_PROTO_D2N_OWN_NET;
#ifdef ETH_DEBUG
std::cerr << "EthernetTx: packet len=" << std::hex << packet_len << " ";
for (size_t i = 0; i < packet_len; i++) {
std::cerr << (unsigned) packet_buf[i] << " ";
}
std::cerr << std::endl;
#endif
}
void step()
......@@ -643,11 +648,13 @@ class EthernetRx {
packet_len = len;
memcpy(packet_buf, data, len);
#ifdef ETH_DEBUG
std::cerr << "EthernetRx: packet len=" << std::hex << packet_len << " ";
for (size_t i = 0; i < packet_len; i++) {
std::cerr << (unsigned) packet_buf[i] << " ";
}
std::cerr << std::endl;
#endif
}
void step()
......@@ -656,18 +663,24 @@ class EthernetRx {
// we have data to send
if (packet_off != 0 && !top.rx_axis_tready) {
// no ready signal, can't advance
std::cerr << "eth rx: no ready" << std::endl;
} else if (packet_off == packet_len) {
// done with packet
#ifdef ETH_DEBUG
std::cerr << "EthernetRx: finished packet" << std::endl;
#endif
top.rx_axis_tvalid = 0;
top.rx_axis_tlast = 0;
packet_off = packet_len = 0;
} else {
// put out more packet data
#ifdef ETH_DEBUG
std::cerr << "EthernetRx: push flit " << packet_off << std::endl;
#endif
top.rx_axis_tkeep = 0;
top.rx_axis_tdata = 0;
for (size_t i = 0; i < 8 && packet_off < packet_len; i++) {
size_t i;
for (i = 0; i < 8 && packet_off < packet_len; i++) {
top.rx_axis_tdata |=
((uint64_t) packet_buf[packet_off]) << (i * 8);
top.rx_axis_tkeep |= (1 << i);
......@@ -714,12 +727,89 @@ static void poll_n2d(EthernetRx &rx)
nicif_n2d_next();
}
static void msi_issue(uint8_t vec)
#if 0
class PCICoordinator {
protected:
struct PCIOp {
union {
DMAOp *dma_op;
uint32_t msi_vec;
};
bool isDma;
bool ready;
};
Vinterface &top;
std::deque<PCIOp *> queue;
std::map<DMAOp *, PCIOp *> dmamap;
void process()
{
PCIOp *op;
while (queue.empty()) {
op = queue.front();
if (!op->ready)
break;
queue.pop_front();
if (!op->isDma) {
pci_msi_issue(op->msi_vec);
delete op;
} else {
pci_dma_issue(op->dma_op);
dmamap.erase(op->dma_op);
delete op;
}
}
}
public:
PCICoordinator(Vinterface &top_)
: top(top_)
{
}
void dma_register(DMAOp *dma_op, bool ready)
{
PCIOp *op = new PCIOp;
op->dma_op = vec;
op->isDma = true;
op->ready = ready;
queue.push_back(op);
dmamap[op] = dma_op;
process();
}
void dma_mark_ready(DMAOp *op)
{
dmamap[op]->ready = true;
process();
}
void msi_enqueue(uint32_t vec)
{
PCIOp *op = new PCIOp;
op->msi_vec = vec;
op->isDma = false;
op->ready = true;
queue.push_back(op);
process();
}
};
#endif
void pci_msi_issue(uint8_t vec)
{
volatile union cosim_pcie_proto_d2h *msg = nicsim_d2h_alloc();
volatile struct cosim_pcie_proto_d2h_interrupt *intr;
#ifdef MSI_DEBUG
std::cerr << "MSI interrupt vec=" << (int) vec << std::endl;
#endif
intr = &msg->interrupt;
intr->vector = vec;
......@@ -730,16 +820,19 @@ static void msi_issue(uint8_t vec)
COSIM_PCIE_PROTO_D2H_OWN_HOST;
}
static void msi_step(Vinterface &top)
static void msi_step(Vinterface &top, PCICoordinator &coord)
{
if (!top.msi_irq)
return;
#ifdef MSI_DEBUG
std::cerr << "msi_step: MSI interrupt raw vec=" << (int) top.msi_irq << std::endl;
#endif
for (size_t i = 0; i < 32; i++) {
if (!((1ULL << i) & top.msi_irq))
continue;
msi_issue(i);
coord.msi_enqueue(i);
}
}
......@@ -884,10 +977,11 @@ int main(int argc, char *argv[])
MemWriter mem_data_writer(p_mem_write_data_dma);
MemReader mem_data_reader(p_mem_read_data_dma);
DMAReader dma_read_ctrl("read ctrl", p_dma_read_ctrl, mem_control_writer);
DMAWriter dma_write_ctrl("write ctrl", p_dma_write_ctrl, mem_control_reader);
DMAReader dma_read_data("read data", p_dma_read_data, mem_data_writer);
DMAWriter dma_write_data("write data", p_dma_write_data, mem_data_reader);
PCICoordinator pci_coord;
DMAReader dma_read_ctrl("read ctrl", p_dma_read_ctrl, mem_control_writer, pci_coord);
DMAWriter dma_write_ctrl("write ctrl", p_dma_write_ctrl, mem_control_reader, pci_coord);
DMAReader dma_read_data("read data", p_dma_read_data, mem_data_writer, pci_coord);
DMAWriter dma_write_data("write data", p_dma_write_data, mem_data_reader, pci_coord);
EthernetTx tx(*top);
EthernetRx rx(*top);
......@@ -930,7 +1024,7 @@ int main(int argc, char *argv[])
tx.step();
rx.step();
msi_step(*top);
msi_step(*top, pci_coord);
/* raising edge */
top->clk = !top->clk;
......
//#define COORD_DEBUG 1
//#define ETH_DEBUG 1
//#define MSI_DEBUG 1
//#define DMA_DEBUG 1
//#define MEM_DEBUG 1
#include <iostream>
#include "debug.h"
#include "corundum.h"
#include "dma.h"
#include "mem.h"
void DMAReader::step()
{
p.dma_ready = 1;
......@@ -17,11 +19,14 @@ void DMAReader::step()
op->tag = p.dma_tag;
op->write = false;
pending.insert(op);
/*std::cout << "dma[" << label << "] op " << op->dma_addr << " -> " <<
#ifdef DMA_DEBUG
std::cout << "dma[" << label << "] op " << op->dma_addr << " -> " <<
op->ram_sel << ":" << op->ram_addr <<
" len=" << op->len << " tag=" << (int) op->tag << std::endl;*/
" len=" << op->len << " tag=" << (int) op->tag << std::endl;
#endif
pci_dma_issue(op);
coord.dma_register(op, true);
}
p.dma_status_valid = 0;
......@@ -64,10 +69,14 @@ void DMAWriter::step()
op->tag = p.dma_tag;
op->write = true;
pending.insert(op);
#ifdef DMA_DEBUG
std::cout << "dma write [" << label << "] op " << op->dma_addr << " -> " <<
op->ram_sel << ":" << op->ram_addr <<
" len=" << op->len << " tag=" << (int) op->tag << std::endl;
#endif
coord.dma_register(op, false);
mr.op_issue(op);
}
......@@ -76,7 +85,9 @@ void DMAWriter::step()
DMAOp *op = completed.front();
completed.pop_front();
#ifdef DMA_DEBUG
std::cout << "dma write [" << label << "] status complete " << op->dma_addr << std::endl;
#endif
p.dma_status_valid = 1;
p.dma_status_tag = op->tag;
......@@ -87,12 +98,16 @@ void DMAWriter::step()
void DMAWriter::pci_op_complete(DMAOp *op)
{
#ifdef DMA_DEBUG
std::cout << "dma write [" << label << "] pci complete " << op->dma_addr << std::endl;
#endif
completed.push_back(op);
}
void DMAWriter::mem_op_complete(DMAOp *op)
{
#ifdef DMA_DEBUG
std::cout << "dma write [" << label << "] mem complete " << op->dma_addr << std::endl;
pci_dma_issue(op);
#endif
coord.dma_mark_ready(op);
}
......@@ -7,6 +7,9 @@
#include "Vinterface.h"
#include "verilated.h"
#include "debug.h"
#include "coord.h"
#define MAX_DMA_LEN 2048
class DMAEngine;
......@@ -56,9 +59,10 @@ struct DMAOp {
class DMAEngine {
protected:
DMAPorts &p;
PCICoordinator &coord;
DMAEngine(DMAPorts &p_)
: p(p_) { }
DMAEngine(DMAPorts &p_, PCICoordinator &coord_)
: p(p_), coord(coord_) { }
public:
virtual void pci_op_complete(DMAOp *op) = 0;
......@@ -73,8 +77,9 @@ class DMAReader : public DMAEngine {
MemWriter &mw;
public:
DMAReader(const char *label_, DMAPorts &p_, MemWriter &mw_)
: DMAEngine(p_), label(label_), mw(mw_)
DMAReader(const char *label_, DMAPorts &p_, MemWriter &mw_,
PCICoordinator &coord_)
: DMAEngine(p_, coord_), label(label_), mw(mw_)
{
}
......@@ -91,8 +96,9 @@ class DMAWriter : public DMAEngine {
MemReader &mr;
public:
DMAWriter(const char *label_, DMAPorts &p_, MemReader &mr_)
: DMAEngine(p_), label(label_), mr(mr_)
DMAWriter(const char *label_, DMAPorts &p_, MemReader &mr_,
PCICoordinator &coord_)
: DMAEngine(p_, coord_), label(label_), mr(mr_)
{
}
......
#include <iostream>
#include "debug.h"
#include "mem.h"
#include "dma.h"
......@@ -49,6 +50,8 @@ void MemWriter::step()
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;
for (size_t i = 0; i < data_byte_width / 4; i++)
p.mem_data[i] = 0;
/* put data bytes in the right places */
......@@ -57,9 +60,6 @@ void MemWriter::step()
data_byte_width - data_offset : cur->len - cur_off);
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)));
......@@ -96,7 +96,9 @@ void MemReader::step()
size_t data_byte_width = DATA_WIDTH / 8;
if (cur && p.mem_resvalid) {
#ifdef MEM_DEBUG
std::cerr << "completed read from: " << std::hex << cur->ram_addr << std::endl;
#endif
p.mem_valid = 0;
/*for (size_t i = 0; i < 32; i++)
std::cerr << " val = " << p.mem_data[i] << std::endl;*/
......@@ -118,11 +120,12 @@ void MemReader::step()
cur = 0;
} else if (!cur && !pending.empty()) {
cur = pending.front();
size_t data_offset = (cur->ram_addr + cur_off) % data_byte_width;
#ifdef MEM_DEBUG
std::cerr << "issuing read from " << std::hex << cur->ram_addr << std::endl;
size_t data_offset = (cur->ram_addr + cur_off) % data_byte_width;
std::cerr << " off=" << data_offset << std::endl;
#endif
/*if (cur->len > data_byte_width - data_offset) {
std::cerr << "MemReader::step: cannot be written in one cycle TODO" << std::endl;
......@@ -168,6 +171,8 @@ void MemReader::step()
void MemReader::op_issue(DMAOp *op)
{
#ifdef MEM_DEBUG
std::cerr << "enqueued read from " << op->ram_addr << std::endl;
#endif
pending.push_back(op);
}
......@@ -103,7 +103,7 @@ module interface #
// Log desc block size field width
parameter LOG_BLOCK_SIZE_WIDTH = 2, /* this one is not explicitly set */
// Enable PTP timestamping
parameter PTP_TS_ENABLE = 1,
parameter PTP_TS_ENABLE = 0,
// PTP timestamp width
parameter PTP_TS_WIDTH = 96,
// Enable TX checksum offload
......
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