Skip to content

Add analog named events (VAMS-2023 §5.10.4, Mantis 7809) - #29

Merged
sai-v-ch merged 3 commits into
OpenVAF:mobfrom
sai-v-ch:vams2023-named-events
Aug 1, 2026
Merged

Add analog named events (VAMS-2023 §5.10.4, Mantis 7809)#29
sai-v-ch merged 3 commits into
OpenVAF:mobfrom
sai-v-ch:vams2023-named-events

Conversation

@sai-v-ch

Copy link
Copy Markdown
Collaborator

Part of the VAMS-2023 alignment effort tracked in #19.

Summary

VAMS-2023 §5.10.4 (Mantis 7809) describes how analog named events are declared, triggered and detected:

event ana_event;
analog begin
   @(timer(1n)) -> ana_event;
   @(ana_event) $strobe("Event: ana_event detected in analog");
end

None of this existed in OpenVAF: event was not a token keyword, -> was not lexed at all, and @(<identifier>) was silently swallowed by the monitored-event path without the name ever being resolved.

Front end

  • lexer / tokens-> (Trigger) and the event keyword. event was already reserved by the Annex B identifier check, so nothing that compiled before stops compiling.
  • grammarEventDecl as a module item, EventTriggerStmt as a statement. The trigger target is wrapped in a path expression so the name goes through the same resolution machinery as every other reference; EventStmt now exposes its event expression.
  • hir_def — an Event item-tree entity interned like a branch and declared in the module scope, plus Stmt::EventTrigger and Event::Named. @(x) is a named event when x is a bare path and a monitored event otherwise.
  • hir_tyTy::Event / TyRequirement::Event. Both -> ev; and @(ev) require a declared event, so naming a variable is a type error and an undeclared name is a resolve error.
  • validationevent_trigger is part of analog_event_statement, not of analog_statement, so in an analog block a trigger is only legal under an event control (@(timer(1n)) -> ev;); it is also allowed in the standalone procedural blocks. This is tracked with a dedicated flag rather than BodyCtx, so a probe-dependent if inside the event body does not produce a false positive.

Lowering

A named event becomes a boolean place, PlaceKind::NamedEvent: false when the block starts, set to true by -> ev;, and used as the guard of the @(ev) body. That gives the sequential semantics of a single evaluation of the analog block — a detection placed before the trigger does not fire, one placed after it fires exactly when the trigger executed, and a conditional trigger produces a real phi rather than a constant. The MIR snapshot shows all three cases.

Known limits

Stated here rather than papered over; all of them are pre-existing properties of OpenVAF's event model:

  • OpenVAF has no digital lane, so an analog event cannot be observed by an always block, and a trigger in a procedural block is not visible to the analog block (the flag is per MIR function).
  • Monitored events (@(timer(...)), @(cross(...))) always evaluate their body, so a trigger inside one always fires.
  • Event arrays (event ev[0:3];) are rejected with a parse error rather than supported.

Test plan

  • openvaf/test_data/ui/named_events.va — declarations (several events per statement), triggers from event statements and detections; compiles with an empty diagnostics log.
  • openvaf/test_data/ui/named_events_err.{va,log} — a trigger outside an event statement, a trigger and a detection naming a variable instead of an event, and an undeclared event.
  • openvaf/test_data/mir/named_events.{va,mir} — MIR snapshot: br v1 (false) for a detection before the trigger, v22 = phi [true, …], [false, …] for a conditional trigger, br v2 (true) for an unconditional one.
  • integration_tests/VAMS2023_EVENTS/ + openvaf/test_data/osdi/vams2023_events.snap — end-to-end compile / link / load of a device whose conductance is selected by a named event.

Verified locally with LLVM 18:

cargo test -p tokens -p lexer -p preprocessor -p syntax -p basedb -p parser -p hir -p hir_def -p hir_ty -p hir_lower -p sourcegen
RUN_DEV_TESTS=1 cargo test -p basedb -p hir -p hir_lower --test data_tests   # all integration models green
RUN_DEV_TESTS=1 cargo test -p openvaf --features llvm18 --test integration -- integration::VAMS2023_EVENTS
cargo fmt --all -- --check

