#[cfg(feature = "frontend")]
mod dedup;
mod dedup_algorithm;
#[cfg(feature = "frontend")]
mod classes;
#[cfg(feature = "frontend")]
mod elaborate;
#[cfg(feature = "frontend")]
mod error;
#[cfg(feature = "frontend")]
mod exprwalk;
#[cfg(feature = "frontend")]
mod instance;
#[cfg(feature = "frontend")]
mod items;
#[cfg(feature = "frontend")]
mod lattice;
#[cfg(feature = "frontend")]
pub mod specify;
#[cfg(feature = "frontend")]
pub fn is_uninstantiated_scope(sym: &sv_lang::Symbol<'_>) -> bool {
use sv_lang_kinds::SymbolKind;
if sym.kind() == SymbolKind::Instance {
sym.instance_body().is_some_and(|b| b.is_uninstantiated())
} else {
sym.kind() == SymbolKind::GenerateBlock && sym.generate_block_is_uninstantiated()
}
}
#[cfg(feature = "frontend")]
pub mod itf;
#[cfg(feature = "frontend")]
mod template;
#[cfg(feature = "frontend")]
pub mod vif;
#[cfg(feature = "frontend")]
pub use classes::{
ClassDefinitionTable, ClassMembers, assign_class_template_ids, base_chain,
check_class_constraints, class_method_symbols, class_param_binding_hash,
class_specialization_key, class_template_key_of, class_templates_with_statics,
classes_with_dynamic_static_init, classify_members, collect_new_class_types,
flattened_interfaces, same_specialization,
};
#[cfg(feature = "frontend")]
pub use dedup::{
ConfirmedMembers, MemberShape, confirm_and_assign_symbol_keys, merge_groups_within_bucket,
};
pub use dedup_algorithm::hash_then_verify_dedup;
#[cfg(feature = "frontend")]
pub(crate) use elaborate::symbol_key_map;
#[cfg(feature = "frontend")]
pub use elaborate::{Netlist, elaborate};
#[cfg(feature = "frontend")]
pub use error::ElabError;
#[cfg(feature = "frontend")]
pub use instance::{InstanceNode, InstanceTree};
#[cfg(feature = "frontend")]
pub use items::{
CheckerOutput, FreeVarKind, ProceduralChecker, checker_instance_body, checker_instances,
checker_output_of, checker_outputs, enclosing_instance_body, enclosing_package,
free_var_groups, free_var_kind, free_var_seed, generate_scopes, is_in_checker, is_in_program,
is_static_procedural_var, module_items, procedural_checkers, state_items,
static_procedural_vars, variable_initializer,
};
#[cfg(feature = "frontend")]
pub use template::{
ContAssignTemplate, DriverEntry, MemoryDecl, PortDecl, PortDirection, ProcessTemplate,
SignalDecl, SignalKind, StaticSensitivity, SubInstanceSlot, Template, ValueDomain,
};
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct SymbolKey(pub u32);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
#[repr(transparent)]
pub struct InstanceId(pub u32);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct InstantiatedSignalId {
pub instance: InstanceId,
pub member: SymbolKey,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct TemplateId(pub u32);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct TemplateKey {
pub definition: u32,
pub params_hash: u64,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct ClassTemplateId(pub u32);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct ClassTemplateKey {
pub definition: u32,
pub params_hash: u64,
}
pub trait HierarchicalNames {
fn hierarchical_path(&self, id: InstanceId) -> &str;
}
pub trait HierPathResolver {
fn resolve_hier_path(&self, path: &str) -> Option<InstantiatedSignalId>;
}
#[cfg(feature = "frontend")]
impl<T: NetlistView + ?Sized> HierPathResolver for T {
fn resolve_hier_path(&self, path: &str) -> Option<InstantiatedSignalId> {
NetlistView::resolve_hier_path(self, path)
}
}
#[cfg(feature = "frontend")]
impl<T: NetlistView + ?Sized> HierarchicalNames for T {
fn hierarchical_path(&self, id: InstanceId) -> &str {
NetlistView::hierarchical_path(self, id)
}
}
#[cfg(feature = "frontend")]
pub trait NetlistView {
fn registration_order(&self) -> Vec<InstanceId>;
fn hierarchical_path(&self, id: InstanceId) -> &str;
fn resolve_hier_path(&self, path: &str) -> Option<InstantiatedSignalId>;
fn dedup_key(&self, tmpl: TemplateId) -> &TemplateKey;
fn tick_ns_per_unit(&self) -> u64;
fn instance(&self, id: InstanceId) -> &InstanceNode;
fn template(&self, id: TemplateId) -> &Template;
}
#[cfg(test)]
mod tests {
use super::{InstanceId, InstantiatedSignalId, SymbolKey};
#[test]
fn dedup_collapses_template_but_preserves_per_instance_identity() {
let shared_member = SymbolKey(7);
let a = InstantiatedSignalId {
instance: InstanceId(1),
member: shared_member,
};
let b = InstantiatedSignalId {
instance: InstanceId(2),
member: shared_member,
};
assert_eq!(
a.member, b.member,
"both instances resolve to the same deduped Template member"
);
assert_ne!(
a, b,
"two instances of a deduped template must never alias to one \
InstantiatedSignalId — equality must also compare `instance`, \
never `member` alone"
);
}
}