stdp_facetshw_synapse_hom#
- class brainpy.state.stdp_facetshw_synapse_hom(*args, **kwargs)#
FACETS/BrainScaleS hardware STDP synapse spec (NEST
stdp_facetshw_synapse_hom).A hardware-constrained STDP model with a 4-bit discrete weight updated only at periodic readout events, not at every spike. Between readouts two analogue charges accumulate from nearest-neighbour pre/post pairings:
\[ \begin{align}\begin{aligned}a_\text{causal} \mathrel{+}= \exp\!\Big(\tfrac{-(t_\text{post}-t_\text{pre})}{\tau_+}\Big) \quad\text{(first post since the last pre)}\\a_\text{acausal} \mathrel{+}= \exp\!\Big(\tfrac{-(t_\text{pre}-t_\text{post})}{\tau_-}\Big) \quad\text{(nearest post before this pre)}\end{aligned}\end{align} \]At a readout (the first pre spike that crosses
next_readout) the weight is quantised to a LUT indexe = round(w / w_\text{ple}), two boolean evaluation functions compare the charges against thresholds, and one look-up table mapse:\[\text{eval}_k = \frac{a_{tl} + b^k_2 a_\text{causal} + b^k_1 a_\text{acausal}} {1 + b^k_2 + b^k_1} > \frac{a_{th} + b^k_0 a_\text{causal} + b^k_3 a_\text{acausal}} {1 + b^k_0 + b^k_3}\]with config bits \(b^k = `\ ``configbit_k`\).
(eval0, eval1)selects the table:(T,F)->lookuptable_0(potentiation),(F,T)->lookuptable_1(depression),(T,T)->lookuptable_2(default identity),(F,F)leaves the index unchanged. The new weight ise' * w_\text{ple}— so the weight is re-quantised at every readout even when no table fires.reset_patternthen zeroes the charges (per branch, causal/acausal), andnext_readoutadvances by wholereadout_cycle_durations past the spike. With the default config bits anda_thresh_th == a_thresh_tl,eval0reduces toa_causal > a_thresh_thandeval1toa_acausal > a_thresh_th.Warning
Default-weight footgun. With
Wmax=100the quantum isw_ple = Wmax/15 ≈ 6.667; the defaultweight=1.0quantises to indexround(1/6.667)=0and the first readout zeroes it. Choose a weight on (or near) the LUT grid — e.g.5 * Wmax/15 ≈ 33.33.- Parameters:
weight (
ArrayLikeorQuantity, optional) – Per-edge weight (pA; bare numbers are pA). Default1.0pA — see the footgun warning above.delay (
Quantity, optional) – Homogeneous axonal delay (> 0). Default1.0 ms.receptor_type (
int, optional) – Postsynaptic receptor port (>= 0). Default0.tau_plus (
Quantity, optional) – Causal-charge (K+) trace constant (> 0). Default20.0 ms.tau_minus (
Quantity, optional) – Acausal-charge (K-) trace constant (> 0). Default20.0 ms.Wmax (
float, optional) – Weight bound, used for the default quantum. Default100.0.a_thresh_th (
float, optional) – Upper/lower charge thresholds in the evaluation functions. Default21.835.a_thresh_tl (
float, optional) – Upper/lower charge thresholds in the evaluation functions. Default21.835.lookuptable_0 (
sequenceofint, optional) – The 16-entry weight-update tables (potentiation / depression / identity). Each entry must index back into the table ([0, 15]).lookuptable_1 (
sequenceofint, optional) – The 16-entry weight-update tables (potentiation / depression / identity). Each entry must index back into the table ([0, 15]).lookuptable_2 (
sequenceofint, optional) – The 16-entry weight-update tables (potentiation / depression / identity). Each entry must index back into the table ([0, 15]).configbit_0 (
sequenceofint, optional) – Four 0/1 bits parameterisingeval0/eval1.configbit_1 (
sequenceofint, optional) – Four 0/1 bits parameterisingeval0/eval1.reset_pattern (
sequenceofint, optional) – Six 0/1 flags: reset (causal, acausal) after alookuptable_0/_1/_2update respectively. Default all-on.weight_per_lut_entry (
float, optional) – The weight quantum. DefaultWmax / (lut_size - 1).synapses_per_driver (
int, optional) – Synapses served by one hardware weight-update controller. Default50.driver_readout_time (
float, optional) – Time (ms) one controller takes per synapse. Default15.0.
Notes
Single-driver scope. For a single edge (and any edge count up to
synapses_per_driver) NEST’sreadout_cycle_duration = int((no_synapses-1)/synapses_per_driver + 1) * driver_readout_timecollapses todriver_readout_timeand every synapse’s first readout offset is 0, which is what this spec models (next_readoutstarts at 0). True multi-driver round-robin grouping forE > synapses_per_driver(staggered per-synapse offsets) is out of scope.Deferred accumulation. NEST accumulates the
send’s pairing after the readout, so a readout never sees the charge from the pair that triggered it. The kernel reproduces this by capturing the causal term at the post (causal_pending) and folding it — together with the acausal term — only at the next pre, after that pre’s readout. Exact pre/post coincidence follows the substrate second-latest convention and is not asserted against NEST.Parity note. The charge-accumulation / LUT-readout pairing convention, the NEST keys and single-driver scope, and the parity test are documented in STDP parity: where state lives and how spikes pair (stdp_facetshw_synapse_hom — hardware (FACETS) charge accumulation + LUT readout).
References
Examples
>>> import brainunit as u >>> from brainpy.state import stdp_facetshw_synapse_hom >>> s = stdp_facetshw_synapse_hom(weight=33.333, Wmax=100.0) >>> round(s.weight_per_lut_entry, 3) 6.667 >>> s._weight_to_entry(33.333) # nearest 4-bit index 5 >>> sorted(s.edge_state_init()) ['a_acausal', 'a_causal', 'causal_pending', 'next_readout', 'post_seen', 'pre_seen']