Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions integration_tests/VAMS2023_EVENTS/vams2023_events.va
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// VAMS-2023 5.10.4 (Mantis 7809): analog named events - declared with `event`,
// triggered with `-> name;` from an analog event statement, detected with
// `@(name)`.
`include "disciplines.vams"

module vams2023_events(a, c);
inout a, c;
electrical a, c;

parameter real r = 1000.0 from (0.0:inf);
parameter real period = 1e-9 from (0.0:inf);

event sample_event;
event blank_event;

real gain;
integer samples;

analog begin
gain = 1.0;
samples = 0;

// conditional trigger from a monitored event statement
@(timer(period)) begin
if (r > 100.0)
-> sample_event;
end

// an event that is never triggered
@(blank_event) gain = 0.0;

// detection after the trigger
@(sample_event) begin
samples = samples + 1;
gain = 2.0;
end

I(a, c) <+ gain * V(a, c) / r;
end
endmodule
69 changes: 58 additions & 11 deletions openvaf/hir/src/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use hir_ty::types::{Signature, Ty};
pub use syntax::ast::{BinaryOp, UnaryOp};

use crate::{
Branch, BranchWrite, CompilationDB, Function, FunctionArg, NatureAttribute, Node, Parameter,
Variable,
Branch, BranchWrite, CompilationDB, Function, FunctionArg, NamedEvent, NatureAttribute, Node,
Parameter, Variable,
};

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -54,6 +54,16 @@ impl<'a> BodyRef<'a> {
Some((src, dst))
}

/// Resolves the path expression naming a [`NamedEvent`] in `-> ev;` or
/// `@(ev)`. `None` if the name did not resolve to an event (already
/// diagnosed by type inference).
pub fn resolve_event(&self, expr: ExprId) -> Option<NamedEvent> {
match self.infere.expr_types[expr] {
Ty::Event(id) => Some(NamedEvent { id }),
_ => None,
}
}

fn resolve_path(&self, expr: ExprId) -> Ref {
match self.infere.expr_types[expr] {
Ty::Var(_, id) => Ref::Variable(Variable { id }),
Expand Down Expand Up @@ -188,6 +198,10 @@ impl<'a> BodyRef<'a> {
hir_def::Stmt::EventControl { ref event, body } => {
Some(Stmt::EventControl { event, body })
}
// an unresolved event was already diagnosed; drop the statement
hir_def::Stmt::EventTrigger { event } => {
Some(Stmt::EventTrigger { event: self.resolve_event(event)? })
}
hir_def::Stmt::Assignment { val, assignment_kind, .. } => {
let indirect = assignment_kind == syntax::ast::AssignOp::Indirect;
let stmt = match self.infere.assignment_destination[&stmnt] {
Expand Down Expand Up @@ -272,17 +286,50 @@ pub enum ContributeKind {
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Stmt<'a> {
Expr(ExprId),
EventControl { event: &'a Event, body: StmtId },
Contribute { kind: ContributeKind, branch: BranchWrite, rhs: ExprId },
Assignment { lhs: AssignmentLhs, rhs: ExprId },
Block { body: &'a [StmtId] },
If { cond: ExprId, then_branch: StmtId, else_branch: StmtId },
ForLoop { init: StmtId, cond: ExprId, incr: StmtId, body: StmtId },
WhileLoop { cond: ExprId, body: StmtId },
Case { discr: ExprId, case_arms: &'a [Case] }, // TODO lint on unreachable
EventControl {
event: &'a Event,
body: StmtId,
},
/// VAMS-2023 5.10.4: `-> ev;`
EventTrigger {
event: NamedEvent,
},
Contribute {
kind: ContributeKind,
branch: BranchWrite,
rhs: ExprId,
},
Assignment {
lhs: AssignmentLhs,
rhs: ExprId,
},
Block {
body: &'a [StmtId],
},
If {
cond: ExprId,
then_branch: StmtId,
else_branch: StmtId,
},
ForLoop {
init: StmtId,
cond: ExprId,
incr: StmtId,
body: StmtId,
},
WhileLoop {
cond: ExprId,
body: StmtId,
},
Case {
discr: ExprId,
case_arms: &'a [Case],
}, // TODO lint on unreachable
Break,
Continue,
Return { value: Option<ExprId> },
Return {
value: Option<ExprId>,
},
}
impl Stmt<'_> {
#[inline]
Expand Down
23 changes: 22 additions & 1 deletion openvaf/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub use hir_def::expr::CaseCond;
pub use hir_def::nameres::diagnostics::PathResolveError;
use hir_def::nameres::{DefMap, LocalScopeId, ScopeDefItem};
use hir_def::{
AliasParamId, BlockId, BlockLoc, BranchId, DefWithBodyId, DisciplineId, FunctionId,
AliasParamId, BlockId, BlockLoc, BranchId, DefWithBodyId, DisciplineId, EventId, FunctionId,
LocalFunctionArgId, Lookup, ModuleBodyKind, ModuleId, ModuleLoc, NatureAttrId, NatureId,
NodeId, ParamId, VarId,
};
Expand Down Expand Up @@ -212,6 +212,25 @@ impl Block {
}
}

/// A named event (VAMS-2023 5.10.4): `event ana_event;`
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct NamedEvent {
pub(crate) id: EventId,
}

stdx::impl_debug! {
match NamedEvent{
NamedEvent{ id } => "{id:?}";
}
}

impl NamedEvent {
pub fn name(self, db: &CompilationDB) -> String {
let loc = self.id.lookup(db);
loc.item_tree(db)[loc.id].name.to_string()
}
}

#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct Function {
id: FunctionId,
Expand Down Expand Up @@ -364,6 +383,7 @@ impl Scope {
ScopeDef::AliasParameter(AliasParameter { id })
}
ScopeDefItem::BranchId(id) => ScopeDef::Branch(Branch { id }),
ScopeDefItem::EventId(id) => ScopeDef::NamedEvent(NamedEvent { id }),
ScopeDefItem::FunctionId(id) => ScopeDef::Function(Function { id }),
// implementation details
ScopeDefItem::BuiltIn(_)
Expand Down Expand Up @@ -649,5 +669,6 @@ pub enum ScopeDef {
Parameter(Parameter),
AliasParameter(AliasParameter),
Branch(Branch),
NamedEvent(NamedEvent),
Function(Function),
}
15 changes: 13 additions & 2 deletions openvaf/hir_def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ impl LowerCtx<'_> {
}
ast::Stmt::CaseStmt(stmt) => self.collect_case_stmt(stmt),
ast::Stmt::EventStmt(stmt) => return self.collect_event_stmt(stmt),
// VAMS-2023 5.10.4: `-> event_identifier;`
ast::Stmt::EventTriggerStmt(stmt) => {
Stmt::EventTrigger { event: self.collect_opt_expr(stmt.expr()) }
}
ast::Stmt::BlockStmt(stmt) => self.collect_block(stmt),
ast::Stmt::BreakStmt(_) => Stmt::Break,
ast::Stmt::ContinueStmt(_) => Stmt::Continue,
Expand All @@ -191,10 +195,17 @@ impl LowerCtx<'_> {
} else if event_stmt.final_step_token().is_some() {
GlobalEvent::FinalStep
} else {
// Monitored event (`@(cross(...))` / `@(timer(...))`): preserve it so MIR
// A bare path is a named event (VAMS-2023 5.10.4); everything else is a
// monitored event (`@(cross(...))` / `@(timer(...))`), preserved so MIR
// lowering can give the variables it assigns cross-timestep retention.
let event = match event_stmt.event() {
Some(ast::Expr::PathExpr(path)) => {
Event::Named { event: self.collect_expr(ast::Expr::PathExpr(path)) }
}
_ => Event::Cross,
};
let body = self.collect_opt_stmt(event_stmt.stmt());
let stmt = Stmt::EventControl { event: Event::Cross, body };
let stmt = Stmt::EventControl { event, body };
return self.alloc_stmt(
stmt,
AstPtr::new(event_stmt).cast().unwrap(),
Expand Down
5 changes: 5 additions & 0 deletions openvaf/hir_def/src/body/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ impl Printer<'_> {
wln!(self, "@({:?})", event);
self.pretty_print_stmt(body)
}
Stmt::EventTrigger { event } => {
w!(self, "-> ");
self.pretty_print_expr(event);
wln!(self, ";");
}
Stmt::Assignment { dst, val, assignment_kind } => {
self.pretty_print_expr(dst);
w!(self, "{:?}", assignment_kind);
Expand Down
8 changes: 5 additions & 3 deletions openvaf/hir_def/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ use crate::item_tree::ItemTree;
use crate::nameres::{DefMap, ScopeOrigin};
use crate::{
AliasParamId, AliasParamLoc, BlockId, BlockLoc, BranchId, BranchLoc, DefWithBodyId,
DisciplineAttrId, DisciplineAttrLoc, DisciplineId, DisciplineLoc, FunctionArgId,
FunctionArgLoc, FunctionId, FunctionLoc, ModuleId, ModuleLoc, NatureAttrId, NatureAttrLoc,
NatureId, NatureLoc, NodeId, NodeLoc, ParamId, ParamLoc, VarId, VarLoc,
DisciplineAttrId, DisciplineAttrLoc, DisciplineId, DisciplineLoc, EventId, EventLoc,
FunctionArgId, FunctionArgLoc, FunctionId, FunctionLoc, ModuleId, ModuleLoc, NatureAttrId,
NatureAttrLoc, NatureId, NatureLoc, NodeId, NodeLoc, ParamId, ParamLoc, VarId, VarLoc,
};

#[salsa::query_group(InternDatabase)]
Expand All @@ -35,6 +35,8 @@ pub trait InternDB: BaseDB {
#[salsa::interned]
fn intern_branch(&self, loc: BranchLoc) -> BranchId;
#[salsa::interned]
fn intern_event(&self, loc: EventLoc) -> EventId;
#[salsa::interned]
fn intern_function(&self, loc: FunctionLoc) -> FunctionId;
#[salsa::interned]
fn intern_nature_attr(&self, loc: NatureAttrLoc) -> NatureAttrId;
Expand Down
24 changes: 18 additions & 6 deletions openvaf/hir_def/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ pub enum Stmt {
discr: ExprId,
case_arms: Vec<Case>,
}, // TODO lint on unreachable
/// VAMS-2023 5.10.4: `-> event_identifier;`. `event` is the path expression
/// naming the event so it is resolved like any other reference.
EventTrigger {
event: ExprId,
},
/// VAMS-2023 §5.11 — exit the innermost loop.
Break,
/// VAMS-2023 §5.11 — skip to the end of the innermost loop (re-check condition).
Expand Down Expand Up @@ -191,6 +196,11 @@ pub enum Event {
/// A monitored analog event such as `@(cross(...))` / `@(timer(...))`. Variables
/// assigned inside its body are given cross-timestep retention during lowering.
Cross,
/// A named event (VAMS-2023 5.10.4): `@(ana_event)`. `event` is the path
/// expression naming the event.
Named {
event: ExprId,
},
}

#[derive(Debug, Clone, Eq, PartialEq)]
Expand All @@ -209,12 +219,13 @@ impl Stmt {
#[inline]
pub fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) {
match *self {
Stmt::Empty
| Stmt::Missing
| Stmt::Block { .. }
| Stmt::EventControl { .. }
| Stmt::Break
| Stmt::Continue => (),
Stmt::Empty | Stmt::Missing | Stmt::Block { .. } | Stmt::Break | Stmt::Continue => (),
Stmt::EventControl { ref event, .. } => {
if let Event::Named { event } = *event {
f(event)
}
}
Stmt::EventTrigger { event } => f(event),
Stmt::If { cond: expr, .. }
| Stmt::ForLoop { cond: expr, .. }
| Stmt::WhileLoop { cond: expr, .. }
Expand Down Expand Up @@ -245,6 +256,7 @@ impl Stmt {
| Stmt::Assignment { .. }
| Stmt::Missing
| Stmt::Empty
| Stmt::EventTrigger { .. }
| Stmt::Break
| Stmt::Continue
| Stmt::Return { .. } => (),
Expand Down
16 changes: 15 additions & 1 deletion openvaf/hir_def/src/item_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ impl ItemTree {
ports,
branches,
functions,
events,
} = &mut self.data;
modules.shrink_to_fit();
disciplines.shrink_to_fit();
Expand All @@ -85,6 +86,7 @@ impl ItemTree {
ports.shrink_to_fit();
branches.shrink_to_fit();
functions.shrink_to_fit();
events.shrink_to_fit();
nature_attrs.shrink_to_fit();
discipline_attrs.shrink_to_fit();
}
Expand All @@ -109,6 +111,7 @@ pub struct ItemTreeData {
pub ports: Arena<Port>,
pub branches: Arena<Branch>,
pub functions: Arena<Function>,
pub events: Arena<Event>,
}

/// Trait implemented by all item nodes in the item tree.
Expand Down Expand Up @@ -227,6 +230,7 @@ item_tree_nodes! {
Net in nets -> ast::NetDecl,
Port in ports -> ast::PortDecl,
Branch in branches -> ast::BranchDecl,
Event in events -> ast::EventDecl,
Function in functions -> ast::Function,
NatureAttr in nature_attrs -> ast::NatureAttr,
DisciplineAttr in discipline_attrs -> ast::DisciplineAttr,
Expand All @@ -250,6 +254,7 @@ pub enum ModuleItem {
Branch(ItemTreeId<Branch>),
Node(LocalNodeId),
Function(ItemTreeId<Function>),
Event(ItemTreeId<Event>),
}

impl_from_typed! (
Expand All @@ -259,7 +264,8 @@ impl_from_typed! (
Variable(ItemTreeId<Var>),
Branch(ItemTreeId<Branch>),
Node(LocalNodeId),
Function(ItemTreeId<Function>) for ModuleItem
Function(ItemTreeId<Function>),
Event(ItemTreeId<Event>) for ModuleItem
);

#[derive(Debug, Eq, PartialEq, Clone)]
Expand Down Expand Up @@ -391,6 +397,14 @@ pub struct Branch {
pub ast_id: AstId<ast::BranchDecl>,
}

/// A named event declaration (VAMS-2023 5.10.4): `event ana_event;`
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Event {
pub name: Name,
pub name_idx: usize,
pub ast_id: AstId<ast::EventDecl>,
}

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Block {
pub name: Option<Name>,
Expand Down
Loading
Loading