Skip to content

Instantly share code, notes, and snippets.

@JinShil
Last active December 18, 2016 14:12
Show Gist options
  • Save JinShil/9acef6ecb6601fb1b925f23ba11092ca to your computer and use it in GitHub Desktop.
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.
#![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