"...resnet50_tensorflow.git" did not exist on "5ceb3acfc48843f260bac9a8afae5f90c5409eed"
Commit 7f503244 authored by Hejing Li's avatar Hejing Li
Browse files

Merge branch 'master' into experiments

parents a002814c e18f4b7b
......@@ -569,6 +569,9 @@ static void poll_h2d(MMIOInterface &mmio)
h2d_writecomp(&msg->writecomp);
break;
case COSIM_PCIE_PROTO_H2D_MSG_DEVCTRL:
break;
case COSIM_PCIE_PROTO_H2D_MSG_SYNC:
break;
......
......@@ -164,8 +164,8 @@ class ExpEnv(object):
self.repodir = os.path.abspath(repo_path)
self.workdir = os.path.abspath(workdir)
self.cpdir = os.path.abspath(cpdir)
self.qemu_img_path = self.repodir + '/qemu/qemu-img'
self.qemu_path = self.repodir + '/qemu/x86_64-softmmu/qemu-system-x86_64'
self.qemu_img_path = self.repodir + '/qemu/build/qemu-img'
self.qemu_path = self.repodir + '/qemu/build/x86_64-softmmu/qemu-system-x86_64'
self.qemu_kernel_path = self.repodir + '/images/bzImage'
self.gem5_path = self.repodir + '/gem5/build/X86/gem5.opt'
self.gem5_py_path = self.repodir + '/gem5/configs/cosim/cosim.py'
......
......@@ -61,6 +61,7 @@ class NetSim(Simulator):
class QemuHost(HostSim):
sync = False
def resreq_cores(self):
return self.node_config.cores + 1
......@@ -74,8 +75,8 @@ class QemuHost(HostSim):
f'{env.hdcopy_path(self)}']
def run_cmd(self, env):
cmd = (f'{env.qemu_path} -machine q35 -cpu host -serial mon:stdio '
'-display none -enable-kvm -nic none '
cmd = (f'{env.qemu_path} -machine q35 -serial mon:stdio '
'-display none -nic none '
f'-kernel {env.qemu_kernel_path} '
f'-drive file={env.hdcopy_path(self)},if=ide,index=0,media=disk '
f'-drive file={env.cfgtar_path(self)},if=ide,index=1,media=disk,'
......@@ -83,11 +84,18 @@ class QemuHost(HostSim):
'-append "earlyprintk=ttyS0 console=ttyS0 root=/dev/sda1 '
'init=/home/ubuntu/guestinit.sh rw" '
f'-m {self.node_config.memory} -smp {self.node_config.cores} ')
if self.sync:
cmd += ' -cpu Skylake-Server -icount shift=0,sleep=off '
else:
cmd += ' -cpu host -enable-kvm '
if len(self.nics) > 0:
assert len(self.nics) == 1
cmd += f'-chardev socket,path={env.nic_pci_path(self.nics[0])},'
cmd += 'id=cosimcd '
cmd += '-device cosim-pci,chardev=cosimcd '
sync_onoff = 'on' if self.sync else 'off'
cmd += f'-device cosim-pci,chardev=cosimcd,sync={sync_onoff} '
return cmd
class Gem5Host(HostSim):
......@@ -122,6 +130,7 @@ class Gem5Host(HostSim):
f'--disk-image={env.hd_raw_path(self.node_config.disk_image)} '
f'--disk-image={env.cfgtar_path(self)} '
f'--cpu-type={cpu_type} --mem-size={self.node_config.memory}MB '
f'--num-cpus={self.node_config.cores} '
'--ddio-enabled --ddio-way-part=8 --mem-type=DDR4_2400_16x4 ')
if env.restore_cp:
......
import modes.experiments as exp
import modes.simulators as sim
import modes.nodeconfig as node
host_configs = ['bm', 'cycle']
seq_configs = ['swseq', 'ehseq']
experiments = []
for host_config in host_configs:
for seq_config in seq_configs:
e = exp.Experiment('nopaxos-' + host_config + '-' + seq_config)
net = sim.NS3SequencerNet()
e.add_network(net)
if host_config == 'bm':
host_class = sim.QemuHost
nic_class = sim.CorundumBMNIC
nc_class = node.CorundumLinuxNode
elif host_config == 'cycle':
host_class = sim.Gem5Host
nic_class = sim.CorundumVerilatorNIC
nc_class = node.CorundumLinuxNode
else:
raise NameError(host_config)
nc_class.disk_image = 'nopaxos'
if seq_config == 'ehseq':
sequencer = sim.create_basic_hosts(e, 1, 'sequencer', net, nic_class,
host_class, nc_class, node.NOPaxosSequencer, ip_start = 100)
sequencer[0].sleep = 1
replicas = sim.create_basic_hosts(e, 3, 'replica', net, nic_class,
host_class, nc_class, node.NOPaxosReplica)
for i in range(len(replicas)):
replicas[i].node_config.app.index = i
replicas[i].sleep = 1
clients = sim.create_basic_hosts(e, 1, 'client', net, nic_class,
host_class, nc_class, node.NOPaxosClient, ip_start = 4)
for c in clients:
c.node_config.app.server_ips = ['10.0.0.1', '10.0.0.2', '10.0.0.3']
c.wait = True
experiments.append(e)
import modes.experiments as exp
import modes.simulators as sim
import modes.nodeconfig as node
class NOPaxosNodeConfig(node.CorundumLinuxNode):
disk_image = 'nopaxos'
config = ['swseq', 'ehseq']
experiments = []
for c in config:
e = exp.Experiment('qemu-nopaxos-' + c)
net = sim.NS3SequencerNet()
e.add_network(net)
if c == 'ehseq':
sequencer = sim.create_basic_hosts(e, 1, 'sequencer', net, sim.CorundumBMNIC,
sim.QemuHost, NOPaxosNodeConfig, node.NOPaxosSequencer, ip_start = 100)
sequencer[0].sleep = 1
replicas = sim.create_basic_hosts(e, 3, 'replica', net, sim.CorundumBMNIC,
sim.QemuHost, NOPaxosNodeConfig, node.NOPaxosReplica)
for i in range(len(replicas)):
replicas[i].node_config.app.index = i
replicas[i].sleep = 1
clients = sim.create_basic_hosts(e, 1, 'client', net, sim.CorundumBMNIC,
sim.QemuHost, NOPaxosNodeConfig, node.NOPaxosClient, ip_start = 4)
for c in clients:
c.node_config.app.server_ips = ['10.0.0.1', '10.0.0.2', '10.0.0.3']
c.wait = True
experiments.append(e)
import modes.experiments as exp
import modes.simulators as sim
import modes.nodeconfig as node
host_configs = ['bm', 'cycle']
n_clients = [1, 2, 4, 8]
target_bandwidth = 100
experiments = []
for host_config in host_configs:
for nc in n_clients:
e = exp.Experiment('scalability-' + host_config + '-' + str(nc))
if host_config == 'bm':
host_class = sim.QemuHost
nic_class = sim.CorundumBMNIC
nc_class = node.CorundumLinuxNode
net = sim.SwitchNet()
elif host_config == 'cycle':
host_class = sim.Gem5Host
nic_class = sim.CorundumVerilatorNIC
nc_class = node.CorundumLinuxNode
net = sim.NS3BridgeNet()
else:
raise NameError(host_config)
e.add_network(net)
servers = sim.create_basic_hosts(e, 1, 'server', net, nic_class, host_class,
nc_class, node.IperfUDPServer)
clients = sim.create_basic_hosts(e, nc, 'client', net, nic_class, host_class,
nc_class, node.IperfUDPClient)
for c in clients:
c.wait = True
c.node_config.app.server_ip = servers[0].node_config.ip
c.node_config.app.rate = str(target_bandwidth/nc)+'m'
experiments.append(e)
#pragma once
#include <stdint.h>
namespace headers {
/******************************************************************************/
/* Ethernet */
#define ETH_ADDR_LEN 6
#define ETH_TYPE_IP 0x0800
#define ETH_TYPE_ARP 0x0806
struct eth_addr {
uint8_t addr[ETH_ADDR_LEN];
} __attribute__ ((packed));
struct eth_hdr {
struct eth_addr dest;
struct eth_addr src;
uint16_t type;
} __attribute__ ((packed));
/******************************************************************************/
/* IPv4 */
#define IPH_V(hdr) ((hdr)->_v_hl >> 4)
#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f)
#define IPH_TOS(hdr) ((hdr)->_tos)
#define IPH_ECN(hdr) ((hdr)->_tos & 0x3)
#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (((v) << 4) | (hl))
#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos)
#define IPH_ECN_SET(hdr, e) (hdr)->_tos = ((hdr)->_tos & 0xffc) | (e)
#define IP_HLEN 20
#define IP_PROTO_IP 0
#define IP_PROTO_ICMP 1
#define IP_PROTO_IGMP 2
#define IP_PROTO_IPENCAP 4
#define IP_PROTO_UDP 17
#define IP_PROTO_UDPLITE 136
#define IP_PROTO_TCP 6
#define IP_PROTO_DCCP 33
#define IP_ECN_NONE 0x0
#define IP_ECN_ECT0 0x2
#define IP_ECN_ECT1 0x1
#define IP_ECN_CE 0x3
struct ip_hdr {
/* version / header length */
uint8_t _v_hl;
/* type of service */
uint8_t _tos;
/* total length */
uint16_t len;
/* identification */
uint16_t id;
/* fragment offset field */
uint16_t offset;
/* time to live */
uint8_t ttl;
/* protocol*/
uint8_t proto;
/* checksum */
uint16_t chksum;
/* source and destination IP addresses */
uint32_t src;
uint32_t dest;
} __attribute__ ((packed));
/******************************************************************************/
/* ARP */
#define ARP_OPER_REQUEST 1
#define ARP_OPER_REPLY 2
#define ARP_HTYPE_ETHERNET 1
#define ARP_PTYPE_IPV4 0x0800
struct arp_hdr {
uint16_t htype;
uint16_t ptype;
uint8_t hlen;
uint8_t plen;
uint16_t oper;
struct eth_addr sha;
uint32_t spa;
struct eth_addr tha;
uint32_t tpa;
} __attribute__((packed));
/******************************************************************************/
/* TCP */
#define TCP_FIN 0x01U
#define TCP_SYN 0x02U
#define TCP_RST 0x04U
#define TCP_PSH 0x08U
#define TCP_ACK 0x10U
#define TCP_URG 0x20U
#define TCP_ECE 0x40U
#define TCP_CWR 0x80U
#define TCP_NS 0x100U
#define TCP_FLAGS 0x1ffU
/* Length of the TCP header, excluding options. */
#define TCP_HLEN 20
#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((uint16_t)(~(uint16_t)(TCP_FLAGS)))) | htons(flags))
#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags))
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
struct tcp_hdr {
uint16_t src;
uint16_t dest;
uint32_t seqno;
uint32_t ackno;
uint16_t _hdrlen_rsvd_flags;
uint16_t wnd;
uint16_t chksum;
uint16_t urgp;
} __attribute__((packed));
/******************************************************************************/
/* UDP */
struct udp_hdr {
uint16_t src;
uint16_t dest;
uint16_t len;
uint16_t chksum;
} __attribute__((packed));
/******************************************************************************/
/* whole packets */
struct pkt_arp {
struct eth_hdr eth;
struct arp_hdr arp;
} __attribute__ ((packed));
struct pkt_ip {
struct eth_hdr eth;
struct ip_hdr ip;
} __attribute__ ((packed));
struct pkt_tcp {
struct eth_hdr eth;
struct ip_hdr ip;
struct tcp_hdr tcp;
} __attribute__ ((packed));
struct pkt_udp {
struct eth_hdr eth;
struct ip_hdr ip;
struct udp_hdr udp;
} __attribute__ ((packed));
} // namespace headers
......@@ -29,12 +29,24 @@ void i40e_bm::setup_intro(struct cosim_pcie_proto_dev_intro &di)
di.bars[BAR_REGS].flags = COSIM_PCIE_PROTO_BAR_64;
di.bars[BAR_IO].len = 32;
di.bars[BAR_IO].flags = COSIM_PCIE_PROTO_BAR_IO;
di.bars[BAR_MSIX].len = 32 * 1024;
di.bars[BAR_MSIX].flags = COSIM_PCIE_PROTO_BAR_64 |
COSIM_PCIE_PROTO_BAR_DUMMY;
di.pci_vendor_id = I40E_INTEL_VENDOR_ID;
di.pci_device_id = I40E_DEV_ID_QSFP_A;
di.pci_class = 0x02;
di.pci_subclass = 0x00;
di.pci_revision = 0x01;
di.pci_msi_nvecs = 32;
di.pci_msix_nvecs = 0x80;
di.pci_msix_table_bar = BAR_MSIX;
di.pci_msix_pba_bar = BAR_MSIX;
di.pci_msix_table_offset = 0x0;
di.pci_msix_pba_offset = 0x1000;
di.psi_msix_cap_offset = 0x70;
}
void i40e_bm::dma_complete(nicbm::DMAOp &op)
......@@ -195,6 +207,18 @@ uint32_t i40e_bm::reg_mem_read32(uint64_t addr)
addr <= I40E_PFQF_HLUT(I40E_PFQF_HLUT_MAX_INDEX))
{
val = regs.pfqf_hlut[(addr - I40E_PFQF_HLUT(0)) / 128];
} else if (addr >= I40E_PFINT_ITRN(0, 0) &&
addr <= I40E_PFINT_ITRN(0, NUM_PFINTS - 1))
{
val = regs.pfint_itrn[0][(addr - I40E_PFINT_ITRN(0, 0)) / 4];
} else if (addr >= I40E_PFINT_ITRN(1, 0) &&
addr <= I40E_PFINT_ITRN(1, NUM_PFINTS - 1))
{
val = regs.pfint_itrn[1][(addr - I40E_PFINT_ITRN(1, 0)) / 4];
} else if (addr >= I40E_PFINT_ITRN(2, 0) &&
addr <= I40E_PFINT_ITRN(2, NUM_PFINTS - 1))
{
val = regs.pfint_itrn[2][(addr - I40E_PFINT_ITRN(2, 0)) / 4];
} else {
switch (addr) {
......@@ -249,6 +273,10 @@ uint32_t i40e_bm::reg_mem_read32(uint64_t addr)
regs.pfint_icr0 = 0;
break;
case I40E_PFINT_STAT_CTL0:
val = regs.pfint_stat_ctl0;
break;
case I40E_PFINT_DYN_CTL0:
val = regs.pfint_dyn_ctl0;
break;
......@@ -504,6 +532,18 @@ void i40e_bm::reg_mem_write32(uint64_t addr, uint32_t val)
addr <= I40E_PFQF_HLUT(I40E_PFQF_HLUT_MAX_INDEX))
{
regs.pfqf_hlut[(addr - I40E_PFQF_HLUT(0)) / 128] = val;
} else if (addr >= I40E_PFINT_ITRN(0, 0) &&
addr <= I40E_PFINT_ITRN(0, NUM_PFINTS - 1))
{
regs.pfint_itrn[0][(addr - I40E_PFINT_ITRN(0, 0)) / 4] = val;
} else if (addr >= I40E_PFINT_ITRN(1, 0) &&
addr <= I40E_PFINT_ITRN(1, NUM_PFINTS - 1))
{
regs.pfint_itrn[1][(addr - I40E_PFINT_ITRN(1, 0)) / 4] = val;
} else if (addr >= I40E_PFINT_ITRN(2, 0) &&
addr <= I40E_PFINT_ITRN(2, NUM_PFINTS - 1))
{
regs.pfint_itrn[2][(addr - I40E_PFINT_ITRN(2, 0)) / 4] = val;
} else {
switch (addr) {
case I40E_PFGEN_CTRL:
......@@ -543,6 +583,9 @@ void i40e_bm::reg_mem_write32(uint64_t addr, uint32_t val)
case I40E_PFINT_ICR0:
regs.pfint_icr0 = val;
break;
case I40E_PFINT_STAT_CTL0:
regs.pfint_stat_ctl0 = val;
break;
case I40E_PFINT_DYN_CTL0:
regs.pfint_dyn_ctl0 = val;
break;
......@@ -659,22 +702,28 @@ void i40e_bm::timed_event(nicbm::TimedEvent &ev)
logger::endl;
#endif
iev.armed = false;
runner->msi_issue(0);
}
void i40e_bm::signal_interrupt(uint16_t vector, uint8_t itr)
{
if (vector != 0) {
log << "signal_interrupt() only supports vector 0" << logger::endl;
if (int_msix_en) {
runner->msix_issue(iev.vector);
} else if (iev.vector > 0) {
log << "timed_event: MSI-X disabled, but vector != 0" << logger::endl;
abort();
} else {
runner->msi_issue(0);
}
}
void i40e_bm::signal_interrupt(uint16_t vector, uint8_t itr)
{
int_ev &iev = intevs[vector];
uint64_t mindelay;
if (itr <= 2) {
// itr 0-2
mindelay = regs.pfint_itr0[itr];
if (vector == 0)
mindelay = regs.pfint_itr0[itr];
else
mindelay = regs.pfint_itrn[itr][vector];
mindelay *= 2000000ULL;
} else if (itr == 3) {
// noitr
......
......@@ -474,9 +474,10 @@ protected:
static const unsigned BAR_REGS = 0;
static const unsigned BAR_IO = 2;
static const unsigned BAR_MSIX = 3;
static const uint32_t NUM_QUEUES = 1536;
static const uint32_t NUM_PFINTS = 512;
static const uint32_t NUM_PFINTS = 128;
static const uint32_t NUM_VSIS = 384;
static const uint16_t MAX_MTU = 2048;
static const uint8_t NUM_ITR = 3;
......@@ -489,7 +490,9 @@ protected:
uint32_t pfint_icr0_ena;
uint32_t pfint_icr0;
uint32_t pfint_itr0[NUM_ITR];
uint32_t pfint_itrn[NUM_ITR][NUM_PFINTS];
uint32_t pfint_stat_ctl0;
uint32_t pfint_dyn_ctl0;
uint32_t pfint_dyn_ctln[NUM_PFINTS - 1];
uint32_t pfint_lnklstn[NUM_PFINTS - 1];
......
......@@ -194,15 +194,10 @@ void lan_queue_base::interrupt()
#endif
uint16_t msix_idx = (qctl & I40E_QINT_TQCTL_MSIX_INDX_MASK) >>
I40E_QINT_TQCTL_ITR_INDX_SHIFT;
I40E_QINT_TQCTL_MSIX_INDX_SHIFT;
uint8_t msix0_idx = (qctl & I40E_QINT_TQCTL_MSIX0_INDX_MASK) >>
I40E_QINT_TQCTL_MSIX0_INDX_SHIFT;
if (msix_idx != 0) {
log << "TODO: only int 0 is supported" << logger::endl;
abort();
}
bool cause_ena = !!(qctl & I40E_QINT_TQCTL_CAUSE_ENA_MASK) &&
!!(gctl & I40E_PFINT_DYN_CTL0_INTENA_MASK);
if (!cause_ena) {
......@@ -212,16 +207,17 @@ void lan_queue_base::interrupt()
return;
}
// TODO throttling?
if (msix_idx == 0) {
#ifdef DEBUG_LAN
log << " setting int0.qidx=" << msix0_idx << logger::endl;
log << " setting int0.qidx=" << msix0_idx << logger::endl;
#endif
lanmgr.dev.regs.pfint_icr0 |= I40E_PFINT_ICR0_INTEVENT_MASK |
(1 << (I40E_PFINT_ICR0_QUEUE_0_SHIFT + msix0_idx));
lanmgr.dev.regs.pfint_icr0 |= I40E_PFINT_ICR0_INTEVENT_MASK |
(1 << (I40E_PFINT_ICR0_QUEUE_0_SHIFT + msix0_idx));
}
uint8_t itr = (qctl & I40E_QINT_TQCTL_ITR_INDX_MASK) >>
I40E_QINT_TQCTL_ITR_INDX_SHIFT;
lanmgr.dev.signal_interrupt(0, itr);
lanmgr.dev.signal_interrupt(msix_idx, itr);
}
......
#include "i40e_bm.h"
using namespace i40e;
rss_key_cache::rss_key_cache(const uint32_t (&key_)[key_len / 4])
: key(key_)
{
cache_dirty = true;
}
void rss_key_cache::build()
{
const uint8_t *k = reinterpret_cast<const uint8_t *> (&key);
uint32_t result = (((uint32_t)k[0]) << 24) |
(((uint32_t)k[1]) << 16) |
(((uint32_t)k[2]) << 8) |
((uint32_t)k[3]);
uint32_t idx = 32;
size_t i;
for (i = 0; i < cache_len; i++, idx++) {
uint8_t shift = (idx % 8);
uint32_t bit;
cache[i] = result;
bit = ((k[idx / 8] << shift) & 0x80) ? 1 : 0;
result = ((result << 1) | bit);
}
cache_dirty = false;
}
void rss_key_cache::set_dirty()
{
cache_dirty = true;
}
uint32_t rss_key_cache::hash_ipv4(uint32_t sip, uint32_t dip, uint16_t sp,
uint16_t dp)
{
static const uint32_t MSB32 = 0x80000000;
static const uint32_t MSB16 = 0x8000;
uint32_t res = 0;
int i;
if (cache_dirty)
build();
for (i = 0; i < 32; i++) {
if (sip & MSB32)
res ^= cache[i];
sip <<= 1;
}
for (i = 0; i < 32; i++) {
if (dip & MSB32)
res ^= cache[32+i];
dip <<= 1;
}
for (i = 0; i < 16; i++) {
if (sp & MSB16)
res ^= cache[64+i];
sp <<= 1;
}
for (i = 0; i < 16; i++) {
if (dp & MSB16)
res ^= cache[80+i];
dp <<= 1;
}
return res;
}
#if 0
int main(int argc, char *argv[])
{
static const uint8_t key[] = {
0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
uint32_t kregs[13];
key_cache kc(kregs);
memcpy(kregs, key, sizeof(key));
kc.set_dirty();
printf("%x\n", kc.hash_ipv4(0x420995bb, 0xa18e6450, 2794, 1766));
printf("%x\n", kc.hash_ipv4(0x420995bb, 0xa18e6450, 0, 0));
return 0;
}
#endif
......@@ -9,7 +9,7 @@ TAS_IMAGE := output-tas/tas
IMAGES := $(BASE_IMAGE) $(NOPAXOS_IMAGE) $(MTCP_IMAGE) $(TAS_IMAGE)
RAW_IMAGES := $(addsuffix .raw,$(IMAGES))
QEMU_IMG := ../qemu/qemu-img
QEMU_IMG := ../qemu/build/qemu-img
all: $(IMAGES) $(RAW_IMAGES) vmlinux bzImage mqnic/mqnic.ko
......
#include <set>
#include <deque>
extern "C" {
#include <nicsim.h>
}
namespace nicbm {
#include <cassert>
extern "C" {
#include <nicsim.h>
}
static const size_t MAX_DMA_LEN = 2048;
......@@ -36,6 +36,11 @@ class TimedEvent {
class Runner {
public:
class Device {
protected:
bool int_intx_en;
bool int_msi_en;
bool int_msix_en;
public:
/**
* Initialize device specific parameters (pci dev/vendor id,
......@@ -74,6 +79,12 @@ class Runner {
* A timed event is due.
*/
virtual void timed_event(TimedEvent &ev);
/**
* Device control update
*/
virtual void devctrl_update(
struct cosim_pcie_proto_h2d_devctrl &devctrl);
};
protected:
......@@ -99,6 +110,7 @@ class Runner {
void h2d_write(volatile struct cosim_pcie_proto_h2d_write *write);
void h2d_readcomp(volatile struct cosim_pcie_proto_h2d_readcomp *rc);
void h2d_writecomp(volatile struct cosim_pcie_proto_h2d_writecomp *wc);
void h2d_devctrl(volatile struct cosim_pcie_proto_h2d_devctrl *dc);
void poll_h2d();
void eth_recv(volatile struct cosim_eth_proto_n2d_recv *recv);
......@@ -118,6 +130,7 @@ class Runner {
/* these three are for `Runner::Device`. */
void issue_dma(DMAOp &op);
void msi_issue(uint8_t vec);
void msix_issue(uint8_t vec);
void eth_send(const void *data, size_t len);
void event_schedule(TimedEvent &evt);
......
......@@ -144,6 +144,21 @@ void Runner::msi_issue(uint8_t vec)
COSIM_PCIE_PROTO_D2H_OWN_HOST;
}
void Runner::msix_issue(uint8_t vec)
{
volatile union cosim_pcie_proto_d2h *msg = d2h_alloc();
#ifdef DEBUG_NICBM
printf("nicbm: issue MSI-X interrupt vec %u\n", vec);
#endif
volatile struct cosim_pcie_proto_d2h_interrupt *intr = &msg->interrupt;
intr->vector = vec;
intr->inttype = COSIM_PCIE_PROTO_INT_MSIX;
// WMB();
intr->own_type = COSIM_PCIE_PROTO_D2H_MSG_INTERRUPT |
COSIM_PCIE_PROTO_D2H_OWN_HOST;
}
void Runner::event_schedule(TimedEvent &evt)
{
events.insert(&evt);
......@@ -230,6 +245,11 @@ void Runner::h2d_writecomp(volatile struct cosim_pcie_proto_h2d_writecomp *wc)
dma_trigger();
}
void Runner::h2d_devctrl(volatile struct cosim_pcie_proto_h2d_devctrl *dc)
{
dev.devctrl_update(*(struct cosim_pcie_proto_h2d_devctrl *) dc);
}
void Runner::eth_recv(volatile struct cosim_eth_proto_n2d_recv *recv)
{
#ifdef DEBUG_NICBM
......@@ -281,6 +301,10 @@ void Runner::poll_h2d()
h2d_writecomp(&msg->writecomp);
break;
case COSIM_PCIE_PROTO_H2D_MSG_DEVCTRL:
h2d_devctrl(&msg->devctrl);
break;
case COSIM_PCIE_PROTO_H2D_MSG_SYNC:
break;
......@@ -437,3 +461,11 @@ int Runner::runMain(int argc, char *argv[])
void Runner::Device::timed_event(TimedEvent &te)
{
}
void Runner::Device::devctrl_update(
struct cosim_pcie_proto_h2d_devctrl &devctrl)
{
int_intx_en = devctrl.flags & COSIM_PCIE_PROTO_CTRL_INTX_EN;
int_msi_en = devctrl.flags & COSIM_PCIE_PROTO_CTRL_MSI_EN;
int_msix_en = devctrl.flags & COSIM_PCIE_PROTO_CTRL_MSIX_EN;
}
......@@ -22,6 +22,9 @@
#define COSIM_PCIE_PROTO_BAR_64 (1 << 1)
/** in bars.flags: this memory bar is prefetchable */
#define COSIM_PCIE_PROTO_BAR_PF (1 << 2)
/** in bars.flags: this memory bar is a dummy bar (device doesn't get MMIO
* messages for this, but it dose get exposed to software. used for MSI-X). */
#define COSIM_PCIE_PROTO_BAR_DUMMY (1 << 3)
/**
* welcome message sent by device to host. This message comes with the shared
......@@ -63,8 +66,22 @@ struct cosim_pcie_proto_dev_intro {
uint8_t pci_subclass;
/* PCI revision */
uint8_t pci_revision;
/* PCI number of MSI vectors */
uint8_t pci_msi_nvecs;
/* PCI number of MSI-X vectors */
uint16_t pci_msix_nvecs;
/* BAR number for MSI-X table */
uint8_t pci_msix_table_bar;
/* BAR number for MSI-X PBA */
uint8_t pci_msix_pba_bar;
/* Offset for MSI-X table */
uint32_t pci_msix_table_offset;
/* Offset for MSI-X PBA */
uint32_t pci_msix_pba_offset;
/* MSI-X capability offset */
uint16_t psi_msix_cap_offset;
} __attribute__((packed));
......@@ -196,6 +213,7 @@ COSIM_PCI_MSG_SZCHECK(union cosim_pcie_proto_d2h);
#define COSIM_PCIE_PROTO_H2D_MSG_WRITE 0x3
#define COSIM_PCIE_PROTO_H2D_MSG_READCOMP 0x4
#define COSIM_PCIE_PROTO_H2D_MSG_WRITECOMP 0x5
#define COSIM_PCIE_PROTO_H2D_MSG_DEVCTRL 0x7
struct cosim_pcie_proto_h2d_dummy {
uint8_t pad[48];
......@@ -257,6 +275,18 @@ struct cosim_pcie_proto_h2d_writecomp {
} __attribute__((packed));
COSIM_PCI_MSG_SZCHECK(struct cosim_pcie_proto_h2d_writecomp);
#define COSIM_PCIE_PROTO_CTRL_INTX_EN (1 << 0)
#define COSIM_PCIE_PROTO_CTRL_MSI_EN (1 << 1)
#define COSIM_PCIE_PROTO_CTRL_MSIX_EN (1 << 2)
struct cosim_pcie_proto_h2d_devctrl {
uint64_t flags;
uint8_t pad[40];
uint64_t timestamp;
uint8_t pad_[7];
uint8_t own_type;
} __attribute__((packed));
COSIM_PCI_MSG_SZCHECK(struct cosim_pcie_proto_h2d_devctrl);
union cosim_pcie_proto_h2d {
struct cosim_pcie_proto_h2d_dummy dummy;
struct cosim_pcie_proto_h2d_sync sync;
......@@ -264,6 +294,7 @@ union cosim_pcie_proto_h2d {
struct cosim_pcie_proto_h2d_write write;
struct cosim_pcie_proto_h2d_readcomp readcomp;
struct cosim_pcie_proto_h2d_writecomp writecomp;
struct cosim_pcie_proto_h2d_devctrl devctrl;
} __attribute__((packed));
COSIM_PCI_MSG_SZCHECK(union cosim_pcie_proto_h2d);
......
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