OpenASIP 2.2
Loading...
Searching...
No Matches
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"
42#include "Application.hh"
43#include "ObjectState.hh"
44
45using std::string;
46using boost::format;
47
48namespace TTAMachine {
49
50// initialization of static data members
51const string Port::OSNAME_PORT = "port";
52const string Port::OSKEY_NAME = "name";
53const string Port::OSKEY_FIRST_SOCKET = "1_socket";
54const 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 */
67Port::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 */
93Port::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 */
140std::string
141Port::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 */
154void
155Port::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 */
190void
193 string procName = "Port::attachSocket";
194
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);
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 */
236void
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 */
260Socket*
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 */
280Socket*
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 */
297bool
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 */
307bool
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 */
322Socket*
323Port::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 */
374int
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 */
392bool
393Port::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
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 */
433void
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 */
458void
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 */
515void
516Port::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 */
535void
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
548bool
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
#define assert(condition)
static void abortProgram() __attribute__((noreturn))
static void writeToErrorLog(const std::string fileName, const int lineNumber, const std::string functionName, const std::string message, const int neededVerbosity=0)
std::string errorMessage() const
Definition Exception.cc:123
static std::string socketPortConnectionError(const TTAMachine::Socket &socket, const TTAMachine::Port &port, const MachineTester &tester)
virtual bool canConnect(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment)
static bool isValidComponentName(const std::string &name)
bool connectionExists() const
bool hasAttribute(const std::string &name) const
void setAttribute(const std::string &name, const std::string &value)
std::string stringAttribute(const std::string &name) const
virtual Machine * machine() const
virtual void ensureRegistration(const Component &component) const
virtual TCEString name() const
ComponentType * item(int index) const
virtual SocketNavigator socketNavigator() const
Definition Machine.cc:368
MachineTester & machineTester() const
Definition Machine.cc:671
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
std::string name_
Name of the port.
Definition Port.hh:107
virtual bool isInput() const
Definition Port.cc:298
Port(const std::string &name, Unit &parentUnit)
Definition Port.cc:67
void loadStateWithoutReferences(const ObjectState *state)
Definition Port.cc:434
Socket * socket1_
Connection to the first socket.
Definition Port.hh:111
static const std::string OSNAME_PORT
ObjectState name for Port.
Definition Port.hh:80
virtual void detachSocket(Socket &socket)
Definition Port.cc:237
static const std::string OSKEY_FIRST_SOCKET
ObjectState attribute key for the name of the connected socket.
Definition Port.hh:84
virtual Socket * unconnectedSocket(int index) const
Definition Port.cc:323
virtual bool isOutput() const
Definition Port.cc:308
static const std::string OSKEY_SECOND_SOCKET
ObjectState attribute key for the name of the other connected socket.
Definition Port.hh:86
virtual void detachAllSockets()
Definition Port.cc:536
virtual bool isConnectedTo(const Socket &socket) const
Definition Port.cc:393
Socket * socket2_
Connection to the second socket.
Definition Port.hh:113
Unit * parentUnit() const
virtual Socket * inputSocket() const
Definition Port.cc:261
virtual ObjectState * saveState() const
Definition Port.cc:404
virtual void loadState(const ObjectState *state)
Definition Port.cc:459
virtual ~Port()
Definition Port.cc:117
virtual std::string name() const
Definition Port.cc:141
Unit * parentUnit_
Parent unit.
Definition Port.hh:109
static const std::string OSKEY_NAME
ObjectState attribute key for the name of the port.
Definition Port.hh:82
virtual void setName(const std::string &name)
Definition Port.cc:155
@ 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
Direction direction() const
void detachPort(const Port &port)
Definition Socket.cc:631
int segmentCount() const
void attachPort(Port &port)
Definition Socket.cc:618
void addPort(Port &port)
Definition Unit.cc:213
virtual int portCount() const
Definition Unit.cc:135
virtual Port * port(const std::string &name) const
Definition Unit.cc:116
virtual void removePort(Port &port)
Definition Unit.cc:235
virtual boost::format text(int textId)
bool operator()(const std::pair< const Port *, const Port * > &pp1, const std::pair< const Port *, const Port * > &pp2) const
Definition Port.cc:549