Failed on a simple AXI-lite RM with Partial Reconfiguration

Hi,

I want to switch the function of adding/subtracting/multiplying in one partition block with partial reconfiguration.

The adder/subtractor IP is generated by HLS in the following C-code

void add(int a, int b, int& c) { // ← may change to different top names
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE s_axilite port=a
#pragma HLS INTERFACE s_axilite port=b
#pragma HLS INTERFACE s_axilite port=c

c = a + b; // ← may change to +, -, *, /
}

This is the final block design.

It works fine for the static design and correct computation and seems right to load the partial bitstream. However, it failed in the coming computation as the system/board hang on mmio.write

from pynq import Overlay
overlay = Overlay(‘/home/xilinx/bsd/design_1.bit’)
my_acc = overlay.pr_0.s_axi_AXILiteS.mmio

my_acc.write(0x10, 3)
my_acc.write(0x18, 2)
my_acc.read(0x20)
=> I got 5 since it’s 3+2.

overlay.pr_download(‘pr_0’, ‘/home/xilinx/bsd/design_1_i_pr_0_rm_mul_pd_pr_0_partial.bit’)
my_acc = overlay.pr_0.mul_0.mmio

my_acc.write(0x10, 3)
my_acc.write(0x18, 2)
=> It hanged at writing.

I basically followed these github repos and XAPP1231.
yunqu/partial_reconfig_example
byuccl/PYNQ-PRIO

Just some part I’m not sure if the configuration matters.

== Decoupler ==
1-1: the input signal of “decouple”, I left it floating, which will be tied to 0.
1-2: I set “Interface Mode at RP” to be Slave, instead of Master.
(Since XAPP1231 sets it to be Slave.)

== AXI Interconnect ==
I didn’t enable the register slice. I thought it’s the FIFO for timing synchronization and it’s also not affecting my issue now.

== Reconfigurable Module ==
I found the module’s axilite’s configuration, mul_0/s_axi_AXILiteS, changed, i.e. num of read/write thread 1->4. I’m not sure if it matters the communication.

It’s s on Pynq-Z1 and PYNQ v2.5. I had used Vivado 2018.2, 2018.3, 2019.1 to compile the bitstream. None of them work.

Sorry for being lengthy.
Hope anyone can help me figure out what I missed.

Have you checked the address of your HLS multiplier? Does it have the same address as your adder, i.e., 0x10, 0x18?

Also, does it hang at writing 0x10, or at writing 0x18? For the latter case, it means you can write to 0x10 at least. You just need to make sure the address mapping.

I would also suggest you do something similar to byuccl - hooking up PS GPIO pins to the input of PR decoupler (instead of leaving it unconnected).

hi , i try it with this scenario, it work.

test code:
ov1 = Overlay(‘/home/xilinx/haddsub/prio.bit’)
pr=ov1.pr_decoupler_0
pr.write(0x0, 0) ← default set to zero
// before download partial bitstream set to one
pr.write(0x0, 1)
add_pb=Bitstream(‘/home/xilinx/haddsub/pr_0_sub.bit’, None, True)
add_pb.download()
// after download
pr.write(0x0, 0)

Thanks @rock and @roy. I finally figured it out.

I double checked my HLS design. They had the same register space for control/data registers. But it still failed in running read/write any one of the registers after partial reconfiguration.

The issue is that Vivado’s automation (on validating) forced the CONFIG.NUM_READ_OUTSTANDING/NUM_WRITE_OUTSTANDING to be 8 to the HLS design, which was 1 on the design and might not be compatible for this simple design.
And it’s happening even without the decoupler whenever there is only one Master interface to the AXI Interconnect.
I’m sure it’s successfully partially reconfigured via adding additional gpio design output to the led pin to my original PR and seeing the led light changed, then the followup read/write transaction still hanged.

Adding other designs or following roy’s solution, that enables multiple Master interfaces on the AXI Interconnect, which prevents the CONFIG from forced 8, solves my issue.

1 Like