Some configuration cannot wait for a mode change: link speeds renegotiate, filters retune, features switch on live traffic. Runtime reconfiguration accepts that the value will change under a running datapath and makes the change atomic and ordered instead of pretending it is static.
Pattern | How it works | When it fits |
|---|---|---|
Drain and update | Quiesce the affected path briefly (drain, update, restart) like a miniature mode change. | Updates that tolerate a short pause; the honest version of “write it live”. |
Shadow with atomic commit | Software writes a shadow copy over many cycles; one synced load pulse swaps the whole live value at once. | Wide values that must never tear; see the config pattern. |
Double-buffered swap | Two live banks; the datapath reads one while software fills the other, then a single bit flips the active bank. | Large tables where even a one-cycle commit window is too disruptive. |
Version-guarded read | Each value carries a sequence count; the consumer reads twice and accepts the value only if the count matches. The count is itself a crossing: it must cross through a synchroniser (or be Gray-coded) and updates must be spaced so that the double read is valid. | Read-mostly status and tuning where an occasional retry is cheaper than a handshake. |
All four share one property: at no instant does the consumer see a mixture of old and new. Drain-and-update separates them in time; the other three separate them in space (two copies) with a single-bit commit.
The commit itself (load pulse, bank bit, valid flag) is a crossing and gets the full synchroniser treatment; an atomic commit delivered by a torn pulse is not atomic.
Partial programming is fenced: the consumer cannot select a bank that software is still filling. A “bank ready” handshake or a fill-then-commit order enforced in hardware closes this.
Read-modify-write from software targets the shadow, never the live copy; writing the live copy directly reintroduces tearing one field at a time.
Randomise the update timing against live traffic in simulation: commit at every phase of the datapath, including mid-packet, and check that each transaction uses wholly-old or wholly-new configuration. Assert the commit pulse spacing the synchroniser needs, and cover the fill-then-commit order with a sequence that tries to violate it.
Because correctness needs the whole set of taps to be consistent, not each tap individually. Between tap writes the filter mixes old and new coefficients. Accumulate the set in a shadow bank and swap atomically.