Skip to main content

sc_neurocore_engine/neurons/hardware/
loihi2.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Commercial license available
3// © Concepts 1996–2026 Miroslav Šotek. All rights reserved.
4// © Code 2020–2026 Miroslav Šotek. All rights reserved.
5// ORCID: 0009-0009-3560-0851
6// Contact: www.anulum.li | protoscience@anulum.li
7// SC-NeuroCore — Loihi 2 Neuron Emulator
8
9/// Loihi 2 — Intel Loihi 2 three-state integer neuron.
10#[derive(Clone, Debug)]
11pub struct Loihi2Neuron {
12    pub s1: i32,
13    pub s2: i32,
14    pub s3: i32,
15    pub tau1: i32,
16    pub tau2: i32,
17    pub tau3: i32,
18    pub w12: i32,
19    pub w13: i32,
20    pub w23: i32,
21    pub s1_threshold: i32,
22    pub s1_reset: i32,
23    pub s3_incr: i32,
24}
25
26impl Loihi2Neuron {
27    pub fn new() -> Self {
28        Self {
29            s1: 0,
30            s2: 0,
31            s3: 0,
32            tau1: 10,
33            tau2: 5,
34            tau3: 50,
35            w12: 1,
36            w13: 0,
37            w23: 0,
38            s1_threshold: 1000,
39            s1_reset: 0,
40            s3_incr: 10,
41        }
42    }
43    pub fn step(&mut self, weighted_input: i32) -> i32 {
44        self.s3 -= self.s3 / self.tau3;
45        self.s2 = self.s2 - self.s2 / self.tau2 + weighted_input + self.w23 * self.s3;
46        self.s1 = self.s1 - self.s1 / self.tau1 + self.w12 * self.s2 + self.w13 * self.s3;
47        if self.s1 >= self.s1_threshold {
48            self.s1 = self.s1_reset;
49            self.s3 += self.s3_incr;
50            1
51        } else {
52            0
53        }
54    }
55    pub fn reset(&mut self) {
56        self.s1 = 0;
57        self.s2 = 0;
58        self.s3 = 0;
59    }
60}
61impl Default for Loihi2Neuron {
62    fn default() -> Self {
63        Self::new()
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn loihi2_fires() {
73        let mut n = Loihi2Neuron {
74            tau3: 8,
75            ..Loihi2Neuron::new()
76        };
77        let t: i32 = (0..500).map(|_| n.step(200)).sum();
78        assert!(t > 0);
79    }
80    #[test]
81    fn loihi2_silent() {
82        let mut n = Loihi2Neuron::new();
83        let t: i32 = (0..200).map(|_| n.step(0)).sum();
84        assert_eq!(t, 0);
85    }
86    #[test]
87    fn loihi2_reset() {
88        let mut n = Loihi2Neuron::new();
89        for _ in 0..50 {
90            n.step(200);
91        }
92        n.reset();
93        assert_eq!(n.s1, 0);
94    }
95    #[test]
96    fn loihi2_bounded() {
97        let mut n = Loihi2Neuron {
98            tau3: 8,
99            ..Loihi2Neuron::new()
100        };
101        for _ in 0..1000 {
102            n.step(10000);
103        }
104    }
105}