Commit 5201df73 authored by Jialin Li's avatar Jialin Li
Browse files

Merge branch 'corundum-bm'

parents 521ce665 a01d9bb1
corundum_bm
tester
CPPFLAGS += -I../nicsim_common/include -I../netsim_common/include -I../proto
CFLAGS += -Wall -Wextra -Wno-unused-parameter -O3
all: corundum_bm tester
corundum.o: corundum.cc
g++ $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
corundum_bm: corundum_bm.o ../nicsim_common/libnicsim_common.a
g++ $^ -o $@
tester: tester.o ../nicsim_common/libnicsim_common.a
clean:
rm -f *.o corundum_bm tester
This diff is collapsed.
#pragma once
#include <stdint.h>
typedef uint32_t reg_t;
typedef uint64_t addr_t;
typedef uint16_t ptr_t;
#define REG_FW_ID 0x0000
#define REG_FW_VER 0x0004
#define REG_BOARD_ID 0x0008
#define REG_BOARD_VER 0x000C
#define REG_PHC_COUNT 0x0010
#define REG_PHC_OFFSET 0x0014
#define REG_PHC_STRIDE 0x0018
#define REG_IF_COUNT 0x0020
#define REG_IF_STRIDE 0x0024
#define REG_IF_CSR_OFFSET 0x002C
#define IF_FEATURE_RSS (1 << 0)
#define IF_FEATURE_PTP_TS (1 << 4)
#define IF_FEATURE_TX_CSUM (1 << 8)
#define IF_FEATURE_RX_CSUM (1 << 9)
#define IF_FEATURE_RX_HASH (1 << 10)
#define PHC_REG_FEATURES 0x0200
#define PHC_REG_PTP_CUR_SEC_L 0x0218
#define PHC_REG_PTP_CUR_SEC_H 0x021C
#define PHC_REG_PTP_SET_FNS 0x0230
#define PHC_REG_PTP_SET_NS 0x0234
#define PHC_REG_PTP_SET_SEC_L 0x0238
#define PHC_REG_PTP_SET_SEC_H 0x023C
#define IF_REG_IF_ID 0x80000
#define IF_REG_IF_FEATURES 0x80004
#define IF_REG_EVENT_QUEUE_COUNT 0x80010
#define IF_REG_EVENT_QUEUE_OFFSET 0x80014
#define IF_REG_TX_QUEUE_COUNT 0x80020
#define IF_REG_TX_QUEUE_OFFSET 0x80024
#define IF_REG_TX_CPL_QUEUE_COUNT 0x80028
#define IF_REG_TX_CPL_QUEUE_OFFSET 0x8002C
#define IF_REG_RX_QUEUE_COUNT 0x80030
#define IF_REG_RX_QUEUE_OFFSET 0x80034
#define IF_REG_RX_CPL_QUEUE_COUNT 0x80038
#define IF_REG_RX_CPL_QUEUE_OFFSET 0x8003C
#define IF_REG_PORT_COUNT 0x80040
#define IF_REG_PORT_OFFSET 0x80044
#define IF_REG_PORT_STRIDE 0x80048
#define QUEUE_ACTIVE_MASK 0x80000000
#define QUEUE_ARM_MASK 0x80000000
#define QUEUE_CONT_MASK 0x40000000
#define EVENT_QUEUE_BASE_ADDR_REG 0x100000
#define EVENT_QUEUE_ACTIVE_LOG_SIZE_REG 0x100008
#define EVENT_QUEUE_INTERRUPT_INDEX_REG 0x10000C
#define EVENT_QUEUE_HEAD_PTR_REG 0x100010
#define EVENT_QUEUE_TAIL_PTR_REG 0x100018
#define TX_QUEUE_BASE_ADDR_REG 0x200000
#define TX_QUEUE_ACTIVE_LOG_SIZE_REG 0x200008
#define TX_QUEUE_CPL_QUEUE_INDEX_REG 0x20000C
#define TX_QUEUE_HEAD_PTR_REG 0x200010
#define TX_QUEUE_TAIL_PTR_REG 0x200018
#define TX_CPL_QUEUE_BASE_ADDR_REG 0x400000
#define TX_CPL_QUEUE_ACTIVE_LOG_SIZE_REG 0x400008
#define TX_CPL_QUEUE_INTERRUPT_INDEX_REG 0x40000C
#define TX_CPL_QUEUE_HEAD_PTR_REG 0x400010
#define TX_CPL_QUEUE_TAIL_PTR_REG 0x400018
#define RX_QUEUE_BASE_ADDR_REG 0x600000
#define RX_QUEUE_ACTIVE_LOG_SIZE_REG 0x600008
#define RX_QUEUE_CPL_QUEUE_INDEX_REG 0x60000C
#define RX_QUEUE_HEAD_PTR_REG 0x600010
#define RX_QUEUE_TAIL_PTR_REG 0x600018
#define RX_CPL_QUEUE_BASE_ADDR_REG 0x700000
#define RX_CPL_QUEUE_ACTIVE_LOG_SIZE_REG 0x700008
#define RX_CPL_QUEUE_INTERRUPT_INDEX_REG 0x70000C
#define RX_CPL_QUEUE_HEAD_PTR_REG 0x700010
#define RX_CPL_QUEUE_TAIL_PTR_REG 0x700018
#define PORT_REG_PORT_ID 0x800000
#define PORT_REG_PORT_FEATURES 0x800004
#define PORT_REG_PORT_MTU 0x800008
#define PORT_REG_SCHED_COUNT 0x800010
#define PORT_REG_SCHED_OFFSET 0x800014
#define PORT_REG_SCHED_STRIDE 0x800018
#define PORT_REG_SCHED_TYPE 0x80001C
#define PORT_REG_SCHED_ENABLE 0x800040
#define PORT_REG_RSS_MASK 0x800080
#define PORT_QUEUE_ENABLE 0x900000
namespace corundum {
#define DESC_SIZE 16
#define CPL_SIZE 32
#define EVENT_SIZE 32
#define MAX_DMA_LEN 2048
class DescRing;
struct Desc {
uint16_t rsvd0;
uint16_t tx_csum_cmd;
uint32_t len;
uint64_t addr;
} __attribute__((packed)) ;
struct Cpl {
uint16_t queue;
uint16_t index;
uint16_t len;
uint16_t rsvd0;
uint32_t ts_ns;
uint16_t ts_s;
uint16_t rx_csum;
uint32_t rx_hash;
uint8_t rx_hash_type;
uint8_t rsvd1;
uint8_t rsvd2;
uint8_t rsvd3;
uint32_t rsvd4;
uint32_t rsvd5;
} __attribute__((packed)) ;
#define EVENT_TYPE_TX_CPL 0x0000
#define EVENT_TYPE_RX_CPL 0x0001
struct Event {
uint16_t type;
uint16_t source;
} __attribute__((packed)) ;
struct RxData {
size_t len;
uint8_t data[MAX_DMA_LEN];
};
#define DMA_TYPE_DESC 0
#define DMA_TYPE_MEM 1
#define DMA_TYPE_TX_CPL 2
#define DMA_TYPE_RX_CPL 3
#define DMA_TYPE_EVENT 4
struct DMAOp {
uint8_t type;
addr_t dma_addr;
size_t len;
DescRing *ring;
RxData *rx_data;
uint64_t tag;
bool write;
uint8_t data[MAX_DMA_LEN];
};
class DescRing {
public:
DescRing();
~DescRing();
addr_t dmaAddr();
size_t sizeLog();
unsigned index();
ptr_t headPtr();
ptr_t tailPtr();
void setDMALower(uint32_t addr);
void setDMAUpper(uint32_t addr);
void setSizeLog(size_t size_log);
void setIndex(unsigned index);
virtual void setHeadPtr(ptr_t ptr);
void setTailPtr(ptr_t ptr);
virtual void dmaDone(DMAOp *op) = 0;
protected:
bool empty();
bool full();
addr_t _dmaAddr;
size_t _sizeLog;
size_t _size;
size_t _sizeMask;
unsigned _index;
ptr_t _headPtr;
ptr_t _tailPtr;
ptr_t _currHead;
ptr_t _currTail;
bool active;
};
class EventRing : public DescRing {
public:
EventRing();
~EventRing();
virtual void dmaDone(DMAOp *op) override;
void issueEvent(unsigned type, unsigned source);
};
class CplRing : public DescRing {
public:
CplRing(EventRing *eventRing);
~CplRing();
virtual void dmaDone(DMAOp *op) override;
void complete(unsigned index, size_t len, bool tx);
private:
EventRing *eventRing;
};
class TxRing : public DescRing {
public:
TxRing(CplRing *cplRing);
~TxRing();
virtual void setHeadPtr(ptr_t ptr) override;
virtual void dmaDone(DMAOp *op) override;
private:
CplRing *txCplRing;
};
class RxRing : public DescRing {
public:
RxRing(CplRing *cplRing);
~RxRing();
virtual void dmaDone(DMAOp *op) override;
void rx(RxData *rx_data);
private:
CplRing *rxCplRing;
};
class Port {
public:
Port();
~Port();
unsigned id();
unsigned features();
size_t mtu();
size_t schedCount();
addr_t schedOffset();
addr_t schedStride();
unsigned schedType();
unsigned rssMask();
void setId(unsigned id);
void setFeatures(unsigned features);
void setMtu(size_t mtu);
void setSchedCount(size_t count);
void setSchedOffset(addr_t offset);
void setSchedStride(addr_t stride);
void setSchedType(unsigned type);
void setRssMask(unsigned mask);
void schedEnable();
void schedDisable();
void queueEnable();
void queueDisable();
private:
unsigned _id;
unsigned _features;
size_t _mtu;
size_t _schedCount;
addr_t _schedOffset;
addr_t _schedStride;
unsigned _schedType;
unsigned _rssMask;
bool _schedEnable;
bool _queueEnable;
};
class Corundum {
public:
Corundum();
~Corundum();
reg_t readReg(addr_t addr);
void writeReg(addr_t addr, reg_t val);
void rx(uint8_t port, RxData *rx_data);
private:
EventRing eventRing;
TxRing txRing;
CplRing txCplRing;
RxRing rxRing;
CplRing rxCplRing;
Port port;
};
} // namespace corundum
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <assert.h>
#include <nicsim.h>
#include <cosim_pcie_proto.h>
static uint8_t *d2h_queue;
static size_t d2h_pos;
static size_t d2h_elen;
static size_t d2h_enum;
static uint8_t *h2d_queue;
static size_t h2d_pos;
static size_t h2d_elen;
static size_t h2d_enum;
static void sigint_handler(int dummy)
{
exit(1);
}
static int uxsocket_init()
{
int cfd;
if ((cfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
return -1;
}
struct sockaddr_un saun;
memset(&saun, 0, sizeof(saun));
saun.sun_family = AF_UNIX;
memcpy(saun.sun_path, "/tmp/cosim-pci", strlen("/tmp/cosim-pci"));
if (connect(cfd, (struct sockaddr *)&saun, sizeof(saun)) == -1) {
close(cfd);
return -1;
}
return cfd;
}
static int queue_create(const struct cosim_pcie_proto_dev_intro di)
{
int fd = -1;
if ((fd = open("/dev/shm/dummy_nic_shm", O_RDWR)) == -1) {
perror("Failed to open shm file");
goto error;
}
void *addr;
if ((addr = mmap(NULL, 32 * 1024 * 1024, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, fd, 0)) == (void *)-1) {
perror("mmap failed");
goto error;
}
d2h_queue = (uint8_t *)addr + di.d2h_offset;
d2h_pos = 0;
d2h_elen = di.d2h_elen;
d2h_enum = di.d2h_nentries;
h2d_queue = (uint8_t *)addr + di.h2d_offset;
h2d_pos = 0;
h2d_elen = di.h2d_elen;
h2d_enum = di.h2d_nentries;
return 0;
error:
if (fd > 0) {
close(fd);
}
return -1;
}
volatile union cosim_pcie_proto_h2d *h2d_alloc()
{
volatile union cosim_pcie_proto_h2d *msg =
(volatile union cosim_pcie_proto_h2d *)
(h2d_queue + h2d_pos * h2d_elen);
if ((msg->dummy.own_type & COSIM_PCIE_PROTO_H2D_OWN_MASK) !=
COSIM_PCIE_PROTO_H2D_OWN_HOST) {
fprintf(stderr, "cosim: failed to allocate h2d message\n");
exit(1);
}
h2d_pos = (h2d_pos + 1) % h2d_enum;
return msg;
}
volatile union cosim_pcie_proto_d2h *d2h_poll()
{
volatile union cosim_pcie_proto_d2h *msg;
msg = (volatile union cosim_pcie_proto_d2h *)
(d2h_queue + d2h_pos * d2h_elen);
if ((msg->dummy.own_type & COSIM_PCIE_PROTO_D2H_OWN_MASK) ==
COSIM_PCIE_PROTO_D2H_OWN_DEV) {
return NULL;
}
return msg;
}
void d2h_done(volatile union cosim_pcie_proto_d2h *msg)
{
msg->dummy.own_type = (msg->dummy.own_type & COSIM_PCIE_PROTO_D2H_MSG_MASK) |
COSIM_PCIE_PROTO_D2H_OWN_DEV;
d2h_pos = (d2h_pos + 1) % d2h_enum;
}
static void dev_read(uint64_t offset, uint16_t len)
{
volatile union cosim_pcie_proto_h2d *h2d_msg = h2d_alloc();
volatile struct cosim_pcie_proto_h2d_read *read = &h2d_msg->read;
read->req_id = 0xF;
read->offset = offset;
read->len = len;
read->bar = 0;
read->own_type = COSIM_PCIE_PROTO_H2D_MSG_READ | COSIM_PCIE_PROTO_H2D_OWN_DEV;
volatile union cosim_pcie_proto_d2h *d2h_msg = NULL;
while (d2h_msg == NULL) {
d2h_msg = d2h_poll();
}
volatile struct cosim_pcie_proto_d2h_readcomp *rc;
rc = &d2h_msg->readcomp;
assert(rc->req_id == 0xF);
printf("received readcomp with data ");
for (int i = 0; i < read->len; i++) {
printf("%x ", ((const uint8_t *)rc->data)[i]);
}
printf("\n");
d2h_done(d2h_msg);
}
int main(int argc, char *argv[])
{
signal(SIGINT, sigint_handler);
int cfd;
if ((cfd = uxsocket_init()) < 0) {
fprintf(stderr, "Failed to open unix socket\n");
return -1;
}
struct cosim_pcie_proto_dev_intro di;
if (recv(cfd, &di, sizeof(di), 0) != sizeof(di)) {
perror("Failed to receive dev_intro");
close(cfd);
return -1;
}
if (queue_create(di) != 0) {
fprintf(stderr, "Failed to create shm queues\n");
close(cfd);
return -1;
}
struct cosim_pcie_proto_host_intro hi;
hi.flags = COSIM_PCIE_PROTO_FLAGS_HI_SYNC;
if (send(cfd, &hi, sizeof(hi), 0) != sizeof(hi)) {
perror("Failed to send host_intro");
close(cfd);
return -1;
}
while (1) {
int op_type;
uint64_t offset;
uint16_t len;
printf("op type (0-read): ");
scanf("%d", &op_type);
printf("offset: ");
scanf("%lx", &offset);
printf("len: ");
scanf("%hu", &len);
switch (op_type) {
case 0:
dev_read(offset, len);
break;
default:
fprintf(stderr, "Unimplemented type %u\n", op_type);
}
}
close(cfd);
return 0;
}
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