OpenASIP  2.0
Port.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 Port.cc
26  *
27  * Implementation of Port class.
28  *
29  * @author Lasse Laasonen 2003 (lasse.laasonen-no.spam-tut.fi)
30  * @note reviewed 17 Jun 2004 by jn, pj, jm, ll
31  * @note rating: red
32  */
33 
34 #include "Port.hh"
35 #include "Unit.hh"
36 #include "Socket.hh"
37 #include "ImmediateUnit.hh"
38 #include "ControlUnit.hh"
39 #include "MachineTester.hh"
40 #include "MOMTextGenerator.hh"
41 #include "MachineTestReporter.hh"
42 #include "Application.hh"
43 #include "ObjectState.hh"
44 
45 using std::string;
46 using boost::format;
47 
48 namespace TTAMachine {
49 
50 // initialization of static data members
51 const string Port::OSNAME_PORT = "port";
52 const string Port::OSKEY_NAME = "name";
53 const string Port::OSKEY_FIRST_SOCKET = "1_socket";
54 const string Port::OSKEY_SECOND_SOCKET = "2_socket";
55 
56 
57 /**
58  * Constructor.
59  *
60  * @param name Name of the port.
61  * @param parentUnit Unit to which the port is connected.
62  * @exception ComponentAlreadyExists If the parent unit already has another
63  * port by the same name.
64  * @exception InvalidName If the given name is not a valid name for a
65  * component.
66  */
67 Port::Port(const std::string& name, Unit& parentUnit)
68  : SubComponent(),
69  name_(name),
70  parentUnit_(NULL),
71  socket1_(NULL),
72  socket2_(NULL) {
74  const string procName = "Port::Port";
75  throw InvalidName(__FILE__, __LINE__, procName);
76  }
77 
78  parentUnit.addPort(*this);
80 }
81 
82 /**
83  * Constructor.
84  *
85  * Loads its state from the given ObjectState instance but does not create
86  * connections to sockets.
87  *
88  * @param state The ObjectState instance.
89  * @param parentUnit The unit which contains the port.
90  * @exception ObjectStateLoadingException If the given ObjectState instance
91  * is invalid.
92  */
93 Port::Port(const ObjectState* state, Unit& parentUnit)
94  : SubComponent(),
95  name_(""),
96  parentUnit_(NULL),
97  socket1_(NULL),
98  socket2_(NULL) {
100  try {
101  parentUnit.addPort(*this);
102  } catch (const ComponentAlreadyExists&) {
103  const string procName = "Port::Port";
104  MOMTextGenerator textGenerator;
105  format errorMsg = textGenerator.text(
107  errorMsg % name() % parentUnit.name();
109  __FILE__, __LINE__, procName, errorMsg.str());
110  }
112 }
113 
114 /**
115  * Destructor.
116  */
118 
119  Unit* parent = parentUnit_;
120 
121  parentUnit_ = NULL;
122  assert(parent != NULL);
123  parent->removePort(*this);
124 
125  if (socket1_ != NULL) {
127  }
128 
129  if (socket2_ != NULL) {
131  }
132 }
133 
134 
135 /**
136  * Returns the name of the port.
137  *
138  * @return Name of the port.
139  */
140 std::string
141 Port::name() const {
142  return name_;
143 }
144 
145 
146 /**
147  * Sets the name of the port.
148  *
149  * @param name The new name.
150  * @exception ComponentAlreadyExists If a port with the given name already
151  * exists in the same unit.
152  * @exception InvalidName If the given name is not a valid component name.
153  */
154 void
155 Port::setName(const std::string& name) {
156  if (name == this->name()) {
157  return;
158  }
159 
160  const string procName = "Port::setName";
161 
163  throw InvalidName(__FILE__, __LINE__, procName);
164  }
165 
166  Unit* parent = this->parentUnit();
167  for (int i = 0; i < parent->portCount(); i++) {
168  Port* port = parent->port(i);
169  if (port->name() == name) {
170  throw ComponentAlreadyExists(__FILE__, __LINE__, procName);
171  }
172  }
173 
174  name_ = name;
175 }
176 
177 /**
178  * Attaches a socket to this port.
179  *
180  * NOTE! If the parent unit is a register file, attaching a socket may affect
181  * to the maximum simultaneous reads of the register file.
182  *
183  * @param socket Socket to be attached.
184  * @exception IllegalRegistration If the port and socket are not in the same
185  * machine.
186  * @exception ComponentAlreadyExists If the given socket is already attached.
187  * @exception IllegalConnectivity If the socket cannot be attached because
188  * of connectivity reasons.
189  */
190 void
192  parentUnit()->ensureRegistration(socket);
193  string procName = "Port::attachSocket";
194 
195  MachineTester& tester = parentUnit()->machine()->machineTester();
196  if (!tester.canConnect(socket, *this)) {
197  if (tester.connectionExists()) {
198  throw ComponentAlreadyExists(__FILE__, __LINE__, procName);
199  } else {
200  string errorMsg = MachineTestReporter::
201  socketPortConnectionError(socket, *this, tester);
202  throw IllegalConnectivity(
203  __FILE__, __LINE__, procName, errorMsg);
204  }
205  }
206 
207  if (socket1_ == NULL) {
208  socket1_ = &socket;
209  } else if (socket2_ == NULL) {
210  socket2_ = &socket;
211  } else {
212  assert(false);
213  }
214 
215  // bookeeping of Socket internal state - private Socket operation
216  // reserved solely to Port class!
217  socket.attachPort(*this);
218 
219  // sanity check
220  if (socket2_ != NULL) {
223  }
224 }
225 
226 /**
227  * Detaches a socket from this port.
228  *
229  * NOTE! If the parent unit is a register file, detaching a socket may affect
230  * to the maximum simultaneous reads of the register file.
231  *
232  * @param socket Socket to be detached.
233  * @exception InstanceNotFound If the given socket is not connected to the
234  * port.
235  */
236 void
238  if (socket1_ == &socket) {
239  socket1_ = NULL;
240  } else if (socket2_ == &socket) {
241  socket2_ = NULL;
242  } else {
243  string procName = "Port::detachSocket";
244  throw InstanceNotFound(__FILE__, __LINE__, procName);
245  }
246 
247  // bookeeping of Socket internal state - private Socket operation
248  // reserved solely to Port class!
249  socket.detachPort(*this);
250 }
251 
252 /**
253  * Returns the input socket of the port.
254  *
255  * If the port does not have input socket (socket whose direction is
256  * Socket::INPUT), returns NULL.
257  *
258  * @return Input socket of the port.
259  */
260 Socket*
262  if (socket1_ != NULL && socket1_->direction() == Socket::INPUT) {
263  return socket1_;
264  } else if (socket2_ != NULL && socket2_->direction() == Socket::INPUT) {
265  return socket2_;
266  } else {
267  return NULL;
268  }
269 }
270 
271 
272 /**
273  * Returns the output socket of the port.
274  *
275  * If the port does not have output socket (socket whose direction is
276  * Socket::OUTPUT), returns NULL.
277  *
278  * @return Output socket of the port.
279  */
280 Socket*
282  if (socket1_ != NULL && socket1_->direction() == Socket::OUTPUT) {
283  return socket1_;
284  } else if (socket2_ != NULL &&
286  return socket2_;
287  } else {
288  return NULL;
289  }
290 }
291 
292 /**
293  * Returns true if this port can be used to read data from bus to the unit.
294  *
295  * @return True if input port.
296  */
297 bool
298 Port::isInput() const {
299  return inputSocket() != NULL;
300 }
301 
302 /**
303  * Returns true if this port can be used to write data from unit to bus.
304  *
305  * @return True if output port.
306  */
307 bool
308 Port::isOutput() const {
309  return outputSocket() != NULL;
310 }
311 
312 /**
313  * Returns the first or the second unconnected socket attached to this port.
314  * If there is no such socket, returns NULL.
315  *
316  * @param index The index which indicates which of the unconnected sockets is
317  * returned. If there is only one unconnected socket, the index
318  * value 0 returns it and value 1 returns NULL.
319  * @return The unconnected socket by the given index.
320  * @exception OutOfRange If the given index is not 0 or 1.
321  */
322 Socket*
323 Port::unconnectedSocket(int index) const {
324  const string procName = "Port::unconnectedSocket";
325 
326  if (index < 0 || index > 1) {
327  throw OutOfRange(__FILE__, __LINE__, procName);
328  }
329 
330  if (socketCount() == 0) {
331  return NULL;
332  } else if (socketCount() == 1) {
333  if (index == 1) {
334  return NULL;
335  } else if (socket1_ != NULL && socket1_->segmentCount() == 0) {
336  return socket1_;
337  } else if (socket2_ != NULL && socket2_->segmentCount() == 0) {
338  return socket2_;
339  } else {
340  return NULL;
341  }
342  } else if (socketCount() == 2) {
343  if (index == 0) {
344  if (socket1_->segmentCount() == 0) {
345  return socket1_;
346  } else if (socket2_->segmentCount() == 0) {
347  return socket2_;
348  } else {
349  return NULL;
350  }
351  } else {
352  if (socket2_->segmentCount() == 0) {
353  return socket2_;
354  } else {
355  return NULL;
356  }
357  }
358  } else {
359  string errorMsg = "Too many sockets attached to a port.";
360  Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
362 
363  // this return statement is just to avoid compilation warning in some
364  // environments.
365  return NULL;
366  }
367 }
368 
369 /**
370  * Returns the number of sockets attached to the port.
371  *
372  * @return The number of sockets.
373  */
374 int
376  if (socket1_ != NULL && socket2_ != NULL) {
377  return 2;
378  } else if (socket1_ != NULL || socket2_ != NULL) {
379  return 1;
380  } else {
381  return 0;
382  }
383 }
384 
385 
386 /**
387  * Checks whether the port is connected to the given socket.
388  *
389  * @param socket The socket.
390  * @return True if the port is connected to the socket, otherwise false.
391  */
392 bool
393 Port::isConnectedTo(const Socket& socket) const {
394  return (socket1_ == &socket || socket2_ == &socket);
395 }
396 
397 
398 /**
399  * Saves the contents to an ObjectState tree.
400  *
401  * @return The newly created ObjectState tree.
402  */
405 
406  ObjectState* port = new ObjectState(OSNAME_PORT);
407  port->setAttribute(OSKEY_NAME, name());
408 
409  // set first socket
410  if (socket1_ != NULL) {
412  } else if (socket2_ != NULL) {
414  }
415 
416  // set second socket
417  if (socket1_ != NULL && socket2_ != NULL) {
419  }
420 
421  return port;
422 }
423 
424 
425 /**
426  * Loads its state from the given ObjectState instance but does not create
427  * connections to sockets.
428  *
429  * @param state The ObjectState instance.
430  * @exception ObjectStateLoadingException If the given ObjectState instance
431  * is invalid.
432  */
433 void
435  const string procName = "Port::loadStateWithoutReferences";
436 
437  try {
438  string name = state->stringAttribute(OSKEY_NAME);
440  throw InvalidName(__FILE__, __LINE__, procName);
441  }
442  name_ = name;
443  } catch (const Exception& exception) {
445  __FILE__, __LINE__, procName, exception.errorMessage());
446  }
447 }
448 
449 /**
450  * Loads its state from the given ObjectState instance.
451  *
452  * @param state The ObjectState instance.
453  * @exception ObjectStateLoadingException If the parent unit has a port by
454  * the same name as the coming name of
455  * this unit or if loading the
456  * references to sockets fails.
457  */
458 void
460  const string procName = "Port::loadState";
463  string socketName = "";
464  MOMTextGenerator textGenerator;
465 
466  try {
467  if (state->hasAttribute(OSKEY_FIRST_SOCKET)) {
468  socketName = state->stringAttribute(OSKEY_FIRST_SOCKET);
469  attachSocket(socketName);
470  }
471  if (state->hasAttribute(OSKEY_SECOND_SOCKET)) {
472  socketName = state->stringAttribute(OSKEY_SECOND_SOCKET);
473  attachSocket(socketName);
474  }
475  } catch (const InstanceNotFound&) {
476  format errorMsg = textGenerator.text(
478  errorMsg % socketName % name() % parentUnit()->name();
480  __FILE__, __LINE__, procName, errorMsg.str());
481  } catch (const IllegalRegistration&) {
482  format errorMsg = textGenerator.text(
484  errorMsg % socketName % name() % parentUnit()->name();
486  __FILE__, __LINE__, procName, errorMsg.str());
487  } catch (const ComponentAlreadyExists&) {
488  format errorMsg = textGenerator.text(
490  errorMsg % name() % parentUnit()->name();
492  __FILE__, __LINE__, procName, errorMsg.str());
493  } catch (const IllegalConnectivity& exception) {
495  __FILE__, __LINE__, procName, exception.errorMessage());
496  }
497 }
498 
499 /**
500  * Attaches the socket by the given name to the port.
501  *
502  * The given socket must be registered to the same machine as the parent
503  * unit.
504  *
505  * @param socketName Name of the socket to be attached.
506  * @exception InstanceNotFound If the given socket is not found from the
507  * machine.
508  * @exception IllegalRegistration If the parent unit is not registered to a
509  * machine.
510  * @exception ComponentAlreadyExists If a socket by the given name is already
511  * attached.
512  * @exception IllegalConnectivity If the socket cannot be attached because
513  * of connectivity reasons.
514  */
515 void
516 Port::attachSocket(const std::string& socketName) {
517  const string procName = "Socket::attachSocket";
518 
519  Machine* mach = parentUnit()->machine();
520  if (mach == NULL) {
521  throw IllegalRegistration(__FILE__, __LINE__, procName);
522  }
523 
524  Machine::SocketNavigator socketNav = mach->socketNavigator();
525  Socket* socket = socketNav.item(socketName);
526  attachSocket(*socket);
527 }
528 
529 /**
530  * Detaches all the sockets connected to the port.
531  *
532  * NOTE! If the parent unit is a register file, detaching sockets may affect
533  * to the maximum simultaneous reads of the register file.
534  */
535 void
537  if (socket1_ != NULL) {
538  socket1_->detachPort(*this);
539  socket1_ = NULL;
540  }
541  if (socket2_ != NULL) {
542  socket2_->detachPort(*this);
543  socket2_ = NULL;
544  }
545 }
546 
547 
548 bool
550  const std::pair<const Port*, const Port*>& pp1,
551  const std::pair<const Port*, const Port*>& pp2)
552  const {
553  if (Comparator()(pp1.first, pp2.first)) {
554  return false;
555  }
556  if (Comparator()(pp2.first, pp1.first)) {
557  return true;
558  }
559  if (Comparator()(pp1.second, pp2.second)) {
560  return true;
561  }
562  return false;
563 }
564 
565 }
566 
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
ObjectState::hasAttribute
bool hasAttribute(const std::string &name) const
Definition: ObjectState.cc:205
TTAMachine::Port::Port
Port(const std::string &name, Unit &parentUnit)
Definition: Port.cc:67
TTAMachine::Port::inputSocket
virtual Socket * inputSocket() const
Definition: Port.cc:261
TTAMachine::SubComponent
Definition: MachinePart.hh:168
TTAMachine::Socket::attachPort
void attachPort(Port &port)
Definition: Socket.cc:618
TTAMachine::Unit::addPort
void addPort(Port &port)
Definition: Unit.cc:213
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
ObjectState::stringAttribute
std::string stringAttribute(const std::string &name) const
Definition: ObjectState.cc:249
TTAMachine::Port::saveState
virtual ObjectState * saveState() const
Definition: Port.cc:404
TTAMachine::Socket::OUTPUT
@ OUTPUT
Data goes from port to bus.
Definition: Socket.hh:60
TTAMachine::Port::PairComparator::operator()
bool operator()(const std::pair< const Port *, const Port * > &pp1, const std::pair< const Port *, const Port * > &pp2) const
Definition: Port.cc:549
ObjectStateLoadingException
Definition: Exception.hh:551
TTAMachine::Unit::removePort
virtual void removePort(Port &port)
Definition: Unit.cc:235
TTAMachine::Component::ensureRegistration
virtual void ensureRegistration(const Component &component) const
Definition: MachinePart.cc:163
Application::writeToErrorLog
static void writeToErrorLog(const std::string fileName, const int lineNumber, const std::string functionName, const std::string message, const int neededVerbosity=0)
Definition: Application.cc:224
OutOfRange
Definition: Exception.hh:320
ObjectState
Definition: ObjectState.hh:59
ImmediateUnit.hh
TTAMachine::Port::OSKEY_SECOND_SOCKET
static const std::string OSKEY_SECOND_SOCKET
ObjectState attribute key for the name of the other connected socket.
Definition: Port.hh:86
MachineTestReporter.hh
Texts::TextGenerator::text
virtual boost::format text(int textId)
Definition: TextGenerator.cc:94
TTAMachine::Socket::direction
Direction direction() const
Socket.hh
TTAMachine::Port::OSNAME_PORT
static const std::string OSNAME_PORT
ObjectState name for Port.
Definition: Port.hh:80
MachineTestReporter::socketPortConnectionError
static std::string socketPortConnectionError(const TTAMachine::Socket &socket, const TTAMachine::Port &port, const MachineTester &tester)
Definition: MachineTestReporter.cc:150
TTAMachine::Port::socketCount
virtual int socketCount() const
Definition: Port.cc:375
Unit.hh
TTAMachine::Port::name_
std::string name_
Name of the port.
Definition: Port.hh:107
TTAMachine::Port::setName
virtual void setName(const std::string &name)
Definition: Port.cc:155
TTAMachine::Port::loadState
virtual void loadState(const ObjectState *state)
Definition: Port.cc:459
assert
#define assert(condition)
Definition: Application.hh:86
TTAMachine::Port::~Port
virtual ~Port()
Definition: Port.cc:117
TTAMachine::Port::attachSocket
virtual void attachSocket(Socket &socket)
Definition: Port.cc:191
Port.hh
TTAMachine::Socket::detachPort
void detachPort(const Port &port)
Definition: Socket.cc:631
TTAMachine::Unit
Definition: Unit.hh:51
InvalidName
Definition: Exception.hh:827
TTAMachine::Machine::machineTester
MachineTester & machineTester() const
Definition: Machine.cc:671
TTAMachine::Port
Definition: Port.hh:54
Application.hh
TTAMachine::Unit::port
virtual Port * port(const std::string &name) const
Definition: Unit.cc:116
ObjectState.hh
TTAMachine::Socket
Definition: Socket.hh:53
TTAMachine::Port::detachSocket
virtual void detachSocket(Socket &socket)
Definition: Port.cc:237
TTAMachine::Port::parentUnit_
Unit * parentUnit_
Parent unit.
Definition: Port.hh:109
Exception
Definition: Exception.hh:54
MachineTester::isValidComponentName
static bool isValidComponentName(const std::string &name)
Definition: MachineTester.cc:312
TTAMachine::Machine::socketNavigator
virtual SocketNavigator socketNavigator() const
Definition: Machine.cc:368
TTAMachine::Port::isOutput
virtual bool isOutput() const
Definition: Port.cc:308
TTAMachine::Unit::portCount
virtual int portCount() const
Definition: Unit.cc:135
Exception::errorMessage
std::string errorMessage() const
Definition: Exception.cc:123
IllegalRegistration
Definition: Exception.hh:532
MachineTester.hh
MachineTester::connectionExists
bool connectionExists() const
Definition: MachineTester.cc:342
TTAMachine::Port::socket2_
Socket * socket2_
Connection to the second socket.
Definition: Port.hh:113
TTAMachine::Port::socket1_
Socket * socket1_
Connection to the first socket.
Definition: Port.hh:111
TTAMachine::Component::machine
virtual Machine * machine() const
TTAMachine::Port::name
virtual std::string name() const
Definition: Port.cc:141
MOMTextGenerator
Definition: MOMTextGenerator.hh:40
ControlUnit.hh
TTAMachine::Port::OSKEY_NAME
static const std::string OSKEY_NAME
ObjectState attribute key for the name of the port.
Definition: Port.hh:82
TTAMachine::Port::loadStateWithoutReferences
void loadStateWithoutReferences(const ObjectState *state)
Definition: Port.cc:434
TTAMachine::Socket::UNKNOWN
@ UNKNOWN
Unknown direction.
Definition: Socket.hh:61
TTAMachine::Port::outputSocket
virtual Socket * outputSocket() const
Definition: Port.cc:281
ComponentAlreadyExists
Definition: Exception.hh:510
TTAMachine::Port::isInput
virtual bool isInput() const
Definition: Port.cc:298
MOMTextGenerator.hh
MOMTextGenerator::TXT_PORT_REF_LOAD_ERR_SOCKET
@ TXT_PORT_REF_LOAD_ERR_SOCKET
Definition: MOMTextGenerator.hh:74
TTAMachine::Machine::Navigator::item
ComponentType * item(int index) const
IllegalConnectivity
Definition: Exception.hh:473
TTAMachine::Port::isConnectedTo
virtual bool isConnectedTo(const Socket &socket) const
Definition: Port.cc:393
TTAMachine::Socket::segmentCount
int segmentCount() const
TTAMachine
Definition: Assembler.hh:48
Application::abortProgram
static void abortProgram() __attribute__((noreturn))
Definition: Application.cc:266
TTAMachine::MachinePart::Comparator
Definition: MachinePart.hh:59
MachineTester
Definition: MachineTester.hh:46
TTAMachine::Port::detachAllSockets
virtual void detachAllSockets()
Definition: Port.cc:536
TTAMachine::Machine::Navigator
Definition: Machine.hh:186
MOMTextGenerator::TXT_PORT_EXISTS_BY_NAME
@ TXT_PORT_EXISTS_BY_NAME
Definition: MOMTextGenerator.hh:73
ObjectState::setAttribute
void setAttribute(const std::string &name, const std::string &value)
Definition: ObjectState.cc:100
InstanceNotFound
Definition: Exception.hh:304
TTAMachine::Machine
Definition: Machine.hh:73
TTAMachine::Socket::INPUT
@ INPUT
Data goes from bus to port.
Definition: Socket.hh:59
TTAMachine::Port::OSKEY_FIRST_SOCKET
static const std::string OSKEY_FIRST_SOCKET
ObjectState attribute key for the name of the connected socket.
Definition: Port.hh:84
TTAMachine::Port::parentUnit
Unit * parentUnit() const