flp_framework/
address.rs

1//! # The `flp_framework::address` Module
2//!
3//! This module contains some of the basic primitive address
4//! types supported by Floorplan including void addresses,
5//! words, bytes, and so on. The implementations in this file
6//! look much like what gets generated for Floorplan-defined
7//! types, but are manually coded here to provide stronger
8//! control over how they get used.
9//!
10//! For information on acquiring the Floorplan compiler itself,
11//! go see the [GitHub project here][github-project].
12//!
13//! [github-project]: https://github.com/RedlineResearch/floorplan
14
15#![allow(non_snake_case)]
16#![allow(dead_code)]
17use std::cmp;
18use std::fmt;
19use std::mem::size_of as size_of;
20
21use super::*;
22
23/// A `VoidAddr`, much like a `void*` in C, is available for those
24/// in need of a quick-and-dirty way of representing the value of a
25/// pointer without actually being able to read from or write to that
26/// pointer.
27#[repr(C)]
28#[derive(Copy, Clone, Eq, Hash)]
29pub struct VoidAddr(usize);
30
31deriveAddrReqs!(VoidAddr);
32impl Address for VoidAddr {
33
34    /// Construct a void address:
35    ///
36    /// ```rust
37    /// # use flp_framework::*;
38    /// let va = VoidAddr::from_usize(0xdeadbeef);
39    /// ```
40    fn from_usize(val : usize) -> VoidAddr { VoidAddr(val) }
41
42    /// Deconstruct a void address:
43    ///
44    /// ```rust
45    /// # use flp_framework::*;
46    /// let va = VoidAddr::from_usize(0xdeadbeef);
47    /// assert!(va.as_usize() == 3735928559);
48    /// ```
49    fn as_usize(&self) -> usize { self.0 }
50
51    /// Trivially verify that this void address looks valid.
52    /// All values are valid:
53    ///
54    /// ```rust
55    /// # use flp_framework::*;
56    /// let va = VoidAddr::from_usize(0xdeadbeef);
57    /// assert!(va.verify());
58    /// ```
59    fn verify(self) -> bool { true }
60
61    /// Void addresses cannot be accessed.
62    #[inline(always)] fn load<T: Copy> (&self) -> T {
63        panic!("Can't load() a VoidAddr!")
64    }
65    
66    /// Void addresses cannot be accessed.
67    #[inline(always)] fn store<T> (&self, _value: T) {
68        panic!("Can't store() a VoidAddr!")
69    }
70    
71    /// Void addresses cannot be accessed.
72    #[inline(always)] fn memset(&self, _char: u8, _length: usize) {
73        panic!("Can't memset() a VoidAddr!")
74    }
75}
76
77impl VoidAddr {
78
79    /// A void address can be constructed from any other address type.
80    pub fn from_addr<A: Address>(ptr : A) -> Self {
81        VoidAddr(ptr.as_usize())
82    }
83
84}
85
86/// A generic address that points to a memory location containing an address.
87#[repr(C)]
88#[derive(Copy, Clone, Eq, Hash)]
89pub struct AddrAddr(usize);
90deriveAddr!(AddrAddr, 1 << size_of::<usize>());
91
92/// Determine whether or not the nth-lowest bit of a byte is set.
93#[inline(always)]
94pub fn test_nth_bit(value: u8, index: usize) -> bool {
95    value & (1 << index) != 0
96}
97
98/// Mask for just the nth-lowest bits of a byte.
99#[inline(always)]
100pub fn lower_bits(value: u8, len: usize) -> u8 {
101    value & ((1 << len) - 1)
102}
103
104/// A `Word` is a value representing data, useful for its ability to
105/// be addressed and subsequently accessed by a `WordAddr`. Suppose
106/// you have some word address in `wa` and you want to ensure that the lowest
107/// bit of that word is set:
108///
109/// ```rust
110/// # #![feature(rustc_private)]
111/// # use std::alloc::{alloc, Layout};
112/// # use flp_framework::*;
113/// # let wa_alloc = unsafe { alloc(Layout::new::<usize>()) };
114/// # let wa = WordAddr::from_ptr(wa_alloc);
115/// # wa.store(WordAddr::from_usize(0b1));
116/// let w : Word = wa.load();
117/// assert!(w.is_aligned_to(2) == false);
118/// ```
119#[repr(C)]
120#[derive(Copy, Clone, Eq, Hash)]
121pub struct Word(usize);
122deriveAddrReqs!(Word);
123
124/// Computes the number of consecutive lower-order bits that are
125/// set to zero in a `usize` value.
126fn trailing_zeros(x : usize) -> usize {
127    if x % 2 != 0 { 0 } else { trailing_zeros(x / 2) }
128}
129
130/// The number of bytes in a word of memory.
131pub const BYTES_IN_WORD : usize = size_of::<usize>();
132
133/// Log base 2 of the number of bytes in a word of memory.
134#[cfg(target_pointer_width = "32")]
135pub const LOG_BYTES_IN_WORD : usize = 2;
136
137/// Log base 2 of the number of bytes in a word of memory.
138#[cfg(target_pointer_width = "64")]
139pub const LOG_BYTES_IN_WORD : usize = 3;
140
141/// Only 32-bit and 64-bit architectures are currently supported by Floorplan.
142#[cfg(all(not(target_pointer_width = "64"), not(target_pointer_width = "32")))]
143pub const LOG_BYTES_IN_WORD : usize =
144    panic!("Unsupported word size.");
145
146/// A `WordAddr` is a value representing the address of a word of memory.
147#[repr(C)]
148#[derive(Copy, Clone, Eq, Hash)]
149pub struct WordAddr(usize);
150impl Address for Word {
151
152    /// Constructor for a word value from a raw `usize`.
153    ///
154    /// ```rust
155    /// # use flp_framework::*;
156    /// let w = Word::from_usize(0xff);
157    /// ```
158    fn from_usize(val : usize) -> Word { Word(val) }
159
160    /// Deconstructor for a word value into a raw `usize` value.
161    ///
162    /// ```rust
163    /// # use flp_framework::*;
164    /// let w = Word::from_usize(0xff);
165    /// assert!(w.as_usize() == 255);
166    /// ```
167    fn as_usize(&self) -> usize { self.0 }
168
169    /// All possible word values are valid:
170    ///
171    /// ```rust
172    /// # use flp_framework::*;
173    /// let w = Word::from_usize(0xff);
174    /// assert!(w.verify());
175    /// ```
176    fn verify(self) -> bool { true }
177
178    /// A word cannot be accessed.
179    #[inline(always)] fn load<T: Copy> (&self) -> T {
180        panic!("Can't load() a Word!")
181    }
182    
183    /// A word cannot be accessed.
184    #[inline(always)] fn store<T> (&self, _value: T) {
185        panic!("Can't store() a Word!")
186    }
187
188    /// Raw word values are not writeable.
189    fn memset(&self, _char: u8, _length: usize) {
190        panic!("Can't memset() a Word!")
191    }
192}
193
194deriveAddrReqs!(WordAddr);
195impl Address for WordAddr {
196
197    /// Constructor for a word address from a raw `usize`.
198    ///
199    /// ```rust
200    /// # use flp_framework::*;
201    /// let wa = WordAddr::from_usize(0xdeadbeef);
202    /// ```
203    fn from_usize(val : usize) -> WordAddr { WordAddr(val) }
204
205    /// Deconstructor for a word address into a raw `usize` value.
206    ///
207    /// ```rust
208    /// # use flp_framework::*;
209    /// let wa = WordAddr::from_usize(0xdeadbeef);
210    /// assert!(wa.as_usize() == 3735928559);
211    /// ```
212    fn as_usize(&self) -> usize { self.0 }
213
214    /// All possible word values are valid:
215    ///
216    /// ```rust
217    /// # use flp_framework::*;
218    /// let wa = WordAddr::from_usize(0xdeadbeef);
219    /// assert!(wa.verify());
220    /// ```
221    fn verify(self) -> bool { true }
222
223    /// A generic address to a raw word cannot be accessed.
224    #[inline(always)] fn load<T: Copy> (&self) -> T { unsafe {
225        *(self.as_usize() as *mut T)
226    }}
227    
228    /// A generic address to a raw word cannot be accessed.
229    #[inline(always)] fn store<T> (&self, value: T) { unsafe {
230        *(self.as_usize() as *mut T) = value;
231    }}
232    
233}
234
235/// A `Byte` is a value representing data, useful for its ability to
236/// be addressed and subsequently accessed by a `ByteAddr`. Suppose
237/// you have some byte address in `ba` and you want to ensure that the lowest
238/// bit of that word is not set:
239///
240/// ```rust
241/// # #![feature(rustc_private)]
242/// # use std::alloc::{alloc, Layout};
243/// # use flp_framework::*;
244/// # let ba_alloc = unsafe { alloc(Layout::new::<usize>()) };
245/// # let ba = ByteAddr::from_ptr(ba_alloc);
246/// # ba.store(ByteAddr::from_usize(0b0));
247/// let b : Byte = ba.load();
248/// assert!(b.is_aligned_to(2) == true);
249/// ```
250#[repr(C)]
251#[derive(Copy, Clone, Eq, Hash)]
252pub struct Byte(u8);
253deriveAddrReqs!(Byte);
254
255// TODO: both this impl and the one for `Word` need to be
256// changed to represent a `Value` or `Prim` trait to show
257// that the associated methods represent operations over primitive
258// values and not operations over an address type.
259impl Address for Byte {
260
261    /// Constructor for a byte value from a raw `usize`.
262    ///
263    /// ```rust
264    /// # use flp_framework::*;
265    /// let w = Byte::from_usize(0xff);
266    /// ```
267    fn from_usize(val : usize) -> Byte { Byte(val as u8) }
268
269    /// Deconstructor for a byte value into a raw `usize` value.
270    ///
271    /// ```rust
272    /// # use flp_framework::*;
273    /// let w = Byte::from_usize(0xff);
274    /// assert!(w.as_usize() == 255);
275    /// ```
276    fn as_usize(&self) -> usize { self.0 as usize }
277
278    /// All possible byte values are valid:
279    ///
280    /// ```rust
281    /// # use flp_framework::*;
282    /// let w = Byte::from_usize(0xff);
283    /// assert!(w.verify());
284    /// ```
285    fn verify(self) -> bool { true }
286
287    /// A byte cannot be accessed.
288    #[inline(always)] fn load<T: Copy> (&self) -> T {
289        panic!("Can't load() a Byte!")
290    }
291    
292    /// A byte cannot be accessed.
293    #[inline(always)] fn store<T> (&self, _value: T) {
294        panic!("Can't store() a Byte!")
295    }
296
297    /// Raw byte values are not writeable.
298    fn memset(&self, _char: u8, _length: usize) {
299        panic!("Can't memset() a Byte!")
300    }
301}
302
303/// A `ByteAddr` is a value representing the address of zero or more bytes of memory.
304#[repr(C)]
305#[derive(Copy, Clone, Eq, Hash)]
306pub struct ByteAddr(usize);
307
308deriveAddrReqs!(ByteAddr);
309impl Address for ByteAddr {
310
311    /// Constructor for a byte address from a raw `usize`.
312    ///
313    /// ```rust
314    /// # use flp_framework::*;
315    /// let ba = ByteAddr::from_usize(0xdeadbeef);
316    /// ```
317    fn from_usize(val : usize) -> ByteAddr { ByteAddr(val) }
318
319    /// Deconstructor for a byte address into a raw `usize` value.
320    ///
321    /// ```rust
322    /// # use flp_framework::*;
323    /// let ba = ByteAddr::from_usize(0xdeadbeef);
324    /// assert!(ba.as_usize() == 3735928559);
325    /// ```
326    fn as_usize(&self) -> usize { self.0 }
327
328    /// All byte addresses are valid:
329    ///
330    /// ```rust
331    /// # use flp_framework::*;
332    /// let ba = ByteAddr::from_usize(0xdeadbeef);
333    /// assert!(ba.verify());
334    /// ```
335    fn verify(self) -> bool { true }
336
337    /// A generic address to a raw byte cannot be accessed.
338    #[inline(always)] fn load<T: Copy> (&self) -> T { unsafe {
339        *(self.as_usize() as *mut T)
340    }}
341    
342    /// A generic address to a raw byte cannot be accessed.
343    #[inline(always)] fn store<T> (&self, value: T) { unsafe {
344        *(self.as_usize() as *mut T) = value;
345    }}
346}
347
348#[cfg(test)]
349mod tests {
350    use super::*;
351
352    pub const VAL : u8 = 0b000011_11;
353    #[test] pub fn v0() { assert_eq!(test_nth_bit(VAL, 0), true); }
354    #[test] pub fn v1() { assert_eq!(test_nth_bit(VAL, 1), true); }
355    #[test] pub fn v2() { assert_eq!(test_nth_bit(VAL, 2), true); }
356    #[test] pub fn v3() { assert_eq!(test_nth_bit(VAL, 3), true); }
357    #[test] pub fn v4() { assert_eq!(test_nth_bit(VAL, 4), false); }
358    #[test] pub fn v5() { assert_eq!(test_nth_bit(VAL, 5), false); }
359    #[test] pub fn v6() { assert_eq!(test_nth_bit(VAL, 6), false); }
360    #[test] pub fn v7() { assert_eq!(test_nth_bit(VAL, 7), false); }
361}
362