libsystemctlm-soc icon indicating copy to clipboard operation
libsystemctlm-soc copied to clipboard

Accesing rp_cosim_reserved for user implementation specific featues

Open rpplgmwolters opened this issue 3 years ago • 2 comments

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();

rpplgmwolters avatar Apr 29 '22 08:04 rpplgmwolters

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

edgarigl avatar Apr 29 '22 09:04 edgarigl

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.

rpplgmwolters avatar May 02 '22 09:05 rpplgmwolters