#[cfg(not(target_arch = "wasm32"))]
use celox::{DefaultBackend, InstanceHierarchy, NamedSignal, get_byte_size};
use celox::{PortTypeKind, VariableKind};
#[cfg(not(target_arch = "wasm32"))]
type NamedEvent = celox::NamedEvent<DefaultBackend>;
#[cfg(not(target_arch = "wasm32"))]
use fxhash::FxHashMap as HashMap;
#[cfg(not(target_arch = "wasm32"))]
use serde::Serialize;
#[cfg(not(target_arch = "wasm32"))]
#[derive(Debug, Clone, Serialize)]
pub struct SignalLayout {
pub offset: usize,
pub width: usize,
pub byte_size: usize,
pub is_4state: bool,
pub direction: &'static str,
pub type_kind: &'static str,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub array_dims: Vec<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub array_element_stride: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub array_plane_size: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub associated_clock: Option<String>,
}
#[cfg(not(target_arch = "wasm32"))]
#[derive(Debug, Clone, Serialize)]
pub struct HierarchyNode {
pub module_name: String,
pub signals: HashMap<String, SignalLayout>,
pub children: HashMap<String, Vec<HierarchyNode>>,
}
pub fn direction_str(var_kind: VariableKind) -> &'static str {
match var_kind {
VariableKind::Input => "input",
VariableKind::Output => "output",
VariableKind::Inout => "inout",
_ => "internal",
}
}
pub fn type_kind_str(type_kind: PortTypeKind) -> &'static str {
match type_kind {
PortTypeKind::Clock => "clock",
PortTypeKind::ResetAsyncHigh => "reset_async_high",
PortTypeKind::ResetAsyncLow => "reset_async_low",
PortTypeKind::ResetSyncHigh => "reset_sync_high",
PortTypeKind::ResetSyncLow => "reset_sync_low",
PortTypeKind::Logic => "logic",
PortTypeKind::Bit => "bit",
PortTypeKind::Other => "other",
}
}
#[cfg(not(target_arch = "wasm32"))]
fn build_signal_layout_entry(ns: &NamedSignal, four_state_mode: bool) -> SignalLayout {
let direction = direction_str(ns.info.var_kind);
let type_kind = type_kind_str(ns.info.type_kind);
let (width, array_dims) = if ns.info.array_dims.is_empty() {
(ns.signal.width, vec![])
} else {
let element_width = ns.signal.width / ns.info.array_dims.iter().product::<usize>();
(element_width, ns.info.array_dims.clone())
};
let (array_element_stride, array_plane_size) = ns
.signal
.array_layout
.map(|layout| (Some(layout.element_stride), Some(layout.plane_size)))
.unwrap_or((None, None));
SignalLayout {
offset: ns.signal.offset,
width,
byte_size: get_byte_size(width),
is_4state: four_state_mode && ns.signal.is_4state,
direction,
type_kind,
array_dims,
array_element_stride,
array_plane_size,
associated_clock: ns.associated_clock.clone(),
}
}
#[cfg(not(target_arch = "wasm32"))]
pub fn build_signal_layout(
signals: &[NamedSignal],
four_state_mode: bool,
) -> HashMap<String, SignalLayout> {
let mut map = HashMap::default();
for ns in signals {
map.insert(
ns.name.clone(),
build_signal_layout_entry(ns, four_state_mode),
);
}
map
}
#[cfg(not(target_arch = "wasm32"))]
pub fn build_hierarchy_node(h: &InstanceHierarchy, four_state: bool) -> HierarchyNode {
let mut signals = HashMap::default();
for ns in &h.signals {
signals.insert(ns.name.clone(), build_signal_layout_entry(ns, four_state));
}
let mut children = HashMap::default();
for (name, instances) in &h.children {
let nodes: Vec<HierarchyNode> = instances
.iter()
.map(|inst| build_hierarchy_node(inst, four_state))
.collect();
children.insert(name.clone(), nodes);
}
HierarchyNode {
module_name: h.module_name.clone(),
signals,
children,
}
}
#[cfg(not(target_arch = "wasm32"))]
pub fn build_event_map(events: &[NamedEvent]) -> HashMap<String, u32> {
let mut map = HashMap::default();
for ne in events {
map.insert(ne.name.clone(), ne.id as u32);
}
map
}