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' is 1 bit by convention.
146 std::ptrdiff_t getBitWidth() const override { return 1; };
147
148 void ensureValid(const std::any &obj) const override;
149 MutableBitVector serialize(const std::any &obj) const override;
150 std::any deserialize(BitVector &data) const override;
151};
152
153/// The "any" type is a special type which can be used to represent any type, as
154/// identified by the type id. Said type id is guaranteed to be present in the
155/// manifest. Importantly, the "any" type id over the wire may not be a string
156/// as it is in software.
157class AnyType : public Type {
158public:
159 AnyType(const ID &id) : Type(id) {}
160 std::ptrdiff_t getBitWidth() const override { return -1; };
161};
162
163/// Type aliases provide a named type which forwards to an inner type.
164class TypeAliasType : public Type {
165public:
166 using Type::deserialize;
167
168 TypeAliasType(const ID &id, std::string name, const Type *innerType)
169 : Type(id), name(std::move(name)), innerType(innerType) {
170 assert(innerType != nullptr &&
171 "TypeAliasType must have a non-null inner type");
172 }
173
174 const std::string &getName() const { return name; }
175 const Type *getInnerType() const { return innerType; }
176
177 std::ptrdiff_t getBitWidth() const override {
178 return innerType->getBitWidth();
179 };
180
181 void ensureValid(const std::any &obj) const override;
182 MutableBitVector serialize(const std::any &obj) const override;
183 std::any deserialize(BitVector &data) const override;
184
185private:
186 std::string name;
188};
189
190/// Bit vectors include signed, unsigned, and signless integers.
191class BitVectorType : public Type {
192public:
193 BitVectorType(const ID &id, uint64_t width) : Type(id), width(width) {}
194
195 uint64_t getWidth() const { return width; }
196 std::ptrdiff_t getBitWidth() const override { return getWidth(); };
197
198private:
199 uint64_t width;
200};
201
202/// Bits are just an array of bits. They are not interpreted as a number but are
203/// identified in the manifest as "signless" ints.
204class BitsType : public BitVectorType {
205public:
207 using Type::deserialize;
208
209 void ensureValid(const std::any &obj) const override;
210 MutableBitVector serialize(const std::any &obj) const override;
211 std::any deserialize(BitVector &data) const override;
212};
213
214/// Integers are bit vectors which may be signed or unsigned and are interpreted
215/// as numbers.
217public:
219};
220
221/// Signed integer.
222class SIntType : public IntegerType {
223public:
224 using IntegerType::IntegerType;
225 using Type::deserialize;
226
227 void ensureValid(const std::any &obj) const override;
228 MutableBitVector serialize(const std::any &obj) const override;
229 std::any deserialize(BitVector &data) const override;
230};
231
232/// Unsigned integer.
233class UIntType : public IntegerType {
234public:
235 using IntegerType::IntegerType;
236 using Type::deserialize;
237
238 void ensureValid(const std::any &obj) const override;
239 MutableBitVector serialize(const std::any &obj) const override;
240 std::any deserialize(BitVector &data) const override;
241};
242
243/// Structs are an ordered collection of fields, each with a name and a type.
244class StructType : public Type {
245public:
246 using FieldVector = std::vector<std::pair<std::string, const Type *>>;
247 using Type::deserialize;
248
249 StructType(const ID &id, const FieldVector &fields, bool reverse = true)
251
252 const FieldVector &getFields() const { return fields; }
253 std::ptrdiff_t getBitWidth() const override {
254 std::ptrdiff_t size = 0;
255 for (auto [name, ty] : getFields()) {
256 std::ptrdiff_t fieldSize = ty->getBitWidth();
257 if (fieldSize < 0)
258 return -1;
259 size += fieldSize;
260 }
261 return size;
262 }
263
264 void ensureValid(const std::any &obj) const override;
265 MutableBitVector serialize(const std::any &obj) const override;
266 std::any deserialize(BitVector &data) const override;
267
268 // Returns whether this struct type should be reversed when
269 // serializing/deserializing.
270 // By default, a truthy value here makes StructType's compatible with system
271 // verilog, which has reversed struct field ordering, wrt. C/software struct
272 // ordering.
273 bool isReverse() const { return reverse; }
274
275private:
278};
279
280/// Arrays have a compile time specified (static) size and an element type.
281class ArrayType : public Type {
282public:
283 ArrayType(const ID &id, const Type *elementType, uint64_t size,
284 bool reverse = true)
286 using Type::deserialize;
287
288 const Type *getElementType() const { return elementType; }
289 uint64_t getSize() const { return size; }
290 bool isReverse() const { return reverse; }
291 std::ptrdiff_t getBitWidth() const override {
292 std::ptrdiff_t elementSize = elementType->getBitWidth();
293 if (elementSize < 0)
294 return -1;
295 return elementSize * size;
296 }
297
298 void ensureValid(const std::any &obj) const override;
299 MutableBitVector serialize(const std::any &obj) const override;
300 std::any deserialize(BitVector &data) const override;
301
302private:
304 uint64_t size;
305 // 'reverse' controls whether array elements are reversed during
306 // serialization/deserialization (to match SystemVerilog/Python ordering
307 // expectations).
309};
310
311/// Windows represent a fixed-size sliding window over a stream of data.
312/// They define an "into" type (the data structure being windowed) and a
313/// "loweredType" (the hardware representation including control signals).
314class WindowType : public Type {
315public:
316 /// Field information describing a field within a frame.
317 struct Field {
318 std::string name;
319 uint64_t numItems = 0; // 0 means not specified (use all items)
320 uint64_t bulkCountWidth = 0; // 0 means parallel encoding, >0 means serial
321 };
322
323 /// Frame information describing which fields are included in a particular
324 /// frame.
325 struct Frame {
326 std::string name;
327 std::vector<Field> fields;
328 };
329
330 WindowType(const ID &id, const std::string &name, const Type *intoType,
331 const Type *loweredType, const std::vector<Frame> &frames)
333 frames(frames) {}
334
335 const std::string &getName() const { return name; }
336 const Type *getIntoType() const { return intoType; }
337 const Type *getLoweredType() const { return loweredType; }
338 const std::vector<Frame> &getFrames() const { return frames; }
339
340 std::ptrdiff_t getBitWidth() const override {
341 return loweredType->getBitWidth();
342 }
343
344private:
345 std::string name;
348 std::vector<Frame> frames;
349};
350
351/// Unions are a tagged collection of fields where only one field is active
352/// at a time. All fields share the same bit range (the width is the max of
353/// all field widths, matching SystemVerilog packed-union semantics).
354class UnionType : public Type {
355public:
356 using FieldVector = std::vector<std::pair<std::string, const Type *>>;
357 using Type::deserialize;
358
359 UnionType(const ID &id, const FieldVector &fields)
360 : Type(id), fields(fields) {}
361
362 const FieldVector &getFields() const { return fields; }
363 std::ptrdiff_t getBitWidth() const override {
364 std::ptrdiff_t maxWidth = 0;
365 for (auto [name, ty] : getFields()) {
366 std::ptrdiff_t fieldWidth = ty->getBitWidth();
367 if (fieldWidth < 0)
368 return -1;
369 maxWidth = std::max(maxWidth, fieldWidth);
370 }
371 return maxWidth;
372 }
373
374 void ensureValid(const std::any &obj) const override;
375 MutableBitVector serialize(const std::any &obj) const override;
376 std::any deserialize(BitVector &data) const override;
377
378private:
380};
381
382/// Lists represent variable-length sequences of elements of a single type.
383/// Unlike arrays which have a fixed size, lists can have any length.
384class ListType : public Type {
385public:
386 ListType(const ID &id, const Type *elementType)
388
389 const Type *getElementType() const { return elementType; }
390
391 std::ptrdiff_t getBitWidth() const override { return -1; }
392
393private:
395};
396
397} // namespace esi
398
399#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:157
std::ptrdiff_t getBitWidth() const override
Definition Types.h:160
AnyType(const ID &id)
Definition Types.h:159
Arrays have a compile time specified (static) size and an element type.
Definition Types.h:281
std::ptrdiff_t getBitWidth() const override
Definition Types.h:291
uint64_t size
Definition Types.h:304
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:420
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:397
bool reverse
Definition Types.h:308
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:439
const Type * elementType
Definition Types.h:303
const Type * getElementType() const
Definition Types.h:288
ArrayType(const ID &id, const Type *elementType, uint64_t size, bool reverse=true)
Definition Types.h:283
uint64_t getSize() const
Definition Types.h:289
bool isReverse() const
Definition Types.h:290
Bit vectors include signed, unsigned, and signless integers.
Definition Types.h:191
BitVectorType(const ID &id, uint64_t width)
Definition Types.h:193
uint64_t width
Definition Types.h:199
std::ptrdiff_t getBitWidth() const override
Definition Types.h:196
uint64_t getWidth() const
Definition Types.h:195
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:204
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:195
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:216
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:210
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:216
Lists represent variable-length sequences of elements of a single type.
Definition Types.h:384
ListType(const ID &id, const Type *elementType)
Definition Types.h:386
std::ptrdiff_t getBitWidth() const override
Definition Types.h:391
const Type * elementType
Definition Types.h:394
const Type * getElementType() const
Definition Types.h:389
A logical chunk of data representing serialized data.
Definition Common.h:113
A mutable bit vector that owns its underlying storage.
Definition Values.h:185
Signed integer.
Definition Types.h:222
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:289
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:278
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:268
Structs are an ordered collection of fields, each with a name and a type.
Definition Types.h:244
bool isReverse() const
Definition Types.h:273
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:331
std::vector< std::pair< std::string, const Type * > > FieldVector
Definition Types.h:246
FieldVector fields
Definition Types.h:276
std::ptrdiff_t getBitWidth() const override
Definition Types.h:253
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:359
StructType(const ID &id, const FieldVector &fields, bool reverse=true)
Definition Types.h:249
const FieldVector & getFields() const
Definition Types.h:252
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:380
Type aliases provide a named type which forwards to an inner type.
Definition Types.h:164
std::ptrdiff_t getBitWidth() const override
Definition Types.h:177
const Type * innerType
Definition Types.h:187
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:183
TypeAliasType(const ID &id, std::string name, const Type *innerType)
Definition Types.h:168
std::string name
Definition Types.h:186
const Type * getInnerType() const
Definition Types.h:175
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:191
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:187
const std::string & getName() const
Definition Types.h:174
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:233
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:320
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:310
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:300
Unions are a tagged collection of fields where only one field is active at a time.
Definition Types.h:354
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:481
UnionType(const ID &id, const FieldVector &fields)
Definition Types.h:359
std::vector< std::pair< std::string, const Type * > > FieldVector
Definition Types.h:356
void ensureValid(const std::any &obj) const override
Ensure that a std::any object is valid for this type.
Definition Types.cpp:451
std::any deserialize(BitVector &data) const override
Deserialize from a BitVector stream (LSB-first).
Definition Types.cpp:506
const FieldVector & getFields() const
Definition Types.h:362
std::ptrdiff_t getBitWidth() const override
Definition Types.h:363
FieldVector fields
Definition Types.h:379
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:146
MutableBitVector serialize(const std::any &obj) const override
Serialize an object to a MutableBitVector (LSB-first stream).
Definition Types.cpp:176
Windows represent a fixed-size sliding window over a stream of data.
Definition Types.h:314
std::ptrdiff_t getBitWidth() const override
Definition Types.h:340
std::vector< Frame > frames
Definition Types.h:348
const std::vector< Frame > & getFrames() const
Definition Types.h:338
const Type * intoType
Definition Types.h:346
std::string name
Definition Types.h:345
const Type * getLoweredType() const
Definition Types.h:337
const std::string & getName() const
Definition Types.h:335
const Type * loweredType
Definition Types.h:347
const Type * getIntoType() const
Definition Types.h:336
WindowType(const ID &id, const std::string &name, const Type *intoType, const Type *loweredType, const std::vector< Frame > &frames)
Definition Types.h:330
Definition esi.py:1
Field information describing a field within a frame.
Definition Types.h:317
uint64_t bulkCountWidth
Definition Types.h:320
std::string name
Definition Types.h:318
Frame information describing which fields are included in a particular frame.
Definition Types.h:325
std::vector< Field > fields
Definition Types.h:327
std::string name
Definition Types.h:326