use crate::netlist::SymbolKey;
use crate::symid::SymbolUid;
use std::collections::{BTreeSet, HashMap};
pub(crate) fn expression_read_set(
expr: sv_lang::Expression<'_>,
scope_keys: &HashMap<crate::symid::SymbolId, SymbolKey>,
) -> Vec<SymbolKey> {
let mut out = BTreeSet::new();
collect(expr, scope_keys, &mut out);
out.into_iter().collect()
}
fn collect(
expr: sv_lang::Expression<'_>,
scope_keys: &HashMap<crate::symid::SymbolId, SymbolKey>,
out: &mut BTreeSet<SymbolKey>,
) {
if let Some(sym) = expr.referenced_symbol()
&& let Some(&key) = scope_keys.get(&sym.uid())
{
out.insert(key);
}
for operand in expr.operands() {
collect(operand, scope_keys, out);
}
}
pub(crate) fn has_pattern_conditional(expr: sv_lang::Expression<'_>) -> bool {
use sv_lang_kinds::ExpressionKind;
let mut stack = vec![expr.as_sem_node()];
while let Some(n) = stack.pop() {
if let Some(e) = n.as_expression()
&& e.kind() == ExpressionKind::ConditionalOp
&& e.conditions().iter().any(|c| c.pattern().is_some())
{
return true;
}
stack.extend(n.children());
}
false
}
pub(crate) fn has_logical_not(expr: sv_lang::Expression<'_>) -> bool {
use sv_lang_kinds::ExpressionKind;
let mut stack = vec![expr.as_sem_node()];
while let Some(n) = stack.pop() {
if let Some(e) = n.as_expression()
&& e.kind() == ExpressionKind::UnaryOp
&& e.unary_op() == Some(sv_lang::UnaryOp::LogicalNot)
{
return true;
}
stack.extend(n.children());
}
false
}
pub(crate) fn rhs_tree_read_set(
expr: sv_lang::Expression<'_>,
scope_keys: &HashMap<crate::symid::SymbolId, SymbolKey>,
) -> Vec<SymbolKey> {
let mut out = BTreeSet::new();
let mut stack = vec![expr.as_sem_node()];
while let Some(n) = stack.pop() {
if let Some(e) = n.as_expression()
&& crate::symid::is_value_name(e.kind())
&& let Some(sym) = e.referenced_symbol()
&& let Some(&key) = scope_keys.get(&sym.uid())
{
out.insert(key);
}
stack.extend(n.children());
}
out.into_iter().collect()
}
pub(crate) fn pattern_rhs_read_set(
expr: sv_lang::Expression<'_>,
scope_keys: &HashMap<crate::symid::SymbolId, SymbolKey>,
) -> Result<Vec<SymbolKey>, String> {
use sv_lang_kinds::ExpressionKind;
let mut stack = vec![expr.as_sem_node()];
while let Some(n) = stack.pop() {
if let Some(e) = n.as_expression()
&& e.kind() == ExpressionKind::Call
&& e.is_system_call() != Some(true)
{
return Err(
"a pattern-matching conditional in a continuous assignment whose right-hand \
side also calls a subroutine (its sensitivity cannot be derived)"
.to_string(),
);
}
stack.extend(n.children());
}
Ok(rhs_tree_read_set(expr, scope_keys))
}