 |
Cerata
A library to generate structural hardware designs
|
15 #include "cerata/vhdl/architecture.h"
22 #include "cerata/node.h"
23 #include "cerata/edge.h"
24 #include "cerata/expression.h"
25 #include "cerata/graph.h"
26 #include "cerata/vhdl/block.h"
27 #include "cerata/vhdl/declaration.h"
28 #include "cerata/vhdl/instantiation.h"
29 #include "cerata/vhdl/vhdl.h"
37 for (
const auto &ic : inst_comps) {
40 if ((ic->meta().count(meta::PRIMITIVE) == 0) || (ic->meta().at(meta::PRIMITIVE) !=
"true")) {
53 for (
const auto &i : instances) {
63 result <<
Line(
"architecture Implementation of " + comp.
name() +
" is");
65 result << GenerateNodeDeclarations<Signal>(comp, 1);
66 result << GenerateNodeDeclarations<SignalArray>(comp, 1);
67 result <<
Line(
"begin");
69 result << GenerateAssignments<Port>(comp, 1);
70 result << GenerateAssignments<Signal>(comp, 1);
71 result << GenerateAssignments<SignalArray>(comp, 1);
72 result <<
Line(
"end architecture;");
79 const std::shared_ptr<Node> &offset_a,
81 const std::shared_ptr<Node> &offset_b,
82 const std::string &lh_prefix,
83 const std::string &rh_prefix,
88 std::shared_ptr<Node> next_offset_a;
89 std::shared_ptr<Node> next_offset_b;
94 next_offset_a = (offset_a + (b_width ? b_width.value() :
rintl(0)));
95 next_offset_b = (offset_b + (a_width ? a_width.value() :
rintl(0)));
112 a = a_ft.
name(NamePart(lh_prefix,
true));
115 if ((p.
num_b() > 1) || a_is_array) {
117 a +=
"(" + offset_a->ToString() +
")";
119 a +=
"(" + (next_offset_a - 1ul)->
ToString();
120 a +=
" downto " + offset_a->ToString() +
")";
123 b = b_ft.name(NamePart(rh_prefix,
true));
124 if ((p.
num_a() > 1) || b_is_array) {
126 b +=
"(" + offset_b->ToString() +
")";
128 b +=
"(" + (next_offset_b - 1ul)->
ToString();
129 b +=
" downto " + offset_b->ToString() +
")";
134 l << b <<
" <= " << a;
136 l << a <<
" <= " << b;
144 static Block GenerateAssignmentPair(std::vector<MappingPair> pairs,
const Node &a,
const Node &b) {
147 std::sort(pairs.begin(), pairs.end(), [](
const MappingPair &x,
const MappingPair &y) ->
bool {
148 return x.index_a(0) < y.index_a(0);
150 bool a_array =
false;
151 bool b_array =
false;
157 a_idx = a.array().value()->IndexOf(a);
161 b_idx = b.array().value()->IndexOf(b);
164 for (
const auto &pair : pairs) {
166 std::shared_ptr<Node> b_offset = pair.width_a(
intl(1)) * b_idx;
168 for (int64_t ia = 0; ia < pair.num_a(); ia++) {
170 auto a_width = pair.flat_type_a(ia).type_->width();
172 std::shared_ptr<Node> a_offset = pair.width_b(
intl(1)) * a_idx;
173 for (int64_t ib = 0; ib < pair.num_b(); ib++) {
175 auto b_width = pair.flat_type_b(ib).type_->width();
177 auto mpblock = GenerateMappingPair(pair, ia, a_offset, ib, b_offset, a.name(), b.name(), a_array, b_array);
180 a_offset = a_offset + (b_width ? b_width.value() :
rintl(1));
183 b_offset = b_offset + (a_width ? a_width.value() :
rintl(1));
189 static Block GenerateNodeAssignment(
const Node &dst,
const Node &src) {
192 auto optional_type_mapper = dst.type()->GetMapper(src.type());
193 if (optional_type_mapper) {
194 auto type_mapper = optional_type_mapper.value();
196 auto pairs = type_mapper->GetUniqueMappingPairs();
198 result << GenerateAssignmentPair(pairs, dst, src);
201 CERATA_LOG(FATAL,
"No type mapping available for: Node[" + dst.name() +
": " + dst.type()->name()
202 +
"] from Other[" + src.name() +
" : " + src.type()->name() +
"]");
217 auto edge =
port.input().value();
218 if (!edge->src()->IsSignal()) {
219 CERATA_LOG(FATAL,
"Component port is not sourced by signal.");
221 ret << GenerateNodeAssignment(*edge->dst(), *edge->src());
235 auto edge = sig.
input().value();
237 Node *src = edge->src();
238 Node *dst = edge->dst();
242 if (src->IsPort() && src->
parent() && src->
parent().value()->IsInstance()) {
249 auto pairs = type_mapper.value()->GetUniqueMappingPairs();
251 b << GenerateAssignmentPair(pairs, *dst, *src);
255 CERATA_LOG(FATAL,
"Assignment of signal " + src->
ToString()
257 +
" failed. No type mapper available.");
265 for (
const auto &node : sig_array.
nodes()) {
266 if (node->IsSignal()) {
267 const auto &sig =
dynamic_cast<const Signal &
>(*node);
270 CERATA_LOG(FATAL,
"Signal Array contains non-signal node.");
273 return ret.
Sort(
'(');
virtual std::vector< const Component * > GetAllInstanceComponents() const
Returns all unique Components that are referred to by child Instances of this graph.
std::vector< Node * > nodes() const
Return all nodes of this NodeArray.
An array of signal nodes.
A structure to hold multiple blocks.
FlatType flat_type_a(int64_t i) const
Return the i-th FlatType on the "a"-side in the mapping matrix.
Type * type_
A pointer to the original type.
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...
bool Is(ID type_id) const
Return true if the Type ID is type_id, false otherwise.
std::vector< Instance * > children() const
Returns all Instance graphs from this Component.
static Block Generate(const Parameter &par, int depth=0)
Generate a parameter declaration as VHDL generic.
static MultiBlock Generate(const Graph &graph)
Generate a VHDL instantiation of a graph.
std::string name() const
Return the name of the object.
std::shared_ptr< Literal > intl(int64_t i)
Obtain a shared pointer to an integer literal from the default node pool.
bool reverse_
Whether to invert this flattened type if it would be on a terminator node.
int64_t num_b() const
Return the number of FlatTypes on the "b"-side.
FlatType flat_type_b(int64_t i) const
Return the i-th FlatType on the "b"-side in the mapping matrix.
virtual std::optional< Node * > width() const
Return the width of the type, if it is synthesizable.
std::string name(const NamePart &root=NamePart(), const std::string &sep="_") const
Return the name of this flattened type, constructed from the name parts.
std::string ToString(const std::vector< Block > &blocks)
Return a vector of blocks as a single string.
Literal * rintl(int64_t i)
Obtain a raw pointer to an integer literal from the default node pool.
Block & Sort(std::optional< char > c=std::nullopt)
Sort the lines in the block. Supply a character to stop sorting per line after encountering the chara...
A structure representing a mapping pair for a type mapping.
static MultiBlock GenerateCompDeclarations(const Component &comp, int indent=0)
Generate component declarations within VHDL architecture declarations block.
virtual std::string ToString() const
Return a human-readable string of this node.
static MultiBlock Generate(const Component &comp)
Generate the VHDL architecture of a component.
static MultiBlock GenerateCompInstantiations(const Component &comp, int indent=0)
Generate component instantiations within VHDL architecture concurrent statements block.
std::optional< Edge * > input() const
Return the single incoming edge.
virtual std::optional< Graph * > parent() const
Return the parent graph of this object, if any. Returns empty option otherwise.
A port is a terminator node on a graph.
std::shared_ptr< Port > port(const std::string &name, const std::shared_ptr< Type > &type, Term::Dir dir, const std::shared_ptr< ClockDomain > &domain)
Make a new port with some name, type and direction.
Type * type() const
Return the node Type.
Contains everything related to the VHDL back-end.
int64_t num_a() const
Return the number of FlatTypes on the "a"-side.