pub struct ElaborateSession { /* private fields */ }Expand description
Session token holding the unfrozen circuit (AD-13).
Implementations§
Source§impl ElaborateSession
impl ElaborateSession
pub fn new(circuit_name: impl Into<String>) -> Self
pub fn begin_module(&mut self, name: impl Into<String>, span: Span)
Sourcepub fn bind_domain(&mut self, name: impl Into<String>, domain: u32)
pub fn bind_domain(&mut self, name: impl Into<String>, domain: u32)
Bind a phantom clock-domain id to a signal (AD-22).
Sourcepub fn mark_cdc_bridge(&mut self, name: impl Into<String>)
pub fn mark_cdc_bridge(&mut self, name: impl Into<String>)
Mark a CDC bridge signal that may legally cross domains.
Sourcepub fn declare_double_flop_stages(
&mut self,
stem: impl Into<String>,
ty: GroundType,
dst_domain: u32,
span: Span,
) -> (String, String)
pub fn declare_double_flop_stages( &mut self, stem: impl Into<String>, ty: GroundType, dst_domain: u32, span: Span, ) -> (String, String)
Declare a synthesizable 2-stage CDC synchronizer register pair (FR79 / AD-29).
Creates {stem}_ff0 and {stem}_ff1, binds both to dst_domain, and marks
{stem}_ff0 as a CDC bridge so Self::assign_reg_d_from / Self::assign_net
may sample a source-domain din. Call Self::connect_double_flop inside a
sequential process to wire ff0 ← din, ff1 ← ff0.
Stage count: 2. Latency: 2 destination-domain ticks to ff1 (see
DoubleFlop::LATENCY_DST_TICKS in prelude).
Sourcepub fn connect_double_flop(
&mut self,
ff0: impl Into<String>,
ff1: impl Into<String>,
din: impl Into<String>,
span: Span,
)
pub fn connect_double_flop( &mut self, ff0: impl Into<String>, ff1: impl Into<String>, din: impl Into<String>, span: Span, )
Wire a previously declared DoubleFlop pair: ff0 ← din, ff1 ← ff0.
Must be called inside a sequential process. ff0/ff1 should come from
Self::declare_double_flop_stages.
pub fn add_input(&mut self, name: impl Into<String>, ty: GroundType, span: Span)
pub fn add_output( &mut self, name: impl Into<String>, ty: GroundType, span: Span, )
Sourcepub fn add_inout(&mut self, name: impl Into<String>, ty: GroundType, span: Span)
pub fn add_inout(&mut self, name: impl Into<String>, ty: GroundType, span: Span)
Top-level InOut / Analog IO (FR27). Non-top uses are rejected at freeze.
pub fn declare_wire( &mut self, name: impl Into<String>, ty: GroundType, span: Span, )
pub fn declare_reg( &mut self, name: impl Into<String>, ty: GroundType, span: Span, )
Sourcepub fn declare_reg_ex(
&mut self,
name: impl Into<String>,
ty: GroundType,
async_reset: bool,
has_enable: bool,
span: Span,
)
pub fn declare_reg_ex( &mut self, name: impl Into<String>, ty: GroundType, async_reset: bool, has_enable: bool, span: Span, )
Declare a register with optional async reset / clock enable (AD-23).
Sourcepub fn declare_sync_read_mem(
&mut self,
name: impl Into<String>,
depth: u32,
width: u32,
span: Span,
)
pub fn declare_sync_read_mem( &mut self, name: impl Into<String>, depth: u32, width: u32, span: Span, )
Declare SyncReadMem (CHIRRTL-friendly; sync_read=true).
Sourcepub fn declare_mem(
&mut self,
name: impl Into<String>,
depth: u32,
width: u32,
span: Span,
)
pub fn declare_mem( &mut self, name: impl Into<String>, depth: u32, width: u32, span: Span, )
Declare Mem (async-read / reg-file style; sync_read=false).
Sourcepub fn declare_mem_with_init(
&mut self,
name: impl Into<String>,
depth: u32,
width: u32,
init: Vec<u64>,
span: Span,
)
pub fn declare_mem_with_init( &mut self, name: impl Into<String>, depth: u32, width: u32, init: Vec<u64>, span: Span, )
Declare Mem with elaborate-time init words (FR73). Prefer
Self::declare_mem_with_init_fn for generator closures.
Sourcepub fn declare_sync_read_mem_with_init(
&mut self,
name: impl Into<String>,
depth: u32,
width: u32,
init: Vec<u64>,
span: Span,
)
pub fn declare_sync_read_mem_with_init( &mut self, name: impl Into<String>, depth: u32, width: u32, init: Vec<u64>, span: Span, )
Declare SyncReadMem with elaborate-time init words (FR73).
Sourcepub fn declare_mem_with_init_fn<F>(
&mut self,
name: impl Into<String>,
depth: u32,
width: u32,
f: F,
span: Span,
)
pub fn declare_mem_with_init_fn<F>( &mut self, name: impl Into<String>, depth: u32, width: u32, f: F, span: Span, )
Elaborate-time Mem init generator (FR73 / AD-18).
Runs f(addr) for each address inside the session, masks to width bits,
and stores plain Vec<u64> on the HIR mem node. The closure does not
enter FrozenHir (NFR36). Only non-capturing Fn is legal; capturing
Wire/Reg/signal refs must be rejected via
Self::assert_no_hw_capture (rhdl::E0142).
Sourcepub fn declare_sync_read_mem_with_init_fn<F>(
&mut self,
name: impl Into<String>,
depth: u32,
width: u32,
f: F,
span: Span,
)
pub fn declare_sync_read_mem_with_init_fn<F>( &mut self, name: impl Into<String>, depth: u32, width: u32, f: F, span: Span, )
SyncReadMem variant of Self::declare_mem_with_init_fn (FR73).
Sourcepub fn check_add(&mut self, lhs: &str, rhs: &str, span: Span) -> Option<u32>
pub fn check_add(&mut self, lhs: &str, rhs: &str, span: Span) -> Option<u32>
Same-width binary add. Returns Err diagnostic via session if widths differ.
pub fn check_connect(&mut self, lhs: &str, rhs: &str, span: Span) -> Option<u32>
Sourcepub fn pad_to(
&mut self,
src: &str,
to_width: u32,
dest: impl Into<String>,
span: Span,
) -> bool
pub fn pad_to( &mut self, src: &str, to_width: u32, dest: impl Into<String>, span: Span, ) -> bool
Explicit zero-extend / sign-pad to a wider width; records result as a temp wire name.
pub fn trunc_to( &mut self, src: &str, to_width: u32, dest: impl Into<String>, span: Span, ) -> bool
pub fn begin_combinational(&mut self, span: Span)
pub fn begin_sequential(&mut self, span: Span)
Sourcepub fn begin_then(&mut self, span: Span)
pub fn begin_then(&mut self, span: Span)
Start an if-branch inside a combinational process (latch analysis).
pub fn begin_else(&mut self, span: Span)
pub fn end_if(&mut self, span: Span)
Sourcepub fn assign_add(
&mut self,
dst: impl Into<String>,
lhs: impl Into<String>,
rhs: impl Into<String>,
span: Span,
)
pub fn assign_add( &mut self, dst: impl Into<String>, lhs: impl Into<String>, rhs: impl Into<String>, span: Span, )
Combinational assign dst = lhs + rhs (same-width required).
Sourcepub fn assign_lit(&mut self, dst: impl Into<String>, lit: u64, span: Span)
pub fn assign_lit(&mut self, dst: impl Into<String>, lit: u64, span: Span)
Combinational assign dst = lit.
Sourcepub fn assign_eq(
&mut self,
dst: impl Into<String>,
lhs: impl Into<String>,
rhs: impl Into<String>,
span: Span,
)
pub fn assign_eq( &mut self, dst: impl Into<String>, lhs: impl Into<String>, rhs: impl Into<String>, span: Span, )
Combinational assign dst = (lhs == rhs) (0/1).
Sourcepub fn assign_mux(
&mut self,
dst: impl Into<String>,
sel: impl Into<String>,
t: impl Into<String>,
f: impl Into<String>,
span: Span,
)
pub fn assign_mux( &mut self, dst: impl Into<String>, sel: impl Into<String>, t: impl Into<String>, f: impl Into<String>, span: Span, )
Combinational assign dst = sel ? t : f (sel != 0 is true).
Sourcepub fn assign_sub(
&mut self,
dst: impl Into<String>,
lhs: impl Into<String>,
rhs: impl Into<String>,
span: Span,
)
pub fn assign_sub( &mut self, dst: impl Into<String>, lhs: impl Into<String>, rhs: impl Into<String>, span: Span, )
Combinational dst = lhs - rhs.
Sourcepub fn assign_and(
&mut self,
dst: impl Into<String>,
lhs: impl Into<String>,
rhs: impl Into<String>,
span: Span,
)
pub fn assign_and( &mut self, dst: impl Into<String>, lhs: impl Into<String>, rhs: impl Into<String>, span: Span, )
Combinational dst = lhs & rhs.
Sourcepub fn assign_or(
&mut self,
dst: impl Into<String>,
lhs: impl Into<String>,
rhs: impl Into<String>,
span: Span,
)
pub fn assign_or( &mut self, dst: impl Into<String>, lhs: impl Into<String>, rhs: impl Into<String>, span: Span, )
Combinational dst = lhs | rhs.
Sourcepub fn assign_xor(
&mut self,
dst: impl Into<String>,
lhs: impl Into<String>,
rhs: impl Into<String>,
span: Span,
)
pub fn assign_xor( &mut self, dst: impl Into<String>, lhs: impl Into<String>, rhs: impl Into<String>, span: Span, )
Combinational dst = lhs ^ rhs.
Sourcepub fn assign_shl(
&mut self,
dst: impl Into<String>,
lhs: impl Into<String>,
rhs: impl Into<String>,
span: Span,
)
pub fn assign_shl( &mut self, dst: impl Into<String>, lhs: impl Into<String>, rhs: impl Into<String>, span: Span, )
Combinational dst = lhs << (rhs & 63).
Sourcepub fn assign_shr(
&mut self,
dst: impl Into<String>,
lhs: impl Into<String>,
rhs: impl Into<String>,
span: Span,
)
pub fn assign_shr( &mut self, dst: impl Into<String>, lhs: impl Into<String>, rhs: impl Into<String>, span: Span, )
Combinational dst = lhs >> (rhs & 63) (logical).
Sourcepub fn assign_net(
&mut self,
name: impl Into<String>,
from: impl Into<String>,
span: Span,
)
pub fn assign_net( &mut self, name: impl Into<String>, from: impl Into<String>, span: Span, )
Assign a combinational net / output / wire from from.
Sourcepub fn assign_reg_d_inc(&mut self, name: impl Into<String>, span: Span)
pub fn assign_reg_d_inc(&mut self, name: impl Into<String>, span: Span)
Assign Reg.d next-state as name + 1 (wrapping).
Sourcepub fn assign_reg_d_from(
&mut self,
name: impl Into<String>,
from: impl Into<String>,
span: Span,
)
pub fn assign_reg_d_from( &mut self, name: impl Into<String>, from: impl Into<String>, span: Span, )
Assign Reg.d from another signal.
Sourcepub fn assign_reg_d_mux(
&mut self,
name: impl Into<String>,
sel: impl Into<String>,
t: impl Into<String>,
f: impl Into<String>,
span: Span,
)
pub fn assign_reg_d_mux( &mut self, name: impl Into<String>, sel: impl Into<String>, t: impl Into<String>, f: impl Into<String>, span: Span, )
Assign Reg.d as a 2:1 mux (same-width t/f as the register).
Used for handwritten seq goldens alongside Self::inline_seq_fn.
Sourcepub fn assign_mem_write(
&mut self,
mem: impl Into<String>,
addr: impl Into<String>,
data: impl Into<String>,
span: Span,
)
pub fn assign_mem_write( &mut self, mem: impl Into<String>, addr: impl Into<String>, data: impl Into<String>, span: Span, )
Sequential SyncReadMem / Mem write: mem[addr] <= data (always enabled).
Sourcepub fn assign_mem_write_en(
&mut self,
mem: impl Into<String>,
addr: impl Into<String>,
data: impl Into<String>,
we: impl Into<String>,
span: Span,
)
pub fn assign_mem_write_en( &mut self, mem: impl Into<String>, addr: impl Into<String>, data: impl Into<String>, we: impl Into<String>, span: Span, )
Sequential mem write gated by we (we != 0).
Sourcepub fn assign_reg_d_mem_read(
&mut self,
reg: impl Into<String>,
mem: impl Into<String>,
addr: impl Into<String>,
span: Span,
)
pub fn assign_reg_d_mem_read( &mut self, reg: impl Into<String>, mem: impl Into<String>, addr: impl Into<String>, span: Span, )
Sequential SyncReadMem read into a register (latency 1 on tick).
pub fn end_process(&mut self)
pub fn end_module(&mut self)
pub fn finish(self) -> Result<FrozenHir, Diagnostics>
Sourcepub fn reject_unsynthesizable(&mut self, construct: &str, span: Span)
pub fn reject_unsynthesizable(&mut self, construct: &str, span: Span)
Record a synthesizable-path violation (heap, threads, f64, capturing closure, …)
as a structured diagnostic (rhdl::E0141 / FR16).
Sourcepub fn reject_hw_capture(&mut self, capture: &HwCaptureRef, span: Span)
pub fn reject_hw_capture(&mut self, capture: &HwCaptureRef, span: Span)
Reject capturing a hardware Wire/Reg/signal ref into an elaborate-time generator or factory closure (FR73 / NFR35 / AD-18).
Stable code: rhdl::E0142. Distinct from FR16 cycle-accurate
Self::reject_unsynthesizable (rhdl::E0141).
Sourcepub fn assert_no_hw_capture(&mut self, captures: &[HwCaptureRef], span: Span)
pub fn assert_no_hw_capture(&mut self, captures: &[HwCaptureRef], span: Span)
Assert that no hardware Wire/Reg/signal refs were captured into a generator / factory context. Empty slice is a no-op (legal non-capturing path).
Call when a documented illegal capture is present (ATDD / macros / typed
handles). Any token → rhdl::E0142 at Self::finish.
Sourcepub fn reject_unsynthesizable_closure(
&mut self,
violation: &SynthesizableClosureViolation,
span: Span,
)
pub fn reject_unsynthesizable_closure( &mut self, violation: &SynthesizableClosureViolation, span: Span, )
Reject a documented SynthesizableClosure constraint breach (FR74 / Cap-R-60).
Stable codes: rhdl::E0143 (heap), rhdl::E0144 (runtime capture
state), rhdl::E0145 (impure). Does not emit closure IR into HIR
(NFR36) — diagnostics only. Distinct from E0141 / E0142.
Sourcepub fn check_synthesizable_closure(
&mut self,
violations: &[SynthesizableClosureViolation],
span: Span,
)
pub fn check_synthesizable_closure( &mut self, violations: &[SynthesizableClosureViolation], span: Span, )
Cap-R-60 check hook: record all documented SynthesizableClosure violations.
Empty violations is a no-op (legal empty/simple closure — paves 28.2).
Reachable from design crates via prelude and from future
cargo bitloom check (or equivalent) wrappers.
Sourcepub fn check_synthesizable_closure_marker<C: SynthesizableClosure>(
&mut self,
closure: &C,
span: Span,
)
pub fn check_synthesizable_closure_marker<C: SynthesizableClosure>( &mut self, closure: &C, span: Span, )
Cap-R-60 helper: run SynthesizableClosure::synthesizable_closure_violations
and record any tokens (empty = pass).
Sourcepub fn inline_comb_fn<F>(
&mut self,
dst: impl Into<String>,
args: &[&str],
violations: &[SynthesizableClosureViolation],
span: Span,
f: F,
)
pub fn inline_comb_fn<F>( &mut self, dst: impl Into<String>, args: &[&str], violations: &[SynthesizableClosureViolation], span: Span, f: F, )
Inline a synthesizable combinational transform (FR75 / Cap-R-55).
Must be called inside an open Self::begin_combinational process
(same rules as assign_*). Sequence:
- Cap-R-60
Self::check_synthesizable_closureonviolations - If any violation token was supplied, do not expand (finish fails)
- Otherwise invoke
f(args)once and lowerCombInlinethrough existing Wire/assign_*paths — FrozenHir holds only ordinaryAssignExpr(NFR36; noFnobjects after freeze)
Incomplete-assign / latch analysis (AD-18) still applies to dst.
Sequential-block inline: Self::inline_seq_fn (Cap-R-56 / Cap-R-70).
session.begin_combinational(span);
session.inline_comb_fn("y", &["a", "b"], &[], span, |args| {
CombInline::Add(args[0].into(), args[1].into())
});
session.end_process();Sourcepub fn inline_comb_fn_marker<C, F>(
&mut self,
dst: impl Into<String>,
args: &[&str],
marker: &C,
span: Span,
f: F,
)
pub fn inline_comb_fn_marker<C, F>( &mut self, dst: impl Into<String>, args: &[&str], marker: &C, span: Span, f: F, )
Cap-R-55 helper: run marker SynthesizableClosure check then inline.
Sourcepub fn reject_seq_ownership_violation(
&mut self,
violation: &SeqOwnershipViolation,
span: Span,
)
pub fn reject_seq_ownership_violation( &mut self, violation: &SeqOwnershipViolation, span: Span, )
Cap-R-70: record documented seq-ownership violations (rhdl::E0146).
Sourcepub fn check_seq_ownership(
&mut self,
violations: &[SeqOwnershipViolation],
span: Span,
)
pub fn check_seq_ownership( &mut self, violations: &[SeqOwnershipViolation], span: Span, )
Cap-R-70 check hook: record all documented seq-ownership violations.
Empty violations is a no-op.
Sourcepub fn inline_seq_fn<F>(
&mut self,
dst_reg: impl Into<String>,
args: &[&str],
synth_violations: &[SynthesizableClosureViolation],
ownership_violations: &[SeqOwnershipViolation],
span: Span,
f: F,
)
pub fn inline_seq_fn<F>( &mut self, dst_reg: impl Into<String>, args: &[&str], synth_violations: &[SynthesizableClosureViolation], ownership_violations: &[SeqOwnershipViolation], span: Span, f: F, )
Inline a synthesizable sequential transform onto Reg.d (FR75 / Cap-R-56).
Must be called inside an open Self::begin_sequential process.
Sequence:
- Cap-R-60
Self::check_synthesizable_closureonsynth_violations - Cap-R-70
Self::check_seq_ownershiponownership_violations - Cap-R-70 auto-detect: if
dst_reg.dis already assigned in this sequential process, diagnoserhdl::E0146and do not expand - If any Cap-R-60 / Cap-R-70 token was supplied, do not expand
- Otherwise invoke
f(args)once and lowerSeqInlineto ordinary sequentialAssignExpr/Reg.d— FrozenHir holds noFn(NFR36)
Cross-process multi-drive / undriven after expand still use AD-4 freeze
checks (rhdl::E0140, …).
session.begin_sequential(span);
session.inline_seq_fn("count", &[], &[], &[], span, |_args| SeqInline::Inc);
session.end_process();Sourcepub fn inline_seq_fn_marker<C, F>(
&mut self,
dst_reg: impl Into<String>,
args: &[&str],
marker: &C,
ownership_violations: &[SeqOwnershipViolation],
span: Span,
f: F,
)
pub fn inline_seq_fn_marker<C, F>( &mut self, dst_reg: impl Into<String>, args: &[&str], marker: &C, ownership_violations: &[SeqOwnershipViolation], span: Span, f: F, )
Cap-R-56 helper: marker Cap-R-60 check then seq inline (Cap-R-70 ownership args).
Sourcepub fn add_instance(
&mut self,
name: impl Into<String>,
module: impl Into<String>,
connects: Vec<(String, String)>,
params: Vec<(String, u32)>,
span: Span,
)
pub fn add_instance( &mut self, name: impl Into<String>, module: impl Into<String>, connects: Vec<(String, String)>, params: Vec<(String, u32)>, span: Span, )
Hierarchical instance (Story 2.2); not flattened at elaborate.
Sourcepub fn generate_instances<F>(&mut self, count: usize, f: F)
pub fn generate_instances<F>(&mut self, count: usize, f: F)
Elaborate-time module factory (FR73 / Cap-R-53).
Invokes f(i, session) for each i in 0..count. The factory should
call Self::add_instance (and optional wire decls) so each iteration
records a child instance plus type-safe port connects. Only ordinary
Stmt::Instance / PortConnect remain after the loop — the closure
does not enter FrozenHir (NFR36). Width/dir checks still run at
finish (FR8 / existing instance validation). Capturing Wire/Reg into
the factory is illegal — use Self::assert_no_hw_capture (rhdl::E0142).
session.generate_instances(4, |i, s| {
s.add_instance(
format!("u{i}"),
"Lane",
vec![
("clk".into(), "clk".into()),
("rst".into(), "rst".into()),
("x".into(), format!("x{i}")),
("y".into(), format!("y{i}")),
],
vec![],
Span::default(),
);
});Sourcepub fn generate_instances_from<F>(&mut self, count: usize, f: F, span: Span)
pub fn generate_instances_from<F>(&mut self, count: usize, f: F, span: Span)
Pure-return factory variant (FR73 / Cap-R-53): f(i) returns an
GeneratedInstance that is immediately recorded as HIR via
Self::add_instance. Prefer when the factory needs no extra session
side effects (wires, dangling marks).