use crate::circuit::{
Runtime, Scope,
operator_traits::{Data, Operator, SourceOperator},
};
use std::{borrow::Cow, marker::PhantomData};
pub struct Generator<T, F> {
generator: F,
_t: PhantomData<T>,
}
impl<T, F> Generator<T, F>
where
T: Clone,
{
pub fn new(g: F) -> Self {
Self {
generator: g,
_t: Default::default(),
}
}
}
impl<T, F> Operator for Generator<T, F>
where
T: Data,
F: 'static,
{
fn name(&self) -> Cow<'static, str> {
Cow::from("Generator")
}
fn fixedpoint(&self, _scope: Scope) -> bool {
false
}
}
impl<T, F> SourceOperator<T> for Generator<T, F>
where
F: FnMut() -> T + 'static,
T: Data,
{
async fn eval(&mut self) -> T {
(self.generator)()
}
}
pub struct TransactionGenerator<T, F> {
generator: F,
flush: bool,
_t: PhantomData<T>,
}
impl<T, F> TransactionGenerator<T, F>
where
T: Clone,
{
pub fn new(g: F) -> Self {
Self {
generator: g,
flush: false,
_t: Default::default(),
}
}
}
impl<T, F> Operator for TransactionGenerator<T, F>
where
T: Data,
F: 'static,
{
fn name(&self) -> Cow<'static, str> {
Cow::from("Generator")
}
fn flush(&mut self) {
self.flush = true;
}
fn fixedpoint(&self, _scope: Scope) -> bool {
false
}
}
impl<T, F> SourceOperator<T> for TransactionGenerator<T, F>
where
F: FnMut(bool) -> T + 'static,
T: Data,
{
async fn eval(&mut self) -> T {
let result = (self.generator)(self.flush);
self.flush = false;
result
}
}
pub struct GeneratorNested<T> {
reset: Box<dyn FnMut() -> Box<dyn FnMut() -> T>>,
generator: Option<Box<dyn FnMut() -> T>>,
flush: bool,
empty: T,
}
impl<T> GeneratorNested<T>
where
T: Clone,
{
pub fn new(reset: Box<dyn FnMut() -> Box<dyn FnMut() -> T>>, empty: T) -> Self {
Self {
reset,
generator: None,
flush: false,
empty,
}
}
}
impl<T> Operator for GeneratorNested<T>
where
T: Data,
{
fn name(&self) -> Cow<'static, str> {
Cow::from("GeneratorNested")
}
fn clock_start(&mut self, scope: Scope) {
if scope == 0 {
self.generator = Some((self.reset)());
}
}
fn is_input(&self) -> bool {
true
}
fn fixedpoint(&self, _scope: Scope) -> bool {
false
}
fn flush(&mut self) {
self.flush = true;
}
}
impl<T> SourceOperator<T> for GeneratorNested<T>
where
T: Data,
{
async fn eval(&mut self) -> T {
if self.flush {
self.flush = false;
(self.generator.as_mut().unwrap())()
} else {
self.empty.clone()
}
}
}
pub struct ConstantGenerator<T> {
generator: T,
}
impl<T> ConstantGenerator<T>
where
T: Clone,
{
pub fn new(g: T) -> Self {
Self { generator: g }
}
}
impl<T> Operator for ConstantGenerator<T>
where
T: Data + 'static,
{
fn name(&self) -> Cow<'static, str> {
Cow::from("ConstantGenerator")
}
fn fixedpoint(&self, _scope: Scope) -> bool {
true
}
}
impl<T> SourceOperator<T> for ConstantGenerator<T>
where
T: Data + 'static + Clone + Default,
{
async fn eval(&mut self) -> T {
if Runtime::worker_index() == 0 {
self.generator.clone()
} else {
T::default()
}
}
}