The negotiated-congestion router can spin without converging on
designs where (a) the architecturally optimal wire is genuinely
unavailable, (b) the cost gradient between two near-equivalent
candidates is too shallow to settle, or (c) a placer choice has
fenced off the legal binding space and the failure won't surface
until bind_and_check_all() actually runs. Today the main loop has
no upper bound on iterations and bind_and_check_all() is only ever
called on full convergence, so a stuck design loops forever while
logging "archfail=NA" every iteration.
Three small, opt-in safety hatches:
1. Hard iteration ceiling -- `cfg.max_router_iters` (default 2000).
When reached, log a warning, bind what we have, and break the
loop instead of spinning.
2. Stall detection -- `cfg.stall_iter_limit` (default 50). Watch
(overused_wires, total_wire_overuse) across consecutive
iterations. When both stay unchanged for stall_iter_limit
iterations, first try resetting `curr_cong_weight` back to
`cfg.init_curr_cong_weight` (once) to escape a local minimum.
If the stall persists after the reset, break with a
best-effort binding rather than continuing to loop.
3. Periodic validity check -- `cfg.bind_check_interval` (default
100). Even when `overused_wires > 0`, call
bind_and_check_all() every `bind_check_interval` iterations so
architectural impossibilities surface early instead of being
silently masked by `archfail=NA`.
All three are fully configurable via context settings
(`router2/maxRouterIters`, `router2/stallIterLimit`,
`router2/bindCheckInterval`). Defaults preserve existing
behaviour for designs that converge promptly (well under 2000
iterations and never stall for 50 in a row), and the new break
paths only fire on pathological cases that would otherwise loop
forever.
No new options exposed at the CLI; defaults are sized for typical
designs and out-of-the-box behaviour is unchanged.
POSIX allows any `int` value to be returned but specifies that only
the low 8 bits are available in some contexts:
https://pubs.opengroup.org/onlinepubs/9699919799/functions/_exit.html
For reasons that aren't entirely clear, WASI requires the value to be
in range [0;126), and this is enforced with an assertion at runtime
level in Wasmtime. This should probably be fixed in Wasmtime but until
it is done there doesn't seem to be any harm in returning `125` instead
of `-1`. This also removes any discrepancy due to truncation.
* generic: Fix Python path not including the examples/ directory in the example
It seems that at some point, the embedded Python stopped including the
directory that nextpnr-generic was executed in inside of its sys.path.
This likely happened by de3d5be8 specifying an explicit argv to
the interpreter init function.
* generic: Improve the example for K != 4
Configuring K < 4 used to result in "dangling" inputs to the cells being
generated (those are just not driven by anything in the resulting Verilog/JSON).
Configuring K > 4 used to result in an assertion crash in cells.cc.
The ctx.setLutK call fixes both cases.
Define open_(o|i)fstream_and_log_error in log.h to:
- quote 'filename'
- add error cause to easier troubleshoot
- use existing consistent string style
- easily allows OS specific message
Introduce it when file are opened and add it where error message
was missing.
* gatemate: removing recursion in GateMateImpl::reassign_bridges
* gatemate: improving comments in GateMateImpl:reassign_bridges
* gatemate: making naming more consistent, adding comments about the need for recursion removal