CIRCT 24.0.0git
Loading...
Searching...
No Matches
Public Member Functions | Public Attributes | Protected Member Functions | List of all members
esiaccel.codegen.generator.CppTypeEmitter Class Reference

Public Member Functions

None __init__ (self, CppTypePlanner planner)
 
str type_identifier (self, types.ESIType type)
 
None write_header (self, Path output_dir, str system_name)
 

Public Attributes

 type_id_map
 
 ordered_types
 
 skipped_types
 
 has_cycle
 

Protected Member Functions

str _cpp_string_literal (self, str value)
 
str _get_bitvector_str (self, types.ESIType type)
 
str _storage_type (self, int bit_width, bool signed)
 
bool _is_value_class_type (self, types.ESIType field_type)
 
Tuple[str, List[int]] _array_base_and_dims (self, types.ArrayType array_type)
 
str _std_array_type (self, types.ArrayType array_type)
 
str _cpp_type (self, types.ESIType wrapped)
 
types.ESIType _unwrap_aliases (self, types.ESIType wrapped)
 
str _format_window_ctor_param (self, str field_name, types.ESIType field_type)
 
int _field_byte_width (self, types.ESIType field_type)
 
Optional[int] _safe_byte_width (self, types.ESIType esi_type)
 
None _emit_size_assert (self, IndentedWriter w, str type_name, Optional[int] expected_bytes)
 
Dict[str, Any] _analyze_window (self, types.WindowType window_type)
 
Tuple[Dict[str, int], int] _compute_field_bit_offsets (self, types.StructType struct_type)
 
bool _is_signed_int_field (self, types.ESIType field_type)
 
None _emit_view_store (self, IndentedWriter w, str raw_member, str src, str off_expr, int width)
 
None _emit_field_accessor (self, IndentedWriter w, str raw_member, str self_type, str field_name, types.ESIType field_type, int bit_offset, int bit_width)
 
None _emit_array_accessor (self, IndentedWriter w, str raw_member, str self_type, str field_name, types.ArrayType array_type, int bit_offset)
 
None _emit_unpack (self, IndentedWriter w, str raw_member, str dst, str off, types.ESIType esi_type, int depth)
 
None _emit_pack (self, IndentedWriter w, str raw_member, str src, str off, types.ESIType esi_type, int depth)
 
str _ctor_param_type (self, types.ESIType field_type)
 
None _emit_struct (self, IndentedWriter w, types.StructType struct_type)
 
None _emit_union (self, IndentedWriter w, types.UnionType union_type)
 
List[Tuple[str, types.ESIType, int, int]] _compute_window_frame_layout (self, List[Tuple[str, Optional[types.ESIType]]] fields, int frame_bits, types.ESIType count_type_synth)
 
None _emit_window_frame (self, IndentedWriter w, str frame_name, int frame_bytes, List[Tuple[str, types.ESIType, int, int]] layout)
 
None _emit_window (self, IndentedWriter hdr, types.WindowType window_type)
 
None _emit_window_data_accessors (self, IndentedWriter hdr, Dict[str, Any] info)
 
None _emit_window_deserializer (self, IndentedWriter hdr, Dict[str, Any] info)
 
None _emit_alias (self, IndentedWriter w, types.TypeAlias alias_type)
 

Detailed Description

Emit C++ headers from precomputed type ordering.

Definition at line 900 of file generator.py.

Constructor & Destructor Documentation

◆ __init__()

None esiaccel.codegen.generator.CppTypeEmitter.__init__ (   self,
CppTypePlanner  planner 
)

Member Function Documentation

◆ _analyze_window()

Dict[str, Any] esiaccel.codegen.generator.CppTypeEmitter._analyze_window (   self,
types.WindowType  window_type 
)
protected

◆ _array_base_and_dims()

Tuple[str, List[int]] esiaccel.codegen.generator.CppTypeEmitter._array_base_and_dims (   self,
types.ArrayType  array_type 
)
protected
Return the base C++ type and outer-to-inner dimensions of a nested array.

