OpenASIP 2.2
Loading...
Searching...
No Matches
Bus.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 Bus.cc
26 *
27 * Implementation of Bus class.
28 *
29 * @author Lasse Laasonen 2004 (lasse.laasonen-no.spam-tut.fi)
30 * @note reviewed 11 Jun 2004 by am, pj, jn, ll
31 * @note rating: red
32 */
33
34#include <string>
35
36#include "Bus.hh"
37#include "Guard.hh"
38#include "Segment.hh"
39#include "Socket.hh"
40#include "Bridge.hh"
42#include "MOMTextGenerator.hh"
43#include "Application.hh"
44#include "ContainerTools.hh"
45#include "ObjectState.hh"
46
47using std::vector;
48using std::string;
49using boost::format;
50
51namespace TTAMachine {
52
53// declaration of constants used in ObjectStates
54const string Bus::OSNAME_BUS = "bus";
55const string Bus::OSKEY_WIDTH = "width";
56const string Bus::OSKEY_IMMWIDTH = "immwidth";
57const string Bus::OSKEY_EXTENSION = "extension";
58const string Bus::OSVALUE_SIGN = "sign";
59const string Bus::OSVALUE_ZERO = "zero";
60
61
62/**
63 * Constructor.
64 *
65 * @param name Name of the bus.
66 * @param width Bit width of the bus.
67 * @param immWidth Bit width of the inline immediate word.
68 * @param extensionMode Extension mode applied to the inline immediate word
69 * when it is narrower than the bus on which it is
70 * transported.
71 * @exception OutOfRange If the given width or immediate width is invalid.
72 * @exception InvalidName If the given name is not a valid component name.
73 */
75 const std::string& name, int width, int immWidth,
76 Machine::Extension extensionMode)
77 : Component(name),
78 width_(width),
79 immWidth_(immWidth),
80 extensionMode_(extensionMode) {
81 if (width <= 0 || immWidth < 0 || immWidth > width) {
82 string procName = "Bus::Bus";
83 throw OutOfRange(__FILE__, __LINE__, procName);
84 }
85}
86
87/**
88 * Constructor.
89 *
90 * Loads the state of the bus from the given ObjectState instance. Does not
91 * load connections to sockets.
92 *
93 * @param state Root node of the ObjectState tree from which the state is
94 * loaded.
95 * @exception ObjectStateLoadingException If the given ObjectState instance
96 * is invalid.
97 */
98Bus::Bus(const ObjectState* state) : Component(state) {
99 try {
101 } catch (Exception&) {
104 throw;
105 }
106}
107
108/**
109 * Destructor.
110 *
111 * Before destruction detaches all sockets from the bus.
112 */
118
119
120/**
121 * Returns the position of the bus in move slot order.
122 *
123 * @return The position (0 is the first position).
124 * @exception NotAvailable If the bus is not registered to a machine.
125 */
126int
128 if (!isRegistered()) {
129 throw NotAvailable(__FILE__, __LINE__, __func__);
130 }
131
133 for (int i = 0; i < busNav.count(); i++) {
134 if (busNav.item(i) == this) {
135 return i;
136 }
137 }
138
139 assert(false);
140 return 0;
141}
142
143/**
144 * Returns the bit width of the bus.
145 *
146 * @return Bit width of the bus.
147 */
148int
149Bus::width() const {
150 return width_;
151}
152
153
154/**
155 * Returns the bit width of the inline immediate word.
156 *
157 * @return Bit width of the inline immediate word.
158 */
159int
161 return immWidth_;
162}
163
164
165/**
166 * Returns true if the bus uses sign extension.
167 *
168 * @return True if the bus uses sign extension.
169 */
170bool
173}
174
175
176/**
177 * Returns true if the bus uses zero extension.
178 *
179 * @return True if the bus uses zero extension.
180 */
181bool
184}
185
186
187/**
188 * Sets the name of the bus.
189 *
190 * @param name Name of the bus.
191 * @exception ComponentAlreadyExists If a bus with the given name is
192 * already in the same machine.
193 * @exception InvalidName If the given name is not a valid component name.
194 */
195void
196Bus::setName(const std::string& name) {
197 if (name == this->name()) {
198 return;
199 }
200
201 if (machine() != NULL) {
202 if (machine()->busNavigator().hasItem(name) ||
203 machine()->immediateSlotNavigator().hasItem(name)) {
204 string procName = "Bus::setName";
205 throw ComponentAlreadyExists(__FILE__, __LINE__, procName);
206 } else {
208 }
209 } else {
211 }
212}
213
214/**
215 * Sets the bit width of the bus.
216 *
217 * @param width The new bit width of the bus.
218 * @exception OutOfRange If the given width is less or equal to zero or if
219 * there is an instruction template that has greater
220 * bit width for this slot.
221 */
222void
223Bus::setWidth(int width) {
224 const string procName = "Bus::setWidth";
225
226 if (width <= 0) {
227 throw OutOfRange(__FILE__, __LINE__, procName);
228 }
229
230 width_ = width;
231}
232
233/**
234 * Sets the number of bits of inline immediates.
235 *
236 * @param width The bit width of inline immediates.
237 * @exception OutOfRange If the given width is negative or
238 greater than the bit width of the bus.
239 */
240void
242 if (width < 0 || width > this->width()) {
243 string procName = "Bus::setImmediateWidth";
244 throw OutOfRange(__FILE__, __LINE__, procName);
245 }
247}
248
249/**
250 * Sets the zero extension mode.
251 */
252void
256
257
258/**
259 * Sets the sign extension mode.
260 */
261void
265
266
267/**
268 * Sets the extension mode.
269 */
270void
272 extensionMode_ = extension;
273}
274
275
276/**
277 * Returns true if the bus has a segment with the given name.
278 *
279 * @param name Name of the segment.
280 * @return True if the bus has a segment with the given name, otherwise
281 * false.
282 */
283bool
284Bus::hasSegment(const std::string& name) const {
285 SegmentTable::const_iterator iter = segments_.begin();
286 while (iter != segments_.end()) {
287 if ((*iter)->name() == name) {
288 return true;
289 }
290 iter++;
291 }
292 return false;
293}
294
295
296/**
297 * Returns true if the bus is connected to the given socket, otherwise false.
298 *
299 * @param socket Socket.
300 * @return True if the bus is connected to the given socket, otherwise false.
301 */
302bool
303Bus::isConnectedTo(const Socket& socket) const {
304
305 SegmentTable::const_iterator iter = segments_.begin();
306 while (iter != segments_.end()) {
307 if ((*iter)->isConnectedTo(socket)) {
308 return true;
309 }
310 iter++;
311 }
312 return false;
313}
314
315
316/**
317 * Returns the bus segment at a given index.
318 *
319 * The index must be greater or equal to 0 and less than the number of
320 * segments. The segments are returned in the correct order. Thus, index 0
321 * returns the first segment in the segment chain, index 1 returns its
322 * destination segment and so on.
323 *
324 * @param index Index.
325 * @return The segment found on the given index.
326 * @exception OutOfRange If the given index is out of range.
327 */
328Segment*
329Bus::segment(int index) const {
330 if (index < 0 || index >= segmentCount()) {
331 string procName = "Bus::segment";
332 throw OutOfRange(__FILE__, __LINE__, procName);
333 }
334
335 // find the first segment of the chain
336 Segment* firstSegment = NULL;
337 SegmentTable::const_iterator iter = segments_.begin();
338 while (iter != segments_.end()) {
339 Segment* segment = *iter;
340 if (!segment->hasSourceSegment()) {
341 firstSegment = segment;
342 break;
343 }
344 iter++;
345 }
346
347 // follow the segment chain until the requested segment is reached
348 Segment* nextSegment = firstSegment;
349 for (int i = 0; i < index; i++) {
350 nextSegment = nextSegment->destinationSegment();
351 }
352
353 return nextSegment;
354}
355
356/**
357 * Returns the segment which has the given name.
358 *
359 * @param name Name of the segment.
360 * @return Segment which has the given name.
361 * @exception InstanceNotFound If the bus does not contain a segment by the
362 * given name.
363 */
364Segment*
365Bus::segment(const std::string& name) const {
366 SegmentTable::const_iterator iter = segments_.begin();
367 while (iter != segments_.end()) {
368 if ((*iter)->name() == name) {
369 return *iter;
370 }
371 iter++;
372 }
373
374 // requested segment not found
375 string procName = "Bus::segment";
376 throw InstanceNotFound(__FILE__, __LINE__, procName);
377}
378
379/**
380 * Returns the number of segments in this bus.
381 *
382 * @return Number of segments in this bus.
383 */
384int
386 return segments_.size();
387}
388
389/**
390 * Checks whether the bus has the given guard.
391 */
392bool
393Bus::hasGuard(const Guard& guard) const {
394 for (GuardTable::const_iterator iter = guards_.begin();
395 iter != guards_.end(); iter++) {
396 if ((*iter)->isEqual(guard)) {
397 return true;
398 }
399 }
400 return false;
401}
402
403/**
404 * Adds guard to the bus.
405 *
406 * @param guard Pointer to the Guard object to be added.
407 * @exception ComponentAlreadyExists If there is an equal guard already.
408 */
409void
411 if (hasGuard(guard)) {
412 string procName = "Bus::addGuard";
413 throw ComponentAlreadyExists(__FILE__, __LINE__, __func__,
414 "Bus already has the given guard!");
415 }
416
417 guards_.push_back(&guard);
418}
419
420/**
421 * Removes the given guard from the bus.
422 *
423 * This method should be called by Guard destructor only.
424 *
425 * @param guard Guard to be removed.
426 */
427void
429 // run time check: can be called from Guard destructor only
430 assert(guard.parentBus() == NULL);
432}
433
434
435/**
436 * Returns the number of guards in the bus.
437 *
438 * @return The number of guards in the bus.
439 */
440int
442 return guards_.size();
443}
444
445
446/**
447 * Returns the guard by the given index.
448 *
449 * The index must be between 0 and the return value of numberOfGuards() - 1.
450 *
451 * @param index Index.
452 * @return The guard by the given index.
453 * @exception OutOfRange If the given index is out of range.
454 */
455Guard*
456Bus::guard(int index) const {
457 if (index < 0 || static_cast<size_t>(index) >= guards_.size()) {
458 string procName = "Bus::guard";
459 throw OutOfRange(__FILE__, __LINE__, procName);
460 }
461 return guards_[index];
462}
463
464/**
465 * Checks if the bus has previous bus.
466 *
467 * Previous does not mean source in that case but the previous bus from
468 * location point of view.
469 *
470 * @return True if the bus has previous bus, otherwise false.
471 */
472bool
474 Bridge* prevBridge = previousBridge();
475 return prevBridge != NULL;
476}
477
478
479/**
480 * Checks if the bus has next bus.
481 *
482 * Next does not mean destination bus in that case but the next bus from
483 * location point of view.
484 *
485 * @return True if the bus has next bus, otherwise false.
486 */
487bool
489 Bridge* nextBridge = this->nextBridge();
490 return nextBridge != NULL;
491}
492
493
494/**
495 * Returns the next bus from the location point of view.
496 *
497 * @return The next bus.
498 * @exception InstanceNotFound If the bus is the last in the chain.
499 */
500Bus*
502 Bridge* nextBridge = this->nextBridge();
503 if (nextBridge != NULL) {
504 return nextBridge->nextBus();
505 } else {
506 string procName = "Bus::nextBus";
507 throw InstanceNotFound(__FILE__, __LINE__, procName);
508 }
509}
510
511/**
512 * Returns the previous bus from the location point of view.
513 *
514 * @return The previous bus.
515 * @exception InstanceNotFound If the bus is the first in the chain.
516 */
517Bus*
519 Bridge* prevBridge = previousBridge();
520 if (prevBridge != NULL) {
521 return prevBridge->previousBus();
522 } else {
523 string procName = "Bus::previousBus";
524 throw InstanceNotFound(__FILE__, __LINE__, procName);
525 }
526}
527
528/**
529 * Checks if the bus can read from the given bus.
530 *
531 * That is, checks if the given bus is source bus of this bus.
532 *
533 * @param bus The bus.
534 * @return True if this bus can read from the given bus.
535 */
536bool
537Bus::canRead(const Bus& bus) const {
538 BridgeTable::const_iterator iter = sourceBridges_.begin();
539 while (iter != sourceBridges_.end()) {
540 if ((*iter)->sourceBus() == &bus) {
541 return true;
542 }
543 iter++;
544 }
545 return false;
546}
547
548
549/**
550 * Checks if the bus can write to the given bus.
551 *
552 * That is, checks if the given bus is destination bus of this bus.
553 *
554 * @param bus The bus.
555 * @return True if this bus can write to the given bus.
556 */
557bool
558Bus::canWrite(const Bus& bus) const {
559 BridgeTable::const_iterator iter = destinationBridges_.begin();
560 while (iter != destinationBridges_.end()) {
561 if ((*iter)->destinationBus() == &bus) {
562 return true;
563 }
564 iter++;
565 }
566 return false;
567}
568
569
570/**
571 * Check if the bus can both read from and write to the given bus.
572 *
573 * That is, checks if the given bus is joined by a bidirectional bridge to
574 * this bus.
575 *
576 * @param bus The bus.
577 * @return True if this bus can both read from and write to the given bus.
578 */
579bool
580Bus::canReadWrite(const Bus& bus) const {
581 return canWrite(bus) && canRead(bus);
582}
583
584
585/**
586 * Adds a source bridge for the bus.
587 *
588 * This method can be called from methods of Bridge only. Do not call this
589 * method.
590 *
591 * @param bridge The source bridge to add.
592 */
593void
595
596 // run time check: can be called from Bridge methods only
597 assert(bridge.destinationBus() == NULL);
598
599 assert(sourceBridges_.size() < 2);
600 sourceBridges_.push_back(&bridge);
601}
602
603
604/**
605 * Adds a destination bridge for the bus.
606 *
607 * This method can be called from methods of Bridge only. Do not call this
608 * method.
609 *
610 * @param bridge The destination bridge to add.
611 */
612void
614
615 // run time check: can be called from Bridge methods only
616 assert(bridge.sourceBus() == NULL);
617
618 assert(destinationBridges_.size() < 2);
619 destinationBridges_.push_back(&bridge);
620}
621
622
623/**
624 * Removes a source bridge from the bus.
625 *
626 * This method can be called from Bridge destructor only. Do not call this
627 * method.
628 *
629 * @param bridge The source bridge to remove.
630 */
631void
633
634 // run time check: can be called from Bridge destructor only
635 assert(bridge.destinationBus() == NULL);
636
638 sourceBridges_, &bridge);
639 assert(removed);
640}
641
642
643/**
644 * Removes a destination bridge from the bus.
645 *
646 * This method can be called from Bridge destructor only. Do not call this
647 * method.
648 *
649 * @param bridge The destination bridge to remove.
650 */
651void
653
654 // run time check: can be called from Bridge destructor only
655 assert(bridge.sourceBus() == NULL);
656
658 destinationBridges_, &bridge);
659 assert(removed);
660}
661
662
663/**
664 * Registers the bus to a machine.
665 *
666 * @param mach Machine to which the bus is going to be registered.
667 * @exception ComponentAlreadyExists If the given machine already has another
668 * bus by the same name.
669 */
670void
672 internalSetMachine(mach);
673 mach.addBus(*this);
674}
675
676/**
677 * Removes registration of the bus from its current machine.
678 *
679 * Detaches all the sockets attached to the bus and deletes all the guards and
680 * modifies instruction templates to not use this bus.
681 */
682void
684
685 Machine* mach = machine();
686
687 if (mach == NULL) {
688 return;
689 }
690
692
693 // detach all sockets
694 SegmentTable::iterator iter = segments_.begin();
695 while (iter != segments_.end()) {
696 (*iter)->detachAllSockets();
697 iter++;
698 }
699
700 // delete bridges
701 Machine::BridgeNavigator bNavigator = mach->bridgeNavigator();
702 for (int i = 0; i < bNavigator.count();) {
703 if (bNavigator.item(i)->sourceBus() == this ||
704 bNavigator.item(i)->destinationBus() == this) {
705 // deleting bridge removes it automatically from the container,
706 // no iterator increment needed
707 delete bNavigator.item(i);
708 } else {
709 i++;
710 }
711 }
712
713 // delete the template slot that uses the bus
716 for (int i = 0; i < itNav.count(); i++) {
717 InstructionTemplate* it = itNav.item(i);
718 it->removeSlot(name());
719 }
720
721 mach->removeBus(*this);
722}
723
724
725
726/**
727 * Adds the given segment to this bus.
728 *
729 * This method should be called by Segment constructor only.
730 *
731 * @param segment Segment to be added.
732 * @exception ComponentAlreadyExists If a segment with the same name as
733 * the given segment is already existing
734 * in this bus.
735 */
736void
738 // run time check: can be called from Segment constructor only
739 assert(segment.parentBus() == NULL);
740
741 if (hasSegment(segment.name())) {
742 string procname = "Bus::addSegment";
743 throw ComponentAlreadyExists(__FILE__, __LINE__, procname);
744 } else {
745 segments_.push_back(&segment);
746 }
747}
748
749/**
750 * Removes the given segment from the bus.
751 *
752 * This method should be called by Segment destructor only.
753 *
754 * @param segment Segment to be removed.
755 */
756void
758
759 // run time check: can be called from Segment destructor only
760 assert(segment.parentBus() == NULL);
761
763 assert(removed);
764}
765
766
767/**
768 * Saves the contents to an ObjectState tree.
769 *
770 * @return Root of the created tree.
771 */
774
775 ObjectState* busState = Component::saveState();
776
777 // change the name of the ObjectState
778 busState->setName(OSNAME_BUS);
779
780 // set attributes
781 busState->setAttribute(OSKEY_WIDTH, width_);
785 } else if (extensionMode_ == Machine::ZERO) {
787 }
788
789 // add segments
790 for (int i = 0; i < segmentCount(); i++) {
791 Segment* seg = segment(i);
792 busState->addChild(seg->saveState());
793 }
794
795 // save guards
796 for (int i = 0; i < guardCount(); i++) {
797 Guard* currentGuard = guard(i);
798 busState->addChild(currentGuard->saveState());
799 }
800
801 return busState;
802}
803
804
805/**
806 * Loads the state of the object from the given ObjectState instance.
807 *
808 * @param state The ObjectState instance.
809 * @exception ObjectStateLoadingException If the name of this bus becomes the
810 * same as an existing bus in the
811 * same machine or if generating
812 * references to other components did
813 * not succeed.
814 */
815void
819
820 // load state without references to other machine parts
821 try {
823
824 // create guards and load states of segments
825 for (int i = 0; i < state->childCount(); i++) {
826 ObjectState* childState = state->child(i);
827 if (childState->name() == PortGuard::OSNAME_PORT_GUARD) {
828 // guard is registered automatically
829 new PortGuard(childState, *this);
830 } else if (childState->name() ==
832 // guard is registered automatically
833 new RegisterGuard(childState, *this);
834 } else if (childState->name() ==
836 // guard is registered automatically.
837 new UnconditionalGuard(childState, *this);
838 } else if (childState->name() == Segment::OSNAME_SEGMENT) {
839 string segmentName =
841 Segment* segment = this->segment(segmentName);
842 segment->loadState(childState);
843 }
844 }
845 } catch (Exception& exception) {
846 const string procName = "Bus::loadState";
848 __FILE__, __LINE__, procName, exception.errorMessage());
849 }
850}
851
852/**
853 * Loads the state of the object from the given ObjectState tree without
854 * references to other components/subcomponents.
855 *
856 * @param state Root node of the ObjectState tree.
857 * @exception ObjectStateLoadingException If a bus by the same name is
858 * already registered to the same
859 * machine or if the given ObjectState
860 * tree is invalid.
861 */
862void
864 const string procName = "Bus::loadStateWithoutReferences";
865
866 if (state->name() != OSNAME_BUS) {
868 __FILE__, __LINE__, procName,
869 "Invalid XML object state for a bus, name: " + state->name());
870 }
871
873
874 // read attributes
875 try {
878 string extensionMode = state->stringAttribute(OSKEY_EXTENSION);
879 if (extensionMode == OSVALUE_SIGN) {
881 } else if (extensionMode == OSVALUE_ZERO) {
883 } else {
884 throw ObjectStateLoadingException(__FILE__, __LINE__, procName);
885 }
886 } catch (Exception& e) {
887 throw ObjectStateLoadingException(__FILE__, __LINE__, procName,
888 e.errorMessage());
889 }
890
891 // create all segments, guards are not created because they are
892 // completely useless without references
893 for (int i = 0; i < state->childCount(); i++) {
894 ObjectState* child = state->child(i);
895 if (child->name() == Segment::OSNAME_SEGMENT) {
896 try {
897 // segment is attached automatically
898 new Segment(child, *this);
899 } catch (const ComponentAlreadyExists&) {
900 MOMTextGenerator textGen;
901 format errorMsg = textGen.text(
903 errorMsg % child->stringAttribute(Segment::OSKEY_NAME) %
904 name();
906 __FILE__, __LINE__, procName, errorMsg.str());
907 }
908 }
909 }
910
911 adjustSegmentChain(state);
912}
913
914/**
915 * Deletes all the segments.
916 */
917void
919 // segment destructor removes the pointer from the table
920 while (segments_.size() > 0) {
921 delete segments_[0];
922 }
923}
924
925
926/**
927 * Deletes all the guards.
928 */
929void
931 // guard destructor removes the pointer from the table
932 while (guards_.size() > 0) {
933 delete guards_[0];
934 }
935}
936
937
938/**
939 * Returns a bridge that joins this bus and the previous bus of this bus.
940 *
941 * If there is two such bridges, returns one of them. If there is no such a
942 * bridge, returns NULL.
943 *
944 * @return Previous bridge or NULL.
945 */
946Bridge*
948 Bridge* prevBridge = previousBridge(sourceBridges_);
949 if (prevBridge == NULL) {
951 }
952 return prevBridge;
953}
954
955
956/**
957 * Returns a bridge that joins this bus and the next bus of this bus.
958 *
959 * If there is two such bridges, returns one of them. If there is no such a
960 * bridge, returns NULL.
961 *
962 * @return Next bridge or NULL.
963 */
964Bridge*
967 if (nextBridge == NULL) {
969 }
970 return nextBridge;
971}
972
973
974/**
975 * Returns a bridge that joins this bus and the previous bus of this bus.
976 *
977 * Returns NULL if such a bridge does not exist.
978 *
979 * @param bridge The bridge table to look for the bridge.
980 * @return The previous bridge.
981 */
982Bridge*
983Bus::previousBridge(const BridgeTable& bridges) const {
984 BridgeTable::const_iterator iter = bridges.begin();
985 while (iter != bridges.end()) {
986 Bridge* bridge = *iter;
987 if (bridge->nextBus() == this) {
988 return bridge;
989 }
990 iter++;
991 }
992 return NULL;
993}
994
995
996/**
997 * Returns a bridge that joins this bus and the next bus of this bus.
998 *
999 * Returns NULL if such a bridge does not exist.
1000 *
1001 * @param bridge The bridge table to look for the bridge.
1002 * @return The next bridge.
1003 */
1004Bridge*
1005Bus::nextBridge(const BridgeTable& bridges) const {
1006 BridgeTable::const_iterator iter = bridges.begin();
1007 while (iter != bridges.end()) {
1008 Bridge* bridge = *iter;
1009 if (bridge->previousBus() == this) {
1010 return bridge;
1011 }
1012 iter++;
1013 }
1014 return NULL;
1015}
1016
1017
1018/**
1019 * Adjusts the order of segments according to the order represented by the
1020 * given ObjectState tree.
1021 *
1022 * @param busState ObjectState tree representing the state of this bus.
1023 * @exception ObjectStateLoadingException If the segment chain is erroneus in
1024 * the given ObjectState tree.
1025 */
1026void
1028 const string procName = "Bus::adjustSegmentChain";
1029
1030 if (segmentCount() == 0) {
1032 return;
1033 }
1034
1035 MOMTextGenerator textGenerator;
1036
1037 try {
1038 // find the last segment, the segment that has no destination
1039 Segment* lastSegment = NULL;
1040 for (int i = 0; i < busState->childCount(); i++) {
1041 ObjectState* childState = busState->child(i);
1042 if (childState->name() == Segment::OSNAME_SEGMENT &&
1044 string lastSegmentName =
1046 lastSegment = segment(lastSegmentName);
1047 break;
1048 }
1049 }
1050
1051 // if last segment was not found, throw
1052 if (lastSegment == NULL) {
1053 format errorMsg = textGenerator.text(
1055 errorMsg % name();
1057 __FILE__, __LINE__, procName, errorMsg.str());
1058 }
1059
1060 Segment* destSegment = lastSegment;
1061 int modifications = 0;
1062
1063 // in the following loop, find a segment whose destination should be
1064 // lastSegment and set it in front of that segment
1065 while (modifications < segmentCount() - 1) {
1066 bool chainModified = false;
1067 for (int i = 0; i < busState->childCount(); i++) {
1068 ObjectState* childState = busState->child(i);
1069 if (childState->name() == Segment::OSNAME_SEGMENT &&
1071 string destName = childState->stringAttribute(
1073 if (destName == destSegment->name()) {
1074 string thisName = childState->
1075 stringAttribute(Segment::OSKEY_NAME);
1076 Segment* thisSegment = segment(thisName);
1077 thisSegment->moveBefore(*destSegment);
1078 destSegment = thisSegment;
1079 modifications++;
1080 chainModified = true;
1081 }
1082 }
1083 }
1084
1085 // if the source segment was not found and the segment chain is not
1086 // set completely yet, throw
1087 if (!chainModified && modifications < segmentCount() - 1) {
1088 format errorMsg = textGenerator.text(
1090 errorMsg % name() % destSegment->name();
1092 __FILE__, __LINE__, procName, errorMsg.str());
1093 }
1094 }
1095 } catch (Exception& exception) {
1097 __FILE__, __LINE__, procName, exception.errorMessage());
1098 }
1099}
1100
1101/**
1102 * Checks is this bus architecture equal with the given bus.
1103 *
1104 * Architecture equality means that buses have same widths, immediate widths,
1105 * extension modes, number of segments and same guards. Bridges are not checked.
1106 *
1107 * @param bus Bus to compare with.
1108 * @return True if the buses are architecture equal.
1109 */
1110bool
1112
1113 if (width() != bus.width() ||
1114 immediateWidth() != bus.immediateWidth() ||
1115 signExtends() != bus.signExtends() ||
1116 segmentCount() != bus.segmentCount()) {
1117 return false;
1118 }
1119 for (int i = 0; i < guardCount(); i++) {
1120 bool match = false;
1121
1122 // check if there is matching guard in another bus
1123 for (int j = 0; j < bus.guardCount(); j++) {
1124 if (guard(i)->isEqual(*bus.guard(j))) {
1125 match = true;
1126 break;
1127 }
1128 }
1129
1130 // if no matching guard was not found buses are not equal
1131 if (match == false) {
1132 return false;
1133 }
1134 // otherwise continue to next guard
1135 }
1136 return true;
1137}
1138
1139/**
1140 * Copies the bus.
1141 *
1142 * @return Copy of the Bus.
1143 */
1144Bus*
1145Bus::copy() const {
1146 ObjectState* newBusState = saveState();
1147 Bus* newBus = new Bus(newBusState);
1148
1149 delete newBusState;
1150 newBusState = NULL;
1151 return newBus;
1152}
1153
1154void
1155Bus::copyGuardsTo(Bus& other) const {
1156 for (int i = 0; i < guardCount(); ++i) {
1157 if (!other.hasGuard(*guard(i)))
1158 guard(i)->copyTo(other);
1159 }
1160}
1161
1162}
#define __func__
#define assert(condition)
static bool removeValueIfExists(ContainerType &aContainer, const ElementType &aKey)
std::string errorMessage() const
Definition Exception.cc:123
bool hasAttribute(const std::string &name) const
void setName(const std::string &name)
void setAttribute(const std::string &name, const std::string &value)
bool hasChild(const std::string &name) const
ObjectState * child(int index) const
void addChild(ObjectState *child)
std::string stringAttribute(const std::string &name) const
int intAttribute(const std::string &name) const
std::string name() const
int childCount() const
Bus * destinationBus() const
Bus * sourceBus() const
Bus * nextBus() const
Definition Bridge.cc:179
Bus * previousBus() const
Definition Bridge.cc:164
Bridge * nextBridge() const
Definition Bus.cc:965
void adjustSegmentChain(const ObjectState *busState)
Definition Bus.cc:1027
void addGuard(Guard &guard)
Definition Bus.cc:410
virtual bool hasSegment(const std::string &name) const
Definition Bus.cc:284
Machine::Extension extensionMode_
Extension mode applied to the inline immediate word.
Definition Bus.hh:152
virtual Segment * segment(int index) const
Definition Bus.cc:329
virtual Bus * previousBus() const
Definition Bus.cc:518
void deleteAllGuards()
Definition Bus.cc:930
virtual bool canReadWrite(const Bus &bus) const
Definition Bus.cc:580
std::vector< Bridge * > BridgeTable
Definition Bus.hh:134
int width_
Bit width of the bus.
Definition Bus.hh:148
virtual void loadState(const ObjectState *state)
Definition Bus.cc:816
virtual ObjectState * saveState() const
Definition Bus.cc:773
virtual void clearSourceBridge(Bridge &bridge)
Definition Bus.cc:632
Bridge * previousBridge() const
Definition Bus.cc:947
BridgeTable sourceBridges_
Contains the source bridges (max 2).
Definition Bus.hh:160
virtual void setName(const std::string &name)
Definition Bus.cc:196
virtual bool canWrite(const Bus &bus) const
Definition Bus.cc:558
virtual Bus * copy() const
Definition Bus.cc:1145
virtual void setImmediateWidth(int width)
Definition Bus.cc:241
GuardTable guards_
Contains all guards of the bus.
Definition Bus.hh:155
int width() const
Definition Bus.cc:149
BridgeTable destinationBridges_
Contains the destination bridges (max 2).
Definition Bus.hh:162
int immediateWidth() const
Definition Bus.cc:160
virtual void addSegment(Segment &segment)
Definition Bus.cc:737
virtual void setSignExtends()
Definition Bus.cc:262
static const std::string OSKEY_EXTENSION
ObjectState attribute key for extension mode.
Definition Bus.hh:122
virtual bool isConnectedTo(const Socket &socket) const
Definition Bus.cc:303
virtual bool isArchitectureEqual(const Bus &bus) const
Definition Bus.cc:1111
int immWidth_
Bit width of the inline immediate word.
Definition Bus.hh:150
static const std::string OSKEY_WIDTH
ObjectState attribute key for bus width.
Definition Bus.hh:118
bool signExtends() const
Definition Bus.cc:171
virtual int position() const
Definition Bus.cc:127
bool hasGuard(const Guard &guard) const
Definition Bus.cc:393
virtual void clearDestinationBridge(Bridge &bridge)
Definition Bus.cc:652
virtual void setZeroExtends()
Definition Bus.cc:253
Guard * guard(int index) const
Definition Bus.cc:456
virtual bool hasPreviousBus() const
Definition Bus.cc:473
virtual void unsetMachine()
Definition Bus.cc:683
bool zeroExtends() const
Definition Bus.cc:182
virtual void setDestinationBridge(Bridge &bridge)
Definition Bus.cc:613
void loadStateWithoutReferences(const ObjectState *state)
Definition Bus.cc:863
virtual void removeGuard(Guard &guard)
Definition Bus.cc:428
virtual bool hasNextBus() const
Definition Bus.cc:488
static const std::string OSNAME_BUS
ObjectState name for Bus ObjectState.
Definition Bus.hh:116
virtual void setSourceBridge(Bridge &bridge)
Definition Bus.cc:594
virtual void setExtensionMode(const Machine::Extension extension)
Definition Bus.cc:271
static const std::string OSVALUE_ZERO
ObjectState attribute key for zero extension.
Definition Bus.hh:126
virtual int segmentCount() const
Definition Bus.cc:385
void deleteAllSegments()
Definition Bus.cc:918
virtual void setMachine(Machine &mach)
Definition Bus.cc:671
virtual ~Bus()
Definition Bus.cc:113
int guardCount() const
Definition Bus.cc:441
static const std::string OSVALUE_SIGN
ObjectState attribute value for sign extension.
Definition Bus.hh:124
Bus(const std::string &name, int width, int immWidth, Machine::Extension extensionMode)
Definition Bus.cc:74
virtual void copyGuardsTo(Bus &other) const
Definition Bus.cc:1155
virtual Bus * nextBus() const
Definition Bus.cc:501
virtual bool canRead(const Bus &bus) const
Definition Bus.cc:537
static const std::string OSKEY_IMMWIDTH
ObjectState attribute key for immediate width.
Definition Bus.hh:120
virtual void removeSegment(Segment &segment)
Definition Bus.cc:757
virtual void setWidth(int width)
Definition Bus.cc:223
SegmentTable segments_
Contains all the segments of the bus.
Definition Bus.hh:157
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 TCEString name() const
virtual ObjectState * saveState() const
virtual bool isEqual(const Guard &guard) const =0
virtual Bus * parentBus() const
virtual ObjectState * saveState() const
Definition Guard.cc:149
virtual void copyTo(Bus &parentBus) const =0
virtual void removeSlot(const std::string &slotName)
ComponentType * item(int index) const
virtual BridgeNavigator bridgeNavigator() const
Definition Machine.cc:404
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition Machine.cc:428
virtual void removeBus(Bus &bus)
Definition Machine.cc:477
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual void addBus(Bus &bus)
Definition Machine.cc:139
@ SIGN
Sign extension.
Definition Machine.hh:82
@ ZERO
Zero extension.
Definition Machine.hh:81
static const std::string OSNAME_PORT_GUARD
ObjectState name for PortGuard ObjectState.
Definition Guard.hh:117
static const std::string OSNAME_REGISTER_GUARD
ObjectState name for RegisterGuard.
Definition Guard.hh:159
virtual void loadState(const ObjectState *state)
Definition Segment.cc:448
virtual ObjectState * saveState() const
Definition Segment.cc:421
Segment * destinationSegment() const
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
static const std::string OSNAME_SEGMENT
ObjectState name for Segment.
Definition Segment.hh:87
bool hasSourceSegment() const
Definition Segment.cc:388
static const std::string OSKEY_NAME
ObjectState attribute key for segment name.
Definition Segment.hh:89
std::string name() const
Bus * parentBus() const
static const std::string OSNAME_UNCONDITIONAL_GUARD
ObjectState name for UnconditionalGuard.
Definition Guard.hh:195
virtual boost::format text(int textId)