use crate::{
clock::ClockDomain,
expr::{Expr, Flow},
intern::Interned,
module::{NameId, ScopedNameId},
source_location::SourceLocation,
ty::{CanonicalType, Type},
};
use std::fmt;
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct Reg<T: Type> {
name: ScopedNameId,
source_location: SourceLocation,
ty: T,
clock_domain: Expr<ClockDomain>,
init: Option<Expr<T>>,
}
impl<T: Type + fmt::Debug> fmt::Debug for Reg<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self {
name,
source_location: _,
ty,
clock_domain,
init,
} = self;
f.debug_struct("Reg")
.field("name", name)
.field("ty", ty)
.field("clock_domain", clock_domain)
.field("init", init)
.finish_non_exhaustive()
}
}
impl<T: Type> Reg<T> {
pub fn canonical(&self) -> Reg<CanonicalType> {
let Self {
name,
source_location,
ref ty,
clock_domain,
init,
} = *self;
Reg {
name,
source_location,
ty: ty.canonical(),
clock_domain,
init: init.map(Expr::canonical),
}
}
#[track_caller]
pub fn new_unchecked(
scoped_name: ScopedNameId,
source_location: SourceLocation,
ty: T,
clock_domain: Expr<ClockDomain>,
init: Option<Expr<T>>,
) -> Self {
assert!(
ty.canonical().is_storable(),
"register type must be a storable type"
);
if let Some(init) = init {
assert_eq!(ty, Expr::ty(init), "register's type must match init type");
}
Self {
name: scoped_name,
source_location,
ty,
clock_domain,
init,
}
}
pub fn ty(&self) -> T {
self.ty
}
pub fn source_location(&self) -> SourceLocation {
self.source_location
}
pub fn containing_module_name(&self) -> Interned<str> {
self.containing_module_name_id().0
}
pub fn containing_module_name_id(&self) -> NameId {
self.name.0
}
pub fn name(&self) -> Interned<str> {
self.name_id().0
}
pub fn name_id(&self) -> NameId {
self.name.1
}
pub fn scoped_name(&self) -> ScopedNameId {
self.name
}
pub fn clock_domain(&self) -> Expr<ClockDomain> {
self.clock_domain
}
pub fn init(&self) -> Option<Expr<T>> {
self.init
}
pub fn flow(&self) -> Flow {
Flow::Duplex
}
pub fn must_connect_to(&self) -> bool {
false
}
}