CGRA-ME
ModuleComposites.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/Exception.h>
12 #include <CGRA/ModuleComposites.h>
13 #include <ios>
14 
15 MemPort::MemPort(std::string name, Location loc, int num_connections_, int size, int num_const_addresses_, bool pred, int II)
16  : Module(name, loc, size)
17  , num_connections(num_connections_)
18  , num_const_addresses(num_const_addresses_)
19 {
20  using std::to_string;
21 
22  addParameter("size", size);
23  if (II > 1)
24  addPort("Context", PORT_INPUT, ceil(log2(II)));
25 
26  if (num_connections < 2) { make_and_throw<cgrame_error>([&](auto&& s) {
27  s << "MemPort doesn't support num_connections < 2. num_connections = " << num_connections;
28  });}
29 
30  // add constant ports (always will have these ports)
31  addPort("out", PORT_OUTPUT, size);
32  node_relative_position.insert({"out", {0.5, 0.7}}); // Add position for visualization
33 
34  // make all input ports
35  for(int i = 0; i < num_connections; i++)
36  {
37  addPort("in" + std::to_string(i), PORT_INPUT, size);
38  // Add position for visualization
39  node_relative_position.insert({"in" + std::to_string(i), {0, static_cast<double>(i+0.5)/num_connections/2.0}});
40  };
41 
42  const auto constAddrName = [](int index) { return "const_addr_" + to_string(index); };
43 
44  // add FU for loads/stores
45  addSubModule(new MemoryUnit("mem_unit", loc, size, isElastic, pred), 0.2, 0, 0.5, 0.2);
46 
47  if (pred) {
48  for (int i = 0; i < num_connections; i++)
49  addPort("pred" + std::to_string(i), PORT_INPUT, 1);
50  addSubModule(new Multiplexer("mux_pred", loc, num_connections, 1), 0.6, 0.4, 0.5, 0.2);
51  for(int i = 0; i < num_connections; i++)
52  addConnection("this.pred" + std::to_string(i), "mux_pred.in" + std::to_string(i));
53  addConnection("mux_pred.out", "mem_unit.pred");
54  addConfig(new ConfigCell("MuxPred", II), {"mux_pred.select"});
55  }
56 
57  for (int i = 0; i < num_const_addresses; ++i) {
58  addSubModule(new ConstUnit(constAddrName(i), loc, size, II), static_cast<double>(i)/num_const_addresses, 0.75, 1.0/num_const_addresses, 0.25);
59  }
60 
61  // add input muxs
62  addSubModule(new Multiplexer("mux_addr", loc, num_connections + num_const_addresses, size), 0.6, 0.2, 0.5, 0.2);
63  addSubModule(new Multiplexer("mux_data", loc, num_connections, size), 0.6, 0.4, 0.5, 0.2);
64  addConfig(new ConfigCell("MuxAddr", II), {"mux_addr.select"});
65  addConfig(new ConfigCell("MuxData", II), {"mux_data.select"});
66 
67  // make all mux input connections
68  for(int i = 0; i < num_connections; i++)
69  {
70  addConnection("this.in" + std::to_string(i), "mux_data.in" + std::to_string(i));
71  addConnection("this.in" + std::to_string(i), "mux_addr.in" + std::to_string(i));
72  }
73  for (int i = 0; i < num_const_addresses; ++i) {
74  addConnection(constAddrName(i) + ".out", "mux_addr.in" + to_string(i + num_connections));
75  }
76 
77  // connections to the mem unit
78  addConnection("mux_addr.out", "mem_unit.addr");
79  addConnection("mux_data.out", "mem_unit.data_in");
80  addConnection("mem_unit.data_out", "this.out");
81  addConfig(new ConfigCell("WriteRq", II), {"mem_unit.w_rq"});
82 
83  if (II > 1) {
84  addConnection("this.Context", "WriteRq.Context", false);
85  addConnection("this.Context", "MuxData.Context", false);
86  addConnection("this.Context", "MuxAddr.Context", false);
87  if (pred)
88  addConnection("this.Context", "MuxPred.Context", false);
89  for (int i = 0; i < num_const_addresses; ++i) {
90  addConnection("this.Context", constAddrName(i) + ".Context", false);
91  }
92  }
93 }
94 
95 std::string MemPort::GenericName()
96 {
97  return string_from_stream([&](auto&& s) {
98  s << "memoryPort_" << num_connections << "connect_" ;
99  if (num_const_addresses != 0) {
100  s << num_const_addresses << "constaddrs_";
101  }
102  s << this->getSize() << "b";
103  });
104 }
105 
107 {
108 }
109 
110 IOPort::IOPort(std::string name, Location loc, int num_inputs_, int size)
111  : Module(name, loc, size)
112  , num_inputs(num_inputs_)
113 {
114  if (num_inputs < 1) { make_and_throw<cgrame_error>([&](auto&& s) {
115  s << "IOPort doesn't support num_inputs < 1. num_inputs = " << num_inputs;
116  });}
117 
118  // add constant ports (always will have these ports)
119  addPort("out", PORT_OUTPUT, size);
120  for(int i = 0; i < num_inputs; i++)
121  {
122  addPort("in" + std::to_string(i), PORT_INPUT, size);
123  };
124 
125  addSubModule(new IO("io_unit", loc, size), 0, 0.5, 1, 0.5);
126 
127  // add connection(s) + mux to io unit
128  if(num_inputs == 1)
129  {
130  addConnection("this.in0", "io_unit.in");
131  addConnection("io_unit.out", "this.out");
132  }
133  else
134  {
135  addSubModule(new Multiplexer("mux_in", loc, num_inputs, size), 0, 0, 1, 0.5);
136 
137  for(int i = 0; i < num_inputs; i++)
138  {
139  addConnection("this.in" + std::to_string(i), "mux_in.in" + std::to_string(i));
140  }
141 
142  addConnection("mux_in.out", "io_unit.in");
143  addConnection("io_unit.out", "this.out");
144 
145  addConfig(new ConfigCell("MuxConfig"), {"mux_in.select"});
146  }
147 }
148 
149 std::string IOPort::GenericName()
150 {
151  return "ioPort_" + std::to_string(num_inputs) + "in";
152 }
153 
155 {
156 }
157 
158 
159 static const std::map<std::string, CGRABlockType> block_type_map =
160 {
161  {"no-bypass", STANDARD_NOBYPASS},
162  {"bypass", STANDARD_BYPASS},
163  {"diagonal", STANDARD_DIAGONAL},
164 };
165 
166 std::istream& operator >>(std::istream &is, CGRABlockType &type)
167 {
168  std::string str;
169  is >> str;
170  if (block_type_map.count(str) > 0)
171  type = block_type_map.at(str);
172  else
173  is.setstate(std::ios_base::failbit);
174 
175  return is;
176 }
177 
178 SimpleFU::SimpleFU(std::string name, Location loc, CGRABlockType blockType_)
179  : Module(name, loc)
180  , blockType(blockType_)
181 {
183  {
184  // add input muxs
185  addSubModule(new Multiplexer("mux_a", loc, 5));
186  addSubModule(new Multiplexer("mux_b", loc, 5));
187  // add FU
188  addSubModule(new FuncUnit("func", loc, {OpCode::ADD, OpCode::MUL}, 32, 1, 0));
189  // add reg
190  addSubModule(new Register("register", loc, 32));
191  // add output mux
192  addSubModule(new Multiplexer("mux_out", loc, 2));
193  // config cells
194  addConfig(new ConfigCell("MuxAConfig"), {"mux_a.select"});
195  addConfig(new ConfigCell("MuxBConfig"), {"mux_b.select"});
196  addConfig(new ConfigCell("MuxOutConfig"), {"mux_out.select"});
197  addConfig(new ConfigCell("FuncConfig"), {"func.select"});
198  addConfig(new ConfigCell("RegisterConfig"), {"register.enable"});
199  // add all ports
205  // to mux_a
206  addConnection("this.in0", "mux_a.in0");
207  addConnection("this.in1", "mux_a.in1");
208  addConnection("this.in2", "mux_a.in2");
209  addConnection("this.in3", "mux_a.in3");
210  addConnection("mux_out.out", "mux_a.in4");
211  // to mux_b
212  addConnection("this.in0", "mux_b.in0");
213  addConnection("this.in1", "mux_b.in1");
214  addConnection("this.in2", "mux_b.in2");
215  addConnection("this.in3", "mux_b.in3");
216  addConnection("mux_out.out", "mux_b.in4");
217  // to funcunit
218  addConnection("mux_a.out", "func.in_a");
219  addConnection("mux_b.out", "func.in_b");
220  // to reg
221  addConnection("func.out", "register.in");
222  // to output mux
223  addConnection("func.out", "mux_out.in0");
224  addConnection("register.out", "mux_out.in1");
225  // to output
226  addConnection("mux_out.out", "this.out");
227  }
228  else if (blockType == STANDARD_BYPASS)
229  {
230  // add input muxs
231  addSubModule(new Multiplexer("mux_a", loc, 5));
232  addSubModule(new Multiplexer("mux_b", loc, 5));
233  // add FU
234  addSubModule(new FuncUnit("func", loc, {OpCode::ADD, OpCode::MUL}, 32, 1, 0));
235  // add bypass mux
236  addSubModule(new Multiplexer("mux_bypass", loc, 3));
237  // add reg
238  addSubModule(new Register("register", loc, 32));
239  // add output mux
240  addSubModule(new Multiplexer("mux_out", loc, 2));
241  // config cells
242  addConfig(new ConfigCell("MuxAConfig"), {"mux_a.select"});
243  addConfig(new ConfigCell("MuxBConfig"), {"mux_b.select"});
244  addConfig(new ConfigCell("MuxBypassConfig"), {"mux_bypass.select"});
245  addConfig(new ConfigCell("MuxOutConfig"), {"mux_out.select"});
246  addConfig(new ConfigCell("FuncConfig"), {"func.select"});
247  addConfig(new ConfigCell("RegisterConfig"), {"register.enable"});
248 
249  // add all ports
255  // to mux_a
256  addConnection("this.in0", "mux_a.in0");
257  addConnection("this.in1", "mux_a.in1");
258  addConnection("this.in2", "mux_a.in2");
259  addConnection("this.in3", "mux_a.in3");
260  addConnection("register.out", "mux_a.in4");
261  // to mux_b
262  addConnection("this.in0", "mux_b.in0");
263  addConnection("this.in1", "mux_b.in1");
264  addConnection("this.in2", "mux_b.in2");
265  addConnection("this.in3", "mux_b.in3");
266  addConnection("register.out", "mux_b.in4");
267  // to funcunit
268  addConnection("mux_a.out", "func.in_a");
269  addConnection("mux_b.out", "func.in_b");
270  // to bypass
271  addConnection("mux_a.out", "mux_bypass.in0");
272  addConnection("mux_b.out", "mux_bypass.in1");
273  addConnection("func.out", "mux_bypass.in2");
274  // to reg
275  addConnection("mux_bypass.out", "register.in");
276  // to output mux
277  addConnection("mux_bypass.out", "mux_out.in0");
278  addConnection("register.out", "mux_out.in1");
279  // to output
280  addConnection("mux_out.out", "this.out");
281  }
282  else if (blockType == STANDARD_DIAGONAL)
283  {
284  // add input muxs
285  addSubModule(new Multiplexer("mux_a", loc, 9));
286  addSubModule(new Multiplexer("mux_b", loc, 9));
287  // add FU
288  addSubModule(new FuncUnit("func", loc, {OpCode::ADD, OpCode::MUL}, 32, 1, 0));
289  // add bypass mux
290  addSubModule(new Multiplexer("mux_bypass", loc, 3));
291  // add reg
292  addSubModule(new Register("register", loc, 32));
293  // add output mux
294  addSubModule(new Multiplexer("mux_out", loc, 2));
295  // config cells
296  addConfig(new ConfigCell("MuxAConfig"), {"mux_a.select"});
297  addConfig(new ConfigCell("MuxBConfig"), {"mux_b.select"});
298  addConfig(new ConfigCell("MuxBypassConfig"), {"mux_bypass.select"});
299  addConfig(new ConfigCell("MuxOutConfig"), {"mux_out.select"});
300  addConfig(new ConfigCell("FuncConfig"), {"func.select"});
301  addConfig(new ConfigCell("RegisterConfig"), {"register.enable"});
302 
303  // add all ports
313  // to mux_a
314  addConnection("this.in0", "mux_a.in0");
315  addConnection("this.in1", "mux_a.in1");
316  addConnection("this.in2", "mux_a.in2");
317  addConnection("this.in3", "mux_a.in3");
318  addConnection("this.in4", "mux_a.in4");
319  addConnection("this.in5", "mux_a.in5");
320  addConnection("this.in6", "mux_a.in6");
321  addConnection("this.in7", "mux_a.in7");
322  addConnection("register.out", "mux_a.in8");
323  // to mux_b
324  addConnection("this.in0", "mux_b.in0");
325  addConnection("this.in1", "mux_b.in1");
326  addConnection("this.in2", "mux_b.in2");
327  addConnection("this.in3", "mux_b.in3");
328  addConnection("this.in4", "mux_b.in4");
329  addConnection("this.in5", "mux_b.in5");
330  addConnection("this.in6", "mux_b.in6");
331  addConnection("this.in7", "mux_b.in7");
332  addConnection("register.out", "mux_b.in8");
333  // to funcunit
334  addConnection("mux_a.out", "func.in_a");
335  addConnection("mux_b.out", "func.in_b");
336  // to bypass
337  addConnection("mux_a.out", "mux_bypass.in0");
338  addConnection("mux_b.out", "mux_bypass.in1");
339  addConnection("func.out", "mux_bypass.in2");
340  // to reg
341  addConnection("mux_bypass.out", "register.in");
342  // to output mux
343  addConnection("mux_bypass.out", "mux_out.in0");
344  addConnection("register.out", "mux_out.in1");
345  // to output
346  addConnection("mux_out.out", "this.out");
347  }
348  else
349  {
350  std::cout << "ERROR, unintended mode\n";
351  }
352 }
353 
355 {
356  return "cgrablock_bt" + std::to_string(blockType);
357 }
358 
360 {
361 }
362 
ConfigCell
Definition: Module.h:825
SimpleFU::~SimpleFU
virtual ~SimpleFU()
Definition: ModuleComposites.cpp:359
ModuleComposites.h
Multiplexer
Zero-cycle latency multiplexer.
Definition: Module.h:592
STANDARD_NOBYPASS
@ STANDARD_NOBYPASS
Definition: Module.h:76
Location
Definition: Module.h:156
Module::addConnection
void addConnection(std::string src, std::string dst, bool isInMRRG=true)
Definition: Module.cpp:1241
SimpleFU::GenericName
virtual std::string GenericName()
Definition: ModuleComposites.cpp:354
Module::addParameter
void addParameter(std::string parameterName, unsigned parameterValue)
Definition: Module.cpp:1503
IOPort::num_inputs
int num_inputs
Definition: ModuleComposites.h:34
Register
A simple latency element with an enable signal; a data flip-flop.
Definition: Module.h:566
OpCode::ADD
@ ADD
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
STANDARD_DIAGONAL
@ STANDARD_DIAGONAL
Definition: Module.h:78
IOPort::IOPort
IOPort(std::string name, Location, int num_inputs, int size=DEFAULT_SIZE)
Definition: ModuleComposites.cpp:110
MemPort::~MemPort
virtual ~MemPort()
Definition: ModuleComposites.cpp:106
to_string
const std::string & to_string(const OpGraphOpCode &opcode)
Definition: OpGraph.cpp:111
SimpleFU::blockType
CGRABlockType blockType
Definition: ModuleComposites.h:43
CGRABlockType
CGRABlockType
Definition: Module.h:74
MemPort::MemPort
MemPort(std::string name, Location, int num_connections, int size, int num_const_addresses, bool pred=false, int II=1)
Definition: ModuleComposites.cpp:15
Exception.h
IO
Supports the input and output ops. Will add an external port at the top-level of generated verilog.
Definition: Module.h:762
MemPort::num_const_addresses
int num_const_addresses
Definition: ModuleComposites.h:32
ConstUnit
Definition: Module.h:540
Module
Definition: Module.h:163
block_type_map
static const std::map< std::string, CGRABlockType > block_type_map
Definition: ModuleComposites.cpp:159
PORT_INPUT
@ PORT_INPUT
Definition: Module.h:63
string_from_stream
std::string string_from_stream(F &&f)
Definition: Exception.h:95
MemPort::GenericName
virtual std::string GenericName()
Definition: ModuleComposites.cpp:95
Module::addConfig
void addConfig(ConfigCell *c, std::vector< std::string > ConnectTo)
Definition: Module.cpp:1087
IOPort::~IOPort
virtual ~IOPort()
Definition: ModuleComposites.cpp:154
Module::getSize
int getSize() const
Definition: Module.h:246
STANDARD_BYPASS
@ STANDARD_BYPASS
Definition: Module.h:77
Module::addSubModule
void addSubModule(Module *m)
Definition: Module.cpp:1124
MemoryUnit
Single load & store memory operations.
Definition: Module.h:517
SimpleFU::SimpleFU
SimpleFU(std::string name, Location, CGRABlockType blockType=STANDARD_NOBYPASS)
Definition: ModuleComposites.cpp:178
Module::isElastic
bool isElastic
Definition: Module.h:236
OpCode::MUL
@ MUL
Module::loc
Location loc
Definition: Module.h:239
IOPort::GenericName
virtual std::string GenericName()
Definition: ModuleComposites.cpp:149
FuncUnit
Functional Unit, does one of a set of arithmetic computations.
Definition: Module.h:406
operator>>
std::istream & operator>>(std::istream &is, CGRABlockType &type)
Definition: ModuleComposites.cpp:166
DEFAULT_SIZE
const int DEFAULT_SIZE
Definition: Module.h:48
MemPort::num_connections
int num_connections
Definition: ModuleComposites.h:31
PORT_OUTPUT
@ PORT_OUTPUT
Definition: Module.h:64