Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ycai
simbricks
Commits
d4666c97
Commit
d4666c97
authored
Feb 13, 2021
by
Antoine Kaufmann
Browse files
Reformat closer to google style
parent
eb125a88
Changes
41
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
3402 additions
and
3685 deletions
+3402
-3685
lib/simbricks/netif/netsim.c
lib/simbricks/netif/netsim.c
+124
-133
lib/simbricks/netif/netsim.h
lib/simbricks/netif/netsim.h
+22
-23
lib/simbricks/netif/utils.c
lib/simbricks/netif/utils.c
+65
-68
lib/simbricks/nicbm/nicbm.cc
lib/simbricks/nicbm/nicbm.cc
+320
-345
lib/simbricks/nicbm/nicbm.h
lib/simbricks/nicbm/nicbm.h
+132
-137
lib/simbricks/nicif/nicsim.c
lib/simbricks/nicif/nicsim.c
+303
-333
lib/simbricks/nicif/nicsim.h
lib/simbricks/nicif/nicsim.h
+16
-17
lib/simbricks/nicif/utils.c
lib/simbricks/nicif/utils.c
+84
-88
lib/simbricks/proto/network.h
lib/simbricks/proto/network.h
+53
-56
lib/simbricks/proto/pcie.h
lib/simbricks/proto/pcie.h
+146
-149
sims/net/switch/net_switch.cc
sims/net/switch/net_switch.cc
+146
-150
sims/net/tap/net_tap.c
sims/net/tap/net_tap.c
+89
-95
sims/net/wire/net_wire.c
sims/net/wire/net_wire.c
+129
-135
sims/nic/corundum/coord.h
sims/nic/corundum/coord.h
+81
-90
sims/nic/corundum/corundum_verilator.cc
sims/nic/corundum/corundum_verilator.cc
+791
-845
sims/nic/corundum/dma.cc
sims/nic/corundum/dma.cc
+78
-87
sims/nic/corundum/dma.h
sims/nic/corundum/dma.h
+77
-80
sims/nic/corundum/mem.cc
sims/nic/corundum/mem.cc
+131
-140
sims/nic/corundum/mem.h
sims/nic/corundum/mem.h
+65
-63
sims/nic/corundum_bm/corundum_bm.cc
sims/nic/corundum_bm/corundum_bm.cc
+550
-651
No files found.
lib/simbricks/netif/netsim.c
View file @
d4666c97
...
...
@@ -22,183 +22,174 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <unistd.h>
#include <simbricks/netif/netsim.h>
#include "lib/simbricks/netif/internal.h"
static
uint64_t
current_epoch
=
0
;
int
netsim_init
(
struct
netsim_interface
*
nsif
,
const
char
*
eth_socket_path
,
int
*
sync_eth
)
{
struct
cosim_eth_proto_dev_intro
di
;
struct
cosim_eth_proto_net_intro
ni
;
int
cfd
,
shm_fd
;
void
*
p
;
if
((
cfd
=
uxsocket_connect
(
eth_socket_path
))
<
0
)
{
return
-
1
;
}
memset
(
&
ni
,
0
,
sizeof
(
ni
));
if
(
*
sync_eth
)
ni
.
flags
|=
COSIM_ETH_PROTO_FLAGS_NI_SYNC
;
if
(
send
(
cfd
,
&
ni
,
sizeof
(
ni
),
0
)
!=
sizeof
(
ni
))
{
perror
(
"sending net intro failed"
);
return
-
1
;
}
if
(
uxsocket_recv
(
cfd
,
&
di
,
sizeof
(
di
),
&
shm_fd
))
{
return
-
1
;
}
if
((
p
=
shm_map
(
shm_fd
))
==
NULL
)
{
return
-
1
;
}
close
(
shm_fd
);
if
((
di
.
flags
&
COSIM_ETH_PROTO_FLAGS_DI_SYNC
)
==
0
)
{
*
sync_eth
=
0
;
nsif
->
sync
=
0
;
}
else
{
nsif
->
sync
=
*
sync_eth
;
}
nsif
->
d2n_queue
=
(
uint8_t
*
)
p
+
di
.
d2n_offset
;
nsif
->
n2d_queue
=
(
uint8_t
*
)
p
+
di
.
n2d_offset
;
nsif
->
d2n_elen
=
di
.
d2n_elen
;
nsif
->
n2d_elen
=
di
.
n2d_elen
;
nsif
->
d2n_enum
=
di
.
d2n_nentries
;
nsif
->
n2d_enum
=
di
.
n2d_nentries
;
nsif
->
d2n_pos
=
nsif
->
n2d_pos
=
0
;
nsif
->
d2n_timestamp
=
nsif
->
n2d_timestamp
=
0
;
return
0
;
int
netsim_init
(
struct
netsim_interface
*
nsif
,
const
char
*
eth_socket_path
,
int
*
sync_eth
)
{
struct
cosim_eth_proto_dev_intro
di
;
struct
cosim_eth_proto_net_intro
ni
;
int
cfd
,
shm_fd
;
void
*
p
;
if
((
cfd
=
uxsocket_connect
(
eth_socket_path
))
<
0
)
{
return
-
1
;
}
memset
(
&
ni
,
0
,
sizeof
(
ni
));
if
(
*
sync_eth
)
ni
.
flags
|=
COSIM_ETH_PROTO_FLAGS_NI_SYNC
;
if
(
send
(
cfd
,
&
ni
,
sizeof
(
ni
),
0
)
!=
sizeof
(
ni
))
{
perror
(
"sending net intro failed"
);
return
-
1
;
}
if
(
uxsocket_recv
(
cfd
,
&
di
,
sizeof
(
di
),
&
shm_fd
))
{
return
-
1
;
}
if
((
p
=
shm_map
(
shm_fd
))
==
NULL
)
{
return
-
1
;
}
close
(
shm_fd
);
if
((
di
.
flags
&
COSIM_ETH_PROTO_FLAGS_DI_SYNC
)
==
0
)
{
*
sync_eth
=
0
;
nsif
->
sync
=
0
;
}
else
{
nsif
->
sync
=
*
sync_eth
;
}
nsif
->
d2n_queue
=
(
uint8_t
*
)
p
+
di
.
d2n_offset
;
nsif
->
n2d_queue
=
(
uint8_t
*
)
p
+
di
.
n2d_offset
;
nsif
->
d2n_elen
=
di
.
d2n_elen
;
nsif
->
n2d_elen
=
di
.
n2d_elen
;
nsif
->
d2n_enum
=
di
.
d2n_nentries
;
nsif
->
n2d_enum
=
di
.
n2d_nentries
;
nsif
->
d2n_pos
=
nsif
->
n2d_pos
=
0
;
nsif
->
d2n_timestamp
=
nsif
->
n2d_timestamp
=
0
;
return
0
;
}
void
netsim_cleanup
(
struct
netsim_interface
*
nsif
)
{
fprintf
(
stderr
,
"netsim_cleanup: TODO
\n
"
);
abort
();
void
netsim_cleanup
(
struct
netsim_interface
*
nsif
)
{
fprintf
(
stderr
,
"netsim_cleanup: TODO
\n
"
);
abort
();
}
volatile
union
cosim_eth_proto_d2n
*
netsim_d2n_poll
(
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
)
{
volatile
union
cosim_eth_proto_d2n
*
msg
=
(
volatile
union
cosim_eth_proto_d2n
*
)
(
nsif
->
d2n_queue
+
nsif
->
d2n_pos
*
nsif
->
d2n_elen
);
/* message not ready */
if
((
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_OWN_MASK
)
!=
COSIM_ETH_PROTO_D2N_OWN_NET
)
return
NULL
;
/* if in sync mode, wait till message is ready */
nsif
->
d2n_timestamp
=
msg
->
dummy
.
timestamp
;
if
(
nsif
->
sync
&&
nsif
->
d2n_timestamp
>
timestamp
)
return
NULL
;
nsif
->
d2n_pos
=
(
nsif
->
d2n_pos
+
1
)
%
nsif
->
d2n_enum
;
return
msg
;
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
)
{
volatile
union
cosim_eth_proto_d2n
*
msg
=
(
volatile
union
cosim_eth_proto_d2n
*
)(
nsif
->
d2n_queue
+
nsif
->
d2n_pos
*
nsif
->
d2n_elen
);
/* message not ready */
if
((
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_OWN_MASK
)
!=
COSIM_ETH_PROTO_D2N_OWN_NET
)
return
NULL
;
/* if in sync mode, wait till message is ready */
nsif
->
d2n_timestamp
=
msg
->
dummy
.
timestamp
;
if
(
nsif
->
sync
&&
nsif
->
d2n_timestamp
>
timestamp
)
return
NULL
;
nsif
->
d2n_pos
=
(
nsif
->
d2n_pos
+
1
)
%
nsif
->
d2n_enum
;
return
msg
;
}
void
netsim_d2n_done
(
struct
netsim_interface
*
nsif
,
volatile
union
cosim_eth_proto_d2n
*
msg
)
{
msg
->
dummy
.
own_type
=
(
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
)
|
COSIM_ETH_PROTO_D2N_OWN_DEV
;
volatile
union
cosim_eth_proto_d2n
*
msg
)
{
msg
->
dummy
.
own_type
=
(
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
)
|
COSIM_ETH_PROTO_D2N_OWN_DEV
;
}
volatile
union
cosim_eth_proto_n2d
*
netsim_n2d_alloc
(
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
uint64_t
latency
)
{
volatile
union
cosim_eth_proto_n2d
*
msg
=
(
volatile
union
cosim_eth_proto_n2d
*
)
(
nsif
->
n2d_queue
+
nsif
->
n2d_pos
*
nsif
->
n2d_elen
);
if
((
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_N2D_OWN_MASK
)
!=
COSIM_ETH_PROTO_N2D_OWN_NET
)
{
return
NULL
;
}
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
uint64_t
latency
)
{
volatile
union
cosim_eth_proto_n2d
*
msg
=
(
volatile
union
cosim_eth_proto_n2d
*
)(
nsif
->
n2d_queue
+
nsif
->
n2d_pos
*
nsif
->
n2d_elen
);
if
((
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_N2D_OWN_MASK
)
!=
COSIM_ETH_PROTO_N2D_OWN_NET
)
{
return
NULL
;
}
msg
->
dummy
.
timestamp
=
timestamp
+
latency
;
nsif
->
n2d_timestamp
=
timestamp
;
msg
->
dummy
.
timestamp
=
timestamp
+
latency
;
nsif
->
n2d_timestamp
=
timestamp
;
nsif
->
n2d_pos
=
(
nsif
->
n2d_pos
+
1
)
%
nsif
->
n2d_enum
;
return
msg
;
nsif
->
n2d_pos
=
(
nsif
->
n2d_pos
+
1
)
%
nsif
->
n2d_enum
;
return
msg
;
}
int
netsim_n2d_sync
(
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
uint64_t
latency
,
uint64_t
sync_delay
,
int
sync_mode
)
{
volatile
union
cosim_eth_proto_n2d
*
msg
;
volatile
struct
cosim_eth_proto_n2d_sync
*
sync
;
int
do_sync
;
uint64_t
latency
,
uint64_t
sync_delay
,
int
sync_mode
)
{
volatile
union
cosim_eth_proto_n2d
*
msg
;
volatile
struct
cosim_eth_proto_n2d_sync
*
sync
;
int
do_sync
;
if
(
!
nsif
->
sync
)
return
0
;
if
(
!
nsif
->
sync
)
return
0
;
switch
(
sync_mode
)
{
switch
(
sync_mode
)
{
case
SYNC_MODES
:
do_sync
=
nsif
->
n2d_timestamp
==
0
||
timestamp
-
nsif
->
n2d_timestamp
>=
sync_delay
;
break
;
do_sync
=
nsif
->
n2d_timestamp
==
0
||
timestamp
-
nsif
->
n2d_timestamp
>=
sync_delay
;
break
;
case
SYNC_BARRIER
:
do_sync
=
current_epoch
==
0
||
timestamp
-
current_epoch
>=
sync_delay
;
break
;
do_sync
=
current_epoch
==
0
||
timestamp
-
current_epoch
>=
sync_delay
;
break
;
default:
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
sync_mode
);
return
0
;
}
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
sync_mode
);
return
0
;
}
if
(
!
do_sync
)
{
return
0
;
}
if
(
!
do_sync
)
{
return
0
;
}
msg
=
netsim_n2d_alloc
(
nsif
,
timestamp
,
latency
);
if
(
msg
==
NULL
)
return
-
1
;
msg
=
netsim_n2d_alloc
(
nsif
,
timestamp
,
latency
);
if
(
msg
==
NULL
)
return
-
1
;
sync
=
&
msg
->
sync
;
// WMB();
sync
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_SYNC
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
sync
=
&
msg
->
sync
;
// WMB();
sync
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_SYNC
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
return
0
;
return
0
;
}
void
netsim_advance_epoch
(
uint64_t
timestamp
,
uint64_t
sync_delay
,
int
sync_mode
)
{
if
(
sync_mode
==
SYNC_BARRIER
)
{
if
(
timestamp
-
current_epoch
>=
sync_delay
)
{
current_epoch
=
timestamp
;
}
int
sync_mode
)
{
if
(
sync_mode
==
SYNC_BARRIER
)
{
if
(
timestamp
-
current_epoch
>=
sync_delay
)
{
current_epoch
=
timestamp
;
}
}
}
uint64_t
netsim_advance_time
(
uint64_t
timestamp
,
uint64_t
sync_delay
,
int
sync_mode
)
{
switch
(
sync_mode
)
{
int
sync_mode
)
{
switch
(
sync_mode
)
{
case
SYNC_MODES
:
return
timestamp
;
return
timestamp
;
case
SYNC_BARRIER
:
return
timestamp
<
current_epoch
+
sync_delay
?
timestamp
:
current_epoch
+
sync_delay
;
return
timestamp
<
current_epoch
+
sync_delay
?
timestamp
:
current_epoch
+
sync_delay
;
default:
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
sync_mode
);
return
timestamp
;
}
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
sync_mode
);
return
timestamp
;
}
}
lib/simbricks/netif/netsim.h
View file @
d4666c97
...
...
@@ -27,48 +27,47 @@
#include <stddef.h>
#include <stdint.h>
#include <simbricks/proto/network.h>
#define SYNC_MODES 0
#define SYNC_BARRIER 1
struct
netsim_interface
{
uint8_t
*
d2n_queue
;
size_t
d2n_pos
;
size_t
d2n_elen
;
size_t
d2n_enum
;
uint64_t
d2n_timestamp
;
uint8_t
*
d2n_queue
;
size_t
d2n_pos
;
size_t
d2n_elen
;
size_t
d2n_enum
;
uint64_t
d2n_timestamp
;
uint8_t
*
n2d_queue
;
size_t
n2d_pos
;
size_t
n2d_elen
;
size_t
n2d_enum
;
uint64_t
n2d_timestamp
;
uint8_t
*
n2d_queue
;
size_t
n2d_pos
;
size_t
n2d_elen
;
size_t
n2d_enum
;
uint64_t
n2d_timestamp
;
int
sync
;
int
sync
;
};
int
netsim_init
(
struct
netsim_interface
*
nsif
,
const
char
*
eth_socket_path
,
int
*
sync_eth
);
int
netsim_init
(
struct
netsim_interface
*
nsif
,
const
char
*
eth_socket_path
,
int
*
sync_eth
);
void
netsim_cleanup
(
struct
netsim_interface
*
nsif
);
volatile
union
cosim_eth_proto_d2n
*
netsim_d2n_poll
(
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
);
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
);
void
netsim_d2n_done
(
struct
netsim_interface
*
nsif
,
volatile
union
cosim_eth_proto_d2n
*
msg
);
static
inline
uint64_t
netsim_d2n_timestamp
(
struct
netsim_interface
*
nsif
)
{
return
nsif
->
d2n_timestamp
;
volatile
union
cosim_eth_proto_d2n
*
msg
);
static
inline
uint64_t
netsim_d2n_timestamp
(
struct
netsim_interface
*
nsif
)
{
return
nsif
->
d2n_timestamp
;
}
volatile
union
cosim_eth_proto_n2d
*
netsim_n2d_alloc
(
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
uint64_t
latency
);
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
uint64_t
latency
);
int
netsim_n2d_sync
(
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
uint64_t
latency
,
uint64_t
sync_delay
,
int
sync_mode
);
uint64_t
latency
,
uint64_t
sync_delay
,
int
sync_mode
);
void
netsim_advance_epoch
(
uint64_t
timestamp
,
uint64_t
sync_delay
,
int
sync_mode
);
int
sync_mode
);
uint64_t
netsim_advance_time
(
uint64_t
timestamp
,
uint64_t
sync_delay
,
int
sync_mode
);
int
sync_mode
);
#endif // SIMBRICKS_NETIF_NETSIM_H_
lib/simbricks/netif/utils.c
View file @
d4666c97
...
...
@@ -24,96 +24,93 @@
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
#include "lib/simbricks/netif/internal.h"
int
uxsocket_connect
(
const
char
*
path
)
{
int
fd
;
struct
sockaddr_un
saun
;
int
uxsocket_connect
(
const
char
*
path
)
{
int
fd
;
struct
sockaddr_un
saun
;
/* prepare and connect socket */
memset
(
&
saun
,
0
,
sizeof
(
saun
));
saun
.
sun_family
=
AF_UNIX
;
strcpy
(
saun
.
sun_path
,
path
);
/* prepare and connect socket */
memset
(
&
saun
,
0
,
sizeof
(
saun
));
saun
.
sun_family
=
AF_UNIX
;
strcpy
(
saun
.
sun_path
,
path
);
if
((
fd
=
socket
(
AF_UNIX
,
SOCK_STREAM
,
0
))
==
-
1
)
{
perror
(
"socket failed"
);
return
-
1
;
}
if
((
fd
=
socket
(
AF_UNIX
,
SOCK_STREAM
,
0
))
==
-
1
)
{
perror
(
"socket failed"
);
return
-
1
;
}
if
(
connect
(
fd
,
(
struct
sockaddr
*
)
&
saun
,
sizeof
(
saun
))
!=
0
)
{
perror
(
"connect failed"
);
return
-
1
;
}
if
(
connect
(
fd
,
(
struct
sockaddr
*
)
&
saun
,
sizeof
(
saun
))
!=
0
)
{
perror
(
"connect failed"
);
return
-
1
;
}
return
fd
;
return
fd
;
}
int
uxsocket_recv
(
int
fd
,
void
*
data
,
size_t
len
,
int
*
pfd
)
{
int
*
ppfd
;
ssize_t
ret
;
struct
cmsghdr
*
cmsg
;
union
{
char
buf
[
CMSG_SPACE
(
sizeof
(
int
))];
struct
cmsghdr
align
;
}
u
;
struct
iovec
iov
=
{
.
iov_base
=
data
,
.
iov_len
=
len
,
};
struct
msghdr
msg
=
{
.
msg_name
=
NULL
,
.
msg_namelen
=
0
,
.
msg_iov
=
&
iov
,
.
msg_iovlen
=
1
,
.
msg_control
=
u
.
buf
,
.
msg_controllen
=
sizeof
(
u
.
buf
),
.
msg_flags
=
0
,
};
int
uxsocket_recv
(
int
fd
,
void
*
data
,
size_t
len
,
int
*
pfd
)
{
int
*
ppfd
;
ssize_t
ret
;
struct
cmsghdr
*
cmsg
;
union
{
char
buf
[
CMSG_SPACE
(
sizeof
(
int
))];
struct
cmsghdr
align
;
}
u
;
struct
iovec
iov
=
{
.
iov_base
=
data
,
.
iov_len
=
len
,
};
struct
msghdr
msg
=
{
.
msg_name
=
NULL
,
.
msg_namelen
=
0
,
.
msg_iov
=
&
iov
,
.
msg_iovlen
=
1
,
.
msg_control
=
u
.
buf
,
.
msg_controllen
=
sizeof
(
u
.
buf
),
.
msg_flags
=
0
,
};
if
((
ret
=
recvmsg
(
fd
,
&
msg
,
0
))
!=
(
ssize_t
)
len
)
{
perror
(
"recvmsg failed"
);
return
-
1
;
}
if
((
ret
=
recvmsg
(
fd
,
&
msg
,
0
))
!=
(
ssize_t
)
len
)
{
perror
(
"recvmsg failed"
);
return
-
1
;
}
cmsg
=
CMSG_FIRSTHDR
(
&
msg
);
ppfd
=
(
int
*
)
CMSG_DATA
(
cmsg
);
if
(
msg
.
msg_controllen
<=
0
||
cmsg
->
cmsg_len
!=
CMSG_LEN
(
sizeof
(
int
)))
{
fprintf
(
stderr
,
"accessing ancillary data failed
\n
"
);
return
-
1
;
}
cmsg
=
CMSG_FIRSTHDR
(
&
msg
);
ppfd
=
(
int
*
)
CMSG_DATA
(
cmsg
);
if
(
msg
.
msg_controllen
<=
0
||
cmsg
->
cmsg_len
!=
CMSG_LEN
(
sizeof
(
int
)))
{
fprintf
(
stderr
,
"accessing ancillary data failed
\n
"
);
return
-
1
;
}
*
pfd
=
*
ppfd
;
return
0
;
*
pfd
=
*
ppfd
;
return
0
;
}
void
*
shm_map
(
int
shm_fd
)
{
void
*
p
;
struct
stat
statbuf
;
void
*
shm_map
(
int
shm_fd
)
{
void
*
p
;
struct
stat
statbuf
;
if
(
fstat
(
shm_fd
,
&
statbuf
)
!=
0
)
{
perror
(
"shm_map: fstat failed"
);
return
NULL
;
}
if
(
fstat
(
shm_fd
,
&
statbuf
)
!=
0
)
{
perror
(
"shm_map: fstat failed"
);
return
NULL
;
}
p
=
mmap
(
NULL
,
statbuf
.
st_size
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
shm_fd
,
0
);
if
(
p
==
MAP_FAILED
)
{
perror
(
"shm_map: mmap failed"
);
return
NULL
;
}
p
=
mmap
(
NULL
,
statbuf
.
st_size
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
shm_fd
,
0
);
if
(
p
==
MAP_FAILED
)
{
perror
(
"shm_map: mmap failed"
);
return
NULL
;
}
return
p
;
return
p
;
}
lib/simbricks/nicbm/nicbm.cc
View file @
d4666c97
This diff is collapsed.
Click to expand it.
lib/simbricks/nicbm/nicbm.h
View file @
d4666c97
...
...
@@ -27,10 +27,11 @@
#include <cassert>
#include <cstring>
#include <set>
#include <deque>
#include <set>
extern
"C"
{
#include <simbricks/nicif/nicsim.h>
#include <simbricks/nicif/nicsim.h>
}
namespace
nicbm
{
...
...
@@ -38,21 +39,22 @@ namespace nicbm {
static
const
size_t
MAX_DMA_LEN
=
2048
;
class
DMAOp
{
public:
virtual
~
DMAOp
()
{
}
bool
write
;
uint64_t
dma_addr
;
size_t
len
;
void
*
data
;
public:
virtual
~
DMAOp
()
{
}
bool
write
;
uint64_t
dma_addr
;
size_t
len
;
void
*
data
;
};
class
TimedEvent
{
public:
virtual
~
TimedEvent
()
{
}
uint64_t
time
;
public:
virtual
~
TimedEvent
()
{
}
uint64_t
time
;
};
/**
* The Runner drives the main simulation loop. It's initialized with a reference
* to a device it should manage, and then once `runMain` is called, it will
...
...
@@ -60,111 +62,107 @@ class TimedEvent {
* device as needed.
* */
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,
* BARs etc. in intro struct.
*/
virtual
void
setup_intro
(
struct
cosim_pcie_proto_dev_intro
&
di
)
=
0
;
/**
* execute a register read from `bar`:`addr` of length `len`.
* Should store result in `dest`.
*/
virtual
void
reg_read
(
uint8_t
bar
,
uint64_t
addr
,
void
*
dest
,
size_t
len
)
=
0
;
/**
* execute a register write to `bar`:`addr` of length `len`,
* with the data in `src`.
*/
virtual
void
reg_write
(
uint8_t
bar
,
uint64_t
addr
,
const
void
*
src
,
size_t
len
)
=
0
;
/**
* the previously issued DMA operation `op` completed.
*/
virtual
void
dma_complete
(
DMAOp
&
op
)
=
0
;
/**
* A packet has arrived on the wire, of length `len` with
* payload `data`.
*/
virtual
void
eth_rx
(
uint8_t
port
,
const
void
*
data
,
size_t
len
)
=
0
;
/**
* 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:
struct
event_cmp
{
bool
operator
()
(
TimedEvent
*
a
,
TimedEvent
*
b
)
{
return
a
->
time
<
b
->
time
;
}
};
Device
&
dev
;
std
::
set
<
TimedEvent
*
,
event_cmp
>
events
;
std
::
deque
<
DMAOp
*>
dma_queue
;
size_t
dma_pending
;
uint64_t
mac_addr
;
struct
nicsim_params
nsparams
;
struct
cosim_pcie_proto_dev_intro
dintro
;
volatile
union
cosim_pcie_proto_d2h
*
d2h_alloc
(
void
);
volatile
union
cosim_eth_proto_d2n
*
d2n_alloc
(
void
);
void
h2d_read
(
volatile
struct
cosim_pcie_proto_h2d_read
*
read
);
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
);
void
poll_n2d
();
bool
event_next
(
uint64_t
&
retval
);
void
event_trigger
();
void
dma_do
(
DMAOp
&
op
);
void
dma_trigger
();
public:
Runner
(
Device
&
dev_
);
/** Run the simulation */
int
runMain
(
int
argc
,
char
*
argv
[]);
/* 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
);
void
event_cancel
(
TimedEvent
&
evt
);
uint64_t
time_ps
()
const
;
uint64_t
get_mac_addr
()
const
;
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,
* BARs etc. in intro struct.
*/
virtual
void
setup_intro
(
struct
cosim_pcie_proto_dev_intro
&
di
)
=
0
;
/**
* execute a register read from `bar`:`addr` of length `len`.
* Should store result in `dest`.
*/
virtual
void
reg_read
(
uint8_t
bar
,
uint64_t
addr
,
void
*
dest
,
size_t
len
)
=
0
;
/**
* execute a register write to `bar`:`addr` of length `len`,
* with the data in `src`.
*/
virtual
void
reg_write
(
uint8_t
bar
,
uint64_t
addr
,
const
void
*
src
,
size_t
len
)
=
0
;
/**
* the previously issued DMA operation `op` completed.
*/
virtual
void
dma_complete
(
DMAOp
&
op
)
=
0
;
/**
* A packet has arrived on the wire, of length `len` with
* payload `data`.
*/
virtual
void
eth_rx
(
uint8_t
port
,
const
void
*
data
,
size_t
len
)
=
0
;
/**
* 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:
struct
event_cmp
{
bool
operator
()(
TimedEvent
*
a
,
TimedEvent
*
b
)
{
return
a
->
time
<
b
->
time
;
}
};
Device
&
dev
;
std
::
set
<
TimedEvent
*
,
event_cmp
>
events
;
std
::
deque
<
DMAOp
*>
dma_queue
;
size_t
dma_pending
;
uint64_t
mac_addr
;
struct
nicsim_params
nsparams
;
struct
cosim_pcie_proto_dev_intro
dintro
;
volatile
union
cosim_pcie_proto_d2h
*
d2h_alloc
(
void
);
volatile
union
cosim_eth_proto_d2n
*
d2n_alloc
(
void
);
void
h2d_read
(
volatile
struct
cosim_pcie_proto_h2d_read
*
read
);
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
);
void
poll_n2d
();
bool
event_next
(
uint64_t
&
retval
);
void
event_trigger
();
void
dma_do
(
DMAOp
&
op
);
void
dma_trigger
();
public:
Runner
(
Device
&
dev_
);
/** Run the simulation */
int
runMain
(
int
argc
,
char
*
argv
[]);
/* 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
);
void
event_cancel
(
TimedEvent
&
evt
);
uint64_t
time_ps
()
const
;
uint64_t
get_mac_addr
()
const
;
};
/**
...
...
@@ -172,26 +170,23 @@ class Runner {
*/
template
<
class
TReg
=
uint32_t
>
class
SimpleDevice
:
public
Runner
::
Device
{
public:
virtual
TReg
reg_read
(
uint8_t
bar
,
uint64_t
addr
)
=
0
;
virtual
void
reg_write
(
uint8_t
bar
,
uint64_t
addr
,
TReg
val
)
=
0
;
virtual
void
reg_read
(
uint8_t
bar
,
uint64_t
addr
,
void
*
dest
,
size_t
len
)
{
assert
(
len
==
sizeof
(
TReg
));
TReg
r
=
reg_read
(
bar
,
addr
);
memcpy
(
dest
,
&
r
,
sizeof
(
r
));
}
virtual
void
reg_write
(
uint8_t
bar
,
uint64_t
addr
,
const
void
*
src
,
size_t
len
)
{
assert
(
len
==
sizeof
(
TReg
));
TReg
r
;
memcpy
(
&
r
,
src
,
sizeof
(
r
));
reg_write
(
bar
,
addr
,
r
);
}
public:
virtual
TReg
reg_read
(
uint8_t
bar
,
uint64_t
addr
)
=
0
;
virtual
void
reg_write
(
uint8_t
bar
,
uint64_t
addr
,
TReg
val
)
=
0
;
virtual
void
reg_read
(
uint8_t
bar
,
uint64_t
addr
,
void
*
dest
,
size_t
len
)
{
assert
(
len
==
sizeof
(
TReg
));
TReg
r
=
reg_read
(
bar
,
addr
);
memcpy
(
dest
,
&
r
,
sizeof
(
r
));
}
virtual
void
reg_write
(
uint8_t
bar
,
uint64_t
addr
,
const
void
*
src
,
size_t
len
)
{
assert
(
len
==
sizeof
(
TReg
));
TReg
r
;
memcpy
(
&
r
,
src
,
sizeof
(
r
));
reg_write
(
bar
,
addr
,
r
);
}
};
}
// namespace nicbm
...
...
lib/simbricks/nicif/nicsim.c
View file @
d4666c97
This diff is collapsed.
Click to expand it.
lib/simbricks/nicif/nicsim.h
View file @
d4666c97
...
...
@@ -25,28 +25,28 @@
#ifndef SIMBRICKS_NICIF_NICSIM_H_
#define SIMBRICKS_NICIF_NICSIM_H_
#include <simbricks/proto/pcie.h>
#include <simbricks/proto/network.h>
#include <simbricks/proto/pcie.h>
#define SYNC_MODES 0 // ModES style synchronization
#define SYNC_BARRIER 1 // Global barrier style synchronization
struct
nicsim_params
{
const
char
*
pci_socket_path
;
const
char
*
eth_socket_path
;
const
char
*
shm_path
;
const
char
*
pci_socket_path
;
const
char
*
eth_socket_path
;
const
char
*
shm_path
;
uint64_t
pci_latency
;
uint64_t
eth_latency
;
uint64_t
sync_delay
;
uint64_t
pci_latency
;
uint64_t
eth_latency
;
uint64_t
sync_delay
;
int
sync_pci
;
int
sync_eth
;
int
sync_mode
;
int
sync_pci
;
int
sync_eth
;
int
sync_mode
;
};
int
nicsim_init
(
struct
nicsim_params
*
params
,
struct
cosim_pcie_proto_dev_intro
*
di
);
struct
cosim_pcie_proto_dev_intro
*
di
);
void
nicsim_cleanup
(
void
);
int
nicsim_sync
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
);
...
...
@@ -55,20 +55,19 @@ uint64_t nicsim_advance_time(struct nicsim_params *params, uint64_t timestamp);
uint64_t
nicsim_next_timestamp
(
struct
nicsim_params
*
params
);
volatile
union
cosim_pcie_proto_h2d
*
nicif_h2d_poll
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
);
struct
nicsim_params
*
params
,
uint64_t
timestamp
);
void
nicif_h2d_done
(
volatile
union
cosim_pcie_proto_h2d
*
msg
);
void
nicif_h2d_next
(
void
);
volatile
union
cosim_pcie_proto_d2h
*
nicsim_d2h_alloc
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
);
struct
nicsim_params
*
params
,
uint64_t
timestamp
);
volatile
union
cosim_eth_proto_n2d
*
nicif_n2d_poll
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
);
volatile
union
cosim_eth_proto_n2d
*
nicif_n2d_poll
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
);
void
nicif_n2d_done
(
volatile
union
cosim_eth_proto_n2d
*
msg
);
void
nicif_n2d_next
(
void
);
volatile
union
cosim_eth_proto_d2n
*
nicsim_d2n_alloc
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
);
struct
nicsim_params
*
params
,
uint64_t
timestamp
);
#endif // SIMBRICKS_NICIF_NICSIM_H_
lib/simbricks/nicif/utils.c
View file @
d4666c97
...
...
@@ -24,116 +24,112 @@
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <s
ys/un
.h>
#include <s
ys/socket
.h>
#include <s
tdio
.h>
#include <s
tdlib
.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include "lib/simbricks/nicif/internal.h"
int
uxsocket_init
(
const
char
*
path
)
{
int
fd
;
struct
sockaddr_un
saun
;
int
uxsocket_init
(
const
char
*
path
)
{
int
fd
;
struct
sockaddr_un
saun
;
if
((
fd
=
socket
(
AF_UNIX
,
SOCK_STREAM
,
0
))
==
-
1
)
{
perror
(
"uxsocket_init: socket failed"
);
goto
error_exit
;
}
if
((
fd
=
socket
(
AF_UNIX
,
SOCK_STREAM
,
0
))
==
-
1
)
{
perror
(
"uxsocket_init: socket failed"
);
goto
error_exit
;
}
memset
(
&
saun
,
0
,
sizeof
(
saun
));
saun
.
sun_family
=
AF_UNIX
;
memcpy
(
saun
.
sun_path
,
path
,
strlen
(
path
));
if
(
bind
(
fd
,
(
struct
sockaddr
*
)
&
saun
,
sizeof
(
saun
)))
{
perror
(
"uxsocket_init: bind failed"
);
goto
error_close
;
}
memset
(
&
saun
,
0
,
sizeof
(
saun
));
saun
.
sun_family
=
AF_UNIX
;
memcpy
(
saun
.
sun_path
,
path
,
strlen
(
path
));
if
(
bind
(
fd
,
(
struct
sockaddr
*
)
&
saun
,
sizeof
(
saun
)))
{
perror
(
"uxsocket_init: bind failed"
);
goto
error_close
;
}
if
(
listen
(
fd
,
5
))
{
perror
(
"uxsocket_init: listen failed"
);
goto
error_close
;
}
if
(
listen
(
fd
,
5
))
{
perror
(
"uxsocket_init: listen failed"
);
goto
error_close
;
}
return
fd
;
return
fd
;
error_close:
close
(
fd
);
close
(
fd
);
error_exit:
return
-
1
;
return
-
1
;
}
int
uxsocket_send
(
int
connfd
,
void
*
data
,
size_t
len
,
int
fd
)
{
ssize_t
tx
;
struct
iovec
iov
=
{
.
iov_base
=
data
,
.
iov_len
=
len
,
};
union
{
char
buf
[
CMSG_SPACE
(
sizeof
(
int
))];
struct
cmsghdr
align
;
}
u
;
struct
msghdr
msg
=
{
.
msg_name
=
NULL
,
.
msg_namelen
=
0
,
.
msg_iov
=
&
iov
,
.
msg_iovlen
=
1
,
.
msg_control
=
u
.
buf
,
.
msg_controllen
=
0
,
.
msg_flags
=
0
,
};
struct
cmsghdr
*
cmsg
=
&
u
.
align
;
if
(
fd
>=
0
)
{
msg
.
msg_controllen
=
sizeof
(
u
.
buf
);
cmsg
->
cmsg_level
=
SOL_SOCKET
;
cmsg
->
cmsg_type
=
SCM_RIGHTS
;
cmsg
->
cmsg_len
=
CMSG_LEN
(
sizeof
(
int
));
*
(
int
*
)
CMSG_DATA
(
cmsg
)
=
fd
;
}
if
((
tx
=
sendmsg
(
connfd
,
&
msg
,
0
))
!=
(
ssize_t
)
len
)
{
fprintf
(
stderr
,
"tx == %zd
\n
"
,
tx
);
return
-
1
;
}
return
0
;
int
uxsocket_send
(
int
connfd
,
void
*
data
,
size_t
len
,
int
fd
)
{
ssize_t
tx
;
struct
iovec
iov
=
{
.
iov_base
=
data
,
.
iov_len
=
len
,
};
union
{
char
buf
[
CMSG_SPACE
(
sizeof
(
int
))];
struct
cmsghdr
align
;
}
u
;
struct
msghdr
msg
=
{
.
msg_name
=
NULL
,
.
msg_namelen
=
0
,
.
msg_iov
=
&
iov
,
.
msg_iovlen
=
1
,
.
msg_control
=
u
.
buf
,
.
msg_controllen
=
0
,
.
msg_flags
=
0
,
};
struct
cmsghdr
*
cmsg
=
&
u
.
align
;
if
(
fd
>=
0
)
{
msg
.
msg_controllen
=
sizeof
(
u
.
buf
);
cmsg
->
cmsg_level
=
SOL_SOCKET
;
cmsg
->
cmsg_type
=
SCM_RIGHTS
;
cmsg
->
cmsg_len
=
CMSG_LEN
(
sizeof
(
int
));
*
(
int
*
)
CMSG_DATA
(
cmsg
)
=
fd
;
}
if
((
tx
=
sendmsg
(
connfd
,
&
msg
,
0
))
!=
(
ssize_t
)
len
)
{
fprintf
(
stderr
,
"tx == %zd
\n
"
,
tx
);
return
-
1
;
}
return
0
;
}
int
shm_create
(
const
char
*
path
,
size_t
size
,
void
**
addr
)
{
int
fd
;
void
*
p
;
int
shm_create
(
const
char
*
path
,
size_t
size
,
void
**
addr
)
{
int
fd
;
void
*
p
;
if
((
fd
=
open
(
path
,
O_CREAT
|
O_RDWR
,
0666
))
==
-
1
)
{
perror
(
"util_create_shmsiszed: open failed"
);
goto
error_out
;
}
if
(
ftruncate
(
fd
,
size
)
!=
0
)
{
perror
(
"util_create_shmsiszed: ftruncate failed"
);
goto
error_remove
;
}
if
((
fd
=
open
(
path
,
O_CREAT
|
O_RDWR
,
0666
))
==
-
1
)
{
perror
(
"util_create_shmsiszed: open failed"
);
goto
error_out
;
}
if
(
ftruncate
(
fd
,
size
)
!=
0
)
{
perror
(
"util_create_shmsiszed: ftruncate failed"
);
goto
error_remove
;
}
if
((
p
=
mmap
(
NULL
,
size
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
|
MAP_POPULATE
,
fd
,
0
))
==
(
void
*
)
-
1
)
{
perror
(
"util_create_shmsiszed: mmap failed"
);
goto
error_remove
;
}
if
((
p
=
mmap
(
NULL
,
size
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
|
MAP_POPULATE
,
fd
,
0
))
==
(
void
*
)
-
1
)
{
perror
(
"util_create_shmsiszed: mmap failed"
);
goto
error_remove
;
}
memset
(
p
,
0
,
size
);
memset
(
p
,
0
,
size
);
*
addr
=
p
;
return
fd
;
*
addr
=
p
;
return
fd
;
error_remove:
close
(
fd
);
unlink
(
path
);
close
(
fd
);
unlink
(
path
);
error_out:
return
-
1
;
return
-
1
;
}
lib/simbricks/proto/network.h
View file @
d4666c97
...
...
@@ -38,34 +38,32 @@
* memory file descriptor attached.
*/
struct
cosim_eth_proto_dev_intro
{
/** flags: see COSIM_ETH_PROTO_FLAGS_DI_* */
uint64_t
flags
;
/** offset of the device-to-network queue in shared memory region */
uint64_t
d2n_offset
;
/** size of an entry in the device-to-network queue in bytes */
uint64_t
d2n_elen
;
/** total device-to-network queue length in #entries */
uint64_t
d2n_nentries
;
/** offset of the net-to-device queue in shared memory region */
uint64_t
n2d_offset
;
/** size of an entry in the net-to-device queue in bytes */
uint64_t
n2d_elen
;
/** total net-to-device queue length in #entries */
uint64_t
n2d_nentries
;
}
__attribute__
((
packed
));
/** flags: see COSIM_ETH_PROTO_FLAGS_DI_* */
uint64_t
flags
;
/** offset of the device-to-network queue in shared memory region */
uint64_t
d2n_offset
;
/** size of an entry in the device-to-network queue in bytes */
uint64_t
d2n_elen
;
/** total device-to-network queue length in #entries */
uint64_t
d2n_nentries
;
/** offset of the net-to-device queue in shared memory region */
uint64_t
n2d_offset
;
/** size of an entry in the net-to-device queue in bytes */
uint64_t
n2d_elen
;
/** total net-to-device queue length in #entries */
uint64_t
n2d_nentries
;
}
__attribute__
((
packed
));
#define COSIM_ETH_PROTO_FLAGS_NI_SYNC (1 << 0)
/** welcome message sent by network to device */
struct
cosim_eth_proto_net_intro
{
/** flags: see COSIM_ETH_PROTO_FLAGS_IN_* */
/** flags: see COSIM_ETH_PROTO_FLAGS_IN_* */
uint64_t
flags
;
}
__attribute__
((
packed
));
/******************************************************************************/
/* Messages on in-memory device to network channel */
...
...
@@ -82,36 +80,35 @@ struct cosim_eth_proto_net_intro {
#define COSIM_ETH_PROTO_D2N_MSG_SEND 0x2
struct
cosim_eth_proto_d2n_dummy
{
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
}
__attribute__
((
packed
));
struct
cosim_eth_proto_d2n_sync
{
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
}
__attribute__
((
packed
));
struct
cosim_eth_proto_d2n_send
{
uint16_t
len
;
uint8_t
port
;
uint8_t
pad
[
45
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
uint16_t
len
;
uint8_t
port
;
uint8_t
pad
[
45
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
}
__attribute__
((
packed
));
union
cosim_eth_proto_d2n
{
struct
cosim_eth_proto_d2n_dummy
dummy
;
struct
cosim_eth_proto_d2n_sync
sync
;
struct
cosim_eth_proto_d2n_send
send
;
struct
cosim_eth_proto_d2n_dummy
dummy
;
struct
cosim_eth_proto_d2n_sync
sync
;
struct
cosim_eth_proto_d2n_send
send
;
};
/******************************************************************************/
/* Messages on in-memory network to device channel */
...
...
@@ -126,33 +123,33 @@ union cosim_eth_proto_d2n {
#define COSIM_ETH_PROTO_N2D_MSG_RECV 0x2
struct
cosim_eth_proto_n2d_dummy
{
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
}
__attribute__
((
packed
));
struct
cosim_eth_proto_n2d_sync
{
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
}
__attribute__
((
packed
));
struct
cosim_eth_proto_n2d_recv
{
uint16_t
len
;
uint8_t
port
;
uint8_t
pad
[
45
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
uint16_t
len
;
uint8_t
port
;
uint8_t
pad
[
45
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
};
union
cosim_eth_proto_n2d
{
struct
cosim_eth_proto_n2d_dummy
dummy
;
struct
cosim_eth_proto_n2d_sync
sync
;
struct
cosim_eth_proto_n2d_recv
recv
;
struct
cosim_eth_proto_n2d_dummy
dummy
;
struct
cosim_eth_proto_n2d_sync
sync
;
struct
cosim_eth_proto_n2d_recv
recv
;
};
#endif // SIMBRICKS_PROTO_NETWORK_H_
lib/simbricks/proto/pcie.h
View file @
d4666c97
...
...
@@ -55,69 +55,67 @@
* memory file descriptor attached.
*/
struct
cosim_pcie_proto_dev_intro
{
/** flags: see COSIM_PCIE_PROTO_FLAGS_DI_* */
uint64_t
flags
;
/** flags: see COSIM_PCIE_PROTO_FLAGS_DI_* */
uint64_t
flags
;
/** offset of the device-to-host queue in shared memory region */
uint64_t
d2h_offset
;
/** size of an entry in the device-to-host queue in bytes */
uint64_t
d2h_elen
;
/** total device-to-host queue length in #entries */
uint64_t
d2h_nentries
;
/** offset of the host-to-device queue in shared memory region */
uint64_t
h2d_offset
;
/** size of an entry in the host-to-device queue in bytes */
uint64_t
h2d_elen
;
/** total host-to-device queue length in #entries */
uint64_t
h2d_nentries
;
/** information for each BAR exposed by the device */
struct
{
/** length of the bar in bytes (len = 0 indicates unused bar) */
uint64_t
len
;
/** flags (see COSIM_PCIE_PROTO_BAR_*) */
uint64_t
flags
;
}
__attribute__
((
packed
))
bars
[
COSIM_PCIE_PROTO_NBARS
];
/** PCI vendor id */
uint16_t
pci_vendor_id
;
/** PCI device id */
uint16_t
pci_device_id
;
/* PCI class */
uint8_t
pci_class
;
/* PCI subclass */
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
;
/** offset of the device-to-host queue in shared memory region */
uint64_t
d2h_offset
;
/** size of an entry in the device-to-host queue in bytes */
uint64_t
d2h_elen
;
/** total device-to-host queue length in #entries */
uint64_t
d2h_nentries
;
/** offset of the host-to-device queue in shared memory region */
uint64_t
h2d_offset
;
/** size of an entry in the host-to-device queue in bytes */
uint64_t
h2d_elen
;
/** total host-to-device queue length in #entries */
uint64_t
h2d_nentries
;
/** information for each BAR exposed by the device */
struct
{
/** length of the bar in bytes (len = 0 indicates unused bar) */
uint64_t
len
;
/** flags (see COSIM_PCIE_PROTO_BAR_*) */
uint64_t
flags
;
}
__attribute__
((
packed
))
bars
[
COSIM_PCIE_PROTO_NBARS
];
/** PCI vendor id */
uint16_t
pci_vendor_id
;
/** PCI device id */
uint16_t
pci_device_id
;
/* PCI class */
uint8_t
pci_class
;
/* PCI subclass */
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
));
#define COSIM_PCIE_PROTO_FLAGS_HI_SYNC (1 << 0)
/** welcome message sent by host to device */
struct
cosim_pcie_proto_host_intro
{
/** flags: see COSIM_PCIE_PROTO_FLAGS_HI_* */
/** flags: see COSIM_PCIE_PROTO_FLAGS_HI_* */
uint64_t
flags
;
}
__attribute__
((
packed
));
/******************************************************************************/
/* Messages on in-memory device to host channel */
...
...
@@ -138,41 +136,41 @@ struct cosim_pcie_proto_host_intro {
#define COSIM_PCIE_PROTO_D2H_MSG_WRITECOMP 0x6
struct
cosim_pcie_proto_d2h_dummy
{
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_dummy
);
struct
cosim_pcie_proto_d2h_sync
{
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_sync
);
struct
cosim_pcie_proto_d2h_read
{
uint64_t
req_id
;
uint64_t
offset
;
uint16_t
len
;
uint8_t
pad
[
30
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint64_t
req_id
;
uint64_t
offset
;
uint16_t
len
;
uint8_t
pad
[
30
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_read
);
struct
cosim_pcie_proto_d2h_write
{
uint64_t
req_id
;
uint64_t
offset
;
uint16_t
len
;
uint8_t
pad
[
30
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
uint64_t
req_id
;
uint64_t
offset
;
uint16_t
len
;
uint8_t
pad
[
30
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_write
);
...
...
@@ -182,46 +180,45 @@ COSIM_PCI_MSG_SZCHECK(struct cosim_pcie_proto_d2h_write);
#define COSIM_PCIE_PROTO_INT_MSIX 3
struct
cosim_pcie_proto_d2h_interrupt
{
uint16_t
vector
;
uint8_t
inttype
;
uint8_t
pad
[
45
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint16_t
vector
;
uint8_t
inttype
;
uint8_t
pad
[
45
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_interrupt
);
struct
cosim_pcie_proto_d2h_readcomp
{
uint64_t
req_id
;
uint8_t
pad
[
40
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
uint64_t
req_id
;
uint8_t
pad
[
40
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_readcomp
);
struct
cosim_pcie_proto_d2h_writecomp
{
uint64_t
req_id
;
uint8_t
pad
[
40
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint64_t
req_id
;
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_d2h_writecomp
);
union
cosim_pcie_proto_d2h
{
struct
cosim_pcie_proto_d2h_dummy
dummy
;
struct
cosim_pcie_proto_d2h_sync
sync
;
struct
cosim_pcie_proto_d2h_read
read
;
struct
cosim_pcie_proto_d2h_write
write
;
struct
cosim_pcie_proto_d2h_interrupt
interrupt
;
struct
cosim_pcie_proto_d2h_readcomp
readcomp
;
struct
cosim_pcie_proto_d2h_writecomp
writecomp
;
struct
cosim_pcie_proto_d2h_dummy
dummy
;
struct
cosim_pcie_proto_d2h_sync
sync
;
struct
cosim_pcie_proto_d2h_read
read
;
struct
cosim_pcie_proto_d2h_write
write
;
struct
cosim_pcie_proto_d2h_interrupt
interrupt
;
struct
cosim_pcie_proto_d2h_readcomp
readcomp
;
struct
cosim_pcie_proto_d2h_writecomp
writecomp
;
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
union
cosim_pcie_proto_d2h
);
/******************************************************************************/
/* Messages on in-memory host to device channel */
...
...
@@ -240,62 +237,62 @@ COSIM_PCI_MSG_SZCHECK(union cosim_pcie_proto_d2h);
#define COSIM_PCIE_PROTO_H2D_MSG_DEVCTRL 0x7
struct
cosim_pcie_proto_h2d_dummy
{
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_dummy
);
struct
cosim_pcie_proto_h2d_sync
{
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_sync
);
struct
cosim_pcie_proto_h2d_read
{
uint64_t
req_id
;
uint64_t
offset
;
uint16_t
len
;
uint8_t
bar
;
uint8_t
pad
[
29
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint64_t
req_id
;
uint64_t
offset
;
uint16_t
len
;
uint8_t
bar
;
uint8_t
pad
[
29
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_read
);
struct
cosim_pcie_proto_h2d_write
{
uint64_t
req_id
;
uint64_t
offset
;
uint16_t
len
;
uint8_t
bar
;
uint8_t
pad
[
29
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
uint64_t
req_id
;
uint64_t
offset
;
uint16_t
len
;
uint8_t
bar
;
uint8_t
pad
[
29
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_write
);
struct
cosim_pcie_proto_h2d_readcomp
{
uint64_t
req_id
;
uint8_t
pad
[
40
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
uint64_t
req_id
;
uint8_t
pad
[
40
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
data
[];
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_readcomp
);
struct
cosim_pcie_proto_h2d_writecomp
{
uint64_t
req_id
;
uint8_t
pad
[
40
];
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint64_t
req_id
;
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_writecomp
);
...
...
@@ -303,22 +300,22 @@ COSIM_PCI_MSG_SZCHECK(struct cosim_pcie_proto_h2d_writecomp);
#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
;
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
;
struct
cosim_pcie_proto_h2d_read
read
;
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
;
struct
cosim_pcie_proto_h2d_dummy
dummy
;
struct
cosim_pcie_proto_h2d_sync
sync
;
struct
cosim_pcie_proto_h2d_read
read
;
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
);
...
...
sims/net/switch/net_switch.cc
View file @
d4666c97
...
...
@@ -22,15 +22,16 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <cassert>
#include <climits>
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <csignal>
#include <climits>
#include <cstring>
#include <unistd.h>
#include <vector>
#include <unordered_map>
#include <
cassert
>
#include <
vector
>
extern
"C"
{
#include <simbricks/netif/netsim.h>
...
...
@@ -41,31 +42,30 @@ static uint64_t eth_latency = (500 * 1000ULL); // 500ns
/* MAC address type */
struct
MAC
{
const
volatile
uint8_t
*
data
;
const
volatile
uint8_t
*
data
;
MAC
(
const
volatile
uint8_t
*
data
)
:
data
(
data
)
{
}
MAC
(
const
volatile
uint8_t
*
data
)
:
data
(
data
)
{
}
bool
operator
==
(
const
MAC
&
other
)
const
{
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
if
(
data
[
i
]
!=
other
.
data
[
i
])
{
return
false
;
}
}
return
true
;
bool
operator
==
(
const
MAC
&
other
)
const
{
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
if
(
data
[
i
]
!=
other
.
data
[
i
])
{
return
false
;
}
}
return
true
;
}
};
namespace
std
{
template
<
>
struct
hash
<
MAC
>
{
size_t
operator
()(
const
MAC
&
m
)
const
{
struct
hash
<
MAC
>
{
size_t
operator
()(
const
MAC
&
m
)
const
{
size_t
res
=
0
;
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
res
=
(
res
<<
4
)
|
(
res
^
m
.
data
[
i
]);
res
=
(
res
<<
4
)
|
(
res
^
m
.
data
[
i
]);
}
return
res
;
}
}
};
}
// namespace std
...
...
@@ -77,149 +77,145 @@ static const MAC bcast_addr(bcast);
static
std
::
vector
<
struct
netsim_interface
>
nsifs
;
static
std
::
unordered_map
<
MAC
,
int
>
mac_table
;
static
void
sigint_handler
(
int
dummy
)
{
exiting
=
1
;
static
void
sigint_handler
(
int
dummy
)
{
exiting
=
1
;
}
static
void
forward_pkt
(
volatile
struct
cosim_eth_proto_d2n_send
*
tx
,
int
port
)
{
volatile
union
cosim_eth_proto_n2d
*
msg_to
;
msg_to
=
netsim_n2d_alloc
(
&
nsifs
[
port
],
cur_ts
,
eth_latency
);
if
(
msg_to
!=
NULL
)
{
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
rx
=
&
msg_to
->
recv
;
rx
->
len
=
tx
->
len
;
rx
->
port
=
0
;
memcpy
((
void
*
)
rx
->
data
,
(
void
*
)
tx
->
data
,
tx
->
len
);
// WMB();
rx
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_RECV
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
}
else
{
fprintf
(
stderr
,
"forward_pkt: dropping packet
\n
"
);
}
static
void
forward_pkt
(
volatile
struct
cosim_eth_proto_d2n_send
*
tx
,
int
port
)
{
volatile
union
cosim_eth_proto_n2d
*
msg_to
;
msg_to
=
netsim_n2d_alloc
(
&
nsifs
[
port
],
cur_ts
,
eth_latency
);
if
(
msg_to
!=
NULL
)
{
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
rx
=
&
msg_to
->
recv
;
rx
->
len
=
tx
->
len
;
rx
->
port
=
0
;
memcpy
((
void
*
)
rx
->
data
,
(
void
*
)
tx
->
data
,
tx
->
len
);
// WMB();
rx
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_RECV
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
}
else
{
fprintf
(
stderr
,
"forward_pkt: dropping packet
\n
"
);
}
}
static
void
switch_pkt
(
struct
netsim_interface
*
nsif
,
int
iport
)
{
volatile
union
cosim_eth_proto_d2n
*
msg_from
=
netsim_d2n_poll
(
nsif
,
cur_ts
);
if
(
msg_from
==
NULL
)
{
return
;
static
void
switch_pkt
(
struct
netsim_interface
*
nsif
,
int
iport
)
{
volatile
union
cosim_eth_proto_d2n
*
msg_from
=
netsim_d2n_poll
(
nsif
,
cur_ts
);
if
(
msg_from
==
NULL
)
{
return
;
}
uint8_t
type
=
msg_from
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
;
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SEND
)
{
volatile
struct
cosim_eth_proto_d2n_send
*
tx
;
tx
=
&
msg_from
->
send
;
// Get MAC addresses
MAC
dst
(
tx
->
data
),
src
(
tx
->
data
+
6
);
// MAC learning
if
(
!
(
src
==
bcast_addr
))
{
mac_table
[
src
]
=
iport
;
}
uint8_t
type
=
msg_from
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
;
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SEND
)
{
volatile
struct
cosim_eth_proto_d2n_send
*
tx
;
tx
=
&
msg_from
->
send
;
// Get MAC addresses
MAC
dst
(
tx
->
data
),
src
(
tx
->
data
+
6
);
// MAC learning
if
(
!
(
src
==
bcast_addr
))
{
mac_table
[
src
]
=
iport
;
}
// L2 forwarding
if
(
mac_table
.
count
(
dst
)
>
0
)
{
int
eport
=
mac_table
.
at
(
dst
);
forward_pkt
(
tx
,
eport
);
}
else
{
// Broadcast
for
(
int
eport
=
0
;
eport
<
nsifs
.
size
();
eport
++
)
{
if
(
eport
!=
iport
)
{
// Do not forward to ingress port
forward_pkt
(
tx
,
eport
);
}
}
}
}
else
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SYNC
)
{
// L2 forwarding
if
(
mac_table
.
count
(
dst
)
>
0
)
{
int
eport
=
mac_table
.
at
(
dst
);
forward_pkt
(
tx
,
eport
);
}
else
{
fprintf
(
stderr
,
"switch_pkt: unsupported type=%u
\n
"
,
type
);
abort
();
// Broadcast
for
(
int
eport
=
0
;
eport
<
nsifs
.
size
();
eport
++
)
{
if
(
eport
!=
iport
)
{
// Do not forward to ingress port
forward_pkt
(
tx
,
eport
);
}
}
}
netsim_d2n_done
(
nsif
,
msg_from
);
}
else
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SYNC
)
{
}
else
{
fprintf
(
stderr
,
"switch_pkt: unsupported type=%u
\n
"
,
type
);
abort
();
}
netsim_d2n_done
(
nsif
,
msg_from
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
c
;
int
bad_option
=
0
;
int
sync_mode
=
SYNC_MODES
;
// Parse command line argument
while
((
c
=
getopt
(
argc
,
argv
,
"s:S:E:m:"
))
!=
-
1
&&
!
bad_option
)
{
switch
(
c
)
{
case
's'
:
{
struct
netsim_interface
nsif
;
int
sync
=
1
;
if
(
netsim_init
(
&
nsif
,
optarg
,
&
sync
)
!=
0
)
{
fprintf
(
stderr
,
"connecting to %s failed
\n
"
,
optarg
);
return
EXIT_FAILURE
;
}
nsifs
.
push_back
(
nsif
);
break
;
}
case
'S'
:
sync_period
=
strtoull
(
optarg
,
NULL
,
0
)
*
1000ULL
;
break
;
case
'E'
:
eth_latency
=
strtoull
(
optarg
,
NULL
,
0
)
*
1000ULL
;
break
;
case
'm'
:
sync_mode
=
strtol
(
optarg
,
NULL
,
0
);
assert
(
sync_mode
==
SYNC_MODES
||
sync_mode
==
SYNC_BARRIER
);
break
;
default:
fprintf
(
stderr
,
"unknown option %c
\n
"
,
c
);
bad_option
=
1
;
break
;
int
main
(
int
argc
,
char
*
argv
[])
{
int
c
;
int
bad_option
=
0
;
int
sync_mode
=
SYNC_MODES
;
// Parse command line argument
while
((
c
=
getopt
(
argc
,
argv
,
"s:S:E:m:"
))
!=
-
1
&&
!
bad_option
)
{
switch
(
c
)
{
case
's'
:
{
struct
netsim_interface
nsif
;
int
sync
=
1
;
if
(
netsim_init
(
&
nsif
,
optarg
,
&
sync
)
!=
0
)
{
fprintf
(
stderr
,
"connecting to %s failed
\n
"
,
optarg
);
return
EXIT_FAILURE
;
}
nsifs
.
push_back
(
nsif
);
break
;
}
case
'S'
:
sync_period
=
strtoull
(
optarg
,
NULL
,
0
)
*
1000ULL
;
break
;
case
'E'
:
eth_latency
=
strtoull
(
optarg
,
NULL
,
0
)
*
1000ULL
;
break
;
case
'm'
:
sync_mode
=
strtol
(
optarg
,
NULL
,
0
);
assert
(
sync_mode
==
SYNC_MODES
||
sync_mode
==
SYNC_BARRIER
);
break
;
default:
fprintf
(
stderr
,
"unknown option %c
\n
"
,
c
);
bad_option
=
1
;
break
;
}
if
(
nsifs
.
empty
()
||
bad_option
)
{
fprintf
(
stderr
,
"Usage: net_switch [-S SYNC-PERIOD] [-E ETH-LATENCY] "
"-s SOCKET-A [-s SOCKET-B ...]
\n
"
);
return
EXIT_FAILURE
;
}
if
(
nsifs
.
empty
()
||
bad_option
)
{
fprintf
(
stderr
,
"Usage: net_switch [-S SYNC-PERIOD] [-E ETH-LATENCY] "
"-s SOCKET-A [-s SOCKET-B ...]
\n
"
);
return
EXIT_FAILURE
;
}
signal
(
SIGINT
,
sigint_handler
);
signal
(
SIGTERM
,
sigint_handler
);
printf
(
"start polling
\n
"
);
while
(
!
exiting
)
{
// Sync all interfaces
for
(
auto
&
nsif
:
nsifs
)
{
if
(
netsim_n2d_sync
(
&
nsif
,
cur_ts
,
eth_latency
,
sync_period
,
sync_mode
)
!=
0
)
{
fprintf
(
stderr
,
"netsim_n2d_sync failed
\n
"
);
abort
();
}
}
signal
(
SIGINT
,
sigint_handler
);
signal
(
SIGTERM
,
sigint_handler
);
printf
(
"start polling
\n
"
);
while
(
!
exiting
)
{
// Sync all interfaces
for
(
auto
&
nsif
:
nsifs
)
{
if
(
netsim_n2d_sync
(
&
nsif
,
cur_ts
,
eth_latency
,
sync_period
,
sync_mode
)
!=
0
)
{
fprintf
(
stderr
,
"netsim_n2d_sync failed
\n
"
);
abort
();
}
}
netsim_advance_epoch
(
cur_ts
,
sync_period
,
sync_mode
);
// Switch packets
uint64_t
min_ts
;
do
{
min_ts
=
ULLONG_MAX
;
for
(
int
port
=
0
;
port
<
nsifs
.
size
();
port
++
)
{
auto
&
nsif
=
nsifs
.
at
(
port
);
switch_pkt
(
&
nsif
,
port
);
if
(
nsif
.
sync
)
{
uint64_t
ts
=
netsim_d2n_timestamp
(
&
nsif
);
min_ts
=
ts
<
min_ts
?
ts
:
min_ts
;
}
}
}
while
(
!
exiting
&&
(
min_ts
<=
cur_ts
));
// Update cur_ts
if
(
min_ts
<
ULLONG_MAX
)
{
cur_ts
=
netsim_advance_time
(
min_ts
,
sync_period
,
sync_mode
);
netsim_advance_epoch
(
cur_ts
,
sync_period
,
sync_mode
);
// Switch packets
uint64_t
min_ts
;
do
{
min_ts
=
ULLONG_MAX
;
for
(
int
port
=
0
;
port
<
nsifs
.
size
();
port
++
)
{
auto
&
nsif
=
nsifs
.
at
(
port
);
switch_pkt
(
&
nsif
,
port
);
if
(
nsif
.
sync
)
{
uint64_t
ts
=
netsim_d2n_timestamp
(
&
nsif
);
min_ts
=
ts
<
min_ts
?
ts
:
min_ts
;
}
}
}
while
(
!
exiting
&&
(
min_ts
<=
cur_ts
));
// Update cur_ts
if
(
min_ts
<
ULLONG_MAX
)
{
cur_ts
=
netsim_advance_time
(
min_ts
,
sync_period
,
sync_mode
);
}
}
return
0
;
return
0
;
}
sims/net/tap/net_tap.c
View file @
d4666c97
...
...
@@ -23,15 +23,15 @@
*/
#include <fcntl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <simbricks/netif/netsim.h>
...
...
@@ -40,119 +40,113 @@
static
struct
netsim_interface
nsif
;
static
int
tap_fd
;
static
int
tap_open
(
const
char
*
name
)
{
struct
ifreq
ifr
;
int
fd
;
static
int
tap_open
(
const
char
*
name
)
{
struct
ifreq
ifr
;
int
fd
;
if
((
fd
=
open
(
"/dev/net/tun"
,
O_RDWR
))
<
0
)
{
perror
(
"tap_open: open failed"
);
return
-
1
;
}
if
((
fd
=
open
(
"/dev/net/tun"
,
O_RDWR
))
<
0
)
{
perror
(
"tap_open: open failed"
);
return
-
1
;
}
memset
(
&
ifr
,
0
,
sizeof
(
ifr
));
ifr
.
ifr_flags
=
IFF_TAP
|
IFF_NO_PI
;
strncpy
(
ifr
.
ifr_name
,
name
,
IFNAMSIZ
);
memset
(
&
ifr
,
0
,
sizeof
(
ifr
));
ifr
.
ifr_flags
=
IFF_TAP
|
IFF_NO_PI
;
strncpy
(
ifr
.
ifr_name
,
name
,
IFNAMSIZ
);
if
(
ioctl
(
fd
,
TUNSETIFF
,
&
ifr
)
!=
0
)
{
perror
(
"tap_open: ioctl failed"
);
close
(
fd
);
return
-
1
;
}
if
(
ioctl
(
fd
,
TUNSETIFF
,
&
ifr
)
!=
0
)
{
perror
(
"tap_open: ioctl failed"
);
close
(
fd
);
return
-
1
;
}
return
fd
;
return
fd
;
}
static
void
d2n_send
(
volatile
struct
cosim_eth_proto_d2n_send
*
s
)
{
static
void
d2n_send
(
volatile
struct
cosim_eth_proto_d2n_send
*
s
)
{
#ifdef DEBUG_PKTMETA
printf
(
"sent packet: len=%u
\n
"
,
s
->
len
);
printf
(
"sent packet: len=%u
\n
"
,
s
->
len
);
#endif
if
(
write
(
tap_fd
,
(
void
*
)
s
->
data
,
s
->
len
)
!=
(
ssize_t
)
s
->
len
)
{
perror
(
"d2n_send: send failed"
);
}
if
(
write
(
tap_fd
,
(
void
*
)
s
->
data
,
s
->
len
)
!=
(
ssize_t
)
s
->
len
)
{
perror
(
"d2n_send: send failed"
);
}
}
static
void
poll_d2n
(
void
)
{
volatile
union
cosim_eth_proto_d2n
*
msg
=
netsim_d2n_poll
(
&
nsif
,
0
);
uint8_t
type
;
static
void
poll_d2n
(
void
)
{
volatile
union
cosim_eth_proto_d2n
*
msg
=
netsim_d2n_poll
(
&
nsif
,
0
);
uint8_t
type
;
/* message not ready */
if
(
msg
==
NULL
)
return
;
/* message not ready */
if
(
msg
==
NULL
)
return
;
type
=
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
;
switch
(
type
)
{
case
COSIM_ETH_PROTO_D2N_MSG_SEND
:
d2n_send
(
&
msg
->
send
);
break
;
type
=
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
;
switch
(
type
)
{
case
COSIM_ETH_PROTO_D2N_MSG_SEND
:
d2n_send
(
&
msg
->
send
);
break
;
default:
fprintf
(
stderr
,
"poll_d2n: unsupported type=%u
\n
"
,
type
);
}
default:
fprintf
(
stderr
,
"poll_d2n: unsupported type=%u
\n
"
,
type
);
}
netsim_d2n_done
(
&
nsif
,
msg
);
netsim_d2n_done
(
&
nsif
,
msg
);
}
static
void
*
rx_handler
(
void
*
arg
)
{
volatile
union
cosim_eth_proto_n2d
*
msg
;
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
ssize_t
len
;
while
(
1
)
{
msg
=
netsim_n2d_alloc
(
&
nsif
,
0
,
0
);
if
(
msg
==
NULL
)
{
fprintf
(
stderr
,
"coudl not allocate message for rx
\n
"
);
abort
();
}
rx
=
&
msg
->
recv
;
len
=
read
(
tap_fd
,
(
void
*
)
rx
->
data
,
nsif
.
n2d_elen
-
sizeof
(
*
msg
));
if
(
len
<=
0
)
{
perror
(
"rx handler: read failed"
);
}
rx
->
len
=
len
;
rx
->
port
=
0
;
#ifdef DEBUG_PKTMETA
printf
(
"received packet: len=%u
\n
"
,
rx
->
len
);
#endif
static
void
*
rx_handler
(
void
*
arg
)
{
volatile
union
cosim_eth_proto_n2d
*
msg
;
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
ssize_t
len
;
// WMB();
rx
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_RECV
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
sync
;
if
(
argc
!=
3
)
{
fprintf
(
stderr
,
"Usage: net_tap TAP_DEVICE_NAME SOCKET
\n
"
);
return
EXIT_FAILURE
;
}
if
((
tap_fd
=
tap_open
(
argv
[
1
]))
<
0
)
{
return
-
1
;
while
(
1
)
{
msg
=
netsim_n2d_alloc
(
&
nsif
,
0
,
0
);
if
(
msg
==
NULL
)
{
fprintf
(
stderr
,
"coudl not allocate message for rx
\n
"
);
abort
();
}
rx
=
&
msg
->
recv
;
sync
=
0
;
if
(
netsim_init
(
&
nsif
,
argv
[
2
],
&
sync
)
!=
0
)
{
close
(
tap_fd
);
return
-
1
;
len
=
read
(
tap_fd
,
(
void
*
)
rx
->
data
,
nsif
.
n2d_elen
-
sizeof
(
*
msg
));
if
(
len
<=
0
)
{
perror
(
"rx handler: read failed"
);
}
rx
->
len
=
len
;
rx
->
port
=
0
;
#ifdef DEBUG_PKTMETA
printf
(
"received packet: len=%u
\n
"
,
rx
->
len
);
#endif
pthread_t
worker
;
if
(
pthread_create
(
&
worker
,
NULL
,
rx_handler
,
NULL
)
!=
0
)
{
return
EXIT_FAILURE
;
}
// WMB()
;
rx
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_RECV
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
}
}
printf
(
"start polling
\n
"
);
while
(
1
)
{
poll_d2n
();
}
return
0
;
int
main
(
int
argc
,
char
*
argv
[])
{
int
sync
;
if
(
argc
!=
3
)
{
fprintf
(
stderr
,
"Usage: net_tap TAP_DEVICE_NAME SOCKET
\n
"
);
return
EXIT_FAILURE
;
}
if
((
tap_fd
=
tap_open
(
argv
[
1
]))
<
0
)
{
return
-
1
;
}
sync
=
0
;
if
(
netsim_init
(
&
nsif
,
argv
[
2
],
&
sync
)
!=
0
)
{
close
(
tap_fd
);
return
-
1
;
}
pthread_t
worker
;
if
(
pthread_create
(
&
worker
,
NULL
,
rx_handler
,
NULL
)
!=
0
)
{
return
EXIT_FAILURE
;
}
printf
(
"start polling
\n
"
);
while
(
1
)
{
poll_d2n
();
}
return
0
;
}
sims/net/wire/net_wire.c
View file @
d4666c97
...
...
@@ -22,19 +22,19 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <assert.h>
#include <fcntl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <pcap/pcap.h>
#include <pthread.h>
#include <s
tdlib
.h>
#include <s
ignal
.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <pcap/pcap.h>
#include <assert.h>
#include <simbricks/netif/netsim.h>
...
...
@@ -44,147 +44,141 @@ static uint64_t cur_ts;
static
int
exiting
=
0
;
static
pcap_dumper_t
*
dumpfile
=
NULL
;
static
void
sigint_handler
(
int
dummy
)
{
exiting
=
1
;
static
void
sigint_handler
(
int
dummy
)
{
exiting
=
1
;
}
static
void
sigusr1_handler
(
int
dummy
)
{
fprintf
(
stderr
,
"main_time = %lu
\n
"
,
cur_ts
);
static
void
sigusr1_handler
(
int
dummy
)
{
fprintf
(
stderr
,
"main_time = %lu
\n
"
,
cur_ts
);
}
static
void
move_pkt
(
struct
netsim_interface
*
from
,
struct
netsim_interface
*
to
)
{
volatile
union
cosim_eth_proto_d2n
*
msg_from
=
netsim_d2n_poll
(
from
,
cur_ts
);
volatile
union
cosim_eth_proto_n2d
*
msg_to
;
volatile
struct
cosim_eth_proto_d2n_send
*
tx
;
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
struct
pcap_pkthdr
ph
;
uint8_t
type
;
if
(
msg_from
==
NULL
)
return
;
type
=
msg_from
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
;
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SEND
)
{
tx
=
&
msg_from
->
send
;
// log to pcap file if initialized
if
(
dumpfile
)
{
memset
(
&
ph
,
0
,
sizeof
(
ph
));
ph
.
ts
.
tv_sec
=
cur_ts
/
1000000000000ULL
;
ph
.
ts
.
tv_usec
=
(
cur_ts
%
1000000000000ULL
)
/
1000ULL
;
ph
.
caplen
=
tx
->
len
;
ph
.
len
=
tx
->
len
;
pcap_dump
((
unsigned
char
*
)
dumpfile
,
&
ph
,
(
unsigned
char
*
)
tx
->
data
);
}
msg_to
=
netsim_n2d_alloc
(
to
,
cur_ts
,
eth_latency
);
if
(
msg_to
!=
NULL
)
{
rx
=
&
msg_to
->
recv
;
rx
->
len
=
tx
->
len
;
rx
->
port
=
0
;
memcpy
((
void
*
)
rx
->
data
,
(
void
*
)
tx
->
data
,
tx
->
len
);
// WMB();
rx
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_RECV
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
}
else
{
fprintf
(
stderr
,
"move_pkt: dropping packet
\n
"
);
}
}
else
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SYNC
)
{
}
else
{
fprintf
(
stderr
,
"move_pkt: unsupported type=%u
\n
"
,
type
);
abort
();
static
void
move_pkt
(
struct
netsim_interface
*
from
,
struct
netsim_interface
*
to
)
{
volatile
union
cosim_eth_proto_d2n
*
msg_from
=
netsim_d2n_poll
(
from
,
cur_ts
);
volatile
union
cosim_eth_proto_n2d
*
msg_to
;
volatile
struct
cosim_eth_proto_d2n_send
*
tx
;
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
struct
pcap_pkthdr
ph
;
uint8_t
type
;
if
(
msg_from
==
NULL
)
return
;
type
=
msg_from
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
;
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SEND
)
{
tx
=
&
msg_from
->
send
;
// log to pcap file if initialized
if
(
dumpfile
)
{
memset
(
&
ph
,
0
,
sizeof
(
ph
));
ph
.
ts
.
tv_sec
=
cur_ts
/
1000000000000ULL
;
ph
.
ts
.
tv_usec
=
(
cur_ts
%
1000000000000ULL
)
/
1000ULL
;
ph
.
caplen
=
tx
->
len
;
ph
.
len
=
tx
->
len
;
pcap_dump
((
unsigned
char
*
)
dumpfile
,
&
ph
,
(
unsigned
char
*
)
tx
->
data
);
}
netsim_d2n_done
(
from
,
msg_from
);
}
msg_to
=
netsim_n2d_alloc
(
to
,
cur_ts
,
eth_latency
);
if
(
msg_to
!=
NULL
)
{
rx
=
&
msg_to
->
recv
;
rx
->
len
=
tx
->
len
;
rx
->
port
=
0
;
memcpy
((
void
*
)
rx
->
data
,
(
void
*
)
tx
->
data
,
tx
->
len
);
int
main
(
int
argc
,
char
*
argv
[])
{
struct
netsim_interface
nsif_a
,
nsif_b
;
uint64_t
ts_a
,
ts_b
;
int
sync_a
,
sync_b
;
pcap_t
*
pc
=
NULL
;
int
sync_mode
=
SYNC_MODES
;
if
(
argc
<
3
&&
argc
>
7
)
{
fprintf
(
stderr
,
"Usage: net_wire SOCKET-A SOCKET-B [SYNC-MODE] "
"[SYNC-PERIOD] [ETH-LATENCY] [PCAP-FILE]
\n
"
);
return
EXIT_FAILURE
;
// WMB();
rx
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_RECV
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
}
else
{
fprintf
(
stderr
,
"move_pkt: dropping packet
\n
"
);
}
}
else
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SYNC
)
{
}
else
{
fprintf
(
stderr
,
"move_pkt: unsupported type=%u
\n
"
,
type
);
abort
();
}
signal
(
SIGINT
,
sigint_handler
);
signal
(
SIGTERM
,
sigint_handler
);
signal
(
SIGUSR1
,
sigusr1_handler
);
if
(
argc
>=
4
)
sync_mode
=
strtol
(
argv
[
3
],
NULL
,
0
);
if
(
argc
>=
5
)
sync_period
=
strtoull
(
argv
[
4
],
NULL
,
0
)
*
1000ULL
;
if
(
argc
>=
6
)
eth_latency
=
strtoull
(
argv
[
5
],
NULL
,
0
)
*
1000ULL
;
if
(
argc
>=
7
)
{
pc
=
pcap_open_dead_with_tstamp_precision
(
DLT_EN10MB
,
65535
,
PCAP_TSTAMP_PRECISION_NANO
);
if
(
pc
==
NULL
)
{
perror
(
"pcap_open_dead failed"
);
return
EXIT_FAILURE
;
}
netsim_d2n_done
(
from
,
msg_from
);
}
dumpfile
=
pcap_dump_open
(
pc
,
argv
[
6
]);
int
main
(
int
argc
,
char
*
argv
[])
{
struct
netsim_interface
nsif_a
,
nsif_b
;
uint64_t
ts_a
,
ts_b
;
int
sync_a
,
sync_b
;
pcap_t
*
pc
=
NULL
;
int
sync_mode
=
SYNC_MODES
;
if
(
argc
<
3
&&
argc
>
7
)
{
fprintf
(
stderr
,
"Usage: net_wire SOCKET-A SOCKET-B [SYNC-MODE] "
"[SYNC-PERIOD] [ETH-LATENCY] [PCAP-FILE]
\n
"
);
return
EXIT_FAILURE
;
}
signal
(
SIGINT
,
sigint_handler
);
signal
(
SIGTERM
,
sigint_handler
);
signal
(
SIGUSR1
,
sigusr1_handler
);
if
(
argc
>=
4
)
sync_mode
=
strtol
(
argv
[
3
],
NULL
,
0
);
if
(
argc
>=
5
)
sync_period
=
strtoull
(
argv
[
4
],
NULL
,
0
)
*
1000ULL
;
if
(
argc
>=
6
)
eth_latency
=
strtoull
(
argv
[
5
],
NULL
,
0
)
*
1000ULL
;
if
(
argc
>=
7
)
{
pc
=
pcap_open_dead_with_tstamp_precision
(
DLT_EN10MB
,
65535
,
PCAP_TSTAMP_PRECISION_NANO
);
if
(
pc
==
NULL
)
{
perror
(
"pcap_open_dead failed"
);
return
EXIT_FAILURE
;
}
assert
(
sync_mode
==
SYNC_MODES
||
sync_mode
==
SYNC_BARRIER
);
sync_a
=
sync_b
=
1
;
if
(
netsim_init
(
&
nsif_a
,
argv
[
1
],
&
sync_a
)
!=
0
)
{
return
-
1
;
dumpfile
=
pcap_dump_open
(
pc
,
argv
[
6
]);
}
assert
(
sync_mode
==
SYNC_MODES
||
sync_mode
==
SYNC_BARRIER
);
sync_a
=
sync_b
=
1
;
if
(
netsim_init
(
&
nsif_a
,
argv
[
1
],
&
sync_a
)
!=
0
)
{
return
-
1
;
}
if
(
netsim_init
(
&
nsif_b
,
argv
[
2
],
&
sync_b
)
!=
0
)
{
return
-
1
;
}
printf
(
"start polling
\n
"
);
while
(
!
exiting
)
{
if
(
netsim_n2d_sync
(
&
nsif_a
,
cur_ts
,
eth_latency
,
sync_period
,
sync_mode
)
!=
0
)
{
fprintf
(
stderr
,
"netsim_n2d_sync(nsif_a) failed
\n
"
);
abort
();
}
if
(
netsim_init
(
&
nsif_b
,
argv
[
2
],
&
sync_b
)
!=
0
)
{
return
-
1
;
if
(
netsim_n2d_sync
(
&
nsif_b
,
cur_ts
,
eth_latency
,
sync_period
,
sync_mode
)
!=
0
)
{
fprintf
(
stderr
,
"netsim_n2d_sync(nsif_a) failed
\n
"
);
abort
();
}
printf
(
"start polling
\n
"
);
while
(
!
exiting
)
{
if
(
netsim_n2d_sync
(
&
nsif_a
,
cur_ts
,
eth_latency
,
sync_period
,
sync_mode
)
!=
0
)
{
fprintf
(
stderr
,
"netsim_n2d_sync(nsif_a) failed
\n
"
);
abort
();
}
if
(
netsim_n2d_sync
(
&
nsif_b
,
cur_ts
,
eth_latency
,
sync_period
,
sync_mode
)
!=
0
)
{
fprintf
(
stderr
,
"netsim_n2d_sync(nsif_a) failed
\n
"
);
abort
();
}
netsim_advance_epoch
(
cur_ts
,
sync_period
,
sync_mode
);
do
{
move_pkt
(
&
nsif_a
,
&
nsif_b
);
move_pkt
(
&
nsif_b
,
&
nsif_a
);
ts_a
=
netsim_d2n_timestamp
(
&
nsif_a
);
ts_b
=
netsim_d2n_timestamp
(
&
nsif_b
);
}
while
(
!
exiting
&&
((
sync_a
&&
ts_a
<=
cur_ts
)
||
(
sync_b
&&
ts_b
<=
cur_ts
)));
if
(
sync_a
&&
sync_b
)
cur_ts
=
netsim_advance_time
(
ts_a
<=
ts_b
?
ts_a
:
ts_b
,
sync_period
,
sync_mode
);
else
if
(
sync_a
)
cur_ts
=
netsim_advance_time
(
ts_a
,
sync_period
,
sync_mode
);
else
if
(
sync_b
)
cur_ts
=
netsim_advance_time
(
ts_b
,
sync_period
,
sync_mode
);
}
if
(
dumpfile
)
pcap_dump_close
(
dumpfile
);
return
0
;
netsim_advance_epoch
(
cur_ts
,
sync_period
,
sync_mode
);
do
{
move_pkt
(
&
nsif_a
,
&
nsif_b
);
move_pkt
(
&
nsif_b
,
&
nsif_a
);
ts_a
=
netsim_d2n_timestamp
(
&
nsif_a
);
ts_b
=
netsim_d2n_timestamp
(
&
nsif_b
);
}
while
(
!
exiting
&&
((
sync_a
&&
ts_a
<=
cur_ts
)
||
(
sync_b
&&
ts_b
<=
cur_ts
)));
if
(
sync_a
&&
sync_b
)
cur_ts
=
netsim_advance_time
(
ts_a
<=
ts_b
?
ts_a
:
ts_b
,
sync_period
,
sync_mode
);
else
if
(
sync_a
)
cur_ts
=
netsim_advance_time
(
ts_a
,
sync_period
,
sync_mode
);
else
if
(
sync_b
)
cur_ts
=
netsim_advance_time
(
ts_b
,
sync_period
,
sync_mode
);
}
if
(
dumpfile
)
pcap_dump_close
(
dumpfile
);
return
0
;
}
sims/nic/corundum/coord.h
View file @
d4666c97
...
...
@@ -26,8 +26,8 @@
#define COORD_H_
#include <deque>
#include <map>
#include <iostream>
#include <map>
#include "sims/nic/corundum/debug.h"
...
...
@@ -39,116 +39,107 @@ void pci_msi_issue(uint8_t vec);
void
pci_rwcomp_issue
(
MMIOOp
*
op
);
class
PCICoordinator
{
protected:
struct
PCIOp
{
union
{
DMAOp
*
dma_op
;
MMIOOp
*
mmio_op
;
uint32_t
msi_vec
;
};
enum
{
OP_DMA
,
OP_MSI
,
OP_RWCOMP
,
}
type
;
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
->
type
==
PCIOp
::
OP_MSI
)
{
protected:
struct
PCIOp
{
union
{
DMAOp
*
dma_op
;
MMIOOp
*
mmio_op
;
uint32_t
msi_vec
;
};
enum
{
OP_DMA
,
OP_MSI
,
OP_RWCOMP
,
}
type
;
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
->
type
==
PCIOp
::
OP_MSI
)
{
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" issuing msi "
<<
op
->
msi_vec
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" issuing msi "
<<
op
->
msi_vec
<<
std
::
endl
;
#endif
pci_msi_issue
(
op
->
msi_vec
);
}
else
if
(
op
->
type
==
PCIOp
::
OP_DMA
)
{
pci_msi_issue
(
op
->
msi_vec
);
}
else
if
(
op
->
type
==
PCIOp
::
OP_DMA
)
{
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" issuing dma "
<<
op
->
dma_op
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" issuing dma "
<<
op
->
dma_op
<<
std
::
endl
;
#endif
pci_dma_issue
(
op
->
dma_op
);
dmamap
.
erase
(
op
->
dma_op
);
}
else
if
(
op
->
type
==
PCIOp
::
OP_RWCOMP
)
{
pci_dma_issue
(
op
->
dma_op
);
dmamap
.
erase
(
op
->
dma_op
);
}
else
if
(
op
->
type
==
PCIOp
::
OP_RWCOMP
)
{
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" issuing mmio "
<<
op
->
mmio_op
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" issuing mmio "
<<
op
->
mmio_op
<<
std
::
endl
;
#endif
pci_rwcomp_issue
(
op
->
mmio_op
);
}
else
{
throw
"unknown type"
;
}
delete
op
;
}
}
public:
void
dma_register
(
DMAOp
*
dma_op
,
bool
ready
)
{
pci_rwcomp_issue
(
op
->
mmio_op
);
}
else
{
throw
"unknown type"
;
}
delete
op
;
}
}
public:
void
dma_register
(
DMAOp
*
dma_op
,
bool
ready
)
{
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" registering dma op "
<<
dma_op
<<
" "
<<
ready
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" registering dma op "
<<
dma_op
<<
" "
<<
ready
<<
std
::
endl
;
#endif
PCIOp
*
op
=
new
PCIOp
;
op
->
dma_op
=
dma_op
;
op
->
type
=
PCIOp
::
OP_DMA
;
op
->
ready
=
ready
;
PCIOp
*
op
=
new
PCIOp
;
op
->
dma_op
=
dma_op
;
op
->
type
=
PCIOp
::
OP_DMA
;
op
->
ready
=
ready
;
queue
.
push_back
(
op
);
dmamap
[
dma_op
]
=
op
;
queue
.
push_back
(
op
);
dmamap
[
dma_op
]
=
op
;
process
();
}
process
();
}
void
dma_mark_ready
(
DMAOp
*
op
)
{
void
dma_mark_ready
(
DMAOp
*
op
)
{
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" readying dma op "
<<
op
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" readying dma op "
<<
op
<<
std
::
endl
;
#endif
dmamap
[
op
]
->
ready
=
true
;
dmamap
[
op
]
->
ready
=
true
;
process
();
}
process
();
}
void
msi_enqueue
(
uint32_t
vec
)
{
void
msi_enqueue
(
uint32_t
vec
)
{
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" enqueuing MSI "
<<
vec
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" enqueuing MSI "
<<
vec
<<
std
::
endl
;
#endif
PCIOp
*
op
=
new
PCIOp
;
op
->
msi_vec
=
vec
;
op
->
type
=
PCIOp
::
OP_MSI
;
op
->
ready
=
true
;
queue
.
push_back
(
op
);
PCIOp
*
op
=
new
PCIOp
;
op
->
msi_vec
=
vec
;
op
->
type
=
PCIOp
::
OP_MSI
;
op
->
ready
=
true
;
queue
.
push_back
(
op
);
process
();
}
process
();
}
void
mmio_comp_enqueue
(
MMIOOp
*
mmio_op
)
{
void
mmio_comp_enqueue
(
MMIOOp
*
mmio_op
)
{
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" enqueuing MMIO comp "
<<
mmio_op
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" enqueuing MMIO comp "
<<
mmio_op
<<
std
::
endl
;
#endif
PCIOp
*
op
=
new
PCIOp
;
op
->
mmio_op
=
mmio_op
;
op
->
type
=
PCIOp
::
OP_RWCOMP
;
op
->
ready
=
true
;
queue
.
push_back
(
op
);
process
();
}
PCIOp
*
op
=
new
PCIOp
;
op
->
mmio_op
=
mmio_op
;
op
->
type
=
PCIOp
::
OP_RWCOMP
;
op
->
ready
=
true
;
queue
.
push_back
(
op
);
process
();
}
};
#endif // COORD_H_
sims/nic/corundum/corundum_verilator.cc
View file @
d4666c97
This diff is collapsed.
Click to expand it.
sims/nic/corundum/dma.cc
View file @
d4666c97
...
...
@@ -22,126 +22,117 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "sims/nic/corundum/dma.h"
#include <iostream>
#include "sims/nic/corundum/debug.h"
#include "sims/nic/corundum/corundum.h"
#include "sims/nic/corundum/d
ma
.h"
#include "sims/nic/corundum/d
ebug
.h"
#include "sims/nic/corundum/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
);
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
);
#ifdef DMA_DEBUG
std
::
cout
<<
main_time
<<
" dma["
<<
label
<<
"] op "
<<
std
::
hex
<<
op
->
dma_addr
<<
" -> "
<<
op
->
ram_sel
<<
":"
<<
op
->
ram_addr
<<
" len="
<<
op
->
len
<<
" tag="
<<
(
int
)
op
->
tag
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" dma["
<<
label
<<
"] op "
<<
std
::
hex
<<
op
->
dma_addr
<<
" -> "
<<
op
->
ram_sel
<<
":"
<<
op
->
ram_addr
<<
" len="
<<
op
->
len
<<
" tag="
<<
(
int
)
op
->
tag
<<
std
::
endl
;
#endif
coord
.
dma_register
(
op
,
true
);
}
coord
.
dma_register
(
op
,
true
);
}
p
.
dma_status_valid
=
0
;
if
(
!
completed
.
empty
())
{
DMAOp
*
op
=
completed
.
front
();
completed
.
pop_front
();
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;
// 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
;
}
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
::
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;
void
DMAReader
::
mem_op_complete
(
DMAOp
*
op
)
{
completed
.
push_back
(
op
);
// std::cout << "dma[" << label << "] mem complete " << op->dma_addr <<
// std::endl;
}
void
DMAWriter
::
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
=
true
;
pending
.
insert
(
op
);
void
DMAWriter
::
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
=
true
;
pending
.
insert
(
op
);
#ifdef DMA_DEBUG
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] op "
<<
std
::
hex
<<
op
->
dma_addr
<<
" -> "
<<
op
->
ram_sel
<<
":"
<<
op
->
ram_addr
<<
" len="
<<
op
->
len
<<
" tag="
<<
(
int
)
op
->
tag
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] op "
<<
std
::
hex
<<
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
);
}
coord
.
dma_register
(
op
,
false
);
mr
.
op_issue
(
op
);
}
p
.
dma_status_valid
=
0
;
if
(
!
completed
.
empty
())
{
DMAOp
*
op
=
completed
.
front
();
completed
.
pop_front
();
p
.
dma_status_valid
=
0
;
if
(
!
completed
.
empty
())
{
DMAOp
*
op
=
completed
.
front
();
completed
.
pop_front
();
#ifdef DMA_DEBUG
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] status complete "
<<
op
->
dma_addr
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] status complete "
<<
op
->
dma_addr
<<
std
::
endl
;
#endif
p
.
dma_status_valid
=
1
;
p
.
dma_status_tag
=
op
->
tag
;
pending
.
erase
(
op
);
// coord.msi_enqueue(0);
delete
op
;
}
p
.
dma_status_valid
=
1
;
p
.
dma_status_tag
=
op
->
tag
;
pending
.
erase
(
op
);
// coord.msi_enqueue(0);
delete
op
;
}
}
void
DMAWriter
::
pci_op_complete
(
DMAOp
*
op
)
{
void
DMAWriter
::
pci_op_complete
(
DMAOp
*
op
)
{
#ifdef DMA_DEBUG
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] pci complete "
<<
op
->
dma_addr
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" 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
<<
main_time
<<
" dma write ["
<<
label
<<
"] mem complete "
<<
op
->
dma_addr
<<
": "
;
for
(
size_t
i
=
0
;
i
<
op
->
len
;
i
++
)
std
::
cout
<<
(
unsigned
)
op
->
data
[
i
]
<<
" "
;
std
::
cout
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] mem complete "
<<
op
->
dma_addr
<<
": "
;
for
(
size_t
i
=
0
;
i
<
op
->
len
;
i
++
)
std
::
cout
<<
(
unsigned
)
op
->
data
[
i
]
<<
" "
;
std
::
cout
<<
std
::
endl
;
#endif
coord
.
dma_mark_ready
(
op
);
coord
.
dma_mark_ready
(
op
);
}
sims/nic/corundum/dma.h
View file @
d4666c97
...
...
@@ -25,15 +25,14 @@
#ifndef DMA_H_
#define DMA_H_
#include <set>
#include <deque>
#include <verilated.h>
#include "sims/nic/corundum/obj_dir/Vinterface.h"
#include <deque>
#include <set>
#include "sims/nic/corundum/debug.h"
#include "sims/nic/corundum/coord.h"
#include "sims/nic/corundum/debug.h"
#include "sims/nic/corundum/obj_dir/Vinterface.h"
#define MAX_DMA_LEN 2048
...
...
@@ -42,95 +41,93 @@ class MemWriter;
class
MemReader
;
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_
)
{
}
/* 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
];
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
;
PCICoordinator
&
coord
;
protected:
DMAPorts
&
p
;
PCICoordinator
&
coord
;
DMAEngine
(
DMAPorts
&
p_
,
PCICoordinator
&
coord_
)
:
p
(
p_
),
coord
(
coord_
)
{
}
DMAEngine
(
DMAPorts
&
p_
,
PCICoordinator
&
coord_
)
:
p
(
p_
),
coord
(
coord_
)
{
}
public:
virtual
void
pci_op_complete
(
DMAOp
*
op
)
=
0
;
virtual
void
mem_op_complete
(
DMAOp
*
op
)
=
0
;
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_
,
PCICoordinator
&
coord_
)
:
DMAEngine
(
p_
,
coord_
),
label
(
label_
),
mw
(
mw_
)
{
}
virtual
void
pci_op_complete
(
DMAOp
*
op
);
virtual
void
mem_op_complete
(
DMAOp
*
op
);
void
step
();
protected:
std
::
set
<
DMAOp
*>
pending
;
std
::
deque
<
DMAOp
*>
completed
;
const
char
*
label
;
MemWriter
&
mw
;
public:
DMAReader
(
const
char
*
label_
,
DMAPorts
&
p_
,
MemWriter
&
mw_
,
PCICoordinator
&
coord_
)
:
DMAEngine
(
p_
,
coord_
),
label
(
label_
),
mw
(
mw_
)
{
}
virtual
void
pci_op_complete
(
DMAOp
*
op
);
virtual
void
mem_op_complete
(
DMAOp
*
op
);
void
step
();
};
class
DMAWriter
:
public
DMAEngine
{
protected:
std
::
set
<
DMAOp
*>
pending
;
std
::
deque
<
DMAOp
*>
completed
;
const
char
*
label
;
MemReader
&
mr
;
public:
DMAWriter
(
const
char
*
label_
,
DMAPorts
&
p_
,
MemReader
&
mr_
,
PCICoordinator
&
coord_
)
:
DMAEngine
(
p_
,
coord_
),
label
(
label_
),
mr
(
mr_
)
{
}
virtual
void
pci_op_complete
(
DMAOp
*
op
);
virtual
void
mem_op_complete
(
DMAOp
*
op
);
void
step
();
protected:
std
::
set
<
DMAOp
*>
pending
;
std
::
deque
<
DMAOp
*>
completed
;
const
char
*
label
;
MemReader
&
mr
;
public:
DMAWriter
(
const
char
*
label_
,
DMAPorts
&
p_
,
MemReader
&
mr_
,
PCICoordinator
&
coord_
)
:
DMAEngine
(
p_
,
coord_
),
label
(
label_
),
mr
(
mr_
)
{
}
virtual
void
pci_op_complete
(
DMAOp
*
op
);
virtual
void
mem_op_complete
(
DMAOp
*
op
);
void
step
();
};
#endif // DMA_H_
sims/nic/corundum/mem.cc
View file @
d4666c97
...
...
@@ -22,10 +22,11 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "sims/nic/corundum/mem.h"
#include <iostream>
#include "sims/nic/corundum/debug.h"
#include "sims/nic/corundum/mem.h"
#include "sims/nic/corundum/dma.h"
/*
...
...
@@ -40,173 +41,163 @@
#define SEG_COUNT 8
#define SEG_WIDTH (DATA_WIDTH / SEG_COUNT)
void
MemWriter
::
step
()
{
if
(
cur
&&
p
.
mem_ready
&&
((
p
.
mem_ready
&
p
.
mem_valid
)
==
p
.
mem_valid
))
{
void
MemWriter
::
step
()
{
if
(
cur
&&
p
.
mem_ready
&&
((
p
.
mem_ready
&
p
.
mem_valid
)
==
p
.
mem_valid
))
{
#ifdef MEM_DEBUG
std
::
cerr
<<
"completed write to: "
<<
cur
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
"completed write to: "
<<
cur
->
ram_addr
<<
std
::
endl
;
#endif
p
.
mem_valid
=
0
;
p
.
mem_be
[
0
]
=
p
.
mem_be
[
1
]
=
p
.
mem_be
[
2
]
=
p
.
mem_be
[
3
]
=
0
;
if
(
cur_off
==
cur
->
len
)
{
/* operation is done */
pending
.
pop_front
();
cur
->
engine
->
mem_op_complete
(
cur
);
cur_off
=
0
;
}
else
{
/* operation is not done yet, we'll pick it back up */
}
cur
=
0
;
}
else
if
(
!
cur
&&
!
pending
.
empty
())
{
cur
=
pending
.
front
();
p
.
mem_valid
=
0
;
p
.
mem_be
[
0
]
=
p
.
mem_be
[
1
]
=
p
.
mem_be
[
2
]
=
p
.
mem_be
[
3
]
=
0
;
if
(
cur_off
==
cur
->
len
)
{
/* operation is done */
pending
.
pop_front
();
cur
->
engine
->
mem_op_complete
(
cur
);
cur_off
=
0
;
}
else
{
/* operation is not done yet, we'll pick it back up */
}
cur
=
0
;
}
else
if
(
!
cur
&&
!
pending
.
empty
())
{
cur
=
pending
.
front
();
#ifdef MEM_DEBUG
std
::
cerr
<<
"issuing write to "
<<
cur
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
"issuing write to "
<<
cur
->
ram_addr
<<
std
::
endl
;
#endif
size_t
data_byte_width
=
DATA_WIDTH
/
8
;
size_t
data_offset
=
(
cur
->
ram_addr
+
cur_off
)
%
data_byte_width
;
/* 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
;
for
(
size_t
i
=
0
;
i
<
data_byte_width
/
4
;
i
++
)
p
.
mem_data
[
i
]
=
0
;
/* put data bytes in the right places */
size_t
off
=
data_offset
;
size_t
cur_len
=
(
cur
->
len
-
cur_off
>
data_byte_width
-
data_offset
?
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
;
p
.
mem_data
[
off
/
4
]
|=
(((
uint32_t
)
cur
->
data
[
cur_off
+
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
+
cur_off
)
/
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
));
}
}
cur_off
+=
cur_len
;
size_t
data_byte_width
=
DATA_WIDTH
/
8
;
size_t
data_offset
=
(
cur
->
ram_addr
+
cur_off
)
%
data_byte_width
;
/* 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
;
for
(
size_t
i
=
0
;
i
<
data_byte_width
/
4
;
i
++
)
p
.
mem_data
[
i
]
=
0
;
/* put data bytes in the right places */
size_t
off
=
data_offset
;
size_t
cur_len
=
(
cur
->
len
-
cur_off
>
data_byte_width
-
data_offset
?
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
;
p
.
mem_data
[
off
/
4
]
|=
(((
uint32_t
)
cur
->
data
[
cur_off
+
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
+
cur_off
)
/
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
));
}
}
cur_off
+=
cur_len
;
}
}
void
MemWriter
::
op_issue
(
DMAOp
*
op
)
{
void
MemWriter
::
op_issue
(
DMAOp
*
op
)
{
#ifdef MEM_DEBUG
std
::
cerr
<<
"enqueued write to "
<<
op
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
"enqueued write to "
<<
op
->
ram_addr
<<
std
::
endl
;
#endif
pending
.
push_back
(
op
);
pending
.
push_back
(
op
);
}
void
MemReader
::
step
()
{
size_t
data_byte_width
=
DATA_WIDTH
/
8
;
void
MemReader
::
step
()
{
size_t
data_byte_width
=
DATA_WIDTH
/
8
;
if
(
cur
&&
p
.
mem_resvalid
&&
((
p
.
mem_resvalid
&
p
.
mem_valid
)
==
p
.
mem_valid
))
{
if
(
cur
&&
p
.
mem_resvalid
&&
((
p
.
mem_resvalid
&
p
.
mem_valid
)
==
p
.
mem_valid
))
{
#ifdef MEM_DEBUG
std
::
cerr
<<
"completed read from: "
<<
std
::
hex
<<
cur
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
" reval = "
<<
(
unsigned
)
p
.
mem_resvalid
<<
std
::
endl
;
std
::
cerr
<<
"completed read from: "
<<
std
::
hex
<<
cur
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
" reval = "
<<
(
unsigned
)
p
.
mem_resvalid
<<
std
::
endl
;
#endif
p
.
mem_valid
=
0
;
p
.
mem_valid
=
0
;
#ifdef MEM_DEBUG
for
(
size_t
i
=
0
;
i
<
32
;
i
++
)
std
::
cerr
<<
" val = "
<<
p
.
mem_data
[
i
]
<<
std
::
endl
;
for
(
size_t
i
=
0
;
i
<
32
;
i
++
)
std
::
cerr
<<
" val = "
<<
p
.
mem_data
[
i
]
<<
std
::
endl
;
#endif
size_t
off
=
(
cur
->
ram_addr
+
cur_off
)
%
data_byte_width
;
size_t
cur_len
=
(
cur
->
len
-
cur_off
>
data_byte_width
-
off
?
data_byte_width
-
off
:
cur
->
len
-
cur_
off
);
for
(
size_t
i
=
0
;
i
<
cur
_
len
;
i
++
,
off
++
)
{
size_t
byte_off
=
(
off
%
4
);
cur
->
data
[
cur_off
+
i
]
=
(
p
.
mem_data
[
off
/
4
]
>>
(
byte_off
*
8
))
&
0xff
;
}
cur_off
+=
cur_len
;
if
(
cur_off
==
cur
->
len
)
{
/* operation is done */
pending
.
pop_front
();
cur
->
engine
->
mem_op_complete
(
cur
);
cur_off
=
0
;
}
else
{
/* operation is not done yet, we'll pick it back up */
}
cur
=
0
;
}
else
if
(
!
cur
&&
!
pending
.
empty
())
{
cur
=
pending
.
front
();
size_t
data_offset
=
(
cur
->
ram_addr
+
cur_off
)
%
data_byte_width
;
size_t
off
=
(
cur
->
ram_addr
+
cur_off
)
%
data_byte_width
;
size_t
cur_len
=
(
cur
->
len
-
cur_off
>
data_byte_width
-
off
?
data_byte_width
-
off
:
cur
->
len
-
cur_off
);
for
(
size_t
i
=
0
;
i
<
cur_len
;
i
++
,
off
++
)
{
size_t
byte_off
=
(
off
%
4
);
cur
->
data
[
cur_off
+
i
]
=
(
p
.
mem_data
[
off
/
4
]
>>
(
byte_off
*
8
))
&
0xff
;
}
cur_off
+=
cur_len
;
if
(
cur_off
==
cur
->
len
)
{
/* operation is done */
pending
.
pop_front
();
cur
->
engine
->
mem_op_complete
(
cur
);
cur_off
=
0
;
}
else
{
/* operation is not done yet, we'll pick it back up */
}
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 op="
<<
cur
<<
" read from "
<<
std
::
hex
<<
cur
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
" off="
<<
data_offset
<<
std
::
endl
;
std
::
cerr
<<
"issuing op="
<<
cur
<<
" read from "
<<
std
::
hex
<<
cur
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
" off="
<<
data_offset
<<
std
::
endl
;
#endif
/* first reset everything */
p
.
mem_sel
=
0
;
p
.
mem_addr
[
0
]
=
p
.
mem_addr
[
1
]
=
p
.
mem_addr
[
2
]
=
0
;
p
.
mem_valid
=
0x0
;
/* put data bytes in the right places */
size_t
off
=
data_offset
;
size_t
cur_len
=
(
cur
->
len
-
cur_off
>
data_byte_width
-
data_offset
?
data_byte_width
-
data_offset
:
cur
->
len
-
cur_off
);
for
(
size_t
i
=
0
;
i
<
cur_len
;
i
++
,
off
++
)
{
p
.
mem_valid
|=
(
1
<<
(
off
/
(
SEG_WIDTH
/
8
)));
}
// p.mem_resready = p.mem_valid;
p
.
mem_resready
=
0xff
;
uint64_t
seg_addr
=
(
cur
->
ram_addr
+
cur_off
)
/
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
));
}
}
/* first reset everything */
p
.
mem_sel
=
0
;
p
.
mem_addr
[
0
]
=
p
.
mem_addr
[
1
]
=
p
.
mem_addr
[
2
]
=
0
;
p
.
mem_valid
=
0x0
;
/* put data bytes in the right places */
size_t
off
=
data_offset
;
size_t
cur_len
=
(
cur
->
len
-
cur_off
>
data_byte_width
-
data_offset
?
data_byte_width
-
data_offset
:
cur
->
len
-
cur_off
);
for
(
size_t
i
=
0
;
i
<
cur_len
;
i
++
,
off
++
)
{
p
.
mem_valid
|=
(
1
<<
(
off
/
(
SEG_WIDTH
/
8
)));
}
// p.mem_resready = p.mem_valid;
p
.
mem_resready
=
0xff
;
uint64_t
seg_addr
=
(
cur
->
ram_addr
+
cur_off
)
/
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
));
}
}
#ifdef MEM_DEBUG
for
(
size_t
i
=
0
;
i
<
3
;
i
++
)
std
::
cerr
<<
" addr = "
<<
p
.
mem_addr
[
i
]
<<
std
::
endl
;
std
::
cerr
<<
" mem_valid = "
<<
(
unsigned
)
p
.
mem_valid
<<
std
::
endl
;
for
(
size_t
i
=
0
;
i
<
3
;
i
++
)
std
::
cerr
<<
" addr = "
<<
p
.
mem_addr
[
i
]
<<
std
::
endl
;
std
::
cerr
<<
" mem_valid = "
<<
(
unsigned
)
p
.
mem_valid
<<
std
::
endl
;
#endif
}
}
}
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
);
}
sims/nic/corundum/mem.h
View file @
d4666c97
This diff is collapsed.
Click to expand it.
sims/nic/corundum_bm/corundum_bm.cc
View file @
d4666c97
This diff is collapsed.
Click to expand it.
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment