fayalite 0.2.0

Hardware Description Language embedded in Rust, using FIRRTL's semantics
Documentation
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{
    expr::{Expr, ToExpr},
    int::Bool,
    source_location::SourceLocation,
    ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
};

mod sealed {
    pub trait ResetTypeSealed {}
}

pub trait ResetType: StaticType<MaskType = Bool> + sealed::ResetTypeSealed {}

macro_rules! reset_type {
    ($name:ident, $Trait:ident::$trait_fn:ident, $is_castable_from_bits:literal) => {
        #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
        pub struct $name;

        impl Type for $name {
            type BaseType = $name;
            type MaskType = Bool;

            impl_match_variant_as_self!();

            fn mask_type(&self) -> Self::MaskType {
                Bool
            }

            fn canonical(&self) -> CanonicalType {
                CanonicalType::$name(*self)
            }

            fn source_location() -> SourceLocation {
                SourceLocation::builtin()
            }

            fn from_canonical(canonical_type: CanonicalType) -> Self {
                let CanonicalType::$name(retval) = canonical_type else {
                    panic!("expected {}", stringify!($name));
                };
                retval
            }
        }

        impl $name {
            pub fn type_properties(self) -> TypeProperties {
                Self::TYPE_PROPERTIES
            }
            pub fn can_connect(self, _rhs: Self) -> bool {
                true
            }
        }

        impl StaticType for $name {
            const TYPE: Self = Self;
            const MASK_TYPE: Self::MaskType = Bool;
            const TYPE_PROPERTIES: TypeProperties = TypeProperties {
                is_passive: true,
                is_storable: false,
                is_castable_from_bits: $is_castable_from_bits,
                bit_width: 1,
            };
            const MASK_TYPE_PROPERTIES: TypeProperties = Bool::TYPE_PROPERTIES;
        }

        impl sealed::ResetTypeSealed for $name {}

        impl ResetType for $name {}

        pub trait $Trait {
            fn $trait_fn(&self) -> Expr<$name>;
        }

        impl<T: ?Sized + $Trait> $Trait for &'_ T {
            fn $trait_fn(&self) -> Expr<$name> {
                (**self).$trait_fn()
            }
        }

        impl<T: ?Sized + $Trait> $Trait for &'_ mut T {
            fn $trait_fn(&self) -> Expr<$name> {
                (**self).$trait_fn()
            }
        }

        impl<T: ?Sized + $Trait> $Trait for Box<T> {
            fn $trait_fn(&self) -> Expr<$name> {
                (**self).$trait_fn()
            }
        }

        impl $Trait for Expr<$name> {
            fn $trait_fn(&self) -> Expr<$name> {
                *self
            }
        }
    };
}

reset_type!(AsyncReset, ToAsyncReset::to_async_reset, true);
reset_type!(SyncReset, ToSyncReset::to_sync_reset, true);
reset_type!(
    Reset,
    ToReset::to_reset,
    false // Reset is not castable from bits because we don't know if it's async or sync
);

impl ToSyncReset for bool {
    fn to_sync_reset(&self) -> Expr<SyncReset> {
        self.to_expr().to_sync_reset()
    }
}

impl ToAsyncReset for bool {
    fn to_async_reset(&self) -> Expr<AsyncReset> {
        self.to_expr().to_async_reset()
    }
}