Definition at line 982 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._cpp_type().

Referenced by esiaccel.codegen.generator.CppTypeEmitter._std_array_type().

◆ _compute_field_bit_offsets()

Tuple[Dict[str, int], int] esiaccel.codegen.generator.CppTypeEmitter._compute_field_bit_offsets (   self,
types.StructType  struct_type 
)
protected
Return `(bit_offset_by_name, total_bits)` for non-void fields.

Fields are laid out LSB-first in wire order, which is reversed manifest
order when `cpp_type.reverse` is set. Caller already knows each field's
type/width from `struct_type.fields`; we only need the per-name offset
and the resulting total bit width to size the storage array.

Definition at line 1193 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._cpp_type().

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_struct().

◆ _compute_window_frame_layout()

List[Tuple[str, types.ESIType, int, int]] esiaccel.codegen.generator.CppTypeEmitter._compute_window_frame_layout (   self,
List[Tuple[str, Optional[types.ESIType]]]  fields,
int  frame_bits,
types.ESIType   count_type_synth 
)
protected
Compute (name, type, bit_offset, bit_width) for each window frame field.

Fields are listed in declared (MSB-first) struct order. The last field
starts at bit zero, matching how CIRCT lowers the serial-window frame
union. Earlier fields sit immediately above it with no inter-field
padding, and any slack (`frame_bits - content_bits`) is at the MSB end.
The returned `bit_offset` is the field's LSB position within the frame's
little-endian `_bytes` array, ready to hand straight to
`_emit_field_accessor`.

The sentinel `(name, None)` count field is materialised as
`count_type_synth` so it can flow through the standard
`_emit_field_accessor` path.

Raises `ValueError` if a field is unbounded (`bit_width < 0`) or if the
accumulated content overflows `frame_bits` -- either would produce bogus
offsets, so fail fast rather than emit silently-wrong accessors.

Definition at line 1701 of file generator.py.

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_window().

◆ _cpp_string_literal()

str esiaccel.codegen.generator.CppTypeEmitter._cpp_string_literal (   self,
str  value 
)
protected
Escape a Python string for use as a C++ string literal.

Definition at line 913 of file generator.py.

◆ _cpp_type()

str esiaccel.codegen.generator.CppTypeEmitter._cpp_type (   self,
types.ESIType  wrapped 
)
protected

◆ _ctor_param_type()

str esiaccel.codegen.generator.CppTypeEmitter._ctor_param_type (   self,
types.ESIType  field_type 
)
protected

◆ _emit_alias()

None esiaccel.codegen.generator.CppTypeEmitter._emit_alias (   self,
IndentedWriter  w,
types.TypeAlias  alias_type 
)
protected
Emit a using alias when the alias targets a different C++ type.

Definition at line 2013 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._cpp_type(), and esiaccel.codegen.generator.CppTypeEmitter.type_id_map.

Referenced by esiaccel.codegen.generator.CppTypeEmitter.write_header().

◆ _emit_array_accessor()

None esiaccel.codegen.generator.CppTypeEmitter._emit_array_accessor (   self,
IndentedWriter  w,
str  raw_member,
str  self_type,
str  field_name,
types.ArrayType  array_type,
int  bit_offset 
)
protected
Emit the accessor set for a fixed-size array field.

Four accessors are emitted, matching the existing array API:

  * `Elem field(std::size_t i)` / `Self &field(std::size_t i, const Elem &)`
    -- per-element get/set, where `Elem` is the (possibly itself an
    array) element type.
  * `Whole field()` / `Self &field(const Whole &)` -- whole-array
    get/set, expressed in terms of the per-element accessors.

