sc_neurocore_engine/neurons/hardware/
spinnaker_lif.rs1#[derive(Clone, Debug)]
11pub struct SpiNNakerLIFNeuron {
12 pub v: f64,
13 pub v_rest: f64,
14 pub v_reset: f64,
15 pub v_threshold: f64,
16 pub tau_m: f64,
17 pub i_offset: f64,
18 pub tau_refrac: f64,
19 pub refrac_count: f64,
20 pub dt: f64,
21}
22
23impl SpiNNakerLIFNeuron {
24 pub fn new() -> Self {
25 Self {
26 v: -70.0,
27 v_rest: -70.0,
28 v_reset: -70.0,
29 v_threshold: -50.0,
30 tau_m: 20.0,
31 i_offset: 0.0,
32 tau_refrac: 2.0,
33 refrac_count: 0.0,
34 dt: 1.0,
35 }
36 }
37 pub fn step(&mut self, current: f64) -> i32 {
38 if self.refrac_count > 0.0 {
39 self.refrac_count -= self.dt;
40 return 0;
41 }
42 self.v += (-(self.v - self.v_rest) + current + self.i_offset) / self.tau_m * self.dt;
43 if self.v >= self.v_threshold {
44 self.v = self.v_reset;
45 self.refrac_count = self.tau_refrac;
46 1
47 } else {
48 0
49 }
50 }
51 pub fn reset(&mut self) {
52 self.v = self.v_rest;
53 self.refrac_count = 0.0;
54 }
55}
56impl Default for SpiNNakerLIFNeuron {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn spinnaker_fires() {
68 let mut n = SpiNNakerLIFNeuron::new();
69 let t: i32 = (0..200).map(|_| n.step(30.0)).sum();
70 assert!(t > 0);
71 }
72 #[test]
73 fn spinnaker_silent() {
74 let mut n = SpiNNakerLIFNeuron::new();
75 let t: i32 = (0..200).map(|_| n.step(0.0)).sum();
76 assert_eq!(t, 0);
77 }
78 #[test]
79 fn spinnaker_reset() {
80 let mut n = SpiNNakerLIFNeuron::new();
81 for _ in 0..50 {
82 n.step(30.0);
83 }
84 n.reset();
85 assert!((n.v - n.v_rest).abs() < 1e-10);
86 }
87 #[test]
88 fn spinnaker_bounded() {
89 let mut n = SpiNNakerLIFNeuron::new();
90 for _ in 0..1000 {
91 n.step(1e4);
92 }
93 assert!(n.v.is_finite());
94 }
95 #[test]
96 fn spinnaker_nan_no_panic() {
97 SpiNNakerLIFNeuron::new().step(f64::NAN);
98 }
99}