cameleon_genapi/
register_base.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::{AccessMode, AddressKind, CachingMode, ImmOrPNode},
7    interface::IPort,
8    ivalue::IValue,
9    node_base::NodeElementBase,
10    store::{CacheStore, NodeId, NodeStore, ValueStore},
11    Device, GenApiError, GenApiResult, ValueCtxt,
12};
13
14#[derive(Debug, Clone)]
15pub struct RegisterBase {
16    pub(crate) elem_base: NodeElementBase,
17
18    pub(crate) streamable: bool,
19    pub(crate) address_kinds: Vec<AddressKind>,
20    pub(crate) length: ImmOrPNode<i64>,
21    pub(crate) access_mode: AccessMode,
22    pub(crate) p_port: NodeId,
23    pub(crate) cacheable: CachingMode,
24    pub(crate) polling_time: Option<u64>,
25    pub(crate) p_invalidators: Vec<NodeId>,
26}
27
28impl RegisterBase {
29    #[must_use]
30    pub fn streamable(&self) -> bool {
31        self.streamable
32    }
33
34    #[must_use]
35    pub fn address_kinds(&self) -> &[AddressKind] {
36        &self.address_kinds
37    }
38
39    #[must_use]
40    pub fn length_elem(&self) -> &ImmOrPNode<i64> {
41        &self.length
42    }
43
44    #[must_use]
45    pub fn access_mode(&self) -> AccessMode {
46        self.access_mode
47    }
48
49    #[must_use]
50    pub fn p_port(&self) -> NodeId {
51        self.p_port
52    }
53
54    #[must_use]
55    pub fn cacheable(&self) -> CachingMode {
56        self.cacheable
57    }
58
59    #[must_use]
60    pub fn polling_time(&self) -> Option<u64> {
61        self.polling_time
62    }
63
64    #[must_use]
65    pub fn p_invalidators(&self) -> &[NodeId] {
66        &self.p_invalidators
67    }
68
69    pub(super) fn with_cache_or_read<T: ValueStore, U: CacheStore, R>(
70        &self,
71        nid: NodeId,
72        device: &mut impl Device,
73        store: &impl NodeStore,
74        cx: &mut ValueCtxt<T, U>,
75        f: impl FnOnce(&[u8]) -> GenApiResult<R>,
76    ) -> GenApiResult<R> {
77        let length = self.length(device, store, cx)?;
78        let address = self.address(device, store, cx)?;
79        if let Some(cache) = cx.get_cache(nid, address, length) {
80            f(cache)
81        } else {
82            let mut buf = vec![0; length as usize];
83            self.read_and_cache(nid, address, length, &mut buf, device, store, cx)?;
84            f(&buf)
85        }
86    }
87
88    #[allow(clippy::too_many_arguments)]
89    pub(super) fn read_and_cache<T: ValueStore, U: CacheStore>(
90        &self,
91        nid: NodeId,
92        address: i64,
93        length: i64,
94        buf: &mut [u8],
95        device: &mut impl Device,
96        store: &impl NodeStore,
97        cx: &mut ValueCtxt<T, U>,
98    ) -> GenApiResult<()> {
99        if buf.len() != length as usize {
100            return Err(GenApiError::invalid_buffer(
101                "given buffer length doesn't same as the register length".into(),
102            ));
103        }
104        self.p_port
105            .expect_iport_kind(store)?
106            .read(address, buf, device, store, cx)?;
107        if self.cacheable != CachingMode::NoCache {
108            cx.cache_data(nid, address, length, buf);
109        }
110
111        Ok(())
112    }
113
114    pub(super) fn write_and_cache<T: ValueStore, U: CacheStore>(
115        &self,
116        nid: NodeId,
117        buf: &[u8],
118        device: &mut impl Device,
119        store: &impl NodeStore,
120        cx: &mut ValueCtxt<T, U>,
121    ) -> GenApiResult<()> {
122        let length = self.length(device, store, cx)?;
123
124        if buf.len() != length as usize {
125            return Err(GenApiError::invalid_buffer(
126                "given buffer length doesn't same as the register length".into(),
127            ));
128        }
129
130        let address = self.address(device, store, cx)?;
131        self.p_port
132            .expect_iport_kind(store)?
133            .write(address, buf, device, store, cx)?;
134
135        if self.cacheable == CachingMode::WriteThrough {
136            cx.cache_data(nid, address, length, buf);
137        }
138        Ok(())
139    }
140
141    pub(super) fn address<T: ValueStore, U: CacheStore>(
142        &self,
143        device: &mut impl Device,
144        store: &impl NodeStore,
145        cx: &mut ValueCtxt<T, U>,
146    ) -> GenApiResult<i64> {
147        let mut address = 0;
148        for addr_kind in self.address_kinds() {
149            address += addr_kind.value(device, store, cx)?;
150        }
151        Ok(address)
152    }
153
154    pub(super) fn length<T: ValueStore, U: CacheStore>(
155        &self,
156        device: &mut impl Device,
157        store: &impl NodeStore,
158        cx: &mut ValueCtxt<T, U>,
159    ) -> GenApiResult<i64> {
160        self.length_elem().value(device, store, cx)
161    }
162
163    pub(super) fn is_readable<T: ValueStore, U: CacheStore>(
164        &self,
165        device: &mut impl Device,
166        store: &impl NodeStore,
167        cx: &mut ValueCtxt<T, U>,
168    ) -> GenApiResult<bool> {
169        Ok(self.elem_base.is_readable(device, store, cx)?
170            && !matches!(self.access_mode(), AccessMode::WO))
171    }
172
173    pub(super) fn is_writable<T: ValueStore, U: CacheStore>(
174        &self,
175        device: &mut impl Device,
176        store: &impl NodeStore,
177        cx: &mut ValueCtxt<T, U>,
178    ) -> GenApiResult<bool> {
179        Ok(self.elem_base.is_writable(device, store, cx)?
180            && !matches!(self.access_mode(), AccessMode::RO))
181    }
182}