Skip to content

Commit c7c022c

Browse files
committed
Add HMB as an example of an optional api
1 parent 0844fd3 commit c7c022c

File tree

5 files changed

+135
-12
lines changed

5 files changed

+135
-12
lines changed

ni-fpga-sys/src/lib.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,33 @@ pub type Offset = u32;
4646
pub type Session = u32;
4747
pub type Status = i32;
4848

49-
use std::{ffi::c_char, fmt};
49+
use std::{
50+
ffi::{c_char, c_void},
51+
fmt,
52+
};
5053

5154
use dlopen::{
5255
utils::platform_file_name,
53-
wrapper::{Container, WrapperApi},
56+
wrapper::{Container, WrapperApi, WrapperMultiApi},
5457
};
5558

56-
use dlopen_derive::WrapperApi;
59+
use dlopen_derive::{WrapperApi, WrapperMultiApi};
5760

5861
pub type NiFpgaApiContainer = Container<NiFpgaApi>;
5962

6063
#[derive(WrapperApi)]
61-
pub struct NiFpgaApi {
64+
pub struct NiFpgaHmbApi {
65+
NiFpgaDll_OpenHmb: extern "C" fn(
66+
session: Session,
67+
memory_name: *const c_char,
68+
memory_size: *mut usize,
69+
virual_address: *mut *mut c_void,
70+
) -> Status,
71+
NiFpgaDll_CloseHmb: extern "C" fn(session: Session, memory_name: *const c_char) -> Status,
72+
}
73+
74+
#[derive(WrapperApi)]
75+
pub struct NiFpgaBaseApi {
6276
NiFpgaDll_Open: extern "C" fn(
6377
bitfile: *const c_char,
6478
signature: *const c_char,
@@ -169,6 +183,12 @@ pub struct NiFpgaApi {
169183
) -> Status,
170184
}
171185

186+
#[derive(WrapperMultiApi)]
187+
pub struct NiFpgaApi {
188+
pub base: NiFpgaBaseApi,
189+
pub hmb: Option<NiFpgaHmbApi>,
190+
}
191+
172192
impl NiFpgaApi {
173193
pub fn load() -> Result<NiFpgaApiContainer, DlOpenError> {
174194
match unsafe { Container::load(platform_file_name("NiFpga")) } {

ni-fpga/src/hmb.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use std::{
2+
ffi::{c_void, CString},
3+
mem::size_of,
4+
ptr,
5+
};
6+
7+
use ni_fpga_sys::{NiFpgaHmbApi, Session};
8+
9+
pub struct Hmb<'a> {
10+
api: &'a NiFpgaHmbApi,
11+
session: Session,
12+
memory_name: CString,
13+
memory_size: usize,
14+
virtual_address: *mut c_void,
15+
}
16+
17+
impl<'a> Hmb<'a> {
18+
pub fn new(
19+
api: &'a NiFpgaHmbApi,
20+
session: Session,
21+
memory_name: CString,
22+
memory_size: usize,
23+
virtual_address: *mut c_void,
24+
) -> Hmb<'a> {
25+
Self {
26+
api,
27+
session,
28+
memory_name,
29+
memory_size,
30+
virtual_address,
31+
}
32+
}
33+
34+
pub fn read<T>(&self, offset: usize) -> T {
35+
unsafe {
36+
assert!(size_of::<T>() + offset <= self.memory_size);
37+
let base: *const u8 = self.virtual_address as *const u8;
38+
let address = base.add(offset);
39+
let typed_address = address as *const T;
40+
ptr::read_volatile(typed_address)
41+
}
42+
}
43+
44+
pub fn write<T>(&mut self, offset: usize, value: T) {
45+
unsafe {
46+
assert!(size_of::<T>() + offset <= self.memory_size);
47+
let base: *mut u8 = self.virtual_address as *mut u8;
48+
let address = base.add(offset);
49+
let typed_address = address as *mut T;
50+
ptr::write_volatile(typed_address, value);
51+
}
52+
}
53+
}
54+
55+
impl<'a> Drop for Hmb<'a> {
56+
fn drop(&mut self) {
57+
// TODO figure out what to do here with the return value
58+
self.api
59+
.NiFpgaDll_CloseHmb(self.session, self.memory_name.as_ptr());
60+
}
61+
}

ni-fpga/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extern crate ni_fpga_sys as ffi;
66
mod datatype;
77
mod errors;
88
pub mod fxp;
9+
pub mod hmb;
910
mod nifpga;
1011
mod session;
1112
mod status;

ni-fpga/src/nifpga.rs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
use std::ffi::CString;
1+
use std::{
2+
ffi::{c_void, CString},
3+
ptr,
4+
};
25

36
use ni_fpga_sys::{NiFpgaApi, NiFpgaApiContainer, Offset, Session};
47

5-
use crate::Error;
8+
use crate::{hmb::Hmb, Error, Status};
69

710
trait StatusHelper {
811
fn to_result(self) -> Result<(), Error>;
@@ -27,12 +30,14 @@ macro_rules! type_wrapper {
2730
$readarr_fun_name:ident, $readarr_ffi_name:ident, $writearr_fun_name:ident, $writearr_ffi_name:ident) => {
2831
pub fn $read_fun_name(&self, indicator: Offset, value: &mut $type) -> Result<(), Error> {
2932
self.api
33+
.base
3034
.$read_ffi_name(self.session, indicator, value as *mut $type)
3135
.to_result()
3236
}
3337

34-
pub fn $write_fun_name(&self, indicator: Offset, value: $type) -> Result<(), Error> {
38+
pub fn $write_fun_name(&mut self, indicator: Offset, value: $type) -> Result<(), Error> {
3539
self.api
40+
.base
3641
.$write_ffi_name(self.session, indicator, value)
3742
.to_result()
3843
}
@@ -43,12 +48,18 @@ macro_rules! type_wrapper {
4348
value: &mut [$type],
4449
) -> Result<(), Error> {
4550
self.api
51+
.base
4652
.$readarr_ffi_name(self.session, indicator, value.as_mut_ptr(), value.len())
4753
.to_result()
4854
}
4955

50-
pub fn $writearr_fun_name(&self, indicator: Offset, value: &[$type]) -> Result<(), Error> {
56+
pub fn $writearr_fun_name(
57+
&mut self,
58+
indicator: Offset,
59+
value: &[$type],
60+
) -> Result<(), Error> {
5161
self.api
62+
.base
5263
.$writearr_ffi_name(self.session, indicator, value.as_ptr(), value.len())
5364
.to_result()
5465
}
@@ -156,6 +167,34 @@ impl NiFpga {
156167
NiFpgaDll_WriteArrayI64
157168
);
158169

170+
pub fn open_hmb(&self, memory_name: &CString) -> Result<Hmb, Error> {
171+
match &self.api.hmb {
172+
Some(hmb) => {
173+
let mut memory_size: usize = 0;
174+
let mut virtual_address: *mut c_void = ptr::null_mut();
175+
match hmb
176+
.NiFpgaDll_OpenHmb(
177+
self.session,
178+
memory_name.as_ptr(),
179+
&mut memory_size,
180+
&mut virtual_address,
181+
)
182+
.to_result()
183+
{
184+
Ok(_) => Ok(Hmb::new(
185+
hmb,
186+
self.session,
187+
memory_name.clone(),
188+
memory_size,
189+
virtual_address,
190+
)),
191+
Err(err) => Err(err),
192+
}
193+
}
194+
None => Err(Error::FPGA(Status::ResourceNotInitialized)),
195+
}
196+
}
197+
159198
pub fn open(
160199
bitfile: &CString,
161200
signature: &CString,
@@ -167,14 +206,15 @@ impl NiFpga {
167206
Err(err) => return Err(Error::DlOpen(err)),
168207
};
169208

170-
let mut session: u32 = 0;
209+
let mut session: Session = 0;
171210
match api
211+
.base
172212
.NiFpgaDll_Open(
173213
bitfile.as_ptr(),
174214
signature.as_ptr(),
175215
resource.as_ptr(),
176216
attribute,
177-
&mut session as *mut Session,
217+
&mut session,
178218
)
179219
.to_result()
180220
{
@@ -185,6 +225,7 @@ impl NiFpga {
185225

186226
pub fn close(self, attribute: u32) -> Result<(), Error> {
187227
self.api
228+
.base
188229
.NiFpgaDll_Close(self.session, attribute)
189230
.to_result()
190231
}
@@ -194,6 +235,6 @@ impl Drop for NiFpga {
194235
fn drop(&mut self) {
195236
// TODO figure out what to do here with attribute
196237
// and the return value
197-
self.api.NiFpgaDll_Close(self.session, 0);
238+
self.api.base.NiFpgaDll_Close(self.session, 0);
198239
}
199240
}

ni-fpga/src/session.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl Session {
3232
Err(err) => Err(err),
3333
}
3434
}
35-
pub fn write<T: Datatype>(&self, offset: Offset, data: &T) -> Result<(), Error>
35+
pub fn write<T: Datatype>(&mut self, offset: Offset, data: &T) -> Result<(), Error>
3636
where
3737
[u8; (T::SIZE_IN_BITS - 1) / 8 + 1]: Sized,
3838
{

0 commit comments

Comments
 (0)