Fletchgen
The Fletcher Design Generator
schema.cc
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 #include "fletchgen/schema.h"
16 
17 #include <fletcher/common.h>
18 
19 #include <string>
20 #include <algorithm>
21 #include <memory>
22 #include <utility>
23 #include <vector>
24 #include <optional>
25 
26 #include "fletchgen/bus.h"
27 
28 namespace fletchgen {
29 
30 SchemaSet::SchemaSet(std::string name) : Named(std::move(name)) {}
31 
32 std::shared_ptr<SchemaSet> SchemaSet::Make(const std::string &name) {
33  return std::make_shared<SchemaSet>(name);
34 }
35 
37  for (const auto &fs : schemas_) {
38  if (fs->mode() == fletcher::Mode::READ) {
39  return true;
40  }
41  }
42  return false;
43 }
44 
46  for (const auto &fs : schemas_) {
47  if (fs->mode() == fletcher::Mode::WRITE) {
48  return true;
49  }
50  }
51  return false;
52 }
53 
54 bool SchemaSet::HasSchemaWithName(const std::string &name) const {
55  for (const auto &fs : schemas_) {
56  if (fs->name() == name) {
57  return true;
58  }
59  }
60  return false;
61 }
62 
63 void SchemaSet::AppendSchema(const std::shared_ptr<arrow::Schema> &arrow_schema) {
64  auto name = fletcher::GetMeta(*arrow_schema, fletcher::meta::NAME);
65  if (name.empty()) {
66  FLETCHER_LOG(WARNING, "Skipping anonymous schema with the following contents:\n" + arrow_schema->ToString());
67  FLETCHER_LOG(WARNING, "Append {'fletcher_name' : '<name>'} kv-metadata to the schema "
68  "to include this schema in hardware generation.");
69  return;
70  }
71  if (!HasSchemaWithName(name)) {
72  auto fs = std::make_shared<FletcherSchema>(arrow_schema);
73  schemas_.push_back(fs);
74  } else {
75  // If a schema with this name already exists. If so, check if its equal.
76  // This would not be an error, since it may come from a recordbatch with the same schema.
77  auto other = GetSchema(name);
78  if ((*other)->arrow_schema()->Equals(*arrow_schema)) {
79  FLETCHER_LOG(INFO, "Duplicate but equal schema in SchemaSet: " + name);
80  } else {
81  // If it's not equal, it's quite fatal. The user should fix their schema.
82  FLETCHER_LOG(FATAL, "Duplicate schema detected in SchemaSet: " + name);
83  }
84  }
85 }
86 
87 std::optional<std::shared_ptr<FletcherSchema>> SchemaSet::GetSchema(const std::string &name) const {
88  for (const auto &fs : schemas_) {
89  if (fs->name() == name) {
90  return fs;
91  }
92  }
93  return std::nullopt;
94 }
95 
96 std::vector<std::shared_ptr<FletcherSchema>> SchemaSet::read_schemas() const {
97  std::vector<std::shared_ptr<FletcherSchema>> ret;
98  for (const auto &s : schemas_) {
99  if (s->mode() == Mode::READ) {
100  ret.push_back(s);
101  }
102  }
103  return ret;
104 }
105 
106 std::vector<std::shared_ptr<FletcherSchema>> SchemaSet::write_schemas() const {
107  std::vector<std::shared_ptr<FletcherSchema>> ret;
108  for (const auto &s : schemas_) {
109  if (s->mode() == Mode::WRITE) {
110  ret.push_back(s);
111  }
112  }
113  return ret;
114 }
115 
117  struct {
118  bool operator()(const std::shared_ptr<FletcherSchema> &a, const std::shared_ptr<FletcherSchema> &b) {
119  return a->name() < b->name();
120  }
121  } NameSort;
122 
123  struct {
124  bool operator()(const std::shared_ptr<FletcherSchema> &a, const std::shared_ptr<FletcherSchema> &b) {
125  if (a->mode() == b->mode()) {
126  return false;
127  } else if (a->mode() == Mode::WRITE) {
128  return false;
129  }
130  return true;
131  }
132  } ModeSort;
133 
134  // Sort the schemas by name, then by mode
135  std::sort(schemas_.begin(), schemas_.end(), NameSort);
136  // Important to keep stable sorting here, else we might lose name order.
137  std::stable_sort(schemas_.begin(), schemas_.end(), ModeSort);
138 }
139 
140 FletcherSchema::FletcherSchema(const std::shared_ptr<arrow::Schema> &arrow_schema, const std::string &schema_name)
141  : arrow_schema_(arrow_schema), mode_(fletcher::GetMode(*arrow_schema)) {
142 
143  // Get name from metadata, if available
144  name_ = fletcher::GetMeta(*arrow_schema_, fletcher::meta::NAME);
145  if (name_.empty()) {
146  FLETCHER_LOG(FATAL, "Schema has no name. Append {'fletcher_name' : '<name>'} kv-metadata to the schema. "
147  "Schema: " + arrow_schema->ToString());
148  }
149  auto bus_spec_val = fletcher::GetMeta(*arrow_schema_, fletcher::meta::BUS_SPEC);
150  bus_dims_ = BusDim::FromString(bus_spec_val, BusDim());
151  FLETCHER_LOG(DEBUG, "Schema " + name() + ":");
152  FLETCHER_LOG(DEBUG, " Direction : " + cerata::Term::str(mode2dir(mode_)));
153  FLETCHER_LOG(DEBUG, " Bus spec : " + bus_dims_.ToString());
154 }
155 
156 std::shared_ptr<FletcherSchema> FletcherSchema::Make(const std::shared_ptr<arrow::Schema> &arrow_schema,
157  const std::string &schema_name) {
158  return std::make_shared<FletcherSchema>(arrow_schema, schema_name);
159 }
160 
161 } // namespace fletchgen
FletcherSchema(const std::shared_ptr< arrow::Schema > &arrow_schema, const std::string &schema_name="")
Construct a new Fletcher schema.
Definition: schema.cc:140
static std::shared_ptr< FletcherSchema > Make(const std::shared_ptr< arrow::Schema > &arrow_schema, const std::string &schema_name="")
Make a new FletcherSchema, returning a shared pointer to it.
Definition: schema.cc:156
std::shared_ptr< arrow::Schema > arrow_schema() const
Return the Arrow schema that this FletcherSchema was based on.
Definition: schema.h:50
std::string name() const
Return the name of this FletcherSchema.
Definition: schema.h:55
std::vector< std::shared_ptr< FletcherSchema > > read_schemas() const
Return all schemas with read mode.
Definition: schema.cc:96
SchemaSet(std::string name)
SchemaSet constructor.
Definition: schema.cc:30
bool RequiresReading() const
Determine whether any schema in this set requires reading from memory.
Definition: schema.cc:36
std::vector< std::shared_ptr< FletcherSchema > > write_schemas() const
Return all schemas with write mode.
Definition: schema.cc:106
void Sort()
Sort the schemas by name, then by read/write mode.
Definition: schema.cc:116
static std::shared_ptr< SchemaSet > Make(const std::string &name)
Make a new, empty SchemaSet, and return a shared pointer to it.
Definition: schema.cc:32
bool HasSchemaWithName(const std::string &name) const
Return true if set contains schema with some name, false otherwise.
Definition: schema.cc:54
void AppendSchema(const std::shared_ptr< arrow::Schema > &schema)
Append a schema.
Definition: schema.cc:63
std::optional< std::shared_ptr< FletcherSchema > > GetSchema(const std::string &name) const
Optionally return a schema with name, if it exists.
Definition: schema.cc:87
bool RequiresWriting() const
Determine whether any schema in this set requires writing to memory.
Definition: schema.cc:45
Contains all classes and functions related to Fletchgen.
Definition: array.cc:29
cerata::Port::Dir mode2dir(fletcher::Mode mode)
Return a Cerata port direction from a Fletcher access mode.
Definition: utils.cc:35
Holds bus interface dimensions.
Definition: bus.h:48
std::string ToString() const
Return a human-readable version of the bus dimensions.
Definition: bus.cc:254
static BusDim FromString(const std::string &str, BusDim default_to)
Returns a BusDim from a string. See [common/cpp/include/fletcher/arrow-utils.h] for more info.
Definition: bus.cc:237