OpenASIP 2.2
Loading...
Searching...
No Matches
Bridge.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 Bridge.cc
26 *
27 * Implementation of Bridge class.
28 *
29 * @author Lasse Laasonen 2003 (lasse.laasonen-no.spam-tut.fi)
30 * @note reviewed 10 Jun 2004 by vpj, am, tr, ll
31 * @note rating: red
32 */
33
34#include <set>
35
36#include "Bridge.hh"
37#include "Machine.hh"
38#include "Bus.hh"
39#include "MachineTester.hh"
41#include "MOMTextGenerator.hh"
42#include "Application.hh"
43#include "AssocTools.hh"
44#include "ObjectState.hh"
45
46using std::string;
47using std::set;
48using boost::format;
49
50namespace TTAMachine {
51
52// initialization of static data members
53const string Bridge::OSNAME_BRIDGE = "bridge";
54const string Bridge::OSKEY_SOURCE_BUS = "source";
55const string Bridge::OSKEY_DESTINATION_BUS = "destination";
56
57
58/**
59 * Constructor.
60 *
61 * @param name Name of the bridge.
62 * @param sourceBus Bus from which the bridge reads data.
63 * @param destinationBus Bus to which the bridge writes data.
64 * @exception IllegalRegistration If the given source and destination buses
65 * are not registered to the same machine.
66 * @exception ComponentAlreadyExists If there is another bridge by the same
67 * name in the machine which contains the
68 * source and destination buses.
69 * @exception IllegalConnectivity If the bridge cannot be created because it
70 * would violate a connectivity constraint.
71 * @exception IllegalParameters If the given buses are the same instance.
72 * @exception InvalidName If the given name is not a valid component name.
73 */
74Bridge::Bridge(const string& name, Bus& sourceBus, Bus& destinationBus)
75 : Component(name), sourceBus_(NULL), destinationBus_(NULL) {
76 const string procName = "Bridge::Bridge";
77
78 if (&sourceBus == &destinationBus) {
79 throw IllegalParameters(__FILE__, __LINE__, procName);
80 }
81
84 if (!tester.canBridge(sourceBus, destinationBus)) {
85 string errorMsg = MachineTestReporter::bridgingError(
86 sourceBus, destinationBus, tester);
87 throw IllegalConnectivity(__FILE__, __LINE__, procName, errorMsg);
88 }
89
92}
93
94/**
95 * Constructor.
96 *
97 * Creates a skeleton objects with name only. This constructor should be used
98 * by Machine::loadState only. Do not use this constructor.
99 *
100 * @param state The ObjectState instance.
101 * @param mach The machine to which the bridge belongs.
102 * @exception ObjectStateLoadingException If the machine already has a bridge
103 * by the same name as the coming name
104 * of this bridge or if the
105 * ObjectState instance is invalid.
106 */
108 : Component(state), sourceBus_(NULL), destinationBus_(NULL) {
109 Machine::BridgeNavigator bridgeNav = mach.bridgeNavigator();
110
111 if (!bridgeNav.hasItem(name())) {
112 setMachine(mach);
113 } else {
114 MOMTextGenerator textGenerator;
115 format errorMsg = textGenerator.text(MOMTextGenerator::
116 TXT_BRIDGE_EXISTS_BY_SAME_NAME);
117 errorMsg % name();
118 string procName = "Bridge::Bridge";
119 throw ObjectStateLoadingException(__FILE__, __LINE__, procName,
120 errorMsg.str());
121 }
122}
123
124/**
125 * Destructor.
126 */
130
131
132/**
133 * Sets the name of the bridge.
134 *
135 * @param name Name of the bridge.
136 * @exception ComponentAlreadyExists If a bridge with the given name is
137 * already in the same machine.
138 * @exception InvalidName If the given name is not a valid component name.
139 */
140void
141Bridge::setName(const string& name) {
142 if (name == this->name()) {
143 return;
144 }
145
146 if (machine() != NULL) {
147 if (machine()->bridgeNavigator().hasItem(name)) {
148 string procName = "Bridge::setName";
149 throw ComponentAlreadyExists(__FILE__, __LINE__, procName);
150 } else {
152 }
153 } else {
155 }
156}
157
158/**
159 * Returns the previous bus from location point of view.
160 *
161 * @return The previous bus.
162 */
163Bus*
165 if (sourcePrevious_) {
166 return sourceBus_;
167 } else {
168 return destinationBus_;
169 }
170}
171
172
173/**
174 * Returns the next bus from location point of view.
175 *
176 * @return The next bus.
177 */
178Bus*
180 if (sourcePrevious_) {
181 return destinationBus_;
182 } else {
183 return sourceBus_;
184 }
185}
186
187
188/**
189 * Registers the bridge to a machine.
190 *
191 * @param mach Machine to which the bridge is going to be registered.
192 * @exception ComponentAlreadyExists If the given machine already has another
193 * bridge by the same name.
194 */
195void
197 mach.addBridge(*this);
198 internalSetMachine(mach);
199}
200
201/**
202 * Removes registration of the bridge from its current machine.
203 *
204 * The bridge is deleted because it cannot be unregistered from the machine.
205 */
206void
208
209 assert(machine() != NULL);
210
211 Bus* oldSource = sourceBus_;
212 Bus* oldDestination = destinationBus_;
213 sourceBus_ = NULL;
214 destinationBus_ = NULL;
215
216 if (oldSource != NULL) {
217 // may be NULL if loading the state from ObjectState has failed
218 oldSource->clearDestinationBridge(*this);
219 }
220
221 if (oldDestination != NULL) {
222 // may be NULL if loading the state from ObjectState has failed
223 oldDestination->clearSourceBridge(*this);
224 }
225
226 Machine* mach = machine();
228 mach->deleteBridge(*this);
229}
230
231
232/**
233 * Saves the contents to an ObjectState object.
234 *
235 * @return The newly created ObjectState object.
236 */
240 bridge->setName(OSNAME_BRIDGE);
241 string sourceBusName = sourceBus_->name();
242 string destinationBusName = destinationBus_->name();
243 bridge->setAttribute(OSKEY_SOURCE_BUS, sourceBusName);
244 bridge->setAttribute(OSKEY_DESTINATION_BUS, destinationBusName);
245 return bridge;
246}
247
248
249/**
250 * Loads its state from the given ObjectState instance.
251 *
252 * If the bridge is already joining two buses, the function will not work and
253 * ObjectStateLoadingException is thrown. This method works only if the
254 * bridge was created by the constructor with ObjectState argument.
255 *
256 * @param state The ObjectState instance.
257 * @exception ObjectStateLoadingException If the machine already a bridge by
258 * the same name as the coming name
259 * of this bridge or if creating
260 * references fails or if the given
261 * ObjectState instance is invalid.
262 */
263void
265 const string procName = "Bridge::loadState";
266
267 if (state->name() != OSNAME_BRIDGE) {
268 throw ObjectStateLoadingException(__FILE__, __LINE__, procName);
269 }
270 if (sourceBus() != NULL || destinationBus() != NULL) {
271 throw ObjectStateLoadingException(__FILE__, __LINE__, procName);
272 }
273
275
276 try {
277 string sourceBusName = state->stringAttribute(OSKEY_SOURCE_BUS);
278 string destinationBusName =
280
283 Bus* source;
284 Bus* destination;
285 try {
286 source = busNav.item(sourceBusName);
287 destination = busNav.item(destinationBusName);
288 } catch (InstanceNotFound& e) {
289 MOMTextGenerator textGenerator;
290 format errorMsg = textGenerator.text(
292 errorMsg % name();
293 throw ObjectStateLoadingException(__FILE__, __LINE__, procName,
294 errorMsg.str());
295 }
296 MachineTester& tester = machine()->machineTester();
297 if (tester.canBridge(*source, *destination)) {
298 setSourceAndDestination(*source, *destination);
299 } else {
300 string errorMsg = MachineTestReporter::bridgingError(
301 *source, *destination, tester);
302 throw ObjectStateLoadingException(__FILE__, __LINE__, procName,
303 errorMsg);
304 }
305
306 } catch(Exception& e) {
307 throw ObjectStateLoadingException(__FILE__, __LINE__, procName,
308 e.errorMessage());
309 }
310}
311
312/**
313 * Adjusts the direction of the bus chain (next/previous).
314 *
315 * When two bus chains are joined by a new bridge the direction of the
316 * destination side chain may have to be changed to verify that the
317 * direction of the new longer chain does not change in the middle of the
318 * chain. That is, if the source bus of the new bridge is the last of its
319 * chain and the destination bus of the new bridge is also the last, the
320 * direction of the destination side chain has to be changed such that the
321 * destination bus will become the first bus of its chain.
322 *
323 * @param sourceBus The new source side bus.
324 * @param destinationBus The new destination side bus.
325 */
326void
328 const Bus& sourceBus,
329 const Bus& destinationBus) {
330
331 Machine* mach = sourceBus.machine();
332 Machine::BridgeNavigator bridgeNav = mach->bridgeNavigator();
333
334 // if another bridge joining the buses is found, see the direction
335 // from that bridge
336 for (int i = 0; i < bridgeNav.count(); i++) {
337 Bridge* bridge = bridgeNav.item(i);
338 if (bridge->sourceBus() == &destinationBus &&
339 bridge->destinationBus() == &sourceBus) {
340 if (bridge->previousBus() == &sourceBus) {
341 sourcePrevious_ = true;
342 } else {
343 sourcePrevious_ = false;
344 }
345 return;
346 }
347 }
348
349 // change the direction of the bus chain containing destinationBus if
350 // needed
351 if (!sourceBus.hasNextBus()) {
352 sourcePrevious_ = true;
354 } else {
355 sourcePrevious_ = false;
356 // find the bus that should be the first bus of destination side
357 // chain
358 const Bus* otherEnd = &destinationBus;
359 while (otherEnd->hasNextBus()) {
360 otherEnd = otherEnd->nextBus();
361 }
362 if (otherEnd != &destinationBus) {
363 setFirstOfChain(*otherEnd);
364 }
365 }
366}
367
368
369/**
370 * Sets the source and destination buses of the bridge.
371 *
372 * The bridge must not have source and destination buses before calling this
373 * method.
374 *
375 * @param sourceBus The source bus.
376 * @param destinationBus The destination bus.
377 */
378void
389
390
391/**
392 * Sets the given bus to the first bus of the bus chain.
393 *
394 * That is, changes the direction of the chain if the given bus is currently
395 * the last bus of the chain. The given bus must be at the end of chain.
396 *
397 * @param bus The bus to be set to the first bus of the chain.
398 */
399void
401
402 assert(!(bus.hasPreviousBus() && bus.hasNextBus()));
403
404 if (bus.hasNextBus()) {
405 // if the bus is already the first
406 return;
407 } else {
408 const Bus* observable = &bus;
409
410 // collect the buses of the chain to set
411 set<const Bus*> busesInChain;
412 busesInChain.insert(observable);
413 while (observable->hasPreviousBus()) {
414 observable = observable->previousBus();
415 busesInChain.insert(observable);
416 }
417
418 Machine::BridgeNavigator bridgeNav =
419 bus.machine()->bridgeNavigator();
420 // change (next/previous) direction of each bridge that is joining
421 // a bus in the set
422 for (int i = 0; i < bridgeNav.count(); i++) {
423 Bridge* bridge = bridgeNav.item(i);
424 // Source bus or destination bus is NULL only if the bridge
425 // was created from ObjectState. Then calling nextBus() is
426 // illegal because sourcePrevious_ member is not initialized.
427 if (bridge->sourceBus() != NULL &&
428 bridge->destinationBus() != NULL &&
429 AssocTools::containsKey(busesInChain, bridge->nextBus())) {
430 bridge->sourcePrevious_ = !bridge->sourcePrevious_;
431 }
432 }
433 }
434}
435
436}
#define assert(condition)
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
std::string errorMessage() const
Definition Exception.cc:123
static std::string bridgingError(const TTAMachine::Bus &sourceBus, const TTAMachine::Bus &destinationBus, const MachineTester &tester)
virtual bool canBridge(const TTAMachine::Bus &source, const TTAMachine::Bus &destination)
void setName(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
Bus * destinationBus() const
virtual ~Bridge()
Definition Bridge.cc:127
Bus * sourceBus() const
Bus * nextBus() const
Definition Bridge.cc:179
virtual void setName(const std::string &name)
Definition Bridge.cc:141
virtual ObjectState * saveState() const
Definition Bridge.cc:238
Bus * sourceBus_
Source bus.
Definition Bridge.hh:84
Bus * previousBus() const
Definition Bridge.cc:164
static const std::string OSNAME_BRIDGE
ObjectState name for bridge.
Definition Bridge.hh:70
Bridge(const std::string &name, Bus &sourceBus, Bus &destinationBus)
Definition Bridge.cc:74
static const std::string OSKEY_DESTINATION_BUS
ObjectState attribute key for destination bus name.
Definition Bridge.hh:74
static const std::string OSKEY_SOURCE_BUS
ObjectState attribute key for source bus name.
Definition Bridge.hh:72
static void setFirstOfChain(const Bus &bus)
Definition Bridge.cc:400
void setSourceAndDestination(Bus &sourceBus, Bus &destination)
Definition Bridge.cc:379
virtual void unsetMachine()
Definition Bridge.cc:207
virtual void loadState(const ObjectState *state)
Definition Bridge.cc:264
Bus * destinationBus_
Destination bus.
Definition Bridge.hh:86
void adjustChainDirection(const Bus &sourceBus, const Bus &destinationBus)
Definition Bridge.cc:327
bool sourcePrevious_
Indicates which of the buses is previous and next.
Definition Bridge.hh:88
virtual void setMachine(Machine &mach)
Definition Bridge.cc:196
virtual Bus * previousBus() const
Definition Bus.cc:518
virtual void clearSourceBridge(Bridge &bridge)
Definition Bus.cc:632
virtual bool canWrite(const Bus &bus) const
Definition Bus.cc:558
virtual void clearDestinationBridge(Bridge &bridge)
Definition Bus.cc:652
virtual bool hasPreviousBus() const
Definition Bus.cc:473
virtual void setDestinationBridge(Bridge &bridge)
Definition Bus.cc:613
virtual bool hasNextBus() const
Definition Bus.cc:488
virtual void setSourceBridge(Bridge &bridge)
Definition Bus.cc:594
virtual Bus * nextBus() const
Definition Bus.cc:501
virtual bool canRead(const Bus &bus) const
Definition Bus.cc:537
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
ComponentType * item(int index) const
bool hasItem(const std::string &name) const
virtual BridgeNavigator bridgeNavigator() const
Definition Machine.cc:404
MachineTester & machineTester() const
Definition Machine.cc:671
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual void addBridge(Bridge &bridge)
Definition Machine.cc:263
virtual void deleteBridge(Bridge &bridge)
Definition Machine.cc:587
virtual boost::format text(int textId)