#
# Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
#
# Author: Stephen MacMahon

#History:
#    2023/15/11 - rs - initial based on QEMU support files created by Stephen MacMahon

proc generate_apps {args} {
	set app ""
	set repo ""
	set xsa "NULL"
	set hw_dtb ""
	set list_apps 0
	set multi 1
	set external_elf 1
	set proc "NULL"
	set force_plm 1
	set force_linker 0
	
	for {set i 0} {$i < [llength $args]} {incr i} {
		if {[lindex $args $i] == "-app"} {
			set app [lindex $args [expr {$i + 1}]]
			if {[file extension $app] == ".elf"} {
				puts "Info: External ELF is used"
				set external_elf 1 
			}
		}
		if {[lindex $args $i] == "-repo"} {
			set repo [lindex $args [expr {$i + 1}]]
		}
		if {[lindex $args $i] == "-xsa"} {
			set xsa [lindex $args [expr {$i + 1}]]
		}
		if {[lindex $args $i] == "-hw_dtb"} {
			set hw_dtb [lindex $args [expr {$i + 1}]]
		}
		if {[lindex $args $i] == "-multi"} {
			set multi [lindex $args [expr {$i + 1}]]
		}
		if {[lindex $args $i] == "-list_apps"} {
			set list_apps 1
		}
		if {[lindex $args $i] == "-proc"} {
			set proc [lindex $args [expr {$i + 1}]]
		}
		if {[lindex $args $i] == "-force_plm"} {
			set force_plm [lindex $args [expr {$i + 1}]]
		}
		if {[lindex $args $i] == "-force_linker"} {
			set force_linker [lindex $args [expr {$i + 1}]]
		}		
	}
    
	if {$xsa == "NULL"} {
		puts "Warning: No XSA passed. Looking in [pwd]"
		set xsa [glob -nocomplain -directory [pwd] -type f *.xsa]
		if {![llength $xsa]} {
			puts "Error: No XSA passed. Use -xsa to pass a Valid XSA file"
			return ""
		} 
	}

	puts "Info: Using XSA file: $xsa"
    	hsi::open_hw_design $xsa
	
	set arch [get_arch]
	puts "Info: Arch detected as $arch"
	
	if {$multi == 1 && $arch == "versal"} {
		puts "Info: Multi versal Arch config. Extracting PDI file from XSA"
		exec unzip -j $xsa *.pdi -d plm_files
		set pdi [glob -nocomplain -directory plm_files -type f *.pdi]
		if {$pdi == ""} {
			puts "Error: No PDI file found in XSA. Exitting..."
			return ""
		}
		exec bootgen -arch versal -dump $pdi -dump_dir ./plm_files
		set pmc_cdo [glob -nocomplain -directory plm_files -type f pmc_cdo.0.*.bin]
		if {$pdi == ""} {
			puts "Error: No PMC CDO file found in PDI. Exitting..."
			return ""
		}
	}
	
	if {$proc != "NULL"} {
		set proc_found 0
		foreach sup_proc [hsi::get_cells -hier -filter {IP_TYPE==PROCESSOR}] {
			if {$proc == $sup_proc} {
				set proc $sup_proc
				set proc_found 1
				break;
			}
		}
		if {$proc_found  == 0} {
			puts "Error: $proc is not a valid processor in your XSA. Please use one of the following:"
			foreach sup_proc [hsi::get_cells -hier -filter {IP_TYPE==PROCESSOR}] {
				puts "\t * $sup_procs"
			}
		}		
	} else {
		set proc [lindex [hsi::get_cells -hier -filter {IP_TYPE==PROCESSOR}] 0]
		puts "Info: Using default processor ${proc}. Users can specify a processor using -proc"
	}
	
	if {$repo != ""} {
		if {[file isdirectory $repo]} {
			puts "Using custom SW repo at $repo"
			hsi::set_repo_path $repo
		} else {
			puts "Warning: $repo is not a directory."
		}
	} else {
		puts "Info: No custom SW repository found. Users can pass this using the -repo option"
	}

	if {$external_elf == 0} {
		if {$list_apps == 1} {
			puts "Info: The list of supported app for your processor is:"
			foreach sapp [hsi::generate_app -proc $proc -sapp] {
				puts " * $sapp"
			}
			hsi::close_hw_design [hsi::current_hw_design]
			return ""
		}
		
		set supported 0
		foreach sapp [hsi::generate_app -proc $proc -sapp] {
			if {$app == $sapp} {
				set supported 1
				puts "Info $app is a supported app for your platform"
			}
		}
		
		if {$supported == 0} {
			puts "Error: Unsupported application $app. The list of supported app for your processor is:"
			foreach sapp [hsi::generate_app -proc $proc -sapp] {
				puts " * $sapp"
			}
			return ""
		}
		set app_name [create_app_name -app $app -proc $proc]
		set proc_type [lindex [split $app_name "_"] end-1]
		puts "Info: Creating $app template for $proc with name $app_name"
		if {$proc_type == "a72"} {
			set fileId [open a72.txt "a+"]
			set cpu_num [string range $proc end end]
			puts $fileId "-device loader,file=${app_name}/executable.elf,cpu-num=${cpu_num} "
			close $fileId
		} 
		if {$proc_type == "a53"} {
			set fileId [open a53.txt "a+"]
			set cpu_num [string range $proc end end]
			puts $fileId "-device loader,file=${app_name}/executable.elf,cpu-num=${cpu_num} "
			close $fileId
		}
		
		if {$proc_type == "r5"} {
			set fileId [open r5.txt "a+"]
			set cpu_num [string range $proc end end]
			if {$arch == "versal"} {
				set cpu_num [expr {$cpu_num + 2}]
			} elseif {$arch == "zynquplus" || $arch == "zynquplusRFSOC"} {
				set cpu_num [expr {$cpu_num + 4}]
			} else {
				puts "Error: unexpected arch : $arch"
			}
			puts $fileId "-device loader,file=${app_name}/executable.elf,cpu-num=${cpu_num} "
			close $fileId
		}
		
		set app_design [hsi::create_sw_design $app_name -proc $proc -app $app]
		
		if {$proc_type == "r5"} {
			common::set_property -name APP_COMPILER_FLAGS -value "-g -mcpu=cortex-r5 -mfloat-abi=hard -mfpu=vfpv3-d16" -objects $app_design
		} else {
			common::set_property -name APP_COMPILER_FLAGS -value "-g" -objects $app_design
		}
		
		foreach ip [hsi::get_mem_ranges -of_objects [hsi::get_cells -hier $proc]] {
			if {[common::get_property IP_NAME [hsi::get_cells -hier $ip]] == "psv_coresight" || [common::get_property IP_NAME [hsi::get_cells -hier $ip]] == "psu_coresight"} {
				puts "Info: Setting STDIN/OUT to $ip"
				common::set_property CONFIG.stdin $ip [hsi::get_os]
				common::set_property CONFIG.stdout $ip [hsi::get_os]
				break;
			}
		}
		hsi::generate_app -dir $app_name -compile
		
		if {$force_linker == 1} {
			if {$repo != ""} {
				if {[file isdirectory $repo]} {
					puts "Info: Importing linker from ${repo}/lib/sw_apps/${app}/src to ${app_name}"
					set linker [glob -nocomplain -directory ${repo}/lib/sw_apps/${app}/src -type f *.ld]
					if {$linker != ""} {
						file copy -force ${repo}/lib/sw_apps/${app}/src/lscript.ld ${app_name}
						after 500
						exec make -C ${app_name}
					} else {
						puts "Warning: -force_linker is enabled, but no ld file found at ${repo}/lib/sw_apps/${app}/src"
					}
				}
			}
		}
	} else {
		puts "Info: Using external generated ELF: $app"
		set app_name [create_app_name -app $app -proc $proc]
		set proc_type [lindex [split $app_name "_"] end-1]
		#if {[file exists $app_name]} {
		#	file delete -force $app_name
		#}
		#file mkdir $app_name
		#file copy -force $app/build/$app.elf ${app_name}/executable.elf
		if {$proc_type == "a72"} {
			set fileId [open a72.txt "a+"]
			set cpu_num [string range $proc end end]
			puts $fileId "-device loader,file=${app}/build/${app}.elf,cpu-num=${cpu_num} "
			close $fileId
		} 
		if {$proc_type == "a53"} {
			set fileId [open a53.txt "a+"]
			set cpu_num [string range $proc end end]
			puts $fileId "-device loader,file=${app}/build/${app}.elf,cpu-num=${cpu_num} "
			close $fileId
		}
		
		if {$proc_type == "r5"} {
			set fileId [open r5.txt "a+"]
			set cpu_num [string range $proc end end]
			if {$arch == "versal"} {
				set cpu_num [expr {$cpu_num + 2}]
			} elseif {$arch == "zynquplus" || $arch == "zynquplusRFSOC"} {
				set cpu_num [expr {$cpu_num + 4}]
			} else {
				puts "Error: unexpected arch : $arch"
			}
			puts $fileId "-device loader,file=${app_name}/executable.elf,cpu-num=${cpu_num} "
			close $fileId
		}
	}
	

	if {$multi == 1 && $arch == "versal"} {
		puts "Info: Creating PLM. Searching for PSV_PMC processor"
		foreach procs [hsi::get_cells -hier -filter {IP_TYPE==PROCESSOR}] {
			if {[common::get_property IP_NAME [hsi::get_cells -hier $procs]] == "psv_pmc"} {
				set proc $procs
				break;
			}
		}
		if {[file isdirectory versal_plm] } {
			if {$force_plm == 1} {
				file delete -force versal_plm
			} else {
				puts "Info: versal_plm already exists. Use -force_plm to force the creation of the PLM"
				file copy versal_plm/executable.elf plm_files/plm.elf
			}
		}
		
		if {![file isdirectory versal_plm] } {
			puts "Info: Using proc $proc for versal_plm application template"
			set app_design [hsi::create_sw_design versal_plm -proc $proc -app versal_plm]
			hsi::generate_app -dir versal_plm -compile
			file copy versal_plm/executable.elf plm_files/plm.elf
		}
	}

	if {$multi == 1} {
		if {$arch == "zynquplus" || $arch == "zynquplusRFSOC"} {
			puts "Info: Creating PLMFW. Searching for PSU_PMU processor"
			foreach procs [hsi::get_cells -hier -filter {IP_TYPE==PROCESSOR}] {
				if {[common::get_property IP_NAME [hsi::get_cells -hier $procs]] == "psu_pmu"} {
					set proc $procs
					break;
				}
			}
			if {[file isdirectory zynqmp_pmufw] } {
				if {$force_plm == 1} {
					file delete -force zynqmp_pmufw
				} else {
					puts "Info: zynqmp_pmufw already exists. Use -force_plm to force the creation of the PLM"
				}
			}
			if {![file isdirectory zynqmp_pmufw] } {
				puts "Info: Using proc $proc for zynqmp_pmufw application template"
				set app_design [hsi::create_sw_design zynqmp_pmufw -proc $proc -app zynqmp_pmufw]
				hsi::generate_app -dir zynqmp_pmufw -compile
				file copy zynqmp_pmufw/executable.elf plm_files/plm.elf
			}
		}
	}	
	
    hsi::close_hw_design [hsi::current_hw_design]
}

