Fletchgen
The Fletcher Design Generator
bus.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/bus.h"
16 
17 #include <cerata/api.h>
18 #include <cerata/vhdl/vhdl.h>
19 
20 #include <memory>
21 #include <vector>
22 
23 #include "fletchgen/basic_types.h"
24 
25 namespace fletchgen {
26 
27 using cerata::PortArray;
28 using cerata::record;
29 using cerata::integer;
30 using cerata::string;
31 using cerata::boolean;
32 using cerata::strl;
33 using cerata::intl;
34 using cerata::booll;
35 using cerata::component;
36 using cerata::parameter;
37 using cerata::stream;
38 using cerata::field;
39 using cerata::vector;
40 using cerata::bit;
41 
42 PARAM_FACTORY(bus_addr_width)
43 PARAM_FACTORY(bus_data_width)
44 PARAM_FACTORY(bus_len_width)
45 PARAM_FACTORY(bus_burst_step_len)
46 PARAM_FACTORY(bus_burst_max_len)
47 
48 // Bus types
49 std::shared_ptr<Type> bus_read(const std::shared_ptr<Node> &addr_width,
50  const std::shared_ptr<Node> &data_width,
51  const std::shared_ptr<Node> &len_width) {
52  auto rreq = stream(record("", {field("addr", vector(addr_width)),
53  field("len", vector(len_width))}));
54  auto rdat = stream(record("", {field("data", vector(data_width)),
55  field("last", last())}));
56  auto result = record("", {field("rreq", rreq),
57  field("rdat", rdat)->Reverse()});
58  return result;
59 }
60 
61 std::shared_ptr<Type> bus_write(const std::shared_ptr<Node> &addr_width,
62  const std::shared_ptr<Node> &data_width,
63  const std::shared_ptr<Node> &len_width) {
64  auto wreq = stream(record("", {field("addr", vector(addr_width)),
65  field("len", vector(len_width)),
66  field("last", last())}));
67  auto wdat = stream(record("", {field("data", vector(data_width)),
68  field("strobe", vector(data_width / 8)),
69  field("last", last())}));
70  auto wrep = stream(record("", {field("ok", bit())}));
71  auto result = record("", {field("wreq", wreq),
72  field("wdat", wdat),
73  field("wrep", wrep)->Reverse()});
74  return result;
75 }
76 
77 static std::string GetBusArbiterName(BusFunction function) {
78  return std::string("Bus") + (function == BusFunction::READ ? "Read" : "Write")
79  + "ArbiterVec";
80 }
81 
82 Component *bus_arbiter(BusFunction function) {
83  // This component model corresponds to a VHDL primitive. Any modifications should be reflected accordingly.
84  auto name = GetBusArbiterName(function);
85 
86  // If it already exists, just return the existing component.
87  auto optional_existing_comp = cerata::default_component_pool()->Get(name);
88  if (optional_existing_comp) {
89  return *optional_existing_comp;
90  }
91 
92  // Create a new component.
93  auto result = component(name);
94 
95  // Parameters.
96  BusDimParams params(result);
97  BusSpecParams spec{params, function};
98 
99  // Remove unused params.
100  result->Remove(params.bs.get());
101  result->Remove(params.bm.get());
102 
103  auto num_slv = parameter("NUM_SLAVE_PORTS", 0);
104 
105  result->Add(num_slv);
106 
107  auto empty_str = strl("");
108 
109  result->Add({parameter("ARB_METHOD", std::string("RR-STICKY")),
110  parameter("MAX_OUTSTANDING", 4),
111  parameter("RAM_CONFIG", std::string("")),
112  parameter("SLV_REQ_SLICES", true),
113  parameter("MST_REQ_SLICE", true),
114  parameter("MST_DAT_SLICE", true),
115  parameter("SLV_DAT_SLICES", true)
116  });
117 
118  // Clock/reset
119  auto clk_rst = port("bcd", cr(), Port::Dir::IN, bus_cd());
120  // Master port
121  auto mst = bus_port("mst", Port::Dir::OUT, spec);
122  // Slave ports
123  auto slv_base = bus_port("slv", Port::Dir::OUT, spec);
124  slv_base->SetName("bsv");
125  slv_base->Reverse();
126  auto slv_arr = port_array(slv_base, num_slv);
127  // Add all ports.
128  result->Add({clk_rst, mst, slv_arr});
129 
130  // This component is a primitive as far as Cerata is concerned.
131  result->SetMeta(cerata::vhdl::meta::PRIMITIVE, "true");
132  result->SetMeta(cerata::vhdl::meta::LIBRARY, "work");
133  result->SetMeta(cerata::vhdl::meta::PACKAGE, "Interconnect_pkg");
134 
135  return result.get();
136 }
137 
138 std::shared_ptr<Component> BusReadSerializer() {
139  auto aw = parameter("ADDR_WIDTH", integer());
140  auto mdw = parameter("MASTER_DATA_WIDTH", integer());
141  auto mlw = parameter("MASTER_LEN_WIDTH", integer());
142  auto sdw = parameter("SLAVE_DATA_WIDTH", integer());
143  auto slw = parameter("SLAVE_LEN_WIDTH", integer());
144  static auto ret = component("BusReadSerializer", {
145  aw, mdw, mlw, sdw, slw,
146  parameter("SLAVE_MAX_BURST", integer()),
147  parameter("ENABLE_FIFO", boolean(), booll(false)),
148  parameter("SLV_REQ_SLICE_DEPTH", integer(), intl(2)),
149  parameter("SLV_DAT_SLICE_DEPTH", integer(), intl(2)),
150  parameter("MST_REQ_SLICE_DEPTH", integer(), intl(2)),
151  parameter("MST_DAT_SLICE_DEPTH", integer(), intl(2)),
152  port("bcd", cr(), Port::Dir::IN, bus_cd()),
153  port("mst", bus_read(aw, mlw, mdw), Port::Dir::OUT),
154  port("slv", bus_read(aw, slw, sdw), Port::Dir::OUT),
155  });
156  ret->SetMeta(cerata::vhdl::meta::PRIMITIVE, "true");
157  ret->SetMeta(cerata::vhdl::meta::LIBRARY, "work");
158  ret->SetMeta(cerata::vhdl::meta::PACKAGE, "Interconnect_pkg");
159  return ret;
160 }
161 
162 bool operator==(const BusSpec &lhs, const BusSpec &rhs) {
163  return (lhs.dim == rhs.dim) && (lhs.func == rhs.func);
164 }
165 
166 std::shared_ptr<Type> bus(const BusSpecParams &spec) {
167  std::shared_ptr<Type> result;
168  if (spec.func == BusFunction::READ) {
169  return bus_read(spec.dim.aw, spec.dim.dw, spec.dim.lw);
170  } else {
171  return bus_write(spec.dim.aw, spec.dim.dw, spec.dim.lw);
172  }
173 }
174 
175 std::shared_ptr<BusPort> bus_port(const std::string &name, Port::Dir dir, const BusSpecParams &params) {
176  return std::make_shared<BusPort>(name, dir, params);
177 }
178 
179 std::shared_ptr<BusPort> bus_port(Port::Dir dir, const BusSpecParams &params) {
180  return std::make_shared<BusPort>(params.ToName(), dir, params);
181 }
182 
183 #define BUS_PARAM_CONNECTION_FACTORY(NAME, ABBR) \
184  auto ABBR##_name = prefix + NAME()->name(); \
185  if (dst->Has(ABBR##_name)) { \
186  auto dst_##ABBR = dst->par(ABBR##_name); \
187  Connect(dst_##ABBR, src.ABBR); \
188  (*rebinding)[src.ABBR.get()] = dst_##ABBR; \
189  }
190 
191 void ConnectBusParam(cerata::Graph *dst,
192  const std::string &prefix,
193  const BusDimParams &src,
194  cerata::NodeMap *rebinding) {
195  BUS_PARAM_CONNECTION_FACTORY(bus_addr_width, aw)
196  BUS_PARAM_CONNECTION_FACTORY(bus_data_width, dw)
197  BUS_PARAM_CONNECTION_FACTORY(bus_len_width, lw)
198  BUS_PARAM_CONNECTION_FACTORY(bus_burst_step_len, bs)
199  BUS_PARAM_CONNECTION_FACTORY(bus_burst_max_len, bm)
200 }
201 
202 #undef BUS_PARAM_CONNECTION_FACTORY
203 
204 bool operator==(const BusDim &lhs, const BusDim &rhs) {
205  return (lhs.aw == rhs.aw) && (lhs.dw == rhs.dw) && (lhs.lw == rhs.lw) && (lhs.bs == rhs.bs) && (lhs.bm == rhs.bm);
206 }
207 
208 std::shared_ptr<cerata::Object> BusPort::Copy() const {
209  auto result = bus_port(name(), dir_, spec_);
210  // Take shared ownership of the type
211  auto typ = type()->shared_from_this();
212  result->SetType(typ);
213  return result;
214 }
215 
216 std::string BusDim::ToName() const {
217  std::stringstream str;
218  str << "AW" << std::to_string(aw);
219  str << "DW" << std::to_string(dw);
220  str << "LW" << std::to_string(lw);
221  str << "BS" << std::to_string(bs);
222  str << "BM" << std::to_string(bm);
223  return str.str();
224 }
225 
226 static std::vector<int64_t> ParseCSV(std::string str) {
227  std::vector<int64_t> result;
228  str += ',';
229  size_t pos = 0;
230  while ((pos = str.find(',')) != std::string::npos) {
231  result.push_back(std::strtoul(str.substr(0, pos).c_str(), nullptr, 10));
232  str.erase(0, pos + 1);
233  }
234  return result;
235 }
236 
237 BusDim BusDim::FromString(const std::string &str, BusDim default_to) {
238  BusDim result = default_to;
239  if (!str.empty()) {
240  auto values = ParseCSV(str);
241  if (values.size() != 5) {
242  FLETCHER_LOG(FATAL, "Bus dimensions string is invalid: " + str
243  + ". Expected: <address width>,<data width>,<len width>,<min burst>,<max burst>");
244  }
245  result.aw = static_cast<uint32_t>(values[0]);
246  result.dw = static_cast<uint32_t>(values[1]);
247  result.lw = static_cast<uint32_t>(values[2]);
248  result.bs = static_cast<uint32_t>(values[3]);
249  result.bm = static_cast<uint32_t>(values[4]);
250  }
251  return result;
252 }
253 
254 std::string BusDim::ToString() const {
255  std::stringstream str;
256  str << "address width: " << std::to_string(aw);
257  str << ", data width: " << std::to_string(dw);
258  str << ", burst length width: " << std::to_string(lw);
259  str << ", minimum burst size: " << std::to_string(bs);
260  str << ", maximum burst size: " << std::to_string(bm);
261  return str.str();
262 }
263 
264 std::vector<std::shared_ptr<Object>> BusDimParams::all() const {
265  return std::vector<std::shared_ptr<Object>>({aw, dw, lw, bs, bm});
266 }
267 
268 BusDimParams::BusDimParams(cerata::Graph *parent, BusDim dim, const std::string &prefix) : plain(dim) {
269  aw = bus_addr_width(dim.aw, prefix);
270  dw = bus_data_width(dim.dw, prefix);
271  lw = bus_len_width(dim.lw, prefix);
272  bs = bus_burst_step_len(dim.bs, prefix);
273  bm = bus_burst_max_len(dim.bm, prefix);
274  parent->Add({aw, dw, lw, bs, bm});
275 }
276 
277 std::string BusSpec::ToName() const {
278  return (func == BusFunction::READ ? "RD" : "WR") + dim.ToName();
279 }
280 
281 std::string BusSpecParams::ToName() const {
282  return BusSpec{*this}.ToName();
283 }
284 } // namespace fletchgen
Contains all classes and functions related to Fletchgen.
Definition: array.cc:29
std::shared_ptr< Type > bus_write(const std::shared_ptr< Node > &addr_width, const std::shared_ptr< Node > &data_width, const std::shared_ptr< Node > &len_width)
Return a Cerata type for a Fletcher bus write interface.
Definition: bus.cc:61
std::shared_ptr< Type > bus_read(const std::shared_ptr< Node > &addr_width, const std::shared_ptr< Node > &data_width, const std::shared_ptr< Node > &len_width)
Return a Cerata type for a Fletcher bus read interface.
Definition: bus.cc:49
std::shared_ptr< Type > cr()
Fletcher clock/reset;.
Definition: basic_types.cc:73
std::shared_ptr< Component > BusReadSerializer()
Return a BusReadSerializer component.
Definition: bus.cc:138
Component * bus_arbiter(BusFunction function)
Return a Cerata model of a BusArbiter.
Definition: bus.cc:82
std::shared_ptr< Type > bus(const BusSpecParams &spec)
Fletcher bus type with access mode conveyed through spec of params.
Definition: bus.cc:166
void ConnectBusParam(cerata::Graph *dst, const std::string &prefix, const BusDimParams &src, cerata::NodeMap *rebinding)
Find and connect all prefixed bus params on a graph to the supplied source params,...
Definition: bus.cc:191
std::shared_ptr< ClockDomain > bus_cd()
Fletcher bus clock domain.
Definition: basic_types.cc:67
std::shared_ptr< Type > last(int width, bool on_primitive)
Fletcher last.
Definition: basic_types.cc:129
std::shared_ptr< BusPort > bus_port(const std::string &name, Port::Dir dir, const BusSpecParams &params)
Make a new port and return a shared pointer to it.
Definition: bus.cc:175
bool operator==(const BusSpec &lhs, const BusSpec &rhs)
Returns true if BusSpecs are equal.
Definition: bus.cc:162
BusFunction
Defines function of a bus interface (read/write).
Definition: bus.h:42
@ READ
Interface reads from memory.
Holds bus interface dimensions.
Definition: bus.h:48
uint32_t dw
Data width.
Definition: bus.h:50
std::string ToString() const
Return a human-readable version of the bus dimensions.
Definition: bus.cc:254
std::string ToName() const
Return a shorter somewhat human-readable name for this BusDims, can be used for comparisons.
Definition: bus.cc:216
uint32_t lw
Len width.
Definition: bus.h:51
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
uint32_t bs
Burst step length.
Definition: bus.h:52
uint32_t aw
Address width.
Definition: bus.h:49
uint32_t bm
Burst max length.
Definition: bus.h:53
Holds bus parameters based on bus dimensions, that has actual nodes representing the dimensions.
Definition: bus.h:68
std::shared_ptr< Node > aw
Value nodes.
Definition: bus.h:79
std::shared_ptr< Node > lw
Len width node.
Definition: bus.h:81
BusDimParams(cerata::Graph *parent, BusDim dim=BusDim{}, const std::string &prefix="")
Construct a new bunch of bus parameters based on a bus spec and function, and add them to a graph.
Definition: bus.cc:268
std::shared_ptr< Node > dw
Data width node.
Definition: bus.h:80
std::vector< std::shared_ptr< Object > > all() const
Return all parameters as an object vector.
Definition: bus.cc:264
std::shared_ptr< Node > bs
Burst step length node.
Definition: bus.h:82
std::shared_ptr< Node > bm
Burst max length node.
Definition: bus.h:83
std::shared_ptr< Object > Copy() const override
Deep-copy the BusPort.
Definition: bus.cc:208
BusSpecParams spec_
The bus spec to which the type generics of the bus port are bound.
Definition: bus.h:139
Holds bus dimensions and function, without instantiating Cerata nodes.
Definition: bus.h:100
std::string ToName() const
Return a shorter somewhat human-readable name, can be used for comparisons.
Definition: bus.cc:277
BusDim dim
Bus dimensions.
Definition: bus.h:106
BusFunction func
Bus function.
Definition: bus.h:108
Holds bus parameters and function based on bus dimensions, that has actual nodes representing the dim...
Definition: bus.h:90
std::string ToName() const
Return a shorter somewhat human-readable name, can be used for comparisons.
Definition: bus.cc:281
BusFunction func
Bus function.
Definition: bus.h:94
BusDimParams dim
Bus dimensions.
Definition: bus.h:92