use crate::neuron::mask;
#[derive(Clone, Copy, Debug)]
pub struct StdpParams {
pub a_plus: i16,
pub a_minus: i16,
pub decay: i16,
pub w_min: i16,
pub w_max: i16,
}
#[derive(Clone, Debug)]
pub struct StdpSynapse {
pub weight: i16,
pub trace_pre: i16,
pub trace_post: i16,
pub data_width: u32,
pub fraction: u32,
}
impl StdpSynapse {
pub fn new(initial_weight: i16, data_width: u32, fraction: u32) -> Self {
Self {
weight: initial_weight,
trace_pre: 0,
trace_post: 0,
data_width,
fraction,
}
}
pub fn step(&mut self, pre_spike: bool, post_spike: bool, params: &StdpParams) {
self.trace_pre = mask(
(self.trace_pre as i32 * params.decay as i32) >> self.fraction,
self.data_width,
);
self.trace_post = mask(
(self.trace_post as i32 * params.decay as i32) >> self.fraction,
self.data_width,
);
if pre_spike {
self.trace_pre = mask(
self.trace_pre as i32 + params.a_plus as i32,
self.data_width,
);
}
if post_spike {
self.trace_post = mask(
self.trace_post as i32 + params.a_minus as i32,
self.data_width,
);
}
if post_spike {
let dw = (self.trace_pre as i32 * params.a_plus as i32) >> self.fraction;
let mut new_w = self.weight as i32 + dw;
if new_w > params.w_max as i32 {
new_w = params.w_max as i32;
}
self.weight = mask(new_w, self.data_width);
}
if pre_spike {
let dw = (self.trace_post as i32 * params.a_minus as i32) >> self.fraction;
let mut new_w = self.weight as i32 + dw; if new_w < params.w_min as i32 {
new_w = params.w_min as i32;
}
self.weight = mask(new_w, self.data_width);
}
}
}