osiris_process/
register.rs

1//! This module describes ways to identify chunks in registers bank and wraps an integral and a floating-point implementation.
2
3use std::ops::RangeInclusive;
4use std::hash::{Hash, Hasher};
5use std::fmt::{Debug, Display, Formatter};
6
7use osiris_data::data::identification::Identifier;
8
9/// A wide range.
10pub const REGISTERS_IN_BANK: usize = 65536;
11
12pub type RangeApplication<T> = fn(&[T]) -> T;
13
14pub trait RegisterBank<T>: where Self: Sized {
15
16    /// Create a new complete bank with register initialized at their default value.
17    fn new() -> Self;
18    
19    /// Sets a specific register in the bank.
20    fn set(&mut self, register: RegisterId, raw: T);
21    
22    /// Gets a specific register from the bank.
23    fn get(&self, register: RegisterId) -> T;
24    
25    /// Apply the specified [RangeApplication] in the bank on the specified [RegisterRange].
26    fn apply(&self, range: RegisterRange, function: RangeApplication<T>) -> T;
27
28    /// Return a slice from the specified range in the bank.
29    fn slice(&self, range: RegisterRange) -> &[T];
30
31    /// Copy the specified slice into the bank to the specified [RegisterId] and nexts.
32    ///
33    /// Do not overflow. Only the fitting elements are copied. 
34    fn copy(&mut self, to: RegisterId, slice: &[T]);
35}
36
37/// A type which always represents a valid register in a bank.
38#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
39pub struct RegisterId(u16);
40
41impl RegisterId {
42    /// Identify a register.
43    pub const fn new(raw: u16) -> Self { Self(raw) }
44    /// Returns the raw `u16` of this identifier.
45    pub const fn to_u16(&self) -> u16 { self.0 }
46}
47
48impl Hash for RegisterId {
49    fn hash<H: Hasher>(&self, state: &mut H) {
50        state.write_usize(self.to_usize());
51    }
52}
53
54impl Identifier for RegisterId {
55    fn to_usize(&self) -> usize { self.0 as usize }
56}
57
58/// Represents a range of registers in a bank.
59/// 
60/// A range is at least 1 register long (if `start == end`).
61#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
62pub struct RegisterRange {
63    /// The first register in the range.
64    pub start: RegisterId,
65    /// The last register in the range.
66    pub end: RegisterId,
67}
68
69impl RegisterRange {
70    /// Creates a range from a start and an end [RegisterId]s.
71    ///
72    /// May **panic** if `end < start`.
73    pub fn new(start: RegisterId, end: RegisterId) -> Self {
74        if end < start {
75            panic!("End of a range cannot be lower to its start.")
76        }
77        Self { start, end }
78    }
79
80    /// Creates a range from a raw `u32`.
81    pub fn from_u32(data: u32) -> Self {
82        Self {
83            start: RegisterId((data >> 16) as u16),
84            end: RegisterId(data as u16),
85        }
86    }
87
88    /// Returns a range usable to extract a slice notably.
89    pub fn to_usize_range(&self) -> RangeInclusive<usize> { self.start.to_usize()..=self.end.to_usize() }
90
91    /// Returns a raw `u32` representing the range.
92    pub fn to_u32(&self) -> u32 { (self.start.to_u16() as u32) << 16 | self.end.to_u16() as u32 }
93
94    /// Returns the number of registers included in the range.
95    pub fn count(&self) -> usize { self.end.to_usize() - self.start.to_usize() + 1 }
96}
97
98impl Display for RegisterRange {
99    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
100        write!(f, "[{:04x}:{:04x}]", self.start.to_u16(), self.end.to_u16())
101    }
102}
103
104#[cfg(feature = "base-integral")]
105pub mod integral;
106
107#[cfg(feature = "state")]
108pub mod state;
109
110#[cfg(feature = "base-floating")]
111pub mod floating_point;