OpenASIP  2.0
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 
47 using std::set;
48 using std::string;
49 using std::pair;
50 using 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  */
68 }
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  */
85 bool
86 MachineTester::canConnect(const Socket& socket, const Segment& segment) {
87 
88  clearState();
89 
90  if (socket.machine() != machine_) {
91  illegalRegistration_ = true;
92  return false;
93  }
94  if (segment.parentBus()->machine() != machine_) {
95  illegalRegistration_ = true;
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) &&
106  !legalPortConnections(socket, Socket::OUTPUT)) {
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  */
126 bool
127 MachineTester::canConnect(const Socket& socket, const Port& port) {
128 
129  clearState();
130 
131  // check registration
132  if (socket.machine() != machine_ ||
133  port.parentUnit()->machine() != machine_) {
134  illegalRegistration_ = true;
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)) {
152  wrongSocketDirection_ = true;
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) {
169  wrongSocketDirection_ = true;
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  */
202 bool
203 MachineTester::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_) {
209  illegalRegistration_ = true;
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  */
282 bool
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  */
311 bool
312 MachineTester::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  */
341 bool
343  return connectionExists_;
344 }
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  */
354 bool
356  return illegalRegistration_;
357 }
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  */
366 bool
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  */
379 Bus*
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  */
396 bool
398  return wrongSocketDirection_;
399 }
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  */
409 bool
411  return maxConnections_;
412 }
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  */
423 bool
425  return unknownDir_;
426 }
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  */
436 bool
438  return noConnections_;
439 }
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  */
450 Port*
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  */
470 Port*
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  */
487 bool
490 }
491 
492 
493 /**
494  * Clears the state of the object.
495  */
496 void
498  connectionExists_ = false;
499  rfPortAlreadyConnected_ = 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  */
520 bool
521 MachineTester::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  */
555 bool
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 }
TTAMachine::Port::unconnectedSocket
virtual Socket * unconnectedSocket(int index) const
Definition: Port.cc:323
MachineTester::canConnect
virtual bool canConnect(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment)
Definition: MachineTester.cc:86
MachineTester::noConnections_
bool noConnections_
Indicates if the reason for failure when tried to set socket direction was that the socket has no seg...
Definition: MachineTester.hh:122
TTAMachine::Port::inputSocket
virtual Socket * inputSocket() const
Definition: Port.cc:261
TTAMachine::Socket::port
Port * port(int index) const
Definition: Socket.cc:266
TTAMachine::Socket::portCount
int portCount() const
machine
TTAMachine::Machine * machine
the architecture definition of the estimated processor
Definition: EstimatorCmdLineUI.cc:59
MachineTester::MachineTester
MachineTester(const TTAMachine::Machine &machine)
Definition: MachineTester.cc:57
TTAMachine::Segment
Definition: Segment.hh:54
MachineTester::unknownSocketDirection
bool unknownSocketDirection() const
Definition: MachineTester.cc:424
TTAMachine::Bus
Definition: Bus.hh:53
TTAMachine::Bus::canWrite
virtual bool canWrite(const Bus &bus) const
Definition: Bus.cc:558
MachineTester::canBridge
virtual bool canBridge(const TTAMachine::Bus &source, const TTAMachine::Bus &destination)
Definition: MachineTester.cc:203
MachineTester::machine_
const TTAMachine::Machine * machine_
The machine on which the tests are carried out.
Definition: MachineTester.hh:94
ImmediateUnit.hh
MachineTester::illegalRegistration
bool illegalRegistration() const
Definition: MachineTester.cc:355
MachineTester::branchedBus_
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...
Definition: MachineTester.hh:109
TTAMachine::Socket::Direction
Direction
Definition: Socket.hh:58
TTAMachine::Socket::direction
Direction direction() const
TTAMachine::Bus::hasPreviousBus
virtual bool hasPreviousBus() const
Definition: Bus.cc:473
MachineTester::noConnections
bool noConnections() const
Definition: MachineTester.cc:437
Socket.hh
MachineTester::sameDirOutputSocketConn_
TTAMachine::Port * sameDirOutputSocketConn_
If the reason for failure when tried to set socket direction to output was that the socket is connect...
Definition: MachineTester.hh:130
MachineTester::wrongSocketDirection
bool wrongSocketDirection() const
Definition: MachineTester.cc:397
MachineTester::sameDirInputSocketConn_
TTAMachine::Port * sameDirInputSocketConn_
If the reason for failure when tried to set socket direction to input was that the socket is connecte...
Definition: MachineTester.hh:126
MachineTester::branchedBus
TTAMachine::Bus * branchedBus() const
Definition: MachineTester.cc:380
MachineTester::loop
bool loop() const
Definition: MachineTester.cc:367
TTAMachine::Port::socketCount
virtual int socketCount() const
Definition: Port.cc:375
Unit.hh
assert
#define assert(condition)
Definition: Application.hh:86
Port.hh
Segment.hh
TTAMachine::Unit
Definition: Unit.hh:51
TTAMachine::Segment::parentBus
Bus * parentBus() const
TTAMachine::Port
Definition: Port.hh:54
Application.hh
MachineTester::registerFilePortAlreadyConnected
bool registerFilePortAlreadyConnected() const
Definition: MachineTester.cc:488
MachineTester::sameDirSocketConnection
TTAMachine::Port * sameDirSocketConnection(TTAMachine::Socket::Direction direction) const
Definition: MachineTester.cc:451
TTAMachine::Socket
Definition: Socket.hh:53
MachineTester::~MachineTester
virtual ~MachineTester()
Definition: MachineTester.cc:67
MachineTester::isValidComponentName
static bool isValidComponentName(const std::string &name)
Definition: MachineTester.cc:312
Bus.hh
TTAMachine::Socket::isConnectedTo
bool isConnectedTo(const Bus &bus) const
Definition: Socket.cc:331
MachineTester::wrongSocketDirection_
bool wrongSocketDirection_
Indicates if the reason for failure when trying to connect a socket to a port was that the direction ...
Definition: MachineTester.hh:113
TTAMachine::Unit::portCount
virtual int portCount() const
Definition: Unit.cc:135
MachineTester::legalPortConnections
bool legalPortConnections(const TTAMachine::Socket &socket, TTAMachine::Socket::Direction direction)
Definition: MachineTester.cc:556
MachineTester::areInSameChain
static bool areInSameChain(const TTAMachine::Bus &bus1, const TTAMachine::Bus &bus2)
Definition: MachineTester.cc:521
MachineTester.hh
MachineTester::connectionExists
bool connectionExists() const
Definition: MachineTester.cc:342
MachineTester::clearState
void clearState()
Definition: MachineTester.cc:497
TTAMachine::BaseRegisterFile::port
virtual RFPort * port(const std::string &name) const
Definition: BaseRegisterFile.cc:129
TTAMachine::Bus::hasNextBus
virtual bool hasNextBus() const
Definition: Bus.cc:488
MachineTester::forbiddenInputSocketDir_
TTAMachine::Port * forbiddenInputSocketDir_
If the reason for failure when tried to set socket direction to input was the socket is connected to ...
Definition: MachineTester.hh:134
MachineTester::loop_
bool loop_
Indicates if the reason for failure when trying to bridge two busses is that a loop in the bus chain ...
Definition: MachineTester.hh:106
MachineTester::forbiddenSocketDirection
TTAMachine::Port * forbiddenSocketDirection(TTAMachine::Socket::Direction direction) const
Definition: MachineTester.cc:471
TTAMachine::Bus::previousBus
virtual Bus * previousBus() const
Definition: Bus.cc:518
TTAMachine::Component::machine
virtual Machine * machine() const
MachineTester::canSetDirection
virtual bool canSetDirection(const TTAMachine::Socket &socket, TTAMachine::Socket::Direction direction)
Definition: MachineTester.cc:283
AssocTools.hh
MachineTester::unknownDir_
bool unknownDir_
Indicates if tried to set the socket direction to Socket::UNKNOWN.
Definition: MachineTester.hh:119
ControlUnit.hh
UNKNOWN
@ UNKNOWN
Definition: MemoryGenerator.hh:58
TTAMachine::Port::outputSocket
virtual Socket * outputSocket() const
Definition: Port.cc:281
MachineTester::rfPortAlreadyConnected_
bool rfPortAlreadyConnected_
Indicates if the reason for failure is that a port of register file is already connected to a particu...
Definition: MachineTester.hh:100
TTAMachine::RegisterFile
Definition: RegisterFile.hh:47
TTAMachine::Port::isConnectedTo
virtual bool isConnectedTo(const Socket &socket) const
Definition: Port.cc:393
TTAMachine::Socket::segmentCount
int segmentCount() const
MachineTester::maxConnections
bool maxConnections() const
Definition: MachineTester.cc:410
TTAMachine
Definition: Assembler.hh:48
TTAMachine::Bus::nextBus
virtual Bus * nextBus() const
Definition: Bus.cc:501
MachineTester::illegalRegistration_
bool illegalRegistration_
Indicates if the reason for last test failure was illegal registration.
Definition: MachineTester.hh:103
MachineTester::maxConnections_
bool maxConnections_
Indicates if the reason for failure when trying to connect a socket to a port was that this connectio...
Definition: MachineTester.hh:117
TTAMachine::Machine
Definition: Machine.hh:73
MachineTester::connectionExists_
bool connectionExists_
Indicates if the reason for the last test failure is that the tested connection already exists.
Definition: MachineTester.hh:97
ContainerTools.hh
TTAMachine::Port::parentUnit
Unit * parentUnit() const
TTAMachine::ImmediateUnit
Definition: ImmediateUnit.hh:50