OpenASIP 2.2
Loading...
Searching...
No Matches
InstructionTemplate.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2014 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 InstructionTemplate.cc
26 *
27 * Implementation of class InstructionTemplate.
28 *
29 * @author Lasse Laasonen 2004 (lasse.laasonen-no.spam-tut.fi)
30 * @author Pekka Jääskeläinen 2014
31 */
32
33#include <set>
34
36#include "TemplateSlot.hh"
37#include "Machine.hh"
38#include "Bus.hh"
39#include "ImmediateUnit.hh"
40#include "MOMTextGenerator.hh"
41#include "ContainerTools.hh"
42#include "SequenceTools.hh"
43#include "ObjectState.hh"
44
45using std::string;
46using std::set;
47using boost::format;
48
49namespace TTAMachine {
50
51const string InstructionTemplate::OSNAME_INSTRUCTION_TEMPLATE = "i_template";
52
53/**
54 * Constructor.
55 *
56 * Creates an empty instruction template. Add slots to make the instruction
57 * template non-empty. An empty instruction template represents the encoding
58 * format of instructions that don't specify any bits of a long immediate or
59 * any immediate register-write action.
60 *
61 * @param name Name of the instruction template.
62 * @param owner The machine to which the instruction template is going to be
63 * registered.
64 * @exception ComponentAlreadyExists If the given machine already contains
65 * another instruction template by the same
66 * name.
67 * @exception InvalidName If the given name is not a valid component name.
68 */
70 : Component(name) {
71 setMachine(owner);
72}
73
74/**
75 * Constructor.
76 *
77 * Loads the state of the instruction template completely from the given
78 * ObjectState tree.
79 *
80 * @param state The ObjectState instance.
81 * @param owner The machine to which the instruction template is going to be
82 * registered.
83 * @exception ObjectStateLoadingException If the given ObjectState instance
84 * is invalid or if there exists an
85 * instruction template by the same
86 * as the upcoming name in the
87 * machine or if references to other
88 * components cannot be resolved.
89 */
91 const ObjectState* state, Machine& owner)
92 : Component(state) {
93 const string procName = "InstructionTemplate::InstructionTemplate";
94
95 try {
96 setMachine(owner);
97 } catch (const ComponentAlreadyExists&) {
98 MOMTextGenerator textGenerator;
99 format errorMsg = textGenerator.text(
101 errorMsg % name();
103 __FILE__, __LINE__, procName, errorMsg.str());
104 }
105
106 try {
107 loadState(state);
108 } catch (const ObjectStateLoadingException&) {
109 unsetMachine();
110 throw;
111 }
112}
113
114/**
115 * Destructor.
116 *
117 * Deletes all the slots of this instruction template too.
118 */
122
123
124/**
125 * Sets the name of the instruction template.
126 *
127 * @param name Name of the instruction template.
128 * @exception ComponentAlreadyExists If an instruction template with the
129 * given name is already in the same
130 * machine.
131 * @exception InvalidName If the given name is not a valid component name.
132 */
133void
134InstructionTemplate::setName(const string& name) {
135 if (name == this->name()) {
136 return;
137 }
138
139 if (machine() != NULL) {
140 if (machine()->instructionTemplateNavigator().hasItem(name)) {
141 string procName = "InstructionTemplate::setName";
142 throw ComponentAlreadyExists(__FILE__, __LINE__, procName);
143 } else {
145 }
146 } else {
148 }
149}
150
151/**
152 * Adds a template slot.
153 *
154 * The given bit width must be greater than 0.
155 *
156 * @param slotName Transport bus in which (part of) part of the long
157 * immediate is stored.
158 * @param width The number of long immediate bits that are encoded on the
159 * slot.
160 * @param dstUnit Destination immediate unit.
161 * @exception InstanceNotFound If the machine does not have a bus or
162 * immediate slot with the given name.
163 * @exception IllegalRegistration If the given destination unit is not
164 * registered to the same machine.
165 * @exception ComponentAlreadyExists If the given slot is already in use.
166 * @exception OutOfRange If the given bit width is out of range.
167 */
168void
170 const std::string& slotName, int width, ImmediateUnit& dstUnit) {
171 const string procName = "InstructionTemplate::addSlot";
172
173 ensureRegistration(dstUnit);
174
175 if (width <= 0) {
176 throw OutOfRange(__FILE__, __LINE__, procName);
177 }
178
179 if (templateSlot(slotName) != NULL) {
180 throw ComponentAlreadyExists(__FILE__, __LINE__, procName);
181 }
182
183 if (machine()->busNavigator().hasItem(slotName)) {
184 Bus* bus = machine()->busNavigator().item(slotName);
185 slots_.push_back(new TemplateSlot(*bus, width, dstUnit));
186 } else if (machine()->immediateSlotNavigator().hasItem(slotName)) {
188 slotName);
189 slots_.push_back(new TemplateSlot(*slot, width, dstUnit));
190 } else {
191 throw InstanceNotFound(__FILE__, __LINE__, procName);
192 }
193}
194
195/**
196 * Removes the template slot which uses the given slot.
197 *
198 * @param slotName Name of the slot.
199 */
200void
201InstructionTemplate::removeSlot(const std::string& slotName) {
202 TemplateSlot* slot = templateSlot(slotName);
203 if (slot != NULL) {
205 assert(removed);
206 }
207}
208
209
210/**
211 * Removes the template slots that has the given immediate unit as
212 * destination unit.
213 *
214 * @param dstUnit The destination immediate unit.
215 */
216void
218 for (SlotTable::iterator iter = slots_.begin(); iter != slots_.end();) {
219 TemplateSlot* slot = *iter;
220 if (slot->destination() == &dstUnit) {
221 delete slot;
222 SlotTable::iterator next = slots_.erase(iter);
223 iter = next;
224 } else {
225 iter++;
226 }
227 }
228}
229
230/**
231 * Return the total number of slots in the template.
232 *
233 * @return The total number of slots in the template.
234 */
235int
237 return slots_.size();
238}
239
240/**
241 * Return the slot in the given index.
242 *
243 * @param index Index of slot.
244 * @return The slot in the given index.
245 * @exception OutOfRange If index is equal to or greater than the number
246 * of slots in the template.
247 */
250 if (index < 0 || index >= static_cast<int>(slots_.size())) {
251 string msg = "Slot index out of bounds.";
252 throw OutOfRange(__FILE__, __LINE__, __func__, msg);
253 } else {
254 return slots_[index];
255 }
256}
257
258/**
259 * Returns true if the instruction template uses the given slot.
260 *
261 * @param slotName Name of the slot.
262 * @return True if the instruction template uses the given slot.
263 */
264bool
265InstructionTemplate::usesSlot(const std::string& slotName) const {
266 TemplateSlot* slot = templateSlot(slotName);
267 return (slot != NULL);
268}
269
270
271/**
272 * Returns true if the instruction template reserves the template slot given
273 * by the slotName input argument for long immediate bits that are written
274 * into a register of the given immediate unit.
275 *
276 * @param slotName Name of the slot.
277 * @param dstUnit The destination immediate unit.
278 */
279bool
281 const std::string& slotName,
282 const ImmediateUnit& dstUnit) const {
283
284 TemplateSlot* slot = templateSlot(slotName);
285 if (slot == NULL) {
286 return false;
287 }
288
289 return (slot->destination() == &dstUnit);
290}
291
292
293/**
294 * Returns how many immediate units are written in parallel by this
295 * instruction template.
296 *
297 * @return The number of immediate units.
298 */
299int
301
302 std::set<ImmediateUnit*> destinations;
303
304 for (SlotTable::const_iterator iter = slots_.begin();
305 iter != slots_.end(); iter++) {
306 TemplateSlot* slot = *iter;
307 destinations.insert(slot->destination());
308 }
309
310 return destinations.size();
311}
312
313
314/**
315 * Checks whether the given immediate unit is one of the immediate
316 * destinations in this instruction template.
317 *
318 * @param dstUnit The immediate unit to check.
319 * @return True if the given immediate unit is a destination, otherwise
320 * false.
321 */
322bool
324 const ImmediateUnit& dstUnit) const {
325
326 for (SlotTable::const_iterator iter = slots_.begin();
327 iter != slots_.end(); iter++) {
328 TemplateSlot* slot = *iter;
329 if (slot->destination() == &dstUnit) {
330 return true;
331 }
332 }
333 return false;
334}
335
336
337/**
338 * Returns the destination unit of the given slot.
339 *
340 * @param slotName Name of the slot.
341 * @return The destination unit.
342 * @exception InstanceNotFound If the instruction template does not use
343 * the given slot to encode long immediate.
344 */
346InstructionTemplate::destinationOfSlot(const std::string& slotName) const {
347 for (SlotTable::const_iterator iter = slots_.begin();
348 iter != slots_.end(); iter++) {
349 TemplateSlot* slot = *iter;
350 if (slot->slot() == slotName) {
351 return slot->destination();
352 }
353 }
354
355 const string procName = "InstructionTemplate::destinationOfSlot";
356 throw InstanceNotFound(__FILE__, __LINE__, procName);
357}
358
359/**
360 * Tells the number of slots that are used to encode the long immediate
361 * which is written to the given destination unit.
362 *
363 * @param dstUnit The destination unit.
364 * @return The number of slots.
365 */
366int
368 int slots(0);
369 for (SlotTable::const_iterator iter = slots_.begin();
370 iter != slots_.end(); iter++) {
371 TemplateSlot* slot = *iter;
372 if (slot->destination() == &dstUnit) {
373 slots++;
374 }
375 }
376 return slots;
377}
378
379
380/**
381 * By the given index, returns the slot used to encode a part of the long
382 * immediate that is to be written to the given destination unit.
383 *
384 * The slot are returned in the same order the parts of the long immediates
385 * are concatenated when they are written to the destination registers. The
386 * most significant end of the immediate is returned by index 0.
387 *
388 * @param dstUnit The destination unit.
389 * @param index The index.
390 * @exception OutOfRange If the given index is negative or not smaller than
391 * the number of slots that are written to the given
392 * destination unit.
393 */
394std::string
396 const ImmediateUnit& dstUnit, int index) const {
397 if (index < 0 || index >= numberOfSlots(dstUnit)) {
398 const string procName = "InstructionTemplate::slotOfDestination";
399 throw OutOfRange(__FILE__, __LINE__, procName);
400 }
401
402 int count(0);
403
404 for (SlotTable::const_iterator iter = slots_.begin();
405 iter != slots_.end(); iter++) {
406 TemplateSlot* slot = *iter;
407 if (slot->destination() == &dstUnit) {
408 if (count == index) {
409 return slot->slot();
410 } else {
411 count++;
412 }
413 }
414 }
415
416 assert(false);
417 return NULL;
418}
419
420/**
421 * Returns the bit width of the widest long immediate that can be encoded by
422 * this instruction template.
423 *
424 * @return The bit width.
425 */
426int
428
429 int maxWidth(0);
430
433 for (int i = 0; i < iuNav.count(); i++) {
434 ImmediateUnit* iu = iuNav.item(i);
435 if (supportedWidth(*iu) > maxWidth) {
436 maxWidth = supportedWidth(*iu);
437 }
438 }
439
440 return maxWidth;
441}
442
443
444/**
445 * Returns the bit width of the widest long immediate that can be encoded by
446 * this instruction template and that writes a register of the given
447 * immediate unit.
448 *
449 * @param dstUnit The immediate unit.
450 * @return The bit width.
451 */
452int
454
455 int totalWidth(0);
456
457 for (SlotTable::const_iterator iter = slots_.begin();
458 iter != slots_.end(); iter++) {
459 TemplateSlot* slot = *iter;
460 if (slot->destination() == &dstUnit) {
461 totalWidth += slot->width();
462 }
463 }
464
465 return totalWidth;
466}
467
468
469/**
470 * Returns the bit width of the long immediate that can be encoded in the
471 * given slot by this instruction template.
472 *
473 * @param slotName Name of the slot.
474 * @return The bit width.
475 */
476int
477InstructionTemplate::supportedWidth(const std::string& slotName) const {
478 TemplateSlot* slot = templateSlot(slotName);
479 if (slot == NULL) {
480 return 0;
481 } else {
482 return slot->width();
483 }
484}
485
486
487/**
488 * Checks whether the instruction template is an empty instruction template
489 * which cannot have any slots.
490 *
491 * @return True if the instruction template is empty, otherwise false.
492 */
493bool
495 return (slots_.size() == 0);
496}
497
498
499/**
500 * Adds the instruction template to the given machine.
501 *
502 * @param machine Machine to which the instruction template is added.
503 * @exception ComponentAlreadyExists If there already is another instruction
504 * template by the same name or another
505 * empty instruction template in the given
506 * machine.
507 */
508void
513
514/**
515 * Removes the instruction template from its machine.
516 *
517 * The instruction template is also deleted because it cannot be alone.
518 * It must be registered to a machine.
519 */
520void
523 Machine* mach = machine();
524 assert(mach != NULL);
526 mach->deleteInstructionTemplate(*this);
527}
528
529
530/**
531 * Saves its state to an ObjectState tree.
532 *
533 * @return The newly created ObjectState tree.
534 */
539 SlotTable::const_iterator iter = slots_.begin();
540 while (iter != slots_.end()) {
541 TemplateSlot* templateSlot = *iter;
542 ObjectState* slotState = templateSlot->saveState();
543 state->addChild(slotState);
544 iter++;
545 }
546 return state;
547}
548
549
550/**
551 * Loads its state from the given ObjectState tree.
552 *
553 * @param state The ObjectState tree.
554 * @exception ObjectStateLoadingException If the given ObjectState tree is
555 * invalid.
556 */
557void
559 const string procName = "InstructionTemplate::loadState";
560
561 if (state->name() != OSNAME_INSTRUCTION_TEMPLATE) {
562 throw ObjectStateLoadingException(__FILE__, __LINE__, procName);
563 }
564
567
568 // add template slots
569 try {
570 for (int i = 0; i < state->childCount(); i++) {
571 MOMTextGenerator textGenerator;
572 ObjectState* child = state->child(i);
573
574 string slotName = child->stringAttribute(
576 if (!machine()->busNavigator().hasItem(slotName) &&
577 !machine()->immediateSlotNavigator().hasItem(slotName)) {
578 format errorMsg = textGenerator.text(
580 errorMsg % slotName % name();
582 __FILE__, __LINE__, procName, errorMsg.str());
583 }
584
586 int width = child->intAttribute(TemplateSlot::OSKEY_WIDTH);
587 string destination =
591 ImmediateUnit* iu = NULL;
592
593 try {
594 iu = iuNav.item(destination);
595 } catch (const InstanceNotFound&) {
596 format errorMsg = textGenerator.text(
598 errorMsg % destination % name();
600 __FILE__, __LINE__, procName, errorMsg.str());
601 }
602
603 addSlot(slotName, width, *iu);
604 }
605 }
606 } catch (const Exception& exception) {
608 __FILE__, __LINE__, procName, exception.errorMessage());
609 }
610}
611
612/**
613 * Deletes all the template slots.
614 */
615void
619
620
621/**
622 * Returns the template slot that uses slot with the given name.
623 *
624 * Returns NULL if no template slot uses the given slot.
625 *
626 * @param slotName Name of the slot.
627 * @return The template slot or NULL.
628 */
630InstructionTemplate::templateSlot(const std::string& slotName) const {
631 for (SlotTable::const_iterator iter = slots_.begin();
632 iter != slots_.end(); iter++) {
633 TemplateSlot* slot = *iter;
634 if (slot->slot() == slotName) {
635 return slot;
636 }
637 }
638 return NULL;
639}
640
641}
#define __func__
#define assert(condition)
TTAMachine::Machine * machine
the architecture definition of the estimated processor
static bool deleteValueIfExists(ContainerType &aContainer, const ElementType &aKey)
std::string errorMessage() const
Definition Exception.cc:123
void setName(const std::string &name)
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
static void deleteAllItems(SequenceType &aSequence)
virtual void setName(const std::string &name)
virtual Machine * machine() const
virtual void loadState(const ObjectState *state)
void internalSetMachine(Machine &machine)
virtual void ensureRegistration(const Component &component) const
virtual TCEString name() const
virtual ObjectState * saveState() const
virtual bool usesSlot(const std::string &slotName) const
virtual ImmediateUnit * destinationOfSlot(const std::string &slotName) const
SlotTable slots_
Contains all the slots of the instruction template.
virtual void addSlot(const std::string &slotName, int width, ImmediateUnit &dstUnit)
InstructionTemplate(const std::string &name, Machine &owner)
virtual bool isOneOfDestinations(const ImmediateUnit &dstUnit) const
virtual void removeSlot(const std::string &slotName)
virtual void setName(const std::string &name)
virtual void loadState(const ObjectState *state)
virtual bool destinationUsesSlot(const std::string &slotName, const ImmediateUnit &dstUnit) const
virtual TemplateSlot * slot(int index) const
virtual int numberOfSlots(const ImmediateUnit &dstUnit) const
virtual std::string slotOfDestination(const ImmediateUnit &dstUnit, int index) const
TemplateSlot * templateSlot(const std::string &slotName) const
virtual void removeSlots(const ImmediateUnit &dstUnit)
static const std::string OSNAME_INSTRUCTION_TEMPLATE
ObjectState name for instruction template.
virtual ObjectState * saveState() const
virtual void setMachine(Machine &machine)
ComponentType * item(int index) const
virtual ImmediateSlotNavigator immediateSlotNavigator() const
Definition Machine.cc:462
virtual void deleteInstructionTemplate(InstructionTemplate &instrTempl)
Definition Machine.cc:599
virtual void addInstructionTemplate(InstructionTemplate &instrTempl)
Definition Machine.cc:275
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
static const std::string OSNAME_TEMPLATE_SLOT
ObjectState name for template slot.
std::string slot() const
static const std::string OSKEY_SLOT
ObjectState attribute key for slot name.
static const std::string OSKEY_DESTINATION
ObjectState attribute key for destination.
ImmediateUnit * destination() const
static const std::string OSKEY_WIDTH
ObjectState attribute key for bit width.
ObjectState * saveState() const
virtual boost::format text(int textId)