CIRCT 23.0.0git
Loading...
Searching...
No Matches
Public Member Functions | Public Attributes | Protected Member Functions | List of all members
esiaccel.codegen.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)
 
int _type_byte_width (self, types.ESIType wrapped)
 
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, TextIO hdr, str type_name, Optional[int] expected_bytes, str indent="")
 
 _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)
 
bool _is_byte_packable (self, types.ESIType esi_type)
 
None _emit_field_accessor (self, TextIO hdr, str indent, str raw_member, str self_type, str field_name, types.ESIType field_type, int bit_offset, int bit_width)
 
str _ctor_param_type (self, types.ESIType field_type)
 
None _emit_struct (self, TextIO hdr, types.StructType struct_type)
 
None _emit_union (self, TextIO hdr, types.UnionType union_type)
 
 _compute_window_frame_layout (self, fields, pad_bytes, count_type_synth)
 
None _emit_window_frame (self, TextIO hdr, str frame_name, int frame_bytes, layout)
 
None _emit_window (self, TextIO hdr, types.WindowType window_type)
 
None _emit_window_data_accessors (self, TextIO hdr, info)
 
None _emit_window_deserializer (self, TextIO hdr, info)
 
None _emit_alias (self, TextIO hdr, types.TypeAlias alias_type)
 

Detailed Description

Emit C++ headers from precomputed type ordering.

Definition at line 1092 of file codegen.py.

Constructor & Destructor Documentation

◆ __init__()

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

Member Function Documentation

◆ _analyze_window()

esiaccel.codegen.CppTypeEmitter._analyze_window (   self,
types.WindowType  window_type 
)
protected

◆ _array_base_and_dims()

Tuple[str, List[int]] esiaccel.codegen.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 1180 of file codegen.py.

References esiaccel.codegen.CppTypeEmitter._cpp_type().

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

◆ _compute_field_bit_offsets()

Tuple[Dict[str, int], int] esiaccel.codegen.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 1390 of file codegen.py.

References esiaccel.codegen.CppTypeEmitter._cpp_type().

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

◆ _compute_window_frame_layout()

esiaccel.codegen.CppTypeEmitter._compute_window_frame_layout (   self,
  fields,
  pad_bytes,
  count_type_synth 
)
protected
Compute (name, type, byte_offset, bit_width) for each window frame field.

Fields are listed in C++ declaration order. They start after `pad_bytes`
bytes of padding and each field consumes `ceil(bit_width/8)` bytes —
matching what the `#pragma pack(1)` layout produced.

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

Definition at line 2079 of file codegen.py.

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

◆ _cpp_string_literal()

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

Definition at line 1105 of file codegen.py.

◆ _cpp_type()

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

◆ _ctor_param_type()

str esiaccel.codegen.CppTypeEmitter._ctor_param_type (   self,
types.ESIType  field_type 
)
protected
Return the C++ constructor-parameter type for a setter call.

Definition at line 1959 of file codegen.py.

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

◆ _emit_alias()

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

Definition at line 2325 of file codegen.py.

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

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

◆ _emit_field_accessor()

None esiaccel.codegen.CppTypeEmitter._emit_field_accessor (   self,
TextIO  hdr,
str  indent,
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 four inline strategies,
fastest first:

  * Path A — 8/16/32/64-bit fields at a byte-aligned offset. Read/write
    via a `reinterpret_cast` through the underlying `std::array<uint8_t>`,
    matching the same aliasing pattern the runtime already relies on in
    `MessageData::from<T>()` / `MessageData::as<T>()`.
  * Path B — byte-aligned offset and width but a non-standard width
    (e.g. `i24`, `i48`). Read each byte directly out of `_bytes` and
    OR-shift them together (and the reverse on write — split the
    value out one byte at a time). Signed fields read into the
    matching unsigned, then sign-extend before returning.
  * Path C — sub-byte alignment. Fall back to the
    `esi::detail::{read,write}{Un,}signedBits` helpers from
    `esi/BitAccess.h`, which loop over the constituent bits.
  * Path D — 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 via `copyBitsOut`. The
    returned view dangles when the parent buffer dies; see the
    lifetime warning at the top of the generated header.

Definition at line 1447 of file codegen.py.

References esiaccel.codegen.CppTypeEmitter._cpp_type(), esiaccel.codegen.CppTypeEmitter._field_byte_width(), esiaccel.codegen.CppTypeEmitter._is_byte_packable(), esiaccel.codegen.CppTypeEmitter._is_signed_int_field(), esiaccel.codegen.CppTypeEmitter._is_value_class_type(), esiaccel.codegen.CppTypePlanner._unwrap_aliases(), and esiaccel.codegen.CppTypeEmitter._unwrap_aliases().

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

◆ _emit_size_assert()

None esiaccel.codegen.CppTypeEmitter._emit_size_assert (   self,
TextIO  hdr,
str  type_name,
Optional[int]  expected_bytes,
str   indent = "" 
)
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 1283 of file codegen.py.

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

◆ _emit_struct()

None esiaccel.codegen.CppTypeEmitter._emit_struct (   self,
TextIO  hdr,
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 1967 of file codegen.py.

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

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

◆ _emit_union()

None esiaccel.codegen.CppTypeEmitter._emit_union (   self,
TextIO  hdr,
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 lives at the MSB end of the buffer
(matching the existing SV-style packed union layout where padding
occupies the lower bytes), so the byte offset for a variant of size
V is `union_bytes - V`. Sub-byte integer variants are byte-padded to
full bytes within that region, matching the Python runtime's union
serialization.

Definition at line 2032 of file codegen.py.

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

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

◆ _emit_window()

None esiaccel.codegen.CppTypeEmitter._emit_window (   self,
TextIO  hdr,
types.WindowType  window_type 
)
protected

◆ _emit_window_data_accessors()

None esiaccel.codegen.CppTypeEmitter._emit_window_data_accessors (   self,
TextIO  hdr,
  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 2225 of file codegen.py.

References esiaccel.codegen.CppTypeEmitter._cpp_type().

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

◆ _emit_window_deserializer()

None esiaccel.codegen.CppTypeEmitter._emit_window_deserializer (   self,
TextIO  hdr,
  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 2280 of file codegen.py.

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

◆ _emit_window_frame()

None esiaccel.codegen.CppTypeEmitter._emit_window_frame (   self,
TextIO  hdr,
str  frame_name,
int  frame_bytes,
  layout 
)
protected
Emit a window header/data frame as a raw-bytes struct with accessors.

Nested inside the window helper class (`indent` = 2 spaces) and uses
the same B3 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 2099 of file codegen.py.

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

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

◆ _field_byte_width()

int esiaccel.codegen.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 1267 of file codegen.py.

Referenced by esiaccel.codegen.CppTypeEmitter._emit_field_accessor(), and esiaccel.codegen.CppTypeEmitter._emit_union().

◆ _format_window_ctor_param()

str esiaccel.codegen.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 1252 of file codegen.py.

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

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

◆ _get_bitvector_str()

str esiaccel.codegen.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 1110 of file codegen.py.

References esiaccel.codegen.CppTypeEmitter._storage_type().

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

◆ _is_byte_packable()

bool esiaccel.codegen.CppTypeEmitter._is_byte_packable (   self,
types.ESIType  esi_type 
)
protected
True if the type's in-memory C++ layout is byte-for-byte identical to
its on-wire bit layout, so a flat per-byte copy round-trips it correctly.

This holds only when every scalar leaf occupies a whole number of bytes
that exactly matches its native storage size:

  * an integer / bits type whose width is one of the native storage
    widths (8/16/32/64). `ui3`, `si5`, a 1-bit `bool`, and even `ui24`
    (stored in a wider `uint32_t`) all have storage wider than their
    wire width and are therefore *not* byte-packable.
  * a struct / union whose total width is a whole number of bytes -- its
    `_bytes` buffer already mirrors the wire layout.
  * an array whose element type is itself byte-packable, so successive
    elements share the same byte stride on the wire and in memory.

Anything that is not byte-packable must be (un)packed element-by-element
from its individual wire bit offset rather than flat-copied.

Definition at line 1418 of file codegen.py.

References esiaccel.codegen.CppTypeEmitter._is_byte_packable(), esiaccel.codegen.CppTypePlanner._unwrap_aliases(), and esiaccel.codegen.CppTypeEmitter._unwrap_aliases().

Referenced by esiaccel.codegen.CppTypeEmitter._emit_field_accessor(), and esiaccel.codegen.CppTypeEmitter._is_byte_packable().

◆ _is_signed_int_field()

bool esiaccel.codegen.CppTypeEmitter._is_signed_int_field (   self,
types.ESIType  field_type 
)
protected
True if the field is a signed integer (only `IntType`, not `UIntType`
or `BitsType`).

Definition at line 1411 of file codegen.py.

References esiaccel.codegen.CppTypePlanner._unwrap_aliases(), and esiaccel.codegen.CppTypeEmitter._unwrap_aliases().

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

◆ _is_value_class_type()

bool esiaccel.codegen.CppTypeEmitter._is_value_class_type (   self,
types.ESIType  field_type 
)
protected
True if the C++ representation of this integer field is one of
the `esi::{BitVector,IntView,UIntView}` view classes from
`esi/Values.h` rather than a native integer.

Definition at line 1164 of file codegen.py.

References esiaccel.codegen.CppTypePlanner._unwrap_aliases(), and esiaccel.codegen.CppTypeEmitter._unwrap_aliases().

Referenced by esiaccel.codegen.CppTypeEmitter._emit_field_accessor(), and esiaccel.codegen.CppTypeEmitter._format_window_ctor_param().

◆ _safe_byte_width()

Optional[int] esiaccel.codegen.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 1271 of file codegen.py.

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

◆ _std_array_type()

str esiaccel.codegen.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 1191 of file codegen.py.

References esiaccel.codegen.CppTypeEmitter._array_base_and_dims().

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

◆ _storage_type()

str esiaccel.codegen.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 1140 of file codegen.py.

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

◆ _type_byte_width()

int esiaccel.codegen.CppTypeEmitter._type_byte_width (   self,
types.ESIType  wrapped 
)
protected
Return the size of a fixed-width type in bytes.

Definition at line 1174 of file codegen.py.

Referenced by esiaccel.codegen.CppTypeEmitter._analyze_window().

◆ _unwrap_aliases()

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

◆ type_identifier()

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

Definition at line 1101 of file codegen.py.

References esiaccel.codegen.CppTypeEmitter._cpp_type().

◆ write_header()

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

Member Data Documentation

◆ has_cycle

esiaccel.codegen.CppTypeEmitter.has_cycle

Definition at line 1099 of file codegen.py.

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

◆ ordered_types

esiaccel.codegen.CppTypeEmitter.ordered_types

◆ skipped_types

esiaccel.codegen.CppTypeEmitter.skipped_types

◆ type_id_map

esiaccel.codegen.CppTypeEmitter.type_id_map

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