CIRCT 24.0.0git
Loading...
Searching...
No Matches
Types.h
Go to the documentation of this file.
1//===- Types.h - ESI type system -------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// DO NOT EDIT!
10// This file is distributed as part of an ESI package. The source for this file
11// should always be modified within CIRCT.
12//
13//===----------------------------------------------------------------------===//
14
15// NOLINTNEXTLINE(llvm-header-guard)
16#ifndef ESI_TYPES_H
17#define ESI_TYPES_H
18
19#include <algorithm>
20#include <any>
21#include <cassert>
22#include <cstdint>
23#include <map>
24#include <span>
25#include <stdexcept>
26#include <string>
27#include <utility>
28#include <vector>
29
30#include "esi/Common.h"
31#include "esi/Values.h" // For BitVector / Int / UInt
32
33namespace esi {
34
35/// Root class of the ESI type system.
36class Type {
37public:
38 using ID = std::string;
39 Type(const ID &id) : id(id) {}
40 virtual ~Type() = default;
41
42 ID getID() const { return id; }
43 virtual std::ptrdiff_t getBitWidth() const { return hwBitwidth; }
44
45 /// Set from manifest JSON hwBitwidth. Allows types without specialized
46 /// parsers (e.g. union types) to still report their width.
47 void setHWBitwidth(std::ptrdiff_t bw) { hwBitwidth = bw; }
48
49 /// Serialize an object to a MutableBitVector (LSB-first stream). The object
50 /// should be passed via std::any. Implementations append fields in the order
51 /// they are iterated (the first serialized field occupies the
52 /// least-significant bits of the result).
53 virtual MutableBitVector serialize(const std::any &obj) const {
54 throw std::runtime_error("Serialization not implemented for type " + id);
55 }
56
57 /// Deserialize from a BitVector stream (LSB-first). Implementations consume
58 /// bits from 'data' in-place (via logical right shifts) and return the
59 /// reconstructed value. Remaining bits stay in 'data'.
60 virtual std::any deserialize(BitVector &data) const {
61 throw std::runtime_error("Deserialization not implemented for type " + id);
62 }
63
64 // Deserialize from a MessageData buffer. Maps the MessageData onto a
65 // MutableBitVector, and proceeds with regular MutableBitVector
66 // deserialization.
67 std::any deserialize(const MessageData &data) const {
68 auto bv = MutableBitVector(std::vector<uint8_t>(data.getData()));
69 return deserialize(bv);
70 }
71
72 /// Ensure that a std::any object is valid for this type. Throws
73 /// std::runtime_error if the object is not valid.
74 virtual void ensureValid(const std::any &obj) const {
75 throw std::runtime_error("Validation not implemented for type " + id);
76 }
77
78 // Check if a std::any object is valid for this type. Returns an optional
79 // error message if the object is not valid, else, std::nullopt.
80 std::optional<std::string> isValid(const std::any &obj) const {
81 try {
82 ensureValid(obj);
83 return std::nullopt;
84 } catch (const std::runtime_error &e) {
85 return e.what();
86 }
87 }
88
89 // Dump a textual representation of this type to the provided stream.
90 void dump(std::ostream &os, bool oneLine = false) const;
91
92 // Return a textual representation of this type.
93 std::string toString(bool oneLine = false) const;
94
95protected:
97 std::ptrdiff_t hwBitwidth = -1;
98};
99
100/// Bundles represent a collection of channels. Services exclusively expose
101/// bundles (sometimes of just one channel). As such, they are the type of
102/// accessible ports on an accelerator, from a host API perspective.
103/// TODO: Add a good description of direction?
104class BundleType : public Type {
105public:
106 enum Direction { To, From };
107
109 std::vector<std::tuple<std::string, Direction, const Type *>>;
110
112 : Type(id), channels(channels) {}
113
114 const ChannelVector &getChannels() const { return channels; }
115 std::ptrdiff_t getBitWidth() const override { return -1; };
116
117 std::pair<const Type *, Direction> findChannel(std::string name) const;
118
119protected:
121};
122
123/// Channels are the basic communication primitives. They are unidirectional and
124/// carry one values of one type.
125class ChannelType : public Type {
126public:
127 using Type::deserialize;
128 ChannelType(const ID &id, const Type *inner) : Type(id), inner(inner) {}
129 const Type *getInner() const { return inner; }
130 std::ptrdiff_t getBitWidth() const override { return inner->getBitWidth(); };
131
132 void ensureValid(const std::any &obj) const override;
133 MutableBitVector serialize(const std::any &obj) const override;
134 std::any deserialize(BitVector &data) const override;
135
136private:
137 const Type *inner;
138};
139
140/// The "void" type is a special type which can be used to represent no type.
141class VoidType : public Type {
142public:
143 using Type::deserialize;
144 VoidType(const ID &id) : Type(id) {}
145 // 'void' carries no data. Transports (e.g. DMA engines, cosim) that require
146 // every message to be at least one byte add a placeholder byte themselves;
147 // the logical type width is 0.
148 std::ptrdiff_t getBitWidth() const override { return 0; };
149
150 void ensureValid(const std::any &obj) const override;
151 MutableBitVector serialize(const std::any &obj) const override;
152 std::any deserialize(BitVector &data) const override;
153};
154
155/// The "any" type is a special type which can be used to represent any type, as
156/// identified by the type id. Said type id is guaranteed to be present in the
157/// manifest. Importantly, the "any" type id over the wire may not be a string
158/// as it is in software.
159class AnyType : public Type {
160public:
161 AnyType(const ID &id) : Type(id) {}
162 std::ptrdiff_t getBitWidth() const override { return -1; };
163};
164
165/// Type aliases provide a named type which forwards to an inner type.
166class TypeAliasType : public Type {
167public:
168 using Type::deserialize;
169
170 TypeAliasType(const ID &id, std::string name, const Type *innerType)
171 : Type(id), name(std::move(name)), innerType(innerType) {
172 assert(innerType != nullptr &&
173 "TypeAliasType must have a non-null inner type");
174 }
175
176 const std::string &getName() const { return name; }
177 const Type *getInnerType() const { return innerType; }
178
179 std::ptrdiff_t getBitWidth() const override {
180 return innerType->getBitWidth();
181 };
182
183 void ensureValid(const std::any &obj) const override;
184 MutableBitVector serialize(const std::any &obj) const override;
185 std::any deserialize(BitVector &data) const override;
186
187private:
188 std::string name;
190};
191
192/// Unwrap TypeAliasType (possibly recursively) to get the underlying type.
193inline const Type *unwrapTypeAlias(const Type *type) {
194 while (auto *alias = dynamic_cast<const TypeAliasType *>(type))
195 type = alias->getInnerType();
196 return type;
197}
198
199/// Unwrap aliases and channels, then cast the payload to T. Returns nullptr
200/// for a null input or a payload that is not a T. Other containers are
201/// retained.
202template <typename T>
203const T *getUnwrappedAs(const Type *type) {
204 type = unwrapTypeAlias(type);
205 while (auto *channel = dynamic_cast<const ChannelType *>(type))
206 type = unwrapTypeAlias(channel->getInner());
207 return dynamic_cast<const T *>(type);
208}
209
210/// Bit vectors include signed, unsigned, and signless integers.
211class BitVectorType : public Type {
212public:
213 BitVectorType(const ID &id, uint64_t width) : Type(id), width(width) {}
214
215 uint64_t getWidth() const { return width; }
216 std::ptrdiff_t getBitWidth() const override { return getWidth(); };
217
218private:
219 uint64_t width;
220};
221
222/// Bits are just an array of bits. They are not interpreted as a number but are
223/// identified in the manifest as "signless" ints.
224class BitsType : public BitVectorType {
225public:
227 using Type::deserialize;
228
229 void ensureValid(const std::any &obj) const override;
230 MutableBitVector serialize(const std::any &obj) const override;
231 std::any deserialize(BitVector &data) const override;
232};
233
234/// Integers are bit vectors which may be signed or unsigned and are interpreted
235/// as numbers.
237public:
239};
240
241/// Signed integer.
242class SIntType : public IntegerType {
243public:
244 using IntegerType::IntegerType;
245 using Type::deserialize;
246
247 void ensureValid(const std::any &obj) const override;
248 MutableBitVector serialize(const std::any &obj) const override;
249 std::any deserialize(BitVector &data) const override;
250};
251
252/// Unsigned integer.
253class UIntType : public IntegerType {
254public:
255 using IntegerType::IntegerType;
256 using Type::deserialize;
257
258 void ensureValid(const std::any &obj) const override;
259 MutableBitVector serialize(const std::any &obj) const override;
260 std::any deserialize(BitVector &data) const override;
261};
262
263/// Structs are an ordered collection of fields, each with a name and a type.
264class StructType : public Type {
265public:
266 using FieldVector = std::vector<std::pair<std::string, const Type *>>;
267 using Type::deserialize;
268
269 StructType(const ID &id, const FieldVector &fields, bool reverse = true)
271
272 const FieldVector &getFields() const { return fields; }
273 std::ptrdiff_t getBitWidth() const override {
274 std::ptrdiff_t size = 0;
275 for (auto [name, ty] : getFields()) {
276 std::ptrdiff_t fieldSize = ty->getBitWidth();
277 if (fieldSize < 0)
278 return -1;
279 size += fieldSize;
280 }
281 return size;
282 }
283
284 void ensureValid(const std::any &obj) const override;
285 MutableBitVector serialize(const std::any &obj) const override;
286 std::any deserialize(BitVector &data) const override;
287
288 // Returns whether this struct type should be reversed when
289 // serializing/deserializing.
290 // By default, a truthy value here makes StructType's compatible with system
291 // verilog, which has reversed struct field ordering, wrt. C/software struct
292 // ordering.
293 bool isReverse() const { return reverse; }
294
295private:
298};
299
300/// Arrays have a compile time specified (static) size and an element type.
301class ArrayType : public Type {
302public:
303 ArrayType(const ID &id, const Type *elementType, uint64_t size,
304 bool reverse = true)
306 using Type::deserialize;
307
308 const Type *getElementType() const { return elementType; }
309 uint64_t getSize() const { return size; }
310 bool isReverse() const { return reverse; }
311 std::ptrdiff_t getBitWidth() const override {
312 std::ptrdiff_t elementSize = elementType->getBitWidth();
313 if (elementSize < 0)
314 return -1;
315 return elementSize * size;
316 }
317
318 void ensureValid(const std::any &obj) const override;
319 MutableBitVector serialize(const std::any &obj) const override;
320 std::any deserialize(BitVector &data) const override;
321
322private:
324 uint64_t size;
325 // 'reverse' controls whether array elements are reversed during
326 // serialization/deserialization (to match SystemVerilog/Python ordering
327 // expectations).
329};
330
331/// Windows represent a fixed-size sliding window over a stream of data.
332/// They define an "into" type (the data structure being windowed) and a
333/// "loweredType" (the hardware representation including control signals).
334class WindowType : public Type {
335public:
336 /// Field information describing a field within a frame.
337 struct Field {
338 std::string name;
339 uint64_t numItems = 0; // 0 means not specified (use all items)
340 uint64_t bulkCountWidth = 0; // 0 means parallel encoding, >0 means serial
341 };
342
343 /// Frame information describing which fields are included in a particular
344 /// frame.
345 struct Frame {
346 std::string name;
347 std::vector<Field> fields;
348 };
349
350 WindowType(const ID &id, const std::string &name, const Type *intoType,
351 const Type *loweredType, const std::vector<Frame> &frames)
353 frames(frames) {}
354
355 const std::string &getName() const { return name; }
356 const Type *getIntoType() const { return intoType; }
357 const Type *getLoweredType() const { return loweredType; }
358 const std::vector<Frame> &getFrames() const { return frames; }
359
360 std::ptrdiff_t getBitWidth() const override {
361 return loweredType->getBitWidth();
362 }
363
364private:
365 std::string name;
368 std::vector<Frame> frames;
369};
370
371/// Unions contain one active field without storing a tag. All fields start at
372/// bit zero, and the width is the maximum field width. Serialization zero-pads
373/// the high bits of narrower fields, matching the hw.union bitcast layout.
374/// Nonzero hw.union member offsets are rejected during manifest generation.
375class UnionType : public Type {
376public:
377 using FieldVector = std::vector<std::pair<std::string, const Type *>>;
378 using Type::deserialize;
379
380 UnionType(const ID &id, const FieldVector &fields)
381 : Type(id), fields(fields) {}
382
383 const FieldVector &getFields() const { return fields; }
384 std::ptrdiff_t getBitWidth() const override {
385 std::ptrdiff_t maxWidth = 0;
386 for (auto [name, ty] : getFields()) {
387 std::ptrdiff_t fieldWidth = ty->getBitWidth();
388 if (fieldWidth < 0)
389 return -1;
390 maxWidth = std::max(maxWidth, fieldWidth);
391 }
392 return maxWidth;
393 }
394
395 void ensureValid(const std::any &obj) const override;
396 MutableBitVector serialize(const std::any &obj) const override;
397 std::any deserialize(BitVector &data) const override;
398
399private:
401};
402
403/// Lists represent variable-length sequences of elements of a single type.
404/// Unlike arrays which have a fixed size, lists can have any length.
405class ListType : public Type {
406public:
407 ListType(const ID &id, const Type *elementType)
409
410 const Type *getElementType() const { return elementType; }
411
412 std::ptrdiff_t getBitWidth() const override { return -1; }
413
414private:
416};
417
418} // namespace esi
419
420#endif // ESI_TYPES_H
assert(baseType &&"element must be base type")
std::ptrdiff_t getBitWidth() const override
Definition Types.h:162
AnyType(const ID &id)
Definition Types.h:161
std::ptrdiff_t getBitWidth() const override
Definition Types.h:311
uint64_t size
Definition Types.h:324
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:414
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:391
bool reverse
Definition Types.h:328
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:433
const Type * elementType
Definition Types.h:323
const Type * getElementType() const
Definition Types.h:308
ArrayType(const ID &id, const Type *elementType, uint64_t size, bool reverse=true)
Definition Types.h:303
uint64_t getSize() const
Definition Types.h:309
bool isReverse() const
Definition Types.h:310
BitVectorType(const ID &id, uint64_t width)
Definition Types.h:213
uint64_t width
Definition Types.h:219
std::ptrdiff_t getBitWidth() const override
Definition Types.h:216
uint64_t getWidth() const
Definition Types.h:215
A lightweight, non-owning bit vector view backed by a byte array span.
Definition Values.h:51
Bits are just an array of bits.
Definition Types.h:224
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:189
BitVectorType(const ID &id, uint64_t width)
Definition Types.h:213
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:210
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:204
BundleType(const ID &id, const ChannelVector &channels)
Definition Types.h:111
std::vector< std::tuple< std::string, Direction, const Type * > > ChannelVector
Definition Types.h:108
std::ptrdiff_t getBitWidth() const override
Definition Types.h:115
const ChannelVector & getChannels() const
Definition Types.h:114
ChannelVector channels
Definition Types.h:120
std::pair< const Type *, Direction > findChannel(std::string name) const
Definition Types.cpp:127
Channels are the basic communication primitives.
Definition Types.h:125
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:135
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:139
std::ptrdiff_t getBitWidth() const override
Definition Types.h:130
ChannelType(const ID &id, const Type *inner)
Definition Types.h:128
const Type * getInner() const
Definition Types.h:129
const Type * inner
Definition Types.h:137
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:143
Integers are bit vectors which may be signed or unsigned and are interpreted as numbers.
Definition Types.h:236
BitVectorType(const ID &id, uint64_t width)
Definition Types.h:213
ListType(const ID &id, const Type *elementType)
Definition Types.h:407
std::ptrdiff_t getBitWidth() const override
Definition Types.h:412
const Type * elementType
Definition Types.h:415
const Type * getElementType() const
Definition Types.h:410
A concrete flat message backed by a single vector of bytes.
Definition Common.h:197
A mutable bit vector that owns its underlying storage.
Definition Values.h:278
Signed integer.
Definition Types.h:242
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:283
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:272
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:262
bool isReverse() const
Definition Types.h:293
std::vector< std::pair< std::string, const Type * > > FieldVector
Definition Types.h:266
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:325
FieldVector fields
Definition Types.h:296
std::ptrdiff_t getBitWidth() const override
Definition Types.h:273
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:353
StructType(const ID &id, const FieldVector &fields, bool reverse=true)
Definition Types.h:269
const FieldVector & getFields() const
Definition Types.h:272
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:374
Type aliases provide a named type which forwards to an inner type.
Definition Types.h:166
std::ptrdiff_t getBitWidth() const override
Definition Types.h:179
const Type * innerType
Definition Types.h:189
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:177
TypeAliasType(const ID &id, std::string name, const Type *innerType)
Definition Types.h:170
std::string name
Definition Types.h:188
const Type * getInnerType() const
Definition Types.h:177
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:185
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:181
const std::string & getName() const
Definition Types.h:176
Root class of the ESI type system.
Definition Types.h:36
ID id
Definition Types.h:96
virtual void ensureValid(const std::any &obj) const
Ensure that a std::any object is valid for this type.
Definition Types.h:74
virtual ~Type()=default
std::string toString(bool oneLine=false) const
Definition Types.cpp:120
Type(const ID &id)
Definition Types.h:39
virtual std::ptrdiff_t getBitWidth() const
Definition Types.h:43
void setHWBitwidth(std::ptrdiff_t bw)
Set from manifest JSON hwBitwidth.
Definition Types.h:47
std::any deserialize(const MessageData &data) const
Definition Types.h:67
std::string ID
Definition Types.h:38
virtual std::any deserialize(BitVector &data) const
Deserialize from a BitVector stream (LSB-first).
Definition Types.h:60
ID getID() const
Definition Types.h:42
std::optional< std::string > isValid(const std::any &obj) const
Definition Types.h:80
virtual MutableBitVector serialize(const std::any &obj) const
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.h:53
void dump(std::ostream &os, bool oneLine=false) const
Definition Types.cpp:115
std::ptrdiff_t hwBitwidth
Definition Types.h:97
Unsigned integer.
Definition Types.h:253
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:314
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:304
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:294
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:475
UnionType(const ID &id, const FieldVector &fields)
Definition Types.h:380
std::vector< std::pair< std::string, const Type * > > FieldVector
Definition Types.h:377
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:445
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:493
const FieldVector & getFields() const
Definition Types.h:383
std::ptrdiff_t getBitWidth() const override
Definition Types.h:384
FieldVector fields
Definition Types.h:400
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:163
VoidType(const ID &id)
Definition Types.h:144
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:147
std::ptrdiff_t getBitWidth() const override
Definition Types.h:148
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:170
std::ptrdiff_t getBitWidth() const override
Definition Types.h:360
std::vector< Frame > frames
Definition Types.h:368
const std::vector< Frame > & getFrames() const
Definition Types.h:358
const Type * intoType
Definition Types.h:366
std::string name
Definition Types.h:365
const Type * getLoweredType() const
Definition Types.h:357
const std::string & getName() const
Definition Types.h:355
const Type * loweredType
Definition Types.h:367
const Type * getIntoType() const
Definition Types.h:356
WindowType(const ID &id, const std::string &name, const Type *intoType, const Type *loweredType, const std::vector< Frame > &frames)
Definition Types.h:350
Definition esi.py:1
const T * getUnwrappedAs(const Type *type)
Unwrap aliases and channels, then cast the payload to T.
Definition Types.h:203
const Type * unwrapTypeAlias(const Type *type)
Unwrap TypeAliasType (possibly recursively) to get the underlying type.
Definition Types.h:193
Field information describing a field within a frame.
Definition Types.h:337
uint64_t bulkCountWidth
Definition Types.h:340
std::string name
Definition Types.h:338
Frame information describing which fields are included in a particular frame.
Definition Types.h:345
std::vector< Field > fields
Definition Types.h:347
std::string name
Definition Types.h:346