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