🤖 Generated with Claude Code

VAMS-2023 5.10.4 (Mantis 7809) describes how analog named events are
declared, triggered and detected:

    event ana_event;
    analog begin
       @(timer(1n)) -> ana_event;
       @(ana_event) $strobe("detected");
    end

None of this existed in OpenVAF: `event` was not a token keyword, `->`
was not lexed, and `@(<identifier>)` was silently swallowed by the
monitored-event path without resolving the name.

Front end
---------
- lexer/tokens: `->` (`Trigger`) and the `event` keyword.
- grammar: `EventDecl` as a module item and `EventTriggerStmt` as a
  statement. The trigger target is wrapped in a path expression so the
  name is resolved by the same machinery as every other reference, and
  `EventStmt` now exposes its event expression.
- hir_def: `Event`/`EventId` item-tree entity interned like a branch,
  declared in the module scope; `Stmt::EventTrigger` and
  `Event::Named`. `@(x)` is a named event when `x` is a bare path and a
  monitored event otherwise.
- hir_ty: `Ty::Event`/`TyRequirement::Event`; both `-> ev;` and `@(ev)`
  require a declared event, so naming a variable is a type error and an
  undeclared name is a resolve error.
- validation: `event_trigger` belongs to `analog_event_statement`, not
  to `analog_statement`, so in an analog block a trigger is only allowed
  under an event control (`@(timer(1n)) -> ev;`); it is also allowed in
  the standalone procedural blocks. Tracked with a dedicated flag rather
  than `BodyCtx` so a probe-dependent `if` inside the event body does
  not produce a false positive.

Lowering
--------
A named event becomes a boolean place, `PlaceKind::NamedEvent`, that is
false when the block starts, set to true by `-> ev;` and used as the
guard of the `@(ev)` body. That gives the sequential semantics of a
single evaluation: a detection placed before the trigger does not fire,
one placed after it fires exactly when the trigger executed, and a
conditional trigger produces a real phi rather than a constant.

Known limits, all pre-existing and documented rather than papered over:
- OpenVAF has no digital lane, so an event cannot be observed by an
  `always` block, and triggering in a procedural block is not visible to
  the analog block (the flag is per MIR function).
- monitored events (`@(timer(...))`, `@(cross(...))`) always evaluate
  their body, so a trigger inside one always fires.
- event arrays (`event ev[0:3];`) are rejected with a parse error.

Tests:
- ui/named_events.va: declarations (several per statement), triggers
  from event statements and detections, accepted without diagnostics.
- ui/named_events_err.log: trigger outside an event statement, trigger
  and detection naming a variable, and an undeclared event.
- mir/named_events.{va,mir}: snapshot showing the guard being `false`
  before the trigger, a phi for a conditional trigger and `true` for an
  unconditional one.
- integration_tests/VAMS2023_EVENTS + osdi/vams2023_events.snap:
  end-to-end compile/link/load of a device whose conductance is selected
  by a named event.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

sai-v-ch added 2 commits July 31, 2026 19:55
Resolves the overlap with OpenVAF#26 (break/continue/return): both branches add
statement kinds to hir_def::Stmt and hir::Stmt and arms to every match
over them, so each conflict is a union of the two sides.

- hir_def::Stmt: EventTrigger alongside Break/Continue/Return; Break and
  Continue join the no-child-expression arm of walk_child_exprs, while
  EventControl needs its own arm for Event::Named.
- hir::Stmt, hir_lower::collect_cross_assigned, hir_ty::infere_stmt and
  the parser's STMT_TS: union.
- The two generated files (tokens/parser/generated.rs,
  syntax/ast/generated/nodes.rs) were regenerated from the cleanly merged
  ungram and KINDS_SRC rather than merged by hand.
@sai-v-ch
sai-v-ch merged commit 0a5d002 into OpenVAF:mob Aug 1, 2026
11 checks passed
@sai-v-ch
sai-v-ch deleted the vams2023-named-events branch August 1, 2026 03:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant