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
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 @@
...
@@ -22,183 +22,174 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <unistd.h>
#include <unistd.h>
#include <simbricks/netif/netsim.h>
#include <simbricks/netif/netsim.h>
#include "lib/simbricks/netif/internal.h"
#include "lib/simbricks/netif/internal.h"
static
uint64_t
current_epoch
=
0
;
static
uint64_t
current_epoch
=
0
;
int
netsim_init
(
struct
netsim_interface
*
nsif
,
int
netsim_init
(
struct
netsim_interface
*
nsif
,
const
char
*
eth_socket_path
,
const
char
*
eth_socket_path
,
int
*
sync_eth
)
int
*
sync_eth
)
{
{
struct
cosim_eth_proto_dev_intro
di
;
struct
cosim_eth_proto_dev_intro
di
;
struct
cosim_eth_proto_net_intro
ni
;
struct
cosim_eth_proto_net_intro
ni
;
int
cfd
,
shm_fd
;
int
cfd
,
shm_fd
;
void
*
p
;
void
*
p
;
if
((
cfd
=
uxsocket_connect
(
eth_socket_path
))
<
0
)
{
if
((
cfd
=
uxsocket_connect
(
eth_socket_path
))
<
0
)
{
return
-
1
;
return
-
1
;
}
}
memset
(
&
ni
,
0
,
sizeof
(
ni
));
memset
(
&
ni
,
0
,
sizeof
(
ni
));
if
(
*
sync_eth
)
if
(
*
sync_eth
)
ni
.
flags
|=
COSIM_ETH_PROTO_FLAGS_NI_SYNC
;
ni
.
flags
|=
COSIM_ETH_PROTO_FLAGS_NI_SYNC
;
if
(
send
(
cfd
,
&
ni
,
sizeof
(
ni
),
0
)
!=
sizeof
(
ni
))
{
if
(
send
(
cfd
,
&
ni
,
sizeof
(
ni
),
0
)
!=
sizeof
(
ni
))
{
perror
(
"sending net intro failed"
);
perror
(
"sending net intro failed"
);
return
-
1
;
return
-
1
;
}
}
if
(
uxsocket_recv
(
cfd
,
&
di
,
sizeof
(
di
),
&
shm_fd
))
{
if
(
uxsocket_recv
(
cfd
,
&
di
,
sizeof
(
di
),
&
shm_fd
))
{
return
-
1
;
return
-
1
;
}
}
if
((
p
=
shm_map
(
shm_fd
))
==
NULL
)
{
if
((
p
=
shm_map
(
shm_fd
))
==
NULL
)
{
return
-
1
;
return
-
1
;
}
}
close
(
shm_fd
);
close
(
shm_fd
);
if
((
di
.
flags
&
COSIM_ETH_PROTO_FLAGS_DI_SYNC
)
==
0
)
{
if
((
di
.
flags
&
COSIM_ETH_PROTO_FLAGS_DI_SYNC
)
==
0
)
{
*
sync_eth
=
0
;
*
sync_eth
=
0
;
nsif
->
sync
=
0
;
nsif
->
sync
=
0
;
}
else
{
}
else
{
nsif
->
sync
=
*
sync_eth
;
nsif
->
sync
=
*
sync_eth
;
}
}
nsif
->
d2n_queue
=
(
uint8_t
*
)
p
+
di
.
d2n_offset
;
nsif
->
d2n_queue
=
(
uint8_t
*
)
p
+
di
.
d2n_offset
;
nsif
->
n2d_queue
=
(
uint8_t
*
)
p
+
di
.
n2d_offset
;
nsif
->
n2d_queue
=
(
uint8_t
*
)
p
+
di
.
n2d_offset
;
nsif
->
d2n_elen
=
di
.
d2n_elen
;
nsif
->
d2n_elen
=
di
.
d2n_elen
;
nsif
->
n2d_elen
=
di
.
n2d_elen
;
nsif
->
n2d_elen
=
di
.
n2d_elen
;
nsif
->
d2n_enum
=
di
.
d2n_nentries
;
nsif
->
d2n_enum
=
di
.
d2n_nentries
;
nsif
->
n2d_enum
=
di
.
n2d_nentries
;
nsif
->
n2d_enum
=
di
.
n2d_nentries
;
nsif
->
d2n_pos
=
nsif
->
n2d_pos
=
0
;
nsif
->
d2n_pos
=
nsif
->
n2d_pos
=
0
;
nsif
->
d2n_timestamp
=
nsif
->
n2d_timestamp
=
0
;
nsif
->
d2n_timestamp
=
nsif
->
n2d_timestamp
=
0
;
return
0
;
return
0
;
}
}
void
netsim_cleanup
(
struct
netsim_interface
*
nsif
)
void
netsim_cleanup
(
struct
netsim_interface
*
nsif
)
{
{
fprintf
(
stderr
,
"netsim_cleanup: TODO
\n
"
);
fprintf
(
stderr
,
"netsim_cleanup: TODO
\n
"
);
abort
();
abort
();
}
}
volatile
union
cosim_eth_proto_d2n
*
netsim_d2n_poll
(
volatile
union
cosim_eth_proto_d2n
*
netsim_d2n_poll
(
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
)
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
)
{
{
volatile
union
cosim_eth_proto_d2n
*
msg
=
volatile
union
cosim_eth_proto_d2n
*
msg
=
(
volatile
union
cosim_eth_proto_d2n
*
)(
nsif
->
d2n_queue
+
(
volatile
union
cosim_eth_proto_d2n
*
)
nsif
->
d2n_pos
*
nsif
->
d2n_elen
);
(
nsif
->
d2n_queue
+
nsif
->
d2n_pos
*
nsif
->
d2n_elen
);
/* message not ready */
/* message not ready */
if
((
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_OWN_MASK
)
!=
if
((
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_OWN_MASK
)
!=
COSIM_ETH_PROTO_D2N_OWN_NET
)
COSIM_ETH_PROTO_D2N_OWN_NET
)
return
NULL
;
return
NULL
;
/* if in sync mode, wait till message is ready */
/* if in sync mode, wait till message is ready */
nsif
->
d2n_timestamp
=
msg
->
dummy
.
timestamp
;
nsif
->
d2n_timestamp
=
msg
->
dummy
.
timestamp
;
if
(
nsif
->
sync
&&
nsif
->
d2n_timestamp
>
timestamp
)
if
(
nsif
->
sync
&&
nsif
->
d2n_timestamp
>
timestamp
)
return
NULL
;
return
NULL
;
nsif
->
d2n_pos
=
(
nsif
->
d2n_pos
+
1
)
%
nsif
->
d2n_enum
;
nsif
->
d2n_pos
=
(
nsif
->
d2n_pos
+
1
)
%
nsif
->
d2n_enum
;
return
msg
;
return
msg
;
}
}
void
netsim_d2n_done
(
struct
netsim_interface
*
nsif
,
void
netsim_d2n_done
(
struct
netsim_interface
*
nsif
,
volatile
union
cosim_eth_proto_d2n
*
msg
)
volatile
union
cosim_eth_proto_d2n
*
msg
)
{
{
msg
->
dummy
.
own_type
=
(
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
)
|
msg
->
dummy
.
own_type
=
(
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
)
COSIM_ETH_PROTO_D2N_OWN_DEV
;
|
COSIM_ETH_PROTO_D2N_OWN_DEV
;
}
}
volatile
union
cosim_eth_proto_n2d
*
netsim_n2d_alloc
(
volatile
union
cosim_eth_proto_n2d
*
netsim_n2d_alloc
(
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
uint64_t
latency
)
{
uint64_t
latency
)
volatile
union
cosim_eth_proto_n2d
*
msg
=
{
(
volatile
union
cosim_eth_proto_n2d
*
)(
nsif
->
n2d_queue
+
volatile
union
cosim_eth_proto_n2d
*
msg
=
nsif
->
n2d_pos
*
nsif
->
n2d_elen
);
(
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
)
{
if
((
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_N2D_OWN_MASK
)
!=
return
NULL
;
COSIM_ETH_PROTO_N2D_OWN_NET
)
}
{
return
NULL
;
}
msg
->
dummy
.
timestamp
=
timestamp
+
latency
;
msg
->
dummy
.
timestamp
=
timestamp
+
latency
;
nsif
->
n2d_timestamp
=
timestamp
;
nsif
->
n2d_timestamp
=
timestamp
;
nsif
->
n2d_pos
=
(
nsif
->
n2d_pos
+
1
)
%
nsif
->
n2d_enum
;
nsif
->
n2d_pos
=
(
nsif
->
n2d_pos
+
1
)
%
nsif
->
n2d_enum
;
return
msg
;
return
msg
;
}
}
int
netsim_n2d_sync
(
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
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
)
{
{
volatile
union
cosim_eth_proto_n2d
*
msg
;
volatile
union
cosim_eth_proto_n2d
*
msg
;
volatile
struct
cosim_eth_proto_n2d_sync
*
sync
;
volatile
struct
cosim_eth_proto_n2d_sync
*
sync
;
int
do_sync
;
int
do_sync
;
if
(
!
nsif
->
sync
)
if
(
!
nsif
->
sync
)
return
0
;
return
0
;
switch
(
sync_mode
)
{
switch
(
sync_mode
)
{
case
SYNC_MODES
:
case
SYNC_MODES
:
do_sync
=
nsif
->
n2d_timestamp
==
0
||
do_sync
=
nsif
->
n2d_timestamp
==
0
||
timestamp
-
nsif
->
n2d_timestamp
>=
sync_delay
;
timestamp
-
nsif
->
n2d_timestamp
>=
sync_delay
;
break
;
break
;
case
SYNC_BARRIER
:
case
SYNC_BARRIER
:
do_sync
=
current_epoch
==
0
||
do_sync
=
current_epoch
==
0
||
timestamp
-
current_epoch
>=
sync_delay
;
timestamp
-
current_epoch
>=
sync_delay
;
break
;
break
;
default:
default:
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
sync_mode
);
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
sync_mode
);
return
0
;
return
0
;
}
}
if
(
!
do_sync
)
{
if
(
!
do_sync
)
{
return
0
;
return
0
;
}
}
msg
=
netsim_n2d_alloc
(
nsif
,
timestamp
,
latency
);
msg
=
netsim_n2d_alloc
(
nsif
,
timestamp
,
latency
);
if
(
msg
==
NULL
)
if
(
msg
==
NULL
)
return
-
1
;
return
-
1
;
sync
=
&
msg
->
sync
;
sync
=
&
msg
->
sync
;
// WMB();
// WMB();
sync
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_SYNC
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
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
,
void
netsim_advance_epoch
(
uint64_t
timestamp
,
uint64_t
sync_delay
,
int
sync_mode
)
int
sync_mode
)
{
{
if
(
sync_mode
==
SYNC_BARRIER
)
{
if
(
sync_mode
==
SYNC_BARRIER
)
{
if
(
timestamp
-
current_epoch
>=
sync_delay
)
{
if
(
timestamp
-
current_epoch
>=
sync_delay
)
{
current_epoch
=
timestamp
;
current_epoch
=
timestamp
;
}
}
}
}
}
}
uint64_t
netsim_advance_time
(
uint64_t
timestamp
,
uint64_t
sync_delay
,
uint64_t
netsim_advance_time
(
uint64_t
timestamp
,
uint64_t
sync_delay
,
int
sync_mode
)
int
sync_mode
)
{
{
switch
(
sync_mode
)
{
switch
(
sync_mode
)
{
case
SYNC_MODES
:
case
SYNC_MODES
:
return
timestamp
;
return
timestamp
;
case
SYNC_BARRIER
:
case
SYNC_BARRIER
:
return
timestamp
<
current_epoch
+
sync_delay
?
return
timestamp
<
current_epoch
+
sync_delay
timestamp
:
current_epoch
+
sync_delay
;
?
timestamp
:
current_epoch
+
sync_delay
;
default:
default:
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
sync_mode
);
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
sync_mode
);
return
timestamp
;
return
timestamp
;
}
}
}
}
lib/simbricks/netif/netsim.h
View file @
d4666c97
...
@@ -27,48 +27,47 @@
...
@@ -27,48 +27,47 @@
#include <stddef.h>
#include <stddef.h>
#include <stdint.h>
#include <stdint.h>
#include <simbricks/proto/network.h>
#include <simbricks/proto/network.h>
#define SYNC_MODES 0
#define SYNC_MODES 0
#define SYNC_BARRIER 1
#define SYNC_BARRIER 1
struct
netsim_interface
{
struct
netsim_interface
{
uint8_t
*
d2n_queue
;
uint8_t
*
d2n_queue
;
size_t
d2n_pos
;
size_t
d2n_pos
;
size_t
d2n_elen
;
size_t
d2n_elen
;
size_t
d2n_enum
;
size_t
d2n_enum
;
uint64_t
d2n_timestamp
;
uint64_t
d2n_timestamp
;
uint8_t
*
n2d_queue
;
uint8_t
*
n2d_queue
;
size_t
n2d_pos
;
size_t
n2d_pos
;
size_t
n2d_elen
;
size_t
n2d_elen
;
size_t
n2d_enum
;
size_t
n2d_enum
;
uint64_t
n2d_timestamp
;
uint64_t
n2d_timestamp
;
int
sync
;
int
sync
;
};
};
int
netsim_init
(
struct
netsim_interface
*
nsif
,
int
netsim_init
(
struct
netsim_interface
*
nsif
,
const
char
*
eth_socket_path
,
const
char
*
eth_socket_path
,
int
*
sync_eth
);
int
*
sync_eth
);
void
netsim_cleanup
(
struct
netsim_interface
*
nsif
);
void
netsim_cleanup
(
struct
netsim_interface
*
nsif
);
volatile
union
cosim_eth_proto_d2n
*
netsim_d2n_poll
(
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
,
void
netsim_d2n_done
(
struct
netsim_interface
*
nsif
,
volatile
union
cosim_eth_proto_d2n
*
msg
);
volatile
union
cosim_eth_proto_d2n
*
msg
);
static
inline
uint64_t
netsim_d2n_timestamp
(
struct
netsim_interface
*
nsif
)
static
inline
uint64_t
netsim_d2n_timestamp
(
struct
netsim_interface
*
nsif
)
{
{
return
nsif
->
d2n_timestamp
;
return
nsif
->
d2n_timestamp
;
}
}
volatile
union
cosim_eth_proto_n2d
*
netsim_n2d_alloc
(
volatile
union
cosim_eth_proto_n2d
*
netsim_n2d_alloc
(
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
uint64_t
latency
);
uint64_t
latency
);
int
netsim_n2d_sync
(
struct
netsim_interface
*
nsif
,
uint64_t
timestamp
,
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
,
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
,
uint64_t
netsim_advance_time
(
uint64_t
timestamp
,
uint64_t
sync_delay
,
int
sync_mode
);
int
sync_mode
);
#endif // SIMBRICKS_NETIF_NETSIM_H_
#endif // SIMBRICKS_NETIF_NETSIM_H_
lib/simbricks/netif/utils.c
View file @
d4666c97
...
@@ -24,96 +24,93 @@
...
@@ -24,96 +24,93 @@
#include <fcntl.h>
#include <fcntl.h>
#include <pthread.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mman.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
#include <unistd.h>
#include "lib/simbricks/netif/internal.h"
#include "lib/simbricks/netif/internal.h"
int
uxsocket_connect
(
const
char
*
path
)
int
uxsocket_connect
(
const
char
*
path
)
{
{
int
fd
;
int
fd
;
struct
sockaddr_un
saun
;
struct
sockaddr_un
saun
;
/* prepare and connect socket */
/* prepare and connect socket */
memset
(
&
saun
,
0
,
sizeof
(
saun
));
memset
(
&
saun
,
0
,
sizeof
(
saun
));
saun
.
sun_family
=
AF_UNIX
;
saun
.
sun_family
=
AF_UNIX
;
strcpy
(
saun
.
sun_path
,
path
);
strcpy
(
saun
.
sun_path
,
path
);
if
((
fd
=
socket
(
AF_UNIX
,
SOCK_STREAM
,
0
))
==
-
1
)
{
if
((
fd
=
socket
(
AF_UNIX
,
SOCK_STREAM
,
0
))
==
-
1
)
{
perror
(
"socket failed"
);
perror
(
"socket failed"
);
return
-
1
;
return
-
1
;
}
}
if
(
connect
(
fd
,
(
struct
sockaddr
*
)
&
saun
,
sizeof
(
saun
))
!=
0
)
{
if
(
connect
(
fd
,
(
struct
sockaddr
*
)
&
saun
,
sizeof
(
saun
))
!=
0
)
{
perror
(
"connect failed"
);
perror
(
"connect failed"
);
return
-
1
;
return
-
1
;
}
}
return
fd
;
return
fd
;
}
}
int
uxsocket_recv
(
int
fd
,
void
*
data
,
size_t
len
,
int
*
pfd
)
int
uxsocket_recv
(
int
fd
,
void
*
data
,
size_t
len
,
int
*
pfd
)
{
{
int
*
ppfd
;
int
*
ppfd
;
ssize_t
ret
;
ssize_t
ret
;
struct
cmsghdr
*
cmsg
;
struct
cmsghdr
*
cmsg
;
union
{
union
{
char
buf
[
CMSG_SPACE
(
sizeof
(
int
))];
char
buf
[
CMSG_SPACE
(
sizeof
(
int
))];
struct
cmsghdr
align
;
struct
cmsghdr
align
;
}
u
;
}
u
;
struct
iovec
iov
=
{
struct
iovec
iov
=
{
.
iov_base
=
data
,
.
iov_base
=
data
,
.
iov_len
=
len
,
.
iov_len
=
len
,
};
};
struct
msghdr
msg
=
{
struct
msghdr
msg
=
{
.
msg_name
=
NULL
,
.
msg_name
=
NULL
,
.
msg_namelen
=
0
,
.
msg_namelen
=
0
,
.
msg_iov
=
&
iov
,
.
msg_iov
=
&
iov
,
.
msg_iovlen
=
1
,
.
msg_iovlen
=
1
,
.
msg_control
=
u
.
buf
,
.
msg_control
=
u
.
buf
,
.
msg_controllen
=
sizeof
(
u
.
buf
),
.
msg_controllen
=
sizeof
(
u
.
buf
),
.
msg_flags
=
0
,
.
msg_flags
=
0
,
};
};
if
((
ret
=
recvmsg
(
fd
,
&
msg
,
0
))
!=
(
ssize_t
)
len
)
{
if
((
ret
=
recvmsg
(
fd
,
&
msg
,
0
))
!=
(
ssize_t
)
len
)
{
perror
(
"recvmsg failed"
);
perror
(
"recvmsg failed"
);
return
-
1
;
return
-
1
;
}
}
cmsg
=
CMSG_FIRSTHDR
(
&
msg
);
cmsg
=
CMSG_FIRSTHDR
(
&
msg
);
ppfd
=
(
int
*
)
CMSG_DATA
(
cmsg
);
ppfd
=
(
int
*
)
CMSG_DATA
(
cmsg
);
if
(
msg
.
msg_controllen
<=
0
||
cmsg
->
cmsg_len
!=
CMSG_LEN
(
sizeof
(
int
)))
{
if
(
msg
.
msg_controllen
<=
0
||
cmsg
->
cmsg_len
!=
CMSG_LEN
(
sizeof
(
int
)))
{
fprintf
(
stderr
,
"accessing ancillary data failed
\n
"
);
fprintf
(
stderr
,
"accessing ancillary data failed
\n
"
);
return
-
1
;
return
-
1
;
}
}
*
pfd
=
*
ppfd
;
*
pfd
=
*
ppfd
;
return
0
;
return
0
;
}
}
void
*
shm_map
(
int
shm_fd
)
void
*
shm_map
(
int
shm_fd
)
{
{
void
*
p
;
void
*
p
;
struct
stat
statbuf
;
struct
stat
statbuf
;
if
(
fstat
(
shm_fd
,
&
statbuf
)
!=
0
)
{
if
(
fstat
(
shm_fd
,
&
statbuf
)
!=
0
)
{
perror
(
"shm_map: fstat failed"
);
perror
(
"shm_map: fstat failed"
);
return
NULL
;
return
NULL
;
}
}
p
=
mmap
(
NULL
,
statbuf
.
st_size
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
shm_fd
,
p
=
mmap
(
NULL
,
statbuf
.
st_size
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
shm_fd
,
0
);
0
);
if
(
p
==
MAP_FAILED
)
{
if
(
p
==
MAP_FAILED
)
{
perror
(
"shm_map: mmap failed"
);
perror
(
"shm_map: mmap failed"
);
return
NULL
;
return
NULL
;
}
}
return
p
;
return
p
;
}
}
lib/simbricks/nicbm/nicbm.cc
View file @
d4666c97
...
@@ -22,483 +22,458 @@
...
@@ -22,483 +22,458 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include <stdlib.h>
#include <simbricks/nicbm/nicbm.h>
#include <signal.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <unistd.h>
#include <unistd.h>
#include <signal.h>
#include <cassert>
#include <cassert>
#include <ctime>
#include <ctime>
#include <iostream>
#include <iostream>
#include <simbricks/nicbm/nicbm.h>
// #define DEBUG_NICBM 1
// #define DEBUG_NICBM 1
#define DMA_MAX_PENDING 64
#define DMA_MAX_PENDING 64
namespace
nicbm
{
using
namespace
nicbm
;
static
volatile
int
exiting
=
0
;
static
volatile
int
exiting
=
0
;
static
uint64_t
main_time
=
0
;
static
uint64_t
main_time
=
0
;
static
void
sigint_handler
(
int
dummy
)
{
static
void
sigint_handler
(
int
dummy
)
exiting
=
1
;
{
exiting
=
1
;
}
}
static
void
sigusr1_handler
(
int
dummy
)
static
void
sigusr1_handler
(
int
dummy
)
{
{
fprintf
(
stderr
,
"main_time = %lu
\n
"
,
main_time
);
fprintf
(
stderr
,
"main_time = %lu
\n
"
,
main_time
);
}
}
volatile
union
cosim_pcie_proto_d2h
*
Runner
::
d2h_alloc
(
void
)
volatile
union
cosim_pcie_proto_d2h
*
Runner
::
d2h_alloc
(
void
)
{
{
volatile
union
cosim_pcie_proto_d2h
*
msg
;
volatile
union
cosim_pcie_proto_d2h
*
msg
;
while
((
msg
=
nicsim_d2h_alloc
(
&
nsparams
,
main_time
))
==
NULL
)
{
while
((
msg
=
nicsim_d2h_alloc
(
&
nsparams
,
main_time
))
==
NULL
)
{
fprintf
(
stderr
,
"d2h_alloc: no entry available
\n
"
);
fprintf
(
stderr
,
"d2h_alloc: no entry available
\n
"
);
}
}
return
msg
;
return
msg
;
}
}
volatile
union
cosim_eth_proto_d2n
*
Runner
::
d2n_alloc
(
void
)
volatile
union
cosim_eth_proto_d2n
*
Runner
::
d2n_alloc
(
void
)
{
{
volatile
union
cosim_eth_proto_d2n
*
msg
;
volatile
union
cosim_eth_proto_d2n
*
msg
;
while
((
msg
=
nicsim_d2n_alloc
(
&
nsparams
,
main_time
))
==
NULL
)
{
while
((
msg
=
nicsim_d2n_alloc
(
&
nsparams
,
main_time
))
==
NULL
)
{
fprintf
(
stderr
,
"d2n_alloc: no entry available
\n
"
);
fprintf
(
stderr
,
"d2n_alloc: no entry available
\n
"
);
}
}
return
msg
;
return
msg
;
}
}
void
Runner
::
issue_dma
(
DMAOp
&
op
)
void
Runner
::
issue_dma
(
DMAOp
&
op
)
{
{
if
(
dma_pending
<
DMA_MAX_PENDING
)
{
if
(
dma_pending
<
DMA_MAX_PENDING
)
{
// can directly issue
// can directly issue
#ifdef DEBUG_NICBM
#ifdef DEBUG_NICBM
printf
(
"nicbm: issuing dma op %p addr %lx len %zu pending %zu
\n
"
,
&
op
,
printf
(
"nicbm: issuing dma op %p addr %lx len %zu pending %zu
\n
"
,
&
op
,
op
.
dma_addr
,
op
.
len
,
dma_pending
);
op
.
dma_addr
,
op
.
len
,
dma_pending
);
#endif
#endif
dma_do
(
op
);
dma_do
(
op
);
}
else
{
}
else
{
#ifdef DEBUG_NICBM
#ifdef DEBUG_NICBM
printf
(
"nicbm: enqueuing dma op %p addr %lx len %zu pending %zu
\n
"
,
&
op
,
printf
(
"nicbm: enqueuing dma op %p addr %lx len %zu pending %zu
\n
"
,
&
op
,
op
.
dma_addr
,
op
.
len
,
dma_pending
);
op
.
dma_addr
,
op
.
len
,
dma_pending
);
#endif
#endif
dma_queue
.
push_back
(
&
op
);
dma_queue
.
push_back
(
&
op
);
}
}
}
}
void
Runner
::
dma_trigger
()
void
Runner
::
dma_trigger
()
{
{
if
(
dma_queue
.
empty
()
||
dma_pending
==
DMA_MAX_PENDING
)
if
(
dma_queue
.
empty
()
||
dma_pending
==
DMA_MAX_PENDING
)
return
;
return
;
DMAOp
*
op
=
dma_queue
.
front
();
DMAOp
*
op
=
dma_queue
.
front
();
dma_queue
.
pop_front
();
dma_queue
.
pop_front
();
dma_do
(
*
op
);
dma_do
(
*
op
);
}
}
void
Runner
::
dma_do
(
DMAOp
&
op
)
void
Runner
::
dma_do
(
DMAOp
&
op
)
{
{
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
dma_pending
++
;
dma_pending
++
;
#ifdef DEBUG_NICBM
#ifdef DEBUG_NICBM
printf
(
"nicbm: executing dma op %p addr %lx len %zu pending %zu
\n
"
,
&
op
,
printf
(
"nicbm: executing dma op %p addr %lx len %zu pending %zu
\n
"
,
&
op
,
op
.
dma_addr
,
op
.
len
,
dma_pending
);
op
.
dma_addr
,
op
.
len
,
dma_pending
);
#endif
#endif
if
(
op
.
write
)
{
if
(
op
.
write
)
{
volatile
struct
cosim_pcie_proto_d2h_write
*
write
=
&
msg
->
write
;
volatile
struct
cosim_pcie_proto_d2h_write
*
write
=
&
msg
->
write
;
if
(
dintro
.
d2h_elen
<
sizeof
(
*
write
)
+
op
.
len
)
{
if
(
dintro
.
d2h_elen
<
sizeof
(
*
write
)
+
op
.
len
)
{
fprintf
(
stderr
,
"issue_dma: write too big (%zu), can only fit up "
fprintf
(
stderr
,
"to (%zu)
\n
"
,
op
.
len
,
dintro
.
d2h_elen
-
sizeof
(
*
write
));
"issue_dma: write too big (%zu), can only fit up "
abort
();
"to (%zu)
\n
"
,
}
op
.
len
,
dintro
.
d2h_elen
-
sizeof
(
*
write
));
abort
();
write
->
req_id
=
(
uintptr_t
)
&
op
;
}
write
->
offset
=
op
.
dma_addr
;
write
->
len
=
op
.
len
;
write
->
req_id
=
(
uintptr_t
)
&
op
;
memcpy
((
void
*
)
write
->
data
,
(
void
*
)
op
.
data
,
op
.
len
);
write
->
offset
=
op
.
dma_addr
;
// WMB();
write
->
len
=
op
.
len
;
write
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_WRITE
|
memcpy
((
void
*
)
write
->
data
,
(
void
*
)
op
.
data
,
op
.
len
);
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
// WMB();
}
else
{
write
->
own_type
=
volatile
struct
cosim_pcie_proto_d2h_read
*
read
=
&
msg
->
read
;
COSIM_PCIE_PROTO_D2H_MSG_WRITE
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
if
(
dintro
.
h2d_elen
<
sizeof
(
struct
cosim_pcie_proto_h2d_readcomp
)
+
}
else
{
op
.
len
)
{
volatile
struct
cosim_pcie_proto_d2h_read
*
read
=
&
msg
->
read
;
fprintf
(
stderr
,
"issue_dma: write too big (%zu), can only fit up "
if
(
dintro
.
h2d_elen
<
"to (%zu)
\n
"
,
op
.
len
,
dintro
.
h2d_elen
-
sizeof
(
struct
cosim_pcie_proto_h2d_readcomp
)
+
op
.
len
)
{
sizeof
(
struct
cosim_pcie_proto_h2d_readcomp
));
fprintf
(
stderr
,
abort
();
"issue_dma: write too big (%zu), can only fit up "
}
"to (%zu)
\n
"
,
op
.
len
,
read
->
req_id
=
(
uintptr_t
)
&
op
;
dintro
.
h2d_elen
-
sizeof
(
struct
cosim_pcie_proto_h2d_readcomp
));
read
->
offset
=
op
.
dma_addr
;
abort
();
read
->
len
=
op
.
len
;
// WMB();
read
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_READ
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
}
read
->
req_id
=
(
uintptr_t
)
&
op
;
read
->
offset
=
op
.
dma_addr
;
read
->
len
=
op
.
len
;
// WMB();
read
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_READ
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
}
}
void
Runner
::
msi_issue
(
uint8_t
vec
)
void
Runner
::
msi_issue
(
uint8_t
vec
)
{
{
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
#ifdef DEBUG_NICBM
#ifdef DEBUG_NICBM
printf
(
"nicbm: issue MSI interrupt vec %u
\n
"
,
vec
);
printf
(
"nicbm: issue MSI interrupt vec %u
\n
"
,
vec
);
#endif
#endif
volatile
struct
cosim_pcie_proto_d2h_interrupt
*
intr
=
&
msg
->
interrupt
;
volatile
struct
cosim_pcie_proto_d2h_interrupt
*
intr
=
&
msg
->
interrupt
;
intr
->
vector
=
vec
;
intr
->
vector
=
vec
;
intr
->
inttype
=
COSIM_PCIE_PROTO_INT_MSI
;
intr
->
inttype
=
COSIM_PCIE_PROTO_INT_MSI
;
// WMB();
// WMB();
intr
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_INTERRUPT
|
intr
->
own_type
=
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
COSIM_PCIE_PROTO_D2H_MSG_INTERRUPT
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
}
void
Runner
::
msix_issue
(
uint8_t
vec
)
void
Runner
::
msix_issue
(
uint8_t
vec
)
{
{
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
#ifdef DEBUG_NICBM
#ifdef DEBUG_NICBM
printf
(
"nicbm: issue MSI-X interrupt vec %u
\n
"
,
vec
);
printf
(
"nicbm: issue MSI-X interrupt vec %u
\n
"
,
vec
);
#endif
#endif
volatile
struct
cosim_pcie_proto_d2h_interrupt
*
intr
=
&
msg
->
interrupt
;
volatile
struct
cosim_pcie_proto_d2h_interrupt
*
intr
=
&
msg
->
interrupt
;
intr
->
vector
=
vec
;
intr
->
vector
=
vec
;
intr
->
inttype
=
COSIM_PCIE_PROTO_INT_MSIX
;
intr
->
inttype
=
COSIM_PCIE_PROTO_INT_MSIX
;
// WMB();
// WMB();
intr
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_INTERRUPT
|
intr
->
own_type
=
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
COSIM_PCIE_PROTO_D2H_MSG_INTERRUPT
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
}
void
Runner
::
event_schedule
(
TimedEvent
&
evt
)
void
Runner
::
event_schedule
(
TimedEvent
&
evt
)
{
{
events
.
insert
(
&
evt
);
events
.
insert
(
&
evt
);
}
}
void
Runner
::
event_cancel
(
TimedEvent
&
evt
)
void
Runner
::
event_cancel
(
TimedEvent
&
evt
)
{
{
events
.
erase
(
&
evt
);
events
.
erase
(
&
evt
);
}
}
void
Runner
::
h2d_read
(
volatile
struct
cosim_pcie_proto_h2d_read
*
read
)
void
Runner
::
h2d_read
(
volatile
struct
cosim_pcie_proto_h2d_read
*
read
)
{
{
volatile
union
cosim_pcie_proto_d2h
*
msg
;
volatile
union
cosim_pcie_proto_d2h
*
msg
;
volatile
struct
cosim_pcie_proto_d2h_readcomp
*
rc
;
volatile
struct
cosim_pcie_proto_d2h_readcomp
*
rc
;
msg
=
d2h_alloc
();
msg
=
d2h_alloc
();
rc
=
&
msg
->
readcomp
;
rc
=
&
msg
->
readcomp
;
dev
.
reg_read
(
read
->
bar
,
read
->
offset
,
(
void
*
)
rc
->
data
,
read
->
len
);
dev
.
reg_read
(
read
->
bar
,
read
->
offset
,
(
void
*
)
rc
->
data
,
read
->
len
);
rc
->
req_id
=
read
->
req_id
;
rc
->
req_id
=
read
->
req_id
;
#ifdef DEBUG_NICBM
#ifdef DEBUG_NICBM
uint64_t
dbg_val
=
0
;
uint64_t
dbg_val
=
0
;
memcpy
(
&
dbg_val
,
(
const
void
*
)
rc
->
data
,
read
->
len
<=
8
?
read
->
len
:
8
);
memcpy
(
&
dbg_val
,
(
const
void
*
)
rc
->
data
,
read
->
len
<=
8
?
read
->
len
:
8
);
printf
(
"nicbm: read(off=0x%lx, len=%u, val=0x%lx)
\n
"
,
read
->
offset
,
printf
(
"nicbm: read(off=0x%lx, len=%u, val=0x%lx)
\n
"
,
read
->
offset
,
read
->
len
,
read
->
len
,
dbg_val
);
dbg_val
);
#endif
#endif
// WMB();
// WMB();
rc
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_READCOMP
|
rc
->
own_type
=
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
COSIM_PCIE_PROTO_D2H_MSG_READCOMP
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
}
void
Runner
::
h2d_write
(
volatile
struct
cosim_pcie_proto_h2d_write
*
write
)
void
Runner
::
h2d_write
(
volatile
struct
cosim_pcie_proto_h2d_write
*
write
)
{
{
volatile
union
cosim_pcie_proto_d2h
*
msg
;
volatile
union
cosim_pcie_proto_d2h
*
msg
;
volatile
struct
cosim_pcie_proto_d2h_writecomp
*
wc
;
volatile
struct
cosim_pcie_proto_d2h_writecomp
*
wc
;
msg
=
d2h_alloc
();
msg
=
d2h_alloc
();
wc
=
&
msg
->
writecomp
;
wc
=
&
msg
->
writecomp
;
#ifdef DEBUG_NICBM
#ifdef DEBUG_NICBM
uint64_t
dbg_val
=
0
;
uint64_t
dbg_val
=
0
;
memcpy
(
&
dbg_val
,
(
const
void
*
)
write
->
data
,
write
->
len
<=
8
?
write
->
len
:
memcpy
(
&
dbg_val
,
(
const
void
*
)
write
->
data
,
write
->
len
<=
8
?
write
->
len
:
8
);
8
);
printf
(
"nicbm: write(off=0x%lx, len=%u, val=0x%lx)
\n
"
,
write
->
offset
,
printf
(
"nicbm: write(off=0x%lx, len=%u, val=0x%lx)
\n
"
,
write
->
offset
,
write
->
len
,
dbg_val
);
write
->
len
,
dbg_val
);
#endif
#endif
dev
.
reg_write
(
write
->
bar
,
write
->
offset
,
(
void
*
)
write
->
data
,
write
->
len
);
dev
.
reg_write
(
write
->
bar
,
write
->
offset
,
(
void
*
)
write
->
data
,
write
->
len
);
wc
->
req_id
=
write
->
req_id
;
wc
->
req_id
=
write
->
req_id
;
// WMB();
// WMB();
wc
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_WRITECOMP
|
wc
->
own_type
=
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
COSIM_PCIE_PROTO_D2H_MSG_WRITECOMP
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
}
void
Runner
::
h2d_readcomp
(
volatile
struct
cosim_pcie_proto_h2d_readcomp
*
rc
)
void
Runner
::
h2d_readcomp
(
volatile
struct
cosim_pcie_proto_h2d_readcomp
*
rc
)
{
{
DMAOp
*
op
=
(
DMAOp
*
)(
uintptr_t
)
rc
->
req_id
;
DMAOp
*
op
=
(
DMAOp
*
)(
uintptr_t
)
rc
->
req_id
;
#ifdef DEBUG_NICBM
#ifdef DEBUG_NICBM
printf
(
"nicbm: completed dma read op %p addr %lx len %zu
\n
"
,
op
,
printf
(
"nicbm: completed dma read op %p addr %lx len %zu
\n
"
,
op
,
op
->
dma_addr
,
op
->
dma_addr
,
op
->
len
);
op
->
len
);
#endif
#endif
memcpy
(
op
->
data
,
(
void
*
)
rc
->
data
,
op
->
len
);
memcpy
(
op
->
data
,
(
void
*
)
rc
->
data
,
op
->
len
);
dev
.
dma_complete
(
*
op
);
dev
.
dma_complete
(
*
op
);
dma_pending
--
;
dma_pending
--
;
dma_trigger
();
dma_trigger
();
}
}
void
Runner
::
h2d_writecomp
(
volatile
struct
cosim_pcie_proto_h2d_writecomp
*
wc
)
void
Runner
::
h2d_writecomp
(
volatile
struct
cosim_pcie_proto_h2d_writecomp
*
wc
)
{
{
DMAOp
*
op
=
(
DMAOp
*
)(
uintptr_t
)
wc
->
req_id
;
DMAOp
*
op
=
(
DMAOp
*
)(
uintptr_t
)
wc
->
req_id
;
#ifdef DEBUG_NICBM
#ifdef DEBUG_NICBM
printf
(
"nicbm: completed dma write op %p addr %lx len %zu
\n
"
,
op
,
printf
(
"nicbm: completed dma write op %p addr %lx len %zu
\n
"
,
op
,
op
->
dma_addr
,
op
->
len
);
op
->
dma_addr
,
op
->
len
);
#endif
#endif
dev
.
dma_complete
(
*
op
);
dev
.
dma_complete
(
*
op
);
dma_pending
--
;
dma_pending
--
;
dma_trigger
();
dma_trigger
();
}
}
void
Runner
::
h2d_devctrl
(
volatile
struct
cosim_pcie_proto_h2d_devctrl
*
dc
)
void
Runner
::
h2d_devctrl
(
volatile
struct
cosim_pcie_proto_h2d_devctrl
*
dc
)
{
{
dev
.
devctrl_update
(
*
(
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
)
void
Runner
::
eth_recv
(
volatile
struct
cosim_eth_proto_n2d_recv
*
recv
)
{
{
#ifdef DEBUG_NICBM
#ifdef DEBUG_NICBM
printf
(
"nicbm: eth rx: port %u len %u
\n
"
,
recv
->
port
,
recv
->
len
);
printf
(
"nicbm: eth rx: port %u len %u
\n
"
,
recv
->
port
,
recv
->
len
);
#endif
#endif
dev
.
eth_rx
(
recv
->
port
,
(
void
*
)
recv
->
data
,
recv
->
len
);
dev
.
eth_rx
(
recv
->
port
,
(
void
*
)
recv
->
data
,
recv
->
len
);
}
}
void
Runner
::
eth_send
(
const
void
*
data
,
size_t
len
)
void
Runner
::
eth_send
(
const
void
*
data
,
size_t
len
)
{
{
#ifdef DEBUG_NICBM
#ifdef DEBUG_NICBM
printf
(
"nicbm: eth tx: len %zu
\n
"
,
len
);
printf
(
"nicbm: eth tx: len %zu
\n
"
,
len
);
#endif
#endif
volatile
union
cosim_eth_proto_d2n
*
msg
=
d2n_alloc
();
volatile
union
cosim_eth_proto_d2n
*
msg
=
d2n_alloc
();
volatile
struct
cosim_eth_proto_d2n_send
*
send
=
&
msg
->
send
;
volatile
struct
cosim_eth_proto_d2n_send
*
send
=
&
msg
->
send
;
send
->
port
=
0
;
// single port
send
->
port
=
0
;
// single port
send
->
len
=
len
;
send
->
len
=
len
;
memcpy
((
void
*
)
send
->
data
,
data
,
len
);
memcpy
((
void
*
)
send
->
data
,
data
,
len
);
send
->
own_type
=
COSIM_ETH_PROTO_D2N_MSG_SEND
|
send
->
own_type
=
COSIM_ETH_PROTO_D2N_MSG_SEND
|
COSIM_ETH_PROTO_D2N_OWN_NET
;
COSIM_ETH_PROTO_D2N_OWN_NET
;
}
}
void
Runner
::
poll_h2d
()
void
Runner
::
poll_h2d
()
{
{
volatile
union
cosim_pcie_proto_h2d
*
msg
=
volatile
union
cosim_pcie_proto_h2d
*
msg
=
nicif_h2d_poll
(
&
nsparams
,
main_time
);
nicif_h2d_poll
(
&
nsparams
,
main_time
);
uint8_t
type
;
uint8_t
type
;
if
(
msg
==
NULL
)
if
(
msg
==
NULL
)
return
;
return
;
type
=
msg
->
dummy
.
own_type
&
COSIM_PCIE_PROTO_H2D_MSG_MASK
;
type
=
msg
->
dummy
.
own_type
&
COSIM_PCIE_PROTO_H2D_MSG_MASK
;
switch
(
type
)
{
switch
(
type
)
{
case
COSIM_PCIE_PROTO_H2D_MSG_READ
:
case
COSIM_PCIE_PROTO_H2D_MSG_READ
:
h2d_read
(
&
msg
->
read
);
h2d_read
(
&
msg
->
read
);
break
;
break
;
case
COSIM_PCIE_PROTO_H2D_MSG_WRITE
:
case
COSIM_PCIE_PROTO_H2D_MSG_WRITE
:
h2d_write
(
&
msg
->
write
);
h2d_write
(
&
msg
->
write
);
break
;
break
;
case
COSIM_PCIE_PROTO_H2D_MSG_READCOMP
:
case
COSIM_PCIE_PROTO_H2D_MSG_READCOMP
:
h2d_readcomp
(
&
msg
->
readcomp
);
h2d_readcomp
(
&
msg
->
readcomp
);
break
;
break
;
case
COSIM_PCIE_PROTO_H2D_MSG_WRITECOMP
:
case
COSIM_PCIE_PROTO_H2D_MSG_WRITECOMP
:
h2d_writecomp
(
&
msg
->
writecomp
);
h2d_writecomp
(
&
msg
->
writecomp
);
break
;
break
;
case
COSIM_PCIE_PROTO_H2D_MSG_DEVCTRL
:
case
COSIM_PCIE_PROTO_H2D_MSG_DEVCTRL
:
h2d_devctrl
(
&
msg
->
devctrl
);
h2d_devctrl
(
&
msg
->
devctrl
);
break
;
break
;
case
COSIM_PCIE_PROTO_H2D_MSG_SYNC
:
case
COSIM_PCIE_PROTO_H2D_MSG_SYNC
:
break
;
break
;
default:
default:
fprintf
(
stderr
,
"poll_h2d: unsupported type=%u
\n
"
,
type
);
fprintf
(
stderr
,
"poll_h2d: unsupported type=%u
\n
"
,
type
);
}
}
nicif_h2d_done
(
msg
);
nicif_h2d_done
(
msg
);
nicif_h2d_next
();
nicif_h2d_next
();
}
}
void
Runner
::
poll_n2d
()
void
Runner
::
poll_n2d
()
{
{
volatile
union
cosim_eth_proto_n2d
*
msg
=
volatile
union
cosim_eth_proto_n2d
*
msg
=
nicif_n2d_poll
(
&
nsparams
,
main_time
);
nicif_n2d_poll
(
&
nsparams
,
main_time
);
uint8_t
t
;
uint8_t
t
;
if
(
msg
==
NULL
)
if
(
msg
==
NULL
)
return
;
return
;
t
=
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_N2D_MSG_MASK
;
t
=
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_N2D_MSG_MASK
;
switch
(
t
)
{
switch
(
t
)
{
case
COSIM_ETH_PROTO_N2D_MSG_RECV
:
case
COSIM_ETH_PROTO_N2D_MSG_RECV
:
eth_recv
(
&
msg
->
recv
);
eth_recv
(
&
msg
->
recv
);
break
;
break
;
case
COSIM_ETH_PROTO_N2D_MSG_SYNC
:
case
COSIM_ETH_PROTO_N2D_MSG_SYNC
:
break
;
break
;
default:
default:
fprintf
(
stderr
,
"poll_n2d: unsupported type=%u"
,
t
);
fprintf
(
stderr
,
"poll_n2d: unsupported type=%u"
,
t
);
}
}
nicif_n2d_done
(
msg
);
nicif_n2d_done
(
msg
);
nicif_n2d_next
();
nicif_n2d_next
();
}
}
uint64_t
Runner
::
time_ps
()
const
uint64_t
Runner
::
time_ps
()
const
{
{
return
main_time
;
return
main_time
;
}
}
uint64_t
Runner
::
get_mac_addr
()
const
uint64_t
Runner
::
get_mac_addr
()
const
{
{
return
mac_addr
;
return
mac_addr
;
}
}
bool
Runner
::
event_next
(
uint64_t
&
retval
)
bool
Runner
::
event_next
(
uint64_t
&
retval
)
{
{
if
(
events
.
empty
())
if
(
events
.
empty
())
return
false
;
return
false
;
retval
=
(
*
events
.
begin
())
->
time
;
retval
=
(
*
events
.
begin
())
->
time
;
return
true
;
return
true
;
}
}
void
Runner
::
event_trigger
()
void
Runner
::
event_trigger
()
{
{
auto
it
=
events
.
begin
();
auto
it
=
events
.
begin
();
if
(
it
==
events
.
end
())
if
(
it
==
events
.
end
())
return
;
return
;
TimedEvent
*
ev
=
*
it
;
TimedEvent
*
ev
=
*
it
;
// event is in the future
// event is in the future
if
(
ev
->
time
>
main_time
)
if
(
ev
->
time
>
main_time
)
return
;
return
;
events
.
erase
(
it
);
events
.
erase
(
it
);
dev
.
timed_event
(
*
ev
);
dev
.
timed_event
(
*
ev
);
}
}
Runner
::
Runner
(
Device
&
dev_
)
Runner
::
Runner
(
Device
&
dev_
)
:
dev
(
dev_
),
events
(
event_cmp
())
{
:
dev
(
dev_
),
events
(
event_cmp
())
// mac_addr = lrand48() & ~(3ULL << 46);
{
dma_pending
=
0
;
// mac_addr = lrand48() & ~(3ULL << 46);
srand48
(
time
(
NULL
)
^
getpid
());
dma_pending
=
0
;
mac_addr
=
lrand48
();
srand48
(
time
(
NULL
)
^
getpid
());
mac_addr
<<=
16
;
mac_addr
=
lrand48
();
mac_addr
^=
lrand48
();
mac_addr
<<=
16
;
mac_addr
&=
~
3ULL
;
mac_addr
^=
lrand48
();
mac_addr
&=
~
3ULL
;
std
::
cerr
<<
std
::
hex
<<
mac_addr
<<
std
::
endl
;
std
::
cerr
<<
std
::
hex
<<
mac_addr
<<
std
::
endl
;
}
}
int
Runner
::
runMain
(
int
argc
,
char
*
argv
[])
int
Runner
::
runMain
(
int
argc
,
char
*
argv
[])
{
{
uint64_t
next_ts
;
uint64_t
next_ts
;
uint64_t
max_step
=
10000
;
uint64_t
max_step
=
10000
;
uint64_t
sync_period
=
100
*
1000ULL
;
uint64_t
sync_period
=
100
*
1000ULL
;
uint64_t
pci_latency
=
500
*
1000ULL
;
uint64_t
pci_latency
=
500
*
1000ULL
;
uint64_t
eth_latency
=
500
*
1000ULL
;
uint64_t
eth_latency
=
500
*
1000ULL
;
int
sync_mode
=
SYNC_MODES
;
int
sync_mode
=
SYNC_MODES
;
if
(
argc
<
4
&&
argc
>
9
)
{
if
(
argc
<
4
&&
argc
>
9
)
{
fprintf
(
stderr
,
fprintf
(
stderr
,
"Usage: corundum_bm PCI-SOCKET ETH-SOCKET "
"Usage: corundum_bm PCI-SOCKET ETH-SOCKET "
"SHM [SYNC-MODE] [START-TICK] [SYNC-PERIOD] [PCI-LATENCY] "
"SHM [SYNC-MODE] [START-TICK] [SYNC-PERIOD] [PCI-LATENCY] "
"[ETH-LATENCY]
\n
"
);
"[ETH-LATENCY]
\n
"
);
return
EXIT_FAILURE
;
return
EXIT_FAILURE
;
}
}
if
(
argc
>=
5
)
if
(
argc
>=
5
)
sync_mode
=
strtol
(
argv
[
4
],
NULL
,
0
);
sync_mode
=
strtol
(
argv
[
4
],
NULL
,
0
);
if
(
argc
>=
6
)
if
(
argc
>=
6
)
main_time
=
strtoull
(
argv
[
5
],
NULL
,
0
);
main_time
=
strtoull
(
argv
[
5
],
NULL
,
0
);
if
(
argc
>=
7
)
if
(
argc
>=
7
)
sync_period
=
strtoull
(
argv
[
6
],
NULL
,
0
)
*
1000ULL
;
sync_period
=
strtoull
(
argv
[
6
],
NULL
,
0
)
*
1000ULL
;
if
(
argc
>=
8
)
if
(
argc
>=
8
)
pci_latency
=
strtoull
(
argv
[
7
],
NULL
,
0
)
*
1000ULL
;
pci_latency
=
strtoull
(
argv
[
7
],
NULL
,
0
)
*
1000ULL
;
if
(
argc
>=
9
)
if
(
argc
>=
9
)
eth_latency
=
strtoull
(
argv
[
8
],
NULL
,
0
)
*
1000ULL
;
eth_latency
=
strtoull
(
argv
[
8
],
NULL
,
0
)
*
1000ULL
;
signal
(
SIGINT
,
sigint_handler
);
signal
(
SIGINT
,
sigint_handler
);
signal
(
SIGUSR1
,
sigusr1_handler
);
signal
(
SIGUSR1
,
sigusr1_handler
);
memset
(
&
dintro
,
0
,
sizeof
(
dintro
));
memset
(
&
dintro
,
0
,
sizeof
(
dintro
));
dev
.
setup_intro
(
dintro
);
dev
.
setup_intro
(
dintro
);
nsparams
.
sync_pci
=
1
;
nsparams
.
sync_pci
=
1
;
nsparams
.
sync_eth
=
1
;
nsparams
.
sync_eth
=
1
;
nsparams
.
pci_socket_path
=
argv
[
1
];
nsparams
.
pci_socket_path
=
argv
[
1
];
nsparams
.
eth_socket_path
=
argv
[
2
];
nsparams
.
eth_socket_path
=
argv
[
2
];
nsparams
.
shm_path
=
argv
[
3
];
nsparams
.
shm_path
=
argv
[
3
];
nsparams
.
pci_latency
=
pci_latency
;
nsparams
.
pci_latency
=
pci_latency
;
nsparams
.
eth_latency
=
eth_latency
;
nsparams
.
eth_latency
=
eth_latency
;
nsparams
.
sync_delay
=
sync_period
;
nsparams
.
sync_delay
=
sync_period
;
assert
(
sync_mode
==
SYNC_MODES
||
sync_mode
==
SYNC_BARRIER
);
assert
(
sync_mode
==
SYNC_MODES
||
sync_mode
==
SYNC_BARRIER
);
nsparams
.
sync_mode
=
sync_mode
;
nsparams
.
sync_mode
=
sync_mode
;
if
(
nicsim_init
(
&
nsparams
,
&
dintro
))
{
if
(
nicsim_init
(
&
nsparams
,
&
dintro
))
{
return
EXIT_FAILURE
;
return
EXIT_FAILURE
;
}
fprintf
(
stderr
,
"sync_pci=%d sync_eth=%d
\n
"
,
nsparams
.
sync_pci
,
nsparams
.
sync_eth
);
bool
is_sync
=
nsparams
.
sync_pci
||
nsparams
.
sync_eth
;
while
(
!
exiting
)
{
while
(
nicsim_sync
(
&
nsparams
,
main_time
))
{
fprintf
(
stderr
,
"warn: nicsim_sync failed (t=%lu)
\n
"
,
main_time
);
}
}
fprintf
(
stderr
,
"sync_pci=%d sync_eth=%d
\n
"
,
nsparams
.
sync_pci
,
nicsim_advance_epoch
(
&
nsparams
,
main_time
);
nsparams
.
sync_eth
);
do
{
bool
is_sync
=
nsparams
.
sync_pci
||
nsparams
.
sync_eth
;
poll_h2d
();
poll_n2d
();
while
(
!
exiting
)
{
event_trigger
();
while
(
nicsim_sync
(
&
nsparams
,
main_time
))
{
fprintf
(
stderr
,
"warn: nicsim_sync failed (t=%lu)
\n
"
,
main_time
);
if
(
is_sync
)
{
}
next_ts
=
nicsim_next_timestamp
(
&
nsparams
);
nicsim_advance_epoch
(
&
nsparams
,
main_time
);
if
(
next_ts
>
main_time
+
max_step
)
next_ts
=
main_time
+
max_step
;
do
{
}
else
{
poll_h2d
();
next_ts
=
main_time
+
max_step
;
poll_n2d
();
}
event_trigger
();
uint64_t
ev_ts
;
if
(
is_sync
)
{
if
(
event_next
(
ev_ts
)
&&
ev_ts
<
next_ts
)
next_ts
=
nicsim_next_timestamp
(
&
nsparams
);
next_ts
=
ev_ts
;
if
(
next_ts
>
main_time
+
max_step
)
}
while
(
next_ts
<=
main_time
&&
!
exiting
);
next_ts
=
main_time
+
max_step
;
main_time
=
nicsim_advance_time
(
&
nsparams
,
next_ts
);
}
else
{
}
next_ts
=
main_time
+
max_step
;
}
fprintf
(
stderr
,
"exit main_time: %lu
\n
"
,
main_time
);
nicsim_cleanup
();
uint64_t
ev_ts
;
return
0
;
if
(
event_next
(
ev_ts
)
&&
ev_ts
<
next_ts
)
next_ts
=
ev_ts
;
}
while
(
next_ts
<=
main_time
&&
!
exiting
);
main_time
=
nicsim_advance_time
(
&
nsparams
,
next_ts
);
}
fprintf
(
stderr
,
"exit main_time: %lu
\n
"
,
main_time
);
nicsim_cleanup
();
return
0
;
}
}
void
Runner
::
Device
::
timed_event
(
TimedEvent
&
te
)
void
Runner
::
Device
::
timed_event
(
TimedEvent
&
te
)
{
{
}
}
void
Runner
::
Device
::
devctrl_update
(
void
Runner
::
Device
::
devctrl_update
(
struct
cosim_pcie_proto_h2d_devctrl
&
devctrl
)
struct
cosim_pcie_proto_h2d_devctrl
&
devctrl
)
{
{
int_intx_en
=
devctrl
.
flags
&
COSIM_PCIE_PROTO_CTRL_INTX_EN
;
int_intx_en
=
devctrl
.
flags
&
COSIM_PCIE_PROTO_CTRL_INTX_EN
;
int_msi_en
=
devctrl
.
flags
&
COSIM_PCIE_PROTO_CTRL_MSI_EN
;
int_msi_en
=
devctrl
.
flags
&
COSIM_PCIE_PROTO_CTRL_MSI_EN
;
int_msix_en
=
devctrl
.
flags
&
COSIM_PCIE_PROTO_CTRL_MSIX_EN
;
int_msix_en
=
devctrl
.
flags
&
COSIM_PCIE_PROTO_CTRL_MSIX_EN
;
}
}
}
// namespace nicbm
lib/simbricks/nicbm/nicbm.h
View file @
d4666c97
...
@@ -27,10 +27,11 @@
...
@@ -27,10 +27,11 @@
#include <cassert>
#include <cassert>
#include <cstring>
#include <cstring>
#include <set>
#include <deque>
#include <deque>
#include <set>
extern
"C"
{
extern
"C"
{
#include <simbricks/nicif/nicsim.h>
#include <simbricks/nicif/nicsim.h>
}
}
namespace
nicbm
{
namespace
nicbm
{
...
@@ -38,21 +39,22 @@ namespace nicbm {
...
@@ -38,21 +39,22 @@ namespace nicbm {
static
const
size_t
MAX_DMA_LEN
=
2048
;
static
const
size_t
MAX_DMA_LEN
=
2048
;
class
DMAOp
{
class
DMAOp
{
public:
public:
virtual
~
DMAOp
()
{
}
virtual
~
DMAOp
()
{
bool
write
;
}
uint64_t
dma_addr
;
bool
write
;
size_t
len
;
uint64_t
dma_addr
;
void
*
data
;
size_t
len
;
void
*
data
;
};
};
class
TimedEvent
{
class
TimedEvent
{
public:
public:
virtual
~
TimedEvent
()
{
}
virtual
~
TimedEvent
()
{
uint64_t
time
;
}
uint64_t
time
;
};
};
/**
/**
* The Runner drives the main simulation loop. It's initialized with a reference
* 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
* to a device it should manage, and then once `runMain` is called, it will
...
@@ -60,111 +62,107 @@ class TimedEvent {
...
@@ -60,111 +62,107 @@ class TimedEvent {
* device as needed.
* device as needed.
* */
* */
class
Runner
{
class
Runner
{
public:
public:
class
Device
{
class
Device
{
protected:
protected:
bool
int_intx_en
;
bool
int_intx_en
;
bool
int_msi_en
;
bool
int_msi_en
;
bool
int_msix_en
;
bool
int_msix_en
;
public:
public:
/**
/**
* Initialize device specific parameters (pci dev/vendor id,
* Initialize device specific parameters (pci dev/vendor id,
* BARs etc. in intro struct.
* BARs etc. in intro struct.
*/
*/
virtual
void
setup_intro
(
struct
cosim_pcie_proto_dev_intro
&
di
)
virtual
void
setup_intro
(
struct
cosim_pcie_proto_dev_intro
&
di
)
=
0
;
=
0
;
/**
/**
* execute a register read from `bar`:`addr` of length `len`.
* execute a register read from `bar`:`addr` of length `len`.
* Should store result in `dest`.
* Should store result in `dest`.
*/
*/
virtual
void
reg_read
(
uint8_t
bar
,
uint64_t
addr
,
void
*
dest
,
virtual
void
reg_read
(
uint8_t
bar
,
uint64_t
addr
,
void
*
dest
,
size_t
len
)
=
0
;
size_t
len
)
=
0
;
/**
/**
* execute a register write to `bar`:`addr` of length `len`,
* execute a register write to `bar`:`addr` of length `len`,
* with the data in `src`.
* with the data in `src`.
*/
*/
virtual
void
reg_write
(
uint8_t
bar
,
uint64_t
addr
,
const
void
*
src
,
virtual
void
reg_write
(
uint8_t
bar
,
uint64_t
addr
,
size_t
len
)
=
0
;
const
void
*
src
,
size_t
len
)
=
0
;
/**
/**
* the previously issued DMA operation `op` completed.
* the previously issued DMA operation `op` completed.
*/
*/
virtual
void
dma_complete
(
DMAOp
&
op
)
=
0
;
virtual
void
dma_complete
(
DMAOp
&
op
)
=
0
;
/**
/**
* A packet has arrived on the wire, of length `len` with
* A packet has arrived on the wire, of length `len` with
* payload `data`.
* payload `data`.
*/
*/
virtual
void
eth_rx
(
uint8_t
port
,
const
void
*
data
,
size_t
len
)
=
0
;
virtual
void
eth_rx
(
uint8_t
port
,
const
void
*
data
,
size_t
len
)
=
0
;
/**
* A timed event is due.
/**
*/
* A timed event is due.
virtual
void
timed_event
(
TimedEvent
&
ev
);
*/
virtual
void
timed_event
(
TimedEvent
&
ev
);
/**
* Device control update
/**
*/
* Device control update
virtual
void
devctrl_update
(
struct
cosim_pcie_proto_h2d_devctrl
&
devctrl
);
*/
};
virtual
void
devctrl_update
(
struct
cosim_pcie_proto_h2d_devctrl
&
devctrl
);
protected:
};
struct
event_cmp
{
bool
operator
()(
TimedEvent
*
a
,
TimedEvent
*
b
)
{
protected:
return
a
->
time
<
b
->
time
;
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
;
Device
&
dev
;
uint64_t
mac_addr
;
std
::
set
<
TimedEvent
*
,
event_cmp
>
events
;
struct
nicsim_params
nsparams
;
std
::
deque
<
DMAOp
*>
dma_queue
;
struct
cosim_pcie_proto_dev_intro
dintro
;
size_t
dma_pending
;
uint64_t
mac_addr
;
volatile
union
cosim_pcie_proto_d2h
*
d2h_alloc
(
void
);
struct
nicsim_params
nsparams
;
volatile
union
cosim_eth_proto_d2n
*
d2n_alloc
(
void
);
struct
cosim_pcie_proto_dev_intro
dintro
;
void
h2d_read
(
volatile
struct
cosim_pcie_proto_h2d_read
*
read
);
volatile
union
cosim_pcie_proto_d2h
*
d2h_alloc
(
void
);
void
h2d_write
(
volatile
struct
cosim_pcie_proto_h2d_write
*
write
);
volatile
union
cosim_eth_proto_d2n
*
d2n_alloc
(
void
);
void
h2d_readcomp
(
volatile
struct
cosim_pcie_proto_h2d_readcomp
*
rc
);
void
h2d_writecomp
(
volatile
struct
cosim_pcie_proto_h2d_writecomp
*
wc
);
void
h2d_read
(
volatile
struct
cosim_pcie_proto_h2d_read
*
read
);
void
h2d_devctrl
(
volatile
struct
cosim_pcie_proto_h2d_devctrl
*
dc
);
void
h2d_write
(
volatile
struct
cosim_pcie_proto_h2d_write
*
write
);
void
poll_h2d
();
void
h2d_readcomp
(
volatile
struct
cosim_pcie_proto_h2d_readcomp
*
rc
);
void
h2d_writecomp
(
volatile
struct
cosim_pcie_proto_h2d_writecomp
*
wc
);
void
eth_recv
(
volatile
struct
cosim_eth_proto_n2d_recv
*
recv
);
void
h2d_devctrl
(
volatile
struct
cosim_pcie_proto_h2d_devctrl
*
dc
);
void
poll_n2d
();
void
poll_h2d
();
bool
event_next
(
uint64_t
&
retval
);
void
eth_recv
(
volatile
struct
cosim_eth_proto_n2d_recv
*
recv
);
void
event_trigger
();
void
poll_n2d
();
void
dma_do
(
DMAOp
&
op
);
bool
event_next
(
uint64_t
&
retval
);
void
dma_trigger
();
void
event_trigger
();
public:
void
dma_do
(
DMAOp
&
op
);
Runner
(
Device
&
dev_
);
void
dma_trigger
();
/** Run the simulation */
public:
int
runMain
(
int
argc
,
char
*
argv
[]);
Runner
(
Device
&
dev_
);
/* these three are for `Runner::Device`. */
/** Run the simulation */
void
issue_dma
(
DMAOp
&
op
);
int
runMain
(
int
argc
,
char
*
argv
[]);
void
msi_issue
(
uint8_t
vec
);
void
msix_issue
(
uint8_t
vec
);
/* these three are for `Runner::Device`. */
void
eth_send
(
const
void
*
data
,
size_t
len
);
void
issue_dma
(
DMAOp
&
op
);
void
msi_issue
(
uint8_t
vec
);
void
event_schedule
(
TimedEvent
&
evt
);
void
msix_issue
(
uint8_t
vec
);
void
event_cancel
(
TimedEvent
&
evt
);
void
eth_send
(
const
void
*
data
,
size_t
len
);
uint64_t
time_ps
()
const
;
void
event_schedule
(
TimedEvent
&
evt
);
uint64_t
get_mac_addr
()
const
;
void
event_cancel
(
TimedEvent
&
evt
);
uint64_t
time_ps
()
const
;
uint64_t
get_mac_addr
()
const
;
};
};
/**
/**
...
@@ -172,26 +170,23 @@ class Runner {
...
@@ -172,26 +170,23 @@ class Runner {
*/
*/
template
<
class
TReg
=
uint32_t
>
template
<
class
TReg
=
uint32_t
>
class
SimpleDevice
:
public
Runner
::
Device
{
class
SimpleDevice
:
public
Runner
::
Device
{
public:
public:
virtual
TReg
reg_read
(
uint8_t
bar
,
uint64_t
addr
)
=
0
;
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_write
(
uint8_t
bar
,
uint64_t
addr
,
TReg
val
)
=
0
;
virtual
void
reg_read
(
uint8_t
bar
,
uint64_t
addr
,
void
*
dest
,
virtual
void
reg_read
(
uint8_t
bar
,
uint64_t
addr
,
void
*
dest
,
size_t
len
)
{
size_t
len
)
assert
(
len
==
sizeof
(
TReg
));
{
TReg
r
=
reg_read
(
bar
,
addr
);
assert
(
len
==
sizeof
(
TReg
));
memcpy
(
dest
,
&
r
,
sizeof
(
r
));
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
)
{
virtual
void
reg_write
(
uint8_t
bar
,
uint64_t
addr
,
assert
(
len
==
sizeof
(
TReg
));
const
void
*
src
,
size_t
len
)
TReg
r
;
{
memcpy
(
&
r
,
src
,
sizeof
(
r
));
assert
(
len
==
sizeof
(
TReg
));
reg_write
(
bar
,
addr
,
r
);
TReg
r
;
}
memcpy
(
&
r
,
src
,
sizeof
(
r
));
reg_write
(
bar
,
addr
,
r
);
}
};
};
}
// namespace nicbm
}
// namespace nicbm
...
...
lib/simbricks/nicif/nicsim.c
View file @
d4666c97
...
@@ -22,11 +22,11 @@
...
@@ -22,11 +22,11 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include <
stdlib
.h>
#include <
poll
.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <poll.h>
#include <unistd.h>
#include <unistd.h>
#include <simbricks/nicif/nicsim.h>
#include <simbricks/nicif/nicsim.h>
...
@@ -45,7 +45,6 @@
...
@@ -45,7 +45,6 @@
#define N2D_ELEN (9024 + 64)
#define N2D_ELEN (9024 + 64)
#define N2D_ENUM 8192
#define N2D_ENUM 8192
static
uint8_t
*
d2h_queue
;
static
uint8_t
*
d2h_queue
;
static
size_t
d2h_pos
;
static
size_t
d2h_pos
;
static
size_t
d2h_off
;
/* offset in shm region */
static
size_t
d2h_off
;
/* offset in shm region */
...
@@ -74,402 +73,373 @@ static int pci_cfd = -1;
...
@@ -74,402 +73,373 @@ static int pci_cfd = -1;
static
int
eth_cfd
=
-
1
;
static
int
eth_cfd
=
-
1
;
static
int
accept_pci
(
struct
cosim_pcie_proto_dev_intro
*
di
,
int
pci_lfd
,
static
int
accept_pci
(
struct
cosim_pcie_proto_dev_intro
*
di
,
int
pci_lfd
,
int
*
sync_pci
)
int
*
sync_pci
)
{
{
if
((
pci_cfd
=
accept
(
pci_lfd
,
NULL
,
NULL
))
<
0
)
{
if
((
pci_cfd
=
accept
(
pci_lfd
,
NULL
,
NULL
))
<
0
)
{
return
-
1
;
return
-
1
;
}
}
close
(
pci_lfd
);
close
(
pci_lfd
);
printf
(
"pci connection accepted
\n
"
);
printf
(
"pci connection accepted
\n
"
);
di
->
d2h_offset
=
d2h_off
;
di
->
d2h_offset
=
d2h_off
;
di
->
d2h_elen
=
D2H_ELEN
;
di
->
d2h_elen
=
D2H_ELEN
;
di
->
d2h_nentries
=
D2H_ENUM
;
di
->
d2h_nentries
=
D2H_ENUM
;
di
->
h2d_offset
=
h2d_off
;
di
->
h2d_offset
=
h2d_off
;
di
->
h2d_elen
=
H2D_ELEN
;
di
->
h2d_elen
=
H2D_ELEN
;
di
->
h2d_nentries
=
H2D_ENUM
;
di
->
h2d_nentries
=
H2D_ENUM
;
if
(
*
sync_pci
)
if
(
*
sync_pci
)
di
->
flags
|=
COSIM_PCIE_PROTO_FLAGS_DI_SYNC
;
di
->
flags
|=
COSIM_PCIE_PROTO_FLAGS_DI_SYNC
;
else
else
di
->
flags
&=
~
((
uint64_t
)
COSIM_PCIE_PROTO_FLAGS_DI_SYNC
);
di
->
flags
&=
~
((
uint64_t
)
COSIM_PCIE_PROTO_FLAGS_DI_SYNC
);
if
(
uxsocket_send
(
pci_cfd
,
di
,
sizeof
(
*
di
),
shm_fd
))
{
if
(
uxsocket_send
(
pci_cfd
,
di
,
sizeof
(
*
di
),
shm_fd
))
{
return
-
1
;
return
-
1
;
}
}
printf
(
"pci intro sent
\n
"
);
printf
(
"pci intro sent
\n
"
);
return
0
;
return
0
;
}
}
static
int
accept_eth
(
int
eth_lfd
,
int
*
sync_eth
)
static
int
accept_eth
(
int
eth_lfd
,
int
*
sync_eth
)
{
{
struct
cosim_eth_proto_dev_intro
di
;
struct
cosim_eth_proto_dev_intro
di
;
if
((
eth_cfd
=
accept
(
eth_lfd
,
NULL
,
NULL
))
<
0
)
{
return
-
1
;
}
close
(
eth_lfd
);
printf
(
"eth connection accepted
\n
"
);
memset
(
&
di
,
0
,
sizeof
(
di
));
di
.
flags
=
0
;
if
(
*
sync_eth
)
di
.
flags
|=
COSIM_ETH_PROTO_FLAGS_DI_SYNC
;
di
.
d2n_offset
=
d2n_off
;
di
.
d2n_elen
=
D2N_ELEN
;
di
.
d2n_nentries
=
D2N_ENUM
;
di
.
n2d_offset
=
n2d_off
;
di
.
n2d_elen
=
N2D_ELEN
;
di
.
n2d_nentries
=
N2D_ENUM
;
if
(
uxsocket_send
(
eth_cfd
,
&
di
,
sizeof
(
di
),
shm_fd
))
{
return
-
1
;
}
printf
(
"eth intro sent
\n
"
);
return
0
;
}
if
((
eth_cfd
=
accept
(
eth_lfd
,
NULL
,
NULL
))
<
0
)
{
static
int
accept_conns
(
struct
cosim_pcie_proto_dev_intro
*
di
,
int
pci_lfd
,
int
*
sync_pci
,
int
eth_lfd
,
int
*
sync_eth
)
{
struct
pollfd
pfds
[
2
];
int
await_pci
=
pci_lfd
!=
-
1
;
int
await_eth
=
eth_lfd
!=
-
1
;
int
ret
;
while
(
await_pci
||
await_eth
)
{
if
(
await_pci
&&
await_eth
)
{
/* we're waiting on both fds */
pfds
[
0
].
fd
=
pci_lfd
;
pfds
[
1
].
fd
=
eth_lfd
;
pfds
[
0
].
events
=
pfds
[
1
].
events
=
POLLIN
;
pfds
[
0
].
revents
=
pfds
[
1
].
revents
=
0
;
ret
=
poll
(
pfds
,
2
,
-
1
);
if
(
ret
<
0
)
{
perror
(
"poll failed"
);
return
-
1
;
return
-
1
;
}
}
close
(
eth_lfd
);
printf
(
"eth connection accepted
\n
"
);
if
(
pfds
[
0
].
revents
)
{
if
(
accept_pci
(
di
,
pci_lfd
,
sync_pci
)
!=
0
)
memset
(
&
di
,
0
,
sizeof
(
di
));
return
-
1
;
di
.
flags
=
0
;
await_pci
=
0
;
if
(
*
sync_eth
)
}
di
.
flags
|=
COSIM_ETH_PROTO_FLAGS_DI_SYNC
;
if
(
pfds
[
1
].
revents
)
{
if
(
accept_eth
(
eth_lfd
,
sync_eth
)
!=
0
)
di
.
d2n_offset
=
d2n_off
;
return
-
1
;
di
.
d2n_elen
=
D2N_ELEN
;
await_eth
=
0
;
di
.
d2n_nentries
=
D2N_ENUM
;
}
}
else
if
(
await_pci
)
{
di
.
n2d_offset
=
n2d_off
;
/* waiting just on pci */
di
.
n2d_elen
=
N2D_ELEN
;
if
(
accept_pci
(
di
,
pci_lfd
,
sync_pci
)
!=
0
)
di
.
n2d_nentries
=
N2D_ENUM
;
if
(
uxsocket_send
(
eth_cfd
,
&
di
,
sizeof
(
di
),
shm_fd
))
{
return
-
1
;
return
-
1
;
await_pci
=
0
;
}
else
{
/* waiting just on ethernet */
if
(
accept_eth
(
eth_lfd
,
sync_eth
)
!=
0
)
return
-
1
;
await_eth
=
0
;
}
}
printf
(
"eth intro sent
\n
"
);
}
return
0
;
}
static
int
accept_conns
(
struct
cosim_pcie_proto_dev_intro
*
di
,
int
pci_lfd
,
int
*
sync_pci
,
int
eth_lfd
,
int
*
sync_eth
)
{
struct
pollfd
pfds
[
2
];
int
await_pci
=
pci_lfd
!=
-
1
;
int
await_eth
=
eth_lfd
!=
-
1
;
int
ret
;
while
(
await_pci
||
await_eth
)
{
if
(
await_pci
&&
await_eth
)
{
/* we're waiting on both fds */
pfds
[
0
].
fd
=
pci_lfd
;
pfds
[
1
].
fd
=
eth_lfd
;
pfds
[
0
].
events
=
pfds
[
1
].
events
=
POLLIN
;
pfds
[
0
].
revents
=
pfds
[
1
].
revents
=
0
;
ret
=
poll
(
pfds
,
2
,
-
1
);
if
(
ret
<
0
)
{
perror
(
"poll failed"
);
return
-
1
;
}
if
(
pfds
[
0
].
revents
)
{
if
(
accept_pci
(
di
,
pci_lfd
,
sync_pci
)
!=
0
)
return
-
1
;
await_pci
=
0
;
}
if
(
pfds
[
1
].
revents
)
{
if
(
accept_eth
(
eth_lfd
,
sync_eth
)
!=
0
)
return
-
1
;
await_eth
=
0
;
}
}
else
if
(
await_pci
)
{
/* waiting just on pci */
if
(
accept_pci
(
di
,
pci_lfd
,
sync_pci
)
!=
0
)
return
-
1
;
await_pci
=
0
;
}
else
{
/* waiting just on ethernet */
if
(
accept_eth
(
eth_lfd
,
sync_eth
)
!=
0
)
return
-
1
;
await_eth
=
0
;
}
}
return
0
;
return
0
;
}
}
int
nicsim_init
(
struct
nicsim_params
*
params
,
int
nicsim_init
(
struct
nicsim_params
*
params
,
struct
cosim_pcie_proto_dev_intro
*
di
)
struct
cosim_pcie_proto_dev_intro
*
di
)
{
{
int
pci_lfd
=
-
1
,
eth_lfd
=
-
1
;
int
pci_lfd
=
-
1
,
eth_lfd
=
-
1
;
void
*
shmptr
;
void
*
shmptr
;
size_t
shm_size
;
size_t
shm_size
;
/* ready in memory queues */
/* ready in memory queues */
shm_size
=
(
uint64_t
)
D2H_ELEN
*
D2H_ENUM
+
(
uint64_t
)
H2D_ELEN
*
H2D_ENUM
+
shm_size
=
(
uint64_t
)
D2H_ELEN
*
D2H_ENUM
+
(
uint64_t
)
D2N_ELEN
*
D2N_ENUM
+
(
uint64_t
)
N2D_ELEN
*
N2D_ENUM
;
(
uint64_t
)
H2D_ELEN
*
H2D_ENUM
+
if
((
shm_fd
=
shm_create
(
params
->
shm_path
,
shm_size
,
&
shmptr
))
<
0
)
{
(
uint64_t
)
D2N_ELEN
*
D2N_ENUM
+
return
-
1
;
(
uint64_t
)
N2D_ELEN
*
N2D_ENUM
;
}
if
((
shm_fd
=
shm_create
(
params
->
shm_path
,
shm_size
,
&
shmptr
))
<
0
)
d2h_off
=
0
;
{
h2d_off
=
d2h_off
+
(
uint64_t
)
D2H_ELEN
*
D2H_ENUM
;
return
-
1
;
d2n_off
=
h2d_off
+
(
uint64_t
)
H2D_ELEN
*
H2D_ENUM
;
}
n2d_off
=
d2n_off
+
(
uint64_t
)
D2N_ELEN
*
D2N_ENUM
;
d2h_off
=
0
;
d2h_queue
=
(
uint8_t
*
)
shmptr
+
d2h_off
;
h2d_off
=
d2h_off
+
(
uint64_t
)
D2H_ELEN
*
D2H_ENUM
;
h2d_queue
=
(
uint8_t
*
)
shmptr
+
h2d_off
;
d2n_off
=
h2d_off
+
(
uint64_t
)
H2D_ELEN
*
H2D_ENUM
;
d2n_queue
=
(
uint8_t
*
)
shmptr
+
d2n_off
;
n2d_off
=
d2n_off
+
(
uint64_t
)
D2N_ELEN
*
D2N_ENUM
;
n2d_queue
=
(
uint8_t
*
)
shmptr
+
n2d_off
;
d2h_queue
=
(
uint8_t
*
)
shmptr
+
d2h_off
;
d2h_pos
=
h2d_pos
=
d2n_pos
=
n2d_pos
=
0
;
h2d_queue
=
(
uint8_t
*
)
shmptr
+
h2d_off
;
d2n_queue
=
(
uint8_t
*
)
shmptr
+
d2n_off
;
/* get listening sockets ready */
n2d_queue
=
(
uint8_t
*
)
shmptr
+
n2d_off
;
if
(
params
->
pci_socket_path
!=
NULL
)
{
if
((
pci_lfd
=
uxsocket_init
(
params
->
pci_socket_path
))
<
0
)
{
d2h_pos
=
h2d_pos
=
d2n_pos
=
n2d_pos
=
0
;
return
-
1
;
/* get listening sockets ready */
if
(
params
->
pci_socket_path
!=
NULL
)
{
if
((
pci_lfd
=
uxsocket_init
(
params
->
pci_socket_path
))
<
0
)
{
return
-
1
;
}
}
if
(
params
->
eth_socket_path
!=
NULL
)
{
if
((
eth_lfd
=
uxsocket_init
(
params
->
eth_socket_path
))
<
0
)
{
return
-
1
;
}
}
}
}
/* accept connection fds */
if
(
params
->
eth_socket_path
!=
NULL
)
{
if
(
accept_conns
(
di
,
pci_lfd
,
&
params
->
sync_pci
,
eth_lfd
,
if
((
eth_lfd
=
uxsocket_init
(
params
->
eth_socket_path
))
<
0
)
{
&
params
->
sync_eth
)
!=
0
)
return
-
1
;
{
return
-
1
;
}
}
}
/* receive introductions from other end */
if
(
params
->
pci_socket_path
!=
NULL
)
{
/* accept connection fds */
struct
cosim_pcie_proto_host_intro
hi
;
if
(
accept_conns
(
di
,
pci_lfd
,
&
params
->
sync_pci
,
eth_lfd
,
if
(
recv
(
pci_cfd
,
&
hi
,
sizeof
(
hi
),
0
)
!=
sizeof
(
hi
))
{
&
params
->
sync_eth
)
!=
0
)
{
return
-
1
;
return
-
1
;
}
}
if
((
hi
.
flags
&
COSIM_PCIE_PROTO_FLAGS_HI_SYNC
)
==
0
)
params
->
sync_pci
=
0
;
/* receive introductions from other end */
printf
(
"pci host info received
\n
"
);
if
(
params
->
pci_socket_path
!=
NULL
)
{
struct
cosim_pcie_proto_host_intro
hi
;
if
(
recv
(
pci_cfd
,
&
hi
,
sizeof
(
hi
),
0
)
!=
sizeof
(
hi
))
{
return
-
1
;
}
}
if
(
params
->
eth_socket_path
!=
NULL
)
{
if
(
(
hi
.
flags
&
COSIM_PCIE_PROTO_FLAGS_HI_SYNC
)
==
0
)
struct
cosim_eth_proto_net_intro
ni
;
params
->
sync_pci
=
0
;
if
(
recv
(
eth_cfd
,
&
ni
,
sizeof
(
ni
),
0
)
!=
sizeof
(
ni
))
{
printf
(
"pci host info received
\n
"
);
return
-
1
;
}
}
if
(
params
->
eth_socket_path
!=
NULL
)
{
if
((
ni
.
flags
&
COSIM_ETH_PROTO_FLAGS_NI_SYNC
)
==
0
)
struct
cosim_eth_proto_net_intro
ni
;
params
->
sync_eth
=
0
;
if
(
recv
(
eth_cfd
,
&
ni
,
sizeof
(
ni
),
0
)
!=
sizeof
(
ni
))
{
printf
(
"eth net info received
\n
"
)
;
return
-
1
;
}
}
if
((
ni
.
flags
&
COSIM_ETH_PROTO_FLAGS_NI_SYNC
)
==
0
)
params
->
sync_eth
=
0
;
printf
(
"eth net info received
\n
"
);
}
return
0
;
return
0
;
}
}
void
nicsim_cleanup
(
void
)
void
nicsim_cleanup
(
void
)
{
{
close
(
pci_cfd
);
close
(
pci_cfd
);
close
(
eth_cfd
);
close
(
eth_cfd
);
}
}
/******************************************************************************/
/******************************************************************************/
/* Sync */
/* Sync */
int
nicsim_sync
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
)
int
nicsim_sync
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
)
{
{
int
ret
=
0
;
int
ret
=
0
;
volatile
union
cosim_pcie_proto_d2h
*
d2h
;
volatile
union
cosim_pcie_proto_d2h
*
d2h
;
volatile
union
cosim_eth_proto_d2n
*
d2n
;
volatile
union
cosim_eth_proto_d2n
*
d2n
;
/* sync PCI if necessary */
/* sync PCI if necessary */
if
(
params
->
sync_pci
)
{
if
(
params
->
sync_pci
)
{
int
sync
;
int
sync
;
switch
(
params
->
sync_mode
)
{
switch
(
params
->
sync_mode
)
{
case
SYNC_MODES
:
case
SYNC_MODES
:
sync
=
pci_last_tx_time
==
0
||
sync
=
pci_last_tx_time
==
0
||
timestamp
-
pci_last_tx_time
>=
params
->
sync_delay
;
timestamp
-
pci_last_tx_time
>=
params
->
sync_delay
;
break
;
break
;
case
SYNC_BARRIER
:
case
SYNC_BARRIER
:
sync
=
current_epoch
==
0
||
sync
=
current_epoch
==
0
||
timestamp
-
current_epoch
>=
params
->
sync_delay
;
timestamp
-
current_epoch
>=
params
->
sync_delay
;
break
;
break
;
default:
default:
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
params
->
sync_mode
);
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
params
->
sync_mode
);
return
ret
;
return
ret
;
}
}
if
(
sync
)
{
if
(
sync
)
d2h
=
nicsim_d2h_alloc
(
params
,
timestamp
);
{
if
(
d2h
==
NULL
)
{
d2h
=
nicsim_d2h_alloc
(
params
,
timestamp
);
ret
=
-
1
;
if
(
d2h
==
NULL
)
{
}
else
{
ret
=
-
1
;
d2h
->
sync
.
own_type
=
}
else
{
COSIM_PCIE_PROTO_D2H_MSG_SYNC
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
d2h
->
sync
.
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_SYNC
|
}
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
}
}
}
/* sync Ethernet if necessary */
if
(
params
->
sync_eth
)
{
int
sync
;
switch
(
params
->
sync_mode
)
{
case
SYNC_MODES
:
sync
=
eth_last_tx_time
==
0
||
timestamp
-
eth_last_tx_time
>=
params
->
sync_delay
;
break
;
case
SYNC_BARRIER
:
sync
=
current_epoch
==
0
||
timestamp
-
current_epoch
>=
params
->
sync_delay
;
break
;
default:
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
params
->
sync_mode
);
return
ret
;
}
}
/* sync Ethernet if necessary */
if
(
sync
)
{
if
(
params
->
sync_eth
)
{
d2n
=
nicsim_d2n_alloc
(
params
,
timestamp
);
int
sync
;
if
(
d2n
==
NULL
)
{
switch
(
params
->
sync_mode
)
{
ret
=
-
1
;
case
SYNC_MODES
:
}
else
{
sync
=
eth_last_tx_time
==
0
||
d2n
->
sync
.
own_type
=
timestamp
-
eth_last_tx_time
>=
params
->
sync_delay
;
COSIM_ETH_PROTO_D2N_MSG_SYNC
|
COSIM_ETH_PROTO_D2N_OWN_NET
;
break
;
}
case
SYNC_BARRIER
:
sync
=
current_epoch
==
0
||
timestamp
-
current_epoch
>=
params
->
sync_delay
;
break
;
default:
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
params
->
sync_mode
);
return
ret
;
}
if
(
sync
)
{
d2n
=
nicsim_d2n_alloc
(
params
,
timestamp
);
if
(
d2n
==
NULL
)
{
ret
=
-
1
;
}
else
{
d2n
->
sync
.
own_type
=
COSIM_ETH_PROTO_D2N_MSG_SYNC
|
COSIM_ETH_PROTO_D2N_OWN_NET
;
}
}
}
}
}
return
ret
;
return
ret
;
}
}
void
nicsim_advance_epoch
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
)
void
nicsim_advance_epoch
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
)
{
{
if
(
params
->
sync_mode
==
SYNC_BARRIER
)
{
if
(
params
->
sync_mode
==
SYNC_BARRIER
)
{
if
((
params
->
sync_pci
||
params
->
sync_eth
)
&&
if
((
params
->
sync_pci
||
params
->
sync_eth
)
&&
timestamp
-
current_epoch
>=
params
->
sync_delay
)
{
timestamp
-
current_epoch
>=
params
->
sync_delay
)
{
current_epoch
=
timestamp
;
current_epoch
=
timestamp
;
}
}
}
}
}
}
uint64_t
nicsim_advance_time
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
)
uint64_t
nicsim_advance_time
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
)
{
{
switch
(
params
->
sync_mode
)
{
switch
(
params
->
sync_mode
)
{
case
SYNC_MODES
:
case
SYNC_MODES
:
return
timestamp
;
return
timestamp
;
case
SYNC_BARRIER
:
case
SYNC_BARRIER
:
return
timestamp
<
current_epoch
+
params
->
sync_delay
?
return
timestamp
<
current_epoch
+
params
->
sync_delay
timestamp
:
current_epoch
+
params
->
sync_delay
;
?
timestamp
:
current_epoch
+
params
->
sync_delay
;
default:
default:
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
params
->
sync_mode
);
fprintf
(
stderr
,
"unsupported sync mode=%u
\n
"
,
params
->
sync_mode
);
return
timestamp
;
return
timestamp
;
}
}
}
}
uint64_t
nicsim_next_timestamp
(
struct
nicsim_params
*
params
)
uint64_t
nicsim_next_timestamp
(
struct
nicsim_params
*
params
)
{
{
if
(
params
->
sync_pci
&&
params
->
sync_eth
)
{
if
(
params
->
sync_pci
&&
params
->
sync_eth
)
{
return
(
pci_last_rx_time
<=
eth_last_rx_time
?
pci_last_rx_time
return
(
pci_last_rx_time
<=
eth_last_rx_time
?
pci_last_rx_time
:
:
eth_last_rx_time
);
eth_last_rx_time
);
}
else
if
(
params
->
sync_pci
)
{
}
else
if
(
params
->
sync_pci
)
{
return
pci_last_rx_time
;
return
pci_last_rx_time
;
}
else
if
(
params
->
sync_eth
)
{
}
else
if
(
params
->
sync_eth
)
{
return
eth_last_rx_time
;
return
eth_last_rx_time
;
}
else
{
}
else
{
return
0
;
return
0
;
}
}
}
}
/******************************************************************************/
/******************************************************************************/
/* PCI */
/* PCI */
volatile
union
cosim_pcie_proto_h2d
*
nicif_h2d_poll
(
volatile
union
cosim_pcie_proto_h2d
*
nicif_h2d_poll
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
)
struct
nicsim_params
*
params
,
uint64_t
timestamp
)
{
{
volatile
union
cosim_pcie_proto_h2d
*
msg
=
volatile
union
cosim_pcie_proto_h2d
*
msg
=
(
volatile
union
cosim_pcie_proto_h2d
*
)(
h2d_queue
+
h2d_pos
*
H2D_ELEN
);
(
volatile
union
cosim_pcie_proto_h2d
*
)
(
h2d_queue
+
h2d_pos
*
H2D_ELEN
);
/* message not ready */
if
((
msg
->
dummy
.
own_type
&
COSIM_PCIE_PROTO_H2D_OWN_MASK
)
!=
/* message not ready */
COSIM_PCIE_PROTO_H2D_OWN_DEV
)
if
((
msg
->
dummy
.
own_type
&
COSIM_PCIE_PROTO_H2D_OWN_MASK
)
!=
return
NULL
;
COSIM_PCIE_PROTO_H2D_OWN_DEV
)
return
NULL
;
/* if in sync mode, wait till message is ready */
pci_last_rx_time
=
msg
->
dummy
.
timestamp
;
/* if in sync mode, wait till message is ready */
if
(
params
->
sync_pci
&&
pci_last_rx_time
>
timestamp
)
pci_last_rx_time
=
msg
->
dummy
.
timestamp
;
return
NULL
;
if
(
params
->
sync_pci
&&
pci_last_rx_time
>
timestamp
)
return
NULL
;
return
msg
;
return
msg
;
}
}
void
nicif_h2d_done
(
volatile
union
cosim_pcie_proto_h2d
*
msg
)
void
nicif_h2d_done
(
volatile
union
cosim_pcie_proto_h2d
*
msg
)
{
{
msg
->
dummy
.
own_type
=
(
msg
->
dummy
.
own_type
&
COSIM_PCIE_PROTO_H2D_MSG_MASK
)
|
msg
->
dummy
.
own_type
=
(
msg
->
dummy
.
own_type
&
COSIM_PCIE_PROTO_H2D_MSG_MASK
)
COSIM_PCIE_PROTO_H2D_OWN_HOST
;
|
COSIM_PCIE_PROTO_H2D_OWN_HOST
;
}
}
void
nicif_h2d_next
(
void
)
void
nicif_h2d_next
(
void
)
{
{
h2d_pos
=
(
h2d_pos
+
1
)
%
H2D_ENUM
;
h2d_pos
=
(
h2d_pos
+
1
)
%
H2D_ENUM
;
}
}
volatile
union
cosim_pcie_proto_d2h
*
nicsim_d2h_alloc
(
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_pcie_proto_d2h
*
msg
=
volatile
union
cosim_pcie_proto_d2h
*
msg
=
(
volatile
union
cosim_pcie_proto_d2h
*
)(
d2h_queue
+
d2h_pos
*
D2H_ELEN
);
(
volatile
union
cosim_pcie_proto_d2h
*
)
(
d2h_queue
+
d2h_pos
*
D2H_ELEN
);
if
((
msg
->
dummy
.
own_type
&
COSIM_PCIE_PROTO_D2H_OWN_MASK
)
!=
COSIM_PCIE_PROTO_D2H_OWN_DEV
)
{
return
NULL
;
}
msg
->
dummy
.
timestamp
=
timestamp
+
params
->
pci_latency
;
if
((
msg
->
dummy
.
own_type
&
COSIM_PCIE_PROTO_D2H_OWN_MASK
)
!=
pci_last_tx_time
=
timestamp
;
COSIM_PCIE_PROTO_D2H_OWN_DEV
)
{
return
NULL
;
}
d2h_pos
=
(
d2h_pos
+
1
)
%
D2H_ENUM
;
msg
->
dummy
.
timestamp
=
timestamp
+
params
->
pci_latency
;
return
msg
;
pci_last_tx_time
=
timestamp
;
d2h_pos
=
(
d2h_pos
+
1
)
%
D2H_ENUM
;
return
msg
;
}
}
/******************************************************************************/
/******************************************************************************/
/* Ethernet */
/* Ethernet */
volatile
union
cosim_eth_proto_n2d
*
nicif_n2d_poll
(
volatile
union
cosim_eth_proto_n2d
*
nicif_n2d_poll
(
struct
nicsim_params
*
params
,
struct
nicsim_params
*
params
,
uint64_t
timestamp
)
uint64_t
timestamp
)
{
{
volatile
union
cosim_eth_proto_n2d
*
msg
=
volatile
union
cosim_eth_proto_n2d
*
msg
=
(
volatile
union
cosim_eth_proto_n2d
*
)(
n2d_queue
+
n2d_pos
*
N2D_ELEN
);
(
volatile
union
cosim_eth_proto_n2d
*
)
(
n2d_queue
+
n2d_pos
*
N2D_ELEN
);
/* message not ready */
/* message not ready */
if
((
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_N2D_OWN_MASK
)
!=
if
((
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_N2D_OWN_MASK
)
!=
COSIM_ETH_PROTO_N2D_OWN_DEV
)
COSIM_ETH_PROTO_N2D_OWN_DEV
)
return
NULL
;
return
NULL
;
/* if in sync mode, wait till message is ready */
/* if in sync mode, wait till message is ready */
eth_last_rx_time
=
msg
->
dummy
.
timestamp
;
eth_last_rx_time
=
msg
->
dummy
.
timestamp
;
if
(
params
->
sync_eth
&&
eth_last_rx_time
>
timestamp
)
if
(
params
->
sync_eth
&&
eth_last_rx_time
>
timestamp
)
return
NULL
;
return
NULL
;
return
msg
;
return
msg
;
}
}
void
nicif_n2d_done
(
volatile
union
cosim_eth_proto_n2d
*
msg
)
void
nicif_n2d_done
(
volatile
union
cosim_eth_proto_n2d
*
msg
)
{
{
msg
->
dummy
.
own_type
=
(
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_N2D_MSG_MASK
)
|
msg
->
dummy
.
own_type
=
(
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_N2D_MSG_MASK
)
COSIM_ETH_PROTO_N2D_OWN_NET
;
|
COSIM_ETH_PROTO_N2D_OWN_NET
;
}
}
void
nicif_n2d_next
(
void
)
void
nicif_n2d_next
(
void
)
{
{
n2d_pos
=
(
n2d_pos
+
1
)
%
N2D_ENUM
;
n2d_pos
=
(
n2d_pos
+
1
)
%
N2D_ENUM
;
}
}
volatile
union
cosim_eth_proto_d2n
*
nicsim_d2n_alloc
(
volatile
union
cosim_eth_proto_d2n
*
nicsim_d2n_alloc
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
)
struct
nicsim_params
*
params
,
uint64_t
timestamp
)
{
{
volatile
union
cosim_eth_proto_d2n
*
msg
=
volatile
union
cosim_eth_proto_d2n
*
msg
=
(
volatile
union
cosim_eth_proto_d2n
*
)(
d2n_queue
+
d2n_pos
*
D2N_ELEN
);
(
volatile
union
cosim_eth_proto_d2n
*
)
(
d2n_queue
+
d2n_pos
*
D2N_ELEN
);
if
((
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_OWN_MASK
)
!=
COSIM_ETH_PROTO_D2N_OWN_DEV
)
{
if
((
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_OWN_MASK
)
!=
return
NULL
;
COSIM_ETH_PROTO_D2N_OWN_DEV
)
}
{
return
NULL
;
}
msg
->
dummy
.
timestamp
=
timestamp
+
params
->
eth_latency
;
msg
->
dummy
.
timestamp
=
timestamp
+
params
->
eth_latency
;
eth_last_tx_time
=
timestamp
;
eth_last_tx_time
=
timestamp
;
d2n_pos
=
(
d2n_pos
+
1
)
%
D2N_ENUM
;
d2n_pos
=
(
d2n_pos
+
1
)
%
D2N_ENUM
;
return
msg
;
return
msg
;
}
}
lib/simbricks/nicif/nicsim.h
View file @
d4666c97
...
@@ -25,28 +25,28 @@
...
@@ -25,28 +25,28 @@
#ifndef SIMBRICKS_NICIF_NICSIM_H_
#ifndef SIMBRICKS_NICIF_NICSIM_H_
#define SIMBRICKS_NICIF_NICSIM_H_
#define SIMBRICKS_NICIF_NICSIM_H_
#include <simbricks/proto/pcie.h>
#include <simbricks/proto/network.h>
#include <simbricks/proto/network.h>
#include <simbricks/proto/pcie.h>
#define SYNC_MODES 0 // ModES style synchronization
#define SYNC_MODES 0 // ModES style synchronization
#define SYNC_BARRIER 1 // Global barrier style synchronization
#define SYNC_BARRIER 1 // Global barrier style synchronization
struct
nicsim_params
{
struct
nicsim_params
{
const
char
*
pci_socket_path
;
const
char
*
pci_socket_path
;
const
char
*
eth_socket_path
;
const
char
*
eth_socket_path
;
const
char
*
shm_path
;
const
char
*
shm_path
;
uint64_t
pci_latency
;
uint64_t
pci_latency
;
uint64_t
eth_latency
;
uint64_t
eth_latency
;
uint64_t
sync_delay
;
uint64_t
sync_delay
;
int
sync_pci
;
int
sync_pci
;
int
sync_eth
;
int
sync_eth
;
int
sync_mode
;
int
sync_mode
;
};
};
int
nicsim_init
(
struct
nicsim_params
*
params
,
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
);
void
nicsim_cleanup
(
void
);
int
nicsim_sync
(
struct
nicsim_params
*
params
,
uint64_t
timestamp
);
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);
...
@@ -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
);
uint64_t
nicsim_next_timestamp
(
struct
nicsim_params
*
params
);
volatile
union
cosim_pcie_proto_h2d
*
nicif_h2d_poll
(
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_done
(
volatile
union
cosim_pcie_proto_h2d
*
msg
);
void
nicif_h2d_next
(
void
);
void
nicif_h2d_next
(
void
);
volatile
union
cosim_pcie_proto_d2h
*
nicsim_d2h_alloc
(
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
(
volatile
union
cosim_eth_proto_n2d
*
nicif_n2d_poll
(
struct
nicsim_params
*
params
,
struct
nicsim_params
*
params
,
uint64_t
timestamp
);
uint64_t
timestamp
);
void
nicif_n2d_done
(
volatile
union
cosim_eth_proto_n2d
*
msg
);
void
nicif_n2d_done
(
volatile
union
cosim_eth_proto_n2d
*
msg
);
void
nicif_n2d_next
(
void
);
void
nicif_n2d_next
(
void
);
volatile
union
cosim_eth_proto_d2n
*
nicsim_d2n_alloc
(
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_
#endif // SIMBRICKS_NICIF_NICSIM_H_
lib/simbricks/nicif/utils.c
View file @
d4666c97
...
@@ -24,116 +24,112 @@
...
@@ -24,116 +24,112 @@
#include <errno.h>
#include <errno.h>
#include <fcntl.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdbool.h>
#include <s
ys/un
.h>
#include <s
tdio
.h>
#include <s
ys/socket
.h>
#include <s
tdlib
.h>
#include <sys/mman.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <unistd.h>
#include "lib/simbricks/nicif/internal.h"
#include "lib/simbricks/nicif/internal.h"
int
uxsocket_init
(
const
char
*
path
)
int
uxsocket_init
(
const
char
*
path
)
{
{
int
fd
;
int
fd
;
struct
sockaddr_un
saun
;
struct
sockaddr_un
saun
;
if
((
fd
=
socket
(
AF_UNIX
,
SOCK_STREAM
,
0
))
==
-
1
)
{
if
((
fd
=
socket
(
AF_UNIX
,
SOCK_STREAM
,
0
))
==
-
1
)
{
perror
(
"uxsocket_init: socket failed"
);
perror
(
"uxsocket_init: socket failed"
);
goto
error_exit
;
goto
error_exit
;
}
}
memset
(
&
saun
,
0
,
sizeof
(
saun
));
memset
(
&
saun
,
0
,
sizeof
(
saun
));
saun
.
sun_family
=
AF_UNIX
;
saun
.
sun_family
=
AF_UNIX
;
memcpy
(
saun
.
sun_path
,
path
,
strlen
(
path
));
memcpy
(
saun
.
sun_path
,
path
,
strlen
(
path
));
if
(
bind
(
fd
,
(
struct
sockaddr
*
)
&
saun
,
sizeof
(
saun
)))
{
if
(
bind
(
fd
,
(
struct
sockaddr
*
)
&
saun
,
sizeof
(
saun
)))
{
perror
(
"uxsocket_init: bind failed"
);
perror
(
"uxsocket_init: bind failed"
);
goto
error_close
;
goto
error_close
;
}
}
if
(
listen
(
fd
,
5
))
{
if
(
listen
(
fd
,
5
))
{
perror
(
"uxsocket_init: listen failed"
);
perror
(
"uxsocket_init: listen failed"
);
goto
error_close
;
goto
error_close
;
}
}
return
fd
;
return
fd
;
error_close:
error_close:
close
(
fd
);
close
(
fd
);
error_exit:
error_exit:
return
-
1
;
return
-
1
;
}
}
int
uxsocket_send
(
int
connfd
,
void
*
data
,
size_t
len
,
int
fd
)
int
uxsocket_send
(
int
connfd
,
void
*
data
,
size_t
len
,
int
fd
)
{
{
ssize_t
tx
;
ssize_t
tx
;
struct
iovec
iov
=
{
struct
iovec
iov
=
{
.
iov_base
=
data
,
.
iov_base
=
data
,
.
iov_len
=
len
,
.
iov_len
=
len
,
};
};
union
{
union
{
char
buf
[
CMSG_SPACE
(
sizeof
(
int
))];
char
buf
[
CMSG_SPACE
(
sizeof
(
int
))];
struct
cmsghdr
align
;
struct
cmsghdr
align
;
}
u
;
}
u
;
struct
msghdr
msg
=
{
struct
msghdr
msg
=
{
.
msg_name
=
NULL
,
.
msg_name
=
NULL
,
.
msg_namelen
=
0
,
.
msg_namelen
=
0
,
.
msg_iov
=
&
iov
,
.
msg_iov
=
&
iov
,
.
msg_iovlen
=
1
,
.
msg_iovlen
=
1
,
.
msg_control
=
u
.
buf
,
.
msg_control
=
u
.
buf
,
.
msg_controllen
=
0
,
.
msg_controllen
=
0
,
.
msg_flags
=
0
,
.
msg_flags
=
0
,
};
};
struct
cmsghdr
*
cmsg
=
&
u
.
align
;
struct
cmsghdr
*
cmsg
=
&
u
.
align
;
if
(
fd
>=
0
)
{
if
(
fd
>=
0
)
{
msg
.
msg_controllen
=
sizeof
(
u
.
buf
);
msg
.
msg_controllen
=
sizeof
(
u
.
buf
);
cmsg
->
cmsg_level
=
SOL_SOCKET
;
cmsg
->
cmsg_level
=
SOL_SOCKET
;
cmsg
->
cmsg_type
=
SCM_RIGHTS
;
cmsg
->
cmsg_type
=
SCM_RIGHTS
;
cmsg
->
cmsg_len
=
CMSG_LEN
(
sizeof
(
int
));
cmsg
->
cmsg_len
=
CMSG_LEN
(
sizeof
(
int
));
*
(
int
*
)
CMSG_DATA
(
cmsg
)
=
fd
;
*
(
int
*
)
CMSG_DATA
(
cmsg
)
=
fd
;
}
}
if
((
tx
=
sendmsg
(
connfd
,
&
msg
,
0
))
!=
(
ssize_t
)
len
)
{
if
((
tx
=
sendmsg
(
connfd
,
&
msg
,
0
))
!=
(
ssize_t
)
len
)
{
fprintf
(
stderr
,
"tx == %zd
\n
"
,
tx
);
fprintf
(
stderr
,
"tx == %zd
\n
"
,
tx
);
return
-
1
;
return
-
1
;
}
}
return
0
;
return
0
;
}
}
int
shm_create
(
const
char
*
path
,
size_t
size
,
void
**
addr
)
int
shm_create
(
const
char
*
path
,
size_t
size
,
void
**
addr
)
{
{
int
fd
;
int
fd
;
void
*
p
;
void
*
p
;
if
((
fd
=
open
(
path
,
O_CREAT
|
O_RDWR
,
0666
))
==
-
1
)
{
if
((
fd
=
open
(
path
,
O_CREAT
|
O_RDWR
,
0666
))
==
-
1
)
{
perror
(
"util_create_shmsiszed: open failed"
);
perror
(
"util_create_shmsiszed: open failed"
);
goto
error_out
;
goto
error_out
;
}
}
if
(
ftruncate
(
fd
,
size
)
!=
0
)
{
if
(
ftruncate
(
fd
,
size
)
!=
0
)
{
perror
(
"util_create_shmsiszed: ftruncate failed"
);
perror
(
"util_create_shmsiszed: ftruncate failed"
);
goto
error_remove
;
goto
error_remove
;
}
}
if
((
p
=
mmap
(
NULL
,
size
,
PROT_READ
|
PROT_WRITE
,
if
((
p
=
mmap
(
NULL
,
size
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
|
MAP_POPULATE
,
MAP_SHARED
|
MAP_POPULATE
,
fd
,
0
))
==
(
void
*
)
-
1
)
fd
,
0
))
==
(
void
*
)
-
1
)
{
{
perror
(
"util_create_shmsiszed: mmap failed"
);
perror
(
"util_create_shmsiszed: mmap failed"
);
goto
error_remove
;
goto
error_remove
;
}
}
memset
(
p
,
0
,
size
);
memset
(
p
,
0
,
size
);
*
addr
=
p
;
*
addr
=
p
;
return
fd
;
return
fd
;
error_remove:
error_remove:
close
(
fd
);
close
(
fd
);
unlink
(
path
);
unlink
(
path
);
error_out:
error_out:
return
-
1
;
return
-
1
;
}
}
lib/simbricks/proto/network.h
View file @
d4666c97
...
@@ -38,34 +38,32 @@
...
@@ -38,34 +38,32 @@
* memory file descriptor attached.
* memory file descriptor attached.
*/
*/
struct
cosim_eth_proto_dev_intro
{
struct
cosim_eth_proto_dev_intro
{
/** flags: see COSIM_ETH_PROTO_FLAGS_DI_* */
/** flags: see COSIM_ETH_PROTO_FLAGS_DI_* */
uint64_t
flags
;
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
));
/** 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)
#define COSIM_ETH_PROTO_FLAGS_NI_SYNC (1 << 0)
/** welcome message sent by network to device */
/** welcome message sent by network to device */
struct
cosim_eth_proto_net_intro
{
struct
cosim_eth_proto_net_intro
{
/** flags: see COSIM_ETH_PROTO_FLAGS_IN_* */
/** flags: see COSIM_ETH_PROTO_FLAGS_IN_* */
uint64_t
flags
;
uint64_t
flags
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
/******************************************************************************/
/******************************************************************************/
/* Messages on in-memory device to network channel */
/* Messages on in-memory device to network channel */
...
@@ -82,36 +80,35 @@ struct cosim_eth_proto_net_intro {
...
@@ -82,36 +80,35 @@ struct cosim_eth_proto_net_intro {
#define COSIM_ETH_PROTO_D2N_MSG_SEND 0x2
#define COSIM_ETH_PROTO_D2N_MSG_SEND 0x2
struct
cosim_eth_proto_d2n_dummy
{
struct
cosim_eth_proto_d2n_dummy
{
uint8_t
pad
[
48
];
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
struct
cosim_eth_proto_d2n_sync
{
struct
cosim_eth_proto_d2n_sync
{
uint8_t
pad
[
48
];
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
struct
cosim_eth_proto_d2n_send
{
struct
cosim_eth_proto_d2n_send
{
uint16_t
len
;
uint16_t
len
;
uint8_t
port
;
uint8_t
port
;
uint8_t
pad
[
45
];
uint8_t
pad
[
45
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
uint8_t
data
[];
uint8_t
data
[];
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
union
cosim_eth_proto_d2n
{
union
cosim_eth_proto_d2n
{
struct
cosim_eth_proto_d2n_dummy
dummy
;
struct
cosim_eth_proto_d2n_dummy
dummy
;
struct
cosim_eth_proto_d2n_sync
sync
;
struct
cosim_eth_proto_d2n_sync
sync
;
struct
cosim_eth_proto_d2n_send
send
;
struct
cosim_eth_proto_d2n_send
send
;
};
};
/******************************************************************************/
/******************************************************************************/
/* Messages on in-memory network to device channel */
/* Messages on in-memory network to device channel */
...
@@ -126,33 +123,33 @@ union cosim_eth_proto_d2n {
...
@@ -126,33 +123,33 @@ union cosim_eth_proto_d2n {
#define COSIM_ETH_PROTO_N2D_MSG_RECV 0x2
#define COSIM_ETH_PROTO_N2D_MSG_RECV 0x2
struct
cosim_eth_proto_n2d_dummy
{
struct
cosim_eth_proto_n2d_dummy
{
uint8_t
pad
[
48
];
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
struct
cosim_eth_proto_n2d_sync
{
struct
cosim_eth_proto_n2d_sync
{
uint8_t
pad
[
48
];
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
struct
cosim_eth_proto_n2d_recv
{
struct
cosim_eth_proto_n2d_recv
{
uint16_t
len
;
uint16_t
len
;
uint8_t
port
;
uint8_t
port
;
uint8_t
pad
[
45
];
uint8_t
pad
[
45
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
uint8_t
data
[];
uint8_t
data
[];
};
};
union
cosim_eth_proto_n2d
{
union
cosim_eth_proto_n2d
{
struct
cosim_eth_proto_n2d_dummy
dummy
;
struct
cosim_eth_proto_n2d_dummy
dummy
;
struct
cosim_eth_proto_n2d_sync
sync
;
struct
cosim_eth_proto_n2d_sync
sync
;
struct
cosim_eth_proto_n2d_recv
recv
;
struct
cosim_eth_proto_n2d_recv
recv
;
};
};
#endif // SIMBRICKS_PROTO_NETWORK_H_
#endif // SIMBRICKS_PROTO_NETWORK_H_
lib/simbricks/proto/pcie.h
View file @
d4666c97
...
@@ -55,69 +55,67 @@
...
@@ -55,69 +55,67 @@
* memory file descriptor attached.
* memory file descriptor attached.
*/
*/
struct
cosim_pcie_proto_dev_intro
{
struct
cosim_pcie_proto_dev_intro
{
/** flags: see COSIM_PCIE_PROTO_FLAGS_DI_* */
/** flags: see COSIM_PCIE_PROTO_FLAGS_DI_* */
uint64_t
flags
;
uint64_t
flags
;
/** offset of the device-to-host queue in shared memory region */
/** offset of the device-to-host queue in shared memory region */
uint64_t
d2h_offset
;
uint64_t
d2h_offset
;
/** size of an entry in the device-to-host queue in bytes */
/** size of an entry in the device-to-host queue in bytes */
uint64_t
d2h_elen
;
uint64_t
d2h_elen
;
/** total device-to-host queue length in #entries */
/** total device-to-host queue length in #entries */
uint64_t
d2h_nentries
;
uint64_t
d2h_nentries
;
/** offset of the host-to-device queue in shared memory region */
/** offset of the host-to-device queue in shared memory region */
uint64_t
h2d_offset
;
uint64_t
h2d_offset
;
/** size of an entry in the host-to-device queue in bytes */
/** size of an entry in the host-to-device queue in bytes */
uint64_t
h2d_elen
;
uint64_t
h2d_elen
;
/** total host-to-device queue length in #entries */
/** total host-to-device queue length in #entries */
uint64_t
h2d_nentries
;
uint64_t
h2d_nentries
;
/** information for each BAR exposed by the device */
/** information for each BAR exposed by the device */
struct
{
struct
{
/** length of the bar in bytes (len = 0 indicates unused bar) */
/** length of the bar in bytes (len = 0 indicates unused bar) */
uint64_t
len
;
uint64_t
len
;
/** flags (see COSIM_PCIE_PROTO_BAR_*) */
/** flags (see COSIM_PCIE_PROTO_BAR_*) */
uint64_t
flags
;
uint64_t
flags
;
}
__attribute__
((
packed
))
bars
[
COSIM_PCIE_PROTO_NBARS
];
}
__attribute__
((
packed
))
bars
[
COSIM_PCIE_PROTO_NBARS
];
/** PCI vendor id */
/** PCI vendor id */
uint16_t
pci_vendor_id
;
uint16_t
pci_vendor_id
;
/** PCI device id */
/** PCI device id */
uint16_t
pci_device_id
;
uint16_t
pci_device_id
;
/* PCI class */
/* PCI class */
uint8_t
pci_class
;
uint8_t
pci_class
;
/* PCI subclass */
/* PCI subclass */
uint8_t
pci_subclass
;
uint8_t
pci_subclass
;
/* PCI revision */
/* PCI revision */
uint8_t
pci_revision
;
uint8_t
pci_revision
;
/* PCI number of MSI vectors */
/* PCI number of MSI vectors */
uint8_t
pci_msi_nvecs
;
uint8_t
pci_msi_nvecs
;
/* PCI number of MSI-X vectors */
/* PCI number of MSI-X vectors */
uint16_t
pci_msix_nvecs
;
uint16_t
pci_msix_nvecs
;
/* BAR number for MSI-X table */
/* BAR number for MSI-X table */
uint8_t
pci_msix_table_bar
;
uint8_t
pci_msix_table_bar
;
/* BAR number for MSI-X PBA */
/* BAR number for MSI-X PBA */
uint8_t
pci_msix_pba_bar
;
uint8_t
pci_msix_pba_bar
;
/* Offset for MSI-X table */
/* Offset for MSI-X table */
uint32_t
pci_msix_table_offset
;
uint32_t
pci_msix_table_offset
;
/* Offset for MSI-X PBA */
/* Offset for MSI-X PBA */
uint32_t
pci_msix_pba_offset
;
uint32_t
pci_msix_pba_offset
;
/* MSI-X capability offset */
/* MSI-X capability offset */
uint16_t
psi_msix_cap_offset
;
uint16_t
psi_msix_cap_offset
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
#define COSIM_PCIE_PROTO_FLAGS_HI_SYNC (1 << 0)
#define COSIM_PCIE_PROTO_FLAGS_HI_SYNC (1 << 0)
/** welcome message sent by host to device */
/** welcome message sent by host to device */
struct
cosim_pcie_proto_host_intro
{
struct
cosim_pcie_proto_host_intro
{
/** flags: see COSIM_PCIE_PROTO_FLAGS_HI_* */
/** flags: see COSIM_PCIE_PROTO_FLAGS_HI_* */
uint64_t
flags
;
uint64_t
flags
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
/******************************************************************************/
/******************************************************************************/
/* Messages on in-memory device to host channel */
/* Messages on in-memory device to host channel */
...
@@ -138,41 +136,41 @@ struct cosim_pcie_proto_host_intro {
...
@@ -138,41 +136,41 @@ struct cosim_pcie_proto_host_intro {
#define COSIM_PCIE_PROTO_D2H_MSG_WRITECOMP 0x6
#define COSIM_PCIE_PROTO_D2H_MSG_WRITECOMP 0x6
struct
cosim_pcie_proto_d2h_dummy
{
struct
cosim_pcie_proto_d2h_dummy
{
uint8_t
pad
[
48
];
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_dummy
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_dummy
);
struct
cosim_pcie_proto_d2h_sync
{
struct
cosim_pcie_proto_d2h_sync
{
uint8_t
pad
[
48
];
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_sync
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_sync
);
struct
cosim_pcie_proto_d2h_read
{
struct
cosim_pcie_proto_d2h_read
{
uint64_t
req_id
;
uint64_t
req_id
;
uint64_t
offset
;
uint64_t
offset
;
uint16_t
len
;
uint16_t
len
;
uint8_t
pad
[
30
];
uint8_t
pad
[
30
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_read
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_read
);
struct
cosim_pcie_proto_d2h_write
{
struct
cosim_pcie_proto_d2h_write
{
uint64_t
req_id
;
uint64_t
req_id
;
uint64_t
offset
;
uint64_t
offset
;
uint16_t
len
;
uint16_t
len
;
uint8_t
pad
[
30
];
uint8_t
pad
[
30
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
uint8_t
data
[];
uint8_t
data
[];
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_write
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_write
);
...
@@ -182,46 +180,45 @@ 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
#define COSIM_PCIE_PROTO_INT_MSIX 3
struct
cosim_pcie_proto_d2h_interrupt
{
struct
cosim_pcie_proto_d2h_interrupt
{
uint16_t
vector
;
uint16_t
vector
;
uint8_t
inttype
;
uint8_t
inttype
;
uint8_t
pad
[
45
];
uint8_t
pad
[
45
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_interrupt
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_interrupt
);
struct
cosim_pcie_proto_d2h_readcomp
{
struct
cosim_pcie_proto_d2h_readcomp
{
uint64_t
req_id
;
uint64_t
req_id
;
uint8_t
pad
[
40
];
uint8_t
pad
[
40
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
uint8_t
data
[];
uint8_t
data
[];
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_readcomp
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_readcomp
);
struct
cosim_pcie_proto_d2h_writecomp
{
struct
cosim_pcie_proto_d2h_writecomp
{
uint64_t
req_id
;
uint64_t
req_id
;
uint8_t
pad
[
40
];
uint8_t
pad
[
40
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_writecomp
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_d2h_writecomp
);
union
cosim_pcie_proto_d2h
{
union
cosim_pcie_proto_d2h
{
struct
cosim_pcie_proto_d2h_dummy
dummy
;
struct
cosim_pcie_proto_d2h_dummy
dummy
;
struct
cosim_pcie_proto_d2h_sync
sync
;
struct
cosim_pcie_proto_d2h_sync
sync
;
struct
cosim_pcie_proto_d2h_read
read
;
struct
cosim_pcie_proto_d2h_read
read
;
struct
cosim_pcie_proto_d2h_write
write
;
struct
cosim_pcie_proto_d2h_write
write
;
struct
cosim_pcie_proto_d2h_interrupt
interrupt
;
struct
cosim_pcie_proto_d2h_interrupt
interrupt
;
struct
cosim_pcie_proto_d2h_readcomp
readcomp
;
struct
cosim_pcie_proto_d2h_readcomp
readcomp
;
struct
cosim_pcie_proto_d2h_writecomp
writecomp
;
struct
cosim_pcie_proto_d2h_writecomp
writecomp
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
union
cosim_pcie_proto_d2h
);
COSIM_PCI_MSG_SZCHECK
(
union
cosim_pcie_proto_d2h
);
/******************************************************************************/
/******************************************************************************/
/* Messages on in-memory host to device channel */
/* Messages on in-memory host to device channel */
...
@@ -240,62 +237,62 @@ COSIM_PCI_MSG_SZCHECK(union cosim_pcie_proto_d2h);
...
@@ -240,62 +237,62 @@ COSIM_PCI_MSG_SZCHECK(union cosim_pcie_proto_d2h);
#define COSIM_PCIE_PROTO_H2D_MSG_DEVCTRL 0x7
#define COSIM_PCIE_PROTO_H2D_MSG_DEVCTRL 0x7
struct
cosim_pcie_proto_h2d_dummy
{
struct
cosim_pcie_proto_h2d_dummy
{
uint8_t
pad
[
48
];
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_dummy
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_dummy
);
struct
cosim_pcie_proto_h2d_sync
{
struct
cosim_pcie_proto_h2d_sync
{
uint8_t
pad
[
48
];
uint8_t
pad
[
48
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_sync
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_sync
);
struct
cosim_pcie_proto_h2d_read
{
struct
cosim_pcie_proto_h2d_read
{
uint64_t
req_id
;
uint64_t
req_id
;
uint64_t
offset
;
uint64_t
offset
;
uint16_t
len
;
uint16_t
len
;
uint8_t
bar
;
uint8_t
bar
;
uint8_t
pad
[
29
];
uint8_t
pad
[
29
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_read
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_read
);
struct
cosim_pcie_proto_h2d_write
{
struct
cosim_pcie_proto_h2d_write
{
uint64_t
req_id
;
uint64_t
req_id
;
uint64_t
offset
;
uint64_t
offset
;
uint16_t
len
;
uint16_t
len
;
uint8_t
bar
;
uint8_t
bar
;
uint8_t
pad
[
29
];
uint8_t
pad
[
29
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
uint8_t
data
[];
uint8_t
data
[];
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_write
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_write
);
struct
cosim_pcie_proto_h2d_readcomp
{
struct
cosim_pcie_proto_h2d_readcomp
{
uint64_t
req_id
;
uint64_t
req_id
;
uint8_t
pad
[
40
];
uint8_t
pad
[
40
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
uint8_t
data
[];
uint8_t
data
[];
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_readcomp
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_readcomp
);
struct
cosim_pcie_proto_h2d_writecomp
{
struct
cosim_pcie_proto_h2d_writecomp
{
uint64_t
req_id
;
uint64_t
req_id
;
uint8_t
pad
[
40
];
uint8_t
pad
[
40
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_writecomp
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_writecomp
);
...
@@ -303,22 +300,22 @@ 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_MSI_EN (1 << 1)
#define COSIM_PCIE_PROTO_CTRL_MSIX_EN (1 << 2)
#define COSIM_PCIE_PROTO_CTRL_MSIX_EN (1 << 2)
struct
cosim_pcie_proto_h2d_devctrl
{
struct
cosim_pcie_proto_h2d_devctrl
{
uint64_t
flags
;
uint64_t
flags
;
uint8_t
pad
[
40
];
uint8_t
pad
[
40
];
uint64_t
timestamp
;
uint64_t
timestamp
;
uint8_t
pad_
[
7
];
uint8_t
pad_
[
7
];
uint8_t
own_type
;
uint8_t
own_type
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_devctrl
);
COSIM_PCI_MSG_SZCHECK
(
struct
cosim_pcie_proto_h2d_devctrl
);
union
cosim_pcie_proto_h2d
{
union
cosim_pcie_proto_h2d
{
struct
cosim_pcie_proto_h2d_dummy
dummy
;
struct
cosim_pcie_proto_h2d_dummy
dummy
;
struct
cosim_pcie_proto_h2d_sync
sync
;
struct
cosim_pcie_proto_h2d_sync
sync
;
struct
cosim_pcie_proto_h2d_read
read
;
struct
cosim_pcie_proto_h2d_read
read
;
struct
cosim_pcie_proto_h2d_write
write
;
struct
cosim_pcie_proto_h2d_write
write
;
struct
cosim_pcie_proto_h2d_readcomp
readcomp
;
struct
cosim_pcie_proto_h2d_readcomp
readcomp
;
struct
cosim_pcie_proto_h2d_writecomp
writecomp
;
struct
cosim_pcie_proto_h2d_writecomp
writecomp
;
struct
cosim_pcie_proto_h2d_devctrl
devctrl
;
struct
cosim_pcie_proto_h2d_devctrl
devctrl
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
COSIM_PCI_MSG_SZCHECK
(
union
cosim_pcie_proto_h2d
);
COSIM_PCI_MSG_SZCHECK
(
union
cosim_pcie_proto_h2d
);
...
...
sims/net/switch/net_switch.cc
View file @
d4666c97
...
@@ -22,15 +22,16 @@
...
@@ -22,15 +22,16 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include <unistd.h>
#include <cassert>
#include <climits>
#include <csignal>
#include <cstdio>
#include <cstdio>
#include <cstdlib>
#include <cstdlib>
#include <csignal>
#include <climits>
#include <cstring>
#include <cstring>
#include <unistd.h>
#include <vector>
#include <unordered_map>
#include <unordered_map>
#include <
cassert
>
#include <
vector
>
extern
"C"
{
extern
"C"
{
#include <simbricks/netif/netsim.h>
#include <simbricks/netif/netsim.h>
...
@@ -41,31 +42,30 @@ static uint64_t eth_latency = (500 * 1000ULL); // 500ns
...
@@ -41,31 +42,30 @@ static uint64_t eth_latency = (500 * 1000ULL); // 500ns
/* MAC address type */
/* MAC address type */
struct
MAC
{
struct
MAC
{
const
volatile
uint8_t
*
data
;
const
volatile
uint8_t
*
data
;
MAC
(
const
volatile
uint8_t
*
data
)
MAC
(
const
volatile
uint8_t
*
data
)
:
data
(
data
)
{
:
data
(
data
)
{
}
}
bool
operator
==
(
const
MAC
&
other
)
const
{
bool
operator
==
(
const
MAC
&
other
)
const
{
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
if
(
data
[
i
]
!=
other
.
data
[
i
])
{
if
(
data
[
i
]
!=
other
.
data
[
i
])
{
return
false
;
return
false
;
}
}
}
return
true
;
}
}
return
true
;
}
};
};
namespace
std
{
namespace
std
{
template
<
>
template
<
>
struct
hash
<
MAC
>
struct
hash
<
MAC
>
{
{
size_t
operator
()(
const
MAC
&
m
)
const
{
size_t
operator
()(
const
MAC
&
m
)
const
{
size_t
res
=
0
;
size_t
res
=
0
;
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
res
=
(
res
<<
4
)
|
(
res
^
m
.
data
[
i
]);
res
=
(
res
<<
4
)
|
(
res
^
m
.
data
[
i
]);
}
}
return
res
;
return
res
;
}
}
};
};
}
// namespace std
}
// namespace std
...
@@ -77,149 +77,145 @@ static const MAC bcast_addr(bcast);
...
@@ -77,149 +77,145 @@ static const MAC bcast_addr(bcast);
static
std
::
vector
<
struct
netsim_interface
>
nsifs
;
static
std
::
vector
<
struct
netsim_interface
>
nsifs
;
static
std
::
unordered_map
<
MAC
,
int
>
mac_table
;
static
std
::
unordered_map
<
MAC
,
int
>
mac_table
;
static
void
sigint_handler
(
int
dummy
)
static
void
sigint_handler
(
int
dummy
)
{
{
exiting
=
1
;
exiting
=
1
;
}
}
static
void
forward_pkt
(
volatile
struct
cosim_eth_proto_d2n_send
*
tx
,
int
port
)
static
void
forward_pkt
(
volatile
struct
cosim_eth_proto_d2n_send
*
tx
,
{
int
port
)
{
volatile
union
cosim_eth_proto_n2d
*
msg_to
;
volatile
union
cosim_eth_proto_n2d
*
msg_to
;
msg_to
=
netsim_n2d_alloc
(
&
nsifs
[
port
],
cur_ts
,
eth_latency
);
msg_to
=
netsim_n2d_alloc
(
&
nsifs
[
port
],
cur_ts
,
eth_latency
);
if
(
msg_to
!=
NULL
)
{
if
(
msg_to
!=
NULL
)
{
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
rx
=
&
msg_to
->
recv
;
rx
=
&
msg_to
->
recv
;
rx
->
len
=
tx
->
len
;
rx
->
len
=
tx
->
len
;
rx
->
port
=
0
;
rx
->
port
=
0
;
memcpy
((
void
*
)
rx
->
data
,
(
void
*
)
tx
->
data
,
tx
->
len
);
memcpy
((
void
*
)
rx
->
data
,
(
void
*
)
tx
->
data
,
tx
->
len
);
// WMB();
// WMB();
rx
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_RECV
|
rx
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_RECV
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
COSIM_ETH_PROTO_N2D_OWN_DEV
;
}
else
{
}
else
{
fprintf
(
stderr
,
"forward_pkt: dropping packet
\n
"
);
fprintf
(
stderr
,
"forward_pkt: dropping packet
\n
"
);
}
}
}
}
static
void
switch_pkt
(
struct
netsim_interface
*
nsif
,
int
iport
)
static
void
switch_pkt
(
struct
netsim_interface
*
nsif
,
int
iport
)
{
{
volatile
union
cosim_eth_proto_d2n
*
msg_from
=
netsim_d2n_poll
(
nsif
,
cur_ts
);
volatile
union
cosim_eth_proto_d2n
*
msg_from
=
netsim_d2n_poll
(
nsif
,
if
(
msg_from
==
NULL
)
{
cur_ts
);
return
;
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
;
}
}
// L2 forwarding
uint8_t
type
=
msg_from
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
;
if
(
mac_table
.
count
(
dst
)
>
0
)
{
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SEND
)
{
int
eport
=
mac_table
.
at
(
dst
);
volatile
struct
cosim_eth_proto_d2n_send
*
tx
;
forward_pkt
(
tx
,
eport
);
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
)
{
}
else
{
}
else
{
fprintf
(
stderr
,
"switch_pkt: unsupported type=%u
\n
"
,
type
);
// Broadcast
abort
();
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
main
(
int
argc
,
char
*
argv
[])
{
{
int
c
;
int
c
;
int
bad_option
=
0
;
int
bad_option
=
0
;
int
sync_mode
=
SYNC_MODES
;
int
sync_mode
=
SYNC_MODES
;
// Parse command line argument
// Parse command line argument
while
((
c
=
getopt
(
argc
,
argv
,
"s:S:E:m:"
))
!=
-
1
&&
!
bad_option
)
{
while
((
c
=
getopt
(
argc
,
argv
,
"s:S:E:m:"
))
!=
-
1
&&
!
bad_option
)
{
switch
(
c
)
{
switch
(
c
)
{
case
's'
:
{
case
's'
:
{
struct
netsim_interface
nsif
;
struct
netsim_interface
nsif
;
int
sync
=
1
;
int
sync
=
1
;
if
(
netsim_init
(
&
nsif
,
optarg
,
&
sync
)
!=
0
)
{
if
(
netsim_init
(
&
nsif
,
optarg
,
&
sync
)
!=
0
)
{
fprintf
(
stderr
,
"connecting to %s failed
\n
"
,
optarg
);
fprintf
(
stderr
,
"connecting to %s failed
\n
"
,
optarg
);
return
EXIT_FAILURE
;
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
;
}
}
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] "
if
(
nsifs
.
empty
()
||
bad_option
)
{
"-s SOCKET-A [-s SOCKET-B ...]
\n
"
);
fprintf
(
stderr
,
return
EXIT_FAILURE
;
"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
();
}
}
}
netsim_advance_epoch
(
cur_ts
,
sync_period
,
sync_mode
);
signal
(
SIGINT
,
sigint_handler
);
signal
(
SIGTERM
,
sigint_handler
);
// Switch packets
uint64_t
min_ts
;
printf
(
"start polling
\n
"
);
do
{
while
(
!
exiting
)
{
min_ts
=
ULLONG_MAX
;
// Sync all interfaces
for
(
int
port
=
0
;
port
<
nsifs
.
size
();
port
++
)
{
for
(
auto
&
nsif
:
nsifs
)
{
auto
&
nsif
=
nsifs
.
at
(
port
);
if
(
netsim_n2d_sync
(
&
nsif
,
cur_ts
,
eth_latency
,
switch_pkt
(
&
nsif
,
port
);
sync_period
,
sync_mode
)
!=
0
)
{
if
(
nsif
.
sync
)
{
fprintf
(
stderr
,
"netsim_n2d_sync failed
\n
"
);
uint64_t
ts
=
netsim_d2n_timestamp
(
&
nsif
);
abort
();
min_ts
=
ts
<
min_ts
?
ts
:
min_ts
;
}
}
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
);
}
}
}
}
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 @@
...
@@ -23,15 +23,15 @@
*/
*/
#include <fcntl.h>
#include <fcntl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <pthread.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mman.h>
#include <unistd.h>
#include <unistd.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <simbricks/netif/netsim.h>
#include <simbricks/netif/netsim.h>
...
@@ -40,119 +40,113 @@
...
@@ -40,119 +40,113 @@
static
struct
netsim_interface
nsif
;
static
struct
netsim_interface
nsif
;
static
int
tap_fd
;
static
int
tap_fd
;
static
int
tap_open
(
const
char
*
name
)
static
int
tap_open
(
const
char
*
name
)
{
{
struct
ifreq
ifr
;
struct
ifreq
ifr
;
int
fd
;
int
fd
;
if
((
fd
=
open
(
"/dev/net/tun"
,
O_RDWR
))
<
0
)
{
if
((
fd
=
open
(
"/dev/net/tun"
,
O_RDWR
))
<
0
)
{
perror
(
"tap_open: open failed"
);
perror
(
"tap_open: open failed"
);
return
-
1
;
return
-
1
;
}
}
memset
(
&
ifr
,
0
,
sizeof
(
ifr
));
memset
(
&
ifr
,
0
,
sizeof
(
ifr
));
ifr
.
ifr_flags
=
IFF_TAP
|
IFF_NO_PI
;
ifr
.
ifr_flags
=
IFF_TAP
|
IFF_NO_PI
;
strncpy
(
ifr
.
ifr_name
,
name
,
IFNAMSIZ
);
strncpy
(
ifr
.
ifr_name
,
name
,
IFNAMSIZ
);
if
(
ioctl
(
fd
,
TUNSETIFF
,
&
ifr
)
!=
0
)
{
if
(
ioctl
(
fd
,
TUNSETIFF
,
&
ifr
)
!=
0
)
{
perror
(
"tap_open: ioctl failed"
);
perror
(
"tap_open: ioctl failed"
);
close
(
fd
);
close
(
fd
);
return
-
1
;
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
#ifdef DEBUG_PKTMETA
printf
(
"sent packet: len=%u
\n
"
,
s
->
len
);
printf
(
"sent packet: len=%u
\n
"
,
s
->
len
);
#endif
#endif
if
(
write
(
tap_fd
,
(
void
*
)
s
->
data
,
s
->
len
)
!=
(
ssize_t
)
s
->
len
)
{
if
(
write
(
tap_fd
,
(
void
*
)
s
->
data
,
s
->
len
)
!=
(
ssize_t
)
s
->
len
)
{
perror
(
"d2n_send: send failed"
);
perror
(
"d2n_send: send failed"
);
}
}
}
}
static
void
poll_d2n
(
void
)
static
void
poll_d2n
(
void
)
{
{
volatile
union
cosim_eth_proto_d2n
*
msg
=
netsim_d2n_poll
(
&
nsif
,
0
);
volatile
union
cosim_eth_proto_d2n
*
msg
=
netsim_d2n_poll
(
&
nsif
,
0
);
uint8_t
type
;
uint8_t
type
;
/* message not ready */
/* message not ready */
if
(
msg
==
NULL
)
if
(
msg
==
NULL
)
return
;
return
;
type
=
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
;
type
=
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
;
switch
(
type
)
{
switch
(
type
)
{
case
COSIM_ETH_PROTO_D2N_MSG_SEND
:
case
COSIM_ETH_PROTO_D2N_MSG_SEND
:
d2n_send
(
&
msg
->
send
);
d2n_send
(
&
msg
->
send
);
break
;
break
;
default:
default:
fprintf
(
stderr
,
"poll_d2n: unsupported type=%u
\n
"
,
type
);
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
)
static
void
*
rx_handler
(
void
*
arg
)
{
{
volatile
union
cosim_eth_proto_n2d
*
msg
;
volatile
union
cosim_eth_proto_n2d
*
msg
;
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
ssize_t
len
;
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
// WMB();
while
(
1
)
{
rx
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_RECV
|
msg
=
netsim_n2d_alloc
(
&
nsif
,
0
,
0
);
COSIM_ETH_PROTO_N2D_OWN_DEV
;
if
(
msg
==
NULL
)
{
}
fprintf
(
stderr
,
"coudl not allocate message for rx
\n
"
);
}
abort
();
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
;
}
}
rx
=
&
msg
->
recv
;
sync
=
0
;
len
=
read
(
tap_fd
,
(
void
*
)
rx
->
data
,
nsif
.
n2d_elen
-
sizeof
(
*
msg
));
if
(
netsim_init
(
&
nsif
,
argv
[
2
],
&
sync
)
!=
0
)
{
if
(
len
<=
0
)
{
close
(
tap_fd
);
perror
(
"rx handler: read failed"
);
return
-
1
;
}
}
rx
->
len
=
len
;
rx
->
port
=
0
;
#ifdef DEBUG_PKTMETA
printf
(
"received packet: len=%u
\n
"
,
rx
->
len
);
#endif
pthread_t
worker
;
// WMB()
;
if
(
pthread_create
(
&
worker
,
NULL
,
rx_handler
,
NULL
)
!=
0
)
{
rx
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_RECV
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
return
EXIT_FAILURE
;
}
}
}
printf
(
"start polling
\n
"
);
int
main
(
int
argc
,
char
*
argv
[])
{
while
(
1
)
{
int
sync
;
poll_d2n
();
}
if
(
argc
!=
3
)
{
return
0
;
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 @@
...
@@ -22,19 +22,19 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include <assert.h>
#include <fcntl.h>
#include <fcntl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <pcap/pcap.h>
#include <pthread.h>
#include <pthread.h>
#include <s
tdlib
.h>
#include <s
ignal
.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mman.h>
#include <unistd.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>
#include <simbricks/netif/netsim.h>
...
@@ -44,147 +44,141 @@ static uint64_t cur_ts;
...
@@ -44,147 +44,141 @@ static uint64_t cur_ts;
static
int
exiting
=
0
;
static
int
exiting
=
0
;
static
pcap_dumper_t
*
dumpfile
=
NULL
;
static
pcap_dumper_t
*
dumpfile
=
NULL
;
static
void
sigint_handler
(
int
dummy
)
static
void
sigint_handler
(
int
dummy
)
{
{
exiting
=
1
;
exiting
=
1
;
}
}
static
void
sigusr1_handler
(
int
dummy
)
static
void
sigusr1_handler
(
int
dummy
)
{
{
fprintf
(
stderr
,
"main_time = %lu
\n
"
,
cur_ts
);
fprintf
(
stderr
,
"main_time = %lu
\n
"
,
cur_ts
);
}
}
static
void
move_pkt
(
struct
netsim_interface
*
from
,
struct
netsim_interface
*
to
)
static
void
move_pkt
(
struct
netsim_interface
*
from
,
{
struct
netsim_interface
*
to
)
{
volatile
union
cosim_eth_proto_d2n
*
msg_from
=
volatile
union
cosim_eth_proto_d2n
*
msg_from
=
netsim_d2n_poll
(
from
,
cur_ts
);
netsim_d2n_poll
(
from
,
cur_ts
);
volatile
union
cosim_eth_proto_n2d
*
msg_to
;
volatile
union
cosim_eth_proto_n2d
*
msg_to
;
volatile
struct
cosim_eth_proto_d2n_send
*
tx
;
volatile
struct
cosim_eth_proto_d2n_send
*
tx
;
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
volatile
struct
cosim_eth_proto_n2d_recv
*
rx
;
struct
pcap_pkthdr
ph
;
struct
pcap_pkthdr
ph
;
uint8_t
type
;
uint8_t
type
;
if
(
msg_from
==
NULL
)
if
(
msg_from
==
NULL
)
return
;
return
;
type
=
msg_from
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
;
type
=
msg_from
->
dummy
.
own_type
&
COSIM_ETH_PROTO_D2N_MSG_MASK
;
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SEND
)
{
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SEND
)
{
tx
=
&
msg_from
->
send
;
tx
=
&
msg_from
->
send
;
// log to pcap file if initialized
// log to pcap file if initialized
if
(
dumpfile
)
{
if
(
dumpfile
)
{
memset
(
&
ph
,
0
,
sizeof
(
ph
));
memset
(
&
ph
,
0
,
sizeof
(
ph
));
ph
.
ts
.
tv_sec
=
cur_ts
/
1000000000000ULL
;
ph
.
ts
.
tv_sec
=
cur_ts
/
1000000000000ULL
;
ph
.
ts
.
tv_usec
=
(
cur_ts
%
1000000000000ULL
)
/
1000ULL
;
ph
.
ts
.
tv_usec
=
(
cur_ts
%
1000000000000ULL
)
/
1000ULL
;
ph
.
caplen
=
tx
->
len
;
ph
.
caplen
=
tx
->
len
;
ph
.
len
=
tx
->
len
;
ph
.
len
=
tx
->
len
;
pcap_dump
((
unsigned
char
*
)
dumpfile
,
&
ph
,
(
unsigned
char
*
)
tx
->
data
);
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
();
}
}
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
[])
// WMB();
{
rx
->
own_type
=
COSIM_ETH_PROTO_N2D_MSG_RECV
|
COSIM_ETH_PROTO_N2D_OWN_DEV
;
struct
netsim_interface
nsif_a
,
nsif_b
;
}
else
{
uint64_t
ts_a
,
ts_b
;
fprintf
(
stderr
,
"move_pkt: dropping packet
\n
"
);
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
;
}
}
}
else
if
(
type
==
COSIM_ETH_PROTO_D2N_MSG_SYNC
)
{
}
else
{
fprintf
(
stderr
,
"move_pkt: unsupported type=%u
\n
"
,
type
);
abort
();
}
signal
(
SIGINT
,
sigint_handler
);
netsim_d2n_done
(
from
,
msg_from
);
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
;
}
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
);
dumpfile
=
pcap_dump_open
(
pc
,
argv
[
6
]);
}
sync_a
=
sync_b
=
1
;
if
(
netsim_init
(
&
nsif_a
,
argv
[
1
],
&
sync_a
)
!=
0
)
{
assert
(
sync_mode
==
SYNC_MODES
||
sync_mode
==
SYNC_BARRIER
);
return
-
1
;
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
)
{
if
(
netsim_n2d_sync
(
&
nsif_b
,
cur_ts
,
eth_latency
,
sync_period
,
sync_mode
)
!=
return
-
1
;
0
)
{
fprintf
(
stderr
,
"netsim_n2d_sync(nsif_a) failed
\n
"
);
abort
();
}
}
netsim_advance_epoch
(
cur_ts
,
sync_period
,
sync_mode
);
printf
(
"start polling
\n
"
);
while
(
!
exiting
)
{
do
{
if
(
netsim_n2d_sync
(
&
nsif_a
,
cur_ts
,
eth_latency
,
sync_period
,
move_pkt
(
&
nsif_a
,
&
nsif_b
);
sync_mode
)
!=
0
)
{
move_pkt
(
&
nsif_b
,
&
nsif_a
);
fprintf
(
stderr
,
"netsim_n2d_sync(nsif_a) failed
\n
"
);
ts_a
=
netsim_d2n_timestamp
(
&
nsif_a
);
abort
();
ts_b
=
netsim_d2n_timestamp
(
&
nsif_b
);
}
}
while
(
!
exiting
&&
if
(
netsim_n2d_sync
(
&
nsif_b
,
cur_ts
,
eth_latency
,
sync_period
,
((
sync_a
&&
ts_a
<=
cur_ts
)
||
(
sync_b
&&
ts_b
<=
cur_ts
)));
sync_mode
)
!=
0
)
{
fprintf
(
stderr
,
"netsim_n2d_sync(nsif_a) failed
\n
"
);
if
(
sync_a
&&
sync_b
)
abort
();
cur_ts
=
netsim_advance_time
(
ts_a
<=
ts_b
?
ts_a
:
ts_b
,
sync_period
,
}
sync_mode
);
netsim_advance_epoch
(
cur_ts
,
sync_period
,
sync_mode
);
else
if
(
sync_a
)
cur_ts
=
netsim_advance_time
(
ts_a
,
sync_period
,
sync_mode
);
do
{
else
if
(
sync_b
)
move_pkt
(
&
nsif_a
,
&
nsif_b
);
cur_ts
=
netsim_advance_time
(
ts_b
,
sync_period
,
sync_mode
);
move_pkt
(
&
nsif_b
,
&
nsif_a
);
}
ts_a
=
netsim_d2n_timestamp
(
&
nsif_a
);
ts_b
=
netsim_d2n_timestamp
(
&
nsif_b
);
if
(
dumpfile
)
}
while
(
!
exiting
&&
pcap_dump_close
(
dumpfile
);
((
sync_a
&&
ts_a
<=
cur_ts
)
||
return
0
;
(
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 @@
...
@@ -26,8 +26,8 @@
#define COORD_H_
#define COORD_H_
#include <deque>
#include <deque>
#include <map>
#include <iostream>
#include <iostream>
#include <map>
#include "sims/nic/corundum/debug.h"
#include "sims/nic/corundum/debug.h"
...
@@ -39,116 +39,107 @@ void pci_msi_issue(uint8_t vec);
...
@@ -39,116 +39,107 @@ void pci_msi_issue(uint8_t vec);
void
pci_rwcomp_issue
(
MMIOOp
*
op
);
void
pci_rwcomp_issue
(
MMIOOp
*
op
);
class
PCICoordinator
{
class
PCICoordinator
{
protected:
protected:
struct
PCIOp
{
struct
PCIOp
{
union
{
union
{
DMAOp
*
dma_op
;
DMAOp
*
dma_op
;
MMIOOp
*
mmio_op
;
MMIOOp
*
mmio_op
;
uint32_t
msi_vec
;
uint32_t
msi_vec
;
};
};
enum
{
enum
{
OP_DMA
,
OP_DMA
,
OP_MSI
,
OP_MSI
,
OP_RWCOMP
,
OP_RWCOMP
,
}
type
;
}
type
;
bool
ready
;
bool
ready
;
};
};
std
::
deque
<
PCIOp
*>
queue
;
std
::
deque
<
PCIOp
*>
queue
;
std
::
map
<
DMAOp
*
,
PCIOp
*>
dmamap
;
std
::
map
<
DMAOp
*
,
PCIOp
*>
dmamap
;
void
process
()
void
process
()
{
{
PCIOp
*
op
;
PCIOp
*
op
;
while
(
!
queue
.
empty
())
{
while
(
!
queue
.
empty
())
{
op
=
queue
.
front
();
op
=
queue
.
front
();
if
(
!
op
->
ready
)
if
(
!
op
->
ready
)
break
;
break
;
queue
.
pop_front
();
queue
.
pop_front
();
if
(
op
->
type
==
PCIOp
::
OP_MSI
)
{
if
(
op
->
type
==
PCIOp
::
OP_MSI
)
{
#ifdef COORD_DEBUG
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" issuing msi "
<<
op
->
msi_vec
<<
std
::
cout
<<
main_time
<<
" issuing msi "
<<
op
->
msi_vec
<<
std
::
endl
;
std
::
endl
;
#endif
#endif
pci_msi_issue
(
op
->
msi_vec
);
pci_msi_issue
(
op
->
msi_vec
);
}
else
if
(
op
->
type
==
PCIOp
::
OP_DMA
)
{
}
else
if
(
op
->
type
==
PCIOp
::
OP_DMA
)
{
#ifdef COORD_DEBUG
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" issuing dma "
<<
op
->
dma_op
<<
std
::
cout
<<
main_time
<<
" issuing dma "
<<
op
->
dma_op
<<
std
::
endl
;
std
::
endl
;
#endif
#endif
pci_dma_issue
(
op
->
dma_op
);
pci_dma_issue
(
op
->
dma_op
);
dmamap
.
erase
(
op
->
dma_op
);
dmamap
.
erase
(
op
->
dma_op
);
}
else
if
(
op
->
type
==
PCIOp
::
OP_RWCOMP
)
{
}
else
if
(
op
->
type
==
PCIOp
::
OP_RWCOMP
)
{
#ifdef COORD_DEBUG
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" issuing mmio "
<<
op
->
mmio_op
<<
std
::
cout
<<
main_time
<<
" issuing mmio "
<<
op
->
mmio_op
<<
std
::
endl
;
std
::
endl
;
#endif
#endif
pci_rwcomp_issue
(
op
->
mmio_op
);
pci_rwcomp_issue
(
op
->
mmio_op
);
}
else
{
}
else
{
throw
"unknown type"
;
throw
"unknown type"
;
}
}
delete
op
;
delete
op
;
}
}
}
}
public:
public:
void
dma_register
(
DMAOp
*
dma_op
,
bool
ready
)
void
dma_register
(
DMAOp
*
dma_op
,
bool
ready
)
{
{
#ifdef COORD_DEBUG
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" registering dma op "
<<
dma_op
<<
" "
std
::
cout
<<
main_time
<<
" registering dma op "
<<
dma_op
<<
" "
<<
ready
<<
ready
<<
std
::
endl
;
<<
std
::
endl
;
#endif
#endif
PCIOp
*
op
=
new
PCIOp
;
PCIOp
*
op
=
new
PCIOp
;
op
->
dma_op
=
dma_op
;
op
->
dma_op
=
dma_op
;
op
->
type
=
PCIOp
::
OP_DMA
;
op
->
type
=
PCIOp
::
OP_DMA
;
op
->
ready
=
ready
;
op
->
ready
=
ready
;
queue
.
push_back
(
op
);
queue
.
push_back
(
op
);
dmamap
[
dma_op
]
=
op
;
dmamap
[
dma_op
]
=
op
;
process
();
process
();
}
}
void
dma_mark_ready
(
DMAOp
*
op
)
void
dma_mark_ready
(
DMAOp
*
op
)
{
{
#ifdef COORD_DEBUG
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" readying dma op "
<<
op
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" readying dma op "
<<
op
<<
std
::
endl
;
#endif
#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
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" enqueuing MSI "
<<
vec
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" enqueuing MSI "
<<
vec
<<
std
::
endl
;
#endif
#endif
PCIOp
*
op
=
new
PCIOp
;
PCIOp
*
op
=
new
PCIOp
;
op
->
msi_vec
=
vec
;
op
->
msi_vec
=
vec
;
op
->
type
=
PCIOp
::
OP_MSI
;
op
->
type
=
PCIOp
::
OP_MSI
;
op
->
ready
=
true
;
op
->
ready
=
true
;
queue
.
push_back
(
op
);
queue
.
push_back
(
op
);
process
();
process
();
}
}
void
mmio_comp_enqueue
(
MMIOOp
*
mmio_op
)
void
mmio_comp_enqueue
(
MMIOOp
*
mmio_op
)
{
{
#ifdef COORD_DEBUG
#ifdef COORD_DEBUG
std
::
cout
<<
main_time
<<
" enqueuing MMIO comp "
<<
mmio_op
<<
std
::
cout
<<
main_time
<<
" enqueuing MMIO comp "
<<
mmio_op
<<
std
::
endl
;
std
::
endl
;
#endif
#endif
PCIOp
*
op
=
new
PCIOp
;
PCIOp
*
op
=
new
PCIOp
;
op
->
mmio_op
=
mmio_op
;
op
->
mmio_op
=
mmio_op
;
op
->
type
=
PCIOp
::
OP_RWCOMP
;
op
->
type
=
PCIOp
::
OP_RWCOMP
;
op
->
ready
=
true
;
op
->
ready
=
true
;
queue
.
push_back
(
op
);
queue
.
push_back
(
op
);
process
();
process
();
}
}
};
};
#endif // COORD_H_
#endif // COORD_H_
sims/nic/corundum/corundum_verilator.cc
View file @
d4666c97
...
@@ -22,27 +22,26 @@
...
@@ -22,27 +22,26 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include <iostream>
#include <deque>
#include <set>
#include <signal.h>
#include <signal.h>
#include <verilated.h>
#include <verilated.h>
#include <deque>
#include <iostream>
#include <set>
#ifdef TRACE_ENABLED
#ifdef TRACE_ENABLED
#include <verilated_vcd_c.h>
#include <verilated_vcd_c.h>
#endif
#endif
extern
"C"
{
extern
"C"
{
#include <simbricks/nicif/nicsim.h>
#include <simbricks/nicif/nicsim.h>
}
}
#include "sims/nic/corundum/obj_dir/Vinterface.h"
#include "sims/nic/corundum/debug.h"
#include "sims/nic/corundum/corundum.h"
#include "sims/nic/corundum/coord.h"
#include "sims/nic/corundum/coord.h"
#include "sims/nic/corundum/corundum.h"
#include "sims/nic/corundum/debug.h"
#include "sims/nic/corundum/dma.h"
#include "sims/nic/corundum/dma.h"
#include "sims/nic/corundum/mem.h"
#include "sims/nic/corundum/mem.h"
#include "sims/nic/corundum/obj_dir/Vinterface.h"
struct
DMAOp
;
struct
DMAOp
;
...
@@ -51,354 +50,337 @@ static uint64_t sync_period = 500 * 1000ULL; // 500ns
...
@@ -51,354 +50,337 @@ static uint64_t sync_period = 500 * 1000ULL; // 500ns
static
uint64_t
pci_latency
=
500
*
1000ULL
;
// 500ns
static
uint64_t
pci_latency
=
500
*
1000ULL
;
// 500ns
static
uint64_t
eth_latency
=
500
*
1000ULL
;
// 500ns
static
uint64_t
eth_latency
=
500
*
1000ULL
;
// 500ns
static
volatile
int
exiting
=
0
;
static
volatile
int
exiting
=
0
;
uint64_t
main_time
=
0
;
uint64_t
main_time
=
0
;
static
struct
nicsim_params
nsparams
;
static
struct
nicsim_params
nsparams
;
#ifdef TRACE_ENABLED
#ifdef TRACE_ENABLED
static
VerilatedVcdC
*
trace
;
static
VerilatedVcdC
*
trace
;
#endif
#endif
static
volatile
union
cosim_pcie_proto_d2h
*
d2h_alloc
(
void
);
static
volatile
union
cosim_pcie_proto_d2h
*
d2h_alloc
(
void
);
static
void
sigint_handler
(
int
dummy
)
{
static
void
sigint_handler
(
int
dummy
)
exiting
=
1
;
{
exiting
=
1
;
}
}
static
void
sigusr1_handler
(
int
dummy
)
static
void
sigusr1_handler
(
int
dummy
)
{
{
fprintf
(
stderr
,
"main_time = %lu
\n
"
,
main_time
);
fprintf
(
stderr
,
"main_time = %lu
\n
"
,
main_time
);
}
}
double
sc_time_stamp
()
double
sc_time_stamp
()
{
{
return
main_time
;
return
main_time
;
}
}
static
void
reset_inputs
(
Vinterface
*
top
)
static
void
reset_inputs
(
Vinterface
*
top
)
{
{
top
->
clk
=
0
;
top
->
clk
=
0
;
top
->
rst
=
0
;
top
->
rst
=
0
;
top
->
m_axis_ctrl_dma_read_desc_ready
=
0
;
top
->
m_axis_ctrl_dma_read_desc_ready
=
0
;
top
->
s_axis_ctrl_dma_read_desc_status_tag
=
0
;
top
->
s_axis_ctrl_dma_read_desc_status_tag
=
0
;
top
->
s_axis_ctrl_dma_read_desc_status_valid
=
0
;
top
->
s_axis_ctrl_dma_read_desc_status_valid
=
0
;
top
->
m_axis_ctrl_dma_write_desc_ready
=
0
;
top
->
m_axis_ctrl_dma_write_desc_ready
=
0
;
top
->
s_axis_ctrl_dma_write_desc_status_tag
=
0
;
top
->
s_axis_ctrl_dma_write_desc_status_tag
=
0
;
top
->
s_axis_ctrl_dma_write_desc_status_valid
=
0
;
top
->
s_axis_ctrl_dma_write_desc_status_valid
=
0
;
top
->
m_axis_data_dma_read_desc_ready
=
0
;
top
->
m_axis_data_dma_read_desc_ready
=
0
;
top
->
s_axis_data_dma_read_desc_status_tag
=
0
;
top
->
s_axis_data_dma_read_desc_status_tag
=
0
;
top
->
s_axis_data_dma_read_desc_status_valid
=
0
;
top
->
s_axis_data_dma_read_desc_status_valid
=
0
;
top
->
m_axis_data_dma_write_desc_ready
=
0
;
top
->
m_axis_data_dma_write_desc_ready
=
0
;
top
->
s_axis_data_dma_write_desc_status_tag
=
0
;
top
->
s_axis_data_dma_write_desc_status_tag
=
0
;
top
->
s_axis_data_dma_write_desc_status_valid
=
0
;
top
->
s_axis_data_dma_write_desc_status_valid
=
0
;
top
->
s_axil_awaddr
=
0
;
top
->
s_axil_awaddr
=
0
;
top
->
s_axil_awprot
=
0
;
top
->
s_axil_awprot
=
0
;
top
->
s_axil_awvalid
=
0
;
top
->
s_axil_awvalid
=
0
;
top
->
s_axil_wdata
=
0
;
top
->
s_axil_wdata
=
0
;
top
->
s_axil_wstrb
=
0
;
top
->
s_axil_wstrb
=
0
;
top
->
s_axil_wvalid
=
0
;
top
->
s_axil_wvalid
=
0
;
top
->
s_axil_bready
=
0
;
top
->
s_axil_bready
=
0
;
top
->
s_axil_araddr
=
0
;
top
->
s_axil_araddr
=
0
;
top
->
s_axil_arprot
=
0
;
top
->
s_axil_arprot
=
0
;
top
->
s_axil_arvalid
=
0
;
top
->
s_axil_arvalid
=
0
;
top
->
s_axil_rready
=
0
;
top
->
s_axil_rready
=
0
;
top
->
m_axil_csr_awready
=
0
;
top
->
m_axil_csr_awready
=
0
;
top
->
m_axil_csr_wready
=
0
;
top
->
m_axil_csr_wready
=
0
;
top
->
m_axil_csr_bresp
=
0
;
top
->
m_axil_csr_bresp
=
0
;
top
->
m_axil_csr_bvalid
=
0
;
top
->
m_axil_csr_bvalid
=
0
;
top
->
m_axil_csr_arready
=
0
;
top
->
m_axil_csr_arready
=
0
;
top
->
m_axil_csr_rdata
=
0
;
top
->
m_axil_csr_rdata
=
0
;
top
->
m_axil_csr_rresp
=
0
;
top
->
m_axil_csr_rresp
=
0
;
top
->
m_axil_csr_rvalid
=
0
;
top
->
m_axil_csr_rvalid
=
0
;
top
->
ctrl_dma_ram_wr_cmd_sel
=
0
;
top
->
ctrl_dma_ram_wr_cmd_sel
=
0
;
// top->ctrl_dma_ram_wr_cmd_be = 0;
// top->ctrl_dma_ram_wr_cmd_be = 0;
// top->ctrl_dma_ram_wr_cmd_addr = 0;
// top->ctrl_dma_ram_wr_cmd_addr = 0;
top
->
ctrl_dma_ram_wr_cmd_valid
=
0
;
top
->
ctrl_dma_ram_wr_cmd_valid
=
0
;
top
->
ctrl_dma_ram_rd_cmd_sel
=
0
;
top
->
ctrl_dma_ram_rd_cmd_sel
=
0
;
// top->ctrl_dma_ram_rd_cmd_addr = 0;
// top->ctrl_dma_ram_rd_cmd_addr = 0;
top
->
ctrl_dma_ram_rd_cmd_valid
=
0
;
top
->
ctrl_dma_ram_rd_cmd_valid
=
0
;
top
->
ctrl_dma_ram_rd_resp_ready
=
0
;
top
->
ctrl_dma_ram_rd_resp_ready
=
0
;
top
->
data_dma_ram_wr_cmd_sel
=
0
;
top
->
data_dma_ram_wr_cmd_sel
=
0
;
// top->data_dma_ram_wr_cmd_be = 0;
// top->data_dma_ram_wr_cmd_be = 0;
// top->data_dma_ram_wr_cmd_addr = 0;
// top->data_dma_ram_wr_cmd_addr = 0;
top
->
data_dma_ram_wr_cmd_valid
=
0
;
top
->
data_dma_ram_wr_cmd_valid
=
0
;
top
->
data_dma_ram_rd_cmd_sel
=
0
;
top
->
data_dma_ram_rd_cmd_sel
=
0
;
// top->data_dma_ram_rd_cmd_addr = 0;
// top->data_dma_ram_rd_cmd_addr = 0;
top
->
data_dma_ram_rd_cmd_valid
=
0
;
top
->
data_dma_ram_rd_cmd_valid
=
0
;
top
->
data_dma_ram_rd_resp_ready
=
0
;
top
->
data_dma_ram_rd_resp_ready
=
0
;
top
->
tx_axis_tready
=
0
;
top
->
tx_axis_tready
=
0
;
top
->
s_axis_tx_ptp_ts_valid
=
0
;
top
->
s_axis_tx_ptp_ts_valid
=
0
;
top
->
rx_axis_tkeep
=
0
;
top
->
rx_axis_tkeep
=
0
;
top
->
rx_axis_tvalid
=
0
;
top
->
rx_axis_tvalid
=
0
;
top
->
rx_axis_tlast
=
0
;
top
->
rx_axis_tlast
=
0
;
top
->
rx_axis_tuser
=
0
;
top
->
rx_axis_tuser
=
0
;
top
->
s_axis_rx_ptp_ts_valid
=
0
;
top
->
s_axis_rx_ptp_ts_valid
=
0
;
top
->
ptp_ts_step
=
0
;
top
->
ptp_ts_step
=
0
;
}
}
static
void
report_output
(
const
char
*
label
,
uint64_t
val
)
static
void
report_output
(
const
char
*
label
,
uint64_t
val
)
{
{
if
(
val
==
0
)
if
(
val
==
0
)
return
;
return
;
std
::
cout
<<
" "
<<
label
<<
" = "
<<
val
<<
std
::
endl
;
std
::
cout
<<
" "
<<
label
<<
" = "
<<
val
<<
std
::
endl
;
}
}
static
void
report_outputs
(
Vinterface
*
top
)
static
void
report_outputs
(
Vinterface
*
top
)
{
{
report_output
(
"m_axis_ctrl_dma_read_desc_dma_addr"
,
report_output
(
"m_axis_ctrl_dma_read_desc_dma_addr"
,
top
->
m_axis_ctrl_dma_read_desc_dma_addr
);
top
->
m_axis_ctrl_dma_read_desc_dma_addr
);
report_output
(
"m_axis_ctrl_dma_read_desc_ram_sel"
,
report_output
(
"m_axis_ctrl_dma_read_desc_ram_sel"
,
top
->
m_axis_ctrl_dma_read_desc_ram_sel
);
top
->
m_axis_ctrl_dma_read_desc_ram_sel
);
report_output
(
"m_axis_ctrl_dma_read_desc_ram_addr"
,
report_output
(
"m_axis_ctrl_dma_read_desc_ram_addr"
,
top
->
m_axis_ctrl_dma_read_desc_ram_addr
);
top
->
m_axis_ctrl_dma_read_desc_ram_addr
);
report_output
(
"m_axis_ctrl_dma_read_desc_len"
,
report_output
(
"m_axis_ctrl_dma_read_desc_len"
,
top
->
m_axis_ctrl_dma_read_desc_len
);
top
->
m_axis_ctrl_dma_read_desc_len
);
report_output
(
"m_axis_ctrl_dma_read_desc_tag"
,
report_output
(
"m_axis_ctrl_dma_read_desc_tag"
,
top
->
m_axis_ctrl_dma_read_desc_tag
);
top
->
m_axis_ctrl_dma_read_desc_tag
);
report_output
(
"m_axis_ctrl_dma_read_desc_valid"
,
report_output
(
"m_axis_ctrl_dma_read_desc_valid"
,
top
->
m_axis_ctrl_dma_read_desc_valid
);
top
->
m_axis_ctrl_dma_read_desc_valid
);
report_output
(
"m_axis_ctrl_dma_write_desc_dma_addr"
,
report_output
(
"m_axis_ctrl_dma_write_desc_dma_addr"
,
top
->
m_axis_ctrl_dma_write_desc_dma_addr
);
top
->
m_axis_ctrl_dma_write_desc_dma_addr
);
report_output
(
"m_axis_ctrl_dma_write_desc_ram_sel"
,
report_output
(
"m_axis_ctrl_dma_write_desc_ram_sel"
,
top
->
m_axis_ctrl_dma_write_desc_ram_sel
);
top
->
m_axis_ctrl_dma_write_desc_ram_sel
);
report_output
(
"m_axis_ctrl_dma_write_desc_ram_addr"
,
report_output
(
"m_axis_ctrl_dma_write_desc_ram_addr"
,
top
->
m_axis_ctrl_dma_write_desc_ram_addr
);
top
->
m_axis_ctrl_dma_write_desc_ram_addr
);
report_output
(
"m_axis_ctrl_dma_write_desc_len"
,
report_output
(
"m_axis_ctrl_dma_write_desc_len"
,
top
->
m_axis_ctrl_dma_write_desc_len
);
top
->
m_axis_ctrl_dma_write_desc_len
);
report_output
(
"m_axis_ctrl_dma_write_desc_tag"
,
report_output
(
"m_axis_ctrl_dma_write_desc_tag"
,
top
->
m_axis_ctrl_dma_write_desc_tag
);
top
->
m_axis_ctrl_dma_write_desc_tag
);
report_output
(
"m_axis_ctrl_dma_write_desc_valid"
,
report_output
(
"m_axis_ctrl_dma_write_desc_valid"
,
top
->
m_axis_ctrl_dma_write_desc_valid
);
top
->
m_axis_ctrl_dma_write_desc_valid
);
report_output
(
"m_axis_data_dma_read_desc_dma_addr"
,
report_output
(
"m_axis_data_dma_read_desc_dma_addr"
,
top
->
m_axis_data_dma_read_desc_dma_addr
);
top
->
m_axis_data_dma_read_desc_dma_addr
);
report_output
(
"m_axis_data_dma_read_desc_ram_sel"
,
report_output
(
"m_axis_data_dma_read_desc_ram_sel"
,
top
->
m_axis_data_dma_read_desc_ram_sel
);
top
->
m_axis_data_dma_read_desc_ram_sel
);
report_output
(
"m_axis_data_dma_read_desc_ram_addr"
,
report_output
(
"m_axis_data_dma_read_desc_ram_addr"
,
top
->
m_axis_data_dma_read_desc_ram_addr
);
top
->
m_axis_data_dma_read_desc_ram_addr
);
report_output
(
"m_axis_data_dma_read_desc_len"
,
report_output
(
"m_axis_data_dma_read_desc_len"
,
top
->
m_axis_data_dma_read_desc_len
);
top
->
m_axis_data_dma_read_desc_len
);
report_output
(
"m_axis_data_dma_read_desc_tag"
,
report_output
(
"m_axis_data_dma_read_desc_tag"
,
top
->
m_axis_data_dma_read_desc_tag
);
top
->
m_axis_data_dma_read_desc_tag
);
report_output
(
"m_axis_data_dma_read_desc_valid"
,
report_output
(
"m_axis_data_dma_read_desc_valid"
,
top
->
m_axis_data_dma_read_desc_valid
);
top
->
m_axis_data_dma_read_desc_valid
);
report_output
(
"m_axis_data_dma_write_desc_dma_addr"
,
report_output
(
"m_axis_data_dma_write_desc_dma_addr"
,
top
->
m_axis_data_dma_write_desc_dma_addr
);
top
->
m_axis_data_dma_write_desc_dma_addr
);
report_output
(
"m_axis_data_dma_write_desc_ram_sel"
,
report_output
(
"m_axis_data_dma_write_desc_ram_sel"
,
top
->
m_axis_data_dma_write_desc_ram_sel
);
top
->
m_axis_data_dma_write_desc_ram_sel
);
report_output
(
"m_axis_data_dma_write_desc_ram_addr"
,
report_output
(
"m_axis_data_dma_write_desc_ram_addr"
,
top
->
m_axis_data_dma_write_desc_ram_addr
);
top
->
m_axis_data_dma_write_desc_ram_addr
);
report_output
(
"m_axis_data_dma_write_desc_len"
,
report_output
(
"m_axis_data_dma_write_desc_len"
,
top
->
m_axis_data_dma_write_desc_len
);
top
->
m_axis_data_dma_write_desc_len
);
report_output
(
"m_axis_data_dma_write_desc_tag"
,
report_output
(
"m_axis_data_dma_write_desc_tag"
,
top
->
m_axis_data_dma_write_desc_tag
);
top
->
m_axis_data_dma_write_desc_tag
);
report_output
(
"m_axis_data_dma_write_desc_valid"
,
report_output
(
"m_axis_data_dma_write_desc_valid"
,
top
->
m_axis_data_dma_write_desc_valid
);
top
->
m_axis_data_dma_write_desc_valid
);
report_output
(
"s_axil_awready"
,
top
->
s_axil_awready
);
report_output
(
"s_axil_awready"
,
top
->
s_axil_awready
);
report_output
(
"s_axil_wready"
,
top
->
s_axil_wready
);
report_output
(
"s_axil_wready"
,
top
->
s_axil_wready
);
report_output
(
"s_axil_bresp"
,
top
->
s_axil_bresp
);
report_output
(
"s_axil_bresp"
,
top
->
s_axil_bresp
);
report_output
(
"s_axil_bvalid"
,
top
->
s_axil_bvalid
);
report_output
(
"s_axil_bvalid"
,
top
->
s_axil_bvalid
);
report_output
(
"s_axil_arready"
,
top
->
s_axil_arready
);
report_output
(
"s_axil_arready"
,
top
->
s_axil_arready
);
report_output
(
"s_axil_rdata"
,
top
->
s_axil_rdata
);
report_output
(
"s_axil_rdata"
,
top
->
s_axil_rdata
);
report_output
(
"s_axil_rresp"
,
top
->
s_axil_rresp
);
report_output
(
"s_axil_rresp"
,
top
->
s_axil_rresp
);
report_output
(
"s_axil_rvalid"
,
top
->
s_axil_rvalid
);
report_output
(
"s_axil_rvalid"
,
top
->
s_axil_rvalid
);
report_output
(
"m_axil_csr_awaddr"
,
top
->
m_axil_csr_awaddr
);
report_output
(
"m_axil_csr_awaddr"
,
top
->
m_axil_csr_awaddr
);
report_output
(
"m_axil_csr_awprot"
,
top
->
m_axil_csr_awprot
);
report_output
(
"m_axil_csr_awprot"
,
top
->
m_axil_csr_awprot
);
report_output
(
"m_axil_csr_awvalid"
,
top
->
m_axil_csr_awvalid
);
report_output
(
"m_axil_csr_awvalid"
,
top
->
m_axil_csr_awvalid
);
report_output
(
"m_axil_csr_wdata"
,
top
->
m_axil_csr_wdata
);
report_output
(
"m_axil_csr_wdata"
,
top
->
m_axil_csr_wdata
);
report_output
(
"m_axil_csr_wstrb"
,
top
->
m_axil_csr_wstrb
);
report_output
(
"m_axil_csr_wstrb"
,
top
->
m_axil_csr_wstrb
);
report_output
(
"m_axil_csr_wvalid"
,
top
->
m_axil_csr_wvalid
);
report_output
(
"m_axil_csr_wvalid"
,
top
->
m_axil_csr_wvalid
);
report_output
(
"m_axil_csr_bready"
,
top
->
m_axil_csr_bready
);
report_output
(
"m_axil_csr_bready"
,
top
->
m_axil_csr_bready
);
report_output
(
"m_axil_csr_araddr"
,
top
->
m_axil_csr_araddr
);
report_output
(
"m_axil_csr_araddr"
,
top
->
m_axil_csr_araddr
);
report_output
(
"m_axil_csr_arprot"
,
top
->
m_axil_csr_arprot
);
report_output
(
"m_axil_csr_arprot"
,
top
->
m_axil_csr_arprot
);
report_output
(
"m_axil_csr_arvalid"
,
top
->
m_axil_csr_arvalid
);
report_output
(
"m_axil_csr_arvalid"
,
top
->
m_axil_csr_arvalid
);
report_output
(
"m_axil_csr_rready"
,
top
->
m_axil_csr_rready
);
report_output
(
"m_axil_csr_rready"
,
top
->
m_axil_csr_rready
);
report_output
(
"ctrl_dma_ram_wr_cmd_ready"
,
top
->
ctrl_dma_ram_wr_cmd_ready
);
report_output
(
"ctrl_dma_ram_wr_cmd_ready"
,
top
->
ctrl_dma_ram_wr_cmd_ready
);
report_output
(
"ctrl_dma_ram_rd_cmd_ready"
,
top
->
ctrl_dma_ram_rd_cmd_ready
);
report_output
(
"ctrl_dma_ram_rd_cmd_ready"
,
top
->
ctrl_dma_ram_rd_cmd_ready
);
report_output
(
"ctrl_dma_ram_rd_resp_valid"
,
top
->
ctrl_dma_ram_rd_resp_valid
);
report_output
(
"ctrl_dma_ram_rd_resp_valid"
,
report_output
(
"data_dma_ram_wr_cmd_ready"
,
top
->
data_dma_ram_wr_cmd_ready
);
top
->
ctrl_dma_ram_rd_resp_valid
);
report_output
(
"data_dma_ram_rd_cmd_ready"
,
top
->
data_dma_ram_rd_cmd_ready
);
report_output
(
"data_dma_ram_wr_cmd_ready"
,
top
->
data_dma_ram_wr_cmd_ready
);
report_output
(
"data_dma_ram_rd_resp_valid"
,
top
->
data_dma_ram_rd_resp_valid
);
report_output
(
"data_dma_ram_rd_cmd_ready"
,
top
->
data_dma_ram_rd_cmd_ready
);
report_output
(
"tx_axis_tkeep"
,
top
->
tx_axis_tkeep
);
report_output
(
"data_dma_ram_rd_resp_valid"
,
report_output
(
"tx_axis_tvalid"
,
top
->
tx_axis_tvalid
);
top
->
data_dma_ram_rd_resp_valid
);
report_output
(
"tx_axis_tlast"
,
top
->
tx_axis_tlast
);
report_output
(
"tx_axis_tkeep"
,
top
->
tx_axis_tkeep
);
report_output
(
"tx_axis_tuser"
,
top
->
tx_axis_tuser
);
report_output
(
"tx_axis_tvalid"
,
top
->
tx_axis_tvalid
);
report_output
(
"s_axis_tx_ptp_ts_ready"
,
top
->
s_axis_tx_ptp_ts_ready
);
report_output
(
"tx_axis_tlast"
,
top
->
tx_axis_tlast
);
report_output
(
"rx_axis_tready"
,
top
->
rx_axis_tready
);
report_output
(
"tx_axis_tuser"
,
top
->
tx_axis_tuser
);
report_output
(
"s_axis_rx_ptp_ts_ready"
,
top
->
s_axis_rx_ptp_ts_ready
);
report_output
(
"s_axis_tx_ptp_ts_ready"
,
top
->
s_axis_tx_ptp_ts_ready
);
report_output
(
"msi_irq"
,
top
->
msi_irq
);
report_output
(
"rx_axis_tready"
,
top
->
rx_axis_tready
);
report_output
(
"s_axis_rx_ptp_ts_ready"
,
top
->
s_axis_rx_ptp_ts_ready
);
report_output
(
"msi_irq"
,
top
->
msi_irq
);
}
}
struct
MMIOOp
{
struct
MMIOOp
{
uint64_t
id
;
uint64_t
id
;
uint64_t
addr
;
uint64_t
addr
;
uint64_t
value
;
uint64_t
value
;
size_t
len
;
size_t
len
;
bool
isWrite
;
bool
isWrite
;
};
};
class
MMIOInterface
{
class
MMIOInterface
{
protected:
protected:
enum
OpState
{
enum
OpState
{
AddrIssued
,
AddrIssued
,
AddrAcked
,
AddrAcked
,
AddrDone
,
AddrDone
,
};
};
Vinterface
&
top
;
Vinterface
&
top
;
PCICoordinator
&
coord
;
PCICoordinator
&
coord
;
std
::
deque
<
MMIOOp
*>
queue
;
std
::
deque
<
MMIOOp
*>
queue
;
MMIOOp
*
rCur
,
*
wCur
;
MMIOOp
*
rCur
,
*
wCur
;
enum
OpState
rState
,
wState
;
enum
OpState
rState
,
wState
;
public:
public:
MMIOInterface
(
Vinterface
&
top_
,
PCICoordinator
&
coord_
)
MMIOInterface
(
Vinterface
&
top_
,
PCICoordinator
&
coord_
)
:
top
(
top_
),
coord
(
coord_
),
rCur
(
0
),
wCur
(
0
)
:
top
(
top_
),
coord
(
coord_
),
rCur
(
0
),
wCur
(
0
)
{
{
}
}
void
step
()
{
void
step
()
if
(
rCur
)
{
{
/* work on active read operation */
if
(
rCur
)
{
/* work on active read operation */
if
(
rState
==
AddrIssued
&&
top
.
s_axil_arready
)
{
/* read handshake is complete */
if
(
rState
==
AddrIssued
&&
top
.
s_axil_arready
)
{
top
.
s_axil_arvalid
=
0
;
/* read handshake is complete */
rState
=
AddrAcked
;
top
.
s_axil_arvalid
=
0
;
}
rState
=
AddrAcked
;
if
(
rState
==
AddrAcked
&&
top
.
s_axil_rvalid
)
{
}
/* read data received */
if
(
rState
==
AddrAcked
&&
top
.
s_axil_rvalid
)
{
top
.
s_axil_rready
=
0
;
/* read data received */
rCur
->
value
=
top
.
s_axil_rdata
;
top
.
s_axil_rready
=
0
;
coord
.
mmio_comp_enqueue
(
rCur
);
rCur
->
value
=
top
.
s_axil_rdata
;
coord
.
mmio_comp_enqueue
(
rCur
);
#ifdef MMIO_DEBUG
#ifdef MMIO_DEBUG
std
::
cout
<<
main_time
<<
" MMIO: completed AXI read op="
<<
std
::
cout
<<
main_time
<<
" MMIO: completed AXI read op="
<<
rCur
rCur
<<
" val="
<<
rCur
->
value
<<
std
::
endl
;
<<
" val="
<<
rCur
->
value
<<
std
::
endl
;
#endif
#endif
rCur
=
0
;
rCur
=
0
;
}
}
}
else
if
(
wCur
)
{
}
else
if
(
wCur
)
{
/* work on active write operation */
/* work on active write operation */
if
(
wState
==
AddrIssued
&&
top
.
s_axil_awready
)
{
if
(
wState
==
AddrIssued
&&
top
.
s_axil_awready
)
{
/* write addr handshake is complete */
/* write addr handshake is complete */
top
.
s_axil_awvalid
=
0
;
top
.
s_axil_awvalid
=
0
;
wState
=
AddrAcked
;
wState
=
AddrAcked
;
}
}
if
(
wState
==
AddrAcked
&&
top
.
s_axil_wready
)
{
if
(
wState
==
AddrAcked
&&
top
.
s_axil_wready
)
{
/* write data handshake is complete */
/* write data handshake is complete */
top
.
s_axil_wvalid
=
0
;
top
.
s_axil_wvalid
=
0
;
top
.
s_axil_bready
=
1
;
top
.
s_axil_bready
=
1
;
wState
=
AddrDone
;
wState
=
AddrDone
;
}
}
if
(
wState
==
AddrDone
&&
top
.
s_axil_bvalid
)
{
if
(
wState
==
AddrDone
&&
top
.
s_axil_bvalid
)
{
/* write complete */
/* write complete */
top
.
s_axil_bready
=
0
;
top
.
s_axil_bready
=
0
;
// TODO(antoinek): check top.s_axil_bresp
// TODO(antoinek): check top.s_axil_bresp
#ifdef MMIO_DEBUG
#ifdef MMIO_DEBUG
std
::
cout
<<
main_time
<<
" MMIO: completed AXI write op="
std
::
cout
<<
main_time
<<
" MMIO: completed AXI write op="
<<
wCur
<<
wCur
<<
std
::
endl
;
<<
std
::
endl
;
#endif
#endif
coord
.
mmio_comp_enqueue
(
wCur
);
coord
.
mmio_comp_enqueue
(
wCur
);
wCur
=
0
;
wCur
=
0
;
}
}
}
else
if
(
/*!top.clk &&*/
!
queue
.
empty
())
{
}
else
if
(
/*!top.clk &&*/
!
queue
.
empty
())
{
/* issue new operation */
/* issue new operation */
MMIOOp
*
op
=
queue
.
front
();
MMIOOp
*
op
=
queue
.
front
();
queue
.
pop_front
();
queue
.
pop_front
();
if
(
!
op
->
isWrite
)
{
if
(
!
op
->
isWrite
)
{
/* issue new read */
/* issue new read */
rCur
=
op
;
rCur
=
op
;
rState
=
AddrIssued
;
rState
=
AddrIssued
;
top
.
s_axil_araddr
=
rCur
->
addr
;
top
.
s_axil_araddr
=
rCur
->
addr
;
top
.
s_axil_arprot
=
0x0
;
top
.
s_axil_arprot
=
0x0
;
top
.
s_axil_arvalid
=
1
;
top
.
s_axil_arvalid
=
1
;
top
.
s_axil_rready
=
1
;
top
.
s_axil_rready
=
1
;
}
else
{
}
else
{
/* issue new write */
/* issue new write */
wCur
=
op
;
wCur
=
op
;
wState
=
AddrIssued
;
wState
=
AddrIssued
;
top
.
s_axil_awaddr
=
wCur
->
addr
;
top
.
s_axil_awaddr
=
wCur
->
addr
;
top
.
s_axil_awprot
=
0x0
;
top
.
s_axil_awprot
=
0x0
;
top
.
s_axil_awvalid
=
1
;
top
.
s_axil_awvalid
=
1
;
top
.
s_axil_wdata
=
wCur
->
value
;
top
.
s_axil_wdata
=
wCur
->
value
;
top
.
s_axil_wstrb
=
0xf
;
top
.
s_axil_wstrb
=
0xf
;
top
.
s_axil_wvalid
=
1
;
top
.
s_axil_wvalid
=
1
;
}
}
}
}
}
}
void
issueRead
(
uint64_t
id
,
uint64_t
addr
,
size_t
len
)
void
issueRead
(
uint64_t
id
,
uint64_t
addr
,
size_t
len
)
{
{
MMIOOp
*
op
=
new
MMIOOp
;
MMIOOp
*
op
=
new
MMIOOp
;
#ifdef MMIO_DEBUG
#ifdef MMIO_DEBUG
std
::
cout
<<
main_time
<<
" MMIO: read id="
<<
id
<<
" addr="
<<
std
::
cout
<<
main_time
<<
" MMIO: read id="
<<
id
<<
" addr="
<<
std
::
hex
std
::
hex
<<
addr
<<
" len="
<<
len
<<
" op="
<<
op
<<
std
::
endl
;
<<
addr
<<
" len="
<<
len
<<
" op="
<<
op
<<
std
::
endl
;
#endif
#endif
op
->
id
=
id
;
op
->
id
=
id
;
op
->
addr
=
addr
;
op
->
addr
=
addr
;
op
->
len
=
len
;
op
->
len
=
len
;
op
->
isWrite
=
false
;
op
->
isWrite
=
false
;
queue
.
push_back
(
op
);
queue
.
push_back
(
op
);
}
}
void
issueWrite
(
uint64_t
id
,
uint64_t
addr
,
size_t
len
,
uint64_t
val
)
{
void
issueWrite
(
uint64_t
id
,
uint64_t
addr
,
size_t
len
,
uint64_t
val
)
MMIOOp
*
op
=
new
MMIOOp
;
{
MMIOOp
*
op
=
new
MMIOOp
;
#ifdef MMIO_DEBUG
#ifdef MMIO_DEBUG
std
::
cout
<<
main_time
<<
" MMIO: write id="
<<
id
<<
" addr="
<<
std
::
cout
<<
main_time
<<
" MMIO: write id="
<<
id
<<
" addr="
<<
std
::
hex
std
::
hex
<<
addr
<<
" len="
<<
len
<<
" val="
<<
val
<<
" op="
<<
addr
<<
" len="
<<
len
<<
" val="
<<
val
<<
" op="
<<
op
<<
op
<<
std
::
endl
;
<<
std
::
endl
;
#endif
#endif
op
->
id
=
id
;
op
->
id
=
id
;
op
->
addr
=
addr
;
op
->
addr
=
addr
;
op
->
len
=
len
;
op
->
len
=
len
;
op
->
value
=
val
;
op
->
value
=
val
;
op
->
isWrite
=
true
;
op
->
isWrite
=
true
;
queue
.
push_back
(
op
);
queue
.
push_back
(
op
);
}
}
};
};
void
pci_rwcomp_issue
(
MMIOOp
*
op
)
void
pci_rwcomp_issue
(
MMIOOp
*
op
)
{
{
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
struct
cosim_pcie_proto_d2h_readcomp
*
rc
;
volatile
struct
cosim_pcie_proto_d2h_readcomp
*
rc
;
volatile
struct
cosim_pcie_proto_d2h_writecomp
*
wc
;
volatile
struct
cosim_pcie_proto_d2h_writecomp
*
wc
;
if
(
!
msg
)
if
(
!
msg
)
throw
"completion alloc failed"
;
throw
"completion alloc failed"
;
if
(
op
->
isWrite
)
{
if
(
op
->
isWrite
)
{
wc
=
&
msg
->
writecomp
;
wc
=
&
msg
->
writecomp
;
wc
->
req_id
=
op
->
id
;
wc
->
req_id
=
op
->
id
;
// WMB();
// WMB();
wc
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_WRITECOMP
|
wc
->
own_type
=
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
COSIM_PCIE_PROTO_D2H_MSG_WRITECOMP
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
else
{
}
else
{
rc
=
&
msg
->
readcomp
;
rc
=
&
msg
->
readcomp
;
memcpy
((
void
*
)
rc
->
data
,
&
op
->
value
,
op
->
len
);
memcpy
((
void
*
)
rc
->
data
,
&
op
->
value
,
op
->
len
);
rc
->
req_id
=
op
->
id
;
rc
->
req_id
=
op
->
id
;
// WMB();
// WMB();
rc
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_READCOMP
|
rc
->
own_type
=
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
COSIM_PCIE_PROTO_D2H_MSG_READCOMP
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
}
delete
op
;
delete
op
;
}
}
#if 0
#if 0
...
@@ -446,49 +428,46 @@ class MemAccessor {
...
@@ -446,49 +428,46 @@ class MemAccessor {
std
::
set
<
DMAOp
*>
pci_dma_pending
;
std
::
set
<
DMAOp
*>
pci_dma_pending
;
void
pci_dma_issue
(
DMAOp
*
op
)
void
pci_dma_issue
(
DMAOp
*
op
)
{
{
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
uint8_t
ty
;
uint8_t
ty
;
if
(
!
msg
)
if
(
!
msg
)
throw
"completion alloc failed"
;
throw
"completion alloc failed"
;
if
(
op
->
write
)
{
if
(
op
->
write
)
{
volatile
struct
cosim_pcie_proto_d2h_write
*
write
=
&
msg
->
write
;
volatile
struct
cosim_pcie_proto_d2h_write
*
write
=
&
msg
->
write
;
write
->
req_id
=
(
uintptr_t
)
op
;
write
->
req_id
=
(
uintptr_t
)
op
;
write
->
offset
=
op
->
dma_addr
;
write
->
offset
=
op
->
dma_addr
;
write
->
len
=
op
->
len
;
write
->
len
=
op
->
len
;
// TODO(antoinek): check DMA length
// TODO(antoinek): check DMA length
memcpy
((
void
*
)
write
->
data
,
op
->
data
,
op
->
len
);
memcpy
((
void
*
)
write
->
data
,
op
->
data
,
op
->
len
);
// WMB();
// WMB();
write
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_WRITE
|
write
->
own_type
=
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
COSIM_PCIE_PROTO_D2H_MSG_WRITE
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
else
{
}
else
{
volatile
struct
cosim_pcie_proto_d2h_read
*
read
=
&
msg
->
read
;
volatile
struct
cosim_pcie_proto_d2h_read
*
read
=
&
msg
->
read
;
read
->
req_id
=
(
uintptr_t
)
op
;
read
->
req_id
=
(
uintptr_t
)
op
;
read
->
offset
=
op
->
dma_addr
;
read
->
offset
=
op
->
dma_addr
;
read
->
len
=
op
->
len
;
read
->
len
=
op
->
len
;
// WMB();
read
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_READ
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
pci_dma_pending
.
insert
(
op
);
// WMB();
}
read
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_READ
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
pci_dma_pending
.
insert
(
op
);
}
static
void
h2d_readcomp
(
volatile
struct
cosim_pcie_proto_h2d_readcomp
*
rc
)
static
void
h2d_readcomp
(
volatile
struct
cosim_pcie_proto_h2d_readcomp
*
rc
)
{
{
DMAOp
*
op
=
(
DMAOp
*
)(
uintptr_t
)
rc
->
req_id
;
DMAOp
*
op
=
(
DMAOp
*
)
(
uintptr_t
)
rc
->
req_id
;
if
(
pci_dma_pending
.
find
(
op
)
==
pci_dma_pending
.
end
())
if
(
pci_dma_pending
.
find
(
op
)
==
pci_dma_pending
.
end
())
throw
"unexpected completion"
;
throw
"unexpected completion"
;
pci_dma_pending
.
erase
(
op
);
pci_dma_pending
.
erase
(
op
);
memcpy
(
op
->
data
,
(
void
*
)
rc
->
data
,
op
->
len
);
memcpy
(
op
->
data
,
(
void
*
)
rc
->
data
,
op
->
len
);
#if 0
#if 0
std::cerr << "dma read comp: ";
std::cerr << "dma read comp: ";
...
@@ -497,335 +476,322 @@ static void h2d_readcomp(volatile struct cosim_pcie_proto_h2d_readcomp *rc)
...
@@ -497,335 +476,322 @@ static void h2d_readcomp(volatile struct cosim_pcie_proto_h2d_readcomp *rc)
std::cerr << std::endl;
std::cerr << std::endl;
#endif
#endif
op
->
engine
->
pci_op_complete
(
op
);
op
->
engine
->
pci_op_complete
(
op
);
}
}
static
void
h2d_writecomp
(
volatile
struct
cosim_pcie_proto_h2d_writecomp
*
wc
)
static
void
h2d_writecomp
(
volatile
struct
cosim_pcie_proto_h2d_writecomp
*
wc
)
{
{
DMAOp
*
op
=
(
DMAOp
*
)(
uintptr_t
)
wc
->
req_id
;
DMAOp
*
op
=
(
DMAOp
*
)
(
uintptr_t
)
wc
->
req_id
;
if
(
pci_dma_pending
.
find
(
op
)
==
pci_dma_pending
.
end
())
if
(
pci_dma_pending
.
find
(
op
)
==
pci_dma_pending
.
end
())
throw
"unexpected completion"
;
throw
"unexpected completion"
;
pci_dma_pending
.
erase
(
op
);
pci_dma_pending
.
erase
(
op
);
op
->
engine
->
pci_op_complete
(
op
);
op
->
engine
->
pci_op_complete
(
op
);
}
}
static
uint64_t
csr_read
(
uint64_t
off
)
static
uint64_t
csr_read
(
uint64_t
off
)
{
{
switch
(
off
)
{
switch
(
off
)
{
case
0x00
:
case
0x00
:
return
32
;
/* firmware id */
return
32
;
/* firmware id */
case
0x04
:
return
1
;
/* firmware version */
case
0x04
:
case
0x08
:
return
0x43215678
;
/* board id */
return
1
;
/* firmware version */
case
0x0c
:
return
0x1
;
/* board version */
case
0x08
:
case
0x10
:
return
1
;
/* phc count */
return
0x43215678
;
/* board id */
case
0x14
:
return
0x200
;
/* phc offset */
case
0x0c
:
case
0x18
:
return
0x80
;
/* phc stride */
return
0x1
;
/* board version */
case
0x20
:
return
1
;
/* if_count */
case
0x10
:
case
0x24
:
return
0x80000
;
/* if stride */
return
1
;
/* phc count */
case
0x2c
:
return
0x80000
;
/* if csr offset */
case
0x14
:
case
0x200
:
return
0x1
;
/* phc features */
return
0x200
;
/* phc offset */
default:
case
0x18
:
std
::
cerr
<<
"csr_read("
<<
off
<<
") unimplemented"
<<
std
::
endl
;
return
0x80
;
/* phc stride */
return
0
;
case
0x20
:
}
return
1
;
/* if_count */
case
0x24
:
return
0x80000
;
/* if stride */
case
0x2c
:
return
0x80000
;
/* if csr offset */
case
0x200
:
return
0x1
;
/* phc features */
default:
std
::
cerr
<<
"csr_read("
<<
off
<<
") unimplemented"
<<
std
::
endl
;
return
0
;
}
}
}
static
void
csr_write
(
uint64_t
off
,
uint64_t
val
)
static
void
csr_write
(
uint64_t
off
,
uint64_t
val
)
{
{
}
}
static
void
h2d_read
(
MMIOInterface
&
mmio
,
static
void
h2d_read
(
MMIOInterface
&
mmio
,
volatile
struct
cosim_pcie_proto_h2d_read
*
read
)
volatile
struct
cosim_pcie_proto_h2d_read
*
read
)
{
{
// std::cout << "got read " << read->offset << std::endl;
// std::cout << "got read " << read->offset << std::endl;
if
(
read
->
offset
<
0x80000
)
{
if
(
read
->
offset
<
0x80000
)
{
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
struct
cosim_pcie_proto_d2h_readcomp
*
rc
;
volatile
struct
cosim_pcie_proto_d2h_readcomp
*
rc
;
if
(
!
msg
)
if
(
!
msg
)
throw
"completion alloc failed"
;
throw
"completion alloc failed"
;
rc
=
&
msg
->
readcomp
;
rc
=
&
msg
->
readcomp
;
memset
((
void
*
)
rc
->
data
,
0
,
read
->
len
);
memset
((
void
*
)
rc
->
data
,
0
,
read
->
len
);
uint64_t
val
=
csr_read
(
read
->
offset
);
uint64_t
val
=
csr_read
(
read
->
offset
);
memcpy
((
void
*
)
rc
->
data
,
&
val
,
read
->
len
);
memcpy
((
void
*
)
rc
->
data
,
&
val
,
read
->
len
);
rc
->
req_id
=
read
->
req_id
;
rc
->
req_id
=
read
->
req_id
;
// WMB();
// WMB();
rc
->
own_type
=
rc
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_READCOMP
|
COSIM_PCIE_PROTO_D2H_MSG_READCOMP
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
else
{
}
else
{
/*printf("read(bar=%u, off=%lu, len=%u) = %lu\n", read->bar, read->offset,
/*printf("read(bar=%u, off=%lu, len=%u) = %lu\n", read->bar, read->offset,
read->len, val);*/
read->len, val);*/
mmio
.
issueRead
(
read
->
req_id
,
read
->
offset
,
read
->
len
);
mmio
.
issueRead
(
read
->
req_id
,
read
->
offset
,
read
->
len
);
}
}
}
}
static
void
h2d_write
(
MMIOInterface
&
mmio
,
static
void
h2d_write
(
MMIOInterface
&
mmio
,
volatile
struct
cosim_pcie_proto_h2d_write
*
write
)
volatile
struct
cosim_pcie_proto_h2d_write
*
write
)
{
{
uint64_t
val
=
0
;
uint64_t
val
=
0
;
memcpy
(
&
val
,
(
void
*
)
write
->
data
,
write
->
len
);
memcpy
(
&
val
,
(
void
*
)
write
->
data
,
write
->
len
);
// std::cout << "got write " << write->offset << " = " << val << std::endl;
// std::cout << "got write " << write->offset << " = " << val << std::endl;
if
(
write
->
offset
<
0x80000
)
{
if
(
write
->
offset
<
0x80000
)
{
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
struct
cosim_pcie_proto_d2h_writecomp
*
wc
;
volatile
struct
cosim_pcie_proto_d2h_writecomp
*
wc
;
if
(
!
msg
)
if
(
!
msg
)
throw
"completion alloc failed"
;
throw
"completion alloc failed"
;
csr_write
(
write
->
offset
,
val
);
csr_write
(
write
->
offset
,
val
);
wc
=
&
msg
->
writecomp
;
wc
=
&
msg
->
writecomp
;
wc
->
req_id
=
write
->
req_id
;
wc
->
req_id
=
write
->
req_id
;
// WMB();
// WMB();
wc
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_WRITECOMP
|
wc
->
own_type
=
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
COSIM_PCIE_PROTO_D2H_MSG_WRITECOMP
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
else
{
}
else
{
mmio
.
issueWrite
(
write
->
req_id
,
write
->
offset
,
write
->
len
,
val
);
mmio
.
issueWrite
(
write
->
req_id
,
write
->
offset
,
write
->
len
,
val
);
}
}
}
}
static
void
poll_h2d
(
MMIOInterface
&
mmio
)
static
void
poll_h2d
(
MMIOInterface
&
mmio
)
{
{
volatile
union
cosim_pcie_proto_h2d
*
msg
=
volatile
union
cosim_pcie_proto_h2d
*
msg
=
nicif_h2d_poll
(
&
nsparams
,
main_time
);
nicif_h2d_poll
(
&
nsparams
,
main_time
);
uint8_t
t
;
uint8_t
t
;
if
(
msg
==
NULL
)
if
(
msg
==
NULL
)
return
;
return
;
t
=
msg
->
dummy
.
own_type
&
COSIM_PCIE_PROTO_H2D_MSG_MASK
;
t
=
msg
->
dummy
.
own_type
&
COSIM_PCIE_PROTO_H2D_MSG_MASK
;
// std::cerr << "poll_h2d: polled type=" << (int) t << std::endl;
// std::cerr << "poll_h2d: polled type=" << (int) t << std::endl;
switch
(
t
)
{
switch
(
t
)
{
case
COSIM_PCIE_PROTO_H2D_MSG_READ
:
case
COSIM_PCIE_PROTO_H2D_MSG_READ
:
h2d_read
(
mmio
,
&
msg
->
read
);
h2d_read
(
mmio
,
&
msg
->
read
);
break
;
break
;
case
COSIM_PCIE_PROTO_H2D_MSG_WRITE
:
case
COSIM_PCIE_PROTO_H2D_MSG_WRITE
:
h2d_write
(
mmio
,
&
msg
->
write
);
h2d_write
(
mmio
,
&
msg
->
write
);
break
;
break
;
case
COSIM_PCIE_PROTO_H2D_MSG_READCOMP
:
case
COSIM_PCIE_PROTO_H2D_MSG_READCOMP
:
h2d_readcomp
(
&
msg
->
readcomp
);
h2d_readcomp
(
&
msg
->
readcomp
);
break
;
break
;
case
COSIM_PCIE_PROTO_H2D_MSG_WRITECOMP
:
case
COSIM_PCIE_PROTO_H2D_MSG_WRITECOMP
:
h2d_writecomp
(
&
msg
->
writecomp
);
h2d_writecomp
(
&
msg
->
writecomp
);
break
;
break
;
case
COSIM_PCIE_PROTO_H2D_MSG_DEVCTRL
:
case
COSIM_PCIE_PROTO_H2D_MSG_DEVCTRL
:
break
;
break
;
case
COSIM_PCIE_PROTO_H2D_MSG_SYNC
:
case
COSIM_PCIE_PROTO_H2D_MSG_SYNC
:
break
;
break
;
default:
default:
std
::
cerr
<<
"poll_h2d: unsupported type="
<<
t
<<
std
::
endl
;
std
::
cerr
<<
"poll_h2d: unsupported type="
<<
t
<<
std
::
endl
;
}
}
nicif_h2d_done
(
msg
);
nicif_h2d_done
(
msg
);
nicif_h2d_next
();
nicif_h2d_next
();
}
;
}
static
volatile
union
cosim_pcie_proto_d2h
*
d2h_alloc
(
void
)
static
volatile
union
cosim_pcie_proto_d2h
*
d2h_alloc
(
void
)
{
{
return
nicsim_d2h_alloc
(
&
nsparams
,
main_time
);
return
nicsim_d2h_alloc
(
&
nsparams
,
main_time
);
}
}
class
EthernetTx
{
class
EthernetTx
{
protected:
protected:
Vinterface
&
top
;
Vinterface
&
top
;
uint8_t
packet_buf
[
2048
];
uint8_t
packet_buf
[
2048
];
size_t
packet_len
;
size_t
packet_len
;
public:
public:
EthernetTx
(
Vinterface
&
top_
)
EthernetTx
(
Vinterface
&
top_
)
:
top
(
top_
),
packet_len
(
0
)
{
:
top
(
top_
),
packet_len
(
0
)
}
{
}
void
packet_done
()
void
packet_done
()
{
{
volatile
union
cosim_eth_proto_d2n
*
msg
=
volatile
union
cosim_eth_proto_d2n
*
msg
=
nicsim_d2n_alloc
(
&
nsparams
,
main_time
);
nicsim_d2n_alloc
(
&
nsparams
,
main_time
);
volatile
struct
cosim_eth_proto_d2n_send
*
send
;
volatile
struct
cosim_eth_proto_d2n_send
*
send
;
if
(
!
msg
)
if
(
!
msg
)
throw
"completion alloc failed"
;
throw
"completion alloc failed"
;
send
=
&
msg
->
send
;
send
=
&
msg
->
send
;
memcpy
((
void
*
)
send
->
data
,
packet_buf
,
packet_len
);
memcpy
((
void
*
)
send
->
data
,
packet_buf
,
packet_len
);
send
->
len
=
packet_len
;
send
->
len
=
packet_len
;
send
->
timestamp
=
main_time
+
eth_latency
;
send
->
timestamp
=
main_time
+
eth_latency
;
// WMB();
// WMB();
send
->
own_type
=
COSIM_ETH_PROTO_D2N_MSG_SEND
|
send
->
own_type
=
COSIM_ETH_PROTO_D2N_MSG_SEND
|
COSIM_ETH_PROTO_D2N_OWN_NET
;
COSIM_ETH_PROTO_D2N_OWN_NET
;
#ifdef ETH_DEBUG
#ifdef ETH_DEBUG
std
::
cerr
<<
main_time
<<
" EthernetTx: packet len="
<<
std
::
hex
<<
std
::
cerr
<<
main_time
<<
" EthernetTx: packet len="
<<
std
::
hex
packet_len
<<
" "
;
<<
packet_len
<<
" "
;
for
(
size_t
i
=
0
;
i
<
packet_len
;
i
++
)
{
for
(
size_t
i
=
0
;
i
<
packet_len
;
i
++
)
{
std
::
cerr
<<
(
unsigned
)
packet_buf
[
i
]
<<
" "
;
std
::
cerr
<<
(
unsigned
)
packet_buf
[
i
]
<<
" "
;
}
}
std
::
cerr
<<
std
::
endl
;
std
::
cerr
<<
std
::
endl
;
#endif
#endif
}
}
void
step
()
void
step
()
{
{
top
.
tx_axis_tready
=
1
;
top
.
tx_axis_tready
=
1
;
if
(
top
.
tx_axis_tvalid
)
{
/* iterate over all 8 bytes */
for
(
size_t
i
=
0
;
i
<
8
;
i
++
)
{
if
((
top
.
tx_axis_tkeep
&
(
1
<<
i
))
!=
0
)
{
assert
(
packet_len
<
2048
);
packet_buf
[
packet_len
++
]
=
(
top
.
tx_axis_tdata
>>
(
i
*
8
));
}
}
if
(
top
.
tx_axis_tlast
)
{
if
(
top
.
tx_axis_tvalid
)
{
packet_done
();
/* iterate over all 8 bytes */
packet_len
=
0
;
for
(
size_t
i
=
0
;
i
<
8
;
i
++
)
{
}
if
((
top
.
tx_axis_tkeep
&
(
1
<<
i
))
!=
0
)
{
}
assert
(
packet_len
<
2048
);
packet_buf
[
packet_len
++
]
=
(
top
.
tx_axis_tdata
>>
(
i
*
8
));
}
}
}
if
(
top
.
tx_axis_tlast
)
{
packet_done
();
packet_len
=
0
;
}
}
}
};
};
class
EthernetRx
{
class
EthernetRx
{
protected:
protected:
Vinterface
&
top
;
Vinterface
&
top
;
static
const
size_t
FIFO_SIZE
=
32
;
static
const
size_t
FIFO_SIZE
=
32
;
uint8_t
fifo_bufs
[
FIFO_SIZE
][
2048
];
uint8_t
fifo_bufs
[
FIFO_SIZE
][
2048
];
size_t
fifo_lens
[
FIFO_SIZE
];
size_t
fifo_lens
[
FIFO_SIZE
];
size_t
fifo_pos_rd
;
size_t
fifo_pos_rd
;
size_t
fifo_pos_wr
;
size_t
fifo_pos_wr
;
size_t
packet_off
;
size_t
packet_off
;
public:
public:
EthernetRx
(
Vinterface
&
top_
)
EthernetRx
(
Vinterface
&
top_
)
:
top
(
top_
),
fifo_pos_rd
(
0
),
fifo_pos_wr
(
0
),
packet_off
(
0
)
{
:
top
(
top_
),
fifo_pos_rd
(
0
),
fifo_pos_wr
(
0
),
packet_off
(
0
)
for
(
size_t
i
=
0
;
i
<
FIFO_SIZE
;
i
++
)
fifo_lens
[
i
]
=
0
;
{
}
for
(
size_t
i
=
0
;
i
<
FIFO_SIZE
;
i
++
)
fifo_lens
[
i
]
=
0
;
void
packet_received
(
const
void
*
data
,
size_t
len
)
{
}
if
(
fifo_lens
[
fifo_pos_wr
]
!=
0
)
{
std
::
cerr
<<
"EthernetRx: dropping packet"
<<
std
::
endl
;
void
packet_received
(
const
void
*
data
,
size_t
len
)
return
;
{
}
if
(
fifo_lens
[
fifo_pos_wr
]
!=
0
)
{
std
::
cerr
<<
"EthernetRx: dropping packet"
<<
std
::
endl
;
return
;
}
memcpy
(
fifo_bufs
[
fifo_pos_wr
],
data
,
len
);
memcpy
(
fifo_bufs
[
fifo_pos_wr
],
data
,
len
);
fifo_lens
[
fifo_pos_wr
]
=
len
;
fifo_lens
[
fifo_pos_wr
]
=
len
;
#ifdef ETH_DEBUG
#ifdef ETH_DEBUG
std
::
cout
<<
main_time
<<
" rx into "
<<
fifo_pos_wr
<<
std
::
endl
;
std
::
cout
<<
main_time
<<
" rx into "
<<
fifo_pos_wr
<<
std
::
endl
;
std
::
cerr
<<
main_time
<<
" EthernetRx: packet len="
<<
std
::
hex
<<
std
::
cerr
<<
main_time
<<
" EthernetRx: packet len="
<<
std
::
hex
<<
len
len
<<
" "
;
<<
" "
;
for
(
size_t
i
=
0
;
i
<
len
;
i
++
)
{
for
(
size_t
i
=
0
;
i
<
len
;
i
++
)
{
std
::
cerr
<<
(
unsigned
)
fifo_bufs
[
fifo_pos_wr
][
i
]
<<
" "
;
std
::
cerr
<<
(
unsigned
)
fifo_bufs
[
fifo_pos_wr
][
i
]
<<
" "
;
}
}
std
::
cerr
<<
std
::
endl
;
std
::
cerr
<<
std
::
endl
;
#endif
#endif
fifo_pos_wr
=
(
fifo_pos_wr
+
1
)
%
FIFO_SIZE
;
fifo_pos_wr
=
(
fifo_pos_wr
+
1
)
%
FIFO_SIZE
;
}
}
void
step
()
void
step
()
{
{
if
(
fifo_lens
[
fifo_pos_rd
]
!=
0
)
{
if
(
fifo_lens
[
fifo_pos_rd
]
!=
0
)
{
// we have data to send
// we have data to send
if
(
packet_off
!=
0
&&
!
top
.
rx_axis_tready
)
{
if
(
packet_off
!=
0
&&
!
top
.
rx_axis_tready
)
{
// no ready signal, can't advance
// no ready signal, can't advance
std
::
cerr
<<
"eth rx: no ready"
<<
std
::
endl
;
std
::
cerr
<<
"eth rx: no ready"
<<
std
::
endl
;
}
else
if
(
packet_off
==
fifo_lens
[
fifo_pos_rd
])
{
}
else
if
(
packet_off
==
fifo_lens
[
fifo_pos_rd
])
{
// done with packet
// done with packet
#ifdef ETH_DEBUG
#ifdef ETH_DEBUG
std
::
cerr
<<
main_time
<<
" EthernetRx: finished packet"
<<
std
::
cerr
<<
main_time
<<
" EthernetRx: finished packet"
<<
std
::
endl
;
std
::
endl
;
#endif
#endif
top
.
rx_axis_tvalid
=
0
;
top
.
rx_axis_tvalid
=
0
;
top
.
rx_axis_tlast
=
0
;
top
.
rx_axis_tlast
=
0
;
packet_off
=
0
;
packet_off
=
0
;
fifo_lens
[
fifo_pos_rd
]
=
0
;
fifo_lens
[
fifo_pos_rd
]
=
0
;
fifo_pos_rd
=
(
fifo_pos_rd
+
1
)
%
FIFO_SIZE
;
fifo_pos_rd
=
(
fifo_pos_rd
+
1
)
%
FIFO_SIZE
;
}
else
{
}
else
{
// put out more packet data
// put out more packet data
#ifdef ETH_DEBUG
#ifdef ETH_DEBUG
std
::
cerr
<<
main_time
<<
" EthernetRx: push flit "
<<
std
::
cerr
<<
main_time
<<
" EthernetRx: push flit "
<<
packet_off
packet_off
<<
std
::
endl
;
<<
std
::
endl
;
if
(
packet_off
==
0
)
if
(
packet_off
==
0
)
std
::
cout
<<
"rx from "
<<
fifo_pos_rd
<<
std
::
endl
;
std
::
cout
<<
"rx from "
<<
fifo_pos_rd
<<
std
::
endl
;
#endif
#endif
top
.
rx_axis_tkeep
=
0
;
top
.
rx_axis_tkeep
=
0
;
top
.
rx_axis_tdata
=
0
;
top
.
rx_axis_tdata
=
0
;
size_t
i
;
size_t
i
;
for
(
i
=
0
;
i
<
8
&&
packet_off
<
fifo_lens
[
fifo_pos_rd
];
for
(
i
=
0
;
i
<
8
&&
packet_off
<
fifo_lens
[
fifo_pos_rd
];
i
++
)
{
i
++
)
{
top
.
rx_axis_tdata
|=
((
uint64_t
)
fifo_bufs
[
fifo_pos_rd
][
packet_off
])
top
.
rx_axis_tdata
|=
<<
(
i
*
8
);
((
uint64_t
)
fifo_bufs
[
fifo_pos_rd
][
packet_off
])
<<
top
.
rx_axis_tkeep
|=
(
1
<<
i
);
(
i
*
8
);
packet_off
++
;
top
.
rx_axis_tkeep
|=
(
1
<<
i
);
packet_off
++
;
}
top
.
rx_axis_tvalid
=
1
;
top
.
rx_axis_tlast
=
(
packet_off
==
fifo_lens
[
fifo_pos_rd
]);
}
// trace->dump(main_time);
}
else
{
// no data
top
.
rx_axis_tvalid
=
0
;
top
.
rx_axis_tlast
=
0
;
}
}
}
top
.
rx_axis_tvalid
=
1
;
top
.
rx_axis_tlast
=
(
packet_off
==
fifo_lens
[
fifo_pos_rd
]);
}
// trace->dump(main_time);
}
else
{
// no data
top
.
rx_axis_tvalid
=
0
;
top
.
rx_axis_tlast
=
0
;
}
}
};
};
static
void
n2d_recv
(
EthernetRx
&
rx
,
static
void
n2d_recv
(
EthernetRx
&
rx
,
volatile
struct
cosim_eth_proto_n2d_recv
*
recv
)
volatile
struct
cosim_eth_proto_n2d_recv
*
recv
)
{
{
rx
.
packet_received
((
const
void
*
)
recv
->
data
,
recv
->
len
);
rx
.
packet_received
((
const
void
*
)
recv
->
data
,
recv
->
len
);
}
}
static
void
poll_n2d
(
EthernetRx
&
rx
)
static
void
poll_n2d
(
EthernetRx
&
rx
)
{
{
volatile
union
cosim_eth_proto_n2d
*
msg
=
volatile
union
cosim_eth_proto_n2d
*
msg
=
nicif_n2d_poll
(
&
nsparams
,
main_time
);
nicif_n2d_poll
(
&
nsparams
,
main_time
);
uint8_t
t
;
uint8_t
t
;
if
(
msg
==
NULL
)
if
(
msg
==
NULL
)
return
;
return
;
t
=
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_N2D_MSG_MASK
;
t
=
msg
->
dummy
.
own_type
&
COSIM_ETH_PROTO_N2D_MSG_MASK
;
switch
(
t
)
{
switch
(
t
)
{
case
COSIM_ETH_PROTO_N2D_MSG_RECV
:
case
COSIM_ETH_PROTO_N2D_MSG_RECV
:
n2d_recv
(
rx
,
&
msg
->
recv
);
n2d_recv
(
rx
,
&
msg
->
recv
);
break
;
break
;
case
COSIM_ETH_PROTO_N2D_MSG_SYNC
:
case
COSIM_ETH_PROTO_N2D_MSG_SYNC
:
break
;
break
;
default:
default:
std
::
cerr
<<
"poll_n2d: unsupported type="
<<
t
<<
std
::
endl
;
std
::
cerr
<<
"poll_n2d: unsupported type="
<<
t
<<
std
::
endl
;
}
}
nicif_n2d_done
(
msg
);
nicif_n2d_done
(
msg
);
nicif_n2d_next
();
nicif_n2d_next
();
}
}
#if 0
#if 0
...
@@ -903,272 +869,252 @@ class PCICoordinator {
...
@@ -903,272 +869,252 @@ class PCICoordinator {
};
};
#endif
#endif
void
pci_msi_issue
(
uint8_t
vec
)
void
pci_msi_issue
(
uint8_t
vec
)
{
{
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
union
cosim_pcie_proto_d2h
*
msg
=
d2h_alloc
();
volatile
struct
cosim_pcie_proto_d2h_interrupt
*
intr
;
volatile
struct
cosim_pcie_proto_d2h_interrupt
*
intr
;
#ifdef MSI_DEBUG
#ifdef MSI_DEBUG
std
::
cerr
<<
main_time
<<
" MSI interrupt vec="
<<
(
int
)
vec
<<
std
::
endl
;
std
::
cerr
<<
main_time
<<
" MSI interrupt vec="
<<
(
int
)
vec
<<
std
::
endl
;
#endif
#endif
intr
=
&
msg
->
interrupt
;
intr
=
&
msg
->
interrupt
;
intr
->
vector
=
vec
;
intr
->
vector
=
vec
;
intr
->
inttype
=
COSIM_PCIE_PROTO_INT_MSI
;
intr
->
inttype
=
COSIM_PCIE_PROTO_INT_MSI
;
// WMB();
// WMB();
intr
->
own_type
=
COSIM_PCIE_PROTO_D2H_MSG_INTERRUPT
|
intr
->
own_type
=
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
COSIM_PCIE_PROTO_D2H_MSG_INTERRUPT
|
COSIM_PCIE_PROTO_D2H_OWN_HOST
;
}
}
static
void
msi_step
(
Vinterface
&
top
,
PCICoordinator
&
coord
)
{
static
void
msi_step
(
Vinterface
&
top
,
PCICoordinator
&
coord
)
if
(
!
top
.
msi_irq
)
{
return
;
if
(
!
top
.
msi_irq
)
return
;
#ifdef MSI_DEBUG
#ifdef MSI_DEBUG
std
::
cerr
<<
main_time
<<
" msi_step: MSI interrupt raw vec="
<<
std
::
cerr
<<
main_time
(
int
)
top
.
msi_irq
<<
std
::
endl
;
<<
" msi_step: MSI interrupt raw vec="
<<
(
int
)
top
.
msi_irq
<<
std
::
endl
;
#endif
#endif
for
(
size_t
i
=
0
;
i
<
32
;
i
++
)
{
for
(
size_t
i
=
0
;
i
<
32
;
i
++
)
{
if
(
!
((
1ULL
<<
i
)
&
top
.
msi_irq
))
if
(
!
((
1ULL
<<
i
)
&
top
.
msi_irq
))
continue
;
continue
;
coord
.
msi_enqueue
(
i
);
coord
.
msi_enqueue
(
i
);
}
}
}
}
int
main
(
int
argc
,
char
*
argv
[])
int
main
(
int
argc
,
char
*
argv
[])
{
{
char
*
vargs
[
2
]
=
{
argv
[
0
],
NULL
};
char
*
vargs
[
2
]
=
{
argv
[
0
],
NULL
};
Verilated
::
commandArgs
(
1
,
vargs
);
Verilated
::
commandArgs
(
1
,
vargs
);
int
sync_mode
=
SYNC_MODES
;
int
sync_mode
=
SYNC_MODES
;
#ifdef TRACE_ENABLED
#ifdef TRACE_ENABLED
Verilated
::
traceEverOn
(
true
);
Verilated
::
traceEverOn
(
true
);
#endif
#endif
if
(
argc
<
4
&&
argc
>
10
)
{
if
(
argc
<
4
&&
argc
>
10
)
{
fprintf
(
stderr
,
"Usage: corundum_verilator PCI-SOCKET ETH-SOCKET "
fprintf
(
stderr
,
"SHM [SYNC-MODE] [START-TICK] [SYNC-PERIOD] [PCI-LATENCY]
"
"Usage: corundum_verilator PCI-SOCKET ETH-SOCKET
"
"[ETH-LATENCY] [CLOCK-FREQ-MHZ]
\n
"
);
"SHM [SYNC-MODE] [START-TICK] [SYNC-PERIOD] [PCI-LATENCY] "
return
EXIT_FAILURE
;
"[ETH-LATENCY] [CLOCK-FREQ-MHZ]
\n
"
)
;
}
return
EXIT_FAILURE
;
if
(
argc
>=
5
)
}
sync_mode
=
strtol
(
argv
[
4
],
NULL
,
0
);
if
(
argc
>=
5
)
if
(
argc
>=
6
)
sync_mode
=
strtol
(
argv
[
4
],
NULL
,
0
);
main_time
=
strtoull
(
argv
[
5
],
NULL
,
0
);
if
(
argc
>=
6
)
if
(
argc
>=
7
)
main_time
=
strtoull
(
argv
[
5
],
NULL
,
0
);
sync_period
=
strtoull
(
argv
[
6
],
NULL
,
0
)
*
1000ULL
;
if
(
argc
>=
7
)
if
(
argc
>=
8
)
sync_period
=
strtoull
(
argv
[
6
],
NULL
,
0
)
*
1000ULL
;
pci_latency
=
strtoull
(
argv
[
7
],
NULL
,
0
)
*
1000ULL
;
if
(
argc
>=
8
)
if
(
argc
>=
9
)
pci_latency
=
strtoull
(
argv
[
7
],
NULL
,
0
)
*
1000ULL
;
eth_latency
=
strtoull
(
argv
[
8
],
NULL
,
0
)
*
1000ULL
;
if
(
argc
>=
9
)
if
(
argc
>=
10
)
eth_latency
=
strtoull
(
argv
[
8
],
NULL
,
0
)
*
1000ULL
;
clock_period
=
1000000ULL
/
strtoull
(
argv
[
9
],
NULL
,
0
)
;
if
(
argc
>=
1
0
)
clock_period
=
1000000ULL
/
strtoull
(
argv
[
9
],
NULL
,
0
);
struct
cosim_pcie_proto_dev_intro
di
;
memset
(
&
di
,
0
,
sizeof
(
di
))
;
struct
cosim_pcie_proto_dev_intro
di
;
memset
(
&
di
,
0
,
sizeof
(
di
));
di
.
bars
[
0
].
len
=
1
<<
24
;
di
.
bars
[
0
].
flags
=
COSIM_PCIE_PROTO_BAR_6
4
;
di
.
bars
[
0
].
len
=
1
<<
2
4
;
di
.
bars
[
0
].
flags
=
COSIM_PCIE_PROTO_BAR_64
;
di
.
pci_vendor_id
=
0x5543
;
di
.
pci_
device
_id
=
0x
1001
;
di
.
pci_
vendor
_id
=
0x
5543
;
di
.
pci_
class
=
0x
02
;
di
.
pci_
device_id
=
0x
1001
;
di
.
pci_
sub
class
=
0x0
0
;
di
.
pci_class
=
0x0
2
;
di
.
pci_
revision
=
0x00
;
di
.
pci_
subclass
=
0x00
;
di
.
pci_
msi_nvecs
=
32
;
di
.
pci_
revision
=
0x00
;
di
.
pci_msi_nvecs
=
32
;
nsparams
.
sync_pci
=
1
;
nsparams
.
sync_
eth
=
1
;
nsparams
.
sync_
pci
=
1
;
nsparams
.
pci_socket_path
=
argv
[
1
]
;
nsparams
.
sync_eth
=
1
;
nsparams
.
eth
_socket_path
=
argv
[
2
];
nsparams
.
pci
_socket_path
=
argv
[
1
];
nsparams
.
shm
_path
=
argv
[
3
];
nsparams
.
eth_socket
_path
=
argv
[
2
];
nsparams
.
pci_latency
=
pci_latency
;
nsparams
.
shm_path
=
argv
[
3
]
;
nsparams
.
eth
_latency
=
eth
_latency
;
nsparams
.
pci
_latency
=
pci
_latency
;
nsparams
.
sync_delay
=
sync_period
;
nsparams
.
eth_latency
=
eth_latency
;
assert
(
sync_mode
==
SYNC_MODES
||
sync_mode
==
SYNC_BARRIER
)
;
nsparams
.
sync_delay
=
sync_period
;
nsparams
.
sync_mode
=
sync_mode
;
assert
(
sync_mode
==
SYNC_MODES
||
sync_mode
==
SYNC_BARRIER
)
;
nsparams
.
sync_mode
=
sync_mode
;
if
(
nicsim_init
(
&
nsparams
,
&
di
))
{
return
EXIT_FAILURE
;
if
(
nicsim_init
(
&
nsparams
,
&
di
))
{
}
return
EXIT_FAILURE
;
std
::
cout
<<
"sync_pci="
<<
nsparams
.
sync_pci
<<
}
"
sync_
eth
="
<<
nsparams
.
sync_
eth
<<
std
::
endl
;
std
::
cout
<<
"
sync_
pci
="
<<
nsparams
.
sync_
pci
<<
" sync_eth="
<<
nsparams
.
sync_eth
<<
std
::
endl
;
signal
(
SIGINT
,
sigint_handler
);
signal
(
SIG
USR1
,
sig
usr1
_handler
);
signal
(
SIG
INT
,
sig
int
_handler
);
signal
(
SIGUSR1
,
sigusr1_handler
);
Vinterface
*
top
=
new
Vinterface
;
Vinterface
*
top
=
new
Vinterface
;
#ifdef TRACE_ENABLED
#ifdef TRACE_ENABLED
trace
=
new
VerilatedVcdC
;
trace
=
new
VerilatedVcdC
;
top
->
trace
(
trace
,
99
);
top
->
trace
(
trace
,
99
);
trace
->
open
(
"debug.vcd"
);
trace
->
open
(
"debug.vcd"
);
#endif
#endif
MemWritePort
p_mem_write_ctrl_dma
(
MemWritePort
p_mem_write_ctrl_dma
(
top
->
ctrl_dma_ram_wr_cmd_sel
,
top
->
ctrl_dma_ram_wr_cmd_sel
,
top
->
ctrl_dma_ram_wr_cmd_be
,
top
->
ctrl_dma_ram_wr_cmd_be
,
top
->
ctrl_dma_ram_wr_cmd_addr
,
top
->
ctrl_dma_ram_wr_cmd_data
,
top
->
ctrl_dma_ram_wr_cmd_addr
,
top
->
ctrl_dma_ram_wr_cmd_valid
,
top
->
ctrl_dma_ram_wr_cmd_ready
);
top
->
ctrl_dma_ram_wr_cmd_data
,
MemReadPort
p_mem_read_ctrl_dma
(
top
->
ctrl_dma_ram_wr_cmd_valid
,
top
->
ctrl_dma_ram_rd_cmd_sel
,
top
->
ctrl_dma_ram_rd_cmd_addr
,
top
->
ctrl_dma_ram_wr_cmd_ready
);
top
->
ctrl_dma_ram_rd_cmd_valid
,
top
->
ctrl_dma_ram_rd_resp_ready
,
MemReadPort
p_mem_read_ctrl_dma
(
top
->
ctrl_dma_ram_rd_resp_data
,
top
->
ctrl_dma_ram_rd_cmd_ready
,
top
->
ctrl_dma_ram_rd_cmd_sel
,
top
->
ctrl_dma_ram_rd_resp_valid
);
top
->
ctrl_dma_ram_rd_cmd_addr
,
MemWritePort
p_mem_write_data_dma
(
top
->
ctrl_dma_ram_rd_cmd_valid
,
top
->
data_dma_ram_wr_cmd_sel
,
top
->
data_dma_ram_wr_cmd_be
,
top
->
ctrl_dma_ram_rd_resp_ready
,
top
->
data_dma_ram_wr_cmd_addr
,
top
->
data_dma_ram_wr_cmd_data
,
top
->
ctrl_dma_ram_rd_resp_data
,
top
->
data_dma_ram_wr_cmd_valid
,
top
->
data_dma_ram_wr_cmd_ready
);
top
->
ctrl_dma_ram_rd_cmd_ready
,
MemReadPort
p_mem_read_data_dma
(
top
->
ctrl_dma_ram_rd_resp_valid
);
top
->
data_dma_ram_rd_cmd_sel
,
top
->
data_dma_ram_rd_cmd_addr
,
MemWritePort
p_mem_write_data_dma
(
top
->
data_dma_ram_rd_cmd_valid
,
top
->
data_dma_ram_rd_resp_ready
,
top
->
data_dma_ram_wr_cmd_sel
,
top
->
data_dma_ram_rd_resp_data
,
top
->
data_dma_ram_rd_cmd_ready
,
top
->
data_dma_ram_wr_cmd_be
,
top
->
data_dma_ram_rd_resp_valid
);
top
->
data_dma_ram_wr_cmd_addr
,
top
->
data_dma_ram_wr_cmd_data
,
DMAPorts
p_dma_read_ctrl
(
top
->
m_axis_ctrl_dma_read_desc_dma_addr
,
top
->
data_dma_ram_wr_cmd_valid
,
top
->
m_axis_ctrl_dma_read_desc_ram_sel
,
top
->
data_dma_ram_wr_cmd_ready
);
top
->
m_axis_ctrl_dma_read_desc_ram_addr
,
MemReadPort
p_mem_read_data_dma
(
top
->
m_axis_ctrl_dma_read_desc_len
,
top
->
data_dma_ram_rd_cmd_sel
,
top
->
m_axis_ctrl_dma_read_desc_tag
,
top
->
data_dma_ram_rd_cmd_addr
,
top
->
m_axis_ctrl_dma_read_desc_valid
,
top
->
data_dma_ram_rd_cmd_valid
,
top
->
m_axis_ctrl_dma_read_desc_ready
,
top
->
data_dma_ram_rd_resp_ready
,
top
->
s_axis_ctrl_dma_read_desc_status_tag
,
top
->
data_dma_ram_rd_resp_data
,
top
->
s_axis_ctrl_dma_read_desc_status_valid
);
top
->
data_dma_ram_rd_cmd_ready
,
DMAPorts
p_dma_write_ctrl
(
top
->
m_axis_ctrl_dma_write_desc_dma_addr
,
top
->
data_dma_ram_rd_resp_valid
);
top
->
m_axis_ctrl_dma_write_desc_ram_sel
,
top
->
m_axis_ctrl_dma_write_desc_ram_addr
,
DMAPorts
p_dma_read_ctrl
(
top
->
m_axis_ctrl_dma_write_desc_len
,
top
->
m_axis_ctrl_dma_read_desc_dma_addr
,
top
->
m_axis_ctrl_dma_write_desc_tag
,
top
->
m_axis_ctrl_dma_read_desc_ram_sel
,
top
->
m_axis_ctrl_dma_write_desc_valid
,
top
->
m_axis_ctrl_dma_read_desc_ram_addr
,
top
->
m_axis_ctrl_dma_write_desc_ready
,
top
->
m_axis_ctrl_dma_read_desc_len
,
top
->
s_axis_ctrl_dma_write_desc_status_tag
,
top
->
m_axis_ctrl_dma_read_desc_tag
,
top
->
s_axis_ctrl_dma_write_desc_status_valid
);
top
->
m_axis_ctrl_dma_read_desc_valid
,
DMAPorts
p_dma_read_data
(
top
->
m_axis_data_dma_read_desc_dma_addr
,
top
->
m_axis_ctrl_dma_read_desc_ready
,
top
->
m_axis_data_dma_read_desc_ram_sel
,
top
->
s_axis_ctrl_dma_read_desc_status_tag
,
top
->
m_axis_data_dma_read_desc_ram_addr
,
top
->
s_axis_ctrl_dma_read_desc_status_valid
);
top
->
m_axis_data_dma_read_desc_len
,
DMAPorts
p_dma_write_ctrl
(
top
->
m_axis_data_dma_read_desc_tag
,
top
->
m_axis_ctrl_dma_write_desc_dma_addr
,
top
->
m_axis_data_dma_read_desc_valid
,
top
->
m_axis_ctrl_dma_write_desc_ram_sel
,
top
->
m_axis_data_dma_read_desc_ready
,
top
->
m_axis_ctrl_dma_write_desc_ram_addr
,
top
->
s_axis_data_dma_read_desc_status_tag
,
top
->
m_axis_ctrl_dma_write_desc_len
,
top
->
s_axis_data_dma_read_desc_status_valid
);
top
->
m_axis_ctrl_dma_write_desc_tag
,
DMAPorts
p_dma_write_data
(
top
->
m_axis_data_dma_write_desc_dma_addr
,
top
->
m_axis_ctrl_dma_write_desc_valid
,
top
->
m_axis_data_dma_write_desc_ram_sel
,
top
->
m_axis_ctrl_dma_write_desc_ready
,
top
->
m_axis_data_dma_write_desc_ram_addr
,
top
->
s_axis_ctrl_dma_write_desc_status_tag
,
top
->
m_axis_data_dma_write_desc_len
,
top
->
s_axis_ctrl_dma_write_desc_status_valid
);
top
->
m_axis_data_dma_write_desc_tag
,
DMAPorts
p_dma_read_data
(
top
->
m_axis_data_dma_write_desc_valid
,
top
->
m_axis_data_dma_read_desc_dma_addr
,
top
->
m_axis_data_dma_write_desc_ready
,
top
->
m_axis_data_dma_read_desc_ram_sel
,
top
->
s_axis_data_dma_write_desc_status_tag
,
top
->
m_axis_data_dma_read_desc_ram_addr
,
top
->
s_axis_data_dma_write_desc_status_valid
);
top
->
m_axis_data_dma_read_desc_len
,
top
->
m_axis_data_dma_read_desc_tag
,
// PCICoordinator pci_coord;
top
->
m_axis_data_dma_read_desc_valid
,
PCICoordinator
pci_coord_mmio
;
top
->
m_axis_data_dma_read_desc_ready
,
PCICoordinator
pci_coord_msi
;
top
->
s_axis_data_dma_read_desc_status_tag
,
PCICoordinator
pci_coord_rc
;
top
->
s_axis_data_dma_read_desc_status_valid
);
PCICoordinator
pci_coord_wc
;
DMAPorts
p_dma_write_data
(
PCICoordinator
pci_coord_rd
;
top
->
m_axis_data_dma_write_desc_dma_addr
,
PCICoordinator
pci_coord_wd
;
top
->
m_axis_data_dma_write_desc_ram_sel
,
MMIOInterface
mmio
(
*
top
,
pci_coord_mmio
);
top
->
m_axis_data_dma_write_desc_ram_addr
,
top
->
m_axis_data_dma_write_desc_len
,
MemWriter
mem_control_writer
(
p_mem_write_ctrl_dma
);
top
->
m_axis_data_dma_write_desc_tag
,
MemReader
mem_control_reader
(
p_mem_read_ctrl_dma
);
top
->
m_axis_data_dma_write_desc_valid
,
MemWriter
mem_data_writer
(
p_mem_write_data_dma
);
top
->
m_axis_data_dma_write_desc_ready
,
MemReader
mem_data_reader
(
p_mem_read_data_dma
);
top
->
s_axis_data_dma_write_desc_status_tag
,
top
->
s_axis_data_dma_write_desc_status_valid
);
DMAReader
dma_read_ctrl
(
"read ctrl"
,
p_dma_read_ctrl
,
mem_control_writer
,
pci_coord_rc
);
// PCICoordinator pci_coord;
DMAWriter
dma_write_ctrl
(
"write ctrl"
,
p_dma_write_ctrl
,
mem_control_reader
,
PCICoordinator
pci_coord_mmio
;
pci_coord_wc
);
PCICoordinator
pci_coord_msi
;
DMAReader
dma_read_data
(
"read data"
,
p_dma_read_data
,
mem_data_writer
,
PCICoordinator
pci_coord_rc
;
pci_coord_rd
);
PCICoordinator
pci_coord_wc
;
DMAWriter
dma_write_data
(
"write data"
,
p_dma_write_data
,
mem_data_reader
,
PCICoordinator
pci_coord_rd
;
pci_coord_wd
);
PCICoordinator
pci_coord_wd
;
MMIOInterface
mmio
(
*
top
,
pci_coord_mmio
);
EthernetTx
tx
(
*
top
);
EthernetRx
rx
(
*
top
);
MemWriter
mem_control_writer
(
p_mem_write_ctrl_dma
);
MemReader
mem_control_reader
(
p_mem_read_ctrl_dma
);
reset_inputs
(
top
);
MemWriter
mem_data_writer
(
p_mem_write_data_dma
);
top
->
rst
=
1
;
MemReader
mem_data_reader
(
p_mem_read_data_dma
);
top
->
eval
();
DMAReader
dma_read_ctrl
(
"read ctrl"
,
p_dma_read_ctrl
,
mem_control_writer
,
/* raising edge */
pci_coord_rc
);
top
->
clk
=
!
top
->
clk
;
DMAWriter
dma_write_ctrl
(
"write ctrl"
,
p_dma_write_ctrl
,
mem_control_reader
,
top
->
eval
();
pci_coord_wc
);
DMAReader
dma_read_data
(
"read data"
,
p_dma_read_data
,
mem_data_writer
,
top
->
rst
=
0
;
pci_coord_rd
);
DMAWriter
dma_write_data
(
"write data"
,
p_dma_write_data
,
mem_data_reader
,
while
(
!
exiting
)
{
pci_coord_wd
);
while
(
nicsim_sync
(
&
nsparams
,
main_time
))
{
std
::
cerr
<<
"warn: nicsim_sync failed (t="
<<
main_time
<<
")"
EthernetTx
tx
(
*
top
);
<<
std
::
endl
;
EthernetRx
rx
(
*
top
);
}
nicsim_advance_epoch
(
&
nsparams
,
main_time
);
reset_inputs
(
top
);
top
->
rst
=
1
;
top
->
eval
();
/* raising edge */
do
{
poll_h2d
(
mmio
);
poll_n2d
(
rx
);
}
while
((
nsparams
.
sync_pci
||
nsparams
.
sync_eth
)
&&
nicsim_next_timestamp
(
&
nsparams
)
<=
main_time
&&
!
exiting
);
/* falling edge */
top
->
clk
=
!
top
->
clk
;
top
->
clk
=
!
top
->
clk
;
main_time
+=
clock_period
/
2
;
top
->
eval
();
top
->
eval
();
top
->
rst
=
0
;
mmio
.
step
();
while
(
!
exiting
)
{
while
(
nicsim_sync
(
&
nsparams
,
main_time
))
{
std
::
cerr
<<
"warn: nicsim_sync failed (t="
<<
main_time
<<
")"
<<
std
::
endl
;
}
nicsim_advance_epoch
(
&
nsparams
,
main_time
);
do
{
poll_h2d
(
mmio
);
poll_n2d
(
rx
);
}
while
((
nsparams
.
sync_pci
||
nsparams
.
sync_eth
)
&&
nicsim_next_timestamp
(
&
nsparams
)
<=
main_time
&&
!
exiting
);
/* falling edge */
top
->
clk
=
!
top
->
clk
;
main_time
+=
clock_period
/
2
;
top
->
eval
();
mmio
.
step
();
dma_read_ctrl
.
step
();
dma_write_ctrl
.
step
();
dma_read_data
.
step
();
dma_write_data
.
step
();
dma_read_ctrl
.
step
();
mem_control_writer
.
step
();
dma_write_ctrl
.
step
();
mem_control_reader
.
step
();
dma_read_data
.
step
();
mem_data_writer
.
step
();
dma_write_data
.
step
();
mem_data_reader
.
step
();
mem_control_writer
.
step
();
tx
.
step
();
mem_control_reader
.
step
();
rx
.
step
();
mem_data_writer
.
step
();
mem_data_reader
.
step
();
tx
.
step
();
msi_step
(
*
top
,
pci_coord_msi
);
rx
.
step
();
msi_step
(
*
top
,
pci_coord_msi
);
/* raising edge */
top
->
clk
=
!
top
->
clk
;
/* raising edge */
main_time
+=
clock_period
/
2
;
top
->
clk
=
!
top
->
clk
;
main_time
+=
clock_period
/
2
;
// top->s_axis_tx_ptp_ts_96 = main_time;
// top->s_axis_tx_ptp_ts_96 = main_time;
top
->
s_axis_tx_ptp_ts_valid
=
1
;
top
->
s_axis_tx_ptp_ts_valid
=
1
;
top
->
s_axis_rx_ptp_ts_valid
=
1
;
top
->
s_axis_rx_ptp_ts_valid
=
1
;
top
->
eval
();
top
->
eval
();
}
}
report_outputs
(
top
);
report_outputs
(
top
);
std
::
cout
<<
std
::
endl
<<
std
::
endl
<<
"main_time:"
<<
main_time
<<
std
::
cout
<<
std
::
endl
<<
std
::
endl
<<
"main_time:"
<<
main_time
<<
std
::
endl
;
std
::
endl
;
#ifdef TRACE_ENABLED
#ifdef TRACE_ENABLED
trace
->
dump
(
main_time
+
1
);
trace
->
dump
(
main_time
+
1
);
trace
->
close
();
trace
->
close
();
#endif
#endif
top
->
final
();
top
->
final
();
delete
top
;
delete
top
;
return
0
;
return
0
;
}
}
sims/nic/corundum/dma.cc
View file @
d4666c97
...
@@ -22,126 +22,117 @@
...
@@ -22,126 +22,117 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include "sims/nic/corundum/dma.h"
#include <iostream>
#include <iostream>
#include "sims/nic/corundum/debug.h"
#include "sims/nic/corundum/corundum.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"
#include "sims/nic/corundum/mem.h"
void
DMAReader
::
step
()
{
void
DMAReader
::
step
()
p
.
dma_ready
=
1
;
{
if
(
p
.
dma_valid
)
{
p
.
dma_ready
=
1
;
DMAOp
*
op
=
new
DMAOp
;
if
(
p
.
dma_valid
)
{
op
->
engine
=
this
;
DMAOp
*
op
=
new
DMAOp
;
op
->
dma_addr
=
p
.
dma_addr
;
op
->
engine
=
this
;
op
->
ram_sel
=
p
.
dma_ram_sel
;
op
->
dma_addr
=
p
.
dma_addr
;
op
->
ram_addr
=
p
.
dma_ram_addr
;
op
->
ram_sel
=
p
.
dma_ram_sel
;
op
->
len
=
p
.
dma_len
;
op
->
ram_addr
=
p
.
dma_ram_addr
;
op
->
tag
=
p
.
dma_tag
;
op
->
len
=
p
.
dma_len
;
op
->
write
=
false
;
op
->
tag
=
p
.
dma_tag
;
pending
.
insert
(
op
);
op
->
write
=
false
;
pending
.
insert
(
op
);
#ifdef DMA_DEBUG
#ifdef DMA_DEBUG
std
::
cout
<<
main_time
<<
" dma["
<<
label
<<
"] op "
<<
std
::
hex
<<
std
::
cout
<<
main_time
<<
" dma["
<<
label
<<
"] op "
<<
std
::
hex
op
->
dma_addr
<<
" -> "
<<
op
->
ram_sel
<<
":"
<<
op
->
ram_addr
<<
<<
op
->
dma_addr
<<
" -> "
<<
op
->
ram_sel
<<
":"
<<
op
->
ram_addr
" len="
<<
op
->
len
<<
" tag="
<<
(
int
)
op
->
tag
<<
std
::
endl
;
<<
" len="
<<
op
->
len
<<
" tag="
<<
(
int
)
op
->
tag
<<
std
::
endl
;
#endif
#endif
coord
.
dma_register
(
op
,
true
);
coord
.
dma_register
(
op
,
true
);
}
}
p
.
dma_status_valid
=
0
;
p
.
dma_status_valid
=
0
;
if
(
!
completed
.
empty
())
{
if
(
!
completed
.
empty
())
{
DMAOp
*
op
=
completed
.
front
();
DMAOp
*
op
=
completed
.
front
();
completed
.
pop_front
();
completed
.
pop_front
();
// std::cout << "dma[" << label << "] status complete " << op->dma_addr
// std::cout << "dma[" << label << "] status complete " << op->dma_addr
// << std::endl;
// << std::endl;
p
.
dma_status_valid
=
1
;
p
.
dma_status_valid
=
1
;
p
.
dma_status_tag
=
op
->
tag
;
p
.
dma_status_tag
=
op
->
tag
;
pending
.
erase
(
op
);
pending
.
erase
(
op
);
delete
op
;
delete
op
;
}
}
}
}
void
DMAReader
::
pci_op_complete
(
DMAOp
*
op
)
void
DMAReader
::
pci_op_complete
(
DMAOp
*
op
)
{
{
mw
.
op_issue
(
op
);
mw
.
op_issue
(
op
);
}
}
void
DMAReader
::
mem_op_complete
(
DMAOp
*
op
)
void
DMAReader
::
mem_op_complete
(
DMAOp
*
op
)
{
{
completed
.
push_back
(
op
);
completed
.
push_back
(
op
);
// std::cout << "dma[" << label << "] mem complete " << op->dma_addr <<
// std::cout << "dma[" << label << "] mem complete " << op->dma_addr <<
// std::endl;
// std::endl;
}
}
void
DMAWriter
::
step
()
{
p
.
dma_ready
=
1
;
void
DMAWriter
::
step
()
if
(
p
.
dma_valid
)
{
{
DMAOp
*
op
=
new
DMAOp
;
p
.
dma_ready
=
1
;
op
->
engine
=
this
;
if
(
p
.
dma_valid
)
{
op
->
dma_addr
=
p
.
dma_addr
;
DMAOp
*
op
=
new
DMAOp
;
op
->
ram_sel
=
p
.
dma_ram_sel
;
op
->
engine
=
this
;
op
->
ram_addr
=
p
.
dma_ram_addr
;
op
->
dma_addr
=
p
.
dma_addr
;
op
->
len
=
p
.
dma_len
;
op
->
ram_sel
=
p
.
dma_ram_sel
;
op
->
tag
=
p
.
dma_tag
;
op
->
ram_addr
=
p
.
dma_ram_addr
;
op
->
write
=
true
;
op
->
len
=
p
.
dma_len
;
pending
.
insert
(
op
);
op
->
tag
=
p
.
dma_tag
;
op
->
write
=
true
;
pending
.
insert
(
op
);
#ifdef DMA_DEBUG
#ifdef DMA_DEBUG
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] op "
<<
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] op "
<<
std
::
hex
std
::
hex
<<
op
->
dma_addr
<<
" -> "
<<
op
->
ram_sel
<<
":"
<<
<<
op
->
dma_addr
<<
" -> "
<<
op
->
ram_sel
<<
":"
<<
op
->
ram_addr
op
->
ram_addr
<<
" len="
<<
op
->
len
<<
" tag="
<<
(
int
)
op
->
tag
<<
" len="
<<
op
->
len
<<
" tag="
<<
(
int
)
op
->
tag
<<
std
::
endl
;
<<
std
::
endl
;
#endif
#endif
coord
.
dma_register
(
op
,
false
);
coord
.
dma_register
(
op
,
false
);
mr
.
op_issue
(
op
);
mr
.
op_issue
(
op
);
}
}
p
.
dma_status_valid
=
0
;
p
.
dma_status_valid
=
0
;
if
(
!
completed
.
empty
())
{
if
(
!
completed
.
empty
())
{
DMAOp
*
op
=
completed
.
front
();
DMAOp
*
op
=
completed
.
front
();
completed
.
pop_front
();
completed
.
pop_front
();
#ifdef DMA_DEBUG
#ifdef DMA_DEBUG
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] status complete "
"] status complete "
<<
op
->
dma_addr
<<
std
::
endl
;
<<
op
->
dma_addr
<<
std
::
endl
;
#endif
#endif
p
.
dma_status_valid
=
1
;
p
.
dma_status_valid
=
1
;
p
.
dma_status_tag
=
op
->
tag
;
p
.
dma_status_tag
=
op
->
tag
;
pending
.
erase
(
op
);
pending
.
erase
(
op
);
// coord.msi_enqueue(0);
// coord.msi_enqueue(0);
delete
op
;
delete
op
;
}
}
}
}
void
DMAWriter
::
pci_op_complete
(
DMAOp
*
op
)
void
DMAWriter
::
pci_op_complete
(
DMAOp
*
op
)
{
{
#ifdef DMA_DEBUG
#ifdef DMA_DEBUG
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] pci complete "
<<
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] pci complete "
op
->
dma_addr
<<
std
::
endl
;
<<
op
->
dma_addr
<<
std
::
endl
;
#endif
#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
#ifdef DMA_DEBUG
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] mem complete "
<<
std
::
cout
<<
main_time
<<
" dma write ["
<<
label
<<
"] mem complete "
op
->
dma_addr
<<
": "
;
<<
op
->
dma_addr
<<
": "
;
for
(
size_t
i
=
0
;
i
<
op
->
len
;
i
++
)
for
(
size_t
i
=
0
;
i
<
op
->
len
;
i
++
)
std
::
cout
<<
(
unsigned
)
op
->
data
[
i
]
<<
" "
;
std
::
cout
<<
(
unsigned
)
op
->
data
[
i
]
<<
" "
;
std
::
cout
<<
std
::
endl
;
std
::
cout
<<
std
::
endl
;
#endif
#endif
coord
.
dma_mark_ready
(
op
);
coord
.
dma_mark_ready
(
op
);
}
}
sims/nic/corundum/dma.h
View file @
d4666c97
...
@@ -25,15 +25,14 @@
...
@@ -25,15 +25,14 @@
#ifndef DMA_H_
#ifndef DMA_H_
#define DMA_H_
#define DMA_H_
#include <set>
#include <deque>
#include <verilated.h>
#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/coord.h"
#include "sims/nic/corundum/debug.h"
#include "sims/nic/corundum/obj_dir/Vinterface.h"
#define MAX_DMA_LEN 2048
#define MAX_DMA_LEN 2048
...
@@ -42,95 +41,93 @@ class MemWriter;
...
@@ -42,95 +41,93 @@ class MemWriter;
class
MemReader
;
class
MemReader
;
struct
DMAPorts
{
struct
DMAPorts
{
/* inputs to DMA engine */
/* inputs to DMA engine */
vluint64_t
&
dma_addr
;
vluint64_t
&
dma_addr
;
vluint8_t
&
dma_ram_sel
;
vluint8_t
&
dma_ram_sel
;
vluint32_t
&
dma_ram_addr
;
vluint32_t
&
dma_ram_addr
;
vluint16_t
&
dma_len
;
vluint16_t
&
dma_len
;
vluint8_t
&
dma_tag
;
vluint8_t
&
dma_tag
;
vluint8_t
&
dma_valid
;
vluint8_t
&
dma_valid
;
/* outputs of DMA engine */
/* outputs of DMA engine */
vluint8_t
&
dma_ready
;
vluint8_t
&
dma_ready
;
vluint8_t
&
dma_status_tag
;
vluint8_t
&
dma_status_tag
;
vluint8_t
&
dma_status_valid
;
vluint8_t
&
dma_status_valid
;
DMAPorts
(
vluint64_t
&
dma_addr_
,
vluint8_t
&
dma_ram_sel_
,
DMAPorts
(
vluint64_t
&
dma_addr_
,
vluint8_t
&
dma_ram_sel_
,
vluint32_t
&
dma_ram_addr_
,
vluint16_t
&
dma_len_
,
vluint8_t
&
dma_tag_
,
vluint32_t
&
dma_ram_addr_
,
vluint16_t
&
dma_len_
,
vluint8_t
&
dma_valid_
,
vluint8_t
&
dma_ready_
,
vluint8_t
&
dma_tag_
,
vluint8_t
&
dma_valid_
,
vluint8_t
&
dma_status_tag_
,
vluint8_t
&
dma_status_valid_
)
vluint8_t
&
dma_ready_
,
vluint8_t
&
dma_status_tag_
,
:
dma_addr
(
dma_addr_
),
vluint8_t
&
dma_status_valid_
)
dma_ram_sel
(
dma_ram_sel_
),
:
dma_addr
(
dma_addr_
),
dma_ram_sel
(
dma_ram_sel_
),
dma_ram_addr
(
dma_ram_addr_
),
dma_ram_addr
(
dma_ram_addr_
),
dma_len
(
dma_len_
),
dma_len
(
dma_len_
),
dma_tag
(
dma_tag_
),
dma_valid
(
dma_valid_
),
dma_tag
(
dma_tag_
),
dma_ready
(
dma_ready_
),
dma_status_tag
(
dma_status_tag_
),
dma_valid
(
dma_valid_
),
dma_status_valid
(
dma_status_valid_
)
dma_ready
(
dma_ready_
),
{
dma_status_tag
(
dma_status_tag_
),
}
dma_status_valid
(
dma_status_valid_
)
{
}
};
};
struct
DMAOp
{
struct
DMAOp
{
DMAEngine
*
engine
;
DMAEngine
*
engine
;
uint64_t
dma_addr
;
uint64_t
dma_addr
;
size_t
len
;
size_t
len
;
uint64_t
ram_addr
;
uint64_t
ram_addr
;
bool
write
;
bool
write
;
uint8_t
ram_sel
;
uint8_t
ram_sel
;
uint8_t
tag
;
uint8_t
tag
;
uint8_t
data
[
MAX_DMA_LEN
];
uint8_t
data
[
MAX_DMA_LEN
];
};
};
class
DMAEngine
{
class
DMAEngine
{
protected:
protected:
DMAPorts
&
p
;
DMAPorts
&
p
;
PCICoordinator
&
coord
;
PCICoordinator
&
coord
;
DMAEngine
(
DMAPorts
&
p_
,
PCICoordinator
&
coord_
)
DMAEngine
(
DMAPorts
&
p_
,
PCICoordinator
&
coord_
)
:
p
(
p_
),
coord
(
coord_
)
{
:
p
(
p_
),
coord
(
coord_
)
{
}
}
public:
public:
virtual
void
pci_op_complete
(
DMAOp
*
op
)
=
0
;
virtual
void
pci_op_complete
(
DMAOp
*
op
)
=
0
;
virtual
void
mem_op_complete
(
DMAOp
*
op
)
=
0
;
virtual
void
mem_op_complete
(
DMAOp
*
op
)
=
0
;
};
};
class
DMAReader
:
public
DMAEngine
{
class
DMAReader
:
public
DMAEngine
{
protected:
protected:
std
::
set
<
DMAOp
*>
pending
;
std
::
set
<
DMAOp
*>
pending
;
std
::
deque
<
DMAOp
*>
completed
;
std
::
deque
<
DMAOp
*>
completed
;
const
char
*
label
;
const
char
*
label
;
MemWriter
&
mw
;
MemWriter
&
mw
;
public:
public:
DMAReader
(
const
char
*
label_
,
DMAPorts
&
p_
,
MemWriter
&
mw_
,
DMAReader
(
const
char
*
label_
,
DMAPorts
&
p_
,
MemWriter
&
mw_
,
PCICoordinator
&
coord_
)
PCICoordinator
&
coord_
)
:
DMAEngine
(
p_
,
coord_
),
label
(
label_
),
mw
(
mw_
)
:
DMAEngine
(
p_
,
coord_
),
label
(
label_
),
mw
(
mw_
)
{
{
}
}
virtual
void
pci_op_complete
(
DMAOp
*
op
);
virtual
void
pci_op_complete
(
DMAOp
*
op
);
virtual
void
mem_op_complete
(
DMAOp
*
op
);
virtual
void
mem_op_complete
(
DMAOp
*
op
);
void
step
();
void
step
();
};
};
class
DMAWriter
:
public
DMAEngine
{
class
DMAWriter
:
public
DMAEngine
{
protected:
protected:
std
::
set
<
DMAOp
*>
pending
;
std
::
set
<
DMAOp
*>
pending
;
std
::
deque
<
DMAOp
*>
completed
;
std
::
deque
<
DMAOp
*>
completed
;
const
char
*
label
;
const
char
*
label
;
MemReader
&
mr
;
MemReader
&
mr
;
public:
public:
DMAWriter
(
const
char
*
label_
,
DMAPorts
&
p_
,
MemReader
&
mr_
,
DMAWriter
(
const
char
*
label_
,
DMAPorts
&
p_
,
MemReader
&
mr_
,
PCICoordinator
&
coord_
)
PCICoordinator
&
coord_
)
:
DMAEngine
(
p_
,
coord_
),
label
(
label_
),
mr
(
mr_
)
:
DMAEngine
(
p_
,
coord_
),
label
(
label_
),
mr
(
mr_
)
{
{
}
}
virtual
void
pci_op_complete
(
DMAOp
*
op
);
virtual
void
pci_op_complete
(
DMAOp
*
op
);
virtual
void
mem_op_complete
(
DMAOp
*
op
);
virtual
void
mem_op_complete
(
DMAOp
*
op
);
void
step
();
void
step
();
};
};
#endif // DMA_H_
#endif // DMA_H_
sims/nic/corundum/mem.cc
View file @
d4666c97
...
@@ -22,10 +22,11 @@
...
@@ -22,10 +22,11 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include "sims/nic/corundum/mem.h"
#include <iostream>
#include <iostream>
#include "sims/nic/corundum/debug.h"
#include "sims/nic/corundum/debug.h"
#include "sims/nic/corundum/mem.h"
#include "sims/nic/corundum/dma.h"
#include "sims/nic/corundum/dma.h"
/*
/*
...
@@ -40,173 +41,163 @@
...
@@ -40,173 +41,163 @@
#define SEG_COUNT 8
#define SEG_COUNT 8
#define SEG_WIDTH (DATA_WIDTH / SEG_COUNT)
#define SEG_WIDTH (DATA_WIDTH / SEG_COUNT)
void
MemWriter
::
step
()
void
MemWriter
::
step
()
{
{
if
(
cur
&&
p
.
mem_ready
&&
((
p
.
mem_ready
&
p
.
mem_valid
)
==
p
.
mem_valid
))
{
if
(
cur
&&
p
.
mem_ready
&&
((
p
.
mem_ready
&
p
.
mem_valid
)
==
p
.
mem_valid
))
{
#ifdef MEM_DEBUG
#ifdef MEM_DEBUG
std
::
cerr
<<
"completed write to: "
<<
cur
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
"completed write to: "
<<
cur
->
ram_addr
<<
std
::
endl
;
#endif
#endif
p
.
mem_valid
=
0
;
p
.
mem_valid
=
0
;
p
.
mem_be
[
0
]
=
p
.
mem_be
[
1
]
=
p
.
mem_be
[
2
]
=
p
.
mem_be
[
3
]
=
0
;
p
.
mem_be
[
0
]
=
p
.
mem_be
[
1
]
=
p
.
mem_be
[
2
]
=
p
.
mem_be
[
3
]
=
0
;
if
(
cur_off
==
cur
->
len
)
{
if
(
cur_off
==
cur
->
len
)
{
/* operation is done */
/* operation is done */
pending
.
pop_front
();
pending
.
pop_front
();
cur
->
engine
->
mem_op_complete
(
cur
);
cur
->
engine
->
mem_op_complete
(
cur
);
cur_off
=
0
;
cur_off
=
0
;
}
else
{
}
else
{
/* operation is not done yet, we'll pick it back up */
/* operation is not done yet, we'll pick it back up */
}
}
cur
=
0
;
cur
=
0
;
}
else
if
(
!
cur
&&
!
pending
.
empty
())
{
}
else
if
(
!
cur
&&
!
pending
.
empty
())
{
cur
=
pending
.
front
();
cur
=
pending
.
front
();
#ifdef MEM_DEBUG
#ifdef MEM_DEBUG
std
::
cerr
<<
"issuing write to "
<<
cur
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
"issuing write to "
<<
cur
->
ram_addr
<<
std
::
endl
;
#endif
#endif
size_t
data_byte_width
=
DATA_WIDTH
/
8
;
size_t
data_byte_width
=
DATA_WIDTH
/
8
;
size_t
data_offset
=
(
cur
->
ram_addr
+
cur_off
)
%
data_byte_width
;
size_t
data_offset
=
(
cur
->
ram_addr
+
cur_off
)
%
data_byte_width
;
/* first reset everything */
/* first reset everything */
p
.
mem_sel
=
0
;
p
.
mem_sel
=
0
;
p
.
mem_addr
[
0
]
=
p
.
mem_addr
[
1
]
=
p
.
mem_addr
[
2
]
=
0
;
p
.
mem_addr
[
0
]
=
p
.
mem_addr
[
1
]
=
p
.
mem_addr
[
2
]
=
0
;
p
.
mem_be
[
0
]
=
p
.
mem_be
[
1
]
=
p
.
mem_be
[
2
]
=
p
.
mem_be
[
3
]
=
0
;
p
.
mem_be
[
0
]
=
p
.
mem_be
[
1
]
=
p
.
mem_be
[
2
]
=
p
.
mem_be
[
3
]
=
0
;
p
.
mem_valid
=
0
;
p
.
mem_valid
=
0
;
for
(
size_t
i
=
0
;
i
<
data_byte_width
/
4
;
i
++
)
for
(
size_t
i
=
0
;
i
<
data_byte_width
/
4
;
i
++
)
p
.
mem_data
[
i
]
=
0
;
p
.
mem_data
[
i
]
=
0
;
/* put data bytes in the right places */
size_t
off
=
data_offset
;
/* put data bytes in the right places */
size_t
cur_len
=
(
cur
->
len
-
cur_off
>
data_byte_width
-
data_offset
size_t
off
=
data_offset
;
?
data_byte_width
-
data_offset
size_t
cur_len
=
(
cur
->
len
-
cur_off
>
data_byte_width
-
data_offset
?
:
cur
->
len
-
cur_off
);
data_byte_width
-
data_offset
:
cur
->
len
-
cur_off
);
for
(
size_t
i
=
0
;
i
<
cur_len
;
i
++
,
off
++
)
{
for
(
size_t
i
=
0
;
i
<
cur_len
;
i
++
,
off
++
)
{
size_t
byte_off
=
off
%
4
;
size_t
byte_off
=
off
%
4
;
p
.
mem_data
[
off
/
4
]
|=
p
.
mem_data
[
off
/
4
]
|=
(((
uint32_t
)
cur
->
data
[
cur_off
+
i
])
<<
(((
uint32_t
)
cur
->
data
[
cur_off
+
i
])
<<
(
byte_off
*
8
));
(
byte_off
*
8
));
p
.
mem_be
[
off
/
32
]
|=
(
1
<<
(
off
%
32
));
p
.
mem_be
[
off
/
32
]
|=
(
1
<<
(
off
%
32
));
p
.
mem_valid
|=
(
1
<<
(
off
/
(
SEG_WIDTH
/
8
)));
p
.
mem_valid
|=
(
1
<<
(
off
/
(
SEG_WIDTH
/
8
)));
}
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
;
}
}
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
#ifdef MEM_DEBUG
std
::
cerr
<<
"enqueued write to "
<<
op
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
"enqueued write to "
<<
op
->
ram_addr
<<
std
::
endl
;
#endif
#endif
pending
.
push_back
(
op
);
pending
.
push_back
(
op
);
}
}
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
))
{
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
))
{
#ifdef MEM_DEBUG
#ifdef MEM_DEBUG
std
::
cerr
<<
"completed read from: "
<<
std
::
hex
<<
cur
->
ram_addr
<<
std
::
cerr
<<
"completed read from: "
<<
std
::
hex
<<
cur
->
ram_addr
std
::
endl
;
<<
std
::
endl
;
std
::
cerr
<<
" reval = "
<<
(
unsigned
)
p
.
mem_resvalid
<<
std
::
endl
;
std
::
cerr
<<
" reval = "
<<
(
unsigned
)
p
.
mem_resvalid
<<
std
::
endl
;
#endif
#endif
p
.
mem_valid
=
0
;
p
.
mem_valid
=
0
;
#ifdef MEM_DEBUG
#ifdef MEM_DEBUG
for
(
size_t
i
=
0
;
i
<
32
;
i
++
)
for
(
size_t
i
=
0
;
i
<
32
;
i
++
)
std
::
cerr
<<
" val = "
<<
p
.
mem_data
[
i
]
<<
std
::
endl
;
std
::
cerr
<<
" val = "
<<
p
.
mem_data
[
i
]
<<
std
::
endl
;
#endif
#endif
size_t
off
=
(
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
?
size_t
cur_len
=
data_byte_width
-
off
:
cur
->
len
-
cur_
off
);
(
cur
->
len
-
cur_off
>
data_byte_width
-
off
?
data_byte_width
-
off
for
(
size_t
i
=
0
;
i
<
cur
_
len
;
i
++
,
off
++
)
{
:
cur
->
len
-
cur_off
);
size_t
byte_off
=
(
off
%
4
);
for
(
size_t
i
=
0
;
i
<
cur_len
;
i
++
,
off
++
)
{
cur
->
data
[
cur_off
+
i
]
=
(
p
.
mem_data
[
off
/
4
]
>>
(
byte_off
*
8
))
&
size_t
byte_off
=
(
off
%
4
);
0xff
;
cur
->
data
[
cur_off
+
i
]
=
(
p
.
mem_data
[
off
/
4
]
>>
(
byte_off
*
8
))
&
0xff
;
}
}
cur_off
+=
cur_len
;
cur_off
+=
cur_len
;
if
(
cur_off
==
cur
->
len
)
{
if
(
cur_off
==
cur
->
len
)
{
/* operation is done */
/* operation is done */
pending
.
pop_front
();
pending
.
pop_front
();
cur
->
engine
->
mem_op_complete
(
cur
);
cur
->
engine
->
mem_op_complete
(
cur
);
cur_off
=
0
;
cur_off
=
0
;
}
else
{
}
else
{
/* operation is not done yet, we'll pick it back up */
/* operation is not done yet, we'll pick it back up */
}
}
cur
=
0
;
cur
=
0
;
}
else
if
(
!
cur
&&
!
pending
.
empty
())
{
}
else
if
(
!
cur
&&
!
pending
.
empty
())
{
cur
=
pending
.
front
();
cur
=
pending
.
front
();
size_t
data_offset
=
(
cur
->
ram_addr
+
cur_off
)
%
data_byte_width
;
size_t
data_offset
=
(
cur
->
ram_addr
+
cur_off
)
%
data_byte_width
;
#ifdef MEM_DEBUG
#ifdef MEM_DEBUG
std
::
cerr
<<
"issuing op="
<<
cur
<<
" read from "
<<
std
::
hex
<<
std
::
cerr
<<
"issuing op="
<<
cur
<<
" read from "
<<
std
::
hex
cur
->
ram_addr
<<
std
::
endl
;
<<
cur
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
" off="
<<
data_offset
<<
std
::
endl
;
std
::
cerr
<<
" off="
<<
data_offset
<<
std
::
endl
;
#endif
#endif
/* first reset everything */
/* first reset everything */
p
.
mem_sel
=
0
;
p
.
mem_sel
=
0
;
p
.
mem_addr
[
0
]
=
p
.
mem_addr
[
1
]
=
p
.
mem_addr
[
2
]
=
0
;
p
.
mem_addr
[
0
]
=
p
.
mem_addr
[
1
]
=
p
.
mem_addr
[
2
]
=
0
;
p
.
mem_valid
=
0x0
;
p
.
mem_valid
=
0x0
;
/* put data bytes in the right places */
/* put data bytes in the right places */
size_t
off
=
data_offset
;
size_t
off
=
data_offset
;
size_t
cur_len
=
(
cur
->
len
-
cur_off
>
data_byte_width
-
data_offset
size_t
cur_len
=
(
cur
->
len
-
cur_off
>
data_byte_width
-
data_offset
?
?
data_byte_width
-
data_offset
data_byte_width
-
data_offset
:
cur
->
len
-
cur_off
);
:
cur
->
len
-
cur_off
);
for
(
size_t
i
=
0
;
i
<
cur_len
;
i
++
,
off
++
)
{
for
(
size_t
i
=
0
;
i
<
cur_len
;
i
++
,
off
++
)
{
p
.
mem_valid
|=
(
1
<<
(
off
/
(
SEG_WIDTH
/
8
)));
p
.
mem_valid
|=
(
1
<<
(
off
/
(
SEG_WIDTH
/
8
)));
}
}
// p.mem_resready = p.mem_valid;
// p.mem_resready = p.mem_valid;
p
.
mem_resready
=
0xff
;
p
.
mem_resready
=
0xff
;
uint64_t
seg_addr
=
(
cur
->
ram_addr
+
cur_off
)
/
data_byte_width
;
uint64_t
seg_addr
=
(
cur
->
ram_addr
+
cur_off
)
/
data_byte_width
;
size_t
seg_addr_bits
=
12
;
size_t
seg_addr_bits
=
12
;
// iterate over the address bit by bit
// iterate over the address bit by bit
for
(
size_t
i
=
0
;
i
<
seg_addr_bits
;
i
++
)
{
for
(
size_t
i
=
0
;
i
<
seg_addr_bits
;
i
++
)
{
uint32_t
bit
=
((
seg_addr
>>
i
)
&
0x1
);
uint32_t
bit
=
((
seg_addr
>>
i
)
&
0x1
);
// iterate over the segments
// iterate over the segments
for
(
size_t
j
=
0
;
j
<
SEG_COUNT
;
j
++
)
{
for
(
size_t
j
=
0
;
j
<
SEG_COUNT
;
j
++
)
{
size_t
dst_bit
=
j
*
seg_addr_bits
+
i
;
size_t
dst_bit
=
j
*
seg_addr_bits
+
i
;
p
.
mem_addr
[
dst_bit
/
32
]
|=
(
bit
<<
(
dst_bit
%
32
));
p
.
mem_addr
[
dst_bit
/
32
]
|=
(
bit
<<
(
dst_bit
%
32
));
}
}
}
}
#ifdef MEM_DEBUG
#ifdef MEM_DEBUG
for
(
size_t
i
=
0
;
i
<
3
;
i
++
)
for
(
size_t
i
=
0
;
i
<
3
;
i
++
)
std
::
cerr
<<
" addr = "
<<
p
.
mem_addr
[
i
]
<<
std
::
endl
;
std
::
cerr
<<
" addr = "
<<
p
.
mem_addr
[
i
]
<<
std
::
endl
;
std
::
cerr
<<
" mem_valid = "
<<
(
unsigned
)
p
.
mem_valid
<<
std
::
endl
;
std
::
cerr
<<
" mem_valid = "
<<
(
unsigned
)
p
.
mem_valid
<<
std
::
endl
;
#endif
#endif
}
}
}
}
void
MemReader
::
op_issue
(
DMAOp
*
op
)
void
MemReader
::
op_issue
(
DMAOp
*
op
)
{
{
#ifdef MEM_DEBUG
#ifdef MEM_DEBUG
std
::
cerr
<<
"enqueued read from "
<<
op
->
ram_addr
<<
std
::
endl
;
std
::
cerr
<<
"enqueued read from "
<<
op
->
ram_addr
<<
std
::
endl
;
#endif
#endif
pending
.
push_back
(
op
);
pending
.
push_back
(
op
);
}
}
sims/nic/corundum/mem.h
View file @
d4666c97
...
@@ -25,91 +25,93 @@
...
@@ -25,91 +25,93 @@
#ifndef MEM_H_
#ifndef MEM_H_
#define MEM_H_
#define MEM_H_
#include <deque>
#include <verilated.h>
#include <verilated.h>
#include <deque>
#include "sims/nic/corundum/obj_dir/Vinterface.h"
#include "sims/nic/corundum/obj_dir/Vinterface.h"
class
DMAOp
;
class
DMAOp
;
struct
MemReadPort
{
struct
MemReadPort
{
/* outputs to memory */
/* outputs to memory */
vluint8_t
&
mem_sel
;
vluint8_t
&
mem_sel
;
vluint32_t
(
&
mem_addr
)[
3
];
vluint32_t
(
&
mem_addr
)[
3
];
vluint8_t
&
mem_valid
;
vluint8_t
&
mem_valid
;
vluint8_t
&
mem_resready
;
vluint8_t
&
mem_resready
;
/* inputs from memory */
/* inputs from memory */
vluint32_t
(
&
mem_data
)[
32
];
vluint32_t
(
&
mem_data
)[
32
];
vluint8_t
&
mem_ready
;
vluint8_t
&
mem_ready
;
vluint8_t
&
mem_resvalid
;
/* for read only */
vluint8_t
&
mem_resvalid
;
/* for read only */
MemReadPort
(
vluint8_t
&
mem_sel_
,
vluint32_t
(
&
mem_addr_
)[
3
],
MemReadPort
(
vluint8_t
&
mem_sel_
,
vluint32_t
(
&
mem_addr_
)[
3
],
vluint8_t
&
mem_valid_
,
vluint8_t
&
mem_resready_
,
vluint8_t
&
mem_valid_
,
vluint8_t
&
mem_resready_
,
vluint32_t
(
&
mem_data_
)[
32
],
vluint8_t
&
mem_ready_
,
vluint32_t
(
&
mem_data_
)[
32
],
vluint8_t
&
mem_ready_
,
vluint8_t
&
mem_resvalid_
)
vluint8_t
&
mem_resvalid_
)
:
mem_sel
(
mem_sel_
),
mem_addr
(
mem_addr_
),
mem_valid
(
mem_valid_
),
:
mem_sel
(
mem_sel_
),
mem_resready
(
mem_resready_
),
mem_data
(
mem_data_
),
mem_ready
(
mem_ready_
),
mem_addr
(
mem_addr_
),
mem_resvalid
(
mem_resvalid_
)
mem_valid
(
mem_valid_
),
{
mem_resready
(
mem_resready_
),
}
mem_data
(
mem_data_
),
mem_ready
(
mem_ready_
),
mem_resvalid
(
mem_resvalid_
)
{
}
};
};
struct
MemWritePort
{
struct
MemWritePort
{
/* outputs to memory */
/* outputs to memory */
vluint8_t
&
mem_sel
;
vluint8_t
&
mem_sel
;
vluint32_t
(
&
mem_be
)[
4
];
/* for write only */
vluint32_t
(
&
mem_be
)[
4
];
/* for write only */
vluint32_t
(
&
mem_addr
)[
3
];
vluint32_t
(
&
mem_addr
)[
3
];
vluint32_t
(
&
mem_data
)[
32
];
vluint32_t
(
&
mem_data
)[
32
];
vluint8_t
&
mem_valid
;
vluint8_t
&
mem_valid
;
/* inputs from memory */
/* inputs from memory */
vluint8_t
&
mem_ready
;
vluint8_t
&
mem_ready
;
MemWritePort
(
vluint8_t
&
mem_sel_
,
vluint32_t
(
&
mem_be_
)[
4
],
MemWritePort
(
vluint8_t
&
mem_sel_
,
vluint32_t
(
&
mem_be_
)[
4
],
vluint32_t
(
&
mem_addr_
)[
3
],
vluint32_t
(
&
mem_data_
)[
32
],
vluint32_t
(
&
mem_addr_
)[
3
],
vluint32_t
(
&
mem_data_
)[
32
],
vluint8_t
&
mem_valid_
,
vluint8_t
&
mem_ready_
)
vluint8_t
&
mem_valid_
,
vluint8_t
&
mem_ready_
)
:
mem_sel
(
mem_sel_
),
mem_be
(
mem_be_
),
mem_addr
(
mem_addr_
),
:
mem_sel
(
mem_sel_
),
mem_data
(
mem_data_
),
mem_valid
(
mem_valid_
),
mem_ready
(
mem_ready_
)
mem_be
(
mem_be_
),
{
mem_addr
(
mem_addr_
),
}
mem_data
(
mem_data_
),
mem_valid
(
mem_valid_
),
mem_ready
(
mem_ready_
)
{
}
};
};
class
MemReader
{
class
MemReader
{
protected:
protected:
MemReadPort
&
p
;
MemReadPort
&
p
;
std
::
deque
<
DMAOp
*>
pending
;
std
::
deque
<
DMAOp
*>
pending
;
DMAOp
*
cur
;
DMAOp
*
cur
;
size_t
cur_off
;
size_t
cur_off
;
public:
public:
MemReader
(
MemReadPort
&
p_
)
MemReader
(
MemReadPort
&
p_
)
:
p
(
p_
),
cur
(
0
),
cur_off
(
0
)
{
:
p
(
p_
),
cur
(
0
),
cur_off
(
0
)
}
{
}
void
step
();
void
step
();
void
op_issue
(
DMAOp
*
op
);
void
op_issue
(
DMAOp
*
op
);
};
};
class
MemWriter
{
class
MemWriter
{
protected:
protected:
MemWritePort
&
p
;
MemWritePort
&
p
;
std
::
deque
<
DMAOp
*>
pending
;
std
::
deque
<
DMAOp
*>
pending
;
DMAOp
*
cur
;
DMAOp
*
cur
;
size_t
cur_off
;
size_t
cur_off
;
public:
public:
MemWriter
(
MemWritePort
&
p_
)
MemWriter
(
MemWritePort
&
p_
)
:
p
(
p_
),
cur
(
0
),
cur_off
(
0
)
{
:
p
(
p_
),
cur
(
0
),
cur_off
(
0
)
}
{
}
void
step
();
void
step
();
void
op_issue
(
DMAOp
*
op
);
void
op_issue
(
DMAOp
*
op
);
};
};
#endif // MEM_H_
#endif // MEM_H_
sims/nic/corundum_bm/corundum_bm.cc
View file @
d4666c97
...
@@ -22,798 +22,697 @@
...
@@ -22,798 +22,697 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/
#include <stdlib.h>
#include "sims/nic/corundum_bm/corundum_bm.h"
#include <signal.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <unistd.h>
#include <unistd.h>
#include <signal.h>
#include <cassert>
#include
"sims/nic/corundum_bm/corundum_bm.h"
#include
<cassert>
static
nicbm
::
Runner
*
runner
;
static
nicbm
::
Runner
*
runner
;
namespace
corundum
{
namespace
corundum
{
DescRing
::
DescRing
()
DescRing
::
DescRing
()
:
_dmaAddr
(
0
),
_sizeLog
(
0
),
_size
(
0
),
_sizeMask
(
0
),
:
_dmaAddr
(
0
),
_index
(
0
),
_headPtr
(
0
),
_tailPtr
(
0
),
_sizeLog
(
0
),
_currHead
(
0
),
_currTail
(
0
),
active
(
false
),
armed
(
false
)
_size
(
0
),
{
_sizeMask
(
0
),
_index
(
0
),
_headPtr
(
0
),
_tailPtr
(
0
),
_currHead
(
0
),
_currTail
(
0
),
active
(
false
),
armed
(
false
)
{
}
}
DescRing
::~
DescRing
()
DescRing
::~
DescRing
()
{
{
}
}
addr_t
DescRing
::
dmaAddr
()
{
addr_t
return
this
->
_dmaAddr
;
DescRing
::
dmaAddr
()
{
return
this
->
_dmaAddr
;
}
}
size_t
size_t
DescRing
::
sizeLog
()
{
DescRing
::
sizeLog
()
return
this
->
_sizeLog
;
{
return
this
->
_sizeLog
;
}
}
unsigned
unsigned
DescRing
::
index
()
{
DescRing
::
index
()
return
this
->
_index
;
{
return
this
->
_index
;
}
}
ptr_t
ptr_t
DescRing
::
headPtr
()
{
DescRing
::
headPtr
()
return
this
->
_headPtr
;
{
return
this
->
_headPtr
;
}
}
ptr_t
ptr_t
DescRing
::
tailPtr
()
{
DescRing
::
tailPtr
()
return
this
->
_tailPtr
;
{
return
this
->
_tailPtr
;
}
}
void
void
DescRing
::
setDMALower
(
uint32_t
addr
)
{
DescRing
::
setDMALower
(
uint32_t
addr
)
this
->
_dmaAddr
&=
0xFFFFFFFF00000000
;
{
this
->
_dmaAddr
|=
(
addr_t
)
addr
;
this
->
_dmaAddr
&=
0xFFFFFFFF00000000
;
this
->
_dmaAddr
|=
(
addr_t
)
addr
;
}
}
void
void
DescRing
::
setDMAUpper
(
uint32_t
addr
)
{
DescRing
::
setDMAUpper
(
uint32_t
addr
)
this
->
_dmaAddr
&=
0xFFFFFFFF
;
{
this
->
_dmaAddr
|=
((
addr_t
)
addr
<<
32
);
this
->
_dmaAddr
&=
0xFFFFFFFF
;
this
->
_dmaAddr
|=
((
addr_t
)
addr
<<
32
);
}
}
void
void
DescRing
::
setSizeLog
(
size_t
size_log
)
{
DescRing
::
setSizeLog
(
size_t
size_log
)
if
(
size_log
&
QUEUE_ACTIVE_MASK
)
{
{
this
->
active
=
true
;
if
(
size_log
&
QUEUE_ACTIVE_MASK
)
{
}
else
{
this
->
active
=
true
;
this
->
active
=
false
;
}
else
{
}
this
->
active
=
false
;
}
this
->
_sizeLog
=
size_log
&
0xFF
;
this
->
_sizeLog
=
size_log
&
0xFF
;
this
->
_size
=
1
<<
this
->
_sizeLog
;
this
->
_size
=
1
<<
this
->
_sizeLog
;
this
->
_sizeMask
=
this
->
_size
-
1
;
this
->
_sizeMask
=
this
->
_size
-
1
;
this
->
cplDma
.
resize
(
this
->
_size
,
false
);
this
->
cplDma
.
resize
(
this
->
_size
,
false
);
}
}
void
void
DescRing
::
setIndex
(
unsigned
index
)
{
DescRing
::
setIndex
(
unsigned
index
)
assert
(
!
(
index
&
QUEUE_CONT_MASK
));
{
if
(
index
&
QUEUE_ARM_MASK
)
{
assert
(
!
(
index
&
QUEUE_CONT_MASK
));
this
->
armed
=
true
;
if
(
index
&
QUEUE_ARM_MASK
)
{
}
this
->
armed
=
true
;
this
->
_index
=
index
&
0xFF
;
}
this
->
_index
=
index
&
0xFF
;
}
}
void
void
DescRing
::
setHeadPtr
(
ptr_t
ptr
)
{
DescRing
::
setHeadPtr
(
ptr_t
ptr
)
this
->
_headPtr
=
ptr
;
{
this
->
_headPtr
=
ptr
;
}
}
void
void
DescRing
::
setTailPtr
(
ptr_t
ptr
)
{
DescRing
::
setTailPtr
(
ptr_t
ptr
)
this
->
_tailPtr
=
ptr
;
{
this
->
_tailPtr
=
ptr
;
}
}
bool
bool
DescRing
::
empty
()
{
DescRing
::
empty
()
return
(
this
->
_headPtr
==
this
->
_currTail
);
{
return
(
this
->
_headPtr
==
this
->
_currTail
);
}
}
bool
bool
DescRing
::
full
()
{
DescRing
::
full
()
return
(
this
->
_currHead
-
this
->
_tailPtr
>=
this
->
_size
);
{
return
(
this
->
_currHead
-
this
->
_tailPtr
>=
this
->
_size
);
}
}
bool
DescRing
::
updatePtr
(
ptr_t
ptr
,
bool
head
)
{
ptr_t
curr_ptr
=
head
?
this
->
_headPtr
:
this
->
_tailPtr
;
if
(
ptr
!=
curr_ptr
)
{
// out of order completion
this
->
cplDma
[
ptr
&
this
->
_sizeMask
]
=
true
;
return
false
;
}
/* Safe to update the pointer. Also check if any DMA is completed
* out-of-order in front of us.
*/
curr_ptr
=
ptr
&
this
->
_sizeMask
;
bool
do
{
DescRing
::
updatePtr
(
ptr_t
ptr
,
bool
head
)
if
(
head
)
{
{
this
->
_headPtr
++
;
ptr_t
curr_ptr
=
head
?
this
->
_headPtr
:
this
->
_tailPtr
;
}
else
{
if
(
ptr
!=
curr_ptr
)
{
this
->
_tailPtr
++
;
// out of order completion
this
->
cplDma
[
ptr
&
this
->
_sizeMask
]
=
true
;
return
false
;
}
}
/* Safe to update the pointer. Also check if any DMA is completed
this
->
cplDma
[
curr_ptr
]
=
false
;
* out-of-order in front of us.
curr_ptr
=
(
curr_ptr
+
1
)
&
this
->
_sizeMask
;
*/
}
while
(
this
->
cplDma
.
at
(
curr_ptr
));
curr_ptr
=
ptr
&
this
->
_sizeMask
;
return
true
;
do
{
if
(
head
)
{
this
->
_headPtr
++
;
}
else
{
this
->
_tailPtr
++
;
}
this
->
cplDma
[
curr_ptr
]
=
false
;
curr_ptr
=
(
curr_ptr
+
1
)
&
this
->
_sizeMask
;
}
while
(
this
->
cplDma
.
at
(
curr_ptr
));
return
true
;
}
}
EventRing
::
EventRing
()
EventRing
::
EventRing
()
{
{
}
}
EventRing
::~
EventRing
()
EventRing
::~
EventRing
()
{
{
}
}
void
void
EventRing
::
dmaDone
(
DMAOp
*
op
)
{
EventRing
::
dmaDone
(
DMAOp
*
op
)
assert
(
op
->
write
);
{
switch
(
op
->
type
)
{
assert
(
op
->
write
);
switch
(
op
->
type
)
{
case
DMA_TYPE_EVENT
:
case
DMA_TYPE_EVENT
:
if
(
updatePtr
((
ptr_t
)
op
->
tag
,
true
))
{
if
(
updatePtr
((
ptr_t
)
op
->
tag
,
true
))
{
runner
->
msi_issue
(
0
);
runner
->
msi_issue
(
0
);
}
}
delete
op
;
delete
op
;
break
;
break
;
default:
default:
fprintf
(
stderr
,
"Unknown DMA type %u
\n
"
,
op
->
type
);
fprintf
(
stderr
,
"Unknown DMA type %u
\n
"
,
op
->
type
);
abort
();
abort
();
}
}
}
}
void
void
EventRing
::
issueEvent
(
unsigned
type
,
unsigned
source
)
{
EventRing
::
issueEvent
(
unsigned
type
,
unsigned
source
)
assert
(
type
==
EVENT_TYPE_TX_CPL
||
type
==
EVENT_TYPE_RX_CPL
);
{
if
(
this
->
armed
)
{
assert
(
type
==
EVENT_TYPE_TX_CPL
||
type
==
EVENT_TYPE_RX_CPL
);
if
(
full
())
{
if
(
this
->
armed
)
{
fprintf
(
stderr
,
"Event ring is rull
\n
"
);
if
(
full
())
{
return
;
fprintf
(
stderr
,
"Event ring is rull
\n
"
);
return
;
}
addr_t
dma_addr
=
this
->
_dmaAddr
+
(
this
->
_currHead
&
this
->
_sizeMask
)
*
EVENT_SIZE
;
/* Issue DMA write */
DMAOp
*
op
=
new
DMAOp
;
op
->
type
=
DMA_TYPE_EVENT
;
op
->
dma_addr
=
dma_addr
;
op
->
len
=
EVENT_SIZE
;
op
->
ring
=
this
;
op
->
tag
=
this
->
_currHead
;
op
->
write
=
true
;
Event
*
event
=
(
Event
*
)
op
->
data
;
memset
(
event
,
0
,
sizeof
(
Event
));
event
->
type
=
type
;
event
->
source
=
source
;
runner
->
issue_dma
(
*
op
);
this
->
_currHead
++
;
this
->
armed
=
false
;
}
}
addr_t
dma_addr
=
this
->
_dmaAddr
+
(
this
->
_currHead
&
this
->
_sizeMask
)
*
EVENT_SIZE
;
/* Issue DMA write */
DMAOp
*
op
=
new
DMAOp
;
op
->
type
=
DMA_TYPE_EVENT
;
op
->
dma_addr
=
dma_addr
;
op
->
len
=
EVENT_SIZE
;
op
->
ring
=
this
;
op
->
tag
=
this
->
_currHead
;
op
->
write
=
true
;
Event
*
event
=
(
Event
*
)
op
->
data
;
memset
(
event
,
0
,
sizeof
(
Event
));
event
->
type
=
type
;
event
->
source
=
source
;
runner
->
issue_dma
(
*
op
);
this
->
_currHead
++
;
this
->
armed
=
false
;
}
}
}
CplRing
::
CplRing
(
EventRing
*
eventRing
)
CplRing
::
CplRing
(
EventRing
*
eventRing
)
:
eventRing
(
eventRing
)
{
:
eventRing
(
eventRing
)
{
}
}
CplRing
::~
CplRing
()
CplRing
::~
CplRing
()
{
{
}
}
void
void
CplRing
::
dmaDone
(
DMAOp
*
op
)
{
CplRing
::
dmaDone
(
DMAOp
*
op
)
assert
(
op
->
write
);
{
switch
(
op
->
type
)
{
assert
(
op
->
write
);
switch
(
op
->
type
)
{
case
DMA_TYPE_TX_CPL
:
case
DMA_TYPE_TX_CPL
:
case
DMA_TYPE_RX_CPL
:
{
case
DMA_TYPE_RX_CPL
:
{
if
(
updatePtr
((
ptr_t
)
op
->
tag
,
true
))
{
if
(
updatePtr
((
ptr_t
)
op
->
tag
,
true
))
{
unsigned
type
=
op
->
type
==
DMA_TYPE_TX_CPL
?
EVENT_TYPE_TX_CPL
:
unsigned
type
=
EVENT_TYPE_RX_CPL
;
op
->
type
==
DMA_TYPE_TX_CPL
?
EVENT_TYPE_TX_CPL
:
EVENT_TYPE_RX_CPL
;
this
->
eventRing
->
issueEvent
(
type
,
0
);
this
->
eventRing
->
issueEvent
(
type
,
0
);
}
}
delete
op
;
delete
op
;
break
;
break
;
}
}
default:
default:
fprintf
(
stderr
,
"Unknown DMA type %u
\n
"
,
op
->
type
);
fprintf
(
stderr
,
"Unknown DMA type %u
\n
"
,
op
->
type
);
abort
();
abort
();
}
}
}
void
CplRing
::
complete
(
unsigned
index
,
size_t
len
,
bool
tx
)
{
CplData
data
;
data
.
index
=
index
;
data
.
len
=
len
;
data
.
tx
=
tx
;
this
->
pending
.
push_back
(
data
);
while
(
!
full
()
&&
!
this
->
pending
.
empty
())
{
CplData
&
data
=
this
->
pending
.
front
();
addr_t
dma_addr
=
this
->
_dmaAddr
+
(
this
->
_currHead
&
this
->
_sizeMask
)
*
CPL_SIZE
;
/* Issue DMA write */
DMAOp
*
op
=
new
DMAOp
;
op
->
type
=
data
.
tx
?
DMA_TYPE_TX_CPL
:
DMA_TYPE_RX_CPL
;
op
->
dma_addr
=
dma_addr
;
op
->
len
=
CPL_SIZE
;
op
->
ring
=
this
;
op
->
tag
=
this
->
_currHead
;
op
->
write
=
true
;
Cpl
*
cpl
=
(
Cpl
*
)
op
->
data
;
memset
(
cpl
,
0
,
sizeof
(
Cpl
));
cpl
->
index
=
data
.
index
;
cpl
->
len
=
data
.
len
;
this
->
pending
.
pop_front
();
runner
->
issue_dma
(
*
op
);
this
->
_currHead
++
;
}
}
}
void
TxRing
::
TxRing
(
CplRing
*
cplRing
)
:
txCplRing
(
cplRing
)
{
CplRing
::
complete
(
unsigned
index
,
size_t
len
,
bool
tx
)
{
CplData
data
;
data
.
index
=
index
;
data
.
len
=
len
;
data
.
tx
=
tx
;
this
->
pending
.
push_back
(
data
);
while
(
!
full
()
&&
!
this
->
pending
.
empty
())
{
CplData
&
data
=
this
->
pending
.
front
();
addr_t
dma_addr
=
this
->
_dmaAddr
+
(
this
->
_currHead
&
this
->
_sizeMask
)
*
CPL_SIZE
;
/* Issue DMA write */
DMAOp
*
op
=
new
DMAOp
;
op
->
type
=
data
.
tx
?
DMA_TYPE_TX_CPL
:
DMA_TYPE_RX_CPL
;
op
->
dma_addr
=
dma_addr
;
op
->
len
=
CPL_SIZE
;
op
->
ring
=
this
;
op
->
tag
=
this
->
_currHead
;
op
->
write
=
true
;
Cpl
*
cpl
=
(
Cpl
*
)
op
->
data
;
memset
(
cpl
,
0
,
sizeof
(
Cpl
));
cpl
->
index
=
data
.
index
;
cpl
->
len
=
data
.
len
;
this
->
pending
.
pop_front
();
runner
->
issue_dma
(
*
op
);
this
->
_currHead
++
;
}
}
}
TxRing
::
TxRing
(
CplRing
*
cplRing
)
TxRing
::~
TxRing
()
{
:
txCplRing
(
cplRing
)
}
{
}
void
TxRing
::
setHeadPtr
(
ptr_t
ptr
)
{
DescRing
::
setHeadPtr
(
ptr
);
TxRing
::~
TxRing
()
while
(
this
->
_currTail
!=
this
->
_headPtr
)
{
{
unsigned
index
=
this
->
_currTail
&
this
->
_sizeMask
;
}
addr_t
dma_addr
=
this
->
_dmaAddr
+
index
*
DESC_SIZE
;
/* Issue DMA read */
void
DMAOp
*
op
=
new
DMAOp
;
TxRing
::
setHeadPtr
(
ptr_t
ptr
)
op
->
type
=
DMA_TYPE_DESC
;
{
op
->
dma_addr
=
dma_addr
;
DescRing
::
setHeadPtr
(
ptr
);
op
->
len
=
DESC_SIZE
;
while
(
this
->
_currTail
!=
this
->
_headPtr
)
{
op
->
ring
=
this
;
unsigned
index
=
this
->
_currTail
&
this
->
_sizeMask
;
op
->
tag
=
this
->
_currTail
;
addr_t
dma_addr
=
this
->
_dmaAddr
+
index
*
DESC_SIZE
;
op
->
write
=
false
;
/* Issue DMA read */
runner
->
issue_dma
(
*
op
);
DMAOp
*
op
=
new
DMAOp
;
this
->
_currTail
++
;
op
->
type
=
DMA_TYPE_DESC
;
}
op
->
dma_addr
=
dma_addr
;
op
->
len
=
DESC_SIZE
;
op
->
ring
=
this
;
op
->
tag
=
this
->
_currTail
;
op
->
write
=
false
;
runner
->
issue_dma
(
*
op
);
this
->
_currTail
++
;
}
}
}
void
void
TxRing
::
dmaDone
(
DMAOp
*
op
)
{
TxRing
::
dmaDone
(
DMAOp
*
op
)
switch
(
op
->
type
)
{
{
switch
(
op
->
type
)
{
case
DMA_TYPE_DESC
:
{
case
DMA_TYPE_DESC
:
{
assert
(
!
op
->
write
);
assert
(
!
op
->
write
);
Desc
*
desc
=
(
Desc
*
)
op
->
data
;
Desc
*
desc
=
(
Desc
*
)
op
->
data
;
op
->
type
=
DMA_TYPE_MEM
;
op
->
type
=
DMA_TYPE_MEM
;
op
->
dma_addr
=
desc
->
addr
;
op
->
dma_addr
=
desc
->
addr
;
op
->
len
=
desc
->
len
;
op
->
len
=
desc
->
len
;
op
->
write
=
false
;
op
->
write
=
false
;
runner
->
issue_dma
(
*
op
);
runner
->
issue_dma
(
*
op
);
break
;
break
;
}
}
case
DMA_TYPE_MEM
:
case
DMA_TYPE_MEM
:
assert
(
!
op
->
write
);
assert
(
!
op
->
write
);
runner
->
eth_send
(
op
->
data
,
op
->
len
);
runner
->
eth_send
(
op
->
data
,
op
->
len
);
updatePtr
((
ptr_t
)
op
->
tag
,
false
);
updatePtr
((
ptr_t
)
op
->
tag
,
false
);
this
->
txCplRing
->
complete
(
op
->
tag
,
op
->
len
,
true
);
this
->
txCplRing
->
complete
(
op
->
tag
,
op
->
len
,
true
);
delete
op
;
delete
op
;
break
;
break
;
default:
default:
fprintf
(
stderr
,
"Unknown DMA type %u
\n
"
,
op
->
type
);
fprintf
(
stderr
,
"Unknown DMA type %u
\n
"
,
op
->
type
);
abort
();
abort
();
}
}
}
}
RxRing
::
RxRing
(
CplRing
*
cplRing
)
RxRing
::
RxRing
(
CplRing
*
cplRing
)
:
rxCplRing
(
cplRing
)
{
:
rxCplRing
(
cplRing
)
{
}
}
RxRing
::~
RxRing
()
RxRing
::~
RxRing
()
{
{
}
}
void
void
RxRing
::
dmaDone
(
DMAOp
*
op
)
{
RxRing
::
dmaDone
(
DMAOp
*
op
)
switch
(
op
->
type
)
{
{
switch
(
op
->
type
)
{
case
DMA_TYPE_DESC
:
{
case
DMA_TYPE_DESC
:
{
assert
(
!
op
->
write
);
assert
(
!
op
->
write
);
Desc
*
desc
=
(
Desc
*
)
op
->
data
;
Desc
*
desc
=
(
Desc
*
)
op
->
data
;
op
->
type
=
DMA_TYPE_MEM
;
op
->
type
=
DMA_TYPE_MEM
;
op
->
dma_addr
=
desc
->
addr
;
op
->
dma_addr
=
desc
->
addr
;
op
->
len
=
op
->
rx_data
->
len
;
op
->
len
=
op
->
rx_data
->
len
;
memcpy
((
void
*
)
op
->
data
,
(
void
*
)
op
->
rx_data
->
data
,
op
->
len
);
memcpy
((
void
*
)
op
->
data
,
(
void
*
)
op
->
rx_data
->
data
,
op
->
len
);
delete
op
->
rx_data
;
delete
op
->
rx_data
;
op
->
write
=
true
;
op
->
write
=
true
;
runner
->
issue_dma
(
*
op
);
runner
->
issue_dma
(
*
op
);
break
;
break
;
}
}
case
DMA_TYPE_MEM
:
case
DMA_TYPE_MEM
:
assert
(
op
->
write
);
assert
(
op
->
write
);
updatePtr
((
ptr_t
)
op
->
tag
,
false
);
updatePtr
((
ptr_t
)
op
->
tag
,
false
);
this
->
rxCplRing
->
complete
(
op
->
tag
,
op
->
len
,
false
);
this
->
rxCplRing
->
complete
(
op
->
tag
,
op
->
len
,
false
);
delete
op
;
delete
op
;
break
;
break
;
default:
default:
fprintf
(
stderr
,
"Unknown DMA type %u
\n
"
,
op
->
type
);
fprintf
(
stderr
,
"Unknown DMA type %u
\n
"
,
op
->
type
);
abort
();
abort
();
}
}
}
}
void
void
RxRing
::
rx
(
RxData
*
rx_data
)
{
RxRing
::
rx
(
RxData
*
rx_data
)
if
(
empty
())
{
{
delete
rx_data
;
if
(
empty
())
{
return
;
delete
rx_data
;
}
return
;
addr_t
dma_addr
=
}
this
->
_dmaAddr
+
(
this
->
_currTail
&
this
->
_sizeMask
)
*
DESC_SIZE
;
addr_t
dma_addr
=
this
->
_dmaAddr
+
(
this
->
_currTail
&
this
->
_sizeMask
)
*
/* Issue DMA read */
DESC_SIZE
;
DMAOp
*
op
=
new
DMAOp
;
/* Issue DMA read */
op
->
type
=
DMA_TYPE_DESC
;
DMAOp
*
op
=
new
DMAOp
;
op
->
dma_addr
=
dma_addr
;
op
->
type
=
DMA_TYPE_DESC
;
op
->
len
=
DESC_SIZE
;
op
->
dma_addr
=
dma_addr
;
op
->
ring
=
this
;
op
->
len
=
DESC_SIZE
;
op
->
rx_data
=
rx_data
;
op
->
ring
=
this
;
op
->
tag
=
this
->
_currTail
;
op
->
rx_data
=
rx_data
;
op
->
write
=
false
;
op
->
tag
=
this
->
_currTail
;
runner
->
issue_dma
(
*
op
);
op
->
write
=
false
;
this
->
_currTail
++
;
runner
->
issue_dma
(
*
op
);
this
->
_currTail
++
;
}
}
Port
::
Port
()
Port
::
Port
()
:
_id
(
0
),
_features
(
0
),
_mtu
(
0
),
:
_id
(
0
),
_schedCount
(
0
),
_schedOffset
(
0
),
_schedStride
(
0
),
_features
(
0
),
_schedType
(
0
),
_rssMask
(
0
),
_schedEnable
(
false
),
_mtu
(
0
),
_queueEnable
(
false
)
_schedCount
(
0
),
{
_schedOffset
(
0
),
_schedStride
(
0
),
_schedType
(
0
),
_rssMask
(
0
),
_schedEnable
(
false
),
_queueEnable
(
false
)
{
}
}
Port
::~
Port
()
Port
::~
Port
()
{
{
}
}
unsigned
unsigned
Port
::
id
()
{
Port
::
id
()
return
this
->
_id
;
{
return
this
->
_id
;
}
}
unsigned
unsigned
Port
::
features
()
{
Port
::
features
()
return
this
->
_features
;
{
return
this
->
_features
;
}
}
size_t
size_t
Port
::
mtu
()
{
Port
::
mtu
()
return
this
->
_mtu
;
{
return
this
->
_mtu
;
}
}
size_t
size_t
Port
::
schedCount
()
{
Port
::
schedCount
()
return
this
->
_schedCount
;
{
return
this
->
_schedCount
;
}
}
addr_t
addr_t
Port
::
schedOffset
()
{
Port
::
schedOffset
()
return
this
->
_schedOffset
;
{
return
this
->
_schedOffset
;
}
}
addr_t
addr_t
Port
::
schedStride
()
{
Port
::
schedStride
()
return
this
->
_schedStride
;
{
return
this
->
_schedStride
;
}
}
unsigned
unsigned
Port
::
schedType
()
{
Port
::
schedType
()
return
this
->
_schedType
;
{
return
this
->
_schedType
;
}
}
unsigned
Port
::
rssMask
()
{
unsigned
return
this
->
_rssMask
;
Port
::
rssMask
()
{
return
this
->
_rssMask
;
}
}
void
void
Port
::
setId
(
unsigned
id
)
{
Port
::
setId
(
unsigned
id
)
this
->
_id
=
id
;
{
this
->
_id
=
id
;
}
}
void
void
Port
::
setFeatures
(
unsigned
features
)
{
Port
::
setFeatures
(
unsigned
features
)
this
->
_features
=
{
features
&
(
IF_FEATURE_RSS
|
IF_FEATURE_PTP_TS
|
IF_FEATURE_TX_CSUM
|
this
->
_features
=
features
&
(
IF_FEATURE_RSS
|
IF_FEATURE_RX_CSUM
|
IF_FEATURE_RX_HASH
);
IF_FEATURE_PTP_TS
|
IF_FEATURE_TX_CSUM
|
IF_FEATURE_RX_CSUM
|
IF_FEATURE_RX_HASH
);
}
}
void
void
Port
::
setMtu
(
size_t
mtu
)
{
Port
::
setMtu
(
size_t
mtu
)
this
->
_mtu
=
mtu
;
{
this
->
_mtu
=
mtu
;
}
}
void
void
Port
::
setSchedCount
(
size_t
count
)
{
Port
::
setSchedCount
(
size_t
count
)
this
->
_schedCount
=
count
;
{
this
->
_schedCount
=
count
;
}
}
void
void
Port
::
setSchedOffset
(
addr_t
offset
)
{
Port
::
setSchedOffset
(
addr_t
offset
)
this
->
_schedOffset
=
offset
;
{
this
->
_schedOffset
=
offset
;
}
}
void
void
Port
::
setSchedStride
(
addr_t
stride
)
{
Port
::
setSchedStride
(
addr_t
stride
)
this
->
_schedStride
=
stride
;
{
this
->
_schedStride
=
stride
;
}
}
void
void
Port
::
setSchedType
(
unsigned
type
)
{
Port
::
setSchedType
(
unsigned
type
)
this
->
_schedType
=
type
;
{
this
->
_schedType
=
type
;
}
}
void
void
Port
::
setRssMask
(
unsigned
mask
)
{
Port
::
setRssMask
(
unsigned
mask
)
this
->
_rssMask
=
mask
;
{
this
->
_rssMask
=
mask
;
}
}
void
void
Port
::
schedEnable
()
{
Port
::
schedEnable
()
this
->
_schedEnable
=
true
;
{
this
->
_schedEnable
=
true
;
}
}
void
void
Port
::
schedDisable
()
{
Port
::
schedDisable
()
this
->
_schedEnable
=
false
;
{
this
->
_schedEnable
=
false
;
}
}
void
void
Port
::
queueEnable
()
{
Port
::
queueEnable
()
this
->
_queueEnable
=
true
;
{
this
->
_queueEnable
=
true
;
}
}
void
void
Port
::
queueDisable
()
{
Port
::
queueDisable
()
this
->
_queueEnable
=
false
;
{
this
->
_queueEnable
=
false
;
}
}
Corundum
::
Corundum
()
Corundum
::
Corundum
()
:
txCplRing
(
&
this
->
eventRing
),
rxCplRing
(
&
this
->
eventRing
),
:
txCplRing
(
&
this
->
eventRing
),
txRing
(
&
this
->
txCplRing
),
rxRing
(
&
this
->
rxCplRing
),
features
(
0
)
rxCplRing
(
&
this
->
eventRing
),
{
txRing
(
&
this
->
txCplRing
),
this
->
port
.
setId
(
0
);
rxRing
(
&
this
->
rxCplRing
),
this
->
port
.
setFeatures
(
this
->
features
);
features
(
0
)
{
this
->
port
.
setMtu
(
2048
);
this
->
port
.
setId
(
0
);
this
->
port
.
setSchedCount
(
1
);
this
->
port
.
setFeatures
(
this
->
features
);
this
->
port
.
setSchedOffset
(
0x100000
);
this
->
port
.
setMtu
(
2048
);
this
->
port
.
setSchedStride
(
0x100000
);
this
->
port
.
setSchedCount
(
1
);
this
->
port
.
setSchedType
(
0
);
this
->
port
.
setSchedOffset
(
0x100000
);
this
->
port
.
setRssMask
(
0
);
this
->
port
.
setSchedStride
(
0x100000
);
this
->
port
.
schedDisable
();
this
->
port
.
setSchedType
(
0
);
}
this
->
port
.
setRssMask
(
0
);
this
->
port
.
schedDisable
();
Corundum
::~
Corundum
()
}
{
}
Corundum
::~
Corundum
()
{
}
reg_t
Corundum
::
reg_read
(
uint8_t
bar
,
addr_t
addr
)
reg_t
Corundum
::
reg_read
(
uint8_t
bar
,
addr_t
addr
)
{
{
switch
(
addr
)
{
switch
(
addr
)
{
case
REG_FW_ID
:
case
REG_FW_ID
:
return
32
;
return
32
;
case
REG_FW_VER
:
case
REG_FW_VER
:
return
1
;
return
1
;
case
REG_BOARD_ID
:
case
REG_BOARD_ID
:
return
0x43215678
;
return
0x43215678
;
case
REG_BOARD_VER
:
case
REG_BOARD_VER
:
return
1
;
return
1
;
case
REG_PHC_COUNT
:
case
REG_PHC_COUNT
:
return
1
;
return
1
;
case
REG_PHC_OFFSET
:
case
REG_PHC_OFFSET
:
return
0x200
;
return
0x200
;
case
REG_PHC_STRIDE
:
case
REG_PHC_STRIDE
:
return
0x80
;
return
0x80
;
case
REG_IF_COUNT
:
case
REG_IF_COUNT
:
return
1
;
return
1
;
case
REG_IF_STRIDE
:
case
REG_IF_STRIDE
:
return
0x80000
;
return
0x80000
;
case
REG_IF_CSR_OFFSET
:
case
REG_IF_CSR_OFFSET
:
return
0x80000
;
return
0x80000
;
case
PHC_REG_FEATURES
:
case
PHC_REG_FEATURES
:
return
0x1
;
return
0x1
;
case
PHC_REG_PTP_CUR_SEC_L
:
case
PHC_REG_PTP_CUR_SEC_L
:
return
0x0
;
return
0x0
;
case
PHC_REG_PTP_CUR_SEC_H
:
case
PHC_REG_PTP_CUR_SEC_H
:
return
0x0
;
return
0x0
;
case
IF_REG_IF_ID
:
case
IF_REG_IF_ID
:
return
0
;
return
0
;
case
IF_REG_IF_FEATURES
:
case
IF_REG_IF_FEATURES
:
return
this
->
features
;
return
this
->
features
;
case
IF_REG_EVENT_QUEUE_COUNT
:
case
IF_REG_EVENT_QUEUE_COUNT
:
return
1
;
return
1
;
case
IF_REG_EVENT_QUEUE_OFFSET
:
case
IF_REG_EVENT_QUEUE_OFFSET
:
return
0x100000
;
return
0x100000
;
case
IF_REG_TX_QUEUE_COUNT
:
case
IF_REG_TX_QUEUE_COUNT
:
return
1
;
return
1
;
case
IF_REG_TX_QUEUE_OFFSET
:
case
IF_REG_TX_QUEUE_OFFSET
:
return
0x200000
;
return
0x200000
;
case
IF_REG_TX_CPL_QUEUE_COUNT
:
case
IF_REG_TX_CPL_QUEUE_COUNT
:
return
1
;
return
1
;
case
IF_REG_TX_CPL_QUEUE_OFFSET
:
case
IF_REG_TX_CPL_QUEUE_OFFSET
:
return
0x400000
;
return
0x400000
;
case
IF_REG_RX_QUEUE_COUNT
:
case
IF_REG_RX_QUEUE_COUNT
:
return
1
;
return
1
;
case
IF_REG_RX_QUEUE_OFFSET
:
case
IF_REG_RX_QUEUE_OFFSET
:
return
0x600000
;
return
0x600000
;
case
IF_REG_RX_CPL_QUEUE_COUNT
:
case
IF_REG_RX_CPL_QUEUE_COUNT
:
return
1
;
return
1
;
case
IF_REG_RX_CPL_QUEUE_OFFSET
:
case
IF_REG_RX_CPL_QUEUE_OFFSET
:
return
0x700000
;
return
0x700000
;
case
IF_REG_PORT_COUNT
:
case
IF_REG_PORT_COUNT
:
return
1
;
return
1
;
case
IF_REG_PORT_OFFSET
:
case
IF_REG_PORT_OFFSET
:
return
0x800000
;
return
0x800000
;
case
IF_REG_PORT_STRIDE
:
case
IF_REG_PORT_STRIDE
:
return
0x200000
;
return
0x200000
;
case
EVENT_QUEUE_HEAD_PTR_REG
:
case
EVENT_QUEUE_HEAD_PTR_REG
:
return
this
->
eventRing
.
headPtr
();
return
this
->
eventRing
.
headPtr
();
case
TX_QUEUE_ACTIVE_LOG_SIZE_REG
:
case
TX_QUEUE_ACTIVE_LOG_SIZE_REG
:
return
this
->
txRing
.
sizeLog
();
return
this
->
txRing
.
sizeLog
();
case
TX_QUEUE_TAIL_PTR_REG
:
case
TX_QUEUE_TAIL_PTR_REG
:
return
this
->
txRing
.
tailPtr
();
return
this
->
txRing
.
tailPtr
();
case
TX_CPL_QUEUE_HEAD_PTR_REG
:
case
TX_CPL_QUEUE_HEAD_PTR_REG
:
return
this
->
txCplRing
.
headPtr
();
return
this
->
txCplRing
.
headPtr
();
case
RX_QUEUE_TAIL_PTR_REG
:
case
RX_QUEUE_TAIL_PTR_REG
:
return
this
->
rxRing
.
tailPtr
();
return
this
->
rxRing
.
tailPtr
();
case
RX_CPL_QUEUE_HEAD_PTR_REG
:
case
RX_CPL_QUEUE_HEAD_PTR_REG
:
return
this
->
rxCplRing
.
headPtr
();
return
this
->
rxCplRing
.
headPtr
();
case
PORT_REG_PORT_ID
:
case
PORT_REG_PORT_ID
:
return
this
->
port
.
id
();
return
this
->
port
.
id
();
case
PORT_REG_PORT_FEATURES
:
case
PORT_REG_PORT_FEATURES
:
return
this
->
port
.
features
();
return
this
->
port
.
features
();
case
PORT_REG_PORT_MTU
:
case
PORT_REG_PORT_MTU
:
return
this
->
port
.
mtu
();
return
this
->
port
.
mtu
();
case
PORT_REG_SCHED_COUNT
:
case
PORT_REG_SCHED_COUNT
:
return
this
->
port
.
schedCount
();
return
this
->
port
.
schedCount
();
case
PORT_REG_SCHED_OFFSET
:
case
PORT_REG_SCHED_OFFSET
:
return
this
->
port
.
schedOffset
();
return
this
->
port
.
schedOffset
();
case
PORT_REG_SCHED_STRIDE
:
case
PORT_REG_SCHED_STRIDE
:
return
this
->
port
.
schedStride
();
return
this
->
port
.
schedStride
();
case
PORT_REG_SCHED_TYPE
:
case
PORT_REG_SCHED_TYPE
:
return
this
->
port
.
schedType
();
return
this
->
port
.
schedType
();
default:
default:
fprintf
(
stderr
,
"Unknown register read %lx
\n
"
,
addr
);
fprintf
(
stderr
,
"Unknown register read %lx
\n
"
,
addr
);
abort
();
abort
();
}
}
}
}
void
Corundum
::
reg_write
(
uint8_t
bar
,
uint64_t
addr
,
reg_t
val
)
{
void
switch
(
addr
)
{
Corundum
::
reg_write
(
uint8_t
bar
,
uint64_t
addr
,
reg_t
val
)
case
REG_FW_ID
:
{
case
REG_FW_VER
:
switch
(
addr
)
{
case
REG_BOARD_ID
:
case
REG_FW_ID
:
case
REG_BOARD_VER
:
case
REG_FW_VER
:
case
REG_PHC_COUNT
:
case
REG_BOARD_ID
:
case
REG_PHC_OFFSET
:
case
REG_BOARD_VER
:
case
REG_PHC_STRIDE
:
case
REG_PHC_COUNT
:
case
REG_IF_COUNT
:
case
REG_PHC_OFFSET
:
case
REG_IF_STRIDE
:
case
REG_PHC_STRIDE
:
case
REG_IF_CSR_OFFSET
:
case
REG_IF_COUNT
:
case
PHC_REG_FEATURES
:
case
REG_IF_STRIDE
:
case
PHC_REG_PTP_SET_FNS
:
case
REG_IF_CSR_OFFSET
:
case
PHC_REG_PTP_SET_NS
:
case
PHC_REG_FEATURES
:
case
PHC_REG_PTP_SET_SEC_L
:
case
PHC_REG_PTP_SET_FNS
:
case
PHC_REG_PTP_SET_SEC_H
:
case
PHC_REG_PTP_SET_NS
:
break
;
case
PHC_REG_PTP_SET_SEC_L
:
case
EVENT_QUEUE_BASE_ADDR_REG
:
case
PHC_REG_PTP_SET_SEC_H
:
this
->
eventRing
.
setDMALower
(
val
);
break
;
break
;
case
EVENT_QUEUE_BASE_ADDR_REG
:
case
EVENT_QUEUE_BASE_ADDR_REG
+
4
:
this
->
eventRing
.
setDMALower
(
val
);
this
->
eventRing
.
setDMAUpper
(
val
);
break
;
break
;
case
EVENT_QUEUE_BASE_ADDR_REG
+
4
:
case
EVENT_QUEUE_ACTIVE_LOG_SIZE_REG
:
this
->
eventRing
.
setDMAUpper
(
val
);
this
->
eventRing
.
setSizeLog
(
val
);
break
;
break
;
case
EVENT_QUEUE_ACTIVE_LOG_SIZE_REG
:
case
EVENT_QUEUE_INTERRUPT_INDEX_REG
:
this
->
eventRing
.
setSizeLog
(
val
);
this
->
eventRing
.
setIndex
(
val
);
break
;
break
;
case
EVENT_QUEUE_INTERRUPT_INDEX_REG
:
case
EVENT_QUEUE_HEAD_PTR_REG
:
this
->
eventRing
.
setIndex
(
val
);
this
->
eventRing
.
setHeadPtr
(
val
);
break
;
break
;
case
EVENT_QUEUE_HEAD_PTR_REG
:
case
EVENT_QUEUE_TAIL_PTR_REG
:
this
->
eventRing
.
setHeadPtr
(
val
);
this
->
eventRing
.
setTailPtr
(
val
);
break
;
break
;
case
EVENT_QUEUE_TAIL_PTR_REG
:
case
TX_QUEUE_BASE_ADDR_REG
:
this
->
eventRing
.
setTailPtr
(
val
);
this
->
txRing
.
setDMALower
(
val
);
break
;
break
;
case
TX_QUEUE_BASE_ADDR_REG
:
case
TX_QUEUE_BASE_ADDR_REG
+
4
:
this
->
txRing
.
setDMALower
(
val
);
this
->
txRing
.
setDMAUpper
(
val
);
break
;
break
;
case
TX_QUEUE_BASE_ADDR_REG
+
4
:
case
TX_QUEUE_ACTIVE_LOG_SIZE_REG
:
this
->
txRing
.
setDMAUpper
(
val
);
this
->
txRing
.
setSizeLog
(
val
);
break
;
break
;
case
TX_QUEUE_ACTIVE_LOG_SIZE_REG
:
case
TX_QUEUE_CPL_QUEUE_INDEX_REG
:
this
->
txRing
.
setSizeLog
(
val
);
this
->
txRing
.
setIndex
(
val
);
break
;
break
;
case
TX_QUEUE_CPL_QUEUE_INDEX_REG
:
case
TX_QUEUE_HEAD_PTR_REG
:
this
->
txRing
.
setIndex
(
val
);
this
->
txRing
.
setHeadPtr
(
val
);
break
;
break
;
case
TX_QUEUE_HEAD_PTR_REG
:
case
TX_QUEUE_TAIL_PTR_REG
:
this
->
txRing
.
setHeadPtr
(
val
);
this
->
txRing
.
setTailPtr
(
val
);
break
;
break
;
case
TX_QUEUE_TAIL_PTR_REG
:
case
TX_CPL_QUEUE_BASE_ADDR_REG
:
this
->
txRing
.
setTailPtr
(
val
);
this
->
txCplRing
.
setDMALower
(
val
);
break
;
break
;
case
TX_CPL_QUEUE_BASE_ADDR_REG
:
case
TX_CPL_QUEUE_BASE_ADDR_REG
+
4
:
this
->
txCplRing
.
setDMALower
(
val
);
this
->
txCplRing
.
setDMAUpper
(
val
);
break
;
break
;
case
TX_CPL_QUEUE_BASE_ADDR_REG
+
4
:
case
TX_CPL_QUEUE_ACTIVE_LOG_SIZE_REG
:
this
->
txCplRing
.
setDMAUpper
(
val
);
this
->
txCplRing
.
setSizeLog
(
val
);
break
;
break
;
case
TX_CPL_QUEUE_ACTIVE_LOG_SIZE_REG
:
case
TX_CPL_QUEUE_INTERRUPT_INDEX_REG
:
this
->
txCplRing
.
setSizeLog
(
val
);
this
->
txCplRing
.
setIndex
(
val
);
break
;
break
;
case
TX_CPL_QUEUE_INTERRUPT_INDEX_REG
:
case
TX_CPL_QUEUE_HEAD_PTR_REG
:
this
->
txCplRing
.
setIndex
(
val
);
this
->
txCplRing
.
setHeadPtr
(
val
);
break
;
break
;
case
TX_CPL_QUEUE_HEAD_PTR_REG
:
case
TX_CPL_QUEUE_TAIL_PTR_REG
:
this
->
txCplRing
.
setHeadPtr
(
val
);
this
->
txCplRing
.
setTailPtr
(
val
);
break
;
break
;
case
TX_CPL_QUEUE_TAIL_PTR_REG
:
case
RX_QUEUE_BASE_ADDR_REG
:
this
->
txCplRing
.
setTailPtr
(
val
);
this
->
rxRing
.
setDMALower
(
val
);
break
;
break
;
case
RX_QUEUE_BASE_ADDR_REG
:
case
RX_QUEUE_BASE_ADDR_REG
+
4
:
this
->
rxRing
.
setDMALower
(
val
);
this
->
rxRing
.
setDMAUpper
(
val
);
break
;
break
;
case
RX_QUEUE_BASE_ADDR_REG
+
4
:
case
RX_QUEUE_ACTIVE_LOG_SIZE_REG
:
this
->
rxRing
.
setDMAUpper
(
val
);
this
->
rxRing
.
setSizeLog
(
val
);
break
;
break
;
case
RX_QUEUE_ACTIVE_LOG_SIZE_REG
:
case
RX_QUEUE_CPL_QUEUE_INDEX_REG
:
this
->
rxRing
.
setSizeLog
(
val
);
this
->
rxRing
.
setIndex
(
val
);
break
;
break
;
case
RX_QUEUE_CPL_QUEUE_INDEX_REG
:
case
RX_QUEUE_HEAD_PTR_REG
:
this
->
rxRing
.
setIndex
(
val
);
this
->
rxRing
.
setHeadPtr
(
val
);
break
;
break
;
case
RX_QUEUE_HEAD_PTR_REG
:
case
RX_QUEUE_TAIL_PTR_REG
:
this
->
rxRing
.
setHeadPtr
(
val
);
this
->
rxRing
.
setTailPtr
(
val
);
break
;
break
;
case
RX_QUEUE_TAIL_PTR_REG
:
case
RX_CPL_QUEUE_BASE_ADDR_REG
:
this
->
rxRing
.
setTailPtr
(
val
);
this
->
rxCplRing
.
setDMALower
(
val
);
break
;
break
;
case
RX_CPL_QUEUE_BASE_ADDR_REG
:
case
RX_CPL_QUEUE_BASE_ADDR_REG
+
4
:
this
->
rxCplRing
.
setDMALower
(
val
);
this
->
rxCplRing
.
setDMAUpper
(
val
);
break
;
break
;
case
RX_CPL_QUEUE_BASE_ADDR_REG
+
4
:
case
RX_CPL_QUEUE_ACTIVE_LOG_SIZE_REG
:
this
->
rxCplRing
.
setDMAUpper
(
val
);
this
->
rxCplRing
.
setSizeLog
(
val
);
break
;
break
;
case
RX_CPL_QUEUE_ACTIVE_LOG_SIZE_REG
:
case
RX_CPL_QUEUE_INTERRUPT_INDEX_REG
:
this
->
rxCplRing
.
setSizeLog
(
val
);
this
->
rxCplRing
.
setIndex
(
val
);
break
;
break
;
case
RX_CPL_QUEUE_INTERRUPT_INDEX_REG
:
case
RX_CPL_QUEUE_HEAD_PTR_REG
:
this
->
rxCplRing
.
setIndex
(
val
);
this
->
rxCplRing
.
setHeadPtr
(
val
);
break
;
break
;
case
RX_CPL_QUEUE_HEAD_PTR_REG
:
case
RX_CPL_QUEUE_TAIL_PTR_REG
:
this
->
rxCplRing
.
setHeadPtr
(
val
);
this
->
rxCplRing
.
setTailPtr
(
val
);
break
;
break
;
case
RX_CPL_QUEUE_TAIL_PTR_REG
:
case
PORT_REG_SCHED_ENABLE
:
this
->
rxCplRing
.
setTailPtr
(
val
);
if
(
val
)
{
break
;
this
->
port
.
schedEnable
();
case
PORT_REG_SCHED_ENABLE
:
}
else
{
if
(
val
)
{
this
->
port
.
schedDisable
();
this
->
port
.
schedEnable
();
}
}
else
{
break
;
this
->
port
.
schedDisable
();
case
PORT_REG_RSS_MASK
:
}
this
->
port
.
setRssMask
(
val
);
break
;
break
;
case
PORT_REG_RSS_MASK
:
case
PORT_QUEUE_ENABLE
:
this
->
port
.
setRssMask
(
val
);
if
(
val
)
{
break
;
this
->
port
.
queueEnable
();
case
PORT_QUEUE_ENABLE
:
}
else
{
if
(
val
)
{
this
->
port
.
queueDisable
();
this
->
port
.
queueEnable
();
}
}
else
{
break
;
this
->
port
.
queueDisable
();
default:
}
fprintf
(
stderr
,
"Unknown register write %lx
\n
"
,
addr
);
break
;
abort
();
default:
}
fprintf
(
stderr
,
"Unknown register write %lx
\n
"
,
addr
);
abort
();
}
}
}
void
void
Corundum
::
setup_intro
(
struct
cosim_pcie_proto_dev_intro
&
di
)
{
Corundum
::
setup_intro
(
struct
cosim_pcie_proto_dev_intro
&
di
)
di
.
bars
[
0
].
len
=
1
<<
24
;
{
di
.
bars
[
0
].
flags
=
COSIM_PCIE_PROTO_BAR_64
;
di
.
bars
[
0
].
len
=
1
<<
24
;
di
.
pci_vendor_id
=
0x5543
;
di
.
bars
[
0
].
flags
=
COSIM_PCIE_PROTO_BAR_64
;
di
.
pci_device_id
=
0x1001
;
di
.
pci_vendor_id
=
0x5543
;
di
.
pci_class
=
0x02
;
di
.
pci_device_id
=
0x1001
;
di
.
pci_subclass
=
0x00
;
di
.
pci_class
=
0x02
;
di
.
pci_revision
=
0x00
;
di
.
pci_subclass
=
0x00
;
di
.
pci_msi_nvecs
=
32
;
di
.
pci_revision
=
0x00
;
di
.
pci_msi_nvecs
=
32
;
}
}
void
void
Corundum
::
dma_complete
(
nicbm
::
DMAOp
&
op
)
{
Corundum
::
dma_complete
(
nicbm
::
DMAOp
&
op
)
DMAOp
*
op_
=
reinterpret_cast
<
DMAOp
*>
(
&
op
);
{
op_
->
ring
->
dmaDone
(
op_
);
DMAOp
*
op_
=
reinterpret_cast
<
DMAOp
*>
(
&
op
);
op_
->
ring
->
dmaDone
(
op_
);
}
}
void
void
Corundum
::
eth_rx
(
uint8_t
port
,
const
void
*
data
,
size_t
len
)
{
Corundum
::
eth_rx
(
uint8_t
port
,
const
void
*
data
,
size_t
len
)
RxData
*
rx_data
=
new
RxData
;
{
memcpy
((
void
*
)
rx_data
->
data
,
data
,
len
);
RxData
*
rx_data
=
new
RxData
;
rx_data
->
len
=
len
;
memcpy
((
void
*
)
rx_data
->
data
,
data
,
len
);
rxRing
.
rx
(
rx_data
);
rx_data
->
len
=
len
;
rxRing
.
rx
(
rx_data
);
}
}
}
// namespace corundum
}
// namespace corundum
using
namespace
corundum
;
int
main
(
int
argc
,
char
*
argv
[])
{
corundum
::
Corundum
dev
;
int
main
(
int
argc
,
char
*
argv
[])
runner
=
new
nicbm
::
Runner
(
dev
);
{
return
runner
->
runMain
(
argc
,
argv
);
Corundum
dev
;
runner
=
new
nicbm
::
Runner
(
dev
);
return
runner
->
runMain
(
argc
,
argv
);
}
}
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