Adds tools/neural_sim/, a NumPy-based reference implementation of the FPGA-Neural V2 numeric model (INT8 in/weight, 32-bit wraparound accumulation, ReLU+saturate out), derived directly from hardware/v2/rtl/neural_processor.v (not assumed) and reusing tools/validation/mac_oracle.py's own pre-existing, hand-verified two's-complement primitives rather than duplicating them. Provides: neuron/layer/network models, a logical memory model of the real V2 SDRAM map (weights/activations/results), deterministic test-vector generators (simple/signed/extremes/zero/random/D-Stress 256x128) with JSON golden-vector export, an FPGA-vs-Python bit-exact comparison utility, four example networks, a CLI (`python -m tools.neural_sim ...`), and a 96-test pytest suite (all passing) covering signed-arithmetic edge cases (including a direct 32-bit wraparound proof), scalar-vs-vectorized neuron cross-checks, layer/memory/vector/comparison tests. This is a golden functional reference (bit-exact numeric result), explicitly NOT a cycle-accurate FPGA simulator -- see tools/neural_sim/README.md for the full scope statement. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
31 lines
1.1 KiB
Python
31 lines
1.1 KiB
Python
import numpy as np
|
|
import pytest
|
|
|
|
from tools.neural_sim.neuron import neuron_scalar, neuron_vectorized
|
|
from tools.neural_sim.numerics import ACT_NONE, ACT_RELU
|
|
|
|
|
|
@pytest.mark.parametrize("n_tiles", [1, 2, 4, 16])
|
|
@pytest.mark.parametrize("activation", [ACT_RELU, ACT_NONE])
|
|
@pytest.mark.parametrize("seed", [0, 1, 2, 3, 4])
|
|
def test_scalar_and_vectorized_agree(n_tiles, activation, seed):
|
|
rng = np.random.default_rng(seed)
|
|
n = n_tiles * 8
|
|
inputs = rng.integers(-128, 128, size=n, dtype=np.int64).tolist()
|
|
weights = rng.integers(-128, 128, size=n, dtype=np.int64).tolist()
|
|
bias = int(rng.integers(-128, 128))
|
|
|
|
scalar = neuron_scalar(inputs, weights, bias=bias, activation=activation)
|
|
vectorized = neuron_vectorized(inputs, weights, bias=bias, activation=activation)
|
|
assert scalar == vectorized
|
|
|
|
|
|
def test_scalar_and_vectorized_agree_on_extremes():
|
|
inputs = [-128, 127] * 4
|
|
weights = [127, -128] * 4
|
|
assert neuron_scalar(inputs, weights) == neuron_vectorized(inputs, weights)
|
|
|
|
|
|
def test_scalar_and_vectorized_agree_on_zero():
|
|
assert neuron_scalar([0] * 8, [0] * 8) == neuron_vectorized([0] * 8, [0] * 8) == 0
|