The per-element get/set bodies are produced by `_emit_unpack` /
`_emit_pack`, which recurse to the scalar leaves and place each leaf at
its true wire offset `bit_offset + i * elemWidth (+ ...)`. This is what
lets sub-byte, odd-width, sub-byte-aggregate, and *arbitrarily nested*
array elements round-trip even when the C++ element layout does not
match the wire layout.

Definition at line 1458 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._cpp_type(), esiaccel.codegen.generator.CppTypeEmitter._emit_pack(), and esiaccel.codegen.generator.CppTypeEmitter._emit_unpack().

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_field_accessor().

◆ _emit_field_accessor()

None esiaccel.codegen.generator.CppTypeEmitter._emit_field_accessor (   self,
IndentedWriter  w,
str  raw_member,
str  self_type,
str  field_name,
types.ESIType  field_type,
int  bit_offset,
int  bit_width 
)
protected
Emit a getter/setter pair that reads/writes `field_name` out of the
raw bytes member `raw_member` at `bit_offset` / `bit_width`.

Setters share the field's name (no `set_` prefix) and return
`self_type &` so the caller can chain calls (e.g.
`Foo{}.a(1).b(2).inner(x)`).

For integer fields the emitter picks between three inline strategies:

  * Native ints (<= 64 bits). Delegate to the compile-time
    `esi::detail::{read,write}{Un,}signedBits` helpers from
    `esi/BitAccess.h`, which loop over the constituent bits at the
    field's constant offset/width. The non-type template parameters
    let the optimiser fully unroll the loop, so a byte-aligned
    standard-width field still collapses to a single load/store on
    -O1+ -- no special-cased `memcpy` / per-byte fast path required.
  * `bool` (a single bit). Same helpers, specialised to read/write one
    bit and hand back a `bool`.
  * View-class fields. Triggered when `_is_value_class_type` is true --
    currently widths above 64 bits, for any of `BitsType`, signed, or
    unsigned. Returns a non-owning
    `esi::BitVector` / `esi::IntView` / `esi::UIntView` view *into*
    the parent struct's `_bytes` -- zero allocation, no copy. The
    setter accepts any `esi::BitVector` (so views and owning
    subclasses both work) and writes back bit-by-bit. The returned
    view dangles when the parent buffer dies; see the lifetime warning
    at the top of the generated header.

Definition at line 1241 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._cpp_type(), esiaccel.codegen.generator.CppTypeEmitter._emit_array_accessor(), esiaccel.codegen.generator.CppTypeEmitter._emit_view_store(), esiaccel.codegen.generator.CppTypeEmitter._is_signed_int_field(), esiaccel.codegen.generator.CppTypeEmitter._is_value_class_type(), esiaccel.codegen.generator.CppTypePlanner._unwrap_aliases(), and esiaccel.codegen.generator.CppTypeEmitter._unwrap_aliases().

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_struct(), esiaccel.codegen.generator.CppTypeEmitter._emit_union(), and esiaccel.codegen.generator.CppTypeEmitter._emit_window_frame().

◆ _emit_pack()

None esiaccel.codegen.generator.CppTypeEmitter._emit_pack (   self,
IndentedWriter  w,
str  raw_member,
str  src,
str  off,
types.ESIType  esi_type,
int  depth 
)
protected

◆ _emit_size_assert()

None esiaccel.codegen.generator.CppTypeEmitter._emit_size_assert (   self,
IndentedWriter  w,
str  type_name,
Optional[int]  expected_bytes 
)
protected
Emit a `static_assert` that pins the C++ `sizeof` of a packed type to
the byte width derived from the manifest.

`std::array` and bit-field layout are technically implementation-defined,
so this assertion is the safety net that catches a toolchain that lays
them out differently from the wire format.  Skipped silently for types
without a bounded static size.

Definition at line 1085 of file generator.py.

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_struct(), esiaccel.codegen.generator.CppTypeEmitter._emit_union(), and esiaccel.codegen.generator.CppTypeEmitter._emit_window_frame().

◆ _emit_struct()

