cyclone_v/
lib.rs

1//! Types for Cyclone V devices.
2//! Derived from https://www.intel.com/content/www/us/en/programmable/hps/cyclone-v/index_frames.html
3//!
4//! These types are used to access the FPGA Manager registers and other Cyclone V specific
5//! registers. The code should be platform-agnostic to allow for tests. This means no
6//! assembly or architecture specific libraries.
7#![cfg_attr(not(feature = "std"), no_std)]
8extern crate core;
9
10use crate::memory::MemoryMapper;
11
12mod macros;
13
14pub mod fpgamgrregs;
15pub mod l3regs;
16pub mod memory;
17pub mod rstmgr;
18pub mod sdr;
19pub mod sysmgr;
20
21macro_rules! declare_field {
22    ($(#[$field_attr:meta])* $field_name: ident, $const_name: ident, $ty: ty [pointer]) => {
23        paste::paste! {
24            $(#[$field_attr])*
25            pub unsafe fn [< $field_name _ptr >](&self) -> *const $ty {
26                self.memory.as_ptr::<u8>().add(offsets::$const_name) as *const $ty
27            }
28
29            $(#[$field_attr])*
30            pub unsafe fn [< $field_name _ptr_mut >](&mut self) -> *mut $ty {
31                self.memory.as_mut_ptr::<u8>().add(offsets::$const_name) as *mut $ty
32            }
33
34            $(#[$field_attr])*
35            pub fn $field_name(&self) -> &$ty {
36                unsafe {
37                    &*(self.memory.as_ptr::<u8>().add(offsets::$const_name) as *const $ty)
38                }
39            }
40
41            $(#[$field_attr])*
42            pub fn [< $field_name _mut >](&mut self) -> &$ty {
43                unsafe {
44                    &mut *(self.memory.as_mut_ptr::<u8>().add(offsets::$const_name) as *mut $ty)
45                }
46            }
47        }
48    };
49    ($(#[$field_attr:meta])* $field_name: ident, $const_name: ident, $ty: ty []) => {
50        paste::paste! {
51            $(#[$field_attr])*
52            pub fn $field_name(&self) -> &$ty {
53                unsafe {
54                    &*((self.memory.as_ptr::<u8>().add(offsets::$const_name)) as *const $ty)
55                }
56            }
57
58            $(#[$field_attr])*
59            pub fn [< $field_name _mut >](&mut self) -> &mut $ty {
60                unsafe {
61                    &mut *((self.memory.as_mut_ptr::<u8>().add(offsets::$const_name)) as *mut $ty)
62                }
63            }
64        }
65    };
66}
67
68// Create various constants for memory locations for Cyclone V.
69macro_rules! create_memory_locations {
70    ($(
71        $(#[$field_attr:meta])*
72        $field_name: ident ($const_name: ident): $ty: ty $([$($tags: ident)*])? => $start: literal .. $end: literal
73    );* $(;)?) => {
74        /// Absolute addresses for the SoC FPGA.
75        #[allow(dead_code)]
76        mod addresses {
77            $(
78                pub const $const_name: usize = $start;
79            )*
80        }
81
82        /// A list of offsets from the base address.
83        #[allow(dead_code)]
84        mod offsets {
85            $(
86                pub const $const_name: usize = (($start as usize) .saturating_sub(crate::addresses::BASE));
87            )*
88        }
89
90        /// A list of sizes for the memory locations.
91        #[allow(dead_code)]
92        mod sizes {
93            $(
94                pub const $const_name: usize = ($end - $start);
95            )*
96        }
97
98        /// Ranges of memory.
99        pub mod ranges {
100            $(
101                pub const $const_name: core::ops::Range<usize> = $start .. $end;
102            )*
103        }
104
105        #[derive(Debug, Copy, Clone)]
106        pub struct SocFpga<M: memory::MemoryMapper> {
107            pub memory: M,
108        }
109
110        impl<M: memory::MemoryMapper> SocFpga<M> {
111            pub fn new(memory: M) -> Self {
112                Self { memory }
113            }
114
115            $(
116                declare_field!($(#[$field_attr])* $field_name, $const_name, $ty [$($($tags)*)?]);
117            )*
118        }
119    };
120}
121
122create_memory_locations! {
123    /// The base location of the memory pointed to with the memory mapper.
124    base(BASE):                 u8 [pointer]                    => 0xFF000000 .. 0xFFFFFFFF;
125
126    /// The accessible host memory from and to the core.
127    host_memory(HOST_MEMORY):   u8 [pointer]                    => 0x20000000 .. 0x3FFFFFFF;
128
129    /// The FPGA Manager registers.
130    regs(FPGAMGRREGS):          fpgamgrregs::FpgaManagerRegs    => 0xFF706000 .. 0xFF706FFF;
131
132    /// The FPGA Manager data.
133    data(FPGAMGRDATA):          u8 [pointer]                    => 0xFFB90000 .. 0xFFB90003;
134
135    /// The SDRAM Controller.
136    sdr(SDR):                   sdr::SdramCtrl                  => 0xFFC20000 .. 0xFFC2FFFF;
137
138    /// The Reset Manager.
139    rstmgr(RSTMGR):             rstmgr::ResetManager            => 0xFFD05000 .. 0xFFD050FF;
140
141    /// Registers to control L3 interconnect settings.
142    l3regs(L3_REGS):            l3regs::L3Regs                  => 0xFF800000 .. 0xFF87FFFF;
143
144    /// System Manager Module
145    sysmgr(SYSMGR):             sysmgr::SystemManagerModule     => 0xFFD08000 .. 0xFFD08FFF;
146}
147
148#[cfg(feature = "std")]
149impl Default for SocFpga<memory::DevMemMemoryMapper> {
150    fn default() -> Self {
151        let memory = memory::DevMemMemoryMapper::create(addresses::BASE, sizes::BASE)
152            .expect("Could not create memory mapper");
153
154        Self::new(memory)
155    }
156}
157
158#[cfg(feature = "std")]
159impl SocFpga<memory::BufferMemoryMapper> {
160    pub fn create_for_test() -> Self {
161        let memory = memory::BufferMemoryMapper::new(sizes::BASE);
162
163        Self::new(memory)
164    }
165}