Skip to content

S5: Slice and concat #22

Description

@jeffersonmourak

Stage S5 of the multi-bit wires language extension. Part of milestone "Multi-bit: Composition + validation".

📖 Full plan: DOCS/plan-multi-bit-language.md

Goal

a[lo..hi] and {a, b, ...} work end to end. Engine grows two new component kinds.

Background: three parallel "kind" type families

This project has three independent kind enums, one per layer. Every new component kind has to be added to all three:

Layer Type Location
Engine Component.Kind (a union(ComponentType)) + ComponentType enum lib/circuit.zig:304, 333
Topology format ComponentKind (an enum(u8)) lib/topology/format.zig:6
IR ComponentKind (a union(enum)) + PrimitiveKind enum lib/ir/types.zig:17, 31

Their integer encodings must agree where they overlap; the topology format ID is the wire format and is version-locked (do not renumber existing values).

Files touched

  • lib/circuit.zig:
    • Extend ComponentType enum with slice and concat.
    • Extend Component.Kind union with two new arms:
      • slice: struct { from: *Component, lo: u8, hi: u8 }
      • concat: struct { operands: []const *Component } (operand widths are read off each operand's state_handle.tier at evaluation time)
    • Extend the switch in recalculateAndReschedule to evaluate each:
      • slice: read source BitVecState, mask to bits [lo..hi), shift right by lo, mask to width hi - lo for both value and defined
      • concat: read each operand BitVecState, OR them into position by left-shifting by the running width prefix sum
  • lib/topology/format.zig: add slice = 6 and concat = 7 to ComponentKind. Update the stability test to lock the new values.
  • lib/topology/full_format.zig, full_serializer.zig, full_decoder.zig: serialize slice ranges and concat operand lists into the auxiliary metadata reserved by decision Switch parser to langlang v0.0.12 Go output #17 in the v02 format (no version bump; S2 already reserved the structural slot).
  • lib/ir/types.zig: extend the IR ComponentKind union (and PrimitiveKind enum if used by primitive synthesis) with slice/concat variants carrying the bit-range and operand-list payloads.
  • lib/ir/resolver.zig: when a SignalSource is indexed, sliced, or concat (from S3.3), synthesize the corresponding IR component and rewrite the connection to feed from it.
  • lib/validator/passes/port_validation.zig: validate slice ranges are in bounds against the source's width; validate concat operand widths sum to the destination's expected width.

Acceptance

  • Slice fixtures: pulling bits 0..2 from a 4-bit bus into a width-2 gate
  • Concat fixtures: assembling four 1-bit inputs into a 4-bit bus
  • Composed fixtures: slice-then-concat round-trip returns the original value
  • Single-bit index a[2] lowers to a width-1 slice a[2..3] (same engine kind, not a separate primitive)
  • Topology ComponentKind stability test extended to assert slice == 6 and concat == 7

Depends on

S4 (resolver must already handle literal widths before slice/concat lowering plugs in).
S3.3 (#40) (AST must carry indexed/sliced/concat SignalSource variants before the IR resolver can lower them).

Effort

Medium

Notes

  • Slice and concat are confined to lowered-only forms. Users never write slice(...) or concat(...) directly. The grammar exposes the operations only through [lo..hi] (S3.3) and {...} (S3.3).
  • BitVecState operations (AND, OR, <<, >>) compose cleanly per-bit, so the evaluators are short. The width field on BitVecState is the slice/concat output width and must be set explicitly on synthesis.

Metadata

Metadata

Assignees

No one assigned

    Labels

    engineSimulation engine (lib/circuit.zig)formatTopology binary format (lib/topology)multi-bit-languageMulti-bit wires language extension (DOCS/plan-multi-bit-language.md)resolverIR types and resolver (lib/ir, lib/resolver)

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions