 |
Cerata
A library to generate structural hardware designs
|
15 #include "cerata/type.h"
21 #include "cerata/utils.h"
22 #include "cerata/node.h"
23 #include "cerata/flattype.h"
24 #include "cerata/pool.h"
29 return type_id ==
id_;
37 case BIT : ret =
name() +
":Bit";
49 default :
throw std::runtime_error(
"Corrupted Type ID.");
52 if (show_meta || show_mappers) {
55 ret += ::cerata::ToString(
meta);
56 if (show_mappers && !
mappers_.empty()) {
61 if (show_mappers && !
mappers_.empty()) {
65 ret += m->b()->ToString();
82 void Type::AddMapper(
const std::shared_ptr<TypeMapper> &mapper,
bool remove_existing) {
83 Type *other = mapper->b();
86 if (!remove_existing) {
87 CERATA_LOG(FATAL,
"Mapper already exists to convert "
88 "from " + this->
ToString(
true,
true) +
" to " + other->
ToString(
true,
true));
95 if (mapper->a() !=
this) {
96 CERATA_LOG(FATAL,
"Type converter does not convert from " +
name());
108 std::optional<std::shared_ptr<TypeMapper>>
Type::GetMapper(
const std::shared_ptr<Type> &other) {
115 if (m->CanConvert(
this, other)) {
120 if (generate_implicit) {
151 if ((*m)->CanConvert(
this, other)) {
160 return other.
id() ==
id_;
166 if (nodes.size() != generics.size()) {
167 CERATA_LOG(ERROR,
"Type contains " + std::to_string(generics.size())
168 +
" generics, but only " + std::to_string(nodes.size())
169 +
" arguments were supplied.");
173 for (
size_t i = 0; i < generics.size(); i++) {
174 map[generics[i]] = nodes[i];
185 :
Type(std::move(name),
Type::VECTOR) {
187 if (!(
width->IsParameter() ||
width->IsLiteral() ||
width->IsExpression())) {
188 CERATA_LOG(FATAL,
"Vector width can only be Parameter, Literal or Expression node.");
193 std::shared_ptr<Type>
vector(
const std::string &name,
const std::shared_ptr<Node> &width) {
194 return std::make_shared<Vector>(name, width);
197 std::shared_ptr<Type>
vector(
const std::shared_ptr<Node> &width) {
198 return std::make_shared<Vector>(
"Vec_" + width->ToString(), width);
201 std::shared_ptr<Type>
vector(
unsigned int width) {
202 return vector(
"vec_" + std::to_string(width),
intl(
static_cast<int>(width)));
205 std::shared_ptr<Type>
vector(std::string name,
unsigned int width) {
207 ret->SetName(std::move(name));
219 if (width_ && other.
width()) {
228 if (!width_->IsLiteral()) {
229 return {width_.get()};
236 width_ = std::move(
width);
240 std::shared_ptr<Type>
bit(
const std::string &name) {
243 static std::shared_ptr<Type> result = std::make_shared<Bit>(name);
246 std::shared_ptr<Type> result = std::make_shared<Bit>(name);
252 static std::shared_ptr<Type> result = std::make_shared<Boolean>(
"boolean");
257 static std::shared_ptr<Type> result = std::make_shared<Integer>(
"integer");
262 static std::shared_ptr<Type> result = std::make_shared<String>(
"string");
270 Field::Field(std::string name, std::shared_ptr<Type> type,
bool reverse,
bool sep)
271 :
Named(std::move(name)), type_(std::move(type)), reverse_(reverse), sep_(sep) {}
273 std::shared_ptr<Field>
field(
const std::string &name,
const std::shared_ptr<Type> &type,
bool reverse,
bool sep) {
274 return std::make_shared<Field>(name, type, reverse, sep);
277 std::shared_ptr<Field>
field(
const std::shared_ptr<Type> &type,
bool reverse,
bool sep) {
278 return std::make_shared<Field>(type->name(), type, reverse, sep);
288 auto it =
fields_.begin() + *index;
297 :
Type(std::move(name),
Type::RECORD), fields_(std::move(fields)) {
299 std::vector<std::string> names;
301 names.push_back(
field->name());
304 CERATA_LOG(ERROR,
"Record field names must be unique.");
308 std::shared_ptr<Record>
record(
const std::string &name,
const std::vector<std::shared_ptr<Field>> &fields) {
309 return std::make_shared<Record>(name, fields);
312 std::shared_ptr<Record>
record(
const std::string &name) {
313 return record(name, std::vector<std::shared_ptr<Field>>());
316 std::shared_ptr<Record>
record(
const std::vector<std::shared_ptr<Field>> &fields) {
317 return record(std::string(
""), fields);
320 std::shared_ptr<Record>
record(
const std::initializer_list<std::shared_ptr<Field>> &fields) {
321 return record(std::string(
""), std::vector<std::shared_ptr<Field>>(fields.begin(), fields.end()));
325 if (&other ==
this) {
333 auto &other_record =
dynamic_cast<const Record &
>(other);
334 if (other_record.num_fields() != this->
num_fields()) {
338 for (
size_t i = 0; i < this->
num_fields(); i++) {
339 auto a = this->
at(i);
340 auto b = other_record.at(i);
341 if (a->reversed() != b->reversed()) {
344 if (!a->type()->IsEqual(*b->type())) {
353 std::vector<Node *> result;
355 auto field_params =
field->type()->GetGenerics();
356 result.insert(result.end(), field_params.begin(), field_params.end());
362 std::vector<Type *> result;
365 result.push_back(
field->type().get());
367 auto nested =
field->type()->GetNested();
368 result.insert(result.end(), nested.begin(), nested.end());
374 for (
const auto &f :
fields_) {
375 if (!f->type()->IsPhysical()) {
383 for (
const auto &f :
fields_) {
384 if (f->type()->IsGeneric()) {
392 std::shared_ptr<Type> result;
397 for (
const auto &mapper :
mappers_) {
398 auto new_mapper = mapper->Make(result.get(), mapper->b());
399 new_mapper->SetMappingMatrix(mapper->map_matrix());
400 result->AddMapper(new_mapper);
407 std::shared_ptr<Type> result;
408 std::optional<std::shared_ptr<Node>> new_width = width_;
409 if (rebinding.count(width_.get()) > 0) {
410 new_width = rebinding.at(width_.get())->shared_from_this();
416 for (
const auto &mapper :
mappers_) {
417 auto new_mapper = mapper->Make(result.get(), mapper->b());
418 new_mapper->SetMappingMatrix(mapper->map_matrix());
419 result->AddMapper(new_mapper);
426 std::shared_ptr<Field> result;
428 if (type_->IsGeneric()) {
429 type = type_->Copy(rebinding);
437 type_ = std::move(
type);
443 return shared_from_this();
447 std::shared_ptr<Type> result;
448 std::vector<std::shared_ptr<Field>>
fields;
449 for (
const auto &f :
fields_) {
450 fields.push_back(f->Copy(rebinding));
456 for (
const auto &mapper :
mappers_) {
457 auto new_mapper = mapper->Make(result.get(), mapper->b());
458 new_mapper->SetMappingMatrix(mapper->map_matrix());
459 result->AddMapper(new_mapper);
467 CERATA_LOG(FATAL,
"Field index out of bounds.");
485 if (f->name() ==
name) {
489 CERATA_LOG(ERROR,
"Field with name " +
name +
" does not exist on Record type " + this->
name()
496 std::stringstream ss;
497 for (
const auto &f :
fields_) {
std::vector< std::shared_ptr< TypeMapper > > mappers() const
Return possible type mappers.
std::vector< std::shared_ptr< Field > > fields_
The fields of this Record.
size_t num_fields() const
Return the number of fields in this record.
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.
static std::shared_ptr< TypeMapper > Make(Type *a)
Construct a new TypeMapper from some type to itself, and return a smart pointer to it.
std::string ToStringFieldNames() const
Return the names of the fields as a comma separated string.
std::unordered_map< std::string, std::string > meta
Metadata for back-end implementations.
Field(std::string name, std::shared_ptr< Type > type, bool reverse=false, bool sep=true)
RecordField constructor.
bool IsPhysical() const override
Return true if the Type has an immediate physical representation, false otherwise.
std::shared_ptr< Field > Reverse()
Reverse the direction of this field and return itself.
std::shared_ptr< Field > NoSep(std::shared_ptr< Field > field)
Convenience function to disable the separator for a record field.
virtual bool IsEqual(const Type &other) const
Determine if this Type is exactly equal to an other Type.
std::vector< T * > ToRawPointers(const std::vector< std::shared_ptr< T >> &list)
Convert a list of shared pointers to raw pointers.
std::optional< Node * > width() const override
Return a pointer to the node representing the width of this vector, if specified.
Record(std::string name, std::vector< std::shared_ptr< Field >> fields={})
Record constructor.
A Record type containing zero or more fields.
Type(std::string name, ID id)
Type constructor.
Contains every Cerata class, function, etc...
Field * operator[](size_t i) const
Return the field at index i contained by this record.
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...
Field * at(const std::string &name) const
Return the field with a specific name.
Type & SetWidth(std::shared_ptr< Node > width)
Set the width of this vector.
Field & SetType(std::shared_ptr< Type > type)
Change the type of this field.
virtual bool CanGenerateMapper(const Type &other) const
Check if a mapper can be generated to another specific type.
std::unordered_map< std::string, std::string > meta
KV storage for metadata of tools or specific backend implementations.
std::unordered_map< const Node *, Node * > NodeMap
A mapping from one object to another object, used in e.g. type generic rebinding.
bool Is(ID type_id) const
Return true if the Type ID is type_id, false otherwise.
ID id() const
Return the Type ID.
int RemoveMappersTo(Type *other)
Remove all mappers to a specific type.
bool IsGeneric() const override
Return true if the Type is a generic type.
std::string name() const
Return the name of the object.
std::string ToString(bool show_meta=false, bool show_mappers=false) const
Return the Type ID as a human-readable string.
std::vector< Node * > GetGenerics() const override
Return all nodes that potentially parametrize the fields of this record.
Vector(std::string name, const std::shared_ptr< Node > &width)
Vector constructor.
std::vector< std::shared_ptr< TypeMapper > > mappers_
A list of mappers that can map this type to another type.
std::shared_ptr< Type > string()
Return a static string type.
std::shared_ptr< Type > boolean()
Return a static boolean type.
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...
std::shared_ptr< Literal > intl(int64_t i)
Obtain a shared pointer to an integer literal from the default node pool.
void AddMapper(const std::shared_ptr< TypeMapper > &mapper, bool remove_existing=true)
Add a type mapper.
std::vector< Type * > GetNested() const override
Obtain any nested types.
virtual std::shared_ptr< TypeMapper > GenerateMapper(Type *other)
Generate a new mapper to a specific other type. Should be checked with CanGenerateMapper first,...
Convenience structure for anything that is named. Names are case-sensitive.
bool Has(const std::string &name) const
Return true if record has field with name name.
virtual std::optional< Node * > width() const
Return the width of the type, if it is synthesizable.
std::vector< std::shared_ptr< Field > > fields() const
Return all fields contained by this record.
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.
bool IsEqual(const Type &other) const override
Determine if this Type is exactly equal to an other Type.
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.
Literal * rintl(int64_t i)
Obtain a raw pointer to an integer literal from the default node pool.
Record & AddField(const std::shared_ptr< Field > &field, std::optional< size_t > index=std::nullopt)
Add a field to this Record.
std::shared_ptr< Field > Copy(const NodeMap &rebinding) const
Create a copy of the field.
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.
virtual std::vector< Node * > GetGenerics() const
Obtain any nodes that this type uses as generics.
std::shared_ptr< Type > integer()
Return a static integer type.
std::optional< Node * > width() const override
Bit width returns integer literal 1.
std::shared_ptr< Type > bit(const std::string &name)
Return a static bit type.
std::shared_ptr< Type > type() const
Return the type of the RecordField.
virtual std::shared_ptr< Type > Copy() const
Make a copy of the type without rebinding.
bool IsEqual(const Type &other) const override
Determine if this Type is exactly equal to an other Type.
std::vector< Node * > GetGenerics() const override
Returns the width parameter of this vector, if any. Otherwise an empty list;.
std::vector< T > Unique(const std::vector< T > &vec)
Return a copy of a vector without any duplicates.
ID
The Type ID. Used for convenient type checking.