Skip to main content

gwr_models/registers/
register.rs

1// Copyright (c) 2023 Graphcore Ltd. All rights reserved.
2
3//! Control and Status Registers.
4
5use std::rc::Rc;
6
7use gwr_engine::traits::Resolver;
8
9/// Interface to a [`Register`]
10pub trait Register {
11    /// Write to a register and trigger `write` callbacks.
12    ///
13    /// **Note:** the underlying register value won't change until the
14    /// `resolver` [`resolve()`](gwr_engine::traits::Resolve)
15    /// is called.
16    fn write(&self, resolver: &impl Resolver, value: u64);
17
18    /// Set the value of the register without triggering `write` callbacks.
19    ///
20    /// **Note:** the underlying register value won't change until the
21    /// `resolver` [`resolve()`](gwr_engine::traits::Resolve)
22    /// is called.
23    fn set(&self, resolver: &impl Resolver, value: u64);
24
25    /// Read the current register value and trigger `read` callbacks.
26    fn read(&self) -> u64;
27
28    /// Return the current register value without triggering `read` callbacks.
29    fn value(&self) -> u64;
30
31    /// Perform a `synchronous` reset.
32    ///
33    /// **Note:** the underlying register value won't change until the
34    /// `resolver` [`resolve()`](gwr_engine::traits::Resolve)
35    /// is called.
36    fn reset_sync(&self, resolver: &impl Resolver);
37
38    /// Perform an `asynchronous` reset where the value is instantly changed.
39    fn reset_async(&self);
40}
41
42pub trait Written {
43    fn written(&self, old_value: u64, value_written: u64, new_value: u64);
44}
45
46pub trait Read {
47    fn read(&self, value_read: u64);
48}
49
50pub type WrittenCallback = Rc<dyn Written + 'static>;
51pub type ReadCallback = Rc<dyn Read + 'static>;
52
53#[macro_export]
54macro_rules! build_register_view {
55    (
56        $(#[$($reg_attrs:tt)*])*
57        $reg:ident, $state:path, $state_perms:path, $priority:ident ;
58        $(
59            $(#[$($field_attrs:tt)*])*
60            $field:ident : $perms:expr
61        ),+ $(,)*
62    ) => {
63    $crate::registers::paste! {
64        $(#[$($reg_attrs)*])*
65        #[doc=concat!("\n\nFor field details, see [`", stringify!($reg), "`](", stringify!($state), ").")]
66        #[doc=concat!("\n\nThis view has the following permissions for each field:\n")]
67        $(
68            #[doc=concat!("  - ", stringify!($field), ": [`", stringify!($perms), "`](crate::registers::Permission).")]
69        )+
70        pub struct [< $reg Reg >]  {
71            state: std::rc::Rc<$state>,
72            perms: $state_perms,
73            write_callbacks: Vec<$crate::registers::register::WrittenCallback>,
74            read_callbacks: Vec<$crate::registers::register::ReadCallback>,
75            priority: $crate::registers::state::UpdatePriority,
76        }
77
78        impl [< $reg Reg >] {
79            pub fn new(state: std::rc::Rc<$state>) -> Self {
80                let perms = $state_perms {
81                    $(
82                    $field: $crate::registers::Permission::$perms,
83                    )+
84                };
85                Self {
86                    state,
87                    perms,
88                    write_callbacks: Vec::new(),
89                    read_callbacks: Vec::new(),
90                    priority: $crate::registers::state::UpdatePriority::$priority,
91                }
92            }
93
94            /// Install a callback function to be called whenever a `write` completes
95            #[allow(dead_code)]
96            pub fn install_write_cb(&mut self, cb: $crate::registers::register::WrittenCallback) {
97                self.write_callbacks.push(cb);
98            }
99
100            /// Install a callback function to be called whenever a `read` completes
101            #[allow(dead_code)]
102            pub fn install_read_cb(&mut self, cb: $crate::registers::register::ReadCallback) {
103                self.read_callbacks.push(cb);
104            }
105        }
106
107        impl $crate::registers::register::Register for [< $reg Reg >] {
108            fn write(&self, resolver: &impl gwr_engine::traits::Resolver, value: u64) {
109                let old_value = self.state.value();
110                let new_value = self.state.write(self.priority, &self.perms, value);
111
112                for cb in &self.write_callbacks {
113                    cb.written(old_value, value, new_value);
114                }
115                resolver.add_resolve(self.state.clone());
116            }
117
118            fn set(&self, resolver: &impl gwr_engine::traits::Resolver, value: u64) {
119                self.state.set(self.priority, &self.perms, value);
120                resolver.add_resolve(self.state.clone());
121            }
122
123            fn read(&self) -> u64 {
124                let value = self.state.read(&self.perms);
125                for cb in &self.read_callbacks {
126                    cb.read(value);
127                }
128                value
129            }
130
131            fn value(&self) -> u64 {
132                let value = self.state.value();
133                value
134            }
135
136            fn reset_sync(&self, resolver: &impl gwr_engine::traits::Resolver) {
137                self.state.reset_sync();
138                resolver.add_resolve(self.state.clone());
139            }
140
141            fn reset_async(&self) {
142                self.state.reset_async();
143            }
144        }
145    }}
146}