OpenASIP 2.2
Loading...
Searching...
No Matches
Socket.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 Socket.cc
26 *
27 * Implementation of Socket class.
28 *
29 * @author Lasse Laasonen 2003 (lasse.laasonen-no.spam-tut.fi)
30 * @note rating: red
31 * @note reviewed 22 Jun 2004 by ao, ml, vpj, ll
32 */
33
34#include <set>
35
36#include "Socket.hh"
37#include "Machine.hh"
38#include "Bus.hh"
39#include "Segment.hh"
40#include "Port.hh"
41#include "Connection.hh"
42#include "MachineTester.hh"
43#include "MOMTextGenerator.hh"
45#include "Application.hh"
46#include "ContainerTools.hh"
47#include "AssocTools.hh"
48#include "ObjectState.hh"
49
50using std::string;
51using std::set;
52using boost::format;
53
54namespace TTAMachine {
55
56// initialization of static data members
57const string Socket::OSNAME_SOCKET = "socket";
58const string Socket::OSKEY_DIRECTION = "direction";
59const string Socket::OSVALUE_INPUT = "input";
60const string Socket::OSVALUE_OUTPUT = "output";
61const string Socket::OSVALUE_UNKNOWN = "unknown";
62
63/**
64 * Constructor.
65 *
66 * @param name Name of the socket.
67 * @exception InvalidName If the given name is not valid for a component.
68 */
69Socket::Socket(const std::string& name)
70 : Component(name), direction_(UNKNOWN), dataPortWidth_() {}
71
72/**
73 * Constructor.
74 *
75 * Loads the state of the socket from the given ObjectState instance but
76 * does not create connections to other components.
77 *
78 * @param state The ObjectState instance.
79 * @exception ObjectStateLoadingException If the given ObjectState instance
80 * is invalid.
81 */
83 : Component(state), direction_(UNKNOWN), dataPortWidth_() {}
84
85/**
86 * Destructor.
87 */
92
93
94/**
95 * Sets the name of the socket.
96 *
97 * @param name New name of the socket.
98 * @exception ComponentAlreadyExists If a socket with the given name is
99 * already in the same machine.
100 * @exception InvalidName If the given name is not valid for a component.
101 */
102void
103Socket::setName(const std::string& name) {
104 if (name == this->name()) {
105 return;
106 }
107
108 if (machine() != NULL) {
109 if (machine()->socketNavigator().hasItem(name)) {
110 string procName = "Socket::setName";
111 throw ComponentAlreadyExists(__FILE__, __LINE__, procName);
112 } else {
114 }
115 } else {
117 }
118}
119
120/**
121 * Sets the direction of the socket.
122 *
123 * The given direction must be either Socket::INPUT or Socket::OUTPUT.
124 *
125 * @param direction The new direction.
126 * @exception IllegalConnectivity If the direction of the port cannot be
127 * changed.
128 */
129void
131 const string procName = "Socket::setDirection";
132
133 if (!isRegistered()) {
134 MOMTextGenerator textGenerator;
135 format text = textGenerator.text(
137 text % name();
138 throw IllegalConnectivity(__FILE__, __LINE__, procName, text.str());
139 }
140
141 MachineTester& tester = machine()->machineTester();
142 if (tester.canSetDirection(*this, direction)) {
144 } else {
146 *this, direction, tester);
147 throw IllegalConnectivity(__FILE__, __LINE__, procName, errorMsg);
148 }
149}
150
151/**
152 * Attaches a bus to the socket.
153 *
154 * If no bus is currently attached, the direction of the socket is set to
155 * Socket::INPUT or Socket::OUTPUT. When possible, the direction is set to
156 * Socket::INPUT. Otherwise, it is set to Socket::OUTPUT.
157 *
158 * @param bus The segment of a bus being attached.
159 * @exception IllegalRegistration If the bus is not registered to the same
160 * machine as the socket.
161 * @exception IllegalConnectivity If the socket is attached to ports in such
162 * a way that its direction cannot be either
163 * input or output.
164 */
165void
167 const string procName = "Socket::attachBus";
168
170 MachineTester& tester = machine()->machineTester();
171 if (!tester.canConnect(*this, bus)) {
173 *this, bus, tester);
174 throw IllegalConnectivity(__FILE__, __LINE__, procName, errorMsg);
175 }
176
177 if (!bus.isConnectedTo(*this)) {
178 const Connection* conn = new Connection(*this, bus);
179 busses_.push_back(conn);
180 bus.attachSocket(*this);
181 } else {
182 assert(false);
183 }
184
185 // set the direction
186 if (direction_ == UNKNOWN) {
187 if (tester.canSetDirection(*this, INPUT)) {
189 } else if (tester.canSetDirection(*this, OUTPUT)) {
191 } else {
192 string errorMsg = "Direction of the socket cannot be set.";
194 __FILE__, __LINE__, procName, errorMsg);
196 }
197 }
198}
199
200/**
201 * Detaches the given segment of a bus from the socket.
202 *
203 * If there are no buses connected to the socket after detaching the given
204 * segment, the direction of the socket is set to Socket::UNKNOWN. Note that
205 * detaching a segment may affect to the value of maximum simultaneous
206 * register reads of register files connected to the socket.
207 *
208 * @param bus The segment to be detached.
209 * @exception InstanceNotFound If the given segment is not attached to the
210 * socket.
211 */
212void
214 if (!isConnectedTo(bus)) {
215 string procName = "Socket::detachBus";
216 throw InstanceNotFound(__FILE__, __LINE__, procName);
217 }
218
219 const Connection& conn = connection(bus);
220 removeConnection(&conn);
221
222 if (bus.isConnectedTo(*this)) {
223 bus.detachSocket(*this);
224 delete &conn;
225 }
226
227 // set socket direction to unknown if it has no connections to buses
228 if (segmentCount() == 0) {
230 }
231}
232
233/**
234 * Detaches all the segments of the given bus from the socket.
235 *
236 * If there are no buses connected to the socket after detaching the given
237 * bus, the direction of the socket is set to Socket::UNKNOWN. Note that
238 * detaching the bus may affect to the value of maximum simultaneous
239 * register reads of register files connected to the socket.
240 *
241 * @param bus Bus to be detached.
242 */
243void
245 int segments = bus.segmentCount();
246 for (int i = 0; i < segments; i++) {
247 Segment* segment = bus.segment(i);
248 if (isConnectedTo(*segment)) {
250 }
251 }
252}
253
254
255/**
256 * Returns a port by the given index.
257 *
258 * The given index must be greater or equal to 0 and less than the number
259 * of ports attached to the socket.
260 *
261 * @param index Index.
262 * @return The port found by the given index.
263 * @exception OutOfRange If the given index is out of range.
264 */
265Port*
266Socket::port(int index) const {
267 if (index < 0 || index >= portCount()) {
268 string procName = "Socket::port";
269 throw OutOfRange(__FILE__, __LINE__, procName);
270 }
271 return ports_[index];
272}
273
274/**
275 * Detaches all ports from the socket.
276 */
277void
279 PortTable::iterator iter = ports_.begin();
280 while (iter != ports_.end()) {
281 // removes the socket from ports_
282 (*iter)->detachSocket(*this);
283 iter = ports_.begin();
284 }
285 ports_.clear();
286}
287
288
289
290
291/**
292 * Returns the Connection object which connects this socket and the given
293 * segment.
294 *
295 * This method is not intended for clients. Do not use this method. The
296 * connection must exist before calling this function.
297 *
298 * @param bus The segment of a bus which is attached to this socket.
299 * @return Connection object which joins the socket and the segment.
300 */
301const Connection&
302Socket::connection(const Segment& bus) const {
303
304 ConnectionTable::const_iterator iter = busses_.begin();
305 while (iter != busses_.end()) {
306 if ((*iter)->bus() == &bus) {
307 return **iter;
308 } else {
309 iter++;
310 }
311 }
312
313 string errorMsg = "The requested Connection object does not exist in "
314 "Socket.";
315 string procName = "Socket::connection";
316 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
318
319 // this return statement is only to avoid warning in Solaris environment
320 return **iter;
321}
322
323
324/**
325 * Checks whether the socket is connected to the given bus.
326 *
327 * @param bus A bus.
328 * @return True if connected, otherwise false.
329 */
330bool
331Socket::isConnectedTo(const Bus& bus) const {
332
333 int segments = bus.segmentCount();
334 for (int i = 0; i < segments; i++) {
335 if (isConnectedTo(*bus.segment(i))) {
336 return true;
337 }
338 }
339 return false;
340}
341
342
343/**
344 * Checks whether the socket is connected to the given segment.
345 *
346 * @param bus Segment of a bus.
347 * @return True if connected, otherwise false.
348 */
349bool
351
352 ConnectionTable::const_iterator iter = busses_.begin();
353 while (iter != busses_.end()) {
354 if ((*iter)->bus() == &bus) {
355 return true;
356 } else {
357 iter++;
358 }
359 }
360
361 return false;
362}
363
364/**
365 * Returns set of buses where the socket is connected to.
366 */
367std::set<Bus*>
369 set<Bus*> result;
370 for (const Connection* conn : busses_) {
371 result.insert(conn->bus()->parentBus());
372 }
373
374 return result;
375}
376
377/**
378 * Returns set of buses where the socket is connected to.
379 */
380const std::set<Bus*>
382 set<Bus*> result;
383 for (const Connection* conn : busses_) {
384 result.insert(conn->bus()->parentBus());
385 }
386
387 return result;
388}
389
390/**
391 * By the given index, returns the segment a socket is connected to.
392 *
393 * The given index must be greater or equal to 0 and smaller than the number
394 * of segments attached to the socket.
395 *
396 * @param index The index.
397 * @return Segment by the given index.
398 * @exception OutOfRange If the given index is out of range.
399 */
400Segment*
401Socket::segment(int index) const {
402 if (index < 0 || index >= segmentCount()) {
403 string procName = "Socket::segment";
404 throw OutOfRange(__FILE__, __LINE__, procName);
405 }
406 return busses_[index]->bus();
407}
408
409bool
411 return !dataPortWidth_.empty();
412}
413
414const std::string&
416 return dataPortWidth_;
417}
418
419void
420Socket::setDataPortWidth(const string& width) {
421 dataPortWidth_ = width;
422}
423
424/**
425 * Registers the socket to a machine.
426 *
427 * @param mach Machine to which the socket is to be registered.
428 * @exception ComponentAlreadyExists If there already is another socket by
429 * the same name in the machine.
430 */
431void
433 internalSetMachine(mach);
434 mach.addSocket(*this);
435}
436
437/**
438 * Removes the socket from the machine it is registered to.
439 *
440 * Detaches all the busses and ports attached to the socket.
441 */
442void
444
445 if (machine() == NULL) {
446 return;
447 }
448
449 Machine* mach = machine();
451
454
455 mach->removeSocket(*this);
456}
457
458
459/**
460 * Saves the contents of the socket to an ObjectState object.
461 *
462 * @return The newly created ObjectState object.
463 */
466
468 root->setName(OSNAME_SOCKET);
469
470 // set direction
471 if (direction_ == INPUT) {
473 } else if (direction_ == OUTPUT) {
475 } else {
477 }
478
479 // add connections
480 ConnectionTable::const_iterator iter = busses_.begin();
481 while (iter != busses_.end()) {
482 const Connection* conn = *iter;
483 ObjectState* bus = conn->saveState();
484 root->addChild(bus);
485 iter++;
486 }
487
488 return root;
489}
490
491
492/**
493 * Loads its state from the given ObjectState instance.
494 *
495 * @param state The ObjectState instance.
496 * @exception ObjectStateLoadingException If the machine already has a socket
497 * by the same name as the new
498 * name of this socket or if the
499 * given ObjectState tree is invalid.
500 */
501void
503 string procName = "Socket::loadState";
504 MOMTextGenerator textGenerator;
505
506 if (state->name() != OSNAME_SOCKET) {
507 throw ObjectStateLoadingException(__FILE__, __LINE__, procName);
508 }
509
511
512 // load connections to busses
514
515 try {
516
517 for (int childIndex = 0; childIndex < state->childCount();
518 childIndex++) {
519 ObjectState* child = state->child(childIndex);
520
521 if (child->name() == Connection::OSNAME_CONNECTION) {
522 string busName =
524 string segmentName =
526
527 if (!isRegistered()) {
528 format text = textGenerator.text(
530 text % name();
532 __FILE__, __LINE__, procName, text.str());
533 }
534
536 Bus* bus = NULL;
537 Segment* segment = NULL;
538
539 try {
540 bus = busNav.item(busName);
541 } catch (InstanceNotFound&) {
542 format text = textGenerator.text(
544 text % busName % name();
546 __FILE__, __LINE__, procName, text.str());
547 }
548
549 try {
550 segment = bus->segment(segmentName);
551 } catch (InstanceNotFound&) {
552 format text = textGenerator.text(
554 text % name() % segmentName % busName;
556 __FILE__, __LINE__, procName, text.str());
557 }
558
560
561 } else {
563 __FILE__, __LINE__, procName);
564 }
565 }
566
567 } catch (const Exception& exception) {
569 __FILE__, __LINE__, procName, exception.errorMessage());
570 }
571
572 // load direction
573 string direction("");
574 try {
576 if (direction == OSVALUE_INPUT) {
578 } else if (direction == OSVALUE_OUTPUT) {
580 } else if (direction == OSVALUE_UNKNOWN) {
581 if (segmentCount() > 0) {
582 format text = textGenerator.text(
584 TXT_UNKNOWN_SOCKET_DIR_AND_SEGMENT_CONN);
586 __FILE__, __LINE__, procName, text.str());
587 }
589 } else {
590 throw ObjectStateLoadingException(__FILE__, __LINE__, procName);
591 }
592
593 } catch (const Exception& exception) {
595 __FILE__, __LINE__, procName, exception.errorMessage());
596 }
597}
598
599/**
600 * Removes a connection from the connection table.
601 *
602 * @param connection The connection to be removed.
603 */
604void
608
609
610/**
611 * Notifies the socket that a port has been attached to it.
612 *
613 * Private helper method used only by friend class Port.
614 *
615 * @param port The port that has been attached to this socket.
616 */
617void
619 ports_.push_back(&port);
620}
621
622
623/**
624 * Notifies the socket that a port has been detached from it.
625 *
626 * Private helper method used only by friend class Port.
627 *
628 * @param port The port that has been detached from this socket.
629 */
630void
634
635
636/**
637 * Detaches all the buses from this socket.
638 */
639void
641 while (busses_.size() > 0) {
642 Segment* bus = busses_[0]->bus();
643 detachBus(*bus);
644 }
645}
646}
#define assert(condition)
@ UNKNOWN
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)
static void deleteAllItems(ContainerType &aMap)
static bool removeValueIfExists(ContainerType &aContainer, const ElementType &aKey)
std::string errorMessage() const
Definition Exception.cc:123
static std::string socketDirectionSettingError(const TTAMachine::Socket &socket, TTAMachine::Socket::Direction, const MachineTester &tester)
static std::string socketSegmentConnectionError(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment, const MachineTester &tester)
virtual bool canConnect(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment)
virtual bool canSetDirection(const TTAMachine::Socket &socket, TTAMachine::Socket::Direction direction)
void setName(const std::string &name)
void setAttribute(const std::string &name, const std::string &value)
ObjectState * child(int index) const
void addChild(ObjectState *child)
std::string stringAttribute(const std::string &name) const
std::string name() const
int childCount() const
virtual Segment * segment(int index) const
Definition Bus.cc:329
virtual int segmentCount() const
Definition Bus.cc:385
virtual void setName(const std::string &name)
virtual Machine * machine() const
virtual void loadState(const ObjectState *state)
void internalSetMachine(Machine &machine)
virtual bool isRegistered() const
virtual void ensureRegistration(const Component &component) const
virtual TCEString name() const
virtual ObjectState * saveState() const
static const std::string OSKEY_SEGMENT
ObjectState attribute key for segment name.
Definition Connection.hh:64
static const std::string OSKEY_BUS
ObjectState attribute key for bus name.
Definition Connection.hh:62
ObjectState * saveState() const
Definition Connection.cc:85
static const std::string OSNAME_CONNECTION
ObjectState name for Connection.
Definition Connection.hh:58
ComponentType * item(int index) const
MachineTester & machineTester() const
Definition Machine.cc:671
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual void removeSocket(Socket &socket)
Definition Machine.cc:490
virtual void addSocket(Socket &socket)
Definition Machine.cc:157
void detachSocket(Socket &socket)
Definition Segment.cc:210
bool isConnectedTo(const Socket &socket) const
Definition Segment.cc:274
Bus * parentBus() const
void attachSocket(Socket &socket)
Definition Segment.cc:180
std::string dataPortWidth_
Dataport width.
Definition Socket.hh:129
void setDirection(Direction direction)
Definition Socket.cc:130
static const std::string OSVALUE_INPUT
ObjectState attribute value for input direction.
Definition Socket.hh:104
virtual void unsetMachine()
Definition Socket.cc:443
@ 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
void removeConnection(const Connection *connection)
Definition Socket.cc:605
static const std::string OSNAME_SOCKET
ObjectState name for socket.
Definition Socket.hh:100
static const std::string OSKEY_DIRECTION
ObjectState attribute key for socket direction.
Definition Socket.hh:102
void detachBus(Segment &bus)
Definition Socket.cc:213
Direction direction() const
ConnectionTable busses_
Contains all connections to busses.
Definition Socket.hh:131
void detachAllBuses()
Definition Socket.cc:640
static const std::string OSVALUE_OUTPUT
ObjectState attribute value for output direction.
Definition Socket.hh:106
bool hasDataPortWidth() const
Definition Socket.cc:410
const Connection & connection(const Segment &bus) const
Definition Socket.cc:302
void detachPort(const Port &port)
Definition Socket.cc:631
void setDataPortWidth(const std::string &width)
Definition Socket.cc:420
std::set< Bus * > connectedBuses()
Definition Socket.cc:368
Port * port(int index) const
Definition Socket.cc:266
virtual void loadState(const ObjectState *state)
Definition Socket.cc:502
void attachBus(Segment &bus)
Definition Socket.cc:166
virtual ObjectState * saveState() const
Definition Socket.cc:465
virtual ~Socket()
Definition Socket.cc:88
Socket(const std::string &name)
Definition Socket.cc:69
virtual void setName(const std::string &name)
Definition Socket.cc:103
PortTable ports_
Contains all connections to ports.
Definition Socket.hh:133
Segment * segment(int index) const
Definition Socket.cc:401
virtual void setMachine(Machine &mach)
Definition Socket.cc:432
void detachAllPorts()
Definition Socket.cc:278
int segmentCount() const
int portCount() const
static const std::string OSVALUE_UNKNOWN
ObjectState attribute value for unknown direction.
Definition Socket.hh:108
Direction direction_
Direction of the socket.
Definition Socket.hh:127
const std::string & dataPortWidth() const
Definition Socket.cc:415
void attachPort(Port &port)
Definition Socket.cc:618
virtual boost::format text(int textId)