Open vaf reloaded documentation#15
Conversation
Covers the forward-mode source-transformation AD pass: Unknown/Derivative types, KnownDerivatives/DerivativeIntern, LiveDerivatives three-phase dataflow analysis, subgraph sharing optimisation, DerivativeBuilder per-opcode rules, and a traced sin_second_order worked example. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the HIR→MIR lowering pipeline: three-layer architecture (MirBuilder/LoweringCtx/BodyLoweringCtx), HirInterner reverse-mapping table, ParamKind/PlaceKind/CallBackKind enums, SSA construction, statement and expression lowering rules, and a resistor_va worked example tracing V(a,b)<+... to SSA instructions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the simulation backend: CompiledModule 8-step construction pipeline, DaeSystem (SimUnknown/Residual/MatrixEntry), Initialization op-independent/op-dependent split with CacheSlot mechanism, NodeCollapse CollapsePair sources, and a full resistor_va trace from CompiledModule::new through to Jacobian entry wiring. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the OSDI 0.4 codegen layer: compile() two-phase structure, OsdiTys stdlib bitcode embedding, OsdiCompilationUnit per-module codegen, OsdiInstanceData/OsdiModelData constant field indices, four generated functions (access/setup_model/setup_instance/eval), 46-field OsdiDescriptor, callback resolution, and all six exported globals. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the MIR-to-LLVM-IR translation layer: LLVMBackend/ModuleLlvm
ownership model, lifetime hierarchy ('t/'a/'ll/'cx), CodegenCx per-module
context, Types primitive table, BuilderVal/MemLoc lazy-load abstraction,
callback protocol (Prebuilt/Inline), build_func() RPO walk with deferred
phi fix-up, complete opcode-to-LLVM dispatch table, fast-math signaling
via negative srcloc, intrinsics/libm registry, and a resistor eval
worked example tracing fmul/fadd/exit to LLVM IR.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the first compilation layer above parsing: Salsa query architecture (InternDB/HirDefDB), ItemTree as the incremental invalidation barrier, three-layer ID system (ItemTreeId/ItemLoc/interned IDs), DefMap scope tree and DefCollector, ScopeId cross-map path resolution, DefWithBodyId/Body/BodySourceMap, unresolved Expr/Stmt trees, *Data semantic query layer, and a full resistor_va trace from source through ItemTree -> DefMap -> Body. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers TiMap<I,K,V> (#[repr(transparent)] over IndexMap with typed index I), TiSet<K,V> (over IndexSet with typed position K), ahash hasher rationale, insert_full/ensure/replace/iter_enumerated API, and usage in hir_lower, mir, sim_back, osdi, and mir_autodiff. Worked example traces an OSDI parameter table build and lookup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers WorkQueue<T> (FIFO) and WorkStack<T> (LIFO) de-duplicating worklist types, the pop-vs-take distinction (re-insertion vs single-visit semantics), BitSet membership oracle rationale, and public fields design. Worked example traces dead_code_elimination's two-phase reverse-sweep + fixpoint-propagation pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the 64-character alphabet, three named base constants (CASE_INSENSITIVE=36, ALPHANUMERIC_ONLY=62, MAX_BASE=64), the stack-allocated push_str implementation (least-significant-first + reverse), and the four call sites: MD5-based cache file naming, LLVM local symbol generation, OSDI module UUID encoding, and temp object file extension generation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the harness=false/custom-main pattern, Test/Failed/Arguments/TestSummary types, from_dir/from_dir_filtered/from_list constructors, the harness! macro and TestOrTestList trait, run_harness execution model (sort→filter→sequential catch_unwind), and all seven data-test users. Worked example traces the basedb data_tests.rs harness! call. Notes the tests.rs/README.md copy-paste artefacts from base_n. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the test-as-codegen pattern (ensure_file_contents fail-then-rewrite), four generators (AST/SyntaxKind from .ungram, MIR opcodes/InstBuilder from the opcodes! DSL, HIR builtins tables, OSDI C-header bindings), the utility layer (CommentBlock extraction, reformat via rustfmt, string-case converters, project_root), and the cross-compilation guard. Worked example traces adding a new MIR opcode through the full regeneration cycle. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the Data union (#[repr(C)], 8-byte, untagged f64/i32/bool/Spur), UNDEF=0xFF sentinel, from_f64_slice transmute, InterpreterState (vals/prev_bb/ next_inst), Interpreter run loop, eval dispatch for all InstructionData variants (Branch/Jump/Exit/PhiNode/Call/Unary/Binary), and the Func<'a> raw- fn-pointer call handler type. Worked example traces the mir_autodiff numerical verification test pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the MIR text format (Cranelift .clif dialect), Lexer token set and scanning rules (numbers/NaN/Inf, entity names via split_entity_name, %names, strings with escapes, -> arrow detection), Parser single-token lookahead recursive-descent design, forward-reference handling via make_invalid_value, Context add_sig/add_block helpers, parse_inst_operands dispatch by InstructionFormat, phi [v,block] pair syntax, and the lasso Rodeo returned alongside the Function. Worked example traces a mir_autodiff test fixture. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the compilation library (Opts, CompilationDestination, CompilationTermination, compile/expand pipeline, cache hash logic) and the CLI binary (mimalloc allocator, ARGS mutex, clap flag table, matches_to_opts, crash_report panic hook). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers Circuit / Node / DeviceId / ModelId / InstanceId; the DeviceImpl / ModelImpl / InstanceImpl trait hierarchy; the Expr / Value / Arena expression system; CircuitDescription elaboration; the Newton-Raphson DC/AC solver backed by KLU; and the Verilog-A device loading path (openvaf::compile → dlopen → OsdiDevice). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ogae_py) verilogae: covers the (*retrieve*) variable extraction model, FatPtr vectorised ABI, ModelInfo/FuncSpec/ParamInfo, the full/info-only compilation paths, per-function MIR slicing, dependency breaking, VFS export, and rayon-parallel codegen. verilogae_ffi: covers the static/dynamic feature split, Opts/VfsExport RAII wrappers, and the links = "verilogae" cargo convention. verilogae_py: covers PyInit_verilogae, the three Python types (VaeModel/VaeFunction/VaeParam), the NumPy FatPtr zero-copy integration, global type-ref caching, and the raw pyo3-ffi approach. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the two active subcommands: `verilogae build/test/publish` (Python wheel pipeline: cargo build → pip wheel → auditwheel → twine) and `gen-msvcrt` (UCRT .def generation via mingw-w64 + clang -E). Notes the commented-out cache and vendor modules. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
crate_graph.gv covers all 35 workspace crates in 6 clusters: entry points, compilation library, frontend, MIR middle-end, backend, utility crates, and consumer crates. Edges are labelled with the primary function/method calls crossing each crate boundary. Dashed edges denote dev-dependencies, generated code, and widely-used macro utilities. Rendered to SVG and PDF. Regenerate with: dot -Tsvg docs/crate_graph.gv -o docs/crate_graph.svg Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request adds comprehensive documentation to the repository, including high-level architecture overviews, detailed internal design documents for individual crates, and a progressive tutorial series. The reviewer's feedback is highly constructive and should be addressed: it corrects systematic spelling typos of 'infer' in the hir_ty internals, fixes invalid Rust code in the base_n internals snippet due to missing type casting, reverses the incorrect dependency arrows for the stdx crate in the Graphviz diagram, and corrects the binary name from openvaf-r to openvaf throughout the tutorials.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
|
||
| `infere_body_query` constructs a `Ctx` and drives the walk: | ||
|
|
||
| ```rust | ||
| struct Ctx<'a> { | ||
| result: InferenceResult, | ||
| body: &'a Body, | ||
| db: &'a dyn HirTyDB, | ||
| expr_stmt_ty: Option<Type>, // expected value type for Expr-statement bodies | ||
| } | ||
| ``` | ||
|
|
||
| `expr_stmt_ty` is set for parameters (`param_data(param).ty`) and variables (`var_data(var).ty`) — bodies that consist of a single value expression rather than a procedural block. For module analog blocks and functions it is `None`. | ||
|
|
||
| **`infere_stmt(stmt)`** dispatches on `Stmt` variant: | ||
|
|
||
| - `Stmt::Expr(expr)` → `infere_assignment(stmt, expr, expr_stmt_ty)` (treats the expression as an implicit assignment to the declared type) | ||
| - `Stmt::Assignment { dst, val, op }` → `infere_assignment_dst` to resolve `dst`, then `infere_assignment` to check `val` against the destination type | ||
| - `Stmt::If/ForLoop/WhileLoop { cond }` → `infere_cond` (expects `Condition`) | ||
| - `Stmt::Case { discr, case_arms }` → infers discriminant; checks each arm value satisfies the discriminant's `TyRequirement` | ||
| - All statement kinds call `walk_child_stmts` to recurse | ||
|
|
There was a problem hiding this comment.
There is a systematic typo in this document where the verb "infer" and its derived function names are spelled with an extra "e" at the end (e.g., infere_body_query, infere_stmt, infere_expr, infere_assignment, infere_cond). Standardizing these to infer matches the actual codebase naming conventions and improves readability.
infer_body_query constructs a Ctx and drives the walk:
```rust
struct Ctx<'a> {
result: InferenceResult,
body: &'a Body,
db: &'a dyn HirTyDB,
expr_stmt_ty: Option<Type>, // expected value type for Expr-statement bodies
}expr_stmt_ty is set for parameters (param_data(param).ty) and variables (var_data(var).ty) — bodies that consist of a single value expression rather than a procedural block. For module analog blocks and functions it is None.
infer_stmt(stmt) dispatches on Stmt variant:
Stmt::Expr(expr)→infer_assignment(stmt, expr, expr_stmt_ty)(treats the expression as an implicit assignment to the declared type)Stmt::Assignment { dst, val, op }→infer_assignment_dstto resolvedst, theninfer_assignmentto checkvalagainst the destination typeStmt::If/ForLoop/WhileLoop { cond }→infer_cond(expectsCondition)Stmt::Case { discr, case_arms }→ infers discriminant; checks each arm value satisfies the discriminant'sTyRequirement- All statement kinds call
walk_child_stmtsto recurse
infer_expr(stmt, expr) -> Option<Ty> is the core dispatch. It matches on self.body.exprs[expr]:
| let mut s = [0u8; 128]; | ||
| let mut index = 0; | ||
|
|
||
| loop { | ||
| s[index] = BASE_64[(n % base) as usize]; | ||
| index += 1; | ||
| n /= base; | ||
| if n == 0 { break; } | ||
| } | ||
| s[0..index].reverse(); | ||
| output.push_str(str::from_utf8(&s[0..index]).unwrap()); |
There was a problem hiding this comment.
In Rust, mixed-type arithmetic is not allowed without explicit casting. Since n is a u128 and base is a usize, expressions like n % base and n /= base will fail to compile. Casting base to u128 beforehand makes the code snippet valid Rust. Additionally, using the fully qualified std::str::from_utf8 ensures the snippet is self-contained.
| let mut s = [0u8; 128]; | |
| let mut index = 0; | |
| loop { | |
| s[index] = BASE_64[(n % base) as usize]; | |
| index += 1; | |
| n /= base; | |
| if n == 0 { break; } | |
| } | |
| s[0..index].reverse(); | |
| output.push_str(str::from_utf8(&s[0..index]).unwrap()); | |
| let mut s = [0u8; 128]; | |
| let mut index = 0; | |
| let base_u128 = base as u128; | |
| loop { | |
| s[index] = BASE_64[(n % base_u128) as usize]; | |
| index += 1; | |
| n /= base_u128; | |
| if n == 0 { break; } | |
| } | |
| s[0..index].reverse(); | |
| output.push_str(std::str::from_utf8(&s[0..index]).unwrap()); |
| stdx -> hir_def [label="impl_idx_from!\nimpl_intern_key!" style=dashed color="#999999" fontcolor="#999999"] | ||
| stdx -> mir [label="impl_idx_from!" style=dashed color="#999999" fontcolor="#999999"] | ||
| stdx -> sim_back [label="impl_idx_from!\nzip()" style=dashed color="#999999" fontcolor="#999999"] |
There was a problem hiding this comment.
The dependency arrows for the stdx utility crate are reversed. In Graphviz, A -> B represents that A depends on or calls B. Since stdx is a leaf utility crate, other crates (like hir_def, mir, and sim_back) depend on it, not the other way around. Reversing these arrows corrects the architectural representation.
hir_def -> stdx [label="impl_idx_from!\nimpl_intern_key!" style=dashed color="#999999" fontcolor="#999999"]
mir -> stdx [label="impl_idx_from!" style=dashed color="#999999" fontcolor="#999999"]
sim_back -> stdx [label="impl_idx_from!\nzip()" style=dashed color="#999999" fontcolor="#999999"]
| A release build takes several minutes on first run. On success the binary | ||
| lives at: |
There was a problem hiding this comment.
The compiled binary produced by the openvaf-driver package is named openvaf (as documented in docs/ARCHITECTURE.md), not openvaf-r. Referencing openvaf-r in the tutorials will cause "file not found" errors for users following the guide. Please update this reference to openvaf here and throughout the rest of the tutorial files.
| Linux / macOS | `target/release/openvaf` |
| Windows | `target\release\openvaf.exe` |
I generated the documentation for the main crate and different modules