None esiaccel.codegen.generator.CppTypeEmitter._emit_struct (   self,
IndentedWriter  w,
types.StructType  struct_type 
)
protected
Emit a packed struct as a raw byte buffer with bit-precise accessors.

The struct's storage is a single `std::array<uint8_t, N>` (where `N`
is the byte width derived from the manifest) whose layout matches the
on-wire bit-packing exactly. Per-field accessors (generated below)
read/write the bits so the wire format does not depend on C++ bit-field
allocation rules, which differ between the Itanium ABI (GCC/Clang) and MSVC.

Definition at line 1598 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._compute_field_bit_offsets(), esiaccel.codegen.generator.CppTypeEmitter._cpp_type(), esiaccel.codegen.generator.CppTypeEmitter._emit_field_accessor(), esiaccel.codegen.generator.CppTypeEmitter._emit_size_assert(), esiaccel.codegen.generator.CppTypeEmitter._safe_byte_width(), and esiaccel.codegen.generator.CppTypeEmitter.type_id_map.

Referenced by esiaccel.codegen.generator.CppTypeEmitter.write_header().

◆ _emit_union()

None esiaccel.codegen.generator.CppTypeEmitter._emit_union (   self,
IndentedWriter  w,
types.UnionType  union_type 
)
protected
Emit a union as a raw byte buffer with per-variant accessors.

The union's storage is a single `std::array<uint8_t, N>` sized to the
widest variant. Each variant starts at bit zero, matching the hw.union
bitcast layout. Accessors use the exact member bit width and preserve
bits outside that member.

Definition at line 1663 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._cpp_type(), esiaccel.codegen.generator.CppTypeEmitter._emit_field_accessor(), esiaccel.codegen.generator.CppTypeEmitter._emit_size_assert(), esiaccel.codegen.generator.CppTypeEmitter._field_byte_width(), and esiaccel.codegen.generator.CppTypeEmitter.type_id_map.

Referenced by esiaccel.codegen.generator.CppTypeEmitter.write_header().

◆ _emit_unpack()

None esiaccel.codegen.generator.CppTypeEmitter._emit_unpack (   self,
IndentedWriter  w,
str  raw_member,
str  dst,
str  off,
types.ESIType  esi_type,
int  depth 
)
protected
Emit statements that read a value of `esi_type` out of `raw_member`
at wire bit offset `off` (a C++ `size_t` expression) into the
already-declared, zero-initialised C++ lvalue `dst`.

Recurses through arrays (one loop per dimension) down to scalar / struct
/ union leaves, which are read with the runtime-offset bit helpers.

Definition at line 1509 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._cpp_type(), esiaccel.codegen.generator.CppTypeEmitter._emit_unpack(), esiaccel.codegen.generator.CppTypeEmitter._is_signed_int_field(), esiaccel.codegen.generator.CppTypeEmitter._is_value_class_type(), esiaccel.codegen.generator.CppTypePlanner._unwrap_aliases(), and esiaccel.codegen.generator.CppTypeEmitter._unwrap_aliases().

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_array_accessor(), and esiaccel.codegen.generator.CppTypeEmitter._emit_unpack().

◆ _emit_view_store()

None esiaccel.codegen.generator.CppTypeEmitter._emit_view_store (   self,
IndentedWriter  w,
str  raw_member,
str  src,
str  off_expr,
int  width 
)
protected
Emit a loop writing the low `width` bits of the view `src` into
`raw_member`, with bit `b` landing at wire bit `off_expr + b`. Shared by
the scalar view-class field setter and the per-element view-array setter.

Definition at line 1221 of file generator.py.

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_field_accessor().

◆ _emit_window()

None esiaccel.codegen.generator.CppTypeEmitter._emit_window (   self,
IndentedWriter  hdr,
types.WindowType  window_type 
)
protected
Emit a SegmentedMessageData helper for a serial list window.

