OpenASIP  2.0
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"
40 #include "MachineTestReporter.hh"
41 #include "MOMTextGenerator.hh"
42 #include "Application.hh"
43 #include "AssocTools.hh"
44 #include "ObjectState.hh"
45 
46 using std::string;
47 using std::set;
48 using boost::format;
49 
50 namespace TTAMachine {
51 
52 // initialization of static data members
53 const string Bridge::OSNAME_BRIDGE = "bridge";
54 const string Bridge::OSKEY_SOURCE_BUS = "source";
55 const 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  */
74 Bridge::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  */
107 Bridge::Bridge(const ObjectState* state, Machine& mach)
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  */
128  unsetMachine();
129 }
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  */
140 void
141 Bridge::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  */
163 Bus*
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  */
178 Bus*
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  */
195 void
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  */
206 void
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  */
239  ObjectState* bridge = Component::saveState();
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  */
263 void
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 
274  Component::loadState(state);
275 
276  try {
277  string sourceBusName = state->stringAttribute(OSKEY_SOURCE_BUS);
278  string destinationBusName =
280 
281  assert(isRegistered());
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  */
326 void
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  */
378 void
379 Bridge::setSourceAndDestination(Bus& sourceBus, Bus& destinationBus) {
380  assert(sourceBus_ == NULL && destinationBus_ == NULL);
388 }
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  */
399 void
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 }
TTAMachine::Bridge::saveState
virtual ObjectState * saveState() const
Definition: Bridge.cc:238
TTAMachine::Bridge::OSKEY_SOURCE_BUS
static const std::string OSKEY_SOURCE_BUS
ObjectState attribute key for source bus name.
Definition: Bridge.hh:72
TTAMachine::Component::internalUnsetMachine
void internalUnsetMachine()
TTAMachine::Component::setName
virtual void setName(const std::string &name)
Definition: MachinePart.cc:142
TTAMachine::Bus::setDestinationBridge
virtual void setDestinationBridge(Bridge &bridge)
Definition: Bus.cc:613
TTAMachine::Bridge::sourceBus
Bus * sourceBus() const
TTAMachine::Bridge::destinationBus
Bus * destinationBus() const
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
ObjectState::stringAttribute
std::string stringAttribute(const std::string &name) const
Definition: ObjectState.cc:249
TTAMachine::Bridge::destinationBus_
Bus * destinationBus_
Destination bus.
Definition: Bridge.hh:86
TTAMachine::Component::isRegistered
virtual bool isRegistered() const
Definition: MachinePart.cc:177
TTAMachine::Bridge::loadState
virtual void loadState(const ObjectState *state)
Definition: Bridge.cc:264
MachineTestReporter::bridgingError
static std::string bridgingError(const TTAMachine::Bus &sourceBus, const TTAMachine::Bus &destinationBus, const MachineTester &tester)
Definition: MachineTestReporter.cc:219
ObjectStateLoadingException
Definition: Exception.hh:551
TTAMachine::Bridge
Definition: Bridge.hh:51
TTAMachine::Bus::setSourceBridge
virtual void setSourceBridge(Bridge &bridge)
Definition: Bus.cc:594
TTAMachine::Component::ensureRegistration
virtual void ensureRegistration(const Component &component) const
Definition: MachinePart.cc:163
AssocTools::containsKey
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
TTAMachine::Bridge::unsetMachine
virtual void unsetMachine()
Definition: Bridge.cc:207
TTAMachine::Bridge::sourcePrevious_
bool sourcePrevious_
Indicates which of the buses is previous and next.
Definition: Bridge.hh:88
TTAMachine::Bridge::~Bridge
virtual ~Bridge()
Definition: Bridge.cc:127
TTAMachine::Bus
Definition: Bus.hh:53
TTAMachine::Component::saveState
virtual ObjectState * saveState() const
Definition: MachinePart.cc:189
TTAMachine::Bus::canWrite
virtual bool canWrite(const Bus &bus) const
Definition: Bus.cc:558
MachineTester::canBridge
virtual bool canBridge(const TTAMachine::Bus &source, const TTAMachine::Bus &destination)
Definition: MachineTester.cc:203
ObjectState
Definition: ObjectState.hh:59
MachineTestReporter.hh
TTAMachine::Machine::Navigator::count
int count() const
Texts::TextGenerator::text
virtual boost::format text(int textId)
Definition: TextGenerator.cc:94
ObjectState::setName
void setName(const std::string &name)
TTAMachine::Bridge::Bridge
Bridge(const std::string &name, Bus &sourceBus, Bus &destinationBus)
Definition: Bridge.cc:74
TTAMachine::Bus::hasPreviousBus
virtual bool hasPreviousBus() const
Definition: Bus.cc:473
TTAMachine::Component::internalSetMachine
void internalSetMachine(Machine &machine)
assert
#define assert(condition)
Definition: Application.hh:86
IllegalParameters
Definition: Exception.hh:113
TTAMachine::Bus::canRead
virtual bool canRead(const Bus &bus) const
Definition: Bus.cc:537
TTAMachine::Bridge::setSourceAndDestination
void setSourceAndDestination(Bus &sourceBus, Bus &destination)
Definition: Bridge.cc:379
TTAMachine::Machine::bridgeNavigator
virtual BridgeNavigator bridgeNavigator() const
Definition: Machine.cc:404
TTAMachine::Bus::clearSourceBridge
virtual void clearSourceBridge(Bridge &bridge)
Definition: Bus.cc:632
TTAMachine::Machine::machineTester
MachineTester & machineTester() const
Definition: Machine.cc:671
TTAMachine::Machine::Navigator::hasItem
bool hasItem(const std::string &name) const
TTAMachine::Component::loadState
virtual void loadState(const ObjectState *state)
Definition: MachinePart.cc:205
Application.hh
ObjectState.hh
TTAMachine::Component
Definition: MachinePart.hh:90
TTAMachine::Machine::deleteBridge
virtual void deleteBridge(Bridge &bridge)
Definition: Machine.cc:587
Machine.hh
Exception
Definition: Exception.hh:54
Bus.hh
ObjectState::name
std::string name() const
Exception::errorMessage
std::string errorMessage() const
Definition: Exception.cc:123
TTAMachine::Bridge::previousBus
Bus * previousBus() const
Definition: Bridge.cc:164
TTAMachine::Bridge::nextBus
Bus * nextBus() const
Definition: Bridge.cc:179
TTAMachine::Bus::clearDestinationBridge
virtual void clearDestinationBridge(Bridge &bridge)
Definition: Bus.cc:652
MachineTester.hh
TTAMachine::Machine::addBridge
virtual void addBridge(Bridge &bridge)
Definition: Machine.cc:263
TTAMachine::Bridge::sourceBus_
Bus * sourceBus_
Source bus.
Definition: Bridge.hh:84
TTAMachine::Bus::hasNextBus
virtual bool hasNextBus() const
Definition: Bus.cc:488
TTAMachine::Bridge::setFirstOfChain
static void setFirstOfChain(const Bus &bus)
Definition: Bridge.cc:400
TTAMachine::Bridge::OSNAME_BRIDGE
static const std::string OSNAME_BRIDGE
ObjectState name for bridge.
Definition: Bridge.hh:70
TTAMachine::Bus::previousBus
virtual Bus * previousBus() const
Definition: Bus.cc:518
TTAMachine::Component::machine
virtual Machine * machine() const
AssocTools.hh
MOMTextGenerator
Definition: MOMTextGenerator.hh:40
TTAMachine::Machine::busNavigator
virtual BusNavigator busNavigator() const
Definition: Machine.cc:356
ComponentAlreadyExists
Definition: Exception.hh:510
MOMTextGenerator.hh
TTAMachine::Bridge::OSKEY_DESTINATION_BUS
static const std::string OSKEY_DESTINATION_BUS
ObjectState attribute key for destination bus name.
Definition: Bridge.hh:74
TTAMachine::Bridge::adjustChainDirection
void adjustChainDirection(const Bus &sourceBus, const Bus &destinationBus)
Definition: Bridge.cc:327
TTAMachine::Machine::Navigator::item
ComponentType * item(int index) const
IllegalConnectivity
Definition: Exception.hh:473
TTAMachine
Definition: Assembler.hh:48
TTAMachine::Bus::nextBus
virtual Bus * nextBus() const
Definition: Bus.cc:501
MachineTester
Definition: MachineTester.hh:46
TTAMachine::Bridge::setMachine
virtual void setMachine(Machine &mach)
Definition: Bridge.cc:196
TTAMachine::Machine::Navigator
Definition: Machine.hh:186
TTAMachine::Bridge::setName
virtual void setName(const std::string &name)
Definition: Bridge.cc:141
ObjectState::setAttribute
void setAttribute(const std::string &name, const std::string &value)
Definition: ObjectState.cc:100
InstanceNotFound
Definition: Exception.hh:304
Bridge.hh
TTAMachine::Machine
Definition: Machine.hh:73
MOMTextGenerator::TXT_BRIDGE_UNKNOWN_SRC_OR_DST
@ TXT_BRIDGE_UNKNOWN_SRC_OR_DST
Definition: MOMTextGenerator.hh:68