libsystemctlm-soc
libsystemctlm-soc copied to clipboard
Accesing rp_cosim_reserved for user implementation specific featues
I am trying to create a way that my software test can notify the simulator for the Programmable Logic (in my case I use QuestaSim) that it has passed or failed the test.
I notice that the reserved RemotePort in the QEMU-devicetrees are allocated to reserved memory according to the ZYNQ or ZYNQ UltraScale+ TRM.
Zynq devicetree: (https://github.com/Xilinx/qemu-devicetrees/blob/master/zynq-pl-remoteport.dtsi#L146)
/* This area can be used for implentation specific emulation*/ rp_cosim_reserved: rp_cosim_reserved@0{ compatible = "remote-port-memory-master"; remote-ports = <&cosim_rp_0 12>; reg = <0xFE000000 0x100000>; };
Zynq UltraScale devicetree: (https://github.com/Xilinx/qemu-devicetrees/blob/master/zynqmp-pl-remoteport.dtsi#L130)
/* This area can be used for implentation specific emulation*/ rp_cosim_reserved: rp_cosim_reserved@0{ compatible = "remote-port-memory-master"; remote-ports = <&cosim_rp_0 15>; reg = <BASE_ADDR(0xFF4E0000) 0x100000>; };
When trying to write to the reserved memory master (on the Zynq) I notice that my bare metal application(main.c compiled in Vitis 2021.1) stops. And does not continue with the other write transactions. I am wondering if the reserved address are interfering with the RemotePort communication.
I would like to know if this is the correct way to access the reserved memory master for communication with the PL.
The main.c is shown below:
init_platform();
u32 WValue = 0;
u32 RValue = 0;
volatile u32 *Localwriteaddr = (volatile u32*) 0x40000000;
volatile u32 *Localaddr = (volatile u32*) XPAR_GPIO_0_BASEADDR;
volatile u32 *start_gp0 = (volatile u32*) 0x40000000;
volatile u32 *end_gp0 = (volatile u32*) 0x4ffffffc;
volatile u32 *start_gp1 = (volatile u32*) 0x80000000;
volatile u32 *end_gp1 = (volatile u32*) 0x8ffffffc;
volatile u32 *start_gp2 = (volatile u32*) 0xfe000000; //Reserved address space, Address for simulation information
volatile u32 *end_gp2 = (volatile u32*) 0xfe0ffffc;
for(int i = 0; i < 10; i++){
//Count Write value
WValue++;
// Write WValue to localaddr in the PL
*Localaddr = WValue;
// Read localaddr in the PL
RValue = *Localaddr;
if(i < 5){
printf("RValue: %lx\n", RValue);
// xil_printf("RValue: %lx\n", RValue);
}
// Shift the RValue 1 byte
// Write Shifted value to localwriteaddr in PL
*Localwriteaddr = RValue << 4;
// Readback the shifted value
RValue = *Localwriteaddr;
// Increment the localwrite addr
Localwriteaddr = Localwriteaddr + 1;
}
*start_gp0 = 10;
*end_gp0 = 1023;
*start_gp1 = 10;
*end_gp1 = 1023;
//Application hangs after reading or write to the *start_gp2 which are reserved address for the user specific implementation features.
*start_gp0 = *start_gp2;
*start_gp2 = 10;
*end_gp2 = 1023;
*start_gp0 = pow(2,32)-1;
*end_gp0 = pow(2,32)-1;
*start_gp1 = pow(2,32)-1;
*end_gp1 = pow(2,32)-1;
cleanup_platform();
Hi Rene,
I'm a bit surprised that execution stops there.
Transactions to reserved memory addresses should show up on the dedicated reserved TLM sockets, for ZynqMP that should be on the following socket: https://github.com/Xilinx/libsystemctlm-soc/blob/master/soc/xilinx/zynqmp/xilinx-zynqmp.h#L123
For Zynq, I see that we've not added the corresponding reserved socket. That may have something to do with this. We should add a Zynq resreved TLM socket connected to remote-port device 12.
Are transactions to other areas in your design (e.g gp0 or gp1) working as expected?
Best regards, Edgar
Hi Edgar,
I have replaced the TLM sockets with my own implementation. While monitoring the RemotePort communication I see, that gp0 (dev 7) and gp0 (dev 8) are working correctly. As shown in the transcript from QuestaSim where i print the monitored values from the RemotePort.
dev: 7 cmd: 4 addr: 40000000 time: 119931 len: 4 width: 0 stream_width: 4 master_id: 0 *data: 10 sizeof *data: 1 datalen: 4 dlen: 60 flags: 0 Write data:000a
dev: 7 cmd: 4 addr: 4ffffffc time: 119957 len: 4 width: 0 stream_width: 4 master_id: 0 *data: 255 sizeof *data: 1 datalen: 4 dlen: 60 flags: 0 Write data:003ff
dev: 8 cmd: 4 addr: 80000000 time: 119983 len: 4 width: 0 stream_width: 4 master_id: 0 *data: 10 sizeof *data: 1 datalen: 4 dlen: 60 flags: 0 Write data:000a
dev: 8 cmd: 4 addr: 8ffffffc time: 120009 len: 4 width: 0 stream_width: 4 master_id: 0 *data: 255 sizeof *data: 1 datalen: 4 dlen: 60 flags: 0 Write data:003ff
When debugging further I noticed that the remote-port-memory-master on the QEMU side never sends a RemotePort packet with addr: 0xfe000000 (*start_gp2) or 0xfe0ffffc (*end_gp2) what i try to access with my main.c. Therefor never sending a packet to dev 12 on the Zynq.
Therefor I think the problem lies in QEMU (Xilinx version), I only tested for the Zynq, I will try to create a test for the ZynqMP trying to access their reserved remoteport master(dev 15) . I notice that you are also a contributing to https://github.com/Xilinx/qemu Do I need to open an issue there or do you know where the problem originates in QEMU.