This emitter builds its own pre-indented text, so it uses the writer
purely as a verbatim `hdr.write(...)` sink. The nested frame structs,
however, are produced by the line-based `_emit_window_frame`, so their
calls are wrapped in `hdr.indented()` to place them at the window
class's member indent.

Definition at line 1761 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._analyze_window(), esiaccel.codegen.generator.CppTypeEmitter._compute_window_frame_layout(), esiaccel.codegen.generator.CppTypeEmitter._emit_window_data_accessors(), esiaccel.codegen.generator.CppTypeEmitter._emit_window_deserializer(), esiaccel.codegen.generator.CppTypeEmitter._emit_window_frame(), and esiaccel.codegen.generator.CppTypeEmitter._format_window_ctor_param().

Referenced by esiaccel.codegen.generator.CppTypeEmitter.write_header().

◆ _emit_window_data_accessors()

None esiaccel.codegen.generator.CppTypeEmitter._emit_window_data_accessors (   self,
IndentedWriter  hdr,
Dict[str, Any]  info 
)
protected
Emit accessors for the header and data fields of a window helper.

Exposes each static header field as a scalar accessor, the count of data
frames, and one vector-valued accessor per data field so decoded values
are easy to inspect on the read side.

Definition at line 1909 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._cpp_type().

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_window().

◆ _emit_window_deserializer()

None esiaccel.codegen.generator.CppTypeEmitter._emit_window_deserializer (   self,
IndentedWriter  hdr,
Dict[str, Any]  info 
)
protected
Emit a few bridge helpers + a `TypeDeserializer` alias.

The actual decoder lives in `esi::SerialListTypeDeserializer<T>`, which
walks the header/data/footer burst protocol generically. Each window
helper only has to expose:

  - `_headerCount(const header_frame &)` -> `count_type`
  - `_fromFrames(const header_frame &, std::vector<data_frame> &&)`
    -> `std::unique_ptr<T>`

plus a `friend class esi::SerialListTypeDeserializer<T>;` so the template
can reach the (private) `header_frame` definition.

Definition at line 1967 of file generator.py.

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_window().

◆ _emit_window_frame()

None esiaccel.codegen.generator.CppTypeEmitter._emit_window_frame (   self,
IndentedWriter  w,
str  frame_name,
int  frame_bytes,
List[Tuple[str, types.ESIType, int, int]]  layout 
)
protected
Emit a window header/data frame as a raw-bytes struct with accessors.

Nested inside the window helper class, it uses the same accessor pattern
as top-level structs/unions: a private `_bytes` array plus per-field
getter/setter pairs returning `frame_name &` to allow chaining.

Definition at line 1741 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._emit_field_accessor(), and esiaccel.codegen.generator.CppTypeEmitter._emit_size_assert().

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_window().

◆ _field_byte_width()

int esiaccel.codegen.generator.CppTypeEmitter._field_byte_width (   self,
types.ESIType  field_type 
)
protected
Compute the byte width of a field type, rounding up to full bytes.

Definition at line 1069 of file generator.py.

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_union().

◆ _format_window_ctor_param()

str esiaccel.codegen.generator.CppTypeEmitter._format_window_ctor_param (   self,
str  field_name,
types.ESIType  field_type 
)
protected
Emit a constructor parameter for generated window helpers.

Small scalar header fields are cheaper to pass by value than by reference.
Larger aggregates stay as const references.

Definition at line 1054 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._cpp_type(), esiaccel.codegen.generator.CppTypeEmitter._is_value_class_type(), esiaccel.codegen.generator.CppTypePlanner._unwrap_aliases(), and esiaccel.codegen.generator.CppTypeEmitter._unwrap_aliases().

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_window().

◆ _get_bitvector_str()

str esiaccel.codegen.generator.CppTypeEmitter._get_bitvector_str (   self,
types.ESIType  type 
)
protected
Get the textual code for the C++ type used to represent an integer
field's value at the API boundary.

