cameleon_genapi/
int_reg.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use super::{
6    elem_type::{Endianness, IntegerRepresentation, Sign},
7    interface::{IInteger, INode, IRegister, ISelector, IncrementMode},
8    node_base::{NodeAttributeBase, NodeBase},
9    register_base::RegisterBase,
10    store::{CacheStore, NodeId, NodeStore, ValueStore},
11    utils, Device, GenApiError, GenApiResult, ValueCtxt,
12};
13
14#[derive(Debug, Clone)]
15pub struct IntRegNode {
16    pub(crate) attr_base: NodeAttributeBase,
17    pub(crate) register_base: RegisterBase,
18
19    pub(crate) sign: Sign,
20    pub(crate) endianness: Endianness,
21    pub(crate) unit: Option<String>,
22    pub(crate) representation: IntegerRepresentation,
23    pub(crate) p_selected: Vec<NodeId>,
24}
25
26impl IntRegNode {
27    #[must_use]
28    pub fn register_base(&self) -> &RegisterBase {
29        &self.register_base
30    }
31
32    #[must_use]
33    pub fn sign(&self) -> Sign {
34        self.sign
35    }
36
37    #[must_use]
38    pub fn endianness(&self) -> Endianness {
39        self.endianness
40    }
41
42    #[must_use]
43    pub fn unit_elem(&self) -> Option<&str> {
44        self.unit.as_deref()
45    }
46
47    #[must_use]
48    pub fn representation_elem(&self) -> IntegerRepresentation {
49        self.representation
50    }
51
52    #[must_use]
53    pub fn p_selected(&self) -> &[NodeId] {
54        &self.p_selected
55    }
56}
57
58impl INode for IntRegNode {
59    fn node_base(&self) -> NodeBase {
60        let elem_base = &self.register_base.elem_base;
61        NodeBase::new(&self.attr_base, elem_base)
62    }
63
64    fn streamable(&self) -> bool {
65        self.register_base().streamable()
66    }
67}
68
69impl IInteger for IntRegNode {
70    #[tracing::instrument(skip(self, device, store, cx),
71                          level = "trace",
72                          fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
73    fn value<T: ValueStore, U: CacheStore>(
74        &self,
75        device: &mut impl Device,
76        store: &impl NodeStore,
77        cx: &mut ValueCtxt<T, U>,
78    ) -> GenApiResult<i64> {
79        let nid = self.node_base().id();
80        let reg = self.register_base();
81        reg.with_cache_or_read(nid, device, store, cx, |data| {
82            utils::int_from_slice(data, self.endianness, self.sign)
83        })
84    }
85
86    #[tracing::instrument(skip(self, device, store, cx),
87                          level = "trace",
88                          fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
89    fn set_value<T: ValueStore, U: CacheStore>(
90        &self,
91        value: i64,
92        device: &mut impl Device,
93        store: &impl NodeStore,
94        cx: &mut ValueCtxt<T, U>,
95    ) -> GenApiResult<()> {
96        let nid = self.node_base().id();
97        cx.invalidate_cache_by(nid);
98
99        let reg = self.register_base();
100        let len = reg.length(device, store, cx)?;
101        let mut buf = vec![0; len as usize];
102        utils::bytes_from_int(value, &mut buf, self.endianness, self.sign)?;
103        reg.write_and_cache(nid, &buf, device, store, cx)?;
104        Ok(())
105    }
106
107    fn min<T: ValueStore, U: CacheStore>(
108        &self,
109        _: &mut impl Device,
110        _: &impl NodeStore,
111        _: &mut ValueCtxt<T, U>,
112    ) -> GenApiResult<i64> {
113        match self.sign {
114            Sign::Signed => Ok(i64::MIN),
115            Sign::Unsigned => Ok(0),
116        }
117    }
118
119    fn max<T: ValueStore, U: CacheStore>(
120        &self,
121        _: &mut impl Device,
122        _: &impl NodeStore,
123        _: &mut ValueCtxt<T, U>,
124    ) -> GenApiResult<i64> {
125        Ok(i64::MAX)
126    }
127
128    fn inc_mode(&self, _: &impl NodeStore) -> Option<IncrementMode> {
129        None
130    }
131
132    fn inc<T: ValueStore, U: CacheStore>(
133        &self,
134        _: &mut impl Device,
135        _: &impl NodeStore,
136        _: &mut ValueCtxt<T, U>,
137    ) -> GenApiResult<Option<i64>> {
138        Ok(None)
139    }
140
141    fn valid_value_set(&self, _: &impl NodeStore) -> &[i64] {
142        &[]
143    }
144
145    fn representation(&self, _: &impl NodeStore) -> IntegerRepresentation {
146        self.representation_elem()
147    }
148
149    fn unit(&self, _: &impl NodeStore) -> Option<&str> {
150        self.unit_elem()
151    }
152
153    #[tracing::instrument(skip(self, store),
154                          level = "trace",
155                          fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
156    fn set_min<T: ValueStore, U: CacheStore>(
157        &self,
158        _: i64,
159        _: &mut impl Device,
160        store: &impl NodeStore,
161        _: &mut ValueCtxt<T, U>,
162    ) -> GenApiResult<()> {
163        Err(GenApiError::not_writable())
164    }
165
166    #[tracing::instrument(skip(self, store),
167                          level = "trace",
168                          fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
169    fn set_max<T: ValueStore, U: CacheStore>(
170        &self,
171        _: i64,
172        _: &mut impl Device,
173        store: &impl NodeStore,
174        _: &mut ValueCtxt<T, U>,
175    ) -> GenApiResult<()> {
176        Err(GenApiError::not_writable())
177    }
178
179    fn is_readable<T: ValueStore, U: CacheStore>(
180        &self,
181        device: &mut impl Device,
182        store: &impl NodeStore,
183        cx: &mut ValueCtxt<T, U>,
184    ) -> GenApiResult<bool> {
185        self.register_base().is_readable(device, store, cx)
186    }
187
188    fn is_writable<T: ValueStore, U: CacheStore>(
189        &self,
190        device: &mut impl Device,
191        store: &impl NodeStore,
192        cx: &mut ValueCtxt<T, U>,
193    ) -> GenApiResult<bool> {
194        self.register_base().is_writable(device, store, cx)
195    }
196}
197
198impl IRegister for IntRegNode {
199    fn read<T: ValueStore, U: CacheStore>(
200        &self,
201        buf: &mut [u8],
202        device: &mut impl Device,
203        store: &impl NodeStore,
204        cx: &mut ValueCtxt<T, U>,
205    ) -> GenApiResult<()> {
206        let address = self.address(device, store, cx)?;
207        let length = self.length(device, store, cx)?;
208        self.register_base().read_and_cache(
209            self.node_base().id(),
210            address,
211            length,
212            buf,
213            device,
214            store,
215            cx,
216        )
217    }
218
219    fn write<T: ValueStore, U: CacheStore>(
220        &self,
221        buf: &[u8],
222        device: &mut impl Device,
223        store: &impl NodeStore,
224        cx: &mut ValueCtxt<T, U>,
225    ) -> GenApiResult<()> {
226        self.register_base()
227            .write_and_cache(self.node_base().id(), buf, device, store, cx)
228    }
229
230    fn address<T: ValueStore, U: CacheStore>(
231        &self,
232        device: &mut impl Device,
233        store: &impl NodeStore,
234        cx: &mut ValueCtxt<T, U>,
235    ) -> GenApiResult<i64> {
236        self.register_base().address(device, store, cx)
237    }
238
239    fn length<T: ValueStore, U: CacheStore>(
240        &self,
241        device: &mut impl Device,
242        store: &impl NodeStore,
243        cx: &mut ValueCtxt<T, U>,
244    ) -> GenApiResult<i64> {
245        self.register_base().length(device, store, cx)
246    }
247}
248
249impl ISelector for IntRegNode {
250    fn selecting_nodes(&self, _: &impl NodeStore) -> GenApiResult<&[NodeId]> {
251        Ok(self.p_selected())
252    }
253}