this repo has no description

Add deploy.py script for JTAG deployment via xsdb

Discovers build artifacts (bitstream, FSBL, app ELF, XSA) from the ws/
and src/ directories and programs a connected Zynq-7000 board using the
xsdb Python API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

oscillatory.net 86f876ed 354f514f

verified
+134
+134
sw/scripts/deploy.py
··· 1 + 2 + """ 3 + Usage: vitis -s <path-to-scripts-repo>deploy.py 4 + 5 + @Description 6 + Deploys a built Vitis workspace to a connected board over JTAG. 7 + Discovers build artifacts (bitstream, FSBL, application ELF, XSA) 8 + from the ws/ and src/ directories relative to this script, then 9 + programs the board using the xsdb Python API. 10 + 11 + Expects the workspace to have been built first via checkout.py. 12 + 13 + @Insights 14 + Sequence for Zynq-7000 (ps7_cortexa9): 15 + 1. Reset the APU 16 + 2. Program the PL bitstream 17 + 3. Load hardware description (XSA) into the debug session 18 + 4. Run FSBL to initialize PS7 (clocks, DDR, peripherals) 19 + 5. Download and run the application ELF 20 + """ 21 + import xsdb 22 + import time 23 + from os import path, sep, walk 24 + 25 + class Deploy: 26 + 27 + FSBL_WAIT_S = 1.0 28 + 29 + def __init__(self): 30 + self._script_path = path.dirname(path.abspath(__file__)) 31 + self._sw_root = self._script_path[:self._script_path.rfind(sep)] 32 + self._ws_path = path.join(self._sw_root, 'ws') 33 + self._src_path = path.join(self._sw_root, 'src') 34 + 35 + def _find_artifact(self, base, suffix): 36 + """ 37 + Walk base directory and return the first file whose path ends with suffix. 38 + Raises if none found. 39 + """ 40 + for dirpath, _, filenames in walk(base): 41 + for filename in filenames: 42 + full = path.join(dirpath, filename) 43 + if full.endswith(suffix): 44 + return full 45 + raise FileNotFoundError(f"Could not find artifact matching '*{suffix}' under {base}") 46 + 47 + def _find_bitstream(self): 48 + """Find .bit file in any app's _ide/bitstream/ directory.""" 49 + for dirpath, _, filenames in walk(self._ws_path): 50 + if '_ide' + sep + 'bitstream' in dirpath: 51 + for filename in filenames: 52 + if filename.endswith('.bit'): 53 + return path.join(dirpath, filename) 54 + raise FileNotFoundError(f"No bitstream (.bit) found under {self._ws_path}") 55 + 56 + def _find_fsbl(self): 57 + """Find fsbl.elf built under the platform's zynq_fsbl/build/ directory.""" 58 + for dirpath, _, filenames in walk(self._ws_path): 59 + if 'zynq_fsbl' + sep + 'build' in dirpath: 60 + if 'fsbl.elf' in filenames: 61 + return path.join(dirpath, 'fsbl.elf') 62 + raise FileNotFoundError(f"No fsbl.elf found under {self._ws_path}") 63 + 64 + def _find_app_elf(self): 65 + """ 66 + Find the application ELF: a .elf in a top-level ws/<app>/build/ directory, 67 + where the file name matches the directory name (Vitis naming convention). 68 + Skips the platform/FSBL directory. 69 + """ 70 + for dirpath, _, filenames in walk(self._ws_path): 71 + # Only look one level deep: ws/<name>/build/ 72 + rel = path.relpath(dirpath, self._ws_path) 73 + parts = rel.split(sep) 74 + if len(parts) == 2 and parts[1] == 'build': 75 + app_name = parts[0] 76 + candidate = app_name + '.elf' 77 + if candidate in filenames: 78 + return path.join(dirpath, candidate) 79 + raise FileNotFoundError(f"No application ELF found under {self._ws_path}") 80 + 81 + def _find_xsa(self): 82 + """Find the .xsa hardware description file under src/.""" 83 + for dirpath, _, filenames in walk(self._src_path): 84 + for filename in filenames: 85 + if filename.endswith('.xsa'): 86 + return path.join(dirpath, filename) 87 + raise FileNotFoundError(f"No XSA file found under {self._src_path}") 88 + 89 + def run(self): 90 + bitstream = self._find_bitstream() 91 + fsbl_elf = self._find_fsbl() 92 + app_elf = self._find_app_elf() 93 + xsa = self._find_xsa() 94 + 95 + print("\n---------------------------------------------------------") 96 + print(" Deploying to board via JTAG ") 97 + print("---------------------------------------------------------") 98 + print(f" Bitstream : {bitstream}") 99 + print(f" FSBL : {fsbl_elf}") 100 + print(f" App ELF : {app_elf}") 101 + print(f" XSA : {xsa}") 102 + print("---------------------------------------------------------\n") 103 + 104 + s = xsdb.start_debug_session() 105 + s.connect() 106 + 107 + print("Resetting APU...") 108 + s.targets("--set", filter="name =~ APU") 109 + s.rst() 110 + 111 + print("Programming bitstream...") 112 + s.fpga(file=bitstream) 113 + 114 + print("Selecting CPU target...") 115 + s.targets("--set", filter="name =~ ARM Cortex-A9 MPCore #0") 116 + s.loadhw(hw=xsa) 117 + 118 + print("Running FSBL (PS7 init)...") 119 + s.dow(fsbl_elf) 120 + s.con() 121 + time.sleep(Deploy.FSBL_WAIT_S) 122 + s.stop() 123 + 124 + print("Downloading application...") 125 + s.dow(app_elf) 126 + 127 + print("Starting application.") 128 + s.con() 129 + 130 + print("\nDone.") 131 + 132 + if __name__ == "__main__": 133 + d = Deploy() 134 + d.run()