proc build_qemu_dts {args} {
	set install ""
	for {set i 0} {$i < [llength $args]} {incr i} {
		if {[lindex $args $i] == "-install"} {
			set install [lindex $args [expr {$i + 1}]]
		}
	
	}
	if {$install == ""} {
		puts "Error: Install Path not set. Use the -install to pass this"
		return ""
	}
	
	puts "Info: Copying DTS files from ${install}/data/emulation/qemu/comp/dts to qemu-devicetrees"
	file copy -force ${install}/data/emulation/qemu/comp/dts qemu-devicetrees
}

proc generate_proc_string {} {

	set proc_string ""
	set arch [get_arch]
	
	if {$arch == "versal"} {
		set procs "a72 r5"
	} elseif {$arch == "zynquplus" || $arch == "zynquplusRFSOC"} {
		set procs "a53 r5"
	} else {
		puts "Error: Unsupported arch $arch"
	}
	
	foreach proc [split $procs] {
		if {[file exists ${proc}.txt]} {
			puts "Info: Configuring QEMU for $proc"
			set fp [open ${proc}.txt r]
			set file_data [read $fp]
			close $fp

			set data [split $file_data "\n"]
			
			#remove blank lines
			set cpu_num 0
			foreach line $data {
				if {$line != ""} {
					set cpu_num [expr {$cpu_num + 1}]
				}
			}
			set mask [string tolower [format %X [expr {0xF - [expr {$cpu_num + 0}]}]]]
			foreach line $data {
				set proc_string " ${proc_string}${line} "
			}
			
			if {$proc == "a72"} {
				set proc_string "${proc_string}-device loader,addr=0xfd1a0300,data=0x8000000${mask},data-len=4 "
			}
			
			if {$proc == "a53"} {
				set proc_string "${proc_string}-device loader,addr=0xfd1a0104,data=0x8000000${mask},data-len=4 "
			}

			if {$proc == "r5"} {
				if {$arch == "versal"} {
					if {$cpu_num == 1} {
						puts "Info: Setting RPU to lockstep mode. Combine R5_0 and R5_1 TCM together, 256KB TCM is visible on R5_0"
						set proc_string "${proc_string}--device loader,addr=0xff5e0300,data=0x14,data-len=4 -device loader,addr=0xff9a0100,data=0x1,data-len=4 -device loader,addr=0xff9a0000,data=0x50,data-len=4 "
					} elseif {$cpu_num == 2} {
						puts "Info: Setting RPU to split mode. Use 128KB TCM with R5_0 and 128KB TCM with R5_1"
						set proc_string "${proc_string}--device loader,addr=0xff5e0300,data=0x14,data-len=4 -device loader,addr=0xff9a0100,data=0x1,data-len=4 -device loader,addr=0xff9a0200,data=0x1,data-len=4 -device loader,addr=0xff9a0000,data=0x8,data-len=4 "
					} else {
						puts "Error: Unexpected number of R5 processor apps. $cpu_num"
					}
				} elseif {$arch == "zynquplus" || $arch == "zynquplusRFSOC"} {
					if {$cpu_num == 1} {
						puts "Info: Setting RPU to lockstep mode."
						set proc_string "${proc_string}-device loader,addr=0XFF5E023C,data=0x80088fde,data-len=4 -device loader,addr=0xff9a0000,data=0x80000218,data-len=4 "
					} elseif {$cpu_num == 2} {
						puts "Info: Setting RPU to split mode."
						set proc_string "${proc_string}-device loader,addr=0XFF5E023C,data=0x80088fdC,data-len=4 -device loader,addr=0xff9a0100,data=0x1,data-len=4 -device loader,addr=0xff9a0200,data=0x1,data-len=4 -device loader,addr=0xff9a0000,data=0x8,data-len=4 "
					} else {
						puts "Error: Unexpected number of R5 processor apps. $cpu_num"
					}
				} else {
					puts "Error: Unknown arch $arch"
				}
			}
		} else {
			puts "Info: No applications found for $proc"
		}
	}
	
	return $proc_string
}

