feat(sv-frontend): lower enums and always_comb control flow - #662
feat(sv-frontend): lower enums and always_comb control flow#662tignear wants to merge 59 commits into
Conversation
Enable the enum_type sv tests by closing three frontend gaps: - fold constant casts of any sized literal, not just zero - resolve $bits and $size of a data type as a cast target width - collect typedef enum member constants as module-level literals - lower if/case inside always_comb into guarded mux chains with latch detection instead of rejecting all comb control flow
77ae1fb to
95045e1
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 77ae1fb4d4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4f0e42cf66
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 12060c7a7b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b75c43322c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7c7f4e3046
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 857395b238
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2690f96e98
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4c4033a531
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e91c4ab9c3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ed17eb741f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1bb3b24e9c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 77ed440fa0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e17c1893f6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1f680e93a6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
celox/crates/celox-sv-analyzer/src/ast.rs
Line 3813 in aa3fe31
When a declared parameter range has a span larger than usize, this unchecked cast truncates the u128 result before + 1; for example, [170141183460469231731687303715884105727:0] becomes usize::MAX + 1 on a 64-bit host. Debug builds panic during analysis, while optimized builds can wrap the dimension to zero and publish an incorrect parameter type. Convert the span with usize::try_from and use checked_add(1) before multiplying.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 16a0a65bfb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31cdab9f28
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 98605cd2ca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
celox/crates/celox-sv-analyzer/src/ast.rs
Line 7598 in 5aa3fa5
When a generate block declares an X/Z-bearing local parameter, this path discards the declaration but add_localparams_from_generate_item cannot add it to block_env because resolved_value only produces an i128. For example, a named generate block containing localparam logic S = 1'bx; always_comb case (S) 1'bx: y = a; endcase is exhaustive, but S remains unknown during case coverage and the valid process is rejected as latch inference. Carry a block-local literal map, including masked values, into combinational lowering instead of relying solely on the numeric environment.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0bbd103294
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b017024e1b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let r#type = type_from_ref_node_with_env( | ||
| RefNode::DataType(node), | ||
| syntax_tree, | ||
| const_env, | ||
| type_aliases, |
There was a problem hiding this comment.
Use the constant environment for function parameter dimensions
When a function parameter range contains a value-dependent cast, this now resolves the parameter's total width with const_env, but tf_params and tf_item_params still obtain its packed_dimensions through the environment-free packed_dimensions_from_ref_node. For example, with parameter W=4 and function logic f(input logic [W'(8):W'(1)] x); return x[7]; endfunction, the formal is correctly recorded as eight bits while its range is discarded; the body consequently leaves x[7] unnormalized and reads flattened bit 7 (declared index 8) rather than bit 6 (declared index 7), silently changing the function result. Lower the function parameter dimensions with the same constant/type-alias environment as the width.
Useful? React with 👍 / 👎.
| const_env: &HashMap<String, i128>, | ||
| type_aliases: &HashMap<String, Type>, | ||
| ) -> bool { | ||
| constant_cast_const_expr(cast, syntax_tree, const_env, type_aliases).is_some() |
There was a problem hiding this comment.
Lower generate-condition casts with the constant environment
Expanding constant-cast validation here makes parameter-sized nonzero casts supported, but the generate traversals still parse their conditions through environment-free const_expr_from_ref_node. Thus a valid construct such as parameter W=2; if (W'(1)) begin : g assign y = 1'b1; end passes the unsupported-construct check using const_env, then comb_processes_from_conditional_generate cannot reconstruct the same cast and returns conditional-generate condition lowering. Use the environment-aware constant-expression lowering for conditional-generate conditions (and the corresponding loop-generate expressions).
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 42148db1a9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ConstExpr::Binary { left, op, right } | ||
| if matches!(op, BinaryOp::BitAnd | BinaryOp::BitOr | BinaryOp::BitXor) => |
There was a problem hiding this comment.
Preserve masks for logical constant expressions
When a constant case selector uses a logical operator whose result is unknown, this mask-preserving evaluator returns None because it accepts only bitwise binary operators. For example, case (1'bx && 1'b1) 1'bx: y = a; endcase has the constant selector X and is exhaustive, but analysis falls back to the entire four-state domain and rejects the valid always_comb block as latch inference. Evaluate LogicAnd/LogicOr here with four-state truth semantics so the known X result reaches case coverage.
Useful? React with 👍 / 👎.
| .function_return_types | ||
| .get(name) | ||
| .and_then(|metadata| metadata.first_packed_dimension_width), | ||
| _ => expr_static_width(&expression, &packed_dimensions), |
There was a problem hiding this comment.
Preserve dimensions for selected
$size arguments
When $size is applied after selecting an unpacked element, this fallback returns the expression's total packed width rather than the first remaining packed dimension. For logic [1:0][3:0] a[2]; localparam P = $size(a[0])'(8'hff);, $size(a[0]) is 2, but the lowered select has static width 8, so the cast produces 255 instead of the required two-bit value 3. Retain the selected value's remaining dimension metadata when first_dimension_only is set.
Useful? React with 👍 / 👎.
| @@ -6201,6 +7845,9 @@ fn add_localparams_from_generate_item_with_literals( | |||
| syntax_tree, | |||
| &mut parameters, | |||
| true, | |||
| const_env, | |||
| &HashMap::default(), | |||
There was a problem hiding this comment.
Forward aliases when resolving generate-local parameters
Fresh evidence after making direct generate conditions environment-aware is that generate-local parameters are still parsed with an empty alias table. For example, with typedef logic [1:0] t; inside a selected generate scope, localparam S = t'(4); if (S) ... else ... should resolve S to zero, but the cast cannot be lowered here, so S is omitted from the block environment and nested generate selection treats both branches as active, potentially rejecting supported code because of constructs in the unreachable branch. Pass the module alias table through this helper and its generate traversal callers.
Useful? React with 👍 / 👎.
| Some(0) => else_expr, | ||
| Some(_) => then_expr, |
There was a problem hiding this comment.
Context-size the chosen constant conditional arm
When a conditional expression has a known condition, returning the chosen arm directly discards the width and signedness context contributed by the other arm. For example, case (1'b1 ? 1'sb1 : 2'sb00) 2'b11: y = a; endcase has a two-bit signed selector equal to 2'b11, but this simplification produces the one-bit signed value 1'sb1; case comparison against the unsigned label then zero-extends it to 2'b01, so the exhaustive block is rejected as latch inference. Resize the selected arm to the conditional expression's result type before replacing the mux.
Useful? React with 👍 / 👎.
| return Ok(()); | ||
| ) -> Option<(&'a Expr, bool)> { | ||
| if let Expr::Unary { | ||
| op: UnaryOp::LogicNot, |
There was a problem hiding this comment.
Recognize one-bit bitwise complements
For a one-bit two-state predicate, bitwise negation is equivalent to logical negation, but this normalization only flips polarity for LogicNot. Thus, with bit s, an outer exhaustive branch containing if (s) y = a; if (~s) y = b; assigns y on every path, yet the complementary-guard proof is missed and the valid always_comb process is rejected for latch inference. Treat BitNot as a polarity inversion when its operand is statically one bit and two-state.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 42148db1a9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let mut packed_dimensions = containing_packed_dimensions( | ||
| RefNode::Expression(argument), | ||
| syntax_tree, | ||
| )? | ||
| else { | ||
| return None; | ||
| }; | ||
| let literal = typecheck::parse_integral_literal(&literal)?; | ||
| if literal.value != 0u8.into() || literal.mask != 0u8.into() { | ||
| return None; | ||
| } | ||
| let target_type = cast_target_type(&cast.nodes.0, syntax_tree, const_env, type_aliases)?; | ||
| let signed = if matches!(cast.nodes.0, sv_parser::CastingType::ConstantPrimary(_)) { | ||
| literal.signed | ||
| const_env, | ||
| type_aliases, | ||
| ) |
There was a problem hiding this comment.
Avoid recursively rebuilding declarations for size casts
When a $bits/$size-sized cast appears inside a port or signal range, this lookup rebuilds the containing module's ports and signals, which lowers the same range and re-enters this call until the analyzer overflows its stack. For example, function logic [7:0] f(); return '0; endfunction; logic [$bits(f())'(7):0] a; triggers this cycle. Unlike the guarded function-return-metadata recursion, this path recurses through containing_packed_dimensions, so it needs its own cycle guard or a context that does not reconstruct the declaration currently being typed.
Useful? React with 👍 / 👎.
| if candidate_msb < whole_low || candidate_msb > whole_high { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Preserve in-range bits of partially out-of-range writes
When a runtime indexed part-select straddles the packed declaration boundary, this check discards the entire candidate instead of applying the overlapping portion of the write. For example, in value = '0; value[index +: 2] = 2'b11; if (replace) value = '1; with logic [7:0] value, index == 7 and replace == 0 should write value[7] while ignoring the out-of-range bit, but normalization emits no matching candidate and leaves value zero. Allow selected_value_after_write to clip these candidates to the in-range overlap rather than requiring both endpoints to be in bounds.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aeefb6e368
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ConstExpr::Binary { left, op, right } | ||
| if matches!(op, BinaryOp::LogicAnd | BinaryOp::LogicOr) => |
There was a problem hiding this comment.
Fold four-state equality selectors before case coverage
When a constant logical equality has X/Z operands, this mask-preserving evaluator handles only logical and bitwise operators and returns None for Eq/Ne. For example, case (1'bx == 1'bx) 1'bx: y = a; endcase is exhaustive because the selector is always X, but coverage analysis treats it as an unconstrained four-state value and rejects the valid always_comb block as latch inference. Evaluate equality results with four-state semantics before case reachability analysis.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3f5038208b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a92da13267
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d572df853d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ConstExpr::Binary { left, op, right } | ||
| if matches!( | ||
| op, | ||
| BinaryOp::Add |
There was a problem hiding this comment.
Preserve X/Z masks when folding shifts
When a constant case selector shifts an X/Z-containing value, this operator whitelist excludes Shl, Shr, and Sar, so mask-preserving folding fails. For example, case (2'bx0 >> 1) 2'b0x: y = a; endcase is exhaustive because the selector is always 2'b0x, but coverage instead treats it as an unconstrained four-state value and rejects the valid always_comb block as latch inference; implement four-state shift folding with the left operand's width and signedness.
Useful? React with 👍 / 👎.
| _ => { | ||
| let constant: crate::ir::ConstExpr = expr_to_const(expr.clone())?.into(); | ||
| typecheck::eval_const_integral_literal_with_types(&constant, const_env, parameter_types) | ||
| } |
There was a problem hiding this comment.
Preserve masks when folding constant bit selects
When a constant selector extracts an X/Z bit, the conversion reaches eval_const_integral_literal_with_types, but integral_literal_from_const_expr has no ConstExpr::Select arm. Thus case (2'bx0[1]) 1'bx: y = a; endcase has a selector that is always X, yet its mask is lost, the selector is treated as ranging over all four states, and the otherwise exhaustive always_comb block is rejected as latch inference; evaluate selected literal bits as one-bit masked literals.
Useful? React with 👍 / 👎.
| let number = eval_ast_const_expr(&value, &eval_env).ok_or_else(|| { | ||
| AnalyzerError::Unsupported(format!("unresolved enum member `{name}` value")) | ||
| })?; |
There was a problem hiding this comment.
Retain unsigned 128-bit enum initializer results
When an enum initializer computes an unsigned 128-bit result above i128::MAX, this required evaluation returns None: the integral evaluator cannot convert the result to i128, and its checked-arithmetic fallback also overflows. For example, typedef enum logic [127:0] { A = 128'h7fff_ffff_ffff_ffff_ffff_ffff_ffff_ffff + 128'h1 } E; is valid and produces the high-bit pattern, but enum collection rejects it as an unresolved member value; preserve unsigned width-128 results as i128 bit patterns, as is already done for direct 128-bit literals.
Useful? React with 👍 / 👎.
| }, | ||
| ConstExpr::Unary { op, expr } => ConstExpr::Unary { | ||
| op, | ||
| expr: Box::new(substitute_const_expr_constants(*expr, const_env)), | ||
| }, | ||
| ConstExpr::Binary { left, op, right } => ConstExpr::Binary { | ||
| left: Box::new(substitute_const_expr_constants(*left, const_env)), | ||
| op, | ||
| right: Box::new(substitute_const_expr_constants(*right, const_env)), | ||
| }, | ||
| ConstExpr::Mux { | ||
| Expr::Ident(name) => { | ||
| packed_dimensions | ||
| .get(name) | ||
| .is_some_and(|dimensions| dimensions.is_2state) | ||
| || packed_dimensions.const_env.contains_key(name) | ||
| } | ||
| Expr::Literal(value) => typecheck::parse_integral_literal(value) | ||
| .is_some_and(|literal| literal.mask == num_bigint::BigUint::default()), | ||
| Expr::Select { expr, msb, lsb, .. } => { | ||
|
|
There was a problem hiding this comment.
Count nonblocking assignments as definite comb writes
When every branch of an always_comb assigns a target with <=, lowering accepts the nonblocking assignments, but this definite-target analysis recognizes only BlockingAssignment. Consequently, always_comb if (s) y <= a; else y <= b; fails to mark the else write as an exhaustive fallback, retains a previous-value mux arm, and is incorrectly rejected as latch inference despite assigning y on every path; handle NonblockingAssignment here the same way as the corresponding written-target collector.
Useful? React with 👍 / 👎.
Summary
Un-ignores the three
enum_typesv frontend tests by closing the missing SystemVerilog frontend pieces they exercise:ConstantCastof any sized literal (e.g.(logic [1:0])'(2'd1)) into a typed literal, not just zero-valued casts(<data type>)and(<data type>)as cast target widths (the form the Veryl emitter produces for enum member initializers)typedef enummembers with explicit values into module-level literal constants so references likeState_Idlein case items resolveif/caseinsidealways_combinto guarded multiplexer chains instead of rejecting all comb control flow, with latch inference rejected and statement ordering preserved for the downstream ordered-assignment dependency checksTest plan
cargo test -p celox --features systemverilog— all green, including the newly enabledenum_typesv tests (case match, FF state machine, assign/compare)cargo test -p celox-sv-analyzer --lib— all greencargo test --workspace— all greencargo clippy/cargo fmtcleanrejects_constructs_that_are_not_yet_loweredto drop the now-supported comb control-flow case