Last active
December 18, 2016 14:12
-
-
Save JinShil/9acef6ecb6601fb1b925f23ba11092ca to your computer and use it in GitHub Desktop.
Another step closer at what I'm looking for out of a BitField implementation.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(const_fn)] | |
#![feature(associated_consts)] | |
#![allow(dead_code)] | |
#![allow(non_camel_case_types)] | |
use std::marker::PhantomData; | |
use std::ptr; | |
pub trait ConstantValue<T> { | |
const VALUE: T; | |
} | |
pub struct b0 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b0 { const VALUE: u8 = 0u8; } | |
pub struct b1 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b1 { const VALUE: u8 = 1u8; } | |
pub struct b2 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b2 { const VALUE: u8 = 2u8; } | |
pub struct b3 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b3 { const VALUE: u8 = 3u8; } | |
pub struct b4 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b4 { const VALUE: u8 = 4u8; } | |
pub struct b5 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b5 { const VALUE: u8 = 5u8; } | |
pub struct b6 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b6 { const VALUE: u8 = 6u8; } | |
pub struct b7 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b7 { const VALUE: u8 = 7u8; } | |
pub struct b8 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b8 { const VALUE: u8 = 8u8; } | |
pub struct b9 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b9 { const VALUE: u8 = 9u8; } | |
pub struct b10 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b10 { const VALUE: u8 = 10u8; } | |
pub struct b11 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b11 { const VALUE: u8 = 11u8; } | |
pub struct b12 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b12 { const VALUE: u8 = 12u8; } | |
pub struct b13 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b13 { const VALUE: u8 = 13u8; } | |
pub struct b14 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b14 { const VALUE: u8 = 14u8; } | |
pub struct b15 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b15 { const VALUE: u8 = 15u8; } | |
pub struct b16 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b16 { const VALUE: u8 = 16u8; } | |
pub struct b17 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b17 { const VALUE: u8 = 17u8; } | |
pub struct b18 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b18 { const VALUE: u8 = 18u8; } | |
pub struct b19 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b19 { const VALUE: u8 = 19u8; } | |
pub struct b20 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b20 { const VALUE: u8 = 20u8; } | |
pub struct b21 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b21 { const VALUE: u8 = 21u8; } | |
pub struct b22 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b22 { const VALUE: u8 = 22u8; } | |
pub struct b23 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b23 { const VALUE: u8 = 23u8; } | |
pub struct b24 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b24 { const VALUE: u8 = 24u8; } | |
pub struct b25 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b25 { const VALUE: u8 = 25u8; } | |
pub struct b26 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b26 { const VALUE: u8 = 26u8; } | |
pub struct b27 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b27 { const VALUE: u8 = 27u8; } | |
pub struct b28 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b28 { const VALUE: u8 = 28u8; } | |
pub struct b29 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b29 { const VALUE: u8 = 29u8; } | |
pub struct b30 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b30 { const VALUE: u8 = 30u8; } | |
pub struct b31 { _ignore : PhantomData<u8> } | |
impl ConstantValue<u8> for b31 { const VALUE: u8 = 31u8; } | |
type Word = u32; | |
trait FromBits<T> { | |
fn from_bits(T) -> Self; | |
} | |
trait IntoBits<T>: Sized { | |
fn into_bits(self) -> T; | |
} | |
impl<T, U> IntoBits<U> for T where U: FromBits<T> { | |
#[inline(always)] | |
fn into_bits(self) -> U { | |
U::from_bits(self) | |
} | |
} | |
impl FromBits<Word> for u32 { | |
#[inline(always)] | |
fn from_bits(bits: Word) -> Self { | |
bits as u32 | |
} | |
} | |
impl FromBits<Word> for u8 { | |
#[inline(always)] | |
fn from_bits(bits: Word) -> Self { | |
bits as u8 | |
} | |
} | |
impl FromBits<u8> for Word { | |
#[inline(always)] | |
fn from_bits(bits: u8) -> Self { | |
bits as Word | |
} | |
} | |
//TODO: Need to add more implementations here for primitive types | |
// Bit-Banded Bit | |
//------------------------------------------------------------------- | |
pub struct BitBandedBit<R, B> { | |
_r : PhantomData<R>, | |
_b : PhantomData<B> | |
} | |
impl<R: Register, B: ConstantValue<u8>> BitBandedBit<R, B> { | |
const fn address(&self) -> u32 { | |
R::ADDRESS | |
} | |
const fn bit_index(&self) -> u8 { | |
B::VALUE | |
} | |
} | |
// BitFields | |
//------------------------------------------------------------------- | |
trait BitField<R: Register, B0: ConstantValue<u8>, B1: ConstantValue<u8>> { | |
fn address(&self) -> *mut Word { | |
//R::ADDRESS | |
self as *const Self as *mut Self as *mut Word | |
} | |
fn ms_bit_index(&self) -> u8 { | |
// Not yet available in Rust. See https://github.com/rust-lang/rfcs/issues/322 | |
// if B0::VALUE > B1::VALUE { B0::VALUE } else { B1::VALUE } | |
// Use branchless bit hack instead | |
// http://guru.multimedia.cx/category/optimization/ | |
// TODO: This has a bug. Must use wrapping_sub(), but it's not available for | |
// const functions | |
B0::VALUE-((B0::VALUE-B1::VALUE)&((B0::VALUE-B1::VALUE)>>7)) | |
} | |
fn ls_bit_index(&self) -> u8 { | |
// Not yet available in Rust. See https://github.com/rust-lang/rfcs/issues/322 | |
// if B0::VALUE < B1::VALUE { B0::VALUE } else { B1::VALUE } | |
// Use branchless bit hack instead | |
// http://guru.multimedia.cx/category/optimization/ | |
B1::VALUE+((B0::VALUE-B1::VALUE)&((B0::VALUE-B1::VALUE)>>7)) | |
} | |
fn width(&self) -> u8 { | |
self.ms_bit_index() - self.ls_bit_index() + 1 | |
} | |
fn word_mask(&self) -> Word { | |
(((1 << self.width()) - 1) << self.ls_bit_index()) | |
} | |
} | |
trait Read<R: Register, B0: ConstantValue<u8>, B1: ConstantValue<u8>, T : FromBits<Word>> : BitField<R, B0, B1> { | |
#[inline(always)] | |
fn read(&self) -> T { | |
let mut bits = R::read_bits(self as *const Self as *const Word); | |
bits &= self.word_mask(); | |
bits >>= self.ls_bit_index(); | |
T::from_bits(bits) | |
} | |
} | |
trait Write<R: Register, B0: ConstantValue<u8>, B1: ConstantValue<u8>, T: IntoBits<Word>> : BitField<R, B0, B1> { | |
#[inline(always)] | |
fn write(&mut self, value: T) { | |
let value_bits: Word = value.into_bits(); | |
let mut bits = R::read_bits(self as *const Self as *const Word); | |
bits &= !self.word_mask(); | |
bits |= value_bits << self.ls_bit_index(); | |
R::write_bits(self as *mut Self as *mut Word, bits); | |
} | |
} | |
#[allow(non_camel_case_types)] | |
pub struct BitField_RW<R, B0, B1, T> { | |
_r : PhantomData<R>, | |
_b0 : PhantomData<B0>, | |
_b1 : PhantomData<B1>, | |
_t : PhantomData<T> | |
} | |
impl< | |
R : Register | |
, B0: ConstantValue<u8> | |
, B1: ConstantValue<u8> | |
, T | |
>BitField<R, B0, B1> for BitField_RW<R, B0, B1, T> { } | |
impl< | |
R : Register | |
, B0: ConstantValue<u8> | |
, B1: ConstantValue<u8> | |
, T : FromBits<Word> | |
> Read<R, B0, B1, T> for BitField_RW<R, B0, B1, T> { } | |
impl< | |
R : Register | |
, B0: ConstantValue<u8> | |
, B1: ConstantValue<u8> | |
, T : IntoBits<Word> | |
> Write<R, B0, B1, T> for BitField_RW<R, B0, B1, T> { } | |
#[allow(non_camel_case_types)] | |
pub struct BitField_R<R, B0, B1, T> { | |
_r : PhantomData<R>, | |
_b0 : PhantomData<B0>, | |
_b1 : PhantomData<B1>, | |
_t : PhantomData<T> | |
} | |
impl< | |
R : Register | |
, B0: ConstantValue<u8> | |
, B1: ConstantValue<u8> | |
, T | |
>BitField<R, B0, B1> for BitField_R<R, B0, B1, T> { } | |
impl< | |
R : Register | |
, B0: ConstantValue<u8> | |
, B1: ConstantValue<u8> | |
, T : FromBits<Word> | |
> Read<R, B0, B1, T> for BitField_R<R, B0, B1, T> { } | |
// Register | |
//------------------------------------------------------------------- | |
pub trait Register { | |
const ADDRESS: u32; | |
fn read_bits(address: *const Word) -> Word { | |
unsafe { | |
ptr::read_volatile(address) | |
// read_volatile(Self::ADDRESS as *const Word) | |
} | |
} | |
fn write_bits(address: *mut Word, bits: Word) { | |
unsafe { | |
ptr::write_volatile(address, bits) | |
// write_volatile(Self::ADDRESS as *const Word as *mut Word, bits) | |
} | |
} | |
} | |
pub struct SR { | |
bf1 : BitBandedBit<SR, b1>, | |
bf2 : BitField_RW<SR, b1, b0, u8>, | |
bf3 : BitField_R<SR, b7, b2, u8> | |
} | |
impl Register for SR { | |
const ADDRESS : u32 = 0x11; | |
} | |
fn main() { | |
println!("Start"); | |
let mut r0 = SR { | |
bf1 : BitBandedBit::<SR, b1> { | |
_r : PhantomData, | |
_b : PhantomData | |
}, | |
bf2 : BitField_RW::<SR, b1, b0, u8> { | |
_r : PhantomData, | |
_b0 : PhantomData, | |
_b1 : PhantomData, | |
_t : PhantomData | |
}, | |
bf3 : BitField_R::<SR, b7, b2, u8> { | |
_r : PhantomData, | |
_b0 : PhantomData, | |
_b1 : PhantomData, | |
_t : PhantomData | |
} | |
}; | |
r0.bf2.write(3u8); | |
println!("{} {} {} {}", | |
r0.bf1.address(), r0.bf1.bit_index(), r0.bf2.width(), r0.bf3.read()); | |
println!("End"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment