Cerata
A library to generate structural hardware designs
flattype.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 <algorithm>
18 #include <tuple>
19 #include <optional>
20 #include <utility>
21 #include <memory>
22 #include <vector>
23 #include <vector>
24 #include <string>
25 #include <sstream>
26 #include <iomanip>
27 #include <unordered_map>
28 
29 #include "cerata/utils.h"
30 #include "cerata/logging.h"
31 
32 namespace cerata {
33 
34 class Type;
35 class Record;
36 class Stream;
37 class Node;
38 
40 struct NamePart {
41  NamePart() = default;
43  explicit NamePart(std::string part, bool append_sep = true) : str(std::move(part)), sep(append_sep) {}
45  std::string str = "";
47  bool sep = false;
48 };
49 
51 struct FlatType {
52  FlatType() = default;
54  FlatType(Type *t, std::vector<NamePart> prefix, const std::string &name, bool invert);
56  Type *type_ = nullptr;
58  int nesting_level_ = 0;
60  std::vector<NamePart> name_parts_;
62  bool reverse_ = false;
64  [[nodiscard]] std::string name(const NamePart &root = NamePart(), const std::string &sep = "_") const;
65 };
66 
68 bool operator<(const FlatType &a, const FlatType &b);
69 
70 // Flattening functions for nested types:
71 
73 void FlattenRecord(std::vector<FlatType> *list,
74  const Record *record,
75  const std::optional<FlatType> &parent,
76  bool invert);
77 
79 void FlattenStream(std::vector<FlatType> *list,
80  const Stream *stream,
81  const std::optional<FlatType> &parent,
82  bool invert);
83 
85 void Flatten(std::vector<FlatType> *list,
86  Type *type,
87  const std::optional<FlatType> &parent,
88  const std::string &name,
89  bool invert,
90  bool sep = true);
91 
93 std::vector<FlatType> Flatten(Type *type);
94 
96 bool ContainsFlatType(const std::vector<FlatType> &flat_types_list, const Type *type);
97 
99 int64_t IndexOfFlatType(const std::vector<FlatType> &flat_types_list, const Type *type);
100 
102 std::string ToString(std::vector<FlatType> flat_type_list);
103 
108 template<typename T>
110  public:
116  MappingMatrix(int64_t height, int64_t width) : height_(height), width_(width) {
117  elements_ = std::vector<T>(height_ * width_, static_cast<T>(0));
118  }
119 
121  static MappingMatrix Identity(int64_t dim) {
122  MappingMatrix ret(dim, dim);
123  for (int64_t i = 0; i < dim; i++) {
124  ret(i, i) = 1;
125  }
126  }
127 
129  int64_t height() { return height_; }
131  int64_t width() { return width_; }
132 
134  T &get(int64_t y, int64_t x) {
135  if (y >= height_ || x >= width_) {
136  CERATA_LOG(FATAL, "Indices exceed matrix dimensions.");
137  }
138  return elements_[width_ * y + x];
139  }
140 
142  [[nodiscard]] const T &get(int64_t y, int64_t x) const {
143  if (y >= height_ || x >= width_) {
144  CERATA_LOG(FATAL, "Indices exceed matrix dimensions.");
145  }
146  return elements_[width_ * y + x];
147  }
148 
150  T &operator()(int64_t y, int64_t x) {
151  return get(y, x);
152  }
153 
155  const T &operator()(int64_t y, int64_t x) const {
156  return get(y, x);
157  }
158 
160  [[nodiscard]] bool IsIdentity() const {
161  if (width_ == height_) {
162  for (size_t d = 0; d < width_; d++) {
163  if (get(d, d) != 1) {
164  return false;
165  }
166  }
167  }
168  return true;
169  }
170 
172  [[nodiscard]] T MaxOfColumn(int64_t x) const {
173  T max = 0;
174  for (int64_t y = 0; y < height_; y++) {
175  if (get(y, x) > max) {
176  max = get(y, x);
177  }
178  }
179  return max;
180  }
181 
183  [[nodiscard]] T MaxOfRow(int64_t y) const {
184  T max = 0;
185  for (int64_t x = 0; x < width_; x++) {
186  if (get(y, x) > max) {
187  max = get(y, x);
188  }
189  }
190  return max;
191  }
192 
194  std::vector<std::pair<int64_t, T>> mapping_column(int64_t x) {
195  std::vector<std::pair<int64_t, T>> ret;
196  for (int64_t y = 0; y < height_; y++) {
197  auto val = get(y, x);
198  if (val > 0) {
199  ret.emplace_back(y, val);
200  }
201  }
202  std::sort(ret.begin(), ret.end(), [](const auto &x, const auto &y) -> bool {
203  return x.second < y.second;
204  });
205  return ret;
206  }
207 
209  std::vector<std::pair<int64_t, T>> mapping_row(int64_t y) {
210  using pair = std::pair<int64_t, T>;
211  std::vector<pair> ret;
212  for (int64_t x = 0; x < width_; x++) {
213  auto val = get(y, x);
214  if (val > 0) {
215  ret.emplace_back(x, val);
216  }
217  }
218  std::sort(ret.begin(), ret.end(), [](const auto &x, const auto &y) -> bool {
219  return x.second < y.second;
220  });
221  return ret;
222  }
223 
225  MappingMatrix &SetNext(int64_t y, int64_t x) {
226  get(y, x) = std::max(MaxOfColumn(x), MaxOfRow(y)) + 1;
227  return *this;
228  }
229 
231  [[nodiscard]] MappingMatrix Transpose() const {
232  MappingMatrix ret(width_, height_);
233  for (int64_t y = 0; y < height_; y++) {
234  for (int64_t x = 0; x < width_; x++) {
235  ret(x, y) = get(y, x);
236  }
237  }
238  return ret;
239  }
240 
242  [[nodiscard]] MappingMatrix Empty() const {
243  MappingMatrix ret(height_, width_);
244  return ret;
245  }
246 
248  std::string ToString() {
249  std::stringstream ret;
250  for (int64_t y = 0; y < height_; y++) {
251  for (int64_t x = 0; x < width_; x++) {
252  ret << std::setw(3) << std::right << std::to_string(get(y, x)) << " ";
253  }
254  ret << "\n";
255  }
256  return ret.str();
257  }
258 
259  private:
261  std::vector<T> elements_;
263  int64_t height_;
265  int64_t width_;
266 };
267 
276 struct MappingPair {
277  using OptionalNode = std::optional<std::shared_ptr<Node>>;
278  using index = int64_t;
279  using offset = int64_t;
280  using IOF = std::tuple<index, offset, FlatType>;
283  std::vector<IOF> a;
285  std::vector<IOF> b;
287  [[nodiscard]] int64_t num_a() const { return a.size(); }
289  [[nodiscard]] int64_t num_b() const { return b.size(); }
291  [[nodiscard]] index index_a(int64_t i) const { return std::get<0>(a[i]); }
293  [[nodiscard]] index index_b(int64_t i) const { return std::get<0>(b[i]); }
295  [[nodiscard]] offset offset_a(int64_t i) const { return std::get<1>(a[i]); }
297  [[nodiscard]] offset offset_b(int64_t i) const { return std::get<1>(b[i]); }
299  [[nodiscard]] FlatType flat_type_a(int64_t i) const { return std::get<2>(a[i]); }
301  [[nodiscard]] FlatType flat_type_b(int64_t i) const { return std::get<2>(b[i]); }
302 
308  [[nodiscard]] std::shared_ptr<Node> width_a(const OptionalNode &no_width_increment = {}) const;
309 
315  [[nodiscard]] std::shared_ptr<Node> width_b(const OptionalNode &no_width_increment = {}) const;
316 
318  [[nodiscard]] std::string ToString() const;
319 };
320 
326 class TypeMapper : public Named {
327  public:
329  TypeMapper(Type *a, Type *b);
331  static std::shared_ptr<TypeMapper> Make(Type *a);
333  static std::shared_ptr<TypeMapper> MakeImplicit(Type *a, Type *b);
335  static std::shared_ptr<TypeMapper> Make(Type *a, Type *b);
337  static std::shared_ptr<TypeMapper> Make(const std::shared_ptr<Type> &a, const std::shared_ptr<Type> &b);
338 
340  TypeMapper &Add(int64_t a, int64_t b);
345 
347  std::vector<FlatType> flat_a() const;
349  std::vector<FlatType> flat_b() const;
351  Type *a() const { return a_; }
353  Type *b() const { return b_; }
354 
356  bool CanConvert(const Type *a, const Type *b) const;
357 
359  std::shared_ptr<TypeMapper> Inverse() const;
360 
362  std::vector<MappingPair> GetUniqueMappingPairs();
363 
365  std::string ToString() const;
366 
368  std::unordered_map<std::string, std::string> meta;
369 
370  protected:
372  std::vector<FlatType> fa_;
374  std::vector<FlatType> fb_;
381 };
382 
383 } // namespace cerata
cerata::NamePart::sep
bool sep
Whether we should insert a separator after this part.
Definition: flattype.h:47
cerata::TypeMapper::Make
static std::shared_ptr< TypeMapper > Make(Type *a)
Construct a new TypeMapper from some type to itself, and return a smart pointer to it.
Definition: flattype.cc:277
cerata::MappingPair::width_b
std::shared_ptr< Node > width_b(const OptionalNode &no_width_increment={}) const
Return the total width of the types on side B.
Definition: flattype.cc:333
cerata::MappingMatrix::mapping_row
std::vector< std::pair< int64_t, T > > mapping_row(int64_t y)
Obtain non-zero element indices and value from row y, sorted by value.
Definition: flattype.h:209
cerata::MappingPair::index
int64_t index
Index type.
Definition: flattype.h:278
cerata::TypeMapper::fa_
std::vector< FlatType > fa_
The list of flattened types on the "a"-side.
Definition: flattype.h:372
cerata::TypeMapper::b_
Type * b_
Type of the "b"-side.
Definition: flattype.h:378
cerata::MappingMatrix::MappingMatrix
MappingMatrix(int64_t height, int64_t width)
Construct a mapping matrix.
Definition: flattype.h:116
cerata::MappingPair::flat_type_a
FlatType flat_type_a(int64_t i) const
Return the i-th FlatType on the "a"-side in the mapping matrix.
Definition: flattype.h:299
cerata::NamePart::NamePart
NamePart(std::string part, bool append_sep=true)
Constuct a new NamePart.
Definition: flattype.h:43
cerata::MappingMatrix::Identity
static MappingMatrix Identity(int64_t dim)
Return a square identity matrix.
Definition: flattype.h:121
cerata::TypeMapper::ToString
std::string ToString() const
Return a human-readable string of this TypeMapper.
Definition: flattype.cc:175
cerata::MappingMatrix::get
const T & get(int64_t y, int64_t x) const
Return a const references to a value in the matrix at some index.
Definition: flattype.h:142
cerata::FlatType::type_
Type * type_
A pointer to the original type.
Definition: flattype.h:56
cerata::Type
A Type.
Definition: type.h:63
cerata::Record
A Record type containing zero or more fields.
Definition: type.h:301
cerata::TypeMapper
A structure to dynamically define type mappings between flattened types.
Definition: flattype.h:326
cerata::TypeMapper::Inverse
std::shared_ptr< TypeMapper > Inverse() const
Return a new TypeMapper that is the inverse of this TypeMapper.
Definition: flattype.cc:225
cerata::MappingMatrix::SetNext
MappingMatrix & SetNext(int64_t y, int64_t x)
Set the next (existing maximum + 1) value in a matrix at some position.
Definition: flattype.h:225
cerata::TypeMapper::flat_b
std::vector< FlatType > flat_b() const
Return the list of flattened types on the "b"-side.
Definition: flattype.cc:219
cerata
Contains every Cerata class, function, etc...
Definition: api.h:41
cerata::MappingPair::IOF
std::tuple< index, offset, FlatType > IOF
Tuple that stores all information required by a mapping pair on one side.
Definition: flattype.h:281
cerata::MappingPair::width_a
std::shared_ptr< Node > width_a(const OptionalNode &no_width_increment={}) const
Return the total width of the types on side A.
Definition: flattype.cc:320
cerata::MappingMatrix::operator()
T & operator()(int64_t y, int64_t x)
Return a reference to a value in the matrix at some index.
Definition: flattype.h:150
cerata::MappingMatrix::Transpose
MappingMatrix Transpose() const
Transpose the matrix.
Definition: flattype.h:231
cerata::NamePart
Convenience struct to generate names in parts.
Definition: flattype.h:40
cerata::MappingMatrix::operator()
const T & operator()(int64_t y, int64_t x) const
Return a const references to a value in the matrix at some index.
Definition: flattype.h:155
cerata::TypeMapper::CanConvert
bool CanConvert(const Type *a, const Type *b) const
Return true if this TypeMapper can map type a to type b.
Definition: flattype.cc:221
cerata::MappingPair::OptionalNode
std::optional< std::shared_ptr< Node > > OptionalNode
Optional shared pointer to a node.
Definition: flattype.h:277
cerata::MappingMatrix::MaxOfRow
T MaxOfRow(int64_t y) const
Return the maximum of some row.
Definition: flattype.h:183
cerata::MappingMatrix::ToString
std::string ToString()
Definition: flattype.h:248
cerata::TypeMapper::GetUniqueMappingPairs
std::vector< MappingPair > GetUniqueMappingPairs()
Get a list of unique mapping pairs.
Definition: flattype.cc:232
cerata::ToString
std::string ToString(Expression::Op operation)
Human-readable expression operator.
Definition: expression.cc:149
cerata::MappingMatrix::MaxOfColumn
T MaxOfColumn(int64_t x) const
Return the maximum of some column.
Definition: flattype.h:172
cerata::TypeMapper::a
Type * a() const
Return the type on the "a"-side.
Definition: flattype.h:351
cerata::FlatType::name_parts_
std::vector< NamePart > name_parts_
Name parts of this flattened type.
Definition: flattype.h:60
cerata::FlatType
A flattened type.
Definition: flattype.h:51
cerata::MappingMatrix::mapping_column
std::vector< std::pair< int64_t, T > > mapping_column(int64_t x)
Obtain non-zero element indices and value from column x, sorted by value.
Definition: flattype.h:194
cerata::IndexOfFlatType
int64_t IndexOfFlatType(const std::vector< FlatType > &flat_types_list, const Type *type)
Return the index of some Type in a list of FlatTypes.
Definition: flattype.cc:132
cerata::operator<
bool operator<(const FlatType &a, const FlatType &b)
Compares two FlatTypes first by name, then by nesting level. Useful for sorting.
Definition: flattype.cc:55
cerata::ContainsFlatType
bool ContainsFlatType(const std::vector< FlatType > &flat_types_list, const Type *type)
Return true if some Type is contained in a list of FlatTypes, false otherwise.
Definition: flattype.cc:123
cerata::TypeMapper::MakeImplicit
static std::shared_ptr< TypeMapper > MakeImplicit(Type *a, Type *b)
Construct a new TypeMapper from some type to another type, and automatically determine the type mappi...
Definition: flattype.cc:160
cerata::FlatType::reverse_
bool reverse_
Whether to invert this flattened type if it would be on a terminator node.
Definition: flattype.h:62
cerata::MappingPair::num_b
int64_t num_b() const
Return the number of FlatTypes on the "b"-side.
Definition: flattype.h:289
cerata::FlattenRecord
void FlattenRecord(std::vector< FlatType > *list, const Record *record, const std::optional< FlatType > &parent, bool invert)
Flatten a Record.
Definition: flattype.cc:63
cerata::MappingPair::index_b
index index_b(int64_t i) const
Return the index of the i-th FlatType on the "b"-side in the mapping matrix.
Definition: flattype.h:293
cerata::TypeMapper::TypeMapper
TypeMapper(Type *a, Type *b)
TypeMapper constructor. Constructs an empty type mapping.
Definition: flattype.cc:141
cerata::MappingPair::flat_type_b
FlatType flat_type_b(int64_t i) const
Return the i-th FlatType on the "b"-side in the mapping matrix.
Definition: flattype.h:301
cerata::Named
Convenience structure for anything that is named. Names are case-sensitive.
Definition: utils.h:40
cerata::Stream
A Stream type.
Definition: stream.h:26
cerata::MappingMatrix::width
int64_t width()
Return the width of the matrix.
Definition: flattype.h:131
cerata::FlatType::name
std::string name(const NamePart &root=NamePart(), const std::string &sep="_") const
Return the name of this flattened type, constructed from the name parts.
Definition: flattype.cc:32
cerata::stream
std::shared_ptr< Stream > stream(const std::string &name, const std::string &element_name, const std::shared_ptr< Type > &element_type, const std::vector< std::shared_ptr< Field >> &control)
Construct a new Stream type and return a shared pointer to it.
Definition: stream.cc:57
cerata::MappingPair::index_a
index index_a(int64_t i) const
Return the index of the i-th FlatType on the "a"-side in the mapping matrix.
Definition: flattype.h:291
cerata::TypeMapper::b
Type * b() const
Return the type on the "b"-side.
Definition: flattype.h:353
cerata::MappingPair::offset_b
offset offset_b(int64_t i) const
Return the offset of the i-th FlatType on the "b"-side in the mapping matrix.
Definition: flattype.h:297
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::TypeMapper::meta
std::unordered_map< std::string, std::string > meta
KV storage for metadata of tools or specific backend implementations.
Definition: flattype.h:368
cerata::NamePart::str
std::string str
The string of this name part.
Definition: flattype.h:45
cerata::MappingPair
A structure representing a mapping pair for a type mapping.
Definition: flattype.h:276
cerata::MappingMatrix::IsIdentity
bool IsIdentity() const
Return true if this is an identity matrix.
Definition: flattype.h:160
cerata::Flatten
void Flatten(std::vector< FlatType > *list, Type *type, const std::optional< FlatType > &parent, const std::string &name, bool invert, bool sep)
Flatten any Type.
Definition: flattype.cc:72
cerata::TypeMapper::map_matrix
MappingMatrix< int64_t > map_matrix()
Return the mapping matrix of this TypeMapper.
Definition: flattype.cc:215
cerata::MappingMatrix::height
int64_t height()
Return the height of the matrix.
Definition: flattype.h:129
cerata::TypeMapper::Add
TypeMapper & Add(int64_t a, int64_t b)
Add a mapping between two FlatTypes to the mapper.
Definition: flattype.cc:170
cerata::MappingMatrix
A matrix used for TypeMapper.
Definition: flattype.h:109
cerata::MappingPair::a
std::vector< IOF > a
Flattype and its index in a mapping matrix on the "a"-side.
Definition: flattype.h:283
cerata::FlattenStream
void FlattenStream(std::vector< FlatType > *list, const Stream *stream, const std::optional< FlatType > &parent, bool invert)
Flatten a Stream.
cerata::TypeMapper::SetMappingMatrix
void SetMappingMatrix(MappingMatrix< int64_t > map_matrix)
Set the mapping matrix of this TypeMapper.
Definition: flattype.cc:281
cerata::MappingMatrix::Empty
MappingMatrix Empty() const
Create an empty matrix of the same size.
Definition: flattype.h:242
cerata::TypeMapper::flat_a
std::vector< FlatType > flat_a() const
Return the list of flattened types on the "a"-side.
Definition: flattype.cc:217
cerata::TypeMapper::a_
Type * a_
Type of the "a"-side.
Definition: flattype.h:376
cerata::TypeMapper::fb_
std::vector< FlatType > fb_
The list of flattened types on the "b"-side.
Definition: flattype.h:374
cerata::TypeMapper::matrix_
MappingMatrix< int64_t > matrix_
The mapping matrix.
Definition: flattype.h:380
cerata::MappingPair::offset
int64_t offset
Definition: flattype.h:279
cerata::FlatType::nesting_level_
int nesting_level_
Nesting level in a type hierarchy.
Definition: flattype.h:58
cerata::MappingMatrix::get
T & get(int64_t y, int64_t x)
Return a reference to a value in the matrix at some index.
Definition: flattype.h:134
cerata::MappingPair::b
std::vector< IOF > b
Flattype and its index in a mapping matrix on the "b"-side.
Definition: flattype.h:285
cerata::MappingPair::offset_a
offset offset_a(int64_t i) const
Return the offset of the i-th FlatType on the "a"-side in the mapping matrix.
Definition: flattype.h:295
cerata::MappingPair::num_a
int64_t num_a() const
Return the number of FlatTypes on the "a"-side.
Definition: flattype.h:287
cerata::MappingPair::ToString
std::string ToString() const
Generate a human-readable version of this MappingPair.
Definition: flattype.cc:289