#![cfg_attr(not(feature = "std"), no_std)]
extern crate core;
use crate::memory::MemoryMapper;
mod macros;
pub mod fpgamgrregs;
pub mod l3regs;
pub mod memory;
pub mod rstmgr;
pub mod sdr;
pub mod sysmgr;
macro_rules! declare_field {
($(#[$field_attr:meta])* $field_name: ident, $const_name: ident, $ty: ty [pointer]) => {
paste::paste! {
$(#[$field_attr])*
pub unsafe fn [< $field_name _ptr >](&self) -> *const $ty {
self.memory.as_ptr::<u8>().add(offsets::$const_name) as *const $ty
}
$(#[$field_attr])*
pub unsafe fn [< $field_name _ptr_mut >](&mut self) -> *mut $ty {
self.memory.as_mut_ptr::<u8>().add(offsets::$const_name) as *mut $ty
}
$(#[$field_attr])*
pub fn $field_name(&self) -> &$ty {
unsafe {
&*(self.memory.as_ptr::<u8>().add(offsets::$const_name) as *const $ty)
}
}
$(#[$field_attr])*
pub fn [< $field_name _mut >](&mut self) -> &$ty {
unsafe {
&mut *(self.memory.as_mut_ptr::<u8>().add(offsets::$const_name) as *mut $ty)
}
}
}
};
($(#[$field_attr:meta])* $field_name: ident, $const_name: ident, $ty: ty []) => {
paste::paste! {
$(#[$field_attr])*
pub fn $field_name(&self) -> &$ty {
unsafe {
&*((self.memory.as_ptr::<u8>().add(offsets::$const_name)) as *const $ty)
}
}
$(#[$field_attr])*
pub fn [< $field_name _mut >](&mut self) -> &mut $ty {
unsafe {
&mut *((self.memory.as_mut_ptr::<u8>().add(offsets::$const_name)) as *mut $ty)
}
}
}
};
}
macro_rules! create_memory_locations {
($(
$(#[$field_attr:meta])*
$field_name: ident ($const_name: ident): $ty: ty $([$($tags: ident)*])? => $start: literal .. $end: literal
);* $(;)?) => {
#[allow(dead_code)]
mod addresses {
$(
pub const $const_name: usize = $start;
)*
}
#[allow(dead_code)]
mod offsets {
$(
pub const $const_name: usize = (($start as usize) .saturating_sub(crate::addresses::BASE));
)*
}
#[allow(dead_code)]
mod sizes {
$(
pub const $const_name: usize = ($end - $start);
)*
}
pub mod ranges {
$(
pub const $const_name: core::ops::Range<usize> = $start .. $end;
)*
}
#[derive(Debug, Copy, Clone)]
pub struct SocFpga<M: memory::MemoryMapper> {
pub memory: M,
}
impl<M: memory::MemoryMapper> SocFpga<M> {
pub fn new(memory: M) -> Self {
Self { memory }
}
$(
declare_field!($(#[$field_attr])* $field_name, $const_name, $ty [$($($tags)*)?]);
)*
}
};
}
create_memory_locations! {
base(BASE): u8 [pointer] => 0xFF000000 .. 0xFFFFFFFF;
host_memory(HOST_MEMORY): u8 [pointer] => 0x20000000 .. 0x3FFFFFFF;
regs(FPGAMGRREGS): fpgamgrregs::FpgaManagerRegs => 0xFF706000 .. 0xFF706FFF;
data(FPGAMGRDATA): u8 [pointer] => 0xFFB90000 .. 0xFFB90003;
sdr(SDR): sdr::SdramCtrl => 0xFFC20000 .. 0xFFC2FFFF;
rstmgr(RSTMGR): rstmgr::ResetManager => 0xFFD05000 .. 0xFFD050FF;
l3regs(L3_REGS): l3regs::L3Regs => 0xFF800000 .. 0xFF87FFFF;
sysmgr(SYSMGR): sysmgr::SystemManagerModule => 0xFFD08000 .. 0xFFD08FFF;
}
#[cfg(feature = "std")]
impl Default for SocFpga<memory::DevMemMemoryMapper> {
fn default() -> Self {
let memory = memory::DevMemMemoryMapper::create(addresses::BASE, sizes::BASE)
.expect("Could not create memory mapper");
Self::new(memory)
}
}
#[cfg(feature = "std")]
impl SocFpga<memory::BufferMemoryMapper> {
pub fn create_for_test() -> Self {
let memory = memory::BufferMemoryMapper::new(sizes::BASE);
Self::new(memory)
}
}