Skip to main content

NS-RAM: Neuro-Synaptic RAM simulator — floating-body transistor neuron/synapse modeling with charge-trapping plasticity. Full BSIM4 path: §6.1 impact ionization, §10.1 junction breakdown (Zener-like), §12 temperature scaling, §3.2 subthreshold, §5.6 velocity-saturated Vdsat, §9 flicker+thermal noise, §13 layout/stress, plus polynomial(Vg1,Vg2) parameter wrapper. GPU-batch fitting. 5 neuron models, 10 RC benchmarks, online learning. 97% XOR, 96.75% MNIST.

Project description

nsram — Neuro-Synaptic RAM Simulator

PyPI Python License

The first open-source Python library for simulating NS-RAM floating-body transistor neurons with charge-trapping synaptic plasticity.

Based on: Pazos et al., "Synaptic and neural behaviours in a standard silicon transistor", Nature 640, 69-76 (2025).

New in v0.12 — Full BSIM4 coverage for NS-RAM

v0.12 expands the BSIM4 path from impact ionization alone to a near-complete set of the equations relevant to floating-body neuron modeling:

  • §10.1 junction breakdown — Zener-like f_breakdown multiplier at the body junction. Structurally closest to Pazos' avalanche-diode subcircuit; alternative firing path to §6.1 channel HCI.
  • §12 temperature scalingtemperature_scale(p, T) applies all T-dependencies: VTH0(T), μ(T), VSAT(T), junction Jss/Jsd(T), capacitances, built-in potentials.
  • §5.6 velocity-saturated Vdsat — replaces Vdsat = Vgt with the physical Esat·L·(Vgt+2vt) / (Abulk·Esat·L + Vgt + 2vt).
  • §3.2 subthreshold — non-zero Ids below Vth via NFACTOR/VOFF, so §6.1 Iii does not collapse to zero at low Vg1.
  • §9 noisethermal_noise_psd() and flicker_noise_psd() (1/f), for stochastic Iii injection.
  • §13 layout stresslayout_scale(p) applies SA/SB stress and L/W scaling to mobility, VSAT, VTH0.
  • PolynomialBSIM4Params{param: {c0, vg1, vg2, vg1_sq, vg2_sq, vg1_vg2}} wrapper Sebastian's polynomial fits drop into directly.
  • Fitters: fit_junction_breakdown, fit_temperature_scaling, fit_polynomial_vg — all with GPU-accelerated batch mode available.

Legacy Chynoweth / BVpar path (v0.x) is unchanged and remains the default for DeviceParams.

New in v0.11 — BSIM4-native 2T floating-body model

The firing mechanism can now be driven directly from BSIM4 impact ionization (§6.1, ALPHA0 / BETA0) and body-bias Vth(Vbs) (§2.2, K1 / K2), with no breakdown-voltage (BVpar) control parameter. Drop in measured I-V curves, extract ALPHA0 / BETA0, and the 2T spiking dynamics follow. See the BSIM4-Native 2T Model section below.

Installation

pip install nsram              # CPU only (numpy + scipy)
pip install nsram[gpu]         # GPU acceleration (PyTorch CUDA/ROCm/MPS)
pip install nsram[all]         # Everything (GPU + plotting)

Quickstart

from nsram import NSRAMReservoir, rc_benchmark

# Create 128-neuron reservoir with heterogeneous short-term plasticity
res = NSRAMReservoir(N=128, stp='heterogeneous')

# Run reservoir computing benchmarks
results = rc_benchmark(res)
# XOR-1: 90.3%, MC: 2.29, NARMA-10: 0.52, Wave-4: 92.5%

Key Results

Benchmark NS-RAM (N=2000) ESN (tanh) Izhikevich PLIF
XOR-1 97.0% 50.5% 50.2% 50.5%
Waveform-4 97.6% 69.8% 34.2% 42.6%
NARMA-10 0.358 0.000 0.000 0.000
Memory Capacity 3.38 4.13 0.02 1.35
Kernel Rank 230 12 213 3
MNIST (5K neurons) 96.75%

