In prjxray, Frames::readFrames applies updateECC() to every frame as it is loaded (lib/include/prjxray/xilinx/frames.h:99 upstream), patching the 13-bit ECC field in bits [12:0] of frame word 0x32. In the port, the ECC math was carried over correctly — xc7::UpdateECC in fpga/xilinx/arch-xc7-frame.h:137 matches prjxray's ecc.cc bit for bit and is unit-tested — but nothing in the production pipeline calls it. BitStream::Encode (fpga/xilinx/bitstream.h) constructs Frames directly from the caller's map and goes straight to packet generation.
The intended hook is broken dead code:
Frames::AddFrame (fpga/xilinx/frames.h:29-32) is never called anywhere in the repo.
- It passes the whole
btree_map (data_) to a member declared as void UpdateECC(FrameWords &) (frames.h:49), so it cannot compile if instantiated.
- That member
Frames::UpdateECC is declared but defined nowhere (link error if ever used).
data_.insert(address, words) is not a valid two-argument absl::btree_map insert.
Consequence: every emitted frame carries a wrong (typically zero) ECC syndrome. The device still configures — ECC is not checked at load time — but the output is not bit-identical to prjxray's xc7frames2bit / Vivado output, and post-configuration SEU mitigation (SEM IP, readback ECC scan) will flag essentially every non-empty frame as corrupted.
Suggested fix: apply xc7::UpdateECC to each frame's words in BitStream::Encode (or in the Frames constructor), and delete or repair the broken Frames::AddFrame / undefined member UpdateECC.
Found by comparing against prjxray @ 7557c7cc.
In prjxray,
Frames::readFramesappliesupdateECC()to every frame as it is loaded (lib/include/prjxray/xilinx/frames.h:99upstream), patching the 13-bit ECC field in bits [12:0] of frame word0x32. In the port, the ECC math was carried over correctly —xc7::UpdateECCinfpga/xilinx/arch-xc7-frame.h:137matches prjxray'secc.ccbit for bit and is unit-tested — but nothing in the production pipeline calls it.BitStream::Encode(fpga/xilinx/bitstream.h) constructsFramesdirectly from the caller's map and goes straight to packet generation.The intended hook is broken dead code:
Frames::AddFrame(fpga/xilinx/frames.h:29-32) is never called anywhere in the repo.btree_map(data_) to a member declared asvoid UpdateECC(FrameWords &)(frames.h:49), so it cannot compile if instantiated.Frames::UpdateECCis declared but defined nowhere (link error if ever used).data_.insert(address, words)is not a valid two-argumentabsl::btree_mapinsert.Consequence: every emitted frame carries a wrong (typically zero) ECC syndrome. The device still configures — ECC is not checked at load time — but the output is not bit-identical to prjxray's
xc7frames2bit/ Vivado output, and post-configuration SEU mitigation (SEM IP, readback ECC scan) will flag essentially every non-empty frame as corrupted.Suggested fix: apply
xc7::UpdateECCto each frame's words inBitStream::Encode(or in theFramesconstructor), and delete or repair the brokenFrames::AddFrame/ undefined memberUpdateECC.Found by comparing against prjxray @ 7557c7cc.