Cerata
A library to generate structural hardware designs
type.h
1 // Copyright 2018-2019 Delft University of Technology
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <optional>
18 #include <utility>
19 #include <memory>
20 #include <vector>
21 #include <unordered_map>
22 #include <string>
23 #include <tuple>
24 
25 #include "cerata/utils.h"
26 #include "cerata/flattype.h"
27 #include "cerata/domain.h"
28 
29 namespace cerata {
30 
31 // Forward decl.
32 class Object;
33 class Node;
34 class Literal;
35 class Graph;
36 std::shared_ptr<Literal> intl(int64_t);
37 typedef std::unordered_map<const Node *, Node *> NodeMap;
38 
63 class Type : public Named, public std::enable_shared_from_this<Type> {
64  public:
66  //
67  // Physical | Generic | Nested
68  // ---------|---------|-----------
69  enum ID {
70  BIT,
72 
76 
77  RECORD
78  };
79 
85  explicit Type(std::string name, ID id);
86 
88  inline ID id() const { return id_; }
89 
95  virtual bool IsEqual(const Type &other) const;
96 
98  bool Is(ID type_id) const;
100  virtual bool IsPhysical() const = 0;
102  virtual bool IsNested() const = 0;
104  virtual bool IsGeneric() const = 0;
106  virtual std::optional<Node *> width() const { return std::nullopt; }
108  std::string ToString(bool show_meta = false, bool show_mappers = false) const;
109 
111  std::vector<std::shared_ptr<TypeMapper>> mappers() const;
113  void AddMapper(const std::shared_ptr<TypeMapper> &mapper, bool remove_existing = true);
115  std::optional<std::shared_ptr<TypeMapper>> GetMapper(Type *other, bool generate_implicit = true);
117  int RemoveMappersTo(Type *other);
119  std::optional<std::shared_ptr<TypeMapper>> GetMapper(const std::shared_ptr<Type> &other);
121  virtual bool CanGenerateMapper(const Type &other) const { return false; }
123  virtual std::shared_ptr<TypeMapper> GenerateMapper(Type *other) { return nullptr; }
124 
126  virtual std::vector<Node *> GetGenerics() const { return {}; }
128  virtual std::vector<Type *> GetNested() const { return {}; }
129 
131  std::unordered_map<std::string, std::string> meta;
132 
141  virtual std::shared_ptr<Type> Copy(const NodeMap &rebinding) const = 0;
142 
147  virtual std::shared_ptr<Type> Copy() const { return Copy({}); }
148 
154  std::shared_ptr<Type> operator()(std::vector<Node *> nodes);
155 
161  std::shared_ptr<Type> operator()(const std::vector<std::shared_ptr<Node>> &nodes);
162 
163  protected:
167  std::vector<std::shared_ptr<TypeMapper>> mappers_;
168 };
169 
171 std::shared_ptr<Type> bit(const std::string &name = "bit");
173 struct Bit : public Type {
174  bool IsPhysical() const override { return true; }
175  bool IsGeneric() const override { return false; }
176  bool IsNested() const override { return false; }
178  explicit Bit(std::string name) : Type(std::move(name), Type::BIT) {}
180  std::optional<Node *> width() const override;
181 
182  std::shared_ptr<Type> Copy(const NodeMap &rebinding) const override;
183 };
184 
186 std::shared_ptr<Type> boolean();
188 struct Boolean : public Type {
190  explicit Boolean(std::string name) : Type(std::move(name), Type::BOOLEAN) {}
191  bool IsPhysical() const override { return false; }
192  bool IsGeneric() const override { return false; }
193  bool IsNested() const override { return false; }
194  std::shared_ptr<Type> Copy(const NodeMap &rebinding) const override { return boolean(); }
195 };
196 
198 std::shared_ptr<Type> integer();
200 struct Integer : public Type {
202  explicit Integer(std::string name) : Type(std::move(name), Type::INTEGER) {}
203  bool IsPhysical() const override { return false; }
204  bool IsGeneric() const override { return false; }
205  bool IsNested() const override { return false; }
206  std::shared_ptr<Type> Copy(const NodeMap &rebinding) const override { return integer(); }
207 };
208 
210 std::shared_ptr<Type> string();
212 struct String : public Type {
214  explicit String(std::string name) : Type(std::move(name), Type::STRING) {}
215  bool IsPhysical() const override { return false; }
216  bool IsGeneric() const override { return false; }
217  bool IsNested() const override { return false; }
218  std::shared_ptr<Type> Copy(const NodeMap &rebinding) const override { return string(); }
219 };
220 
222 class Vector : public Type {
223  public:
224  bool IsPhysical() const override { return true; }
225  bool IsGeneric() const override { return true; }
226  bool IsNested() const override { return false; }
227 
229  Vector(std::string name, const std::shared_ptr<Node> &width);
231  std::optional<Node *> width() const override;
233  Type &SetWidth(std::shared_ptr<Node> width);
235  bool IsEqual(const Type &other) const override;
237  std::vector<Node *> GetGenerics() const override;
238 
239  std::shared_ptr<Type> Copy(const NodeMap &rebinding) const override;
240 
241  private:
243  std::shared_ptr<Node> width_;
244 };
245 
247 std::shared_ptr<Type> vector(const std::string &name, const std::shared_ptr<Node> &width);
249 std::shared_ptr<Type> vector(const std::shared_ptr<Node> &width);
251 std::shared_ptr<Type> vector(unsigned int width);
253 std::shared_ptr<Type> vector(std::string name, unsigned int width);
254 
256 class Field : public Named, public std::enable_shared_from_this<Field> {
257  public:
259  Field(std::string name, std::shared_ptr<Type> type, bool reverse = false, bool sep = true);
261  Field &SetType(std::shared_ptr<Type> type);
263  std::shared_ptr<Type> type() const { return type_; }
265  bool reversed() const { return reverse_; }
267  std::shared_ptr<Field> Reverse();
269  bool sep() const { return sep_; }
271  void NoSep() { sep_ = false; }
273  void UseSep() { sep_ = true; }
275  std::unordered_map<std::string, std::string> meta;
277  std::shared_ptr<Field> Copy(const NodeMap &rebinding) const;
278 
279  private:
281  std::shared_ptr<Type> type_;
283  bool reverse_;
285  bool sep_;
286 };
287 
289 std::shared_ptr<Field> field(const std::string &name,
290  const std::shared_ptr<Type> &type,
291  bool reverse = false,
292  bool sep = true);
293 
295 std::shared_ptr<Field> field(const std::shared_ptr<Type> &type, bool reverse = false, bool sep = true);
296 
298 std::shared_ptr<Field> NoSep(std::shared_ptr<Field> field);
299 
301 class Record : public Type {
302  public:
303  bool IsPhysical() const override;
304  bool IsGeneric() const override;
305  bool IsNested() const override { return true; }
306 
308  explicit Record(std::string name, std::vector<std::shared_ptr<Field>> fields = {});
310  Record &AddField(const std::shared_ptr<Field> &field, std::optional<size_t> index = std::nullopt);
312  bool Has(const std::string &name) const;
314  Field *at(const std::string &name) const;
316  Field *at(size_t i) const;
318  Field *operator[](size_t i) const;
320  Field *operator[](const std::string& name) const;
322  std::vector<std::shared_ptr<Field>> fields() const { return fields_; }
324  inline size_t num_fields() const { return fields_.size(); }
326  bool IsEqual(const Type &other) const override;
328  std::vector<Node *> GetGenerics() const override;
330  std::vector<Type *> GetNested() const override;
331 
332  std::shared_ptr<Type> Copy(const NodeMap &rebinding) const override;
333 
335  std::string ToStringFieldNames() const;
336 
337  protected:
339  std::vector<std::shared_ptr<Field>> fields_;
340 };
341 
347 std::shared_ptr<Record> record(const std::string &name);
348 
355 std::shared_ptr<Record> record(const std::string &name,
356  const std::vector<std::shared_ptr<Field>> &fields);
357 
363 std::shared_ptr<Record> record(const std::vector<std::shared_ptr<Field>> &fields);
364 
365 
371 std::shared_ptr<Record> record(const std::initializer_list<std::shared_ptr<Field>> &fields);
372 
373 } // namespace cerata
cerata::Type::mappers
std::vector< std::shared_ptr< TypeMapper > > mappers() const
Return possible type mappers.
Definition: type.cc:78
cerata::Type::IsNested
virtual bool IsNested() const =0
Return true if the Type is a nested, false otherwise.
cerata::String::IsPhysical
bool IsPhysical() const override
Return true if the Type has an immediate physical representation, false otherwise.
Definition: type.h:215
cerata::Record::fields_
std::vector< std::shared_ptr< Field > > fields_
The fields of this Record.
Definition: type.h:339
cerata::Type::RECORD
@ RECORD
? | ? | Yes
Definition: type.h:77
cerata::Record::num_fields
size_t num_fields() const
Return the number of fields in this record.
Definition: type.h:324
cerata::field
std::shared_ptr< Field > field(const std::string &name, const std::shared_ptr< Type > &type, bool reverse, bool sep)
Create a new RecordField, and return a shared pointer to it.
Definition: type.cc:273
cerata::Record::ToStringFieldNames
std::string ToStringFieldNames() const
Return the names of the fields as a comma separated string.
Definition: type.cc:495
cerata::Bit::IsPhysical
bool IsPhysical() const override
Return true if the Type has an immediate physical representation, false otherwise.
Definition: type.h:174
cerata::Type::BOOLEAN
@ BOOLEAN
No | No | No.
Definition: type.h:75
cerata::Field::meta
std::unordered_map< std::string, std::string > meta
Metadata for back-end implementations.
Definition: type.h:275
cerata::Field::Field
Field(std::string name, std::shared_ptr< Type > type, bool reverse=false, bool sep=true)
RecordField constructor.
Definition: type.cc:270
cerata::Vector
Vector type.
Definition: type.h:222
cerata::Record::IsPhysical
bool IsPhysical() const override
Return true if the Type has an immediate physical representation, false otherwise.
Definition: type.cc:373
cerata::Field::Reverse
std::shared_ptr< Field > Reverse()
Reverse the direction of this field and return itself.
Definition: type.cc:441
cerata::NoSep
std::shared_ptr< Field > NoSep(std::shared_ptr< Field > field)
Convenience function to disable the separator for a record field.
Definition: type.cc:281
cerata::Field
A Record field.
Definition: type.h:256
cerata::String::IsNested
bool IsNested() const override
Return true if the Type is a nested, false otherwise.
Definition: type.h:217
cerata::Type::id_
ID id_
Type ID.
Definition: type.h:165
cerata::Boolean::IsPhysical
bool IsPhysical() const override
Return true if the Type has an immediate physical representation, false otherwise.
Definition: type.h:191
cerata::Type::IsEqual
virtual bool IsEqual(const Type &other) const
Determine if this Type is exactly equal to an other Type.
Definition: type.cc:159
cerata::Bit
A bit type.
Definition: type.h:173
cerata::Type
A Type.
Definition: type.h:63
cerata::Type::BIT
@ BIT
Yes | No | No.
Definition: type.h:70
cerata::Vector::width
std::optional< Node * > width() const override
Return a pointer to the node representing the width of this vector, if specified.
Definition: type.cc:211
cerata::Record::Record
Record(std::string name, std::vector< std::shared_ptr< Field >> fields={})
Record constructor.
Definition: type.cc:296
cerata::Record
A Record type containing zero or more fields.
Definition: type.h:301
cerata::Integer::IsPhysical
bool IsPhysical() const override
Return true if the Type has an immediate physical representation, false otherwise.
Definition: type.h:203
cerata::Type::Type
Type(std::string name, ID id)
Type constructor.
Definition: type.cc:32
cerata
Contains every Cerata class, function, etc...
Definition: api.h:41
cerata::Field::sep
bool sep() const
Return true if in name generation of this field name for flattened types a separator should be placed...
Definition: type.h:269
cerata::Record::operator[]
Field * operator[](size_t i) const
Return the field at index i contained by this record.
Definition: type.cc:472
cerata::Field::UseSep
void UseSep()
Enable the separator in name generation of this field.
Definition: type.h:273
cerata::Type::GetMapper
std::optional< std::shared_ptr< TypeMapper > > GetMapper(Type *other, bool generate_implicit=true)
Get a mapper to another type, if it exists. Generates one, if possible, when generate_implicit = true...
Definition: type.cc:112
cerata::Record::at
Field * at(const std::string &name) const
Return the field with a specific name.
Definition: type.cc:483
cerata::Bit::IsNested
bool IsNested() const override
Return true if the Type is a nested, false otherwise.
Definition: type.h:176
cerata::Vector::SetWidth
Type & SetWidth(std::shared_ptr< Node > width)
Set the width of this vector.
Definition: type.cc:235
cerata::Field::SetType
Field & SetType(std::shared_ptr< Type > type)
Change the type of this field.
Definition: type.cc:436
cerata::Integer::Integer
Integer(std::string name)
Integer constructor.
Definition: type.h:202
cerata::Type::CanGenerateMapper
virtual bool CanGenerateMapper(const Type &other) const
Check if a mapper can be generated to another specific type.
Definition: type.h:121
cerata::Type::meta
std::unordered_map< std::string, std::string > meta
KV storage for metadata of tools or specific backend implementations.
Definition: type.h:131
cerata::NodeMap
std::unordered_map< const Node *, Node * > NodeMap
A mapping from one object to another object, used in e.g. type generic rebinding.
Definition: node.h:135
cerata::Type::Is
bool Is(ID type_id) const
Return true if the Type ID is type_id, false otherwise.
Definition: type.cc:28
cerata::Type::id
ID id() const
Return the Type ID.
Definition: type.h:88
cerata::Bit::IsGeneric
bool IsGeneric() const override
Return true if the Type is a generic type.
Definition: type.h:175
cerata::Type::GetNested
virtual std::vector< Type * > GetNested() const
Obtain any nested types.
Definition: type.h:128
cerata::Type::RemoveMappersTo
int RemoveMappersTo(Type *other)
Remove all mappers to a specific type.
Definition: type.cc:148
cerata::Record::IsGeneric
bool IsGeneric() const override
Return true if the Type is a generic type.
Definition: type.cc:382
cerata::String::String
String(std::string name)
String constructor.
Definition: type.h:214
cerata::Type::IsPhysical
virtual bool IsPhysical() const =0
Return true if the Type has an immediate physical representation, false otherwise.
cerata::Named::name
std::string name() const
Return the name of the object.
Definition: utils.h:45
cerata::Type::ToString
std::string ToString(bool show_meta=false, bool show_mappers=false) const
Return the Type ID as a human-readable string.
Definition: type.cc:34
cerata::Record::GetGenerics
std::vector< Node * > GetGenerics() const override
Return all nodes that potentially parametrize the fields of this record.
Definition: type.cc:352
cerata::Vector::Vector
Vector(std::string name, const std::shared_ptr< Node > &width)
Vector constructor.
Definition: type.cc:184
cerata::Type::mappers_
std::vector< std::shared_ptr< TypeMapper > > mappers_
A list of mappers that can map this type to another type.
Definition: type.h:167
cerata::string
std::shared_ptr< Type > string()
Return a static string type.
Definition: type.cc:261
cerata::Type::STRING
@ STRING
No | No | No.
Definition: type.h:74
cerata::Integer::Copy
std::shared_ptr< Type > Copy(const NodeMap &rebinding) const override
Make a copy of the type, and rebind any type generic nodes that are keys in the rebinding to their va...
Definition: type.h:206
cerata::Boolean::IsNested
bool IsNested() const override
Return true if the Type is a nested, false otherwise.
Definition: type.h:193
cerata::boolean
std::shared_ptr< Type > boolean()
Return a static boolean type.
Definition: type.cc:251
cerata::intl
std::shared_ptr< Literal > intl(int64_t i)
Obtain a shared pointer to an integer literal from the default node pool.
Definition: pool.h:144
cerata::Type::AddMapper
void AddMapper(const std::shared_ptr< TypeMapper > &mapper, bool remove_existing=true)
Add a type mapper.
Definition: type.cc:82
cerata::Record::GetNested
std::vector< Type * > GetNested() const override
Obtain any nested types.
Definition: type.cc:361
cerata::Type::GenerateMapper
virtual std::shared_ptr< TypeMapper > GenerateMapper(Type *other)
Generate a new mapper to a specific other type. Should be checked with CanGenerateMapper first,...
Definition: type.h:123
cerata::Bit::Bit
Bit(std::string name)
Bit type constructor.
Definition: type.h:178
cerata::Named
Convenience structure for anything that is named. Names are case-sensitive.
Definition: utils.h:40
cerata::Record::Has
bool Has(const std::string &name) const
Return true if record has field with name name.
Definition: type.cc:474
cerata::Integer::IsGeneric
bool IsGeneric() const override
Return true if the Type is a generic type.
Definition: type.h:204
cerata::Vector::IsNested
bool IsNested() const override
Return true if the Type is a nested, false otherwise.
Definition: type.h:226
cerata::Type::width
virtual std::optional< Node * > width() const
Return the width of the type, if it is synthesizable.
Definition: type.h:106
cerata::Record::fields
std::vector< std::shared_ptr< Field > > fields() const
Return all fields contained by this record.
Definition: type.h:322
cerata::vector
std::shared_ptr< Type > vector(const std::string &name, const std::shared_ptr< Node > &width)
Create a new vector type, and return a shared pointer to it.
Definition: type.cc:193
cerata::Vector::IsPhysical
bool IsPhysical() const override
Return true if the Type has an immediate physical representation, false otherwise.
Definition: type.h:224
cerata::Record::IsEqual
bool IsEqual(const Type &other) const override
Determine if this Type is exactly equal to an other Type.
Definition: type.cc:324
cerata::Boolean::IsGeneric
bool IsGeneric() const override
Return true if the Type is a generic type.
Definition: type.h:192
cerata::record
std::shared_ptr< Record > record(const std::string &name, const std::vector< std::shared_ptr< Field >> &fields)
Create a new Record type, and return a shared pointer to it.
Definition: type.cc:308
cerata::Record::AddField
Record & AddField(const std::shared_ptr< Field > &field, std::optional< size_t > index=std::nullopt)
Add a field to this Record.
Definition: type.cc:286
cerata::Boolean::Boolean
Boolean(std::string name)
Boolean constructor.
Definition: type.h:190
cerata::String::Copy
std::shared_ptr< Type > Copy(const NodeMap &rebinding) const override
Make a copy of the type, and rebind any type generic nodes that are keys in the rebinding to their va...
Definition: type.h:218
cerata::Field::Copy
std::shared_ptr< Field > Copy(const NodeMap &rebinding) const
Create a copy of the field.
Definition: type.cc:425
cerata::Type::operator()
std::shared_ptr< Type > operator()(std::vector< Node * > nodes)
Make a copy of the type, and rebind any type generic nodes in order of the GetGenerics call.
Definition: type.cc:163
cerata::Vector::IsGeneric
bool IsGeneric() const override
Return true if the Type is a generic type.
Definition: type.h:225
cerata::Type::INTEGER
@ INTEGER
No | No | No.
Definition: type.h:73
cerata::Boolean::Copy
std::shared_ptr< Type > Copy(const NodeMap &rebinding) const override
Make a copy of the type, and rebind any type generic nodes that are keys in the rebinding to their va...
Definition: type.h:194
cerata::String::IsGeneric
bool IsGeneric() const override
Return true if the Type is a generic type.
Definition: type.h:216
cerata::Type::GetGenerics
virtual std::vector< Node * > GetGenerics() const
Obtain any nodes that this type uses as generics.
Definition: type.h:126
cerata::integer
std::shared_ptr< Type > integer()
Return a static integer type.
Definition: type.cc:256
cerata::Bit::width
std::optional< Node * > width() const override
Bit width returns integer literal 1.
Definition: type.cc:266
cerata::bit
std::shared_ptr< Type > bit(const std::string &name)
Return a static bit type.
Definition: type.cc:240
cerata::String
String type.
Definition: type.h:212
cerata::Field::type
std::shared_ptr< Type > type() const
Return the type of the RecordField.
Definition: type.h:263
cerata::Field::reversed
bool reversed() const
Return if this individual field should be reversed w.r.t. parent Record type itself on graph edges.
Definition: type.h:265
cerata::Field::NoSep
void NoSep()
Disable the separator in name generation of this field.
Definition: type.h:271
cerata::Record::IsNested
bool IsNested() const override
Return true if the Type is a nested, false otherwise.
Definition: type.h:305
cerata::Type::Copy
virtual std::shared_ptr< Type > Copy() const
Make a copy of the type without rebinding.
Definition: type.h:147
cerata::Type::Copy
virtual std::shared_ptr< Type > Copy(const NodeMap &rebinding) const =0
Make a copy of the type, and rebind any type generic nodes that are keys in the rebinding to their va...
cerata::Boolean
Boolean type.
Definition: type.h:188
cerata::Integer
Integer type.
Definition: type.h:200
cerata::Type::VECTOR
@ VECTOR
Yes | Yes | No.
Definition: type.h:71
cerata::Vector::IsEqual
bool IsEqual(const Type &other) const override
Determine if this Type is exactly equal to an other Type.
Definition: type.cc:215
cerata::Vector::GetGenerics
std::vector< Node * > GetGenerics() const override
Returns the width parameter of this vector, if any. Otherwise an empty list;.
Definition: type.cc:227
cerata::Type::IsGeneric
virtual bool IsGeneric() const =0
Return true if the Type is a generic type.
cerata::Integer::IsNested
bool IsNested() const override
Return true if the Type is a nested, false otherwise.
Definition: type.h:205
cerata::Type::ID
ID
The Type ID. Used for convenient type checking.
Definition: type.h:69