Version 0.86 beta, September 2012.
This DPI module allows you to interact with a Verilator simulation using standard Ethernet network tools like ping or Wireshark.
It is like running a virtual PC with VirtualBox: your SoC simulation would be the virtual PC, Verilator would be VirtualBox, and this Ethernet DPI module acts as the network bridge software built into VirtualBox.
The simulated System-on-a-Chip (SoC) becomes a virtual Ethernet controller compatible with the one normally used in OpenRISC designs, see the testbench in the MinSoC project for a practical example. The Ethernet controller's registers are available as memory locations on a Wishbone slave interface, and data transfers take place on a separate Wishbone master interface (DMA style).
The user must create a virtual TAP network interface on the host system where the simulation runs. The TAP interface also provides a virtual Ethernet cable, and this DPI module acts as a bridge between that virtual cable and the virtual Ethernet controller in the simulation.
This module contains a few extra checks to make sure that the software driving the Ethernet controller behaves appropriately. You may find it helpful when debugging your ethernet driver, or when porting it to another operating system or platform. The OpenRISC simulator (as of Dic 2011) and the synthesized Ethernet controller (also as of Dic 2011) provide no such error checking.
The Linux and eCos drivers assume that the received 32-bit Ethernet CRC is always appended, although it's actually discarded.
The TAP interface does not use CRCs, so this DPI module does not calculate, send or receive one. However, before handing an ethernet frame over to the user, this module always appends 4 bytes with the dummy CRC value 0xDEADF00D.
The real Ethernet interface, at least as included in the MinSoC project as of Dic 2011, does not seem to take the lower 2 bits of the 32-bit Wishbone memory addresses, it assumes that they are always zero. However, this simulation model takes all the bits and checks that the 2 lower bits are actually zero, as all memory addresses must be 32-bit aligned.
This module does not attempt to simulate any Ethernet timing, the simulated SoC sees an extremely fast Ethernet network.
If your design is sensitive to timing, it will not work properly.
There is an optional gap of one Wishbone cycle between DMA memory transfers, so that higher-priority bus masters can interrupt long Ethernet DMA transfers. Otherwise, a debugger connecting via JTAG may not be able to access memory in a timely manner. See parameter INSERT_WAIT_STATE_BETWEEN_DMA_ACCESSES.
This wait state might not be necessary with an enhanced traffic COP that were able to interrupt transfers if a higher-priority master comes along, but I am not sure that such an enhancement is possible within the boundaries of the Wishbone specification, at least when not using plain classic transfers (when using the burst or pipeline modes). [Later note: the new simple_wishbone_switch component does interrupt Wishbone cycles, so the wait state should no longer be necessary, at least for that particular switch]
There are never network transmission errors
The TAP interface provides a virtual Ethernet cable where collision or transmission errors are not possible.
The Retransmission Limit (RL) error flag in the Tx Buffer Descriptor is never set, the Ethernet model will wait forever for the TAP interface to accept the next frame. The Retry Count (RTRY) in the Tx Buffer Descriptor will always be set to 0. The Underrun (UR), Defer Indication (DI) and Carrier Sense Lost (CS) flags will always be set to 0 upon transmission.
The minimum frame length feature does not work
The minimum Ethernet frame length can be configured in the PACKETLEN register and is normally set to 64 bytes. The minimum Ethernet payload size is normally 46 bytes. However, the TAP interface does not seem to add any padding. For example, frames generated by the 'arping' tool are only 42 bytes long, and exactly that many bytes are received when reading the frame off the TAP interface.
I am uncertain where the limit should be or how to handle small packets in this respect. Until I get to know more, the minimum frame length (MINFL in PACKETLEN and RECSMALL in the Rx Buffer descriptors) is ignored, and the bit Short Frame (SF) bit in the Rx Buffer Descriptors is never set upon frame reception. The PAD bit in the MODER register is also ignored.
Ethernet Control Frames are not supported
The Ethernet Pause frame, used for flow control, is sent as a Control Frame and therefore is not supported either.
The BUSY interrupt is not supported
There is never a receive overflow: if there are no receive buffers available, no further frames will be read from the TAP interface. If the internal TAP buffer overflows and discards frames, the user of this Ethernet module will never know.
MAC address recognition with hash tables is not supported
This is beta sofware and has not been thoroughly tested. Besides, I am no Ethernet expert, so there may be some rough edges left. Your feedback will be greatly appreciated. Testers with Ethernet controller experience are specially welcome.
Note that the current version has been developed and tested only on Linux.
This package is implemented as a SystemVerilog DPI module, SystemC is not used or required. I have only tested it with Verilator, but there's nothing Verilator-specific, so it should be possible to run it on any standard Verilog simulator.
I don't have access to other commercial simulators to test the Ethernet DPI module on, help is welcome. Cygwin and BSD maintainers are also welcome.
You need to be familiar with Verilator or your simulator of choice, as you need to add file ethernet_dpi.cpp to the generated C++ code. There are a few ways to do that:
Alternative 1) Add ethernet_dpi.cpp to the Verilator command line.
Alternative 2) Include ethernet_dpi.cpp from your main .cpp file (with #include).
Alternative 3) Edit the makefile you are using.
You also need to add file ethernet_dpi.v to the Verilog sources and connect its Verilog module to some Wishbone master. Here is an instantiation example:
ethernet_dpi ethmac (
// WISHBONE common signals.
.wb_clk_i ( wb_clk ),
.wb_rst_i ( wb_rst ),
// WISHBONE slave interface to access the Ethernet controller registers.
.wb_dat_i ( wb_es_dat_i ),
.wb_dat_o ( wb_es_dat_o ),
.wb_adr_i ( wb_es_adr_i ), // WARNING: All 32 address bits are taken, this may be different from the real Ethernet model.
.wb_sel_i ( wb_es_sel_i ),
.wb_we_i ( wb_es_we_i ),
.wb_cyc_i ( wb_es_cyc_i ),
.wb_stb_i ( wb_es_stb_i ),
.wb_ack_o ( wb_es_ack_o ),
.wb_err_o ( wb_es_err_o ),
// WISHBONE master interface for DMA transfers.
.m_wb_adr_o ( wb_em_adr_o ),
.m_wb_sel_o ( wb_em_sel_o ),
.m_wb_we_o ( wb_em_we_o ),
.m_wb_dat_o ( wb_em_dat_o ),
.m_wb_dat_i ( wb_em_dat_i ),
.m_wb_cyc_o ( wb_em_cyc_o ),
.m_wb_stb_o ( wb_em_stb_o ),
.m_wb_ack_i ( wb_em_ack_i ),
.m_wb_err_i ( wb_em_err_i ),
// Interrupt signal.
.int_o ( pic_ints[`APP_INT_ETH] )
);
Note that the memory addresses where the Ethernet controller registers are mapped to must be non-cacheable or be marked with some "cache inhibited" flag. Similarly, the memory buffers referenced by the Ethernet Buffer Descriptors are read from and written to in a DMA style and should also be marked as non-cacheable. Alternatively, the data cache must be flushed/synchronised before sending or receiving an Ethernet frame.
This DPI module assumes that a persistent TAP interface already exists in the host computer. There are several ways to create one, check out your operating system's documentation for details. For example, under Ubuntu 10.04 you can install the openvpn package, although the tunctl tool in package uml-utilities would also do. You must be root in order to be able to create a TAP interface, or, alternatively, your account must have the CAP_NET_ADMIN capability. The following works for me:
# Create the interface.
sudo openvpn --dev-type tap --dev dpi-tap1 --mktun --user "$USER" --group "$USER"
# Configure and start it. Consult your network administrator for
# the best address to use in your environment.
sudo ifconfig dpi-tap1 192.168.254.254 up
# Optionally check that the new interface is there, look for the "dpi-tap1" name in the list.
ifconfig
# Use the interface here.
# For example, with this command you can generate one ARP Ethernet frame on the TAP interface,
# which is then received by the simulated SoC:
# sudo arping -c 1 -f -w 10 -I dpi-tap1 192.168.254.1
...
# Delete the interface.
sudo openvpn --dev-type tap --dev dpi-tap1 --rmtun
# Optionally check that the interface is gone, visually check that "dpi-tap1" is gone.
ifconfig
It is possible to set up an ethernet bridge between the TAP interface and your physical network so that your simulated SoC can communicate with other computers on your network, or even with the Internet. Consult your operating system's documentation for further information.
If you need to write a software driver in order to control this Ethernet simulation model or the real Ethernet core, you do not need to start from scratch, you can take a look at one of the following existing drivers:
File ethernet_example.c included with this simulation module
This is a very simple software driver mainly used for testing purposes.
OpenCore's version of uclinux for the OpenRISC platform
Take a look at files open_eth.h and open_eth.c under uclinux/drivers/net/open_eth.c .
OpenCore's Linux for the OpenRISC platform
Look for the open_eth driver in the or32 Linux port.
OpenCore's orpmon bootloader for the OpenRISC platform
Look for files eth.h and eth.c .
Other bootloaders, like Das U-Boot (Universal Bootloader) , may have ethernet drivers too.
eCos
The eCos operating system has an ethernet driver, take a look at this bug report:
Bug 1000153 - Added driver for Opencores 10/100 Mbit ethernet driver
RTEMS
The RTEMS operating system has an ethernet driver, look for the open_eth driver and its README.open_eth file.
Copyright (C) R. Diez 2011, rdiezmail-openrisc at yahoo.de
The Ethernet DPI source code is released under the LGPL 3 license.
This document is released under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) license.