Legacy documentation: The DPR targets, runtime API, and example described in this guide are not present in the current ESP source tree. The guide is retained as a historical record of an earlier AMD/Xilinx flow. Consult the official
esp_dpr_flow_integrationbranch for the latest public DPR development snapshot; it is not part of ESP 2026.1.0.
Dynamic partial reconfiguration (DPR) modifies a portion of the FPGA logic at runtime without requiring a reload of the full bitstream. In ESP, DPR allows the user to swap accelerators on the fly. ESP accelerator tiles are partially reconfigurable, while the other tile types form the static region.
DPR also enabled incremental compilation of ESP SoC designs during iterative FPGA implementation, when only some of the SoC accelerators changed in each iteration. The incremental flow detected the modified reconfigurable tiles and generated new partial bitstreams (PBS) only for them, reducing design recompilation time.
This guide introduces the historical ESP DPR FPGA flow and runtime swapping of accelerators using bare-metal and Linux applications. It also illustrates incremental compilation for accelerators inside ESP SoCs.
This archived guide documents the AMD/Xilinx VC707 evaluation-board flow.
Later VCU118 and VCU128 work exists on the development branch above; verify
the branch revision, tool versions, and board status before using it.
Historical platform support: This flow used AMD/Xilinx partial-reconfiguration infrastructure and did not support Intel/Altera.
1. DPR on a single accelerator SoC
The first part of the tutorial covers the DPR flow with a default SoC configuration, which consists of a 2x2 mesh with one processor tile,
one memory tile, one auxiliary tile, and a single accelerator tile. This guide illustrates DPR using the Adder accelerator from the ESP repo and
the MAC accelerator that was designed using the C/C++ Vivado HLS flow.
Both accelerators can be found inside <esp>/accelerators/vivado_hls/. ESP supports DPR for SoCs with Leon3 or Ariane processor cores.
This tutorial assumes that system designers are familiar with the ESP infrastructure and know how to run basic make targets to create a simple instance of ESP, integrating just a single core and the various ESP accelerator design flows. Please make sure the DPR environment is also set correctly before running this guide.
The DPR flow is executed in two phases. In the first phase we create an SoC with an instance of the MAC accelerator and implement it on the FPGA. The first phase compiles the entire SoC (the processor, memory, I/O, and MAC accelerator tiles). It generates a full bitstream for the SoC and a partial bitstream for the MAC accelerator.
The second phase is an incremental compilation of the design, where the MAC is replaced with the ADDER accelerator followed by reimplementation of the design. Unlike the first implementation, this incremental step compiles only the ADDER accelerator. The same applies to subsequent implementations that modify only the accelerator tile.
HLS and SoC configuration
This tutorial targeted the Xilinx VC707 evaluation board, which uses a Virtex-7 FPGA.
# Move to the Xilinx VC707 working folder
cd <esp>/socs/xilinx-vc707-xc7vx485t
Then generate the RTL for both accelerators inside the design folder using the following make targets.
# Generate the RTL for both accelerators
make adder_vivado-hls
make mac_vivado-hls
When the RTL generation finishes, the SoC is first configured with an instance of MAC accelerator.
The SoC configuration can be visualized and modified with the ESP configuration GUI:
make esp-xconfig

Note: Make sure you check the Enable Partial-reconf button on the GUI.
FPGA implementation
FPGA compilation of the SoC is fully automated with a single make target.
make vivado-syn-dpr
This make target starts by replacing the accelerators inside the static part with black-box instances and then synthesizes the static part and the reconfigurable accelerator RTL using separate Vivado instances. It then automates DPR floorplanning using the open-source FLORA tool. Finally, it performs place and route (P&R) and bitstream generation by plugging the synthesized accelerator netlist into the static netlist.
At the end of this step, the full bitstream of the design is located at <esp>/socs/xilinx-vc707-xc7vx485t/vivado_dpr/Bitstreams/acc_bs.bit,
while the PBS for the MAC accelerator is located inside <esp>/socs/xilinx-vc707-xc7vx485t/partial_bitstreams/mac_vivado_<tile_id>.bin.
# List of files generated and modified by the DPR flow
<esp>/socs/<soc_design_folder>
├── partial_bitstreams
│ └── mac_vivado_<tile_id>.bin # accelerator PBS
│
├── socgen
│ └── esp
│ └── pbs_map.h #PBS descriptor
│
└── vivado_dpr
├── Synth #folder for synthesized RTL of the design
│ ├── Static #synthesized static netlist
│ └── mac_vivado_<tile_id> #synthesized acc netlist
│
├── Implement
│ └── top_dpr #routed static part
│
└── Bitstreams
└── acc_bs.bit #full bitstream of the design
The flow also generates a PBS descriptor (a struct named bs_descriptor) inside
<esp>/socs/xilinx-vc707-xc7vx485t/socgen/esp/pbs_map.h that enables software
to manage PBS at runtime. The descriptor contains specific information about the name, size, and tile_id of the PBS.
#define LEN_DEVNAME_MAX 32
typedef struct pbs_map {
char name [LEN_DEVNAME_MAX]; //name_of_accelerator
unsigned pbs_size; //size of *PBS* in bytes
unsigned long long pbs_addr; //*PBS* addr offset in memory
unsigned pbs_tile_id; //accelerator tile_id
}pbs_map;
Incremental compilation
Following the successful implementation of the first SoC instance, subsequent accelerators
are compiled using the incremental flow. To do so, MAC is replaced with Adder in the accelerator tile
and the design is recompiled.
Once again launch the ESP configuration GUI and replace MAC with Adder inside the accelerator tile.
Then run the make target for an incremental compilation
# Make target for incremental compilation
make vivado-syn-dpr-acc
Note: The make target for incremental DPR compilation is slightly different from the one for a full DPR compilation.
The incremental FPGA flow performs the following:
- Compares the old and the new SoC configurations to detect the newly modified accelerator tiles.
- Performs RTL synthesis only for the modified accelerators.
- Checks if the old accelerator tile contains enough resources for the new one.
Best case scenario–> If there are enough resources, then it performs P&R only on the new accelerator RTL on top of the previously pre-routed static part and generates PBS for the new accelerators.Worst case scenario–> If there are not enough resources, then it creates a new floorplan for all accelerator tiles (modified and unmodified) and performs P&R on the full SoC (including the static part).
Note: Even in the worst case, the incremental compilation reduces the design runtime by avoiding to re-synthesize the static part and the unmodified accelerators.
This step finishes by adding <esp>/socs/xilinx-vc707-xc7vx485t/partial_bitstreams/ with the newly generated Adder PBS
and updating the PBS descriptor inside <esp>/socs/xilinx-vc707-xc7vx485t/socgen/esp/pbs_map.h.
2. Runtime reconfiguration
The auxiliary tile integrates a partial reconfiguration controller (PRC) IP from Xilinx that is responsible for loading accelerator PBS at runtime. The ESP software stack provides bare-metal and Linux device-driver APIs to control the reconfiguration from software. The drivers are also seamlessly compiled together with the applications.
Enabling DPR requires minimal modification to the source code of the bare-metal or Linux applications that are generated in the various accelerator design flows.
Bare-metal applications
To swap accelerators at runtime, bare-metal applications need to include a single header file and a single driver API call.
The reconfiguration is triggered using the reconfigure_FPGA function call from the driver API:
int reconfigure_FPGA(struct esp_device *dev, int pbs_id);
On a high-level the function initializes and configures the PRC based on the PBS descriptor, decouples the accelerator tile, and finally starts the reconfiguration. The return value of the function signifies the success of the reconfiguration.
The following is a skeleton of an example bare-metal application that can be used to switch between the Adder and MAC
accelerators that were designed in this guide. The full C source of the application can be found in
<esp>/soft/common/apps/baremetal/dpr_multi_acc/dpr_multi_acc.c
Bare-metal application skeleton
#include "prc_utils.h" // Contains DPR-related declarations and definitions
#define DEV_NAME_ADDER "sld,adder_vivado" // Name of the Adder accelerator in ESP
#define DEV_NAME_MAC "sld,mac_vivado" // Name of the MAC accelerator in ESP
int main(int argc, char * argv[])
{
struct esp_device *dev_tile_1;
// Probe the tile
probe(&dev_tile_1, VENDOR_SLD, SLD_ACC_TILE_1, DEV_NAME_ADDER);
// Load the Adder PBS
reconfigure_FPGA(dev_tile_1, 0);
/*<invoke Adder accelerator and wait until done>*/
// Load the MAC PBS
reconfigure_FPGA(dev_tile_1, 1);
/*<invoke MAC accelerator and wait until done>*/
}