patch notes · #627 September
#6 · The CLI's untested paths get checks, one number for the count, a test that reads the bitstream, the board test ready for the board
In numbers. test/run.sh: 213 passed before, 237 passed, 0 failed after (15 min 7 s; the 24 new checks add about 35 s), plus one SKIP: flash on the board: no board: plug the Basys3 in and run test/run.sh again. test/run.sh --list prints every check's name, 133 probes and 293 checks (the two clean-install checks and the board check are counted on every machine, so no single plain run reaches 293: the header says which ones a run skips). README, README.tr and the cli page quote 293 and 133 from --list, and a check compares them. Vivado-supported probes passing all four stages 59/111 → 59/111 (this update changes tests, not verdicts); the stage columns of expect.tsv unchanged. test/bit-check.sh reads the frames back out of blink.bit and compares them with the .fasm: bit ok: blink.bit holds the 5408 frames of blink.fasm (105 non-zero), read back from 1 FDRI write(s); another design's fasm, a .bit cut in half and a .bit with one bit flipped in a used frame are refused. The board checks are written and skip without a board; their first real run is Damla's, with the Basys3 on USB.
6A · The CLI's untested paths get checks; test/run.sh --list prints the count the docs quote.
test/run.sh --list prints every check's name, then 133 probes and 289 checks, and exits 0 without running anything; ONLY=regex test/run.sh runs the checks whose name matches (the probes are skipped). README, README.tr and site/cli quote 289 checks / 289 kontrol and 133 SystemVerilog probes, and one check greps the three files for the two numbers --list printed, so a stale number fails the suite.
Paths that had no check before (15 in == error paths, 3 in == rebuild rules): bit src/x, bit --foo, an FPGA_HOME with a space, a UTF-8 BOM, a testbench without $finish (SIM_TIMEOUT=2), a testbench ending with $stop, a _tb.v testbench (Verilog-2005), a missing IOSTANDARD, a failed build removing the old .bit, uninstall removing what install built and keeping the rest, uninstall with nothing installed, a design only yosys-slang reads, the note naming dewfpga install when slang.so is absent, two clocks named on the pnr line; a changed .svh include rebuilds and the .bit and .frames differ byte for byte, a changed .mem ROM rebuilds and the .bit differs, a renamed testbench recompiles (sleep 1.1 first: make compares whole seconds). personal_paths adds --exclude=.git (in a worktree .git is a file holding a home path).
Integration: 6A and 6B both edited test/run.sh and clashed in three hunks (the shellcheck line, the old flash checks, the section after the rebuild rules); resolved by hand keeping both. 6A's count was 284 before 6B's block (+5 checks without a board); the number on the pages is what --list prints after both: 289. Run alone: ONLY='new \+ dewfpga bit|unnamed instance|blink\.bit|cut in half|flipped|flash|quote the numbers|shellcheck' test/run.sh -> passed 11, failed 0, known gaps 0, with SKIP flash on the board: no board: plug the Basys3 in and run test/run.sh again. Untested tonight: the flash check with a board (no board plugged in), the full suite.
6B · A test looks inside the bitstream; the board test is ready for the board.
test/bit-check.sh <top.bit> <top.fasm|top.frames> reads the bitstream back. No test had ever opened a .bit: bit checked the file's size and that the .frames file was the same twice. Now the .bit is parsed as UG470 chapter 5 lays it out: the header up to the sync word AA995566, then the type 1 / type 2 configuration packets; the FDRI write is cut into 101-word frames (UG470 table 5-18, 7-series) and each frame gets its address by walking part.yaml's columns the way xc7frames2bit does (block type, top/bottom, row, column, minor; two zero frames between rows and block types). Every one of the part's 5408 frames is compared with what fasm2frames.py makes of the .fasm (a .frames file is taken as is; frames it does not name are zero). The one thing not compared is the 13-bit ECC field of word 50, which xc7frames2bit computes and the .frames does not hold. prjxray's bitread is not built in ~/fpga (only xc7frames2bit is), so the reader is 60 lines of Python in the script, on the venv's python and yaml.
What it printed (paths shortened):
- blink.bit + blink.fasm:
bit ok: blink.bit holds the 5408 frames of blink.fasm (105 non-zero), read back from 1 FDRI write(s), exit 0 - blink.bit + blink.frames: the same line, exit 0
- blink.bit + the fasm of another design (probe 07, a sw -> led state machine):
ERROR [bit-check]: blink.bit does not hold the frames of top.fasm: 82 of 5408 frames differ, first 3: 0x00000a00 word 24: bit 0x00000200, fasm 0x00000000; 0x00000a01 word 24: bit 0x00000040, fasm 0x00000000; 0x00000a04 word 62: bit 0x00800000, fasm 0x00000000, exit 1 - blink.bit cut in half (
head -c 1096057):ERROR [bit-check]: half.bit does not hold the frames of blink.fasm: truncated: a packet at word 45 says 547420 words, only 273929 are left (1096057 bytes in the file), exit 1 - blink.bit with one bit flipped inside a used frame:
ERROR [bit-check]: flip.bit does not hold the frames of blink.fasm: 1 of 5408 frames differ, first 1: 0x00000a04 word 74: bit 0x42000000, fasm 0x02000000, exit 1
test/run.sh: the block == inside the bitstream, and the board (one delimited block after the project template section, marked #6B), seven checks without a board, run alone against a prebuilt blink and probe 07's fasm: passed 7, failed 0. The five bitstream checks are the five lines above, on the blink dewfpga new built ($T/p) and the sw -> led design of the unnamed-instance check ($T/ui). The two flash checks moved here from the build section: dewfpga flash without a board has to exit 1 with ERROR [board-not-found]: board not found and no make: *** trailer, and the run then prints one line: SKIP flash on the board: no board: plug the Basys3 in and run test/run.sh again. With a Basys3 on USB (system_profiler lists Digilent) the block instead runs dewfpga flash on that blink and greps openFPGALoader's own success line, Done (the string in /opt/homebrew/bin/openFPGALoader; SRAM only, gone at power off). The old DEWFPGA_TEST_BOARD=1 gate is gone: a plugged-in board is programmed with blink. Not run with a board tonight: no board was plugged in. The board branch is written from openFPGALoader's strings, not from a run; the first run with a board is the check of that line. shellcheck -S style covers test/bit-check.sh now.
Test count: two flash checks before, seven checks in the block after: +5 without a board (+4 with one). test/run.sh was not run whole here (9 minutes); the block was run on its own.
Fix round 1 (6B-fix), two findings of the judges:
--listprinted 288 with a board, 289 without. The board branch held one check, the no-board branch two, and--listwalks whichever branch the machine is in, so the number the three pages quote (289) was wrong on the machine the board is plugged into, and the docs check failed there. Reproduced with a fakesystem_profilerfirst on PATH (test/run.shcalls it unqualified) that printsDigilent USB Device:test/run.sh --list | tail -1printed288 checksandONLY='quote the numbers' test/run.shprintedFAIL README, README.tr and site/cli quote the numbers --list prints (checks, probes). Now either branch is two checks: with a board,flash on the board: openFPGALoader programs it (its Done line)andflash on the board: exit 0, no ERROR line(dewfpga flash >out 2>&1 && ! grep -q 'ERROR \[' out). After:289 checkswith the fake board and without, and the docs checkPASSin both. The board branch is still not run against a board (none plugged in tonight).bit-check.shblamed the.fasmwhen the tools were not where it looked, and it looked only atFPGA_HOME/~/fpga, not at.fpga_homeasbin/dewfpgadoes. Reproduced:FPGA_HOME=/nowhere test/bit-check.sh top.bit top.fasmprintedline 25: /nowhere/venv/bin/python: No such file or directoryandERROR [bit-check]: fasm2frames could not read top.fasm. Now the script resolves the folder the waybin/dewfpgaline 18 does ($FPGA_HOME, else the repo's.fpga_home, else~/fpga), checks that the venv python,fasm2frames.pyand the part'spart.yamlexist before anything else, and names the missing one and where the folder came from:ERROR [bit-check]: /nowhere/venv/bin/python is not there (FPGA_HOME=/nowhere). Fix: run install.sh, or set FPGA_HOME to the folder that holds venv/, prjxray/ and nextpnr-xilinx/.With.fpga_homesaying/elsewhere(a copy of the script under a scratch root):ERROR [bit-check]: /elsewhere/venv/bin/python is not there (<root>/.fpga_home says /elsewhere). Fix: .... A real fasm2frames failure now carries its last stderr line instead of "could not read": on a file holdinggarbage line !!:ERROR [bit-check]: fasm2frames (~/fpga/prjxray/utils/fasm2frames.py) failed on bad.fasm: textx.exceptions.TextXSyntaxError: .../bad.fasm:1:14: Expected S or '=' or '{' or '#' or Identifier or Newline or EOF => 'bage line *!! '. Fix: the .fasm has to be nextpnr-xilinx's own output for xc7a35tcpg236-1; rebuild it with dewfpga bit.The sane run is unchanged:bit ok: top.bit holds the 5408 frames of top.fasm (192 non-zero), read back from 1 FDRI write(s).shellcheck -S styleon both scripts: clean.
Fix round 1 (6A-fix + integration), the other findings:
--listprinted a different number underFULL=1and on a board machine. Now every branch is listed whatever the machine: the two board checks, the two no-board checks and the two clean-install checks all count, sotest/run.sh --list | tail -1prints293 checksplain, underFULL=1, with a fakesystem_profilerthat printsDigilent USB Device, and with both. The run prints fewer PASS lines than that, never more: the branch the machine cannot run prints one SKIP line (SKIP flash on the board: no board: plug the Basys3 in and run test/run.sh again, orSKIP flash w/o board (2 checks): a Basys3 is on USB). The docs check readsFULL='' test/run.sh --listand finds theN probesline by pattern, not by position. README, README.tr and site/cli say 293 and why. Merged with finding 1 above: the board branch keeps 6B-fix's two checks (Done line; exit 0 and no ERROR line), so 289 + 2 board + 2 install = 293. With the fake board: the docs checkPASS, the two board checksFAIL(no board is plugged in), as they must.- The bitstream and board checks could not run alone under
ONLY=regex: they used$T/pand$T/ui, built by checks the regex had skipped.need_pandneed_uibuild them when missing.ONLY='blink.bit|\.bit |flash' test/run.sh: the five bitstream checks and the two no-board checksPASS,passed 10, failed 0(three rebuild/probe-runner checks match the regex too). The== buildand== multi-file designchecks still need the section's first check in the regex; the header oftest/run.shsays so. - Integration note. The tree before this update has no
--list:test/run.sh --listthere ignores the argument and starts the whole nine-minute suite (the before/after demo killed it after 25 s, exit 142). Its pages said46 checks.bin/dewfpga,templates/*,install.shandtest/sv/expect.tsvare untouched.
Fix round 3 (6B-fix), one finding of the judges:
- A board check that FAILs showed nothing a student could act on. The first on-board check piped
dewfpga flashintogrep -q 'Done'and the others wrote to their ownoutfile, so$T/out(whatbad()prints five lines of) was empty; the same for the seven bitstream checks. Reproduced with a fakesystem_profileron PATH printingDigilent USB Device,ONLY='flash on the board' test/run.sh:FAIL flash on the board: openFPGALoader programs it (its Done line)andFAIL flash on the board: exit 0, no ERROR linewith nothing under either,passed 0, failed 2; and in a scratch copy of the product withboard-not-foundrenamed,ONLY='flash w/o board':FAIL flash w/o board: board-not-found line, exit 1, bare. Nowtest/run.shhassay <cmd...>: it runs the command with its output kept in$T/sayfor the check's grep and printed too, so it lands in the check's output and under a FAIL; the nine checks of the block run the product through it.check()also prints anyERROR [line past the first five (shown), since the product's ERROR line comes last, after openFPGALoader's own lines. After, the same fake board:FAIL flash on the board: openFPGALoader programs it (its Done line)followed byunable to open ftdi device: -3 (device not found)/JTAG init failed with: unable to open ftdi device/ERROR [board-not-found]: board not found: the Mac sees no Basys3 on USB (openFPGALoader: unable to open ftdi device). Fix: plug the USB into the PROG port, switch the power ON, and try another cable or port. https://nosey-dewdrop.github.io/dewfpga/errors/board-not-found/, the same three lines under the second FAIL; the renamed copy shows itsERROR [board-missing]: ...line under its FAIL; a bit-check refusal made to fail (its "frames differ" wording renamed in a copy) showsERROR [bit-check]: .../p/blink.bit does not hold the frames of .../ui/ui.fasm: 111 of 5408 frames disagree, first 3: 0x00000a00 word 24: .... Unchanged where it should be:ONLY='blink.bit|\.bit |flash' test/run.shon the real product, no board: the five bitstream checks and the two no-board checksPASS, one SKIP line;test/run.sh --list | tail -1still293 checks;shellcheck -S style test/run.shclean. Still not run with a board (none plugged in).
Tried and dropped:
- Re-encoding the
.frameswithxc7frames2bitand comparing bytes: the header carries the date and time, and a byte compare says nothing about which frame differs. Parsing the packets does. - Comparing word 50 whole:
xc7frames2bitrewrites its low 13 bits (updateECCin prjxray'secc.cc,data[50] &= 0xFFFFE000), so the.framesand the.bitalways differ there. Masked. - Building
bitreadfrom prjxray's sources: it would write into~/fpga, which this update leaves alone.
Also in this commit. The check uninstall refuses FPGA_HOME=HOME ran the real CLI's uninstall against the real home (the judge read it: the day the guard breaks, the test deletes ~/venv); it runs against a scratch home now, with a scratch fpga and venv that must survive.
Found and left to later updates.
- Product (K2 or #4 later): a build that fails in the XDC stage (a missing IOSTANDARD, a wrong port name) leaves the previous
.bitnext to the sources (only the synthesis rule removes it); the.depsrebuild rules miss a change made within the same second as the previous compile (Apple's make 3.81 compares whole seconds: bitessim, neverbit); a block-RAM or$readmemhdesign with registers onposedge clkprintsWarning: No clocks found in designand0 LUT, 0 FF, no clocked pathsalthough it is clocked (DOĞRULANMADI why: possibly the sync read became LUTRAM output registers nextpnr does not time). - Tests:
bit-check.shaccepts a.bitwith garbage appended after the last packet (words that are neither type-1 nor type-2 are skipped as padding); the SKIP line sends the student to the whole suite for two 40-second checks (ONLY='new \+ dewfpga bit|flash' test/run.shruns them alone); the two on-board checks were run only with a fakesystem_profiler, never with a board. - Not verified (DOĞRULANMADI): whether make 3.81 on this Mac lacks sub-second timestamps or the copy does.
Orchestration, for the record. 15 agents, 1 h 27 min, none died: 2 build (40, 30 minutes), 1 integrator, 2 break rounds, 3 fix agents, the judge, 3 integrations; the integrators committed in the main tree (the first commit went out with the #5 CI fix; the three fix commits are squashed into this one). The judge's process notes: the metric "N passed before → M passed after" needed two full runs no agent was allowed to make (the main session made them: 213 → 237); two agents in one file (test/run.sh) cost a hand merge in three hunks; a before-demo command must be vetted against the before tree (--list did not exist there and started the whole suite); "the same number on every machine" shipped twice without a run on a second kind of machine (env -i would have caught yosys: command not found at line 83 and the board and FULL modes); a check that hides the product's output prints a bare FAIL (fixed in round 3 with say/shown); "each new check broken once" was promised and not evidenced in the integrator's report (the judge did three).
previous: #5 Every message in one shape, with its code and its page
next: #7 Safer installation and reproducible simulator distribution
This entry in the full list
The commands this entry names: dewfpga install · dewfpga bit · dewfpga flash · dewfpga new
Every SystemVerilog construct measured so far, next to what Vivado does: the probes, stage by stage