proc create_app_name {args} {
	set app 0
	set proc 0
	for {set i 0} {$i < [llength $args]} {incr i} {
		if {[lindex $args $i] == "-app"} {
			set app [lindex $args [expr {$i + 1}]]
		}
		if {[lindex $args $i] == "-proc"} {
			set proc [lindex $args [expr {$i + 1}]]
		}
	}
	
	if {$proc == 0} {
		puts "Error: pass the proc using -proc"
		return ""
	}
	if {$app == 0} {
		puts "Error: pass the app using -app"
		return ""
	}
	
	if {[file extension $app] == ".elf"} {
		set app [file tail [file rootname $app]]
	}
	
	set ip_name [common::get_property IP_NAME [hsi::get_cells -hier $proc]]
	
	if {$ip_name == "psv_cortexa72" || $ip_name == "psu_cortexa53"} {
		return "${app}_[string range $proc end-4 end]"
	}
	
	if {$ip_name == "psv_cortexr5" || $ip_name == "psu_cortexr5"} {
		return "${app}_[string range $proc end-3 end]"
	}
	
	return $app
}

proc get_supported_procs {args} {
	set open_xsa 0
	set xsa "NULL"
	for {set i 0} {$i < [llength $args]} {incr i} {
		if {[lindex $args $i] == "-open_xsa"} {
			set open_xsa 1
		}
		if {[lindex $args $i] == "-xsa"} {
			set xsa [lindex $args [expr {$i + 1}]]
		}
	}
	
	if {$open_xsa == 1} {
		if {$xsa == "NULL"} {
			puts "Warning: No XSA passed. Looking in [pwd]"
			set xsa [glob -nocomplain -directory [pwd] -type f *.xsa]
			if {![llength $xsa]} {
				puts "Error: No XSA passed. Use -xsa to pass a Valid XSA file"
				return ""
			} 
		}
		hsi::open_hw_design $xsa
	}
	puts "Info: list of supported processors are:"
	foreach procs [hsi::get_cells -hier -filter {IP_TYPE==PROCESSOR}] {
		puts "\t * $procs"
	}

	if {$open_xsa == 1} {
		hsi::close_hw_design [hsi::current_hw_design]
	}	
}

proc get_arch {args} {
	set open_xsa 0
	for {set i 0} {$i < [llength $args]} {incr i} {
		if {[lindex $args $i] == "-open_xsa"} {
			set open_xsa 1
		}
	}
	
	if {$open_xsa == 1} {
		set xsa [glob -nocomplain -directory [pwd] -type f *.xsa *.hdf]
		hsi::open_hw_design $xsa
	}
	
	set arch [common::get_property FAMILY [hsi::current_hw_design]]
	
	if {$open_xsa == 1} {
		hsi::close_hw_design [hsi::current_hw_design]
	}
	
	return $arch
}

proc get_port {} {
	for {set port 9000} {$port <= 9100} {incr port} {
		if {![catch {
				set sock [socket -server localhost $port]
			}]} then {
				break
		}
	}
	# If we failed...
	if {![info exist sock]} {
		error "No ports free in range 9000-9100"
		return ""
	} else {
		return $port
	}
}

proc generate_qemu_scripts {args} {
	set xsa "NULL"
	set tmp_dir "./tmp_dir"
	set install ""
	set aarch64_cmd ""
	set microblazeel_cmd ""
	set cosim 0
	set external_elf 1
	for {set i 0} {$i < [llength $args]} {incr i} {
		if {[lindex $args $i] == "-xsa"} {
			set xsa [lindex $args [expr {$i + 1}]]
		}
		if {[lindex $args $i] == "-install"} {
			set install [lindex $args [expr {$i + 1}]]
		}
		if {[lindex $args $i] == "-multi"} {
			set multi [lindex $args [expr {$i + 1}]]
		}
		if {[lindex $args $i] == "-cosim"} {
			set cosim [lindex $args [expr {$i + 1}]]
		}
		if {[lindex $args $i] == "-tmp_dir"} {
			set tmp_dir [lindex $args [expr {$i + 1}]]
		}
	}

	if {$xsa == "NULL"} {
		puts "Warning: No XSA passed. Looking in [pwd]"
		set xsa [glob -nocomplain -directory [pwd] -type f *.xsa]
		if {![llength $xsa]} {
			puts "Error: No XSA passed. Use -xsa to pass a Valid XSA file"
			return ""
		} 
	}
	
	puts "Info: Using XSA file: $xsa"
    	hsi::open_hw_design $xsa
	
	set arch [get_arch]
	puts "Info: Arch detected as $arch"
	
	if {$arch == ""} {
		puts "Error: No arch detected"
		return ""
	}

	if {$install == ""} {
		puts "Error: Install Path not set. Use the -install to pass this"
		return ""
	} else {
		set qemu ${install}/data/emulation/qemu/comp/qemu/sysroots/x86_64-petalinux-linux/usr/bin/qemu-system
	}
	
	set available_port [get_port]
	if {$available_port != ""} {
			set gdb_port "-gdb tcp::${available_port}"
	} else {
		set gdb_port ""
	}
	
	if {$multi == 1} {
		puts "Info: -machine-path set $tmp_dir"
		set machine_path "-machine-path $tmp_dir"
		if {$arch == "versal"} {
			set hw_dtb qemu-devicetrees/LATEST/MULTI_ARCH/board-versal-ps-vck190.dtb
		} elseif {$arch == "zynquplus" || $arch == "zynquplusRFSOC"} {
			set hw_dtb qemu-devicetrees/LATEST/MULTI_ARCH/board-zynqmp-zcu104.dtb
		} else {
			puts "Error: Unsupported arch $arch"
		}
	} else {
		puts "Info: -machine-path set NULL"
		set machine_path ""
		if {$arch == "versal"} {
			set hw_dtb qemu-devicetrees/LATEST/SINGLE_ARCH/board-versal-ps-vck190.dtb
		} elseif {$arch == "zynquplus" || $arch == "zynquplusRFSOC"} {
			set hw_dtb qemu-devicetrees/LATEST/SINGLE_ARCH/board-zynqmp-zcu104.dtb
		} else {
			puts "Error: Unsupported arch $arch"
		}
	}

	if {$cosim == 1} {
		puts "Info: Co-Simulation Enabled."
		set machine_path "-machine-path $tmp_dir -sync-quantum 1000000"
		if {$multi == 1} {
			if {$arch == "versal"} {
				set hw_dtb qemu-devicetrees/LATEST/MULTI_ARCH/board-versal-ps-cosim-vitis-vck190.dtb
			} elseif {$arch == "zynquplus" || $arch == "zynquplusRFSOC"} {
				set hw_dtb qemu-devicetrees/LATEST/MULTI_ARCH/board-zynqmp-cosim-zcu104.dtb
			} else {
				puts "Error: Unsupported arch $arch"
			}
		} else {
			if {$arch == "versal"} {
				set hw_dtb qemu-devicetrees/LATEST/SINGLE_ARCH/board-versal-ps-cosim-vck190.dtb
			} elseif {$arch == "zynquplus" || $arch == "zynquplusRFSOC"} {
				set hw_dtb qemu-devicetrees/LATEST/SINGLE_ARCH/board-zynqmp-cosim-zcu104.dtb
			} else {
				puts "Error: Unsupported arch $arch"
			}
		}
			
	} 
	
	puts "Info: Using hw-dtb set to $hw_dtb"

		
	if {$arch == "versal"} {
		set proc_string [generate_proc_string]
		if {$multi == 1} {
			set microblazeel_cmd "${qemu}-microblazeel -M microblaze-fdt  \
			-serial mon:stdio -display none \
			-device loader,addr=0xf0000000,data=0xba020004,data-len=4 \
			-device loader,addr=0xf0000004,data=0xb800fffc,data-len=4 \
			-device loader,file=plm_files/pmc_cdo.0.0.bin,addr=0xf2000000 \
			-device loader,file=plm_files/plm.elf \
			-hw-dtb qemu-devicetrees/LATEST/MULTI_ARCH/board-versal-pmc-virt.dtb \
			-machine-path $tmp_dir \
			-device loader,addr=0xF1110624,data=0x0,data-len=4 \
			-device loader,addr=0xF1110620,data=0x1,data-len=4"
			set aarch64_cmd "${qemu}-aarch64 -nographic -M arm-generic-fdt \
			-serial null -serial null -serial mon:stdio -serial null -display none \
			$proc_string \
			$machine_path \
			-hw-dtb $hw_dtb -m 8G -display none $gdb_port\
			-net nic,netdev=eth0 -netdev user,id=eth0,tftp=/tftpboot -net nic"
		} else {
			set aarch64_cmd "${qemu}-aarch64 -nographic -M arm-generic-fdt \
			-serial null -serial null -serial mon:stdio -serial null -display none \
			$proc_string \
			$machine_path \
			-hw-dtb $hw_dtb -m 8G -display none $gdb_port \
			-net nic,netdev=eth0 -netdev user,id=eth0,tftp=/tftpboot -net nic"
		}
	} elseif {$arch == "zynquplus"} {
		set proc_string [generate_proc_string]
		if {$multi == 1} {
			set microblazeel_cmd "${qemu}-microblazeel -M microblaze-fdt \
			-serial mon:stdio -serial /dev/null -display none \
			-kernel pmu_rom_qemu_sha3.elf \
			-device loader,file=plm_files/plm.elf \
			-hw-dtb qemu-devicetrees/LATEST/MULTI_ARCH/zynqmp-pmu.dtb \
			$machine_path \
			-device loader,addr=0xfd1a0074,data=0x1011003,data-len=4 \
			-device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4"
			set aarch64_cmd "${qemu}-aarch64 -nographic -M arm-generic-fdt \
			-serial mon:stdio -serial null -display none \
			$proc_string \
			$machine_path \
			-global xlnx,zynqmp-boot.use-pmufw=true \
			-hw-dtb $hw_dtb -m 8G -display none $gdb_port \
			-net nic -net nic -net nic -net nic,netdev=gem3 -netdev user,id=gem3,hostfwd=tcp:127.0.0.1:1540-10.0.2.15:1534"
		} else {
			set aarch64_cmd "${qemu}-aarch64 -nographic -M arm-generic-fdt \
			-serial mon:stdio -serial null -display none \
			$proc_string \
			$machine_path \
			-hw-dtb $hw_dtb -m 8G -display none $gdb_port \
			-net nic -net nic -net nic -net nic,netdev=gem3 -netdev user,id=gem3,hostfwd=tcp:127.0.0.1:1540-10.0.2.15:1534"
		}
	# Im not sure if this is the correct hw-dtb to use for zcu111
	} elseif {$arch == "zynquplusRFSOC"} {
		set proc_string [generate_proc_string]
		if {$multi == 1} {
			set microblazeel_cmd "${qemu}-microblazeel -M microblaze-fdt \
			-serial mon:stdio -serial /dev/null -display none \
			-kernel pmu_rom_qemu_sha3.elf \
			-device loader,file=plm_files/plm.elf \
			-hw-dtb qemu-devicetrees/LATEST/MULTI_ARCH/zynqmp-pmu.dtb \
			-machine-path $tmp_dir \
			-device loader,addr=0xfd1a0074,data=0x1011003,data-len=4 \
			-device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4"
			set aarch64_cmd "${qemu}-aarch64 -nographic -M arm-generic-fdt \
			-serial mon:stdio -serial null -display none \
			$proc_string \
			$machine_path \
			-global xlnx,zynqmp-boot.use-pmufw=true \
			-hw-dtb $hw_dtb -m 8G -display none $gdb_port \
			-net nic -net nic -net nic -net nic,netdev=gem3 -netdev user,id=gem3,hostfwd=tcp:127.0.0.1:1540-10.0.2.15:1534"
		} else {
			set aarch64_cmd "${qemu}-aarch64 -nographic -M arm-generic-fdt \
			-serial mon:stdio -serial null -display none \
			$proc_string \
			$machine_path \
			-hw-dtb $hw_dtb -m 8G -display none $gdb_port \
			-net nic -net nic -net nic -net nic,netdev=gem3 -netdev user,id=gem3,hostfwd=tcp:127.0.0.1:1540-10.0.2.15:1534"
		}
	} else {
		puts "Error: Unsupported arch $arch"
	}
	if {$multi == 1} {
		set fileId [open run_qemu_microblazeel.sh "w"]
		puts $fileId "echo 'INFO: Starting microblaze QEMU'"
		puts $fileId "echo 'INFO: $microblazeel_cmd'"
		puts $fileId $microblazeel_cmd
		close $fileId
	}
	set fileId [open run_qemu_aarch64.sh "w"]
	puts $fileId "echo 'INFO: Starting aarch64 QEMU'"
	puts $fileId "echo 'INFO: TCP PORT is free $available_port'"
	puts $fileId "echo 'INFO: $aarch64_cmd'"
	puts $fileId $aarch64_cmd
	close $fileId
	set fileId [open run_qemu.sh "w"]
	if {$multi == 1} {
		puts $fileId "source run_qemu_microblazeel.sh &"
	}
	puts $fileId "source run_qemu_aarch64.sh"
	close $fileId
	puts "Info: run_qemu script generated. Use the make run_qemu command to test the app on QEMU"
}
#<copyright-disclaimer-start>
#<copyright-disclaimer-start>
#  **************************************************************************************************************
#  * © 2024 Advanced Micro Devices, Inc. All rights reserved.                                                   *
#  * DISCLAIMER                                                                                                 *
#  * The information contained herein is for informational purposes only, and is subject to change              *
#  * without notice. While every precaution has been taken in the preparation of this document, it              *
#  * may contain technical inaccuracies, omissions and typographical errors, and AMD is under no                *
#  * obligation to update or otherwise correct this information.  Advanced Micro Devices, Inc. makes            *
#  * no representations or warranties with respect to the accuracy or completeness of the contents of           *
#  * this document, and assumes no liability of any kind, including the implied warranties of noninfringement,  *
#  * merchantability or fitness for particular purposes, with respect to the operation or use of AMD            *
#  * hardware, software or other products described herein.  No license, including implied or                   *
#  * arising by estoppel, to any intellectual property rights is granted by this document.  Terms and           *
#  * limitations applicable to the purchase or use of AMD’s products are as set forth in a signed agreement     *
#  * between the parties or in AMD's Standard Terms and Conditions of Sale. GD-18                               *
#  *                                                                                                            *
#  **************************************************************************************************************
#<copyright-disclaimer-end>
#<copyright-disclaimer-end>
