OpenASIP 2.2
Loading...
Searching...
No Matches
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"
44#include "Application.hh"
45#include "ContainerTools.hh"
46#include "ObjectState.hh"
47
48using std::string;
49using boost::format;
50
51namespace TTAMachine {
52
53// declaration of constant strings used in loadState and saveState
54const string Segment::OSNAME_SEGMENT = "segment";
55const string Segment::OSKEY_NAME = "name";
56const 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 */
70Segment::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 */
106Segment::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 */
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 */
147void
148Segment::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 */
179void
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 {
189 assert(!tester.canConnect(socket, *this));
190 MachineTestReporter reporter;
191 string errorMsg =
192 reporter.socketSegmentConnectionError(socket, *this, tester);
193 string procName = "Segment::attachSocket";
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 */
209void
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 */
228void
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 */
249const Connection&
250Segment::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 */
273bool
274Segment::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 */
299Socket*
300Segment::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 */
319void
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
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 */
356void
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 */
387bool
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 */
398bool
400 return (destinationSegment_ != NULL);
401}
402
403
404/**
405 * Removes connection from the connection table.
406 *
407 * @param connection Connection to be removed.
408 */
409void
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 */
447void
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 */
468void
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}
#define assert(condition)
static bool removeValueIfExists(ContainerType &aContainer, const ElementType &aKey)
std::string errorMessage() const
Definition Exception.cc:123
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)
static bool isValidComponentName(const std::string &name)
void setAttribute(const std::string &name, const std::string &value)
std::string stringAttribute(const std::string &name) const
std::string name() const
virtual bool hasSegment(const std::string &name) const
Definition Bus.cc:284
virtual Segment * segment(int index) const
Definition Bus.cc:329
virtual void addSegment(Segment &segment)
Definition Bus.cc:737
virtual int segmentCount() const
Definition Bus.cc:385
virtual void removeSegment(Segment &segment)
Definition Bus.cc:757
virtual Machine * machine() const
virtual void ensureRegistration(const Component &component) const
MachineTester & machineTester() const
Definition Machine.cc:671
void detachSocket(Socket &socket)
Definition Segment.cc:210
virtual void loadState(const ObjectState *state)
Definition Segment.cc:448
void detachAllSockets()
Definition Segment.cc:229
const Connection & connection(const Socket &socket) const
Definition Segment.cc:250
virtual ObjectState * saveState() const
Definition Segment.cc:421
ConnectionTable connections_
Contains all the connections to sockets.
Definition Segment.hh:109
void moveBefore(Segment &segment)
Definition Segment.cc:320
static const std::string OSKEY_DESTINATION
ObjectState attribute key for destination segment name.
Definition Segment.hh:91
Segment(const std::string &name, Bus &parent)
Definition Segment.cc:70
void moveAfter(Segment &segment)
Definition Segment.cc:357
Segment * sourceSegment_
Source segment.
Definition Segment.hh:105
static const std::string OSNAME_SEGMENT
ObjectState name for Segment.
Definition Segment.hh:87
bool hasSourceSegment() const
Definition Segment.cc:388
std::string name_
Name of the segment.
Definition Segment.hh:101
void setName(const std::string &name)
Definition Segment.cc:148
Bus * parent_
The parent bus.
Definition Segment.hh:103
bool isConnectedTo(const Socket &socket) const
Definition Segment.cc:274
bool hasDestinationSegment() const
Definition Segment.cc:399
static const std::string OSKEY_NAME
ObjectState attribute key for segment name.
Definition Segment.hh:89
int connectionCount() const
void removeConnection(const Connection *connection)
Definition Segment.cc:410
std::string name() const
Bus * parentBus() const
Segment * destinationSegment_
Destination segment.
Definition Segment.hh:107
void loadStateWithoutReferences(const ObjectState *state)
Definition Segment.cc:469
void attachSocket(Socket &socket)
Definition Segment.cc:180
bool isConnectedTo(const Bus &bus) const
Definition Socket.cc:331
void detachBus(Segment &bus)
Definition Socket.cc:213
const Connection & connection(const Segment &bus) const
Definition Socket.cc:302
void attachBus(Segment &bus)
Definition Socket.cc:166