What is NS-RAM?

NS-RAM (Neuro-Synaptic Random Access Memory) is a standard CMOS floating-body transistor that exhibits both neuron-like spiking and synapse-like plasticity from device physics alone — no special materials or processes required.

Key device physics simulated:

  • Impact ionization avalanche (Chynoweth model): I_aval = I0 × exp((Vcb - BVpar) / Vt)
  • Breakdown voltage control: BVpar = 3.5 - 1.5 × Vg1 (gate-tunable, from Pazos SPICE)
  • Temperature dependence: BVpar(T) = BVpar × (1 - 21.3μ × ΔT)
  • SRH charge trapping: dQ/dt = k_cap(Vg2) × (1-Q) × rate - k_em × Q
  • VG2-controlled mode switching (neuron ↔ synapse)
  • BSIM4-native mode (v0.11+): impact ionization Iii ∝ (Vds−Vdseff)·exp(−BETA0/(Vds−Vdseff))·Ids (§6.1) and Vth(Vbs) = VTH0 + K1·(√(Φs−Vbs) − √Φs) − K2·Vbs (§2.2), with no BVpar control parameter

Library Overview (v0.11.0)

16 modules, 4.4K+ lines, 100+ public exports.

Core Simulation

Module Description
nsram.physics Full device physics — SPICE-matched avalanche, SRH trapping, body-charge ODE
nsram.neuron Single-cell ODE simulation (scipy), IV curves, parameter extraction
nsram.network GPU-accelerated NS-RAM spiking network (10K+ neurons)
nsram.reservoir High-level reservoir computing API
nsram.vision Batch GPU image classifier — 96.75% MNIST at 5K neurons

Alternative Neuron Models

Model Class Description
Izhikevich IzhikevichNetwork 20+ firing patterns (RS, IB, CH, FS, LTS, TC, RZ, mixed)
Parametric LIF PLIFNetwork Learnable time constants (Wu et al. 2021)
Hodgkin-Huxley HHNetwork 4-variable biophysical gold standard
from nsram import IzhikevichNetwork, PLIFNetwork, HHNetwork

iz = IzhikevichNetwork(N=1000, preset='mixed')
result = iz.run(signal)  # → dict with 'states', 'spikes'

Benchmarks

Benchmark Function Reference
Temporal XOR xor_accuracy() Delay-τ nonlinear memory
Memory Capacity memory_capacity() Jaeger 2001
NARMA-N narma_prediction() Atiya & Parlos 2000
Waveform Classification waveform_classification() N-class temporal
Mackey-Glass mackey_glass() Chaotic time series prediction
Kernel Rank kernel_rank() Nonlinear transformation capacity
Generalization Rank generalization_rank() Generalization vs memorization
Nonlinear Memory nonlinear_memory_capacity() Memory × nonlinearity tradeoff
from nsram import mackey_glass, kernel_rank, nonlinear_memory_capacity

mg_r2 = mackey_glass(states, washout=500, tau=17)
kr = kernel_rank(states, washout=500)
nmc = nonlinear_memory_capacity(states, inputs, washout=500)

Spike Encoding & Decoding

Encoder Function Description
Rate (Poisson) rate_encode() Firing probability ∝ input value
Latency latency_encode() Time-to-first-spike
Delta delta_encode() DVS-style change detection
Population population_encode() Gaussian receptive fields
Phase phase_encode() Phase-of-firing coding
from nsram import rate_encode, latency_encode, population_encode

spikes = rate_encode(image, n_steps=100, gain=1.0)
ttfs = latency_encode(features, n_steps=50, tau=5.0)
pop = population_encode(signal, n_neurons=20)

Analysis & Visualization

