-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
use calyx_ir::Context; | ||
use std::{ | ||
any, cell::RefCell, collections::HashMap, env, path::PathBuf, rc::Rc, | ||
}; | ||
|
||
/// A non-combinational calyx component. | ||
pub trait CalyxFFIComponent: any::Any { | ||
/// The path to the component source file. Must be a constant expression. | ||
fn path(&self) -> &'static str; | ||
|
||
/// The in-source name of this component. Must be a constant expression. | ||
fn name(&self) -> &'static str; | ||
|
||
/// Internal initialization routine. Do not call! | ||
fn init(&mut self, context: &Context); | ||
|
||
/// Resets this component. | ||
fn reset(&mut self); | ||
|
||
/// Whether this component's backend supports ticking. | ||
fn can_tick(&self) -> bool; | ||
|
||
/// Advances this component by one clock cycle. May not always be available, so check [`has_tick`]([CalyxFFIComponent::has_tick]). | ||
fn tick(&mut self); | ||
|
||
/// Calls this component, blocking until it is done executing. | ||
fn go(&mut self); | ||
} | ||
|
||
pub type CalyxFFIComponentRef = Rc<RefCell<dyn CalyxFFIComponent>>; | ||
|
||
fn box_calyx_ffi_component<T: CalyxFFIComponent>( | ||
comp: T, | ||
) -> CalyxFFIComponentRef { | ||
Rc::new(RefCell::new(comp)) | ||
} | ||
|
||
#[derive(Default)] | ||
pub struct CalyxFFI { | ||
contexts: HashMap<&'static str, Context>, | ||
} | ||
|
||
impl CalyxFFI { | ||
pub fn new() -> Self { | ||
Self::default() | ||
} | ||
|
||
/// Constructs a new calyx component of the given type. | ||
/// | ||
/// The `path` implementation for `CalyxFFIComponent` must be a constant | ||
/// expression and should derived via the `calyx_ffi` procedural macro. | ||
pub fn new_comp<T: CalyxFFIComponent + Default>( | ||
&mut self, | ||
) -> CalyxFFIComponentRef { | ||
let mut comp = T::default(); | ||
let path = comp.path(); | ||
let context = self.contexts.entry(path).or_insert_with_key(|path| { | ||
// there has to be a better way to find lib | ||
let home_dir = env::var("HOME").expect("user home not set"); | ||
let mut lib_path = PathBuf::from(home_dir); | ||
lib_path.push(".calyx"); | ||
let ws = calyx_frontend::Workspace::construct( | ||
&Some(path.into()), | ||
&lib_path, | ||
) | ||
.expect("couldn't parse calyx"); | ||
calyx_ir::from_ast::ast_to_ir(ws) | ||
.expect("couldn't construct calyx ir") | ||
}); | ||
comp.init(context); | ||
box_calyx_ffi_component(comp) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,4 @@ | ||
use calyx_ir::Context; | ||
use std::{ | ||
any, cell::RefCell, collections::HashMap, env, path::PathBuf, rc::Rc, | ||
}; | ||
|
||
pub mod backend; | ||
pub mod interface; | ||
pub mod prelude; | ||
|
||
/// A non-combinational calyx component. | ||
pub trait CalyxFFIComponent: any::Any { | ||
/// The path to the component source file. Must be a constant expression. | ||
fn path(&self) -> &'static str; | ||
|
||
/// The in-source name of this component. Must be a constant expression. | ||
fn name(&self) -> &'static str; | ||
|
||
/// Internal initialization routine. Do not call! | ||
fn init(&mut self, context: &Context); | ||
|
||
/// Resets this component. | ||
fn reset(&mut self); | ||
|
||
/// Whether this component's backend supports ticking. | ||
fn can_tick(&self) -> bool; | ||
|
||
/// Advances this component by one clock cycle. May not always be available, so check [`has_tick`]([CalyxFFIComponent::has_tick]). | ||
fn tick(&mut self); | ||
|
||
/// Calls this component, blocking until it is done executing. | ||
fn go(&mut self); | ||
} | ||
|
||
pub type CalyxFFIComponentRef = Rc<RefCell<dyn CalyxFFIComponent>>; | ||
|
||
fn box_calyx_ffi_component<T: CalyxFFIComponent>( | ||
comp: T, | ||
) -> CalyxFFIComponentRef { | ||
Rc::new(RefCell::new(comp)) | ||
} | ||
|
||
#[derive(Default)] | ||
pub struct CalyxFFI { | ||
contexts: HashMap<&'static str, Context>, | ||
} | ||
|
||
impl CalyxFFI { | ||
pub fn new() -> Self { | ||
Self::default() | ||
} | ||
|
||
/// Constructs a new calyx component of the given type. | ||
/// | ||
/// The `path` implementation for `CalyxFFIComponent` must be a constant | ||
/// expression and should derived via the `calyx_ffi` procedural macro. | ||
pub fn new_comp<T: CalyxFFIComponent + Default>( | ||
&mut self, | ||
) -> CalyxFFIComponentRef { | ||
let mut comp = T::default(); | ||
let path = comp.path(); | ||
let context = self.contexts.entry(path).or_insert_with_key(|path| { | ||
// there has to be a better way to find lib | ||
let home_dir = env::var("HOME").expect("user home not set"); | ||
let mut lib_path = PathBuf::from(home_dir); | ||
lib_path.push(".calyx"); | ||
let ws = calyx_frontend::Workspace::construct( | ||
&Some(path.into()), | ||
&lib_path, | ||
) | ||
.expect("couldn't parse calyx"); | ||
calyx_ir::from_ast::ast_to_ir(ws) | ||
.expect("couldn't construct calyx ir") | ||
}); | ||
comp.init(context); | ||
box_calyx_ffi_component(comp) | ||
} | ||
} | ||
|
||
pub type Value<const N: u64> = interp::BitVecValue; | ||
|
||
pub fn value_from_u64<const N: u64>(value: u64) -> Value<N> { | ||
Value::from_u64(value, N as u32) | ||
} | ||
pub mod value; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
use std::{error, fmt}; | ||
|
||
pub use interp::WidthInt; | ||
Check failure on line 3 in tools/calyx-ffi/src/value.rs GitHub Actions / Check Formatting
|
||
|
||
#[derive(Debug)] | ||
pub enum ValueConversionError { | ||
WidthTooLarge(interp::WidthInt), | ||
Check failure on line 7 in tools/calyx-ffi/src/value.rs GitHub Actions / Check Formatting
|
||
} | ||
|
||
impl fmt::Display for ValueConversionError { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
match self { | ||
ValueConversionError::WidthTooLarge(width) => { | ||
write!( | ||
f, | ||
"Failed to convert bitvector of width `{}` into `u64`", | ||
width | ||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl error::Error for ValueConversionError {} | ||
|
||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)] | ||
pub struct Value<const N: interp::WidthInt> { | ||
Check failure on line 27 in tools/calyx-ffi/src/value.rs GitHub Actions / Check Formatting
|
||
pub inner: interp::BitVecValue, | ||
} | ||
|
||
impl<const N: interp::WidthInt> From<u64> for Value<N> { | ||
Check failure on line 31 in tools/calyx-ffi/src/value.rs GitHub Actions / Check Formatting
|
||
fn from(value: u64) -> Self { | ||
Self { | ||
inner: interp::BitVecValue::from_u64(value, N), | ||
} | ||
} | ||
} | ||
|
||
impl<const N: interp::WidthInt> TryInto<u64> for &Value<N> { | ||
Check failure on line 39 in tools/calyx-ffi/src/value.rs GitHub Actions / Check Formatting
|
||
type Error = ValueConversionError; | ||
|
||
fn try_into(self) -> Result<u64, Self::Error> { | ||
use interp::BitVecOps; | ||
self.inner | ||
.to_u64() | ||
.ok_or(Self::Error::WidthTooLarge(self.inner.width())) | ||
} | ||
} | ||
|
||
impl<const N: interp::WidthInt> interp::BitVecOps for Value<N> { | ||
Check failure on line 50 in tools/calyx-ffi/src/value.rs GitHub Actions / Check Formatting
|
||
fn width(&self) -> interp::WidthInt { | ||
Check failure on line 51 in tools/calyx-ffi/src/value.rs GitHub Actions / Check Formatting
|
||
N | ||
} | ||
|
||
fn words(&self) -> &[interp::Word] { | ||
Check failure on line 55 in tools/calyx-ffi/src/value.rs GitHub Actions / Check Formatting
|
||
self.inner.words() | ||
} | ||
} |