diff options
| author | Sandeep Gundlupet Raju <sandeep.gundlupet-raju@amd.com> | 2023-01-10 01:24:04 -0700 |
|---|---|---|
| committer | Mark Hatle <mark.hatle@amd.com> | 2023-01-11 12:23:20 -0600 |
| commit | 771747ae2372e819ed29628cd18453b05c026b2f (patch) | |
| tree | c251345ceb7ec3e911535bb9175c354e238c5ef7 /meta-xilinx-core/classes | |
| parent | 2b71f50fe7f34a0e7443f52376a69a35bf2aaf8d (diff) | |
| download | meta-xilinx-771747ae2372e819ed29628cd18453b05c026b2f.tar.gz | |
fpgamanager_custom: Add support for dtsi and prebuilt dtbo
1. Add support for prebuilt dtbo input from firmware recipe.
2. Add support for dtsi which is generated outside of dtg
as input from from firmware recipe.
3. Add support for versal.
bbclass can support three flows, flow is decided by user inputs
in SRC_URI
XSA + pl-partial-custom.dtsi -> dtg + dtc
dtsi + bit/bin/pdi -> dtc (no xsct involved)
dtbo + bit/bin/pdi -> none (no xsct involved)
Signed-off-by: Sandeep Gundlupet Raju <sandeep.gundlupet-raju@amd.com>
Signed-off-by: Mark Hatle <mark.hatle@amd.com>
Diffstat (limited to 'meta-xilinx-core/classes')
| -rw-r--r-- | meta-xilinx-core/classes/fpgamanager_custom.bbclass | 135 |
1 files changed, 105 insertions, 30 deletions
diff --git a/meta-xilinx-core/classes/fpgamanager_custom.bbclass b/meta-xilinx-core/classes/fpgamanager_custom.bbclass index 7bec7972..8e7e86c3 100644 --- a/meta-xilinx-core/classes/fpgamanager_custom.bbclass +++ b/meta-xilinx-core/classes/fpgamanager_custom.bbclass | |||
| @@ -20,65 +20,140 @@ BOOTGEN_FLAGS ?= " -arch ${SOC_FAMILY} ${@bb.utils.contains('SOC_FAMILY','zynqmp | |||
| 20 | S ?= "${WORKDIR}" | 20 | S ?= "${WORKDIR}" |
| 21 | FW_DIR ?= "" | 21 | FW_DIR ?= "" |
| 22 | DTSI_PATH ?= "" | 22 | DTSI_PATH ?= "" |
| 23 | DTBO_PATH ?= "" | ||
| 23 | DT_FILES_PATH = "${S}/${DTSI_PATH}" | 24 | DT_FILES_PATH = "${S}/${DTSI_PATH}" |
| 24 | 25 | ||
| 25 | python (){ | 26 | python() { |
| 26 | 27 | soc_family = d.getVar("SOC_FAMILY") | |
| 27 | if "git://" in d.getVar("SRC_URI") or "https://" in d.getVar("SRC_URI"): | 28 | if "git://" in d.getVar("SRC_URI") or "https://" in d.getVar("SRC_URI"): |
| 28 | d.setVar("S",'${WORKDIR}/git/'+d.getVar("FW_DIR")) | 29 | d.setVar("S",'${WORKDIR}/git/'+d.getVar("FW_DIR")) |
| 29 | else: | 30 | else: |
| 30 | if d.getVar("SRC_URI").count(".dtsi") != 1 or d.getVar("SRC_URI").count(".bit") != 1 \ | 31 | dtsi_found = False |
| 31 | or d.getVar("SRC_URI").count("shell.json") != 1: | 32 | dtbo_found = False |
| 32 | raise bb.parse.SkipRecipe("Need one '.dtsi', one '.bit' and one 'shell.json' file added to SRC_URI") | 33 | bit_found = False |
| 33 | 34 | pdi_found = False | |
| 34 | d.setVar("DTSI_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.dtsi' in a][0].lstrip('file://'))) | 35 | |
| 35 | d.setVar("BIT_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.bit' in a][0].lstrip('file://'))) | 36 | # Required Inputs |
| 36 | d.setVar("JSON_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if 'shell.json' in a][0].lstrip('file://'))) | 37 | if '.dtsi' in d.getVar("SRC_URI"): |
| 38 | dtsi_found = True | ||
| 39 | d.setVar("DTSI_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.dtsi' in a][0].lstrip('file://'))) | ||
| 40 | |||
| 41 | if '.dtbo' in d.getVar("SRC_URI"): | ||
| 42 | dtbo_found = True | ||
| 43 | d.setVar("DTBO_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.dtbo' in a][0].lstrip('file://'))) | ||
| 44 | |||
| 45 | if '.bit' in d.getVar("SRC_URI") and soc_family != "versal": | ||
| 46 | bit_found = True | ||
| 47 | d.setVar("BIT_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.bit' in a][0].lstrip('file://'))) | ||
| 48 | |||
| 49 | if '.pdi' in d.getVar("SRC_URI") and soc_family == "versal": | ||
| 50 | pdi_found = True | ||
| 51 | d.setVar("PDI_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.pdi' in a][0].lstrip('file://'))) | ||
| 52 | |||
| 53 | # Check for valid combination of input files in SRC_URI | ||
| 54 | if dtsi_found or dtbo_found: | ||
| 55 | bb.debug(2, "dtsi or dtbo found in SRC_URI") | ||
| 56 | if bit_found or pdi_found: | ||
| 57 | bb.debug(2, "bitstream or pdi found in SRC_URI") | ||
| 58 | else: | ||
| 59 | raise bb.parse.SkipRecipe("Need one '.bit' or one '.pdi' file added to SRC_URI ") | ||
| 60 | else: | ||
| 61 | raise bb.parse.SkipRecipe("Need one '.dtsi' or one '.dtbo' file added to SRC_URI ") | ||
| 62 | |||
| 63 | # Optional input | ||
| 64 | if 'accel.json' in d.getVar("SRC_URI"): | ||
| 65 | d.setVar("JSON_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if 'accel.json' in a][0].lstrip('file://'))) | ||
| 37 | 66 | ||
| 38 | #optional input | ||
| 39 | if '.xclbin' in d.getVar("SRC_URI"): | 67 | if '.xclbin' in d.getVar("SRC_URI"): |
| 40 | d.setVar("XCL_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.xclbin' in a][0].lstrip('file://'))) | 68 | d.setVar("XCL_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.xclbin' in a][0].lstrip('file://'))) |
| 41 | } | 69 | } |
| 42 | python do_configure() { | 70 | python do_configure() { |
| 43 | import glob, re, shutil | 71 | import glob, re, shutil |
| 72 | soc_family = d.getVar("SOC_FAMILY") | ||
| 44 | 73 | ||
| 45 | if bb.utils.contains('MACHINE_FEATURES', 'fpga-overlay', False, True, d): | 74 | if bb.utils.contains('MACHINE_FEATURES', 'fpga-overlay', False, True, d): |
| 46 | bb.warn("Using fpga-manager.bbclass requires fpga-overlay MACHINE_FEATURE to be enabled") | 75 | bb.warn("Using fpga-manager.bbclass requires fpga-overlay MACHINE_FEATURE to be enabled") |
| 47 | 76 | ||
| 48 | #renaming firmware-name using $PN as bitstream will be renamed using $PN when generating the bin file | 77 | # Renaming firmware-name using $PN as bitstream/PDI will be renamed using |
| 49 | orig_dtsi = glob.glob(d.getVar('S')+ (d.getVar('DTSI_PATH') or '') + '/*.dtsi')[0] | 78 | # $PN when generating the bin/pdi file. |
| 50 | new_dtsi = d.getVar('S') + '/pl.dtsi_firmwarename' | 79 | if '.dtsi' in d.getVar("SRC_URI"): |
| 51 | with open(new_dtsi, 'w') as newdtsi: | 80 | orig_dtsi = glob.glob(d.getVar('S')+ (d.getVar('DTSI_PATH') or '') + '/*.dtsi')[0] |
| 52 | with open(orig_dtsi) as olddtsi: | 81 | new_dtsi = d.getVar('S') + '/pl.dtsi_firmwarename' |
| 53 | for line in olddtsi: | 82 | with open(new_dtsi, 'w') as newdtsi: |
| 54 | newdtsi.write(re.sub('firmware-name.*\".*\"','firmware-name = \"'+d.getVar('PN')+'.bit.bin\"',line)) | 83 | with open(orig_dtsi) as olddtsi: |
| 55 | shutil.move(new_dtsi,orig_dtsi) | 84 | for line in olddtsi: |
| 85 | if soc_family == 'versal': | ||
| 86 | newdtsi.write(re.sub('firmware-name.*\".*\"','firmware-name = \"'+d.getVar('PN')+'.pdi\"',line)) | ||
| 87 | else: | ||
| 88 | newdtsi.write(re.sub('firmware-name.*\".*\"','firmware-name = \"'+d.getVar('PN')+'.bit.bin\"',line)) | ||
| 89 | shutil.move(new_dtsi,orig_dtsi) | ||
| 56 | } | 90 | } |
| 57 | 91 | ||
| 58 | python devicetree_do_compile:append() { | 92 | python devicetree_do_compile:append() { |
| 59 | import glob, subprocess | 93 | import glob, subprocess |
| 60 | pn = d.getVar('PN') | 94 | soc_family = d.getVar("SOC_FAMILY") |
| 61 | biffile = pn + '.bif' | 95 | |
| 96 | # Convert .bit to bit.bin format only if dtsi is input. | ||
| 97 | # In case of dtbo as input, bbclass doesn't know if firmware-name is .bit or | ||
| 98 | # .bit.bin format and corresponding file name. Hence we are not doing | ||
| 99 | # bit.bin conversion. | ||
| 100 | if soc_family != 'versal' and '.dtsi' in d.getVar("SRC_URI"): | ||
| 101 | pn = d.getVar('PN') | ||
| 102 | biffile = pn + '.bif' | ||
| 62 | 103 | ||
| 63 | with open(biffile, 'w') as f: | 104 | with open(biffile, 'w') as f: |
| 64 | f.write('all:\n{\n\t' + glob.glob(d.getVar('S')+(d.getVar('BIT_PATH') or '') + '/*.bit')[0] + '\n}') | 105 | f.write('all:\n{\n\t' + glob.glob(d.getVar('S')+(d.getVar('BIT_PATH') or '') + '/*.bit')[0] + '\n}') |
| 65 | 106 | ||
| 66 | bootgenargs = ["bootgen"] + (d.getVar("BOOTGEN_FLAGS") or "").split() | 107 | bootgenargs = ["bootgen"] + (d.getVar("BOOTGEN_FLAGS") or "").split() |
| 67 | bootgenargs += ["-image", biffile, "-o", pn + ".bit.bin"] | 108 | bootgenargs += ["-image", biffile, "-o", pn + ".bit.bin"] |
| 68 | subprocess.run(bootgenargs, check = True) | 109 | subprocess.run(bootgenargs, check = True) |
| 69 | 110 | ||
| 70 | if not os.path.isfile(pn + ".bit.bin"): | 111 | if not os.path.isfile(pn + ".bit.bin"): |
| 71 | bb.fatal("bootgen failed. Enable -log debug with bootgen and check logs") | 112 | bb.fatal("bootgen failed. Enable -log debug with bootgen and check logs") |
| 72 | } | 113 | } |
| 73 | 114 | ||
| 74 | do_install() { | 115 | do_install() { |
| 75 | install -d ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ | 116 | install -d ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ |
| 76 | install -Dm 0644 *.dtbo ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.dtbo | 117 | |
| 77 | install -Dm 0644 ${PN}.bit.bin ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.bit.bin | 118 | # In case of dtbo as input, dtbo will be copied from directly from ${S} |
| 119 | # In case of dtsi as input, dtbo will be copied from directly from ${B} | ||
| 120 | if [ -f ${S}/*.dtbo ]; then | ||
| 121 | install -Dm 0644 ${S}/*.dtbo ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ | ||
| 122 | elif [ -f ${B}/*.dtbo ]; then | ||
| 123 | install -Dm 0644 ${B}/*.dtbo ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.dtbo | ||
| 124 | else | ||
| 125 | bbfatal "A dtbo ending '.dtbo' expected but not found" | ||
| 126 | fi | ||
| 127 | |||
| 128 | if [ "${SOC_FAMILY}" == "versal" ]; then | ||
| 129 | # In case of dtbo as input, pdi will be copied from directly from ${S} | ||
| 130 | # without renaming the pdi name to ${PN}.pdi | ||
| 131 | if [ -f ${S}/*.pdi ] && [ -f ${S}/*.dtbo ]; then | ||
| 132 | install -Dm 0644 ${S}/*.pdi ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ | ||
| 133 | elif [ -f ${S}/*.pdi ] && [ -f ${B}/*.dtbo ]; then | ||
| 134 | install -Dm 0644 ${S}/*.pdi ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.pdi | ||
| 135 | else | ||
| 136 | bbfatal "A PDI file with '.pdi' expected but not found" | ||
| 137 | fi | ||
| 138 | else | ||
| 139 | # In case of dtbo as input, .bit or .bit.in will be copied from directly | ||
| 140 | # from ${S} without renaming the .bit name to ${PN}.bit.bin | ||
| 141 | if [ -f ${S}/*.bit* ] && [ -f ${S}/*.dtbo ]; then | ||
| 142 | install -Dm 0644 ${S}/*.bit* ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ | ||
| 143 | elif [ -f ${B}/${PN}.bit.bin ] && [ -f ${B}/*.dtbo ]; then | ||
| 144 | install -Dm 0644 ${B}/${PN}.bit.bin ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.bit.bin | ||
| 145 | else | ||
| 146 | bbfatal "A bitstream file with '.bit' or '.bit.bin' expected but not found" | ||
| 147 | fi | ||
| 148 | fi | ||
| 149 | |||
| 78 | if ls ${S}/${XCL_PATH}/*.xclbin >/dev/null 2>&1; then | 150 | if ls ${S}/${XCL_PATH}/*.xclbin >/dev/null 2>&1; then |
| 79 | install -Dm 0644 ${S}/${XCL_PATH}/*.xclbin ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.xclbin | 151 | install -Dm 0644 ${S}/${XCL_PATH}/*.xclbin ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.xclbin |
| 80 | fi | 152 | fi |
| 81 | install -Dm 0644 ${S}/${JSON_PATH}/shell.json ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/shell.json | 153 | |
| 154 | if [ -f ${WORKDIR}/${JSON_PATH}/accel.json ]; then | ||
| 155 | install -Dm 0644 ${S}/${JSON_PATH}/accel.json ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/accel.json | ||
| 156 | fi | ||
| 82 | } | 157 | } |
| 83 | 158 | ||
| 84 | do_deploy[noexec] = "1" | 159 | do_deploy[noexec] = "1" |