Tool Function Description
Firing rate firing_rate() Per-neuron, sliding window
ISI statistics isi_statistics() Mean, CV, burst ratio
Fano factor fano_factor() Spike count variability
Correlation correlation_matrix() Pairwise spike correlation
Synchrony synchrony_index() Population synchrony measure
Entropy spike_entropy() Shannon entropy of spike trains
Transfer entropy transfer_entropy() Directed information flow
Avalanche analysis avalanche_analysis() Power-law criticality test
Effective dimension effective_dimension() State space dimensionality
Lyapunov exponent lyapunov_estimate() Chaos detection
Raster plot raster_plot() Publication-quality spike raster
ISI histogram isi_histogram() ISI distribution visualization
from nsram import raster_plot, avalanche_analysis, effective_dimension

raster_plot(spikes, title='NS-RAM Network', save_path='raster.png')
aval = avalanche_analysis(spikes)
print(f"Critical: {aval['is_critical']}, α = {aval['size_exponent']:.2f}")
ed = effective_dimension(states)

Learning Rules

Hardware-realistic (tapeout-compatible):

Rule Class Reference
STDP STDP Bi & Poo 1998
Reward-STDP RewardSTDP Three-factor rule, eligibility traces
Voltage-STDP VoltageSTDP Clopath et al. 2010, uses body potential
Homeostatic HomeostaticPlasticity Intrinsic plasticity via charge trapping
Forward-Forward ForwardForward Hinton 2022, goodness = spike rate²
Equilibrium Propagation EquilibriumPropagation Scellier & Bengio 2017
e-prop Eprop Bellec et al. 2020, eligibility propagation

Export & Integration

from nsram import to_brian2, to_nestml, to_spice_subcircuit

brian2_eqs = to_brian2()           # Brian2 NeuronGroup equations
nestml_model = to_nestml()         # NESTML model for NEST HPC
spice_subckt = to_spice_subcircuit()  # SPICE .subckt for any simulator

SPICE Bridge

from nsram import NSRAMCell, simulate_iv_curve

cell = NSRAMCell()
cell.generate_netlist('nsram_1t.spice', Vg1=0.3)
iv_data = simulate_iv_curve(Vg1=0.3)  # Runs ngspice

Novel Finding: Charge Trapping = Tsodyks-Markram STP

This library implements the analytical mapping between NS-RAM charge trapping and the Tsodyks-Markram short-term plasticity model:

NS-RAM physics TM-STP neuroscience
Q (trapped charge) 1 − x (depleted resources)
k_cap(VG2) U (utilization)
1/k_em τ_rec (recovery time)
ΔVth = −αQ PSP amplitude modulation

VG2 voltage controls the STP type: low VG2 → depression, high VG2 → facilitation.

BSIM4-Native 2T Model (v0.11+)

An alternative path that drops the Zenodo avalanche-diode subcircuit and builds the floating-body dynamics directly on BSIM4.3.0 equations: impact ionization (§6.1), Vth(Vbs) body effect (§2.2), optional GIDL/GISL (§6.2), and source/drain-body junction diodes (§10.1). The body charge balance

Cb · dVB/dt = Iii(Vds, Vgs, Vbs) + IGIDL − Ibs(Vbs) − Ibd(Vbd) − VB/Rb

