OpenASIP  2.0
Segment.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 Segment.cc
26  *
27  * Implementation of Segment class.
28  *
29  * @author Lasse Laasonen 2003 (lasse.laasonen-no.spam-tut.fi)
30  * @note reviewed 14 Jun 2004 by am, tr, ao, ll
31  * @note rating: red
32  */
33 
34 #include <string>
35 #include <boost/format.hpp>
36 
37 #include "Segment.hh"
38 #include "Bus.hh"
39 #include "Socket.hh"
40 #include "Connection.hh"
41 #include "MOMTextGenerator.hh"
42 #include "MachineTester.hh"
43 #include "MachineTestReporter.hh"
44 #include "Application.hh"
45 #include "ContainerTools.hh"
46 #include "ObjectState.hh"
47 
48 using std::string;
49 using boost::format;
50 
51 namespace TTAMachine {
52 
53 // declaration of constant strings used in loadState and saveState
54 const string Segment::OSNAME_SEGMENT = "segment";
55 const string Segment::OSKEY_NAME = "name";
56 const string Segment::OSKEY_DESTINATION = "destination";
57 
58 /**
59  * Constructor.
60  *
61  * The segment is appended at the end of the segment chain of its parent
62  * bus.
63  *
64  * @param name Name of the segment.
65  * @param parent The bus this segment belongs to (parent bus).
66  * @exception ComponentAlreadyExists If a segment with the same name already
67  * exists in the same segment chain.
68  * @exception InvalidName If the given name is not a valid component name.
69  */
70 Segment::Segment(const string& name, Bus& parent)
71  : name_(name),
72  parent_(NULL),
73  sourceSegment_(NULL),
74  destinationSegment_(NULL) {
76  const string procName = "Segment::Segment";
77  throw InvalidName(__FILE__, __LINE__, procName);
78  }
79 
80  parent.addSegment(*this);
81  parent_ = &parent;
82 
83  for (int i = 0; i < parent.segmentCount(); i++) {
84  Segment* segment = parent.segment(i);
85  if (segment->destinationSegment_ == NULL && segment != this) {
86  segment->destinationSegment_ = this;
87  sourceSegment_ = segment;
88  break;
89  }
90  }
91 }
92 
93 /**
94  * Constructor.
95  *
96  * Creates a skeleton segment with name only. This method should be called
97  * by Bus::loadStateWithoutReferences only. Do not use this constructor.
98  *
99  * @param state The ObjectState instance from which the name is loaded.
100  * @param parent The bus this segment belongs to (parent bus).
101  * @exception ComponentAlreadyExists If a segment with the same name already
102  * exists in the given parent bus.
103  * @exception ObjectStateLoadingException If an error occurs while loading
104  * the state.
105  */
106 Segment::Segment(const ObjectState* state, Bus& parent)
107  : name_(""),
108  parent_(NULL),
109  sourceSegment_(NULL),
110  destinationSegment_(NULL) {
112  parent.addSegment(*this);
113  parent_ = &parent;
114 }
115 
116 /**
117  * Destructor.
118  *
119  * Detaches all the sockets before destruction.
120  */
122 
123  Bus* parentBus = parent_;
124  parent_ = NULL;
125  parentBus->removeSegment(*this);
126 
128 
129  if (sourceSegment_ != NULL) {
131  }
132  if (destinationSegment_ != NULL) {
134  }
135 }
136 
137 
138 /**
139  * Sets the name of the segment.
140  *
141  * @param name Name of the segment.
142  * @exception ComponentAlreadyExists If a segment with the given name already
143  * exists in the segment chain of the
144  * parent bus.
145  * @exception InvalidName If the given name is not a valid component name.
146  */
147 void
148 Segment::setName(const string& name) {
149  if (name == this->name()) {
150  return;
151  }
152 
153  const string procName = "Segment::setName";
154 
156  throw InvalidName(__FILE__, __LINE__, procName);
157  }
158 
159  Bus* parent = parentBus();
160  for (int i = 0; i < parent->segmentCount(); i++) {
161  Segment* segment = parent->segment(i);
162  if (segment->name() == name) {
163  throw ComponentAlreadyExists(__FILE__, __LINE__, procName);
164  }
165  }
166 
167  name_ = name;
168 }
169 
170 /**
171  * Connects a socket to the segment.
172  *
173  * @param socket Socket to be connected.
174  * @exception IllegalRegistration If socket and segment do not belong to the
175  * same machine.
176  * @exception IllegalConnectivity If the connection would violate a
177  * connectivity constraint.
178  */
179 void
181  parentBus()->ensureRegistration(socket);
182 
183  if (socket.isConnectedTo(*this)) {
184  if (!isConnectedTo(socket)) {
185  const Connection* conn = &(socket.connection(*this));
186  connections_.push_back(conn);
187  } else {
188  MachineTester& tester = parentBus()->machine()->machineTester();
189  assert(!tester.canConnect(socket, *this));
190  MachineTestReporter reporter;
191  string errorMsg =
192  reporter.socketSegmentConnectionError(socket, *this, tester);
193  string procName = "Segment::attachSocket";
194  throw IllegalConnectivity(
195  __FILE__, __LINE__, procName, errorMsg);
196  }
197  } else {
198  socket.attachBus(*this);
199  }
200 }
201 
202 /**
203  * Detaches socket from the segment.
204  *
205  * @param socket Socket which is detached.
206  * @exception InstanceNotFound If the segment is not attached to the given
207  * socket.
208  */
209 void
211  if (!isConnectedTo(socket)) {
212  string procName = "Segment::detachSocket";
213  throw InstanceNotFound(__FILE__, __LINE__, procName);
214  }
215 
216  const Connection& conn = connection(socket);
217  removeConnection(&conn);
218 
219  if (socket.isConnectedTo(*this)) {
220  socket.detachBus(*this);
221  delete &conn;
222  }
223 }
224 
225 /**
226  * Detaches all the sockets attached to the segment.
227  */
228 void
230  ConnectionTable::iterator iter = connections_.begin();
231  while (iter != connections_.end()) {
232  Socket* socket = (*iter)->socket();
233  detachSocket(*socket); // removes the socket from connections_
234  iter = connections_.begin();
235  }
236 }
237 
238 
239 /**
240  * Returns the Connection object which joins this segment and the given
241  * socket.
242  *
243  * The connection must exist before calling this method. This method is not
244  * intended for clients. Do not use this method.
245  *
246  * @param socket Socket which is attached to this segment.
247  * @return Connection object which joins the socket and the segment.
248  */
249 const Connection&
250 Segment::connection(const Socket& socket) const {
251 
252  ConnectionTable::const_iterator iter = connections_.begin();
253  while (iter != connections_.end()) {
254  if ((*iter)->socket() == &socket) {
255  return **iter;
256  } else {
257  iter++;
258  }
259  }
260  assert(false);
261 
262  // this return statement is only to avoid warning in Solaris environment
263  return **iter;
264 }
265 
266 
267 /**
268  * Checks whether the segment is connected to the given socket.
269  *
270  * @param socket Socket.
271  * @return True if connected, otherwise false.
272  */
273 bool
274 Segment::isConnectedTo(const Socket& socket) const {
275 
276  ConnectionTable::const_iterator iter = connections_.begin();
277  while (iter != connections_.end()) {
278  if ((*iter)->socket() == &socket) {
279  return true;
280  } else {
281  iter++;
282  }
283  }
284 
285  return false;
286 }
287 
288 
289 /**
290  * Returns the connected socket by the given index.
291  *
292  * The index must be greater or equal to 0 and less than the number of
293  * socket connections.
294  *
295  * @param index Index.
296  * @return The connected socket by the given index.
297  * @exception OutOfRange If the given index is out of range.
298  */
299 Socket*
300 Segment::connection(int index) const {
301  if (index < 0 || index >= connectionCount()) {
302  string procName = "Segment::connection";
303  throw OutOfRange(__FILE__, __LINE__, procName);
304  }
305  return connections_[index]->socket();
306 }
307 
308 /**
309  * Moves the segment to the front of the given segment in the segment chain.
310  *
311  * The successor of this segment will become the successor of the current
312  * predecessor of this segment. The current predecessor of the given segment
313  * will become the predecessor of this segment.
314  *
315  * @param segment The segment in front of which the segment is moved.
316  * @exception IllegalRegistration If the given segment is in different bus
317  * than this segment.
318  */
319 void
321  if (parentBus() != segment.parentBus()) {
322  string procName = "Segment::moveBefore";
323  throw IllegalRegistration(__FILE__, __LINE__, procName);
324  }
325 
326  // detach from chain
327  if (destinationSegment_ != NULL) {
329  }
330  if (sourceSegment_ != NULL) {
332  }
333 
334  // attach to new position
335  if (segment.sourceSegment_ != NULL) {
336  segment.sourceSegment_->destinationSegment_ = this;
337  }
338 
339  sourceSegment_ = segment.sourceSegment_;
340  destinationSegment_ = &segment;
341 
342  segment.sourceSegment_ = this;
343 }
344 
345 /**
346  * Moves the segment behind the given segment in the segment chain.
347  *
348  * The successor of this segment will become the successor of the current
349  * predecessor of this segment. The current successor of the given segment
350  * will become the successor the this segment.
351  *
352  * @param segment The segment behind of which the segment is moved.
353  * @exception IllegalRegistration If the given segment is in different bus
354  * than this segment.
355  */
356 void
358  if (parentBus() != segment.parentBus()) {
359  string procName = "Segment::moveAfter";
360  throw IllegalRegistration(__FILE__, __LINE__, procName);
361  }
362 
363  // detach from chain
364  if (destinationSegment_ != NULL) {
366  }
367  if (sourceSegment_ != NULL) {
369  }
370 
371  // attach to new position
372  if (segment.destinationSegment_ != NULL) {
373  segment.destinationSegment_->sourceSegment_ = this;
374  }
375 
376  sourceSegment_ = &segment;
378 
379  segment.destinationSegment_ = this;
380 }
381 
382 /**
383  * Returns true if the segment has a source segment, otherwise false.
384  *
385  * @return True if the segment has a source segment, otherwise false.
386  */
387 bool
389  return (sourceSegment_ != NULL);
390 }
391 
392 
393 /**
394  * Returns true if the segment has a destination segment, otherwise false.
395  *
396  * @return True if the segment has a destination segment, otherwise false.
397  */
398 bool
400  return (destinationSegment_ != NULL);
401 }
402 
403 
404 /**
405  * Removes connection from the connection table.
406  *
407  * @param connection Connection to be removed.
408  */
409 void
412 }
413 
414 
415 /**
416  * Saves the contents of the segment to an ObjectState object.
417  *
418  * @return The created ObjectState object.
419  */
422 
423  ObjectState* segmentState = new ObjectState(OSNAME_SEGMENT);
424  segmentState->setAttribute(OSKEY_NAME, name());
425  if (destinationSegment_ != NULL) {
426  segmentState->setAttribute(
428  }
429 
430  return segmentState;
431 }
432 
433 
434 /**
435  * Loads the state of the segment from the given ObjectState instance.
436  *
437  * Loads only name of the segment. Does not load connections to
438  * sockets. The destination of the segment and the order the
439  * segments in the chain is set later, in Bus::loadState.
440  *
441  * @param state The ObjectState instance.
442  * @exception ObjectStateLoadingException If the parent bus has a segment
443  * with the same name that is
444  * assigned to this segment or if the
445  * ObjectState tree is invalid.
446  */
447 void
449  string procName = "Segment::loadState";
450  MOMTextGenerator textGenerator;
451 
452  if (state->name() != OSNAME_SEGMENT) {
453  throw ObjectStateLoadingException(__FILE__, __LINE__, procName);
454  }
455 
458 }
459 
460 /**
461  * Loads the state of the object from the given ObjectState instance without
462  * references to other machine parts.
463  *
464  * @param state The ObjectState instance.
465  * @exception ObjectStateLoadingException If the given ObjectState instance
466  * is invalid.
467  */
468 void
470  const string procName = "Segment::loadStateWithoutReferences";
471 
472  if (state->name() != OSNAME_SEGMENT) {
473  throw ObjectStateLoadingException(__FILE__, __LINE__, procName);
474  }
475 
476  try {
477  string name = state->stringAttribute(OSKEY_NAME);
479  throw InvalidName(__FILE__, __LINE__, procName);
480  }
481  if (parent_ != NULL && parent_->hasSegment(name) &&
482  this->name() != name) {
483  throw ObjectStateLoadingException(__FILE__, __LINE__, procName);
484  }
485  name_ = name;
486  } catch (const Exception& exception) {
488  __FILE__, __LINE__, procName, exception.errorMessage());
489  }
490 }
491 }
MachineTester::canConnect
virtual bool canConnect(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment)
Definition: MachineTester.cc:86
TTAMachine::Socket::connection
const Connection & connection(const Segment &bus) const
Definition: Socket.cc:302
TTAMachine::Segment::setName
void setName(const std::string &name)
Definition: Segment.cc:148
TTAMachine::Segment::destinationSegment_
Segment * destinationSegment_
Destination segment.
Definition: Segment.hh:107
TTAMachine::Segment::attachSocket
void attachSocket(Socket &socket)
Definition: Segment.cc:180
ObjectState::stringAttribute
std::string stringAttribute(const std::string &name) const
Definition: ObjectState.cc:249
ObjectStateLoadingException
Definition: Exception.hh:551
TTAMachine::Segment
Definition: Segment.hh:54
TTAMachine::Component::ensureRegistration
virtual void ensureRegistration(const Component &component) const
Definition: MachinePart.cc:163
Connection.hh
OutOfRange
Definition: Exception.hh:320
TTAMachine::Bus
Definition: Bus.hh:53
TTAMachine::Segment::OSKEY_NAME
static const std::string OSKEY_NAME
ObjectState attribute key for segment name.
Definition: Segment.hh:89
ObjectState
Definition: ObjectState.hh:59
MachineTestReporter::socketSegmentConnectionError
static std::string socketSegmentConnectionError(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment, const MachineTester &tester)
Definition: MachineTestReporter.cc:55
TTAMachine::Segment::connections_
ConnectionTable connections_
Contains all the connections to sockets.
Definition: Segment.hh:109
MachineTestReporter.hh
TTAMachine::Bus::segment
virtual Segment * segment(int index) const
Definition: Bus.cc:329
TTAMachine::Segment::moveAfter
void moveAfter(Segment &segment)
Definition: Segment.cc:357
TTAMachine::Segment::loadState
virtual void loadState(const ObjectState *state)
Definition: Segment.cc:448
Socket.hh
TTAMachine::Segment::OSNAME_SEGMENT
static const std::string OSNAME_SEGMENT
ObjectState name for Segment.
Definition: Segment.hh:87
TTAMachine::Segment::detachSocket
void detachSocket(Socket &socket)
Definition: Segment.cc:210
TTAMachine::Bus::addSegment
virtual void addSegment(Segment &segment)
Definition: Bus.cc:737
assert
#define assert(condition)
Definition: Application.hh:86
TTAMachine::Segment::connectionCount
int connectionCount() const
Segment.hh
TTAMachine::Socket::attachBus
void attachBus(Segment &bus)
Definition: Socket.cc:166
InvalidName
Definition: Exception.hh:827
TTAMachine::Segment::~Segment
~Segment()
Definition: Segment.cc:121
ContainerTools::removeValueIfExists
static bool removeValueIfExists(ContainerType &aContainer, const ElementType &aKey)
TTAMachine::Machine::machineTester
MachineTester & machineTester() const
Definition: Machine.cc:671
TTAMachine::Segment::parentBus
Bus * parentBus() const
Application.hh
ObjectState.hh
TTAMachine::Socket
Definition: Socket.hh:53
TTAMachine::Segment::detachAllSockets
void detachAllSockets()
Definition: Segment.cc:229
Exception
Definition: Exception.hh:54
TTAMachine::Segment::isConnectedTo
bool isConnectedTo(const Socket &socket) const
Definition: Segment.cc:274
MachineTester::isValidComponentName
static bool isValidComponentName(const std::string &name)
Definition: MachineTester.cc:312
TTAMachine::Bus::hasSegment
virtual bool hasSegment(const std::string &name) const
Definition: Bus.cc:284
Bus.hh
TTAMachine::Segment::sourceSegment_
Segment * sourceSegment_
Source segment.
Definition: Segment.hh:105
ObjectState::name
std::string name() const
TTAMachine::Segment::connection
const Connection & connection(const Socket &socket) const
Definition: Segment.cc:250
TTAMachine::Socket::isConnectedTo
bool isConnectedTo(const Bus &bus) const
Definition: Socket.cc:331
TTAMachine::Segment::hasSourceSegment
bool hasSourceSegment() const
Definition: Segment.cc:388
TTAMachine::Segment::saveState
virtual ObjectState * saveState() const
Definition: Segment.cc:421
TTAMachine::Socket::detachBus
void detachBus(Segment &bus)
Definition: Socket.cc:213
Exception::errorMessage
std::string errorMessage() const
Definition: Exception.cc:123
IllegalRegistration
Definition: Exception.hh:532
MachineTester.hh
TTAMachine::Connection
Definition: Connection.hh:48
TTAMachine::Segment::hasDestinationSegment
bool hasDestinationSegment() const
Definition: Segment.cc:399
TTAMachine::Bus::removeSegment
virtual void removeSegment(Segment &segment)
Definition: Bus.cc:757
TTAMachine::Component::machine
virtual Machine * machine() const
MOMTextGenerator
Definition: MOMTextGenerator.hh:40
MachineTestReporter
Definition: MachineTestReporter.hh:45
ComponentAlreadyExists
Definition: Exception.hh:510
TTAMachine::Segment::moveBefore
void moveBefore(Segment &segment)
Definition: Segment.cc:320
TTAMachine::Segment::parent_
Bus * parent_
The parent bus.
Definition: Segment.hh:103
MOMTextGenerator.hh
TTAMachine::Segment::name_
std::string name_
Name of the segment.
Definition: Segment.hh:101
TTAMachine::Segment::OSKEY_DESTINATION
static const std::string OSKEY_DESTINATION
ObjectState attribute key for destination segment name.
Definition: Segment.hh:91
TTAMachine::Segment::Segment
Segment(const std::string &name, Bus &parent)
Definition: Segment.cc:70
IllegalConnectivity
Definition: Exception.hh:473
TTAMachine::Segment::removeConnection
void removeConnection(const Connection *connection)
Definition: Segment.cc:410
TTAMachine::Segment::name
std::string name() const
TTAMachine
Definition: Assembler.hh:48
MachineTester
Definition: MachineTester.hh:46
TTAMachine::Bus::segmentCount
virtual int segmentCount() const
Definition: Bus.cc:385
TTAMachine::Segment::loadStateWithoutReferences
void loadStateWithoutReferences(const ObjectState *state)
Definition: Segment.cc:469
ObjectState::setAttribute
void setAttribute(const std::string &name, const std::string &value)
Definition: ObjectState.cc:100
InstanceNotFound
Definition: Exception.hh:304
ContainerTools.hh