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
"src/vscode:/vscode.git/clone" did not exist on "92fe689f06bcec27c4f48cb90574c2b9c42c643b"
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