is integrated externally — BSIM4 has no native floating-body mode (that's BSIMSOI), so TwoTransistorCell wraps the BSIM4 current sources with a Cb / Rb integrator and Vg2→Rb mode switch.

from nsram import (
    BSIM4Params, BSIM4_PRESETS,
    TwoTransistorCell, impact_ionization_bsim4,
    fit_bsim4_impact,
)

# 1. Simulate a 2T cell — no BVpar, firing emerges from Iii + Vth(Vbs)
cell = TwoTransistorCell(bsim=BSIM4_PRESETS["ns_ram_180nm"])
res = cell.simulate(Vg1=0.9, Vg2=0.2, Vds=3.8, t_end=20e-6, dt=1e-8)
print(f"spikes: {len(res['spikes'])}, peak Iii: {res['Iii'].max():.2e} A")

# 2. Extract ALPHA0 / BETA0 from a measured I-V sweep
fit = fit_bsim4_impact(Vds_array, Isub_array, Vgs=1.0, Vbs=0.0)
# → fit['params'] is a BSIM4Params ready to drop into TwoTransistorCell

Presets: ns_ram_180nm (default), ns_ram_180nm_hot, generic_65nm. Override any BSIM4 parameter in BSIM4Params(ALPHA0=..., BETA0=..., K1=..., ...).

BSIM4 parameters (selected — full set in nsram.bsim4.BSIM4Params)

Parameter Default BSIM4 § Role
ALPHA0 6e-6 §6.1 / A.5 first Iii coefficient (A·m/V)
ALPHA1 0 §6.1 / A.5 length-scaling Iii coefficient
BETA0 22 §6.1 / A.5 Chynoweth exponential coefficient (V)
VTH0 0.432 §2.2 / A.3 long-channel Vth at Vbs=0
K1 0.55 §2.2 / A.3 first-order body coefficient (V^½)
K2 0.03 §2.2 / A.3 second-order body coefficient
AGIDL 1e-10 §6.2 / A.6 GIDL pre-exponential (mho)
BGIDL 2.3e9 §6.2 / A.6 GIDL exponential (V/m)
JSS/JSD 1e-4 §10.1 / A.12 body-diode reverse sat current density (A/m²)
NJS/NJD 1.0 §10.1 / A.12 body-diode ideality factor
Cb 1 pF external floating-body capacitance
Rb 1 MΩ external bulk leakage resistance (Vg2-modulated in TwoTransistorCell)

Round-trip fit of synthetic Iii data recovers ALPHA0/BETA0 to <1% (R² ≈ 0.998). Measured I-V CSVs drop straight into fit_bsim4_impact(Vds, Isub, Vgs).

Junction breakdown, temperature, polynomial (v0.12)

from nsram import (
    BSIM4Params,
    junction_breakdown_current, fit_junction_breakdown,
    temperature_scale, fit_temperature_scaling,
    PolynomialBSIM4Params, fit_polynomial_vg,
    layout_scale,
)

# §10.1 junction breakdown — Zener-like, often closer to NS-RAM than §6.1
p = BSIM4Params(dioMod=2, BVD=5.0, XJBVD=15.0)
Ibd = junction_breakdown_current(Vbd_array, p, side="drain",
                                  include_breakdown=True)
r = fit_junction_breakdown(Vbd_measured, Ibd_measured, side="drain")
# → r["BV"], r["XJBV"], r["NJ"], r["params"]

# §12 temperature — single call T-scales VTH0, μ, VSAT, Js, CJ, PB
p340 = temperature_scale(p, T=340.0)

# Joint (ALPHA0, BETA0, KT1, UTE) fit across a T-sweep
rT = fit_temperature_scaling(Vds_list, Iii_list, T_list,
                              Vgs=0.9, base=BSIM4Params())

# Polynomial(Vg1, Vg2) parameterisation — Sebastian's flow
wrapper = PolynomialBSIM4Params(
    base=BSIM4Params(),
    coeffs={"ALPHA0": {"c0": 6e-6, "vg1": 3e-6, "vg2": -2e-6,
                       "vg1_vg2": 1.5e-6}},
)
p_at = wrapper.evaluate(Vg1=0.9, Vg2=0.4)   # returns a BSIM4Params

# Fit polynomial coefficients from a bias grid
rp = fit_polynomial_vg(Vds_list, Iii_list, Vg1_list, Vg2_list,
                        param_name="ALPHA0",
                        poly_terms=("c0", "vg1", "vg2", "vg1_vg2"))

# §13 layout stress — SA/SB with KU0, KVTH0 coefficients
p_stressed = layout_scale(
    BSIM4Params(SA=0.5e-6, SB=0.5e-6, KU0=-5e-6, KVTH0=1e-8))

GPU-batch fitting

Per-curve scipy is fast (~2 ms/curve) but scales linearly. For wafer-scale Monte Carlo or (Vg1 × Vg2 × T × seed) grids use the batch GPU fitter — ~0.7 s for 4000 curves, crossover ~400 curves vs scipy. Example GPU batch-fit skeleton in scripts/z2b_bsim4_gpu_scaling.py.

Device Parameters

Default parameters from Pazos et al. SPICE model (Zenodo: 13843362):

Parameter Value Source
BVpar₀ 3.5 V BJTparams.txt
dBVpar/dVg1 -1.5 V/V BJTparams.txt
Tbv1 -21.3 μ/K Davalanche.txt
Is 1×10⁻¹⁶ A BJTparams.txt
Bf 50 BJTparams.txt
Vth₀ (NMOS) 0.432 V PTM130bulk_lite.txt
Energy/spike 21 fJ Nature 640
Cell area (1T) 8 μm² Nature 640
Cell area (2T) 17 μm² Nature 640

Backends

Backend Devices Detection
NumPy CPU (any) Always available
PyTorch CUDA NVIDIA GPUs torch.cuda.is_available()
PyTorch ROCm AMD GPUs (gfx1100, gfx1151, ...) torch.cuda.is_available() via HIP
PyTorch MPS Apple Silicon torch.backends.mps.is_available()

Examples

See examples/ for runnable scripts:

Script Description
quickstart.py Minimal hello-world
bsim4_2t_floating_body.py BSIM4-native 2T cell — Iii sweep, neuron/synapse spiking, ALPHA0/BETA0 fit
architecture_comparison.py 5 neuron models × 10 benchmarks × 3 scales
mnist_scaling.py MNIST accuracy vs neuron count (96.75% at 8K)
brain_arena.py 90K-neuron cortical brain foraging in 2D arena
brain_plays_pong.py 50K-neuron brain playing Pong
cortical_breakout.py 200K cortical brain on Breakout
learning_benchmark.py STDP, R-STDP, V-STDP comparison
onchip_mnist.py Forward-Forward vs EP vs e-prop on MNIST
large_scale_test.py 8 publication-quality plots
hero_figure.py Single hero image for publication

Citation

If you use this library, please cite:

@article{pazos2025nsram,
  title={Synaptic and neural behaviours in a standard silicon transistor},
  author={Pazos, Sebastian and others},
  journal={Nature},
  volume={640},
  pages={69--76},
  year={2025}
}

License

Apache 2.0 — Enimble Solutions AB

GitHub: github.com/Heigke/NSRAM | PyPI: pypi.org/project/nsram

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nsram-0.12.0.tar.gz (96.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nsram-0.12.0-py3-none-any.whl (94.9 kB view details)

Uploaded Python 3

File details

Details for the file nsram-0.12.0.tar.gz.

File metadata

  • Download URL: nsram-0.12.0.tar.gz
  • Upload date:
  • Size: 96.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for nsram-0.12.0.tar.gz
Algorithm Hash digest
SHA256 661b8aeb40db6ab31306a2bfece7b2db53b72f1dad3f96d5d5fbae6c2bed983c
MD5 c805e38a13b044c5bb8863c914056f52
BLAKE2b-256 bfe0a72b5d76e202e53faf280529d6fe766003be1e06ccad38d5914579813247

See more details on using hashes here.

File details

Details for the file nsram-0.12.0-py3-none-any.whl.

File metadata

  • Download URL: nsram-0.12.0-py3-none-any.whl
  • Upload date:
  • Size: 94.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for nsram-0.12.0-py3-none-any.whl
Algorithm Hash digest
SHA256 012c6949477576356dda6e34c5522a7644f6a64e644de202673b1eb37d391f8c
MD5 cacb5d9db9560a24c624cae3158b7b2d
BLAKE2b-256 463fd3ea184a833a299f77129c8f9d250f302b31939aa19734689e416002285c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page