Integers up to 64 bits map to the native `int{N}_t` / `uint{N}_t`
(or `bool` for a single bit) storage types so common scalars stay
zero-overhead, behave identically to plain C ints, and stay valid as
template parameters for the existing `TypedReadPort<T>` /
`TypedWritePort<T>` / `TypedFunction<...>` machinery.

Wider integers (signed > 64 bits, unsigned > 64 bits, or any
`BitsType` > 64 bits) fall back to the non-owning view classes from
`esi/Values.h`: `esi::BitVector` for `BitsType`, `esi::IntView` for
signed integers, `esi::UIntView` for unsigned. All three are
non-owning views over the parent struct's bytes, so generated
getters are zero-allocation; see the lifetime note on `BitVector`
and at the top of the generated header.

Definition at line 918 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._storage_type().

Referenced by esiaccel.codegen.generator.CppTypeEmitter._cpp_type().

◆ _is_signed_int_field()

bool esiaccel.codegen.generator.CppTypeEmitter._is_signed_int_field (   self,
types.ESIType  field_type 
)
protected

◆ _is_value_class_type()

bool esiaccel.codegen.generator.CppTypeEmitter._is_value_class_type (   self,
types.ESIType  field_type 
)
protected

◆ _safe_byte_width()

Optional[int] esiaccel.codegen.generator.CppTypeEmitter._safe_byte_width (   self,
types.ESIType  esi_type 
)
protected
Return the bounded byte width of `esi_type`, or `None` if it has no
well-defined static size (e.g. unbounded `!esi.any` or recursive types).

Definition at line 1073 of file generator.py.

Referenced by esiaccel.codegen.generator.CppTypeEmitter._emit_struct().

◆ _std_array_type()

str esiaccel.codegen.generator.CppTypeEmitter._std_array_type (   self,
types.ArrayType  array_type 
)
protected
Return the equivalent nested `std::array<...>` type for an array.

`std::array<T, N>` is layout-compatible in practice with `T[N]` on every
major implementation (and identical under `#pragma pack(1)`), so the
generator uses it everywhere a fixed-size array would appear.  This keeps
field/value/ctor types storable in `std::vector` and assignable with `=`.

Definition at line 993 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._array_base_and_dims().

Referenced by esiaccel.codegen.generator.CppTypeEmitter._cpp_type().

◆ _storage_type()

str esiaccel.codegen.generator.CppTypeEmitter._storage_type (   self,
int  bit_width,
bool  signed 
)
protected
Get the textual code for a native byte-addressable integer storage
type. Only valid for widths 1..64; wider integers are handled by
`_get_bitvector_str` via the `esi::IntView` / `esi::UIntView` view
classes.

Definition at line 948 of file generator.py.

Referenced by esiaccel.codegen.generator.CppTypeEmitter._analyze_window(), and esiaccel.codegen.generator.CppTypeEmitter._get_bitvector_str().

◆ _unwrap_aliases()

types.ESIType esiaccel.codegen.generator.CppTypeEmitter._unwrap_aliases (   self,
types.ESIType  wrapped 
)
protected

◆ type_identifier()

str esiaccel.codegen.generator.CppTypeEmitter.type_identifier (   self,
types.ESIType  type 
)
Get the C++ type string for an ESI type.

Definition at line 909 of file generator.py.

References esiaccel.codegen.generator.CppTypeEmitter._cpp_type().

◆ write_header()

None esiaccel.codegen.generator.CppTypeEmitter.write_header (   self,
Path  output_dir,
str  system_name 
)

Member Data Documentation

◆ has_cycle

esiaccel.codegen.generator.CppTypeEmitter.has_cycle

◆ ordered_types

esiaccel.codegen.generator.CppTypeEmitter.ordered_types

◆ skipped_types

esiaccel.codegen.generator.CppTypeEmitter.skipped_types

◆ type_id_map

esiaccel.codegen.generator.CppTypeEmitter.type_id_map

The documentation for this class was generated from the following file: