Partial Reconfiguration via ICAP

Hello,

I’m trying to dynimically reconfigure my PYNQ Z2 board via ICAP but I’m not sure of the way to do it. From PG585, now I know that I have to modify devConfig register by writting 1 at the 27th bit (PCAP_MODE) et 0 at the 26th bit (PCAP_PR) of devConfig Control register. So I did it like that in the Jupyter book:

XDCFG_BASE_ADDRESS = 0xF8007000
PCAP_MODE = 26
PCAP_PR = 27
dev_cfg_ctrl = overlay.Register(XDCFG_BASE_ADDRESS)
dev_cfg_ctrl[PCAP_MODE] = 1
dev_cfg_ctrl[PCAP_PR] = 0

Now I am wondering if it is enough to just use pr_download to partially reconfigure my board via ICAP? For example by writting something like that:

from pynq import Overlay
overlay = Overlay(“./bitstreams/static_full.bit”)
overlay.pr_download(“ACCEL_0”, “./bitstreams/pd0_rm1_sleep.bit”)

Hereunder is my design:

Thanks for your reply!

Another view of my design to see what IP I’m using for partial reconfiguration:

Hi @PierrMa,

Welcome to the PYNQ community.

Is there any particular reason you are using the ICAP? PYNQ support partial reconfiguration without the need to add this IP.

https://pynq.readthedocs.io/en/latest/overlay_design_methodology/partial_reconfiguration.html

You can check a proven instance of this with the Composable Overlay.

https://pynq-composable.readthedocs.io/en/latest/

Mario

Hi Mario,

Thanks for your reply!
I already have a design using PCAP for partial reconfiguration in the way mentionning on this link : Partial Reconfiguration — Python productivity for Zynq (Pynq) . However I want to use ICAP to improve Partial reconfiguration delays. The thing is that I’m neither sure of my hardware design nor of my Pynq overlay program.

I saw the video on composable overlay but I don’t think it is a solution for me because it consume more silicon whereas the goal of partial reconfiguration is to do temporal multiplexing and by that improving footprint and energy consumption.

To be honnest, I’m quite confidente that using only pr_download is not enough to do partial reconfiguration via ICAP. That’s why I’ve writing a function to read and write via ICAP given that the information found in PG349 p20-21 (AMD Adaptive Computing Documentation Portal) . Hereunder are my functions:

#configure dev Config to allow DPR via ICAP
XDCFG_BASE_ADDRESS = 0xF8007000 #(find in the UG585)
PCAP_MODE = 26
PCAP_PR = 27
dev_cfg_ctrl = overlay.Register(XDCFG_BASE_ADDRESS)
dev_cfg_ctrl[PCAP_MODE] = 1
dev_cfg_ctrl[PCAP_PR] = 0

#define constants for AXI_HBICAP
AXI_HBICAP_S_AXI = 0X8AA00000
AXI_HBICAP_S_AXI_CTRL = 0X40030000
SIZE_REGISTER = overlay.Register(AXI_HBICAP_S_AXI_CTRL + 0X108)
CONTROL_REGISTER = overlay.Register(AXI_HBICAP_S_AXI_CTRL + 0X10C)
STATUS_REGISTER = overlay.Register(AXI_HBICAP_S_AXI_CTRL + 0X110)

AXI_HBICAP_S_AXI_MMIO = MMIO(AXI_HBICAP_S_AXI,0x10000)
AXI_HBICAP_S_AXI_CTRL_MMIO = MMIO(AXI_HBICAP_S_AXI_CTRL,0x10000)

##function to read via ICAP
#first_write_size = number of 32-bit words in the first set to be write
#read_size = number of 32-bit words to be read
#second_write_size = number of 32-bit words in the second set to be write
#data = data to be transferred

def read_ICAP(first_set,second_set,first_write_size,read_size,second_write_size):
#1-Program the Size register with the number of words to write
SIZE_REGISTER = first_write_size

#2-Send the first set or words to be write to the ICAP
AXI_HBICAP_S_AXI_MMIO.write(0,first_set)

#3-Wait for the Done signal from the Status register
while(STATUS_REGISTER[0]!=1):
time.sleep(0.001)

#4-Program the Size register with the number of words to be read from the ICAP
SIZE_REGISTER = read_size

#5-Initiate a read on the ICAP
CONTROL_REGISTER = 0X00000002

#6-Use the chosen read interface
AXI_HBICAP_S_AXI_MMIO.read(0,read_size)

#7-Wait until the ICAP is available for another transaction
while CONTROL_REGISTER[1] == 1:
time.sleep(0.001)

#8-write DE-SYNC and other commands to terminate the Read operation on the ICAP
SIZE_REGISTER = second_write_size
#9-Send the commands using the memory mapped AXI4 interface
AXI_HBICAP_S_AXI_MMIO.write(0,second_set)

#10-Return the Done signal to check if the requested number of words have been written on the ICAP interface
return STATUS_REGISTER[0]

##function to write via ICAP
#size : number of words to be transferred
#data : data to be write to the ICAP
def write_ICAP(size,data):

#1-Program the number of words to be transferred
if size>256: return ‘error’
else: SIZE_REGISTER = size

#2-send burst transaction from memory mapped AXI4 interface
AXI_HBICAP_S_AXI_MMIO.write(0,data)
while(STATUS_REGISTER[0]!=1):
pass

The problem now is that I don’t no how to use these functions. Could someone help me?