CGRA-ME
ModuleRoutingStructures.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * The software programs comprising "CGRA-ME" and the documentation provided
3  * with them are copyright by its authors and the University of Toronto. Only
4  * non-commercial, not-for-profit use of this software is permitted without ex-
5  * plicit permission. This software is provided "as is" with no warranties or
6  * guarantees of support. See the LICENCE for more details. You should have re-
7  * ceived a copy of the full licence along with this software. If not, see
8  * <http://cgra-me.ece.utoronto.ca/license/>.
9  ******************************************************************************/
10 
11 #include <CGRA/Module.h>
12 
13 #include <regex>
14 #include <unordered_set>
15 #include <unordered_map>
16 
17 /************ Register **********/
18 Register::Register(std::string name, Location loc, int size, bool isElastic)
19  : Module(name, loc, size, isElastic)
20 {
22  // Create ports
23  addPort("in", PORT_INPUT, "size" ,size, isElastic);
24  addPort("out", PORT_OUTPUT_REG, "size", size, isElastic);
25  addPort("enable", PORT_CONFIG, 1, isElastic);
26 
27 
28  // Add position for visualization
29  node_relative_position.insert({"in", {0, 0}});
30  node_relative_position.insert({"m_in", {0, 1.0/6}});
31  node_relative_position.insert({"reg", {0, 2.0/6}});
32  node_relative_position.insert({"m_out", {0, 3.0/6}});
33  node_relative_position.insert({"m_enable", {0, 4.0/6}});
34  node_relative_position.insert({"out", {0, 5.0/6}});
35 }
36 
37 // Virtual function that overrides Module::GenericName. Returns generic name of the object
38 std::string Register::GenericName()
39 {
40  std::string elas = isElastic ? "elastic_" : "";
41  return elas + "register_" + std::to_string(getSize()) + "b";
42 }
43 
44 // Virtual function that overrides Module::GetFunctionality. Generates the functionality for register
45 void Register::GenFunctionality() // Virtual function override
46 {
47  std::cout << SET_INDENT << "always @(posedge CGRA_Clock, posedge CGRA_Reset)\n";
48  std::cout << SET_DOUBLE_INDENT << "if (CGRA_Reset == 1)\n";
49  std::cout << SET_TRIPLE_INDENT << "out <= 0;\n";
50  std::cout << SET_DOUBLE_INDENT << "else\n";
51  std::cout << SET_TRIPLE_INDENT << "out <= in;\n";
52 }
53 
54 // CoreIR Implementation of GenFunctionality
55 nlohmann::json Register::CoreIRGenFunctionality() // Virtual function override
56 {
57  nlohmann::json vjson;
58 
59  // Create Header
60  vjson["prefix"] = "cgrame_";
61  vjson["parameters"] = {};
62  for (auto& parameter : parameterlist)
63  {
64  vjson["parameters"].push_back(parameter.first);
65  }
66  vjson["interface"] = {};
67  vjson["interface"].push_back("CGRA_Clock");
68  vjson["interface"].push_back("CGRA_Reset");
69  vjson["interface"].push_back("CGRA_Enable");
70 
71 
72  for (auto& port : ports)
73  {
74  std::string portName = port.second->getName();
75  vjson["interface"].push_back(portName);
76  }
77 
78  // module definition
79  std::string moduleDefinition;
80  moduleDefinition += std::string(SET_INDENT) + "input CGRA_Clock;\n";
81  moduleDefinition += std::string(SET_INDENT) + "input CGRA_Reset;\n";
82  moduleDefinition += std::string(SET_INDENT) + "input CGRA_Enable;\n";
83  for (auto& port : ports)
84  {
85  port_type portType = port.second->pt;
86  std::string portTypeString = {};
87  if(portType == port_type::PORT_INPUT)
88  {
89  portTypeString = "input";
90  }
91  else if (portType == port_type::PORT_OUTPUT)
92  {
93  portTypeString = "output";
94  }
95  else if (portType == port_type::PORT_OUTPUT_REG)
96  {
97  portTypeString = "output reg";
98  }
99  else
100  {
101  portTypeString = "inout";
102  }
103  std::string portSizeString;
104  if (!(port.second->parameter).empty()) // Check if size is parameterized
105  {
106  std::string portParameterName = port.second->parameter;
107  portSizeString = "[" + portParameterName + "-1:0]";
108  }
109  else
110  {
111  portSizeString = "[" + std::to_string(port.second->size - 1) + ":0]";
112  }
113  std::string portName = port.second->getName();
114  std::string portDeclaration = portTypeString + " " + portSizeString + " " + portName + ";\n";
115  moduleDefinition += std::string(SET_INDENT) + portDeclaration;
116  }
117 
118  if (!this->isElastic) {
119  // Functionality
120  moduleDefinition += std::string(SET_INDENT) + "always @(posedge CGRA_Clock, posedge CGRA_Reset)\n";
121  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "if (CGRA_Reset == 1)\n";
122  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "out <= 0;\n";
123  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "else\n";
124  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "if (enable & CGRA_Enable)\n";
125  moduleDefinition += std::string(SET_QUAD_INDENT) + "out <= in;";
126  } else {
127  // Functionality
128  moduleDefinition += std::string(SET_INDENT) + "always @(posedge CGRA_Clock, posedge CGRA_Reset)\n";
129  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "if (CGRA_Reset == 1) begin\n";
130  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "out <= 0;\n";
131  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "out_valid_downstream <= 0;\n";
132  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "end\n";
133  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "else if (enable & CGRA_Enable & ~in_stop_upstream) begin\n";
134  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "out <= in;\n";
135  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "out_valid_downstream <= in_valid_upstream;\n";
136  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "end\n";
137  moduleDefinition += std::string(SET_INDENT) + "assign enable_stop_upstream = in_stop_upstream;\n";
138  moduleDefinition += std::string(SET_INDENT) + "assign enable_valid_upstream = in_valid_upstream;\n";
139  moduleDefinition += std::string(SET_INDENT) + "assign in_stop_upstream = out_stop_downstream;\n";
140  }
141 
142  vjson["definition"] = moduleDefinition;
143  return vjson;
144 }
145 
146 
148 {
149 }
150 
152  const MRRG& mrrg, const OpGraph & og,
153  const Mapping& map,
154  const ConfigCell& ccell,
155  const MRRGNodesFromOpNode& mrrg_nodes_from_op_node,
156  const MRRGNodesFromValNode& mrrg_nodes_from_val_node
157 ) const {
158  BitConfig bitConfig(mrrg.initiationInterval());
159  // Use the m_in node to check if this register is being used
160  const std::regex in_regex("\\.m_in$");
161 
162  // Organize nodes mapping by cycle
163  std::vector<MRRGNodesFromValNode> valNodesByCycle(mrrg.initiationInterval());
164  for (const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
165  for (const auto& mrrg_node : val_and_mrrg_nodes.second) {
166  valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
167  }
168  }
169 
170  int cycle = 0;
171  int used_cycles = 0;
172  for (auto & mrrg_nodes_from_val_by_cycle : valNodesByCycle) {
173  if (mrrg_nodes_from_val_by_cycle.empty()) {
174  bitConfig.add({BitSetting::DONT_CARE_PREFER_LOW}, cycle);
175  } else {
176  bool enableRegister = false;
177  for (auto & op_val_and_nodes: mrrg_nodes_from_val_by_cycle) {
178  for (auto & mrrg_node : op_val_and_nodes.second) {
179  auto name = mrrg_node->getHierarchyQualifiedName();
180  if (regex_search(name, in_regex)) {
181  // Considering doing an error check here to see if "m_in" shows up twice
182  enableRegister = true;
183  break;
184  }
185  }
186  }
187  if (enableRegister) {
188  used_cycles++;
189  bitConfig.add({BitSetting::HIGH}, cycle);
190  }
191  else {
192  bitConfig.add({BitSetting::LOW}, cycle);
193  }
194  }
195  ++cycle;
196  }
197  bitConfig.setUsedCycles(used_cycles);
198  return bitConfig;
199 }
200 
201 MRRG* Register::createMRRG(unsigned II = 1)
202 {
203  /*
204  * Visualized MRRG:
205  * Context[N-1]:|Context[N]: |Context[N+1]:
206  * | in ──> m_in ───────┐ |
207  * | v |
208  * ... reg ─> m_out ─> out ─> m_enable ─> reg ─> m_out ...
209  * | |
210  */
211 
212  MRRG* result_ptr = new MRRG(II);
213  auto& result = *result_ptr;
214 
215  // create nodes
216  for (int this_cycle = 0; this_cycle < (int)II; ++this_cycle) {
217  result.insert(MRRGNode::make_routing(this, data_size, this_cycle, "in", 0));
218  result.insert(MRRGNode::make_routing(this, data_size, this_cycle, "m_in", 0));
219  result.insert(MRRGNode::make_routing(this, data_size, this_cycle, "reg", 1));
220  result.insert(MRRGNode::make_routing(this, data_size, this_cycle, "m_out", 0));
221  result.insert(MRRGNode::make_routing(this, data_size, this_cycle, "m_enable", 0));
222  result.insert(MRRGNode::make_routing(this, data_size, this_cycle, "out", 0));
223  }
224 
225  // connect them up
226  for (int this_cycle = 0; this_cycle < (int)II; ++this_cycle) {
227  const int next_cycle = (this_cycle + 1) % II;
228  const auto& nodes_this_cycle = makeNodeGetterForCycle(result, this_cycle);
229  const auto& nodes_NEXT_cycle = makeNodeGetterForCycle(result, next_cycle); // emphasis needed
230 
231  // stuff within the same cycle
232  result.link(nodes_this_cycle("in"), nodes_this_cycle("m_in"));
233  result.link(nodes_this_cycle("m_in"), nodes_this_cycle("reg"));
234  result.link(nodes_this_cycle("m_enable"), nodes_this_cycle("reg"));
235  result.link(nodes_this_cycle("m_out"), nodes_this_cycle("out"));
236  result.link(nodes_this_cycle("out"), nodes_this_cycle("m_enable"));
237 
238  // the special one
239  result.link(nodes_this_cycle("reg"), nodes_NEXT_cycle("m_out"));
240  }
241 
242  return result_ptr;
243 }
244 
245 
246 /************DeMultiplexer**********/
247 DeMux::DeMux(std::string name, Location loc, unsigned demux_size_, unsigned size, bool isElastic)
248  : Module(name, loc, size, isElastic), demux_size(demux_size_)
249 {
250  if (demux_size <= 1) { make_and_throw<cgrame_error>([&](auto&& s) {
251  s << "DeMultiplexer doesn't support demux_size <= 1. demux_size = " << demux_size;
252  });}
253 
254  //Create Ports
255  addPort("in", PORT_INPUT, "size", size, isElastic);
256  addPort("select", PORT_CONFIG, ceil(log2(demux_size)), isElastic);
257 
258  node_relative_position.insert({"in",{0, 0.2}});
259  node_relative_position.insert({"demux", {0.5,0.5}});
260 
261  for(int i = 0; i < demux_size; i++) {
262  addPort("out" + std::to_string(i), PORT_OUTPUT_REG, "size", size, isElastic);
263  node_relative_position.insert({"out" + std::to_string(i), {static_cast<double>(i)/demux_size, 0.5}});
264  }
265 
266 }
267 
268 // Virtual function that overrides Module::GenericName. Returns generic name of the object
269 std::string DeMux::GenericName() // Virtual function override
270 {
271  std::string elas = isElastic ? "elastic_" : "";
272  return elas + "demux_" + std::to_string(demux_size) + "to1_" + std::to_string(getSize()) + "b";
273 }
274 
275 // CoreIR Implementation of GenFunctionality
276 nlohmann::json DeMux::CoreIRGenFunctionality() // Virtual function override
277 {
278  nlohmann::json vjson;
279 
280  // Create Header
281  vjson["prefix"] = "cgrame_";
282  vjson["parameters"] = {};
283  for (auto& parameter : parameterlist)
284  {
285  vjson["parameters"].push_back(parameter.first);
286  }
287  vjson["interface"] = {};
288  for (auto& port : ports)
289  {
290  std::string portName = port.second->getName();
291  vjson["interface"].push_back(portName);
292  }
293 
294  // module definition
295  std::string moduleDefinition;
296  for (auto& port : ports)
297  {
298  port_type portType = port.second->pt;
299  std::string portTypeString = {};
300  if(portType == port_type::PORT_INPUT)
301  {
302  portTypeString = "input";
303  }
304  else if (portType == port_type::PORT_OUTPUT)
305  {
306  portTypeString = "output";
307  }
308  else if (portType == port_type::PORT_OUTPUT_REG)
309  {
310  portTypeString = "output reg";
311  }
312  else
313  {
314  portTypeString = "inout";
315  }
316  std::string portSizeString;
317  if (!(port.second->parameter).empty()) // Check if size is parameterized
318  {
319  std::string portParameterName = port.second->parameter;
320  portSizeString = "[" + portParameterName + "-1:0]";
321  }
322  else
323  {
324  portSizeString = "[" + std::to_string(port.second->size - 1) + ":0]";
325  }
326  std::string portName = port.second->getName();
327  std::string portDeclaration = portTypeString + " " + portSizeString + " " + portName + ";\n";
328  moduleDefinition += std::string(SET_INDENT) + portDeclaration;
329  }
330 
331  // Functionality
332  if (isElastic) {
333  moduleDefinition += std::string(SET_INDENT) + "always @(*)\n";
334  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "case (select)\n";
335  for (int i = 0; i < demux_size; ++i)
336  {
337  std::string stringI = std::to_string(i);
338  moduleDefinition += std::string(SET_TRIPLE_INDENT) + stringI + ":begin\n";
339  moduleDefinition += std::string(SET_QUAD_INDENT) + " out" + stringI + "= in;\n";
340  moduleDefinition += std::string(SET_QUAD_INDENT) + " in_stop_upstream = out" + stringI + "_stop_downstream;\n";
341  for (int j = 0; j < demux_size; ++j){
342  std::string stringJ = std::to_string(j);
343  if (j == i)
344  moduleDefinition += std::string(SET_QUAD_INDENT) + " out" + stringJ + "_valid_downstream = in_valid_upstream;\n";
345  else
346  moduleDefinition += std::string(SET_QUAD_INDENT) + " out" + stringJ + "_valid_downstream = 1'b0;\n";
347  }
348  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "end\n";
349  }
350  //moduleDefinition += std::string(SET_TRIPLE_INDENT) + "default: out = {size{1'bx}};\n";
351  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "endcase";
352 
353 
354  } else {
355  moduleDefinition += std::string(SET_INDENT) + "always @(*)\n";
356  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "case (select)\n";
357  for (int i = 0; i < demux_size; ++i)
358  {
359  std::string stringI = std::to_string(i);
360  moduleDefinition += std::string(SET_TRIPLE_INDENT) + stringI + ": out" + stringI + " = in;\n";
361  }
362  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "endcase";
363  }
364  vjson["definition"] = moduleDefinition;
365  return vjson;
366 }
367 
369  const MRRG& mrrg, const OpGraph & og,
370  const Mapping& map,
371  const ConfigCell& ccell,
372  const MRRGNodesFromOpNode& mrrg_nodes_from_op_node,
373  const MRRGNodesFromValNode& mrrg_nodes_from_val_node
374 ) const {
375  (void)ccell;
376  (void)mrrg_nodes_from_op_node;
377  const std::vector<std::regex> required_node_regexes {
378  std::regex("\\.demux$"), std::regex("\\.in$"),
379  };
380  const std::regex in_regex("\\.out([0-9]+)$");
381  BitConfig bitConfig(mrrg.initiationInterval());
382 
383  // Organize nodes mapping by cycle
384  std::vector<MRRGNodesFromValNode> valNodesByCycle(mrrg.initiationInterval());
385  for (const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
386  for (const auto& mrrg_node : val_and_mrrg_nodes.second) {
387  valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
388  }
389  }
390 
391  int cycle = 0;
392  int used_cycles = 0;
393  for (auto & mrrg_nodes_from_val_per_cycle : valNodesByCycle) {
394  std::unordered_set<int> inputs_used;
395 
396  for (const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
397  std::vector<bool> required_node_types_found;
398  for (const auto& req_node_regex : required_node_regexes) {
399  required_node_types_found.push_back(false);
400  for (const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
401  std::smatch match_results;
402  if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
403  if (required_node_types_found.back()) {
404  throw cgrame_error("found a node that matched two required node regexes");
405  } else {
406  required_node_types_found.back() = true;
407  }
408  }
409  }
410  }
411 
412  if (std::all_of(begin(required_node_types_found), end(required_node_types_found), [&](auto&& v) { return v; })) {
413  for (const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
414  std::smatch match_results;
415  std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
416  if (match_results.size() == 2) {
417  inputs_used.insert(stoi(match_results[1].str()));
418  }
419  }
420  } else {
421  // ignore the val
422  }
423  }
424 
425  if (inputs_used.empty()) {
426  bitConfig.add({(size_t)std::lround(ceil(log2(demux_size))), BitSetting::DONT_CARE_PREFER_LOW}, cycle);
427  } else {
428  if (inputs_used.size() != 1) {
429  throw cgrame_error("DeMultiplexer must only have one input");
430  } else {
431  used_cycles++;
432  bitConfig.add(bitsettings_from_int(*begin(inputs_used), (int)std::lround(ceil(log2(demux_size)))), cycle);
433  }
434  }
435  bitConfig.setUsedCycles(used_cycles);
436  ++cycle;
437  }
438 
439  return bitConfig;
440 }
441 
442 MRRG* DeMux::createMRRG(unsigned II = 1)
443 {
444  MRRG* result_ptr = new MRRG(II);
445  auto& result = *result_ptr;
446 
447  for(unsigned i = 0; i < II; i++)
448  {
449  MRRG::NodeDescriptor in = result.insert(MRRGNode::make_routing(this, data_size, i, "in")).first;
450  MRRG::NodeDescriptor demux = result.insert(MRRGNode::make_routing(this, data_size, i, "demux", 0)).first;
451 
452  result.link(in, demux);
453 
454  for(int j = 0; j < demux_size; j++)
455  {
456  MRRG::NodeDescriptor out = result.insert(MRRGNode::make_routing(this, data_size, i, "out" + std::to_string(j))).first;
457 
458  result.link(demux, out);
459  }
460 
461  }
462 
463  return result_ptr;
464 }
465 
467 {
468 }
469 
470 
471 /************ Multiplexer **********/
472 Multiplexer::Multiplexer(std::string name, Location loc, unsigned mux_size_, unsigned size, bool isElastic)
473  : Module(name, loc, size, isElastic)
474  , mux_size(mux_size_)
475 {
476 
477  if (mux_size <= 1) { make_and_throw<cgrame_error>([&](auto&& s) {
478  s << "Multiplexer doesn't support mux_size <= 1. mux_size = " << mux_size<< " name "<< name;
479  });}
480 
481  // Create ports
482  for(int i = 0; i < mux_size; i++) {
483  addPort("in" + std::to_string(i), PORT_INPUT, "size", size, isElastic);
484  node_relative_position.insert({"in" + std::to_string(i), {static_cast<double>(i)/mux_size, 0.2}});
485  }
486 
487  // Add position for visualization
488  node_relative_position.insert({"out", {0.25, 0.5}});
489  node_relative_position.insert({"mux", {0.5, 0.5}});
490 
491  addPort("out", PORT_OUTPUT_REG, "size", size, isElastic);
492  // select port should have size that is log base 2 of the mux size
493  addPort("select", PORT_CONFIG, ceil(log2(mux_size)), isElastic);
494 }
495 
496 // Virtual function that overrides Module::GenericName. Returns generic name of the object
497 std::string Multiplexer::GenericName() // Virtual function override
498 {
499  std::string elas = isElastic ? "elastic_" : "";
500  return elas + "mux_" + std::to_string(mux_size) + "to1_" + std::to_string(getSize()) + "b";
501 }
502 
503 // Generates the case statement for the multiplexer
504 void Multiplexer::GenFunctionality() // Virtual function override
505 {
506  std::cout << SET_INDENT << "always @(*)\n";
507  std::cout << SET_DOUBLE_INDENT << "case (select)\n";
508  for (int i = 0; i < mux_size; ++i)
509  std::cout << SET_TRIPLE_INDENT << i << ": out = in" << i << ";\n";
510  std::cout << SET_TRIPLE_INDENT << "default: out = {size{1'bx}};\n";
511  std::cout << SET_DOUBLE_INDENT << "endcase\n";
512 }
513 
514 // CoreIR Implementation of GenFunctionality
515 nlohmann::json Multiplexer::CoreIRGenFunctionality() // Virtual function override
516 {
517  nlohmann::json vjson;
518 
519  // Create Header
520  vjson["prefix"] = "cgrame_";
521  vjson["parameters"] = {};
522  for (auto& parameter : parameterlist)
523  {
524  vjson["parameters"].push_back(parameter.first);
525  }
526  vjson["interface"] = {};
527  for (auto& port : ports)
528  {
529  std::string portName = port.second->getName();
530  vjson["interface"].push_back(portName);
531  }
532 
533  // module definition
534  std::string moduleDefinition;
535  for (auto& port : ports)
536  {
537  port_type portType = port.second->pt;
538  std::string portTypeString = {};
539  if(portType == port_type::PORT_INPUT)
540  {
541  portTypeString = "input";
542  }
543  else if (portType == port_type::PORT_OUTPUT)
544  {
545  portTypeString = "output";
546  }
547  else if (portType == port_type::PORT_OUTPUT_REG)
548  {
549  portTypeString = "output reg";
550  }
551  else
552  {
553  portTypeString = "inout";
554  }
555  std::string portSizeString;
556  if (!(port.second->parameter).empty()) // Check if size is parameterized
557  {
558  std::string portParameterName = port.second->parameter;
559  portSizeString = "[" + portParameterName + "-1:0]";
560  }
561  else
562  {
563  portSizeString = "[" + std::to_string(port.second->size - 1) + ":0]";
564  }
565  std::string portName = port.second->getName();
566  std::string portDeclaration = portTypeString + " " + portSizeString + " " + portName + ";\n";
567  moduleDefinition += std::string(SET_INDENT) + portDeclaration;
568  }
569 
570  // Functionality
571  if (isElastic) {
572  moduleDefinition += std::string(SET_INDENT) + "always @(*)\n";
573  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "case (select)\n";
574  for (int i = 0; i < mux_size; ++i)
575  {
576  std::string stringI = std::to_string(i);
577  moduleDefinition += std::string(SET_TRIPLE_INDENT) + stringI + ":begin\n";
578  moduleDefinition += std::string(SET_QUAD_INDENT) + " out = in" + stringI + ";\n";
579  moduleDefinition += std::string(SET_QUAD_INDENT) + " out_valid_downstream = in" + stringI + "_valid_upstream;\n";
580  for (int j = 0; j < mux_size; ++j){
581  std::string stringJ = std::to_string(j);
582  if (j == i)
583  moduleDefinition += std::string(SET_QUAD_INDENT) + " in" + stringJ + "_stop_upstream = out_stop_downstream;\n";
584  else
585  moduleDefinition += std::string(SET_QUAD_INDENT) +" in" + stringJ + "_stop_upstream = 1'b1;\n";
586  }
587  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "end\n";
588  }
589  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "default: out = {size{1'bx}};\n";
590  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "endcase\n";
591  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "assign select_stop_upstream = out_stop_downstream;\n";
592  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "assign select_valid_upstream = out_valid_downstream;\n";
593  } else {
594  moduleDefinition += std::string(SET_INDENT) + "always @(*)\n";
595  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "case (select)\n";
596  for (int i = 0; i < mux_size; ++i)
597  {
598  std::string stringI = std::to_string(i);
599  moduleDefinition += std::string(SET_TRIPLE_INDENT) + stringI + ": out = in" + stringI + ";\n";
600  }
601  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "default: out = {size{1'bx}};\n";
602  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "endcase";
603  }
604  vjson["definition"] = moduleDefinition;
605  return vjson;
606 
607 }
608 
610  const MRRG& mrrg, const OpGraph & og,
611  const Mapping& map,
612  const ConfigCell& ccell,
613  const MRRGNodesFromOpNode& mrrg_nodes_from_op_node,
614  const MRRGNodesFromValNode& mrrg_nodes_from_val_node
615 ) const {
616  (void)ccell;
617  (void)mrrg_nodes_from_op_node;
618  const std::vector<std::regex> required_node_regexes {
619  std::regex("\\.mux$"), std::regex("\\.out$"),
620  };
621  const std::regex in_regex("\\.in([0-9]+)$");
622  BitConfig bitConfig(mrrg.initiationInterval());
623 
624  // Organize nodes mapping by cycle
625  std::vector<MRRGNodesFromValNode> valNodesByCycle(mrrg.initiationInterval());
626  for (const auto& val_and_mrrg_nodes : mrrg_nodes_from_val_node) {
627  for (const auto& mrrg_node : val_and_mrrg_nodes.second) {
628  valNodesByCycle[mrrg_node->cycle][val_and_mrrg_nodes.first].insert(mrrg_node);
629  }
630  }
631 
632  int cycle = 0;
633  int used_cycles = 0;
634  for (auto & mrrg_nodes_from_val_per_cycle : valNodesByCycle) {
635  std::unordered_set<int> inputs_used;
636 
637  for (const auto& val_node_and_mrrg_nodes : mrrg_nodes_from_val_per_cycle) {
638  std::vector<bool> required_node_types_found;
639  for (const auto& req_node_regex : required_node_regexes) {
640  required_node_types_found.push_back(false);
641  for (const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
642  std::smatch match_results;
643  if (std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, req_node_regex)) {
644  if (required_node_types_found.back()) {
645  throw cgrame_error("found a node that matched two required node regexes");
646  } else {
647  required_node_types_found.back() = true;
648  }
649  }
650  }
651  }
652 
653  if (std::all_of(begin(required_node_types_found), end(required_node_types_found), [&](auto&& v) { return v; })) {
654  for (const auto& mrrg_node : val_node_and_mrrg_nodes.second) {
655  std::smatch match_results;
656  std::regex_search(mrrg_node->getHierarchyQualifiedName(), match_results, in_regex);
657  if (match_results.size() == 2) {
658  inputs_used.insert(stoi(match_results[1].str()));
659  }
660  }
661  } else {
662  // ignore the val
663  }
664  }
665 
666  if (inputs_used.empty()) {
667  bitConfig.add({(size_t)std::lround(ceil(log2(mux_size))), BitSetting::DONT_CARE_PREFER_LOW}, cycle);
668  } else {
669  if (inputs_used.size() != 1) {
670  throw cgrame_error("Multiplexer must only have one input");
671  } else {
672  used_cycles++;
673  bitConfig.add(bitsettings_from_int(*begin(inputs_used), (int)std::lround(ceil(log2(mux_size)))), cycle);
674  }
675  }
676  ++cycle;
677  }
678  bitConfig.setUsedCycles(used_cycles);
679  return bitConfig;
680 }
681 
682 MRRG* Multiplexer::createMRRG(unsigned II = 1)
683 {
684  MRRG* result_ptr = new MRRG(II);
685  auto& result = *result_ptr;
686 
687  for(unsigned i = 0; i < II; i++)
688  {
689  MRRG::NodeDescriptor out = result.insert(MRRGNode::make_routing(this, data_size, i, "out")).first;
690  MRRG::NodeDescriptor mux = result.insert(MRRGNode::make_routing(this, data_size, i, "mux", 0)).first;
691 
692  result.link(mux, out);
693 
694  for(int j = 0; j < mux_size; j++)
695  {
696  MRRG::NodeDescriptor in = result.insert(MRRGNode::make_routing(this, data_size, i, "in" + std::to_string(j))).first;
697 
698  result.link(in, mux);
699  }
700 
701  }
702 
703  return result_ptr;
704 }
705 
707 {
708 }
709 
710 /************ Truncate Input **********/
711 TruncateInput::TruncateInput(std::string name, Location loc, unsigned splitPos, unsigned size, bool isElastic)
712  : Module(name, loc, size, isElastic)
713  , pos(splitPos)
714 {
715  // Create ports
716  addPort("in", PORT_INPUT, "size", size, isElastic);
717  addPort("out0", PORT_OUTPUT_REG, splitPos, isElastic);
718 }
719 
720 // Virtual function that overrides Module::GenericName. Returns generic name of the object
721 std::string TruncateInput::GenericName() // Virtual function override
722 {
723  std::string elas = isElastic ? "elastic_" : "";
724  return elas + "split_input_at_" + std::to_string(pos) + "_size_" + std::to_string(getSize()) + "b";
725 }
726 
727 // CoreIR Implementation of GenFunctionality
728 nlohmann::json TruncateInput::CoreIRGenFunctionality() // Virtual function override
729 {
730  nlohmann::json vjson;
731 
732  // Create Header
733  vjson["prefix"] = "cgrame_";
734  vjson["parameters"] = {};
735  for (auto& parameter : parameterlist)
736  {
737  vjson["parameters"].push_back(parameter.first);
738  }
739  vjson["interface"] = {};
740  for (auto& port : ports)
741  {
742  std::string portName = port.second->getName();
743  vjson["interface"].push_back(portName);
744  }
745 
746  // module definition
747  std::string moduleDefinition;
748  for (auto& port : ports)
749  {
750  port_type portType = port.second->pt;
751  std::string portTypeString = {};
752  if(portType == port_type::PORT_INPUT)
753  {
754  portTypeString = "input";
755  }
756  else if (portType == port_type::PORT_OUTPUT)
757  {
758  portTypeString = "output";
759  }
760  else if (portType == port_type::PORT_OUTPUT_REG)
761  {
762  portTypeString = "output reg";
763  }
764  else
765  {
766  portTypeString = "inout";
767  }
768  std::string portSizeString;
769  if (!(port.second->parameter).empty()) // Check if size is parameterized
770  {
771  std::string portParameterName = port.second->parameter;
772  portSizeString = "[" + portParameterName + "-1:0]";
773  }
774  else
775  {
776  portSizeString = "[" + std::to_string(port.second->size - 1) + ":0]";
777  }
778  std::string portName = port.second->getName();
779  std::string portDeclaration = portTypeString + " " + portSizeString + " " + portName + ";\n";
780  moduleDefinition += std::string(SET_INDENT) + portDeclaration;
781  }
782 
783  // Functionality
784  moduleDefinition += std::string(SET_INDENT) + "assign out0 = in[" + std::to_string(pos - 1) + ": 0 ];\n" ;
785  if (isElastic) {
786  moduleDefinition += std::string(SET_INDENT) + "assign out0_valid_downstream = in_valid_upstream;\n";
787  moduleDefinition += std::string(SET_INDENT) + "assign in_stop_upstream = out0_stop_downstream;\n";
788  }
789  vjson["definition"] = moduleDefinition;
790  return vjson;
791 
792 }
793 
795 {
796  MRRG* result_ptr = new MRRG(II);
797  auto& result = *result_ptr;
798 
799  for(unsigned i = 0; i < II; i++)
800  {
801  //MRRG::NodeDescriptor out0 = result.insert(MRRGNode::make_operand_pin(this, i, "out0", {Operands::PREDICATE})).first;
802  MRRG::NodeDescriptor out0 = result.insert(MRRGNode::make_routing(this, data_size, i, "out0")).first;
803  MRRG::NodeDescriptor truncate = result.insert(MRRGNode::make_routing(this, data_size, i, "truncate")).first;
804  MRRG::NodeDescriptor in = result.insert(MRRGNode::make_routing(this, data_size, i, "in")).first;
805 
806  result.link(truncate, out0);
807  result.link(in, truncate);
808  }
809 
810  return result_ptr;
811 }
812 
814 {
815 }
816 
817 /************ RegisterFile **********/
818 RegisterFile::RegisterFile(std::string name, Location loc, int numInputPorts_, int numOutputPorts_, int log2Registers_, int size, int II, bool isElastic)
819  : Module(name, loc, size, isElastic)
820  , numInputPorts(numInputPorts_)
821  , numOutputPorts(numOutputPorts_)
822  , log2Registers(log2Registers_)
823 {
825  if (log2Registers < 1) { make_and_throw<cgrame_error>([&](auto&& s) {
826  s << "RegisterFile doesn't support less than 2 registers. log2Registers = " << log2Registers;
827  });}
828 
829  if (II > 1)
830  addPort("Context", PORT_INPUT, ceil(log2(II)));
831  // Generating input ports
832  for (int i = 0; i < numInputPorts; i++)
833  {
834  addPort("in" + std::to_string(i), PORT_INPUT, "size", size, isElastic); // input data
835  }
836 
837  // Generating output ports
838  for (int i = 0; i < numOutputPorts; i++)
839  {
840  addPort("out" + std::to_string(i), PORT_OUTPUT_REG, "size", size, isElastic); // output ports/registers
841  // addPort("address_out" + std::to_string(i), PORT_INPUT, "log2regs", log2Registers); // addresses for output
842  }
843 
844  // Generating input muxes and registers
845  for (int i = 0; i < (1 << log2Registers); ++i) {
846  addSubModule(new Register("reg" + std::to_string(i), loc, size, isElastic), 0.1 + static_cast<double>(i)/(1 << log2Registers), 0.3, 1.0/(1 << log2Registers),0.2);
847  addConfig(new ConfigCell(name + "Reg" + std::to_string(i) + "Config", II), {"reg" + std::to_string(i) + ".enable"});
848 
849  if (numInputPorts > 1) {
850  addSubModule(new Multiplexer("in_mux" + std::to_string(i), loc, numInputPorts, size, isElastic), 0.1 + static_cast<double>(i)/numOutputPorts, 0.1, 1.0/numInputPorts, 0.3);
851  addConfig(new ConfigCell(name + "InMux" + std::to_string(i) + "Config", II), {"in_mux" + std::to_string(i) + ".select"});
852 
853  // Connect input mux to reg
854  addConnection("in_mux" + std::to_string(i) + ".out", "reg" + std::to_string(i) + ".in");
855 
856  for (int j = 0; j < numInputPorts; ++j) {
857  addConnection("this.in" + std::to_string(j), "in_mux" + std::to_string(i) + ".in" + std::to_string(j));
858  }
859  }
860  else {
861  addConnection("this.in0", "reg" + std::to_string(i) + ".in");
862  }
863  }
864 
865  // Generating output muxes
866  for (int i = 0; i < numOutputPorts; ++i) {
867  addSubModule(new Multiplexer("out_mux" + std::to_string(i), loc, (1 << log2Registers), size, isElastic), 0.1 + static_cast<double>(i)/numOutputPorts, 0.7, 1.0/numOutputPorts, 0.3);
868  addConfig(new ConfigCell(name + "OutMux" + std::to_string(i) + "Config", II), {"out_mux" + std::to_string(i) + ".select"});
869 
870  // Connect every register to this output mux
871  for (int j = 0; j < (1 << log2Registers); ++j) {
872  addConnection("reg" + std::to_string(j) + ".out", "out_mux" + std::to_string(i) + ".in" + std::to_string(j));
873  }
874  addConnection("out_mux" + std::to_string(i) + ".out", "this.out" + std::to_string(i));
875  }
876  if (II > 1) {
877  for (int i = 0; i < (1 << log2Registers); ++i) {
878  addConnection("this.Context", name + "Reg" + std::to_string(i) + "Config.Context", false);
879  if (numInputPorts > 1) {
880  addConnection("this.Context", name + "InMux" + std::to_string(i) + "Config.Context", false);
881  }
882  }
883  for (int i = 0; i < numOutputPorts; ++i) {
884  addConnection("this.Context", name + "OutMux" + std::to_string(i) + "Config.Context", false);
885  }
886  }
887 
888  // Setting positions for nodes
889  for (int i = 0; i < numInputPorts; i++) {
890  setNodePosition("in" + std::to_string(i), static_cast<double>(i*log2Registers+1)/(numInputPorts*log2Registers+2), 0.1);
891  }
892 
893  for (int i = 0; i < numOutputPorts; ++i) {
894  setNodePosition("out" + std::to_string(i), static_cast<double>(i+1)/(numOutputPorts+2), 0.95);
895  }
896 }
897 
898 // Generates a unique name for a register file,based on number of input ports and output ports
900 {
901  return "registerFile_" + std::to_string(numInputPorts) + "in_" + std::to_string(numOutputPorts) + "out_" + std::to_string(getSize()) + "b";
902 }
903 
904 // Prints the register file and always block
905 // begin block for CGRA Reset MUST be named
906 // We must use either entirely blocking or nonblocking assignment statements in this always block, no mixes allowed
908 {
909  std::cout << "\n" << SET_INDENT << "// Setting the always blocks and inside registers\n";
910  std::cout << SET_INDENT << "reg [size-1:0] register[2**log2regs-1:0];\n";
911  std::cout << SET_INDENT << "always@(posedge CGRA_Clock, posedge CGRA_Reset)\n";
912  std::cout << SET_DOUBLE_INDENT << "if(CGRA_Reset)\n";
913  std::cout << SET_TRIPLE_INDENT << "begin : RESET\n";
914  std::cout << SET_QUAD_INDENT << "integer i;\n";
915  std::cout << SET_QUAD_INDENT << "for (i = 0; i < 2**log2regs; i = i+1)\n";
916  std::cout << SET_PENTA_INDENT << "register[i] = 0;\n";
917  std::cout << SET_TRIPLE_INDENT << "end\n";
918  std::cout << SET_DOUBLE_INDENT << "else\n";
919  std::cout << SET_TRIPLE_INDENT << "begin\n";
920  for (int i = 0; i < numOutputPorts; i++)
921  std::cout << SET_QUAD_INDENT << "out" << i << " = " << "register[address_out" << i << "];\n";
922  for (int i = 0; i < numInputPorts; i++)
923  {
924  std::cout << SET_QUAD_INDENT << "if(WE" << i << ")\n";
925  std::cout << SET_PENTA_INDENT << "register[address_in" << i << "] = in" << i << ";\n";
926  }
927  std::cout << SET_TRIPLE_INDENT << "end\n";
928 }
929 
930 // CoreIR Implementation of GenFunctionality
931 nlohmann::json RegisterFile::CoreIRGenFunctionality() // Virtual function override
932 {
933  nlohmann::json vjson;
934 
935  // Create Header
936  vjson["prefix"] = "cgrame_"; //module prefix
937  vjson["parameters"] = {};
938  for (auto& parameter : parameterlist)
939  {
940  vjson["parameters"].push_back(parameter.first);
941  }
942  vjson["interface"] = {};
943  vjson["interface"].push_back("CGRA_Clock");
944  vjson["interface"].push_back("CGRA_Reset");
945  vjson["interface"].push_back("CGRA_Enable");
946  for (auto& port : ports)
947  {
948  std::string portName = port.second->getName();
949  vjson["interface"].push_back(portName);
950  }
951 
952  // module definition
953  std::string moduleDefinition;
954  moduleDefinition += std::string(SET_INDENT) + "input CGRA_Clock;\n";
955  moduleDefinition += std::string(SET_INDENT) + "input CGRA_Reset;\n";
956  moduleDefinition += std::string(SET_INDENT) + "input CGRA_Enable;\n";
957  for (auto& port : ports)
958  {
959  port_type portType = port.second->pt;
960  std::string portTypeString = {};
961  if(portType == port_type::PORT_INPUT)
962  {
963  portTypeString = "input";
964  }
965  else if (portType == port_type::PORT_OUTPUT)
966  {
967  portTypeString = "output";
968  }
969  else if (portType == port_type::PORT_OUTPUT_REG)
970  {
971  portTypeString = "output reg";
972  }
973  else
974  {
975  portTypeString = "inout";
976  }
977  std::string portSizeString;
978  if (!(port.second->parameter).empty()) // Check if size is parameterized
979  {
980  std::string portParameterName = port.second->parameter;
981  portSizeString = "[" + portParameterName + "-1:0]";
982  }
983  else
984  {
985  portSizeString = "[" + std::to_string(port.second->size - 1) + ":0]";
986  }
987  std::string portName = port.second->getName();
988  std::string portDeclaration = portTypeString + " " + portSizeString + " " + portName + ";\n";
989  moduleDefinition += std::string(SET_INDENT) + portDeclaration;
990  }
991 
992  // Functionality
993  moduleDefinition += std::string(SET_INDENT) + "// Setting the always blocks and inside registers\n";
994  moduleDefinition += std::string(SET_INDENT) + "reg [size-1:0] register[2**log2regs-1:0];\n";
995  moduleDefinition += std::string(SET_INDENT) + "always@(posedge CGRA_Clock, posedge CGRA_Reset)\n";
996  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "if(CGRA_Reset)\n";
997  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "begin : RESET\n";
998  moduleDefinition += std::string(SET_QUAD_INDENT) + "integer i;\n";
999  moduleDefinition += std::string(SET_QUAD_INDENT) + "for (i = 0; i < 2**log2regs; i = i+1)\n";
1000  moduleDefinition += std::string(SET_PENTA_INDENT) + "register[i] = 0;\n";
1001  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "end\n";
1002  moduleDefinition += std::string(SET_DOUBLE_INDENT) + "else if (CGRA_Enable)\n";
1003  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "begin\n";
1004  for (int i = 0; i < numOutputPorts; i++)
1005  moduleDefinition += std::string(SET_QUAD_INDENT) + "out" + std::to_string(i) + " = " + "register[address_out" + std::to_string(i) + "];\n";
1006  for (int i = 0; i < numInputPorts; i++)
1007  {
1008  moduleDefinition += std::string(SET_QUAD_INDENT) + "if(WE" + std::to_string(i) + ")\n";
1009  moduleDefinition += std::string(SET_PENTA_INDENT) + "register[address_in" + std::to_string(i) + "] = in" + std::to_string(i) + ";\n";
1010  }
1011  moduleDefinition += std::string(SET_TRIPLE_INDENT) + "end";
1012 
1013  vjson["definition"] = moduleDefinition;
1014  return vjson;
1015 }
1016 
1018 {
1019 }
1020 
1021 
1023 {
1024  return "crossbar_" + std::to_string(num_inputs) + "in_" + std::to_string(num_outputs) + "out_" + std::to_string(data_size) + "data_size" ;
1025 }
1026 
1027 Crossbar::Crossbar(std::string name, Location loc, int num_inputs, int num_outputs, int data_size, bool predExist, int contexts)
1028  : Module(name, loc, data_size)
1029  , num_inputs(num_inputs)
1030  , num_outputs(num_outputs)
1031 {
1032 
1033  // 1. Create num_output muxes (each num_input in sie)
1034  for(int i = 0; i < num_outputs; i++)
1035  {
1036  // Connects to regA for HyCube
1037  if (predExist){
1038  addSubModule(new SelMultiplexer("mux_" + std::to_string(i), loc, num_inputs, data_size), 0.2, static_cast<double>(i)/num_outputs, 0.6, 0.8/num_outputs);
1039  }
1040  else{
1041  addSubModule(new Multiplexer("mux_" + std::to_string(i), loc, num_inputs, data_size), 0.2, static_cast<double>(i)/num_outputs, 0.6, 0.8/num_outputs);
1042  }
1043  }
1044 
1045  // 2. Create the configuration cells for each mux
1046  for(int i = 0; i < num_outputs; i++)
1047  {
1048  addConfig(new ConfigCell("Mux" + std::to_string(i) + "config", contexts), {"mux_" + std::to_string(i) + ".select"});
1049  }
1050 
1051  // 3. Wiring and Ports
1052  // 3A. Create input and output ports
1053  // Context Port
1054  if (contexts > 1) {
1055  addPort("Context", PORT_INPUT, ceil(log2(contexts)));
1056  }
1057  // Input ports:
1058  for(int i = 0; i < num_inputs; i++)
1059  {
1061  node_relative_position.insert({"in" + std::to_string(i), {0, static_cast<double>(i)/num_inputs}}); // Add position for visualization
1062  }
1063  // If pred exist a port to get in the select predicate
1064  if (predExist){
1065  addPort("pred_in", PORT_INPUT, 1);
1066  }
1067 
1068  // Output ports:
1069  for(int i = 0; i < num_outputs; i++)
1070  {
1072  node_relative_position.insert({"out" + std::to_string(i), {1, static_cast<double>(i)/num_outputs}}); // Add position for visualization
1073  }
1074 
1075  // 3B. Wiring ports to muxes
1076  // Crossbar input ports to mux inputs:
1077  for(int j = 0; j < num_outputs; j++)
1078  {
1079  if (predExist) {
1080  addConnection("this.pred_in", "mux_" + std::to_string(j) + ".selectpred");
1081  }
1082  for(int i = 0; i < num_inputs; i++)
1083  {
1084  addConnection("this.in" + std::to_string(i), "mux_" + std::to_string(j) + ".in" + std::to_string(i));
1085  }
1086  }
1087 
1088  // Mux outputs to crossbar output ports:
1089  for(int i = 0; i < num_outputs; i++)
1090  {
1091  addConnection("mux_" + std::to_string(i) + ".out", "this.out" + std::to_string(i));
1092  }
1093  if (contexts > 1) {
1094  for(int i = 0; i < num_outputs; i++)
1095  {
1096  addConnection("this.Context" , "Mux" + std::to_string(i) + "config.Context", false);
1097  }
1098 
1099  }
1100 }
BitSetting::HIGH
@ HIGH
BitConfig
Definition: BitSetting.h:58
Module::name
std::string name
Definition: Module.h:341
ConfigCell
Definition: Module.h:825
Multiplexer::GenFunctionality
virtual void GenFunctionality() override
Definition: ModuleRoutingStructures.cpp:504
RegisterFile::GenericName
virtual std::string GenericName() override
Definition: ModuleRoutingStructures.cpp:899
Multiplexer
Zero-cycle latency multiplexer.
Definition: Module.h:592
SET_TRIPLE_INDENT
const char *const SET_TRIPLE_INDENT
Definition: Module.h:39
MRRG
Definition: MRRG.h:216
PORT_OUTPUT_REG
@ PORT_OUTPUT_REG
Definition: Module.h:65
MRRGNodesFromOpNode
std::map< OpGraphOp *, std::set< MRRG::NodeDescriptor > > MRRGNodesFromOpNode
Definition: Module.h:146
Location
Definition: Module.h:156
Module::data_size
unsigned data_size
Definition: Module.h:338
DeMux::demux_size
int demux_size
Definition: Module.h:693
Module::addConnection
void addConnection(std::string src, std::string dst, bool isInMRRG=true)
Definition: Module.cpp:1241
begin
auto begin(const SingleItemImmutableSet< VertexID > &siis)
Definition: Collections.h:137
SET_PENTA_INDENT
const char *const SET_PENTA_INDENT
Definition: Module.h:41
Module.h
Module::adds_synchronous_circuitry
bool adds_synchronous_circuitry
Definition: Module.h:370
makeNodeGetterForCycle
auto makeNodeGetterForCycle(M &mrrg, int cycle)
Definition: MRRG.h:401
Module::setNodePosition
bool setNodePosition(const std::string &nodeName, double x, double y)
Definition: Module.cpp:1671
Module::parameterlist
std::map< std::string, unsigned > parameterlist
Definition: Module.h:224
BitSetting::DONT_CARE_PREFER_LOW
@ DONT_CARE_PREFER_LOW
Register
A simple latency element with an enable signal; a data flip-flop.
Definition: Module.h:566
BitConfig::add
void add(std::vector< BitSetting > bitsetting, int cycle)
Definition: BitSetting.h:63
Module::addPort
void addPort(std::string portname, port_type pt, unsigned size)
Definition: Module.cpp:1354
Module::node_relative_position
std::map< std::string, VisualPositionPoint > node_relative_position
Definition: Module.h:360
Register::createMRRG
MRRG * createMRRG(unsigned II) override
Definition: ModuleRoutingStructures.cpp:201
to_string
const std::string & to_string(const OpGraphOpCode &opcode)
Definition: OpGraph.cpp:111
DeMux::createMRRG
MRRG * createMRRG(unsigned II) override
Definition: ModuleRoutingStructures.cpp:442
RegisterFile::RegisterFile
RegisterFile(std::string name, Location, int numInputPorts, int numOutputPorts, int log2Registers, int size=DEFAULT_SIZE, int contexts=1, bool isElastic=false)
Definition: ModuleRoutingStructures.cpp:818
RegisterFile::numInputPorts
int numInputPorts
Definition: Module.h:717
Register::GenFunctionality
virtual void GenFunctionality() override
Definition: ModuleRoutingStructures.cpp:45
DeMux::GenericName
virtual std::string GenericName() override
Definition: ModuleRoutingStructures.cpp:269
Register::getBitConfig
virtual BitConfig getBitConfig(const MRRG &mrrg, const OpGraph &og, const Mapping &map, const ConfigCell &ccell, const MRRGNodesFromOpNode &mrrg_nodes_from_op_node, const MRRGNodesFromValNode &mrrg_nodes_from_val_node) const override
Definition: ModuleRoutingStructures.cpp:151
MRRG::insert
std::pair< NodeDescriptor, bool > insert(MRRGNode node)
Definition: MRRG.cpp:91
TruncateInput::~TruncateInput
virtual ~TruncateInput()
Definition: ModuleRoutingStructures.cpp:813
MRRGNodesFromValNode
std::map< OpGraphVal *, std::set< MRRG::NodeDescriptor > > MRRGNodesFromValNode
Definition: Module.h:147
BitSetting::LOW
@ LOW
RegisterFile::log2Registers
int log2Registers
Definition: Module.h:717
Mapping
Definition: Mapping.h:31
DeMux::DeMux
DeMux(std::string, Location, unsigned demux_size, unsigned size=DEFAULT_SIZE, bool isElastic=false)
Definition: ModuleRoutingStructures.cpp:247
PORT_CONFIG
@ PORT_CONFIG
Definition: Module.h:67
DeMux::CoreIRGenFunctionality
virtual nlohmann::json CoreIRGenFunctionality() override
Definition: ModuleRoutingStructures.cpp:276
TruncateInput::CoreIRGenFunctionality
virtual nlohmann::json CoreIRGenFunctionality() override
Definition: ModuleRoutingStructures.cpp:728
DeMux::getBitConfig
virtual BitConfig getBitConfig(const MRRG &mrrg, const OpGraph &og, const Mapping &map, const ConfigCell &ccell, const MRRGNodesFromOpNode &mrrg_nodes_from_op_node, const MRRGNodesFromValNode &mrrg_nodes_from_val_node) const override
Definition: ModuleRoutingStructures.cpp:368
RegisterFile::GenFunctionality
virtual void GenFunctionality() override
Definition: ModuleRoutingStructures.cpp:907
Multiplexer::getBitConfig
virtual BitConfig getBitConfig(const MRRG &mrrg, const OpGraph &og, const Mapping &map, const ConfigCell &ccell, const MRRGNodesFromOpNode &mrrg_nodes_from_op_node, const MRRGNodesFromValNode &mrrg_nodes_from_val_node) const override
Definition: ModuleRoutingStructures.cpp:609
RegisterFile::~RegisterFile
virtual ~RegisterFile()
Definition: ModuleRoutingStructures.cpp:1017
Register::GenericName
virtual std::string GenericName() override
Definition: ModuleRoutingStructures.cpp:38
RegisterFile::CoreIRGenFunctionality
virtual nlohmann::json CoreIRGenFunctionality() override
Definition: ModuleRoutingStructures.cpp:931
SET_INDENT
const char *const SET_INDENT
Definition: Module.h:37
Module
Definition: Module.h:163
PORT_INPUT
@ PORT_INPUT
Definition: Module.h:63
TruncateInput::createMRRG
MRRG * createMRRG(unsigned II) override
Definition: ModuleRoutingStructures.cpp:794
Crossbar::num_outputs
int num_outputs
Definition: Module.h:727
Register::CoreIRGenFunctionality
virtual nlohmann::json CoreIRGenFunctionality() override
Definition: ModuleRoutingStructures.cpp:55
Multiplexer::~Multiplexer
virtual ~Multiplexer()
Definition: ModuleRoutingStructures.cpp:706
Register::Register
Register(std::string, Location, int size=DEFAULT_SIZE, bool isElastic=false)
Definition: ModuleRoutingStructures.cpp:18
Module::addConfig
void addConfig(ConfigCell *c, std::vector< std::string > ConnectTo)
Definition: Module.cpp:1087
end
auto end(const SingleItemImmutableSet< VertexID > &siis)
Definition: Collections.h:138
Multiplexer::createMRRG
MRRG * createMRRG(unsigned II) override
Definition: ModuleRoutingStructures.cpp:682
RegisterFile::numOutputPorts
int numOutputPorts
Definition: Module.h:717
MRRGNode
Definition: MRRG.h:60
Module::getSize
int getSize() const
Definition: Module.h:246
Multiplexer::CoreIRGenFunctionality
virtual nlohmann::json CoreIRGenFunctionality() override
Definition: ModuleRoutingStructures.cpp:515
Crossbar::Crossbar
Crossbar(std::string name, Location, int num_inputs, int num_outputs, int data_size, bool predExist=false, int contexts=1)
Definition: ModuleRoutingStructures.cpp:1027
Register::~Register
virtual ~Register()
Definition: ModuleRoutingStructures.cpp:147
Module::addSubModule
void addSubModule(Module *m)
Definition: Module.cpp:1124
BitConfig::setUsedCycles
void setUsedCycles(int uc)
Definition: BitSetting.h:67
Multiplexer::Multiplexer
Multiplexer(std::string, Location, unsigned mux_size, unsigned size=DEFAULT_SIZE, bool isElastic=false)
Definition: ModuleRoutingStructures.cpp:472
DeMux::~DeMux
virtual ~DeMux()
Definition: ModuleRoutingStructures.cpp:466
Crossbar::GenericName
virtual std::string GenericName() override
Definition: ModuleRoutingStructures.cpp:1022
Module::isElastic
bool isElastic
Definition: Module.h:236
SET_DOUBLE_INDENT
const char *const SET_DOUBLE_INDENT
Definition: Module.h:38
Module::ports
std::map< std::string, Port * > ports
Definition: Module.h:225
Multiplexer::mux_size
int mux_size
Definition: Module.h:610
Module::loc
Location loc
Definition: Module.h:239
SelMultiplexer
2 Zero-cycle latency multiplexers for predication support.
Definition: Module.h:647
MRRG::initiationInterval
int initiationInterval() const
Definition: MRRG.h:346
MRRGNode::make_routing
static MRRGNode make_routing(Module *parent, int bitwidth, int cycle, STR &&name, int latency=0, int max_cap=1)
Definition: MRRG.h:151
port_type
port_type
Definition: Module.h:61
TruncateInput::pos
int pos
Definition: Module.h:632
Multiplexer::GenericName
virtual std::string GenericName() override
Definition: ModuleRoutingStructures.cpp:497
TruncateInput::TruncateInput
TruncateInput(std::string, Location, unsigned pos, unsigned size=DEFAULT_SIZE, bool isElastic=false)
Definition: ModuleRoutingStructures.cpp:711
OpGraph
Definition: OpGraph.h:215
cgrame_error
Definition: Exception.h:20
PORT_OUTPUT
@ PORT_OUTPUT
Definition: Module.h:64
TruncateInput::GenericName
virtual std::string GenericName() override
Definition: ModuleRoutingStructures.cpp:721
SET_QUAD_INDENT
const char *const SET_QUAD_INDENT
Definition: Module.h:40
bitsettings_from_int
std::vector< BitSetting > bitsettings_from_int(const INTEGRAL &value, int num_bits)
Definition: BitSetting.h:52
Crossbar::num_inputs
int num_inputs
Definition: Module.h:726