Replies: 3 comments 6 replies
-
Can we nic-loopback it?Looking through the git history for So, after following the Chipyard Repo Setup docs, then: MAKEFLAGS=-j`nproc` make -C sims/verilator VERILATOR_THREADS=1
make -C tests nic-loopback.riscv followed by: time ./sims/verilator/simulator-chipyard.harness-RocketConfig +permissive +max-cycles=10000000 +permissive-off tests/nic-loopback.riscv produces this output:
Next ideas:
|
Beta Was this translation helpful? Give feedback.
-
Can we tuntap it?Since we're going for connecting a user-space program (the simulated risc-v chip) into the network, there's also the matter of getting the other "end" of that virtual link cable connected to something. In Linux, "I want to connect my userspace program to a virtual network device" has a spelling of tun/tap. They're a little awkward to use, but with help from these two resources:
(and more than a few hours of failed experiments), I managed to setupsubnet=0
for mode in tun tap; do
sudo ip tuntap add "${mode}2" mode "${mode}" user $USER
sudo ip addr add 10.0."$(( subnet++ ))".1/24 dev "${mode}2"
sudo sysctl -w net.ipv6.conf."${mode}"2.disable_ipv6=1
sudo ip link set "${mode}2" up
done
sudo ip neigh add 10.0.1.2 dev tap2 lladdr "$(ip --brief link show tap2 | awk '{print $3}' )" nud permanent That creates a A A run itSave this somewhere, maybe as import struct
from fcntl import ioctl
def open_dev(mode, name=b''):
fd = open("/dev/net/tun", "r+b", buffering=0)
LINUX_IFF_TUN = 0x0001
LINUX_IFF_TAP = 0x0002
LINUX_IFF_NO_PI = 0x1000
LINUX_TUNSETIFF = 0x400454CA
flags = LINUX_IFF_NO_PI
if mode == 'tun':
flags |= LINUX_IFF_TUN
else:
flags |= LINUX_IFF_TAP
ifs = struct.pack("16sH22s", name, flags, b"")
ioctl(fd, LINUX_TUNSETIFF, ifs)
return fd
import sys
if sys.argv[1] not in ['tap', 'tun']:
print(f'invalid mode: {sys.argv[1]}', file=sys.stderr)
print(f'usage: {sys.argv[0]} tap|tun [DEV_NAME]', file=sys.stderr)
sys.exit(2)
mode = sys.argv[1]
dev = open_dev(mode, (sys.argv[2:] or [''])[0].encode('utf=8'))
offset = 0 if mode == 'tun' else 14
while True:
data = dev.read(1500)
if len(data) == 0:
break
print(data.hex())
reply = bytearray(data)
ip_pkt = reply[offset:]
# swap source & dest IP (doesn't change checksum)
ip_pkt[12:16], ip_pkt[16:20] = ip_pkt[16:20], ip_pkt[12:16]
# change from ICMP echo request (8) to ip_pkt (0)
ip_pkt[20] = 0
ip_pkt[22] = (ip_pkt[22] + 8) % 256 # fixup checksum
reply[offset:] = ip_pkt
# also swap src & dst mac addrs when we're in 'tap' mode
if mode == 'tap':
reply[0:6], reply[6:12] = reply[6:12], reply[0:6]
dev.write(reply)
print("-> ", reply.hex()) Then, run: $ python pingd.py tun tun2
# or, python pingd.py tap tap2
# in another terminal
$ ping -nc2 10.0.0.2
# or, 10.0.1.2 if you ran in `tap` mode And you should see familiar ping output:
with output similar to the following from the python side:
Which we can plug into the handy https://hpd.gasmi.net :
To see that we've got an ICMP echo ping request/reply. notes
cleanupStop any running python programs (lest you see for mode in tun tap; do sudo ip tuntap del "${mode}2" mode "${mode}"; done next steps ?
wrapping up / what was it all forSo, we pinged it! Now, "all" we have to do is "simply" replace our More concretely (and the reason I've taken at least 2x as long to write this up as it did to get a little janky prototype working), this can act as a point of reference when something goes wrong in hooking up the verilog RTL simulation. If it works with Footnotes
|
Beta Was this translation helpful? Give feedback.
-
Yes, we can! (Simulate it)Adding this config somewhere in the Chipyard Cinematic Universe (I put it in PeripheralDeviceConfigs.scala): class TapNICRocketConfig extends Config(
new chipyard.harness.WithSimNetwork ++
new icenet.WithIceNIC ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) Reading from the bottom up (because that's how scala evaluates it), we've got:
With that in hand, we can run:
(why With everything set up, that produces a
These are very similar to "can we tuntap it" above; the last bit compiles the Now we can run:
Which reads: "run the simulator, letting me pass arbitrary plusargs, throw "netdev=tap0" into the void and hope SimNetwork reads it, turn strict argument parsing back on, and simulate running the bare-metal binary After quite a while (~80s on my machine), that'll print out something like
(Note the Hooray, a 2 second ping to localhost! The first one takes a bit longer because, unlike the simpler Finally, if you wanted to see the
The real standout, of course, is the iTLB misses: Potential next avenues (in increasing order of difficulty):
|
Beta Was this translation helpful? Give feedback.
-
Tracking notes/discussion thread for the goal: "Can we run Chipyard's pingd test?"
The second question is on hold for now, as I'm lacking the desire to get too into part selection yet—e.g. none of the diligent dev gear has two ethernet ports, the minimum required for an interesting router (though a single 10/100MB port would work for a ping test).
Pinging the simulated SoC
In order to ping the SoC from my Linux host, we'd have to connect the I/O somehow from the outside world. In other contexts (e.g. containers) I've done this with a veth interface, but there's a whole bunch of options for "thing that can be passed to the
-I
flag of ping."The harder challenge is probably going to be figuring out how to get the
verilator
simulation host to set itself up to translate the SoC's read attempts to interact with theveth
(or whichever). That's going to reward understanding at least a little bit about what the IceNet "thing" is, and what I/O "looks like".Some possible resources:
Beta Was this translation helpful? Give feedback.
All reactions