CIRCT 23.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/// Bit vectors include signed, unsigned, and signless integers.
193class BitVectorType : public Type {
194public:
195 BitVectorType(const ID &id, uint64_t width) : Type(id), width(width) {}
196
197 uint64_t getWidth() const { return width; }
198 std::ptrdiff_t getBitWidth() const override { return getWidth(); };
199
200private:
201 uint64_t width;
202};
203
204/// Bits are just an array of bits. They are not interpreted as a number but are
205/// identified in the manifest as "signless" ints.
206class BitsType : public BitVectorType {
207public:
209 using Type::deserialize;
210
211 void ensureValid(const std::any &obj) const override;
212 MutableBitVector serialize(const std::any &obj) const override;
213 std::any deserialize(BitVector &data) const override;
214};
215
216/// Integers are bit vectors which may be signed or unsigned and are interpreted
217/// as numbers.
219public:
221};
222
223/// Signed integer.
224class SIntType : public IntegerType {
225public:
226 using IntegerType::IntegerType;
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/// Unsigned integer.
235class UIntType : public IntegerType {
236public:
237 using IntegerType::IntegerType;
238 using Type::deserialize;
239
240 void ensureValid(const std::any &obj) const override;
241 MutableBitVector serialize(const std::any &obj) const override;
242 std::any deserialize(BitVector &data) const override;
243};
244
245/// Structs are an ordered collection of fields, each with a name and a type.
246class StructType : public Type {
247public:
248 using FieldVector = std::vector<std::pair<std::string, const Type *>>;
249 using Type::deserialize;
250
251 StructType(const ID &id, const FieldVector &fields, bool reverse = true)
253
254 const FieldVector &getFields() const { return fields; }
255 std::ptrdiff_t getBitWidth() const override {
256 std::ptrdiff_t size = 0;
257 for (auto [name, ty] : getFields()) {
258 std::ptrdiff_t fieldSize = ty->getBitWidth();
259 if (fieldSize < 0)
260 return -1;
261 size += fieldSize;
262 }
263 return size;
264 }
265
266 void ensureValid(const std::any &obj) const override;
267 MutableBitVector serialize(const std::any &obj) const override;
268 std::any deserialize(BitVector &data) const override;
269
270 // Returns whether this struct type should be reversed when
271 // serializing/deserializing.
272 // By default, a truthy value here makes StructType's compatible with system
273 // verilog, which has reversed struct field ordering, wrt. C/software struct
274 // ordering.
275 bool isReverse() const { return reverse; }
276
277private:
280};
281
282/// Arrays have a compile time specified (static) size and an element type.
283class ArrayType : public Type {
284public:
285 ArrayType(const ID &id, const Type *elementType, uint64_t size,
286 bool reverse = true)
288 using Type::deserialize;
289
290 const Type *getElementType() const { return elementType; }
291 uint64_t getSize() const { return size; }
292 bool isReverse() const { return reverse; }
293 std::ptrdiff_t getBitWidth() const override {
294 std::ptrdiff_t elementSize = elementType->getBitWidth();
295 if (elementSize < 0)
296 return -1;
297 return elementSize * size;
298 }
299
300 void ensureValid(const std::any &obj) const override;
301 MutableBitVector serialize(const std::any &obj) const override;
302 std::any deserialize(BitVector &data) const override;
303
304private:
306 uint64_t size;
307 // 'reverse' controls whether array elements are reversed during
308 // serialization/deserialization (to match SystemVerilog/Python ordering
309 // expectations).
311};
312
313/// Windows represent a fixed-size sliding window over a stream of data.
314/// They define an "into" type (the data structure being windowed) and a
315/// "loweredType" (the hardware representation including control signals).
316class WindowType : public Type {
317public:
318 /// Field information describing a field within a frame.
319 struct Field {
320 std::string name;
321 uint64_t numItems = 0; // 0 means not specified (use all items)
322 uint64_t bulkCountWidth = 0; // 0 means parallel encoding, >0 means serial
323 };
324
325 /// Frame information describing which fields are included in a particular
326 /// frame.
327 struct Frame {
328 std::string name;
329 std::vector<Field> fields;
330 };
331
332 WindowType(const ID &id, const std::string &name, const Type *intoType,
333 const Type *loweredType, const std::vector<Frame> &frames)
335 frames(frames) {}
336
337 const std::string &getName() const { return name; }
338 const Type *getIntoType() const { return intoType; }
339 const Type *getLoweredType() const { return loweredType; }
340 const std::vector<Frame> &getFrames() const { return frames; }
341
342 std::ptrdiff_t getBitWidth() const override {
343 return loweredType->getBitWidth();
344 }
345
346private:
347 std::string name;
350 std::vector<Frame> frames;
351};
352
353/// Unions are a tagged collection of fields where only one field is active
354/// at a time. All fields share the same bit range (the width is the max of
355/// all field widths, matching SystemVerilog packed-union semantics).
356class UnionType : public Type {
357public:
358 using FieldVector = std::vector<std::pair<std::string, const Type *>>;
359 using Type::deserialize;
360
361 UnionType(const ID &id, const FieldVector &fields)
362 : Type(id), fields(fields) {}
363
364 const FieldVector &getFields() const { return fields; }
365 std::ptrdiff_t getBitWidth() const override {
366 std::ptrdiff_t maxWidth = 0;
367 for (auto [name, ty] : getFields()) {
368 std::ptrdiff_t fieldWidth = ty->getBitWidth();
369 if (fieldWidth < 0)
370 return -1;
371 maxWidth = std::max(maxWidth, fieldWidth);
372 }
373 return maxWidth;
374 }
375
376 void ensureValid(const std::any &obj) const override;
377 MutableBitVector serialize(const std::any &obj) const override;
378 std::any deserialize(BitVector &data) const override;
379
380private:
382};
383
384/// Lists represent variable-length sequences of elements of a single type.
385/// Unlike arrays which have a fixed size, lists can have any length.
386class ListType : public Type {
387public:
388 ListType(const ID &id, const Type *elementType)
390
391 const Type *getElementType() const { return elementType; }
392
393 std::ptrdiff_t getBitWidth() const override { return -1; }
394
395private:
397};
398
399} // namespace esi
400
401#endif // ESI_TYPES_H
assert(baseType &&"element must be base type")
The "any" type is a special type which can be used to represent any type, as identified by the type i...
Definition Types.h:159
std::ptrdiff_t getBitWidth() const override
Definition Types.h:162
AnyType(const ID &id)
Definition Types.h:161
Arrays have a compile time specified (static) size and an element type.
Definition Types.h:283
std::ptrdiff_t getBitWidth() const override
Definition Types.h:293
uint64_t size
Definition Types.h:306
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:310
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:433
const Type * elementType
Definition Types.h:305
const Type * getElementType() const
Definition Types.h:290
ArrayType(const ID &id, const Type *elementType, uint64_t size, bool reverse=true)
Definition Types.h:285
uint64_t getSize() const
Definition Types.h:291
bool isReverse() const
Definition Types.h:292
Bit vectors include signed, unsigned, and signless integers.
Definition Types.h:193
BitVectorType(const ID &id, uint64_t width)
Definition Types.h:195
uint64_t width
Definition Types.h:201
std::ptrdiff_t getBitWidth() const override
Definition Types.h:198
uint64_t getWidth() const
Definition Types.h:197
A lightweight, non-owning bit vector view backed by a byte array span.
Definition Values.h:42
Bits are just an array of bits.
Definition Types.h:206
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:189
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
Bundles represent a collection of channels.
Definition Types.h:104
BundleType(const ID &id, const ChannelVector &channels)
Definition Types.h:111
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::vector< std::tuple< std::string, Direction, const Type * > > ChannelVector
Definition Types.h:109
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:218
Lists represent variable-length sequences of elements of a single type.
Definition Types.h:386
ListType(const ID &id, const Type *elementType)
Definition Types.h:388
std::ptrdiff_t getBitWidth() const override
Definition Types.h:393
const Type * elementType
Definition Types.h:396
const Type * getElementType() const
Definition Types.h:391
A concrete flat message backed by a single vector of bytes.
Definition Common.h:155
A mutable bit vector that owns its underlying storage.
Definition Values.h:185
Signed integer.
Definition Types.h:224
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
Structs are an ordered collection of fields, each with a name and a type.
Definition Types.h:246
bool isReverse() const
Definition Types.h:275
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:325
std::vector< std::pair< std::string, const Type * > > FieldVector
Definition Types.h:248
FieldVector fields
Definition Types.h:278
std::ptrdiff_t getBitWidth() const override
Definition Types.h:255
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:251
const FieldVector & getFields() const
Definition Types.h:254
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:235
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
Unions are a tagged collection of fields where only one field is active at a time.
Definition Types.h:356
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:361
std::vector< std::pair< std::string, const Type * > > FieldVector
Definition Types.h:358
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:500
const FieldVector & getFields() const
Definition Types.h:364
std::ptrdiff_t getBitWidth() const override
Definition Types.h:365
FieldVector fields
Definition Types.h:381
The "void" type is a special type which can be used to represent no type.
Definition Types.h:141
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
Windows represent a fixed-size sliding window over a stream of data.
Definition Types.h:316
std::ptrdiff_t getBitWidth() const override
Definition Types.h:342
std::vector< Frame > frames
Definition Types.h:350
const std::vector< Frame > & getFrames() const
Definition Types.h:340
const Type * intoType
Definition Types.h:348
std::string name
Definition Types.h:347
const Type * getLoweredType() const
Definition Types.h:339
const std::string & getName() const
Definition Types.h:337
const Type * loweredType
Definition Types.h:349
const Type * getIntoType() const
Definition Types.h:338
WindowType(const ID &id, const std::string &name, const Type *intoType, const Type *loweredType, const std::vector< Frame > &frames)
Definition Types.h:332
Definition esi.py:1
Field information describing a field within a frame.
Definition Types.h:319
uint64_t bulkCountWidth
Definition Types.h:322
std::string name
Definition Types.h:320
Frame information describing which fields are included in a particular frame.
Definition Types.h:327
std::vector< Field > fields
Definition Types.h:329
std::string name
Definition Types.h:328