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