Launching the Pothos FPGA project Fri, Oct 31 2014 AM
For the last two weeks I have been putting together the ground work for the Pothos FPGA project. The immediate goal is to demonstrate heterogeneous computational flow in Pothos with the FPGA. In the long run, this will provide valuable simulation, debugging, and architectural tools for developers working with FPGAs. Take a look at the Pothos FPGA project page.
The project basically consists of:
- A configurable streaming interconnect fabric
- Host libraries to configure the interconnect
- Host-based blocks for FPGA topology integration
- FPGA DMA blocks for specific platforms like Zynq
- Host-based plugins for specific FPGA platforms
I'm familiar with both the Altera Avalon streaming and the Xilinx AXI streaming standards, and used both standards in prior projects. They are basically the same standard as far as streaming is concerned (data, valid, and backpressure). So, I chose the Avalon standard, but borrowed the AXI conventions for packet signals due to their brevity. Meaning, "endofpacket" is called "last", and startofpacket is dropped due to few implementations using this signal. The interconnect library provides a StreamInspector which can replicate the startofpacket signal if its needed.
I created a configurable interconnect module in VHDL with adaptable bus width and fabric complexity. The interconnect provides a configuration bus and a variable number of input and output ports. User-created processing blocks, source blocks, sink blocks, and DMA blocks can connect to the various ports to gain configurable connectivity for both data and control flows.
In addition to the stream standard, the interconnect ports use an additional wire for signaling packet metadata, and an additional backpressure wire for signaling packet-level flow control through the interconnect fabric. The "meta" signal allows processing implementations to be agnostic to packet formats by differenting between stream elements and the packet header or trailer contents. The "begin" signal allows consumers to indicate their readiness to a producer about space availability; the intention being to avoid serious interconnect backpressure within the middle of a packet transfer. Read more about these signals in the documentation below:
It turns out that Pothos is also a pretty good tool for driving FPGA simulations. The feeder and collector blocks (which support pseudorandom test plans) are used in many of the existing unit tests to proof data integrity. And thats exactly what I need to rapidly and thoroughly test the various FPGA modules that make up the interconnect.
Bridging VHDL to Pothos
First off, we are using GHDL as a checker and compiler. Its free, easy to install through the package manager, and can interface with C through foreign functions/procedures. Using the foreign interface support, I created C functions to bridge a Pothos C++ source and sink block to a VHDL simulation source and sink block. Basically, when a simulation instantiates an external source or sink module, the bindings create corresponding blocks over in the Pothos/C++ domain. Check it out:
Executing GHDL simulations
So, GHDL builds an executable to run the simulations. This means that our unit tests will need to execute the simulation binaries, and connect to the source and sink blocks created by the simulation. Fortunately, one of Pothos's major strengths is that dealing with remote objects is essentially transparent. Therefore, the simulation is going to start a Pothos proxy server, and the unit test will connect to this proxy server just like any other remote client, access the simulation blocks, instantiate other test blocks, and connect them into a topology.
This magic is all packaged up into getSimulationEnv(). The getSimulationEnv() call executes the simulation, connects to proxy server inside the simulation process, and returns a proxy environment to the caller. This environment is used to interact transparently with the remote process. At this point, using the environment, the rest of the test is identical in style to all the other regular block tests. Take a look at the code for the simulation environment client/server: