Does OpenCPI support checkpoint files for OSP development? For instance, if I have a firmware bitstream which loads when the OS boots and I want my HDL worker to operate within this wrapper.
No, right now OpenCPI doesn’t have this capability.
If I understand your question correctly, your looking for a feature that exports OpenCPI HDL assembly / container into a design check point (.dcp) file that can be imported it into an existing platforms build process.
Currently OpenCPI requires OSP developers to control the entire FPGA fabric. This is where all clocks and interconnect interfaces are defined such that it comes down to building an HDL assembly all the necessary IP is there to support it.
We’ve actually been discussing this internally for sometime. Such a capability would ease platform developers integration into existing platforms and allow users to drop in OpenCPI functionality into existing builds and platforms.
Is that what you were thinking?
Speaking very very roughly here, what is possible in that setup if you have access to the top level (as in, you can change what ports are on the top level of the dcp) is:
- You pipe out one M_AXI_GP
- Various widths are possible, but 32 address 32 data works.
- This needs a specific base address (0xA0000000 off the top of my head) and at least 64MB (off the top of my head) of range
- IIRC, you don’t actually need to set this in Vivado. You can leave the port unmapped.
- You pipe out two S_AXI_HP
- Various widths are possible, but 32 address 64 data works.
- Pipe out a clk and a reset (sync or async).
That is enough to implement an OpenCPI Platform Worker (you might be able to get away with less). Every other dcp pin can be set to a pin in the Platform Worker XML and will passthrough directly to a top level pin.
Your dcp can then be in the sourcefiles of the Platform Worker.
The constraints file can be just a dump of the checkpoints constraints, with the current_instance commands regex changed to move where the dcp is in the hierarchy (your top level is now “deeper” in the design so the constraints will reference the wrong location).
That’s a very rough description, but that’s the simplest existing top level DCP → OSP flow possible changing as little of the dcp as you can.
I can expand on this if helpful.
I agree @waltersdom all the pieces are already there for zynq and zynq_ultra platforms we just need a reproducible process flushed out and document it. If we stick to the same address spaces as you suggested would be easiest but perhaps add configurability to addresses would provide more flexibility.
Hi, thanks for your reply. Yes this is my thinking
Hi, thanks for your reply. This is very helpful. I will give this a try, I’m new to OSP development so I may have some questions.
Hi @waltersdom,
Am I understanding correctly that you are suggesting the following structure?
Can partition pins then be connected to component ports in an Application Spec as shown?
What do I need to do instantiate the DCP in the platform worker? Normally this would be an instance declared in another VHDL file.
Is the platform worker bitstream loaded when I run mysetup.sh and I therefore need to to change the OS so it doesn’t load the bitstream on boot?
Yes, this image is broadly correct.
If the A/B pins just go directly to an external FPGA IC Pin then you can do that directly on the Platform Worker, removing the need for E/F. Although you may still choose that approach if you want for partitioning reasons (associating it to the function of the Device Worker, or if there is some intermediate processing required, etc).
Can partition pins then be connected to component ports in an Application Spec as shown?
Not sure I fully understand what this means, so I’ll give a concrete example (in the below, I’ve highlighted as many OpenCPI XML terms as possible as code).
Say the .dcp pins S/T are actually an AXI Stream interface for something, perhaps an IQ stream from/to an RF transceiver. U/V would be defined as a devsignal interface, and your hdldevice then does the translation to the expected protocol (U/V => W/X) and presents the interface as a port. Your hdlplatform would then have some hdlconfig that instantiates this hdldevice, making the port accessible to an assembly.
You can then use this port in a hdlcontainer within an assembly, binding it to some external connection defined in the assembly.
What do I need to do instantiate the DCP in the platform worker? Normally this would be an instance declared in another VHDL file.
At the minimum you need to include the .dcp in the sourcefiles for the hdlplatform, and then define the VHDL component for the .dcp somewhere. This could be in the VHDL architecture declaration region, or in a VHDL package that you then include. If your .dcp is written directly out of Vivado, you can have it produce a VHDL package declaration as well I think.
Then instantiate it in the hdlplatform VHDL file and wire up all the necessary signals (primarily the clocks, resets, and the AXI control lanes). For this part, I’d look at the other existing hdlplatforms for a reference; zed if your on Zynq7000, or zcu104 if on Ultrascale MPSoC.
Is the platform worker bitstream loaded when I run mysetup.sh and I therefore need to to change the OS so it doesn’t load the bitstream on boot?
mysetup.sh will load the testbias assembly for your platform. I think there can already be a bitstream loaded at boot and the mysetup.sh will just reload over it, then assert the OpenCPI reset as it starts. If that’s not okay for your platform, then yes it should be prevented from loading.
Alternatively, you could have it load the OpenCPI testbias bitstream on boot instead. This could be useful if, for example, the FPGA is in control of front panel buttons or LEDs that you want to be functional as the system boots.
