Skip to content

Instantly share code, notes, and snippets.

@regymm
Created January 17, 2025 12:58
Show Gist options
  • Save regymm/1265dd6e9885983dc1d9977e42724319 to your computer and use it in GitHub Desktop.
Save regymm/1265dd6e9885983dc1d9977e42724319 to your computer and use it in GitHub Desktop.
PrjXray Notes

PrjXray Notes

This official document is a very good reference, just that now there are many more fuzzers.

https://f4pga.readthedocs.io/projects/prjxray/en/latest/db_dev_process/newpart.html

Multi-thread

Error might be confusing (as when error occurs, all “current running jobs” will be stopped, making other fuzzers in half-done state — but no worries, other fuzzers will start from scratch if being run again). Troubleshooting on single thread is better.

But for real compiling it works very fine, and saves a lot of time. Single-thread run of the whole database from scratch can take >48 hours.

I need to add the —jobserver-style=pipe to make things compatible

make —jobserver-style=pipe -j8 MAX_VIVADO_PROCESS=8 -C fuzzers

074-dump-all may use a lot of memory for Zynq 7045 and 7100, need to single-thread run again on fail. MAX_VIVADO_PROCESS will not affect the vital part, need to use export MAX_GRID_GPU=1, for the create_node_tree.py, generate_grid.py, etc. Threads/multicore probably doesn’t reduce maximum memory usage. 128 GB memory + swap is needed for 7100. Manually single-step the scripts in fuzzers/074-dump_all/generate_after_dump.sh if got OOM error.

Format

You may notice files in database have different size from the database on GitHub (which is larger). Don’t worry! A make db-format-zynq7 will format the database, and recreate a exact same file as in prjxray-db repo. The format process adds more blank spaces and enlarged the size.

Part and All

In fuzzers/Makefile, all fuzzers are listed. Some depend on other ones (mostly 005-tilegrid), some don’t (can run standalone).

When a fuzzer is finished, a run.ok is touched in fuzzer dir, if the result can be shared between devices (my understanding). Otherwise, for each device, a run.xc7axxxx.ok is touched.

Thus, when adding a new device (family), it may be better to have a completed run of existing devices, so all inter-part fuzzers can be already finished.

Can run with make -C fuzzers, or use top Makefile’s functions like make db-part-only-zynq7100

In default Makefile, the way of building full DB is first run part specific + all inter-part fuzzers for the base part, then run part-only for the other devices.

On Zynq when both Artix and Kintex fabric are present, another full run on Zynq7030 is needed.

db-extras-zynq7-parts: $(addprefix db-part-only-,$(ZYNQ_PARTS))
db-extras-$(1): db-extras-$(1)-parts db-extras-$(1)-roi db-extras-$(1)-harness
db-$(1)-all: db-$(1) db-extras-$(1)-parts
	# Build harnesses after database is complete
	$$(MAKE) db-extras-$(1)-roi
	$$(MAKE) db-extras-$(1)-harness

XRAY_ROI_GRID_XX

This is also confusing but can be solved by looking at the implemented device view in Vivado.

ROI means region of interest.

Generally (my understanding, may be wrong), XRAY_ROI_TILEGRID is the whole device, and XRAY_ROI (as well as XRAY_ROI_GRID_XX) is a sub part to use for fuzzing (as an optimization). If the part is too small, important block may not be included inside. A minimum area including all required element is the best, but we can just make it the whole device (same as XRAY_ROI_TILEGRID).

In fuzzer code, the X1/X2/Y1/Y2 are used many times to “select out” a region of interest. To be safe, this is also set to all of the devices. There seems no penalty (except speed?) for setting it larger.

Whole device (xc7z100):

Left top is PS7, right middle to bottom is transceivers (GTX).

image

image 1

image 2

By picking the corners (real corner, PS7/GT tiles makes the corner smaller…), we

Can also see, left IO banks are LIOB33 (high range), right IO banks are ROIB18 (high performance, maximum 1.8V).

Very interesting to see where the instances we wrote in Verilog really are on hardware.

Haven’t checked but maybe this commit’s info can help: https://github.com/openXC7/prjxray/commit/b9d8f1ae7995a7bb926b27705e37ce74a9e26edf

BYTESRC/BYTETERM?

These are marked on some IO pins’ places, several per IO bank, on both HR and HP banks. Didn’t find information about the name. This requires some extra (but trivial?) handling in fuzzers.

image 3

image 4

image 5

Unbonded IOs

Usually, all IOs are bonded on the largest footprint of a certain device. On smaller footprint devices, some IO banks are not bonded (but all the primitives and logic resources are still there).

On Zynq 7045, however, the X0Y0 bank seems always unbonded, thus requires modifying some fuzzers (005). It’s not recommended to use these IOs.

image 6

005-tilegrid

I don’t know what this is doing exactly, but the Makefile inside is as important as the fuzzer’s overall Makefile. Enable/disable of certain components (e.g. IOB18, PCIE, GT) are also specified here.

Since it’s in Python (unlike nextpnr…), if something wrong happens, it’s very straightforward to peek into the file, print out related variables (tile_name, site_name, etc), and deal with the error part.

When called from parent (Make run), every existing result will be cleaned before running.

When called directly (make -C fuzzers/005-tilegrid), old result will remain.

Morale: many things are skipped. But (in my feeling) skipping doesn’t mean anything bad. In most cases, it’s just some corner cases that are not handled that properly. There are always some “special” elements and maybe only Xilinx knows why.

Even if good primitives are skipped, it’s totally fine as far as we don’t use it — for some exotic IO primitives, probably no one uses them. The flow would be like, if primitives or other bits are reported missing by nextpnr, they can always be addressed back and fixed (or avoided in nextpnr). The flow will NOT use skipped/unsupported elements and just fail silently.

PPIPS

It’s a inter-part fuzzer, but for Zynq with Kintex fabrics, ppips need to be run twice, once on 7010/7020, another times on 7030/etc.

Just rm fuzzers/071-ppips/run.ok and make --jobserver-style=pipe -j8 MAX_VIVADO_PROCESS=8 -C fuzzers again, with zynq7030.sh sourced.

This create correct ppips_rioi.db, as long as 3.3V RIOB’s ppips_rioi3.db (two files are literally the same though, can vimdiff it and see).

Otherwise, fasm will complain about missing entries:

prjxray.fasm_assembler.FasmLookupError: Segment DB RIOI, key RIOI.RIOI_I0.RIOI_IBUF0 not found from line 'RIOI_X139Y347.RIOI_I0.RIOI_IBUF0'
Segment DB RIOI, key RIOI.IOI_LOGIC_OUTS18_1.IOI_ILOGIC0_O not found from line 'RIOI_X139Y347.IOI_LOGIC_OUTS18_1.IOI_ILOGIC0_O'
Segment DB RIOI, key RIOI.RIOI_ILOGIC0_D.RIOI_I0 not found from line 'RIOI_X139Y347.RIOI_ILOGIC0_D.RIOI_I0'G

This might also solve the manually created “fake” ppips_rioi_tbyteterm.db as mentioned in https://github.com/openXC7/prjxray-db/tree/master/kintex7#changelog

If fasm errors occur, can just find the keyword like RIOI_I0.RIOI_IBUF0 in database/zynq7 to pinpoint the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment