OpenASIP 2.2
Loading...
Searching...
No Matches
MachineTester.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 MachineTester.cc
26 *
27 * Implementation of MachineTester class.
28 *
29 * @author Lasse Laasonen 2004 (lasse.laasonen-no.spam-tut.fi)
30 */
31
32#include <string>
33#include <cctype>
34
35#include "MachineTester.hh"
36#include "Socket.hh"
37#include "Bus.hh"
38#include "Segment.hh"
39#include "Port.hh"
40#include "Unit.hh"
41#include "ImmediateUnit.hh"
42#include "ControlUnit.hh"
43#include "ContainerTools.hh"
44#include "AssocTools.hh"
45#include "Application.hh"
46
47using std::set;
48using std::string;
49using std::pair;
50using namespace TTAMachine;
51
52/**
53 * Constructor.
54 *
55 * @param machine The machine on which the tests are done.
56 */
58 machine_(&machine) {
59
60 clearState();
61}
62
63
64/**
65 * Destructor.
66 */
69
70
71/**
72 * Tests if the given socket can be connected to the given segment.
73 *
74 * After calling this function, the reason for a test failure can be
75 * queried. Functions for querying the possible reasons are:
76 * connectionExists, illegalRegistration, sameDirSocketConnection,
77 * forbiddenSocketDirection.
78 *
79 * Note that only the first reason encountered is recorded.
80 *
81 * @param socket The socket.
82 * @param segment The segment.
83 * @return True if the connection can be made.
84 */
85bool
86MachineTester::canConnect(const Socket& socket, const Segment& segment) {
87
88 clearState();
89
90 if (socket.machine() != machine_) {
92 return false;
93 }
94 if (segment.parentBus()->machine() != machine_) {
96 return false;
97 }
98 if (socket.isConnectedTo(segment)) {
99 connectionExists_ = true;
100 return false;
101 }
102
103 // check that the direction of the socket can be set if needed
104 if (socket.segmentCount() == 0) {
105 if (!legalPortConnections(socket, Socket::INPUT) &&
107 return false;
108 }
109 }
110
111 return true;
112}
113
114
115/**
116 * Checks if the given socket can be connected to the given port.
117 *
118 * If false is returned, the reason for the test failure can be queried
119 * using the following functions: illegalRegistration, connectionExists,
120 * wrongSocketDirection, maxConnections.
121 *
122 * @param socket The socket.
123 * @param port The port.
124 * @return True if the connection can be made, otherwise false.
125 */
126bool
127MachineTester::canConnect(const Socket& socket, const Port& port) {
128
129 clearState();
130
131 // check registration
132 if (socket.machine() != machine_ ||
133 port.parentUnit()->machine() != machine_) {
135 return false;
136 }
137
138 // check the existing connections of the port
139 Socket* inputSocket = port.inputSocket();
140 Socket* outputSocket = port.outputSocket();
141 Socket* firstUnconnected = port.unconnectedSocket(0);
142 Socket* secondUnconnected = port.unconnectedSocket(1);
143
144 if (inputSocket == &socket || outputSocket == &socket ||
145 firstUnconnected == &socket || secondUnconnected == &socket) {
146 connectionExists_ = true;
147 return false;
148 }
149
150 if ((inputSocket != NULL && socket.direction() == Socket::INPUT) ||
151 (outputSocket != NULL && socket.direction() == Socket::OUTPUT)) {
153 return false;
154 }
155 if (port.socketCount() == 2) {
156 maxConnections_ = true;
157 return false;
158 }
159
160 // check the special cases of allowed socket directions
161 Unit* parentUnit = port.parentUnit();
162 if (dynamic_cast<ImmediateUnit*>(parentUnit) != NULL) {
163 assert(port.socketCount() <= 1);
164 if (port.socketCount() == 1) {
165 maxConnections_ = true;
166 return false;
167 }
168 if (socket.direction() == Socket::INPUT) {
170 return false;
171 }
172 }
173
174 // ports of a register file cannot be connected to same socket
175 RegisterFile* parentRf = dynamic_cast<RegisterFile*>(parentUnit);
176 if (parentRf != NULL) {
177 for (int i = 0; i < parentRf->portCount(); i++) {
178 Port* rfPort = parentRf->port(i);
179 if (rfPort->isConnectedTo(socket)) {
181 return false;
182 }
183 }
184 }
185
186 return true;
187}
188
189
190/**
191 * Checks if the given source and destination buses can be joined by a new
192 * bridge.
193 *
194 * If the test has negative outcome, the reason for it can be queried using
195 * the following functions: illegalRegistration, loop, connectionExists,
196 * branchedBus.
197 *
198 * @param source The source bus of the bridge.
199 * @param destination The destination bus of the bridge.
200 * @return True if the can be created, otherwise false.
201 */
202bool
203MachineTester::canBridge(const Bus& source, const Bus& destination) {
204
205 clearState();
206
207 // check registration of the buses
208 if (source.machine() != machine_ || destination.machine() != machine_) {
210 return false;
211 }
212
213 if (&source == &destination) {
214 return false;
215 }
216
217 // check if there already exists an equal bridge
218 if (source.canWrite(destination)) {
219 connectionExists_ = true;
220 return false;
221 } else if (destination.canWrite(source)) {
222 // if an opposite bridge already exists between the buses, the new
223 // bridge can be created
224 return true;
225 }
226
227 // check if a loop would be created
228
229 // Buses cannot be joined by a new bridge if they are already in the same
230 // chain and are not adjacent. If they are adjacent then it is possible
231 // to join them in order the create a bidirection bridge.
232 if (areInSameChain(source, destination)) {
233 bool adjacent = false;
234 if (source.hasNextBus()) {
235 if (source.nextBus() == &destination) {
236 adjacent = true;
237 }
238 }
239 if (source.hasPreviousBus()) {
240 if (source.previousBus() == &destination) {
241 adjacent = true;
242 }
243 }
244 if (!adjacent) {
245 loop_ = true;
246 return false;
247 }
248 }
249
250 // check that a branch will not be created
251 if (source.hasNextBus() && source.hasPreviousBus()) {
252 if (source.nextBus() != &destination &&
253 source.previousBus() != &destination) {
254 branchedBus_ = &source;
255 return false;
256 }
257 }
258 if (destination.hasNextBus() && destination.hasPreviousBus()) {
259 if (destination.nextBus() != &source &&
260 destination.previousBus() != &source) {
261 branchedBus_ = &destination;
262 return false;
263 }
264 }
265
266 return true;
267}
268
269
270/**
271 * Checks if the direction of the given socket can be set to the given value.
272 *
273 * Takes into account the ports that are directly connected to the given
274 * socket only. The reason for error can be queried for using the following
275 * functions: unknownSocketDirection, noConnections, sameDirSocketConnection,
276 * forbiddenSocketDirection.
277 *
278 * @param socket The socket.
279 * @param direction The new direction of the socket.
280 * @return True if the direction can be set, otherwise false.
281 */
282bool
284 const Socket& socket,
285 Socket::Direction direction) {
286
287 clearState();
288
289 if (direction == Socket::UNKNOWN) {
290 unknownDir_ = true;
291 return false;
292 }
293 if (socket.segmentCount() == 0) {
294 noConnections_ = true;
295 return false;
296 }
297 if (direction == socket.direction()) {
298 return true;
299 }
300
301 return legalPortConnections(socket, direction);
302}
303
304
305/**
306 * Checks whether the given string is a valid machine component name.
307 *
308 * @param name The name to check.
309 * @return True if the name is valid, otherwise false.
310 */
311bool
312MachineTester::isValidComponentName(const std::string& name) {
313
314 if (name.length() == 0) {
315 return false;
316 }
317
318 for (unsigned int i = 0; i < name.length(); i++) {
319 char character = name[i];
320 if (i == 0) {
321 if (!isalpha(character)) {
322 return false;
323 }
324 } else {
325 if (!isalpha(character) && !isdigit(character) &&
326 character != '_' && character != ':') {
327 return false;
328 }
329 }
330 }
331 return true;
332}
333
334
335/**
336 * Returns true if the reason for failure of the previous test was that a
337 * connection exists already between the components.
338 *
339 * @return True if a connection exists, otherwise false.
340 */
341bool
345
346
347/**
348 * Returns true if the reason for failure of the previous test was illegal
349 * registration of components.
350 *
351 * @return True if the components were not registered to the same machine,
352 * otherwise false.
353 */
354bool
358
359
360/**
361 * If the reason for failure when tried to join two buses by a bridge was
362 * loop in bus chain, returns true. Otherwise returns false.
363 *
364 * @return True, if loop was the reason for failure.
365 */
366bool
368 return loop_;
369}
370
371
372/**
373 * If the reason for failure when tried to join two buses by a bridge was
374 * a branched bus chain, returns the bus that was going to be branched.
375 * Otherwise returns NULL.
376 *
377 * @return The branched bus.
378 */
379Bus*
381 if (branchedBus_ == NULL) {
382 return NULL;
383 } else {
384 return const_cast<Bus*>(branchedBus_);
385 }
386}
387
388
389/**
390 * Checks if wrong direction of socket was the reason for failure when tried
391 * to attach a port to a socket.
392 *
393 * @return True, if wrong direction of socket was the reason, otherwise
394 * false.
395 */
396bool
400
401
402/**
403 * Checks if maximum number of connections in port was the reason for
404 * failure when tried to attach a port to a socket.
405 *
406 * @return True, if maximum number of connection was the reason, otherwise
407 * false.
408 */
409bool
413
414
415/**
416 * Returns true if the reason for failure when tried to set socket direction
417 * was unknown direction. The direction of socket can never be set to
418 * unknown.
419 *
420 * @return True if the reason for failure was unknown socket direction,
421 * otherwise false.
422 */
423bool
427
428
429/**
430 * Returns true if the reason for failure when tried to set socket direction
431 * was that the socket has no connections to segments.
432 *
433 * @return True if the socket has no connections to segments, otherwise
434 * false.
435 */
436bool
440
441
442/**
443 * If the reason for failure when tried to set socket direction was that the
444 * socket was connected to a port that was connected to another socket that
445 * has the same direction, returns that port. Otherwise returns NULL.
446 *
447 * @param direction The direction that was tried to set.
448 * @return The port.
449 */
450Port*
452 if (direction == Socket::INPUT) {
454 } else if (direction == Socket::OUTPUT) {
456 } else {
457 return NULL;
458 }
459}
460
461
462/**
463 * If the reason for failure when tried to set socket direction was that the
464 * socket was connected to a port of a unit that doesn't allow sockets of
465 * such direction to be connected, returns the port. Otherwise returns NULL.
466 *
467 * @param direction The direction that was tried to set.
468 * @return The port.
469 */
470Port*
472 if (direction == Socket::INPUT) {
474 } else {
475 return NULL;
476 }
477}
478
479
480/**
481 * Tells whether the reason for failure when tried to attach a port to a
482 * socket was that the parent unit of the port was register file and a port
483 * of the register file was already connected to the socket.
484 *
485 * @return True if that was the reason, otherwise false.
486 */
487bool
491
492
493/**
494 * Clears the state of the object.
495 */
496void
498 connectionExists_ = false;
500 illegalRegistration_ = false;
501 loop_ = false;
502 branchedBus_ = NULL;
503 wrongSocketDirection_ = false;
504 maxConnections_ = false;
505 unknownDir_ = false;
506 noConnections_ = false;
510}
511
512
513/**
514 * Checks if the given buses are in the same bus chain.
515 *
516 * @param bus1 The first bus.
517 * @param bus2 The second bus.
518 * @return True if they are in the same chain, otherwise false.
519 */
520bool
521MachineTester::areInSameChain(const Bus& bus1, const Bus& bus2) {
522
523 if (&bus1 == &bus2) {
524 return true;
525 }
526
527 const Bus* bus = &bus1;
528 while (bus->hasPreviousBus()) {
529 bus = bus->previousBus();
530 if (bus == &bus2) {
531 return true;
532 }
533 }
534
535 bus = &bus1;
536 while (bus->hasNextBus()) {
537 bus = bus->nextBus();
538 if (bus == &bus2) {
539 return true;
540 }
541 }
542
543 return false;
544}
545
546
547/**
548 * Checks if the given socket will have legal connections to ports if its
549 * direction is changed to the given value.
550 *
551 * @param socket The socket to test.
552 * @param direction The direction to test.
553 * @return True if the connections will stay legal, otherwise false.
554 */
555bool
557 const Socket& socket,
558 Socket::Direction direction) {
559
560 for (int i = 0; i < socket.portCount(); i++) {
561 Port* port = socket.port(i);
562 if (direction == Socket::INPUT && port->inputSocket() != NULL) {
564 return false;
565 } else if (direction == Socket::OUTPUT &&
566 port->outputSocket() != NULL) {
568 return false;
569 }
570 Unit* parent = port->parentUnit();
571 if (dynamic_cast<ImmediateUnit*>(parent) != NULL &&
572 direction == Socket::INPUT) {
574 return false;
575 }
576 }
577
578 return true;
579}
#define assert(condition)
TTAMachine::Machine * machine
the architecture definition of the estimated processor
TTAMachine::Port * sameDirSocketConnection(TTAMachine::Socket::Direction direction) const
TTAMachine::Port * sameDirOutputSocketConn_
If the reason for failure when tried to set socket direction to output was that the socket is connect...
const TTAMachine::Machine * machine_
The machine on which the tests are carried out.
bool wrongSocketDirection_
Indicates if the reason for failure when trying to connect a socket to a port was that the direction ...
const TTAMachine::Bus * branchedBus_
If the reason for failure when trying to bridge two busses is that a branch in the bus chain would be...
bool legalPortConnections(const TTAMachine::Socket &socket, TTAMachine::Socket::Direction direction)
bool illegalRegistration_
Indicates if the reason for last test failure was illegal registration.
virtual ~MachineTester()
bool illegalRegistration() const
bool wrongSocketDirection() const
bool maxConnections() const
TTAMachine::Bus * branchedBus() const
virtual bool canConnect(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment)
bool noConnections() const
TTAMachine::Port * forbiddenSocketDirection(TTAMachine::Socket::Direction direction) const
virtual bool canBridge(const TTAMachine::Bus &source, const TTAMachine::Bus &destination)
bool maxConnections_
Indicates if the reason for failure when trying to connect a socket to a port was that this connectio...
bool noConnections_
Indicates if the reason for failure when tried to set socket direction was that the socket has no seg...
static bool isValidComponentName(const std::string &name)
bool registerFilePortAlreadyConnected() const
MachineTester(const TTAMachine::Machine &machine)
bool connectionExists() const
TTAMachine::Port * sameDirInputSocketConn_
If the reason for failure when tried to set socket direction to input was that the socket is connecte...
bool unknownSocketDirection() const
bool loop() const
TTAMachine::Port * forbiddenInputSocketDir_
If the reason for failure when tried to set socket direction to input was the socket is connected to ...
virtual bool canSetDirection(const TTAMachine::Socket &socket, TTAMachine::Socket::Direction direction)
bool loop_
Indicates if the reason for failure when trying to bridge two busses is that a loop in the bus chain ...
bool connectionExists_
Indicates if the reason for the last test failure is that the tested connection already exists.
bool unknownDir_
Indicates if tried to set the socket direction to Socket::UNKNOWN.
bool rfPortAlreadyConnected_
Indicates if the reason for failure is that a port of register file is already connected to a particu...
static bool areInSameChain(const TTAMachine::Bus &bus1, const TTAMachine::Bus &bus2)
virtual RFPort * port(const std::string &name) const
virtual Bus * previousBus() const
Definition Bus.cc:518
virtual bool canWrite(const Bus &bus) const
Definition Bus.cc:558
virtual bool hasPreviousBus() const
Definition Bus.cc:473
virtual bool hasNextBus() const
Definition Bus.cc:488
virtual Bus * nextBus() const
Definition Bus.cc:501
virtual Machine * machine() const
virtual Socket * outputSocket() const
Definition Port.cc:281
virtual int socketCount() const
Definition Port.cc:375
virtual Socket * unconnectedSocket(int index) const
Definition Port.cc:323
virtual bool isConnectedTo(const Socket &socket) const
Definition Port.cc:393
Unit * parentUnit() const
virtual Socket * inputSocket() const
Definition Port.cc:261
Bus * parentBus() const
@ OUTPUT
Data goes from port to bus.
Definition Socket.hh:60
@ INPUT
Data goes from bus to port.
Definition Socket.hh:59
@ UNKNOWN
Unknown direction.
Definition Socket.hh:61
bool isConnectedTo(const Bus &bus) const
Definition Socket.cc:331
Direction direction() const
Port * port(int index) const
Definition Socket.cc:266
int segmentCount() const
int portCount() const
virtual int portCount() const
Definition Unit.cc:135