OpenASIP 2.2
Loading...
Searching...
No Matches
FullyConnectedCheck.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file FullyConnectedCheck.hh
26 *
27 * Implementation of FullyConnectedCheck class.
28 *
29 * @author Jari Mäntyneva 2007 (jari.mantyneva-no.spam-tut.fi)
30 * @note rating: red
31 */
32
34#include "Machine.hh"
35#include "MachineTester.hh"
36#include "FunctionUnit.hh"
37#include "FUPort.hh"
38#include "Socket.hh"
39#include "HWOperation.hh"
40#include "ExecutionPipeline.hh"
41#include "ControlUnit.hh"
43#include "Socket.hh"
45#include "Conversion.hh"
46
47using namespace TTAMachine;
48
49/**
50 * Constructor for using this generic class directly.
51 */
53 MachineCheck("Fully connected machine check.") {
54}
55
56/**
57 * Constructor for deriving.
58 *
59 * @param shortDesc The short description of the check.
60 */
61FullyConnectedCheck::FullyConnectedCheck(const std::string& shortDesc):
62 MachineCheck(shortDesc) {
63}
64
65/**
66 * The destructor.
67 */
70
71/**
72 * Returns true if the machine can be fixed to pass the check.
73 *
74 * @param mach The machine to be analyzed.
75 * @return True if the machine can be fixed to pass the check.
76 */
77bool
79
81 mach.bridgeNavigator();
82
84 mach.busNavigator();
85
86 if (busNav.count() == 0 || brNav.count() > 0) {
87 return false;
88 }
89 return true;
90}
91
92/**
93 * Checks is the machine fully connected.
94 *
95 * @param mach Machine to be checked.
96 * @return True if the machine is fully connected.
97 */
98bool
101 socketNav = mach.socketNavigator();
102
103 for (int so = 0; so < socketNav.count(); so++) {
104 // for each socket in the machine
105 if (!socketAttachedToAllBusses(*socketNav.item(so))) {
106 return false;
107 }
108 }
109
110 // check unconnected FU ports
112
113 for (int i = 0; i < fuNav.count(); i++) {
114 FunctionUnit& fu = *fuNav.item(i);
115 for (int p = 0; p < fu.operationPortCount(); p++) {
116 FUPort& port = *fu.operationPort(p);
117 if (port.socketCount() == 0) {
118 return false;
119 }
120 }
121 }
122
123 // check unconnected IU ports
126
127 for (int i = 0; i < iuNav.count(); i++) {
128 ImmediateUnit& iu = *iuNav.item(i);
129 for (int p = 0; p < iu.portCount(); p++) {
130 RFPort& port = *iu.port(p);
131 if (port.socketCount() == 0) {
132 return false;
133 }
134 }
135 }
136
137 // check unconnected RF ports
139
140 for (int i = 0; i < rfNav.count(); i++) {
141 RegisterFile& rf = *rfNav.item(i);
142 for (int p = 0; p < rf.portCount(); p++) {
143 RFPort& port = *rf.port(p);
144 if (port.socketCount() == 0) {
145 return false;
146 }
147 }
148 }
149
150 ControlUnit* gcu = mach.controlUnit();
151 if (gcu != NULL) {
152 for (int p = 0; p < gcu->operationPortCount(); p++) {
153 FUPort& port = *gcu->operationPort(p);
154 if (port.socketCount() == 0) {
155 return false;
156 }
157 }
158 }
159 return true;
160}
161
162/**
163 * Checks is the machine fully connected and adds errors to results.
164 *
165 * @param mach Machine to be checked.
166 * @param results Check results.
167 * @return True if the machine is fully connected.
168 */
169bool
171 const TTAMachine::Machine& mach, MachineCheckResults& results) const {
172
173 bool result = true;
174
176 socketNav = mach.socketNavigator();
177
178 for (int so = 0; so < socketNav.count(); so++) {
179 // for each socket in the machine
180 if (!socketAttachedToAllBusses(*socketNav.item(so))) {
181 results.addError(
182 *this, "All sockets not connected to all busses.");
183 result = false;
184 }
185 }
186
187 // check unconnected FU ports
189
190 for (int i = 0; i < fuNav.count(); i++) {
191 FunctionUnit& fu = *fuNav.item(i);
192 for (int p = 0; p < fu.operationPortCount(); p++) {
193 FUPort& port = *fu.operationPort(p);
194 if (port.socketCount() == 0) {
195 results.addError(
196 *this, "FU: '" + fu.name() + "' port '" +
197 port.name() + "' not connected to any socket.");
198 result = false;
199 }
200 }
201 }
202
203 // check unconnected IU ports
206
207 for (int i = 0; i < iuNav.count(); i++) {
208 ImmediateUnit& iu = *iuNav.item(i);
209 for (int p = 0; p < iu.portCount(); p++) {
210 RFPort& port = *iu.port(p);
211 if (port.socketCount() == 0) {
212 results.addError(
213 *this, "IU: '" + iu.name() + "' port '" +
214 port.name() + "' not connected to any socket.");
215 result = false;
216 }
217 }
218 }
219
220 // check unconnected RF ports
222
223 for (int i = 0; i < rfNav.count(); i++) {
224 RegisterFile& rf = *rfNav.item(i);
225 for (int p = 0; p < rf.portCount(); p++) {
226 RFPort& port = *rf.port(p);
227 if (port.socketCount() == 0) {
228 results.addError(
229 *this, "RF: '" + rf.name() + "' port '" +
230 port.name() + "' not connected to any socket.");
231 result = false;
232 }
233 }
234 }
235
236 ControlUnit* gcu = mach.controlUnit();
237 if (gcu != NULL) {
238 for (int p = 0; p < gcu->operationPortCount(); p++) {
239 FUPort& port = *gcu->operationPort(p);
240 if (port.socketCount() == 0) {
241 results.addError(
242 *this, "GCU port '" +
243 port.name() + "' not connected to any socket.");
244 return false;
245 }
246 }
247 for (int p = 0; p < gcu->specialRegisterPortCount(); p++) {
249 if (port.socketCount() == 0) {
250 results.addError(
251 *this, "GCU port '" +
252 port.name() + "' not connected to any socket.");
253 }
254 }
255 }
256 return result;
257}
258
259/**
260 * Fixes the machine to pass the chek if possible.
261 *
262 * @param mach Machine to be fixed.
263 * @return Returns an empty string.
264 * @exception InvalidData Thows if the machine cannot be fixed.
265 */
266std::string
268 if (!canFix(mach)) {
269 throw InvalidData(
270 __FILE__, __LINE__, __func__,
271 "Machines contains no busses or contains bridges.");
272 }
273
275 socketNav = mach.socketNavigator();
276
277 for (int so = 0; so < socketNav.count(); so++) {
278 // for each socket in the machine
279 attachSocketToAllBusses(*socketNav.item(so));
280 }
281 // Connect all unconnected FU ports to newly created sockets.
283
284 for (int i = 0; i < fuNav.count(); i++) {
285 FunctionUnit& fu = *fuNav.item(i);
286 for (int p = 0; p < fu.operationPortCount(); p++) {
287 FUPort& port = *fu.operationPort(p);
288 if (port.socketCount() == 0) {
289 connectFUPort(port);
290 }
291 }
292 }
293
294 // Connect all unconnected IU ports to new sockets.
297
298 for (int i = 0; i < iuNav.count(); i++) {
299 ImmediateUnit& iu = *iuNav.item(i);
300 for (int p = 0; p < iu.portCount(); p++) {
301 RFPort& port = *iu.port(p);
302 if (port.socketCount() == 0) {
303 connectIUPort(port);
304 }
305 }
306 }
307
308 // Connect all unconnected RF ports to new sockets.
310
311 for (int i = 0; i < rfNav.count(); i++) {
312 RegisterFile& rf = *rfNav.item(i);
313 int maxReads = rf.maxReads();
314 int maxWrites = rf.maxWrites();
315 bool lastWasReadPort = false;
316 for (int p = 0; p < rf.portCount(); p++) {
317 RFPort& port = *rf.port(p);
318 if (port.socketCount() == 0) {
319 if (maxReads > 0) {
321 maxReads--;
322 } else if (maxWrites > 0) {
324 maxWrites--;
325 } else {
326 // when maxReads == 0 and maxWrites == 0, connect every other
327 // port as a read port, every other as write
328 if (lastWasReadPort) {
330 lastWasReadPort = false;
331 } else {
333 lastWasReadPort = true;
334 }
335 }
336
337 }
338 else // port connected, check wheter it is input or output
339 {
340 if (port.inputSocket() != NULL) {
341 maxWrites--;
342 } else if (port.outputSocket() != NULL) {
343 maxReads--;
344 } else {
345 // port connected, but input and output sockets are null
346 throw InvalidData(
347 __FILE__, __LINE__, __func__,
348 "Port connected to unknown socket.");
349 }
350 }
351 }
352 }
353
354 ControlUnit* gcu = mach.controlUnit();
355 if (gcu != NULL) {
356 connectControlUnit(*gcu);
357 }
358
359 return "";
360}
361
362void
364 for (int p = 0; p < gcu.operationPortCount(); p++) {
365 FUPort& port = *gcu.operationPort(p);
366 if (port.socketCount() == 0) {
367 connectFUPort(port);
368 }
369 }
370 for (int p = 0; p < gcu.specialRegisterPortCount(); p++) {
372 if (port.socketCount() == 0) {
374 }
375 }
376}
377/**
378 * Connects an immediate unit port to all possible busses.
379 *
380 * @param port Immediate unit port to connect.
381 */
382void
384
385 MachineTester tester(*port.parentUnit()->machine());
386
387 Socket* socket = createSocket(*port.parentUnit(), Socket::OUTPUT);
388
389 if (tester.canConnect(*socket, port)) {
390 port.attachSocket(*socket);
391 } else {
392 delete socket;
393 }
394}
395
396/**
397 * Connects a special register port to all possible busses.
398 *
399 * @param port Special register port to connect.
400 */
401void
403 SpecialRegisterPort& port) const{
404
405 MachineTester tester(*port.parentUnit()->machine());
406
407 Socket* inSocket = createSocket(*port.parentUnit(), Socket::INPUT);
408 Socket* outSocket = createSocket(*port.parentUnit(), Socket::OUTPUT);
409
410 if (tester.canConnect(*inSocket, port)) {
411 port.attachSocket(*inSocket);
412 } else {
413 delete inSocket;
414 }
415
416 if (tester.canConnect(*outSocket, port)) {
417 port.attachSocket(*outSocket);
418 } else {
419 delete outSocket;
420 }
421}
422
423
424/**
425 * Connects a register file port to all possible busses.
426 *
427 * @param port Immediate unit port to connect.
428 */
429void
431
432 MachineTester tester(*port.parentUnit()->machine());
433 const BaseRegisterFile& rf = *port.parentUnit();
434
435 Socket* socket = NULL;
436 socket = createSocket(rf, direction);
437
438 if (tester.canConnect(*socket, port)) {
439 port.attachSocket(*socket);
440 } else {
441 delete socket;
442 }
443
444}
445
446/**
447 * Creates a new socket to be attached to an unit.
448 *
449 * @param unit Unit whose name is used to generate a name for the socket.
450 * @param direction Direction of the socket.
451 * @return A new socket, attached to all possible busses, but not to a port.
452 */
453Socket*
455 const Unit& unit, Socket::Direction direction) const {
456
458
461
462 int s = 1;
463 std::string socketName = unit.name();
464 if (direction == Socket::INPUT) {
465 socketName = socketName + "_i";
466 } else {
467 socketName = socketName + "_o";
468 }
469
470 while (socketNav.hasItem(
471 socketName + Conversion::toString(s))) {
472
473 s++;
474 }
475
476 Socket* socket =
477 new Socket(socketName + Conversion::toString(s));
478
479 socket->setMachine(machine);
481
482 // direction can be set only if the socket is connected to a segment
483 if (socket->segmentCount() > 0) {
484 socket->setDirection(direction);
485 }
486
487 return socket;
488}
489
490
491/**
492 * Creates socket(s) and connects a FU port to all possible busses.
493 *
494 * @param port FU port to connect to busses.
495 */
496void
498
499 const FunctionUnit& fu = *port.parentUnit();
500 Machine& machine = *fu.machine();
501 MachineTester tester(machine);
502
504 const Machine::SocketNavigator socketNav =
506
507 // Operand ports.
508 for (int i = 0; i < fu.operationCount(); i++) {
509 const HWOperation& operation = *fu.operation(i);
510 for (int c = 0; c < operation.latency(); c++) {
511 if (port.inputSocket() == NULL &&
512 operation.pipeline()->isPortRead(port, c)) {
513
514 Socket* socket = createSocket(fu, Socket::INPUT);
515
516 if (tester.canConnect(*socket, port)) {
517 port.attachSocket(*socket);
518 } else {
519 delete socket;
520 }
521 break;
522 }
523 }
524 }
525
526 // Result ports.
527 for (int i = 0; i < fu.operationCount(); i++) {
528 const HWOperation& operation = *fu.operation(i);
529 for (int c = 0; c < operation.latency(); c++) {
530 if (port.outputSocket() == NULL &&
531 operation.pipeline()->isPortWritten(port, c)) {
532
533 Socket* socket = createSocket(fu, Socket::OUTPUT);
534 if (tester.canConnect(*socket, port)) {
535 port.attachSocket(*socket);
536 } else {
537 delete socket;
538 }
539 break;
540 }
541 }
542 }
543
544}
545
546/**
547 * Attaches given socket to all possible busses.
548 *
549 * @param socket Socket to connect.
550 */
551void
553
555 MachineTester tester(machine);
556
558
559 for (int b = 0; b < busNav.count(); b++) {
560 // for each bus in the machine
561 TTAMachine::Bus& bus = *busNav.item(b);
562 for (int seg = 0; seg < bus.segmentCount(); seg++) {
563 TTAMachine::Segment& segment = *bus.segment(seg);
564 // for each segment in the bus
565 if ((!socket.isConnectedTo(segment)) &&
566 tester.canConnect(socket, segment)) {
567
568 socket.attachBus(segment);
569 }
570 }
571 }
572}
573
574/**
575 * Checks if the given socket is attached to all possible busses.
576 *
577 * @param socket Socket to check.
578 * @return True if the socket is attached to all possible busses.
579 */
580bool
582
584 MachineTester tester(machine);
585
587
588 for (int b = 0; b < busNav.count(); b++) {
589 // for each bus in the machine
590 TTAMachine::Bus& bus = *busNav.item(b);
591 for (int seg = 0; seg < bus.segmentCount(); seg++) {
592 TTAMachine::Segment& segment = *bus.segment(seg);
593 // for each segment in the bus
594 if (!socket.isConnectedTo(segment)) {
595 if (tester.canConnect(socket, segment)) {
596 return false;
597 }
598 }
599 }
600 }
601 return true;
602}
#define __func__
TTAMachine::Machine * machine
the architecture definition of the estimated processor
static std::string toString(const T &source)
virtual bool check(const TTAMachine::Machine &mach) const
bool socketAttachedToAllBusses(const TTAMachine::Socket &socket) const
void connectRFPort(TTAMachine::RFPort &port, TTAMachine::Socket::Direction direction) const
void connectControlUnit(TTAMachine::ControlUnit &gcu) const
void connectIUPort(TTAMachine::RFPort &port) const
void attachSocketToAllBusses(TTAMachine::Socket &socket) const
void connectSpecialRegisterPort(TTAMachine::SpecialRegisterPort &port) const
virtual std::string fix(TTAMachine::Machine &mach) const
virtual bool canFix(const TTAMachine::Machine &mach) const
TTAMachine::Socket * createSocket(const TTAMachine::Unit &unit, TTAMachine::Socket::Direction direction) const
void connectFUPort(TTAMachine::FUPort &port) const
void addError(const MachineCheck &check, const std::string &errorMsg)
virtual bool canConnect(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment)
FunctionUnit * parentUnit() const
Definition BaseFUPort.cc:96
virtual RFPort * port(const std::string &name) const
virtual Segment * segment(int index) const
Definition Bus.cc:329
virtual int segmentCount() const
Definition Bus.cc:385
virtual Machine * machine() const
virtual TCEString name() const
SpecialRegisterPort * specialRegisterPort(int index) const
int specialRegisterPortCount() const
bool isPortWritten(const FUPort &port, int cycle) const
bool isPortRead(const FUPort &port, int cycle) const
virtual HWOperation * operation(const std::string &name) const
virtual int operationCount() const
virtual FUPort * operationPort(const std::string &name) const
virtual int operationPortCount() const
ExecutionPipeline * pipeline() const
ComponentType * item(int index) const
bool hasItem(const std::string &name) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual BridgeNavigator bridgeNavigator() const
Definition Machine.cc:404
virtual SocketNavigator socketNavigator() const
Definition Machine.cc:368
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
virtual Socket * outputSocket() const
Definition Port.cc:281
virtual void attachSocket(Socket &socket)
Definition Port.cc:191
virtual int socketCount() const
Definition Port.cc:375
virtual Socket * inputSocket() const
Definition Port.cc:261
virtual std::string name() const
Definition Port.cc:141
BaseRegisterFile * parentUnit() const
Definition RFPort.cc:93
virtual int maxReads() const
virtual int maxWrites() const
void setDirection(Direction direction)
Definition Socket.cc:130
@ OUTPUT
Data goes from port to bus.
Definition Socket.hh:60
@ INPUT
Data goes from bus to port.
Definition Socket.hh:59
bool isConnectedTo(const Bus &bus) const
Definition Socket.cc:331
void attachBus(Segment &bus)
Definition Socket.cc:166
virtual void setMachine(Machine &mach)
Definition Socket.cc:432
int segmentCount() const
virtual int portCount() const
Definition Unit.cc:135