OpenASIP 2.2
Loading...
Searching...
No Matches
BEMGenerator.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 BEMGenerator.cc
26 *
27 * Implementation of BEMGenerator class.
28 *
29 * @author Lasse Laasonen 2005 (lasse.laasonen-no.spam-tut.fi)
30 * @note rating: red
31 */
32
33#include <string>
34#include <set>
35#include <map>
36#include "BEMGenerator.hh"
37#include "BinaryEncoding.hh"
38#include "MoveSlot.hh"
39#include "ImmediateSlotField.hh"
42#include "DestinationField.hh"
43#include "SourceField.hh"
44#include "GuardField.hh"
45#include "SocketEncoding.hh"
46#include "BridgeEncoding.hh"
47#include "ImmediateEncoding.hh"
48#include "FUGuardEncoding.hh"
49#include "GPRGuardEncoding.hh"
51#include "NOPEncoding.hh"
52#include "SocketCodeTable.hh"
53#include "FUPortCode.hh"
54#include "RFPortCode.hh"
55#include "IUPortCode.hh"
56#include "MathTools.hh"
57#include "Machine.hh"
58#include "Segment.hh"
59#include "HWOperation.hh"
60#include "FUPort.hh"
61#include "Guard.hh"
62#include "MapTools.hh"
63#include "AssocTools.hh"
64#include "TemplateSlot.hh"
65#include "RISCVFields.hh"
66#include "InstructionFormat.hh"
70#include "TCEString.hh"
71
72using std::string;
73using std::pair;
74using std::set;
75using std::vector;
76using std::multiset;
77using std::map;
78using namespace TTAMachine;
79
80/**
81 * The constructor.
82 *
83 * @param machine The machine for which the binary encoding map will be
84 * generated.
85 */
87 machine_(&machine) {
88}
89
90
91/**
92 * The destructor.
93 */
96
97
98/**
99 * Generates the binary encoding map.
100 *
101 * @return The newly created binary encoding map.
102 */
105
106 BinaryEncoding* bem = new BinaryEncoding();
107
109 addTopLevelFields(*bem);
110 for (int i = 0; i < bem->moveSlotCount(); i++) {
111 MoveSlot& slot = bem->moveSlot(i);
112 addSubfields(slot);
113 }
114
115 return bem;
116}
117
118
119/**
120 * Adds the socket code tables to the given binary encoding map.
121 *
122 * @param bem The binary encoding map.
123 */
124void
127 for (int i = 0; i < socketNav.count(); i++) {
128 Socket* socket = socketNav.item(i);
131 if (suitable != NULL) {
132 assignSocketCodeTable(socket, suitable);
133 } else {
134 SocketCodeTable* table =
135 new SocketCodeTable(socket->name(), bem);
136 addPortCodes(*table, *socket);
138 }
139 }
140 }
141}
142
143
144/**
145 * Adds the top-level fields to the given binary encoding map.
146 *
147 * @param bem The binary encoding to be modified.
148 */
149void
151
152 // add immediate slots
155 for (int i = 0; i < isNav.count(); i++) {
156 ImmediateSlot* slot = isNav.item(i);
157 int width = slot->width();
158 if (width > 0) {
159 new ImmediateSlotField(slot->name(), width, bem);
160 }
161 }
162
163 // add move slots
165 for (int i = 0; i < busNav.count(); i++) {
166 Bus* bus = busNav.item(i);
167 new MoveSlot(bus->name(), bem);
168 }
169
170 // add long immediate destination register fields
172
173 // add long immediate control field
176
177 if (itNav.count() > 1) {
179 addEncodings(*field);
180 }
181
182 unsigned amountOfRCustomOps = 0;
183 unsigned amountOfR3RCustomOps = 0;
184
187
188 // For CVX-IF, make sure these are iterated in the correct order.
189 for (int i = 0; i < fNav.count(); i++) {
190 OperationTriggeredFormat* fTemp = fNav.item(i);
191 addRiscvFormat(fTemp, bem, amountOfRCustomOps, amountOfR3RCustomOps);
192 }
193}
194
195/**
196 * Adds a RISC-V format to the binary encoding map
197 *
198 * @param format The operation triggered format
199 * @param bem The binary encoding
200 */
201
202void
205 unsigned& amountOfRCustomOps, unsigned& amountOfR3RCustomOps) const {
206 std::string name = format->name();
207 InstructionFormat* instrFormat = new InstructionFormat(name, bem);
208 const unsigned OPC_CUSTOM_0 = 0b0001011;
209 const unsigned OPC_CUSTOM_1 = 0b0101011;
210
211 if (name == RISCVFields::RISCV_R_TYPE_NAME) {
213 new OperationTriggeredEncoding(std::string("rs1"), *instrFormat);
215 new OperationTriggeredEncoding(std::string("rs2"), *instrFormat);
217 new OperationTriggeredEncoding(std::string("rd"), *instrFormat);
218 new OperationTriggeredField(*rs1, 0, 15, 5);
219 new OperationTriggeredField(*rs2, 0, 20, 5);
220 new OperationTriggeredField(*rd, 0, 7, 5);
222 std::string("opcode"), *instrFormat);
223 new OperationTriggeredField(*opcode, 0, 0, 7);
224 new OperationTriggeredField(*opcode, 1, 12, 3);
225 new OperationTriggeredField(*opcode, 2, 25, 7);
226
227 // Reserve first few encodings for fixed special case
228 for (int i = 0; i < format->operationCount(); i++) {
229 const std::string op = format->operationAtIndex(i);
231 instrFormat->addOperation(op, RISCVFields::RISCVRTypeOperations.at(op));
232 } else {
233 unsigned int customEncoding = OPC_CUSTOM_0;
234 customEncoding += (amountOfRCustomOps << 7);
235 amountOfRCustomOps++;
236 // 10 bit encoding for operation
237 assert(amountOfRCustomOps < 1024);
238 instrFormat->addOperation(op, customEncoding);
239 }
240 }
241 } else if (name == RISCVFields::RISCV_I_TYPE_NAME) {
242 // TODO: shift operations use immediate bits for funct code in this
243 // format
245 new OperationTriggeredEncoding(std::string("rs1"), *instrFormat);
247 new OperationTriggeredEncoding(std::string("imm"), *instrFormat);
249 new OperationTriggeredEncoding(std::string("rd"), *instrFormat);
250 new OperationTriggeredField(*rs1, 0, 15, 5);
251 new OperationTriggeredField(*imm, 0, 25, 12);
252 new OperationTriggeredField(*rd, 0, 7, 5);
254 std::string("opcode"), *instrFormat);
255 new OperationTriggeredField(*opcode, 0, 0, 7);
256 new OperationTriggeredField(*opcode, 1, 12, 3);
257 new OperationTriggeredField(*opcode, 2, 25, 7);
258 for (int i = 0; i < format->operationCount(); i++) {
259 const std::string op = format->operationAtIndex(i);
261 instrFormat->addOperation(op, RISCVFields::RISCVITypeOperations.at(op));
262 } else {
263 assert(false);
264 }
265 }
266 } else if (name == RISCVFields::RISCV_S_TYPE_NAME) {
268 new OperationTriggeredEncoding(std::string("rs1"), *instrFormat);
270 new OperationTriggeredEncoding(std::string("imm"), *instrFormat);
272 new OperationTriggeredEncoding(std::string("rs2"), *instrFormat);
273 new OperationTriggeredField(*rs1, 0, 15, 5);
274 new OperationTriggeredField(*rs2, 0, 20, 5);
275 new OperationTriggeredField(*imm, 0, 7, 5);
276 new OperationTriggeredField(*imm, 1, 25, 7);
278 std::string("opcode"), *instrFormat);
279 new OperationTriggeredField(*opcode, 0, 0, 7);
280 new OperationTriggeredField(*opcode, 1, 12, 3);
281 for (int i = 0; i < format->operationCount(); i++) {
282 const std::string op = format->operationAtIndex(i);
284 instrFormat->addOperation(op, RISCVFields::RISCVSTypeOperations.at(op));
285 } else {
286 assert(false);
287 }
288 }
289 } else if (name == RISCVFields::RISCV_B_TYPE_NAME) {
291 new OperationTriggeredEncoding(std::string("rs1"), *instrFormat);
293 new OperationTriggeredEncoding(std::string("imm"), *instrFormat);
295 new OperationTriggeredEncoding(std::string("rs2"), *instrFormat);
296 new OperationTriggeredField(*rs1, 0, 15, 5);
297 new OperationTriggeredField(*rs2, 0, 20, 5);
298 new OperationTriggeredField(*imm, 0, 8, 4);
299 new OperationTriggeredField(*imm, 1, 25, 6);
300 new OperationTriggeredField(*imm, 2, 11, 1);
301 new OperationTriggeredField(*imm, 3, 31, 1);
303 std::string("opcode"), *instrFormat);
304 new OperationTriggeredField(*opcode, 0, 0, 7);
305 new OperationTriggeredField(*opcode, 1, 12, 3);
306 for (int i = 0; i < format->operationCount(); i++) {
307 const std::string op = format->operationAtIndex(i);
309 instrFormat->addOperation(op, RISCVFields::RISCVBTypeOperations.at(op));
310 } else {
311 assert(false);
312 }
313 }
314 } else if (name == RISCVFields::RISCV_U_TYPE_NAME) {
316 new OperationTriggeredEncoding(std::string("rd"), *instrFormat);
317 new OperationTriggeredField(*rd, 0, 7, 5);
319 std::string("opcode"), *instrFormat);
321 new OperationTriggeredEncoding(std::string("imm"), *instrFormat);
322 new OperationTriggeredField(*imm, 0, 12, 20);
323 new OperationTriggeredField(*opcode, 0, 0, 7);
324 for (int i = 0; i < format->operationCount(); i++) {
325 const std::string op = format->operationAtIndex(i);
327 instrFormat->addOperation(op, RISCVFields::RISCVUTypeOperations.at(op));
328 } else {
329 assert(false);
330 }
331 }
332 } else if (name == RISCVFields::RISCV_J_TYPE_NAME) {
334 new OperationTriggeredEncoding(std::string("rd"), *instrFormat);
335 new OperationTriggeredField(*rd, 0, 7, 5);
337 std::string("opcode"), *instrFormat);
339 new OperationTriggeredEncoding(std::string("imm"), *instrFormat);
340 new OperationTriggeredField(*imm, 0, 20, 10);
341 new OperationTriggeredField(*imm, 1, 20, 1);
342 new OperationTriggeredField(*imm, 2, 15, 8);
343 new OperationTriggeredField(*imm, 3, 31, 1);
344 new OperationTriggeredField(*opcode, 0, 0, 7);
345 for (int i = 0; i < format->operationCount(); i++) {
346 const std::string op = format->operationAtIndex(i);
348 instrFormat->addOperation(op, RISCVFields::RISCVJTypeOperations.at(op));
349 } else {
350 assert(false);
351 }
352 }
353 // This is a custom format for unary operations
354 // but it still uses R-format with rs2 = x0
355 } else if (name == RISCVFields::RISCV_R1R_TYPE_NAME) {
357 new OperationTriggeredEncoding(std::string("rs1"), *instrFormat);
359 new OperationTriggeredEncoding(std::string("rd"), *instrFormat);
360 new OperationTriggeredField(*rs1, 0, 15, 5);
361 new OperationTriggeredField(*rd, 0, 7, 5);
363 std::string("opcode"), *instrFormat);
364 new OperationTriggeredField(*opcode, 0, 0, 7);
365 new OperationTriggeredField(*opcode, 1, 12, 3);
366 new OperationTriggeredField(*opcode, 2, 25, 7);
367
368 for (int i = 0; i < format->operationCount(); i++) {
369 const std::string op = format->operationAtIndex(i);
370 unsigned int customEncoding = OPC_CUSTOM_0;
371 customEncoding += (amountOfRCustomOps << 7);
372 amountOfRCustomOps++;
373 // 10 bit encoding for operation
374 assert(amountOfRCustomOps < 1024);
375 instrFormat->addOperation(op, customEncoding);
376 }
377 // unary without output, stdout for example
378 } else if (name == RISCVFields::RISCV_R1_TYPE_NAME) {
380 new OperationTriggeredEncoding(std::string("rs1"), *instrFormat);
381 new OperationTriggeredField(*rs1, 0, 15, 5);
383 std::string("opcode"), *instrFormat);
384 new OperationTriggeredField(*opcode, 0, 0, 7);
385 new OperationTriggeredField(*opcode, 1, 12, 3);
386 new OperationTriggeredField(*opcode, 2, 25, 7);
387
388 for (int i = 0; i < format->operationCount(); i++) {
389 const std::string op = format->operationAtIndex(i);
390 unsigned int customEncoding = OPC_CUSTOM_0;
391 // Reserve this for printing
392 if (TCEString(op).lower() != "stdout") {
393 customEncoding += (amountOfRCustomOps << 7);
394 amountOfRCustomOps++;
395 }
396 // 10 bit encoding for operation
397 assert(amountOfRCustomOps < 1024);
398 instrFormat->addOperation(op, customEncoding);
399 }
400 } else if (name == RISCVFields::RISCV_R3R_TYPE_NAME) {
402 new OperationTriggeredEncoding(std::string("rs1"), *instrFormat);
404 new OperationTriggeredEncoding(std::string("rs2"), *instrFormat);
406 new OperationTriggeredEncoding(std::string("rs3"), *instrFormat);
408 new OperationTriggeredEncoding(std::string("rd"), *instrFormat);
409 new OperationTriggeredField(*rs1, 0, 15, 5);
410 new OperationTriggeredField(*rs2, 0, 20, 5);
411 new OperationTriggeredField(*rs3, 0, 27, 5);
412 new OperationTriggeredField(*rd, 0, 7, 5);
414 std::string("opcode"), *instrFormat);
415 new OperationTriggeredField(*opcode, 0, 0, 7);
416 new OperationTriggeredField(*opcode, 1, 12, 3);
417 new OperationTriggeredField(*opcode, 2, 25, 2);
418
419 // Reserve first few encodings for fixed special case
420 for (int i = 0; i < format->operationCount(); i++) {
421 const std::string op = format->operationAtIndex(i);
423 instrFormat->addOperation(op, RISCVFields::RISCVRTypeOperations.at(op));
424 } else {
425 unsigned int customEncoding = OPC_CUSTOM_1;
426 customEncoding += (amountOfR3RCustomOps << 7);
427 amountOfR3RCustomOps++;
428 assert(amountOfR3RCustomOps < 32);
429 instrFormat->addOperation(op, customEncoding);
430 }
431 }
432 } else {
433 // TODO: Throw some meaniningful exception here
434 assert(false);
435 }
436}
437
438/**
439 * Adds the long immediate destination register fields to the given
440 * binary encoding map.
441 *
442 * @param bem The binary encoding map.
443 */
444void
446
447 // check how many fields is needed
450 int fieldCount(0);
451 for (int i = 0; i < itNav.count(); i++) {
452 InstructionTemplate* iTemp = itNav.item(i);
453 int thisRequires = 0;
456 for (int i = 0; i < iuNav.count(); i++) {
457 ImmediateUnit* iu = iuNav.item(i);
458 if (iu->numberOfRegisters() > 1 &&
459 iTemp->isOneOfDestinations(*iu)) {
460 thisRequires++;
461 }
462 }
463
464 if (thisRequires > fieldCount) {
465 fieldCount = thisRequires;
466 }
467 }
468
469 // create a vector that contains the required widths of the fields
472 std::vector<int> fieldWidths(fieldCount, 0);
473
474 for (int i = 0; i < itNav.count(); i++) {
475 InstructionTemplate* iTemp = itNav.item(i);
476
477 // collect the destinations units to a set
478 std::set<ImmediateUnit*> dstUnits;
479 for (int i = 0; i < iuNav.count(); i++) {
480 ImmediateUnit* iu = iuNav.item(i);
481 if (iTemp->isOneOfDestinations(*iu)) {
482 dstUnits.insert(iu);
483 }
484 }
485
486 // create a set containing the sizes required by all the destinations
487 // of the instruction template
488 std::multiset<int> requiredSizes;
489 for (set<ImmediateUnit*>::const_iterator iter = dstUnits.begin();
490 iter != dstUnits.end(); iter++) {
491 ImmediateUnit* iu = *iter;
492 if (iu->numberOfRegisters() > 1) {
493 requiredSizes.insert(
495 }
496 }
497
498 // increase the values in fieldWidhts if required
499 int counter(0);
500 for (multiset<int>::const_reverse_iterator iter =
501 requiredSizes.rbegin();
502 iter != requiredSizes.rend(); iter++) {
503 if (fieldWidths[counter] < *iter) {
504 fieldWidths[counter] = *iter;
505 }
506 counter++;
507 }
508 }
509
510 // create the fields
511 typedef std::pair<InstructionTemplate*, ImmediateUnit*> ImmDstMapping;
512 std::set<ImmDstMapping> mappedDestinations;
513 for (int i = fieldCount-1; i >= 0; i--) {
514 unsigned int fieldWidth = fieldWidths[i];
516 fieldWidth, bem);
517 for (int i = 0; i < itNav.count(); i++) {
518 InstructionTemplate* iTemp = itNav.item(i);
519 for (int i = 0; i < iuNav.count(); i++) {
520 ImmediateUnit* iu = iuNav.item(i);
521 if (iTemp->isOneOfDestinations(*iu) &&
522 iu->numberOfRegisters() > 1 &&
523 static_cast<unsigned int>(
525 <= fieldWidth &&
527 mappedDestinations,
528 ImmDstMapping(iTemp, iu))) {
529 newField->addDestination(iTemp->name(), iu->name());
530 mappedDestinations.insert(ImmDstMapping(iTemp, iu));
531 }
532 }
533 }
534 }
535}
536
537
538/**
539 * Adds subfields to the given move slot.
540 *
541 * @param slot The move slot.
542 */
543void
545
546 string busName = slot.name();
548 assert(busNav.hasItem(busName));
549 Bus* bus = busNav.item(busName);
550
553 SourceField* sField = new SourceField(BinaryEncoding::LEFT, slot);
554 GuardField* gField = NULL;
555
556 addEncodings(*dField); // destination field
557 addEncodings(*sField); // source field
558
559 // we need guard field only if we have >1 guard.
560 if (bus->guardCount() > 1) {
561 gField = new GuardField(slot);
562 addEncodings(*gField); // guard field
563 }
564
565 // adds extra bits to guard field (any field is probably ok) if needed.
566 // extra bits added so that long immediate fits to the slot.
567 int longImmWidth = maxLongImmSlotWidth(slot);
568 if (longImmWidth > slot.width()) {
569 // if no guard field, create it so that it can be enlarged.
570 if (gField == NULL) {
571 gField = new GuardField(slot);
572 addEncodings(*gField); // guard field
573 }
574 gField->setExtraBits((longImmWidth - slot.width()) +
575 gField->extraBits());
576 }
577}
578
579
580/**
581 * Adds the encoding for instruction templates to the given immediate
582 * control field.
583 *
584 * @param field The immediate control field.
585 */
586void
590 for (int i = 0; i < itNav.count(); i++) {
591 InstructionTemplate* iTemp = itNav.item(i);
592 field.addTemplateEncoding(iTemp->name(), i);
593 }
594}
595
596
597/**
598 * Adds encodings for the given destination field.
599 *
600 * @param field The destination field.
601 */
602void
604
605 string busName = field.parent()->name();
607 assert(busNav.hasItem(busName));
608 Bus* bus = busNav.item(busName);
609 bool createNopField = true;
610 for (int i = 0; i < bus->guardCount(); i++) {
611 Guard* g = bus->guard(i);
612 if (g->isInverted() && dynamic_cast<UnconditionalGuard*>(g) != NULL) {
613 createNopField = false;
614 }
615 }
616
617 int dstSockets = socketCount(*bus, Socket::INPUT);
618 if (dstSockets == 0) {
619 return;
620 }
621
622 multiset<int> socketCodeWidths = socketCodeWidthsForBus(
623 *bus, Socket::INPUT);
624 // add socket code width for NOP encoding
625 if (createNopField) {
626 socketCodeWidths.insert(0);
627 }
628 multiset<Encoding> encodings;
629 calculateEncodings(socketCodeWidths, true, encodings);
630
631 set<Socket*> handledSockets;
632 multiset<int>::reverse_iterator scIter = socketCodeWidths.rbegin();
633 bool nopEncodingSet = false;
634 for (multiset<Encoding>::const_iterator encIter = encodings.begin();
635 encIter != encodings.end(); encIter++) {
636 Encoding enc = *encIter;
637 int scWidth = *scIter;
638 if (scWidth == 0 && !nopEncodingSet && createNopField) {
639 // add NOP encoding
640 new NOPEncoding(enc.first, enc.second, field);
641 nopEncodingSet = true;
642 } else {
643 // find socket that has correct socket code width
644 for (int i = 0; i < dstSockets; i++) {
646 i, *bus, Socket::INPUT);
648 if (scTable == NULL && scWidth == 0 &&
649 !AssocTools::containsKey(handledSockets, &socket)) {
650 new SocketEncoding(
651 socket.name(), enc.first, enc.second, field);
652 handledSockets.insert(&socket);
653 break;
654 } else if (scTable != NULL && scWidth == scTable->width() &&
656 handledSockets, &socket)) {
657 SocketEncoding* socketEnc = new SocketEncoding(
658 socket.name(), enc.first, enc.second, field);
659 socketEnc->setSocketCodes(*scTable);
660 handledSockets.insert(&socket);
661 break;
662 }
663 }
664 }
665 scIter++;
666 }
667}
668
669
670/**
671 * Adds encodings for the given source field.
672 *
673 * @param field The source field.
674 */
675void
677
678 string busName = field.parent()->name();
680 assert(busNav.hasItem(busName));
681 Bus* bus = busNav.item(busName);
682 bool createNopField = true;
683 for (int i = 0; i < bus->guardCount(); i++) {
684 Guard* g = bus->guard(i);
685 if (g->isInverted() && dynamic_cast<UnconditionalGuard*>(g) != NULL) {
686 createNopField = false;
687 }
688 }
689
690 int srcSockets = socketCount(*bus, Socket::OUTPUT);
691 int srcBridges = sourceBridgeCount(*bus);
692 bool shortImmSupport = (bus->immediateWidth() > 0);
693
694 multiset<int> socketCodeWidths = socketCodeWidthsForBus(
695 *bus, Socket::OUTPUT);
696 for (int i = 0; i < srcBridges; i++) {
697 socketCodeWidths.insert(0);
698 }
699 if (shortImmSupport) {
700 socketCodeWidths.insert(bus->immediateWidth());
701 }
702 // one encoding for NOP
703 if (createNopField) {
704 socketCodeWidths.insert(0);
705 }
706
707 multiset<Encoding> encodings;
708 calculateEncodings(socketCodeWidths, true, encodings);
709
710 // set the encodings
711 set<Socket*> handledSockets;
712 int nextBridge = 0;
713 bool nopEncodingSet = false;
714 bool immEncodingSet = !shortImmSupport;
715 multiset<int>::reverse_iterator scIter = socketCodeWidths.rbegin();
716 for (multiset<Encoding>::const_iterator encIter = encodings.begin();
717 encIter != encodings.end(); encIter++) {
718 Encoding enc = *encIter;
719 int scWidth = *scIter;
720 if (scWidth == 0 && !nopEncodingSet && createNopField) {
721 new NOPEncoding(enc.first, enc.second, field);
722 nopEncodingSet = true;
723 } else if (!immEncodingSet && scWidth == bus->immediateWidth()) {
725 enc.first, enc.second, bus->immediateWidth(), field);
726 immEncodingSet = true;
727 } else {
728 bool socketFound = false;
729 // find the socket that has correct socket code width
730 for (int i = 0; i < srcSockets; i++) {
732 i, *bus, Socket::OUTPUT);
734 if (scTable == NULL && scWidth == 0 &&
735 !AssocTools::containsKey(handledSockets, &socket)) {
736 new SocketEncoding(
737 socket.name(), enc.first, enc.second, field);
738 handledSockets.insert(&socket);
739 socketFound = true;
740 break;
741 } else if (scTable != NULL && scWidth == scTable->width() &&
743 handledSockets, &socket)) {
744 SocketEncoding* socketEnc = new SocketEncoding(
745 socket.name(), enc.first, enc.second, field);
746 socketEnc->setSocketCodes(*scTable);
747 handledSockets.insert(&socket);
748 socketFound = true;
749 break;
750 }
751 }
752 if (!socketFound) {
753 assert(scWidth == 0);
754 assert(nextBridge < srcBridges);
756 nextBridge, *bus);
757 new BridgeEncoding(
758 bridge.name(), enc.first, enc.second, field);
759 nextBridge++;
760 }
761 }
762 scIter++;
763 }
764}
765
766
767/**
768 * Adds guard encodings to the given guard field.
769 *
770 * @param field The guard field.
771 */
772void
774
775 string busName = field.parent()->name();
777 assert(busNav.hasItem(busName));
778 Bus* bus = busNav.item(busName);
779
780 int guards = bus->guardCount();
781
782 for (int i = 0; i < guards; i++) {
783 Guard* guard = bus->guard(i);
784 PortGuard* portGuard = dynamic_cast<PortGuard*>(guard);
785 RegisterGuard* regGuard = dynamic_cast<RegisterGuard*>(guard);
786 UnconditionalGuard* ucGuard =
787 dynamic_cast<UnconditionalGuard*>(guard);
788 if (portGuard != NULL) {
789 FUPort* port = portGuard->port();
790 new FUGuardEncoding(
791 port->parentUnit()->name(), port->name(),
792 portGuard->isInverted(), i, field);
793 } else if (regGuard != NULL) {
795 regGuard->registerFile()->name(), regGuard->registerIndex(),
796 regGuard->isInverted(), i, field);
797 } else if (ucGuard != NULL) {
798 new UnconditionalGuardEncoding(ucGuard->isInverted(), i, field);
799 } else {
800 assert(false);
801 }
802 }
803}
804
805
806/**
807 * Returns the socket code table that is assigned to the given socket.
808 *
809 * @param socket The socket.
810 * @return The socket code table or NULL if no socket code table is assigned
811 * to the given socket.
812 */
817 } else {
818 return NULL;
819 }
820}
821
822
823/**
824 * Finds a suitable socket code table from the socket code table map for
825 * the given socket.
826 *
827 * Returns NULL if there is no suitable socket code table.
828 *
829 * @param socket The socket.
830 * @return The socket code table or NULL.
831 */
834 for (SCTableMap::const_iterator iter = scTableMap_.begin();
835 iter != scTableMap_.end(); iter++) {
836 const Socket* toCheck = (*iter).first;
837 if (haveEqualConnections(socket, *toCheck)) {
838 return (*iter).second;
839 }
840 }
841 return NULL;
842}
843
844
845/**
846 * Assigns the given socket code table for the given socket.
847 *
848 * @param socket The socket.
849 * @param table The socket code table.
850 */
851void
853 const Socket* socket,
854 SocketCodeTable* table) {
855
857 scTableMap_.insert(pair<const Socket*, SocketCodeTable*>(socket, table));
858}
859
860
861/**
862 * Returns the number of sockets of the given direction connected to the
863 * given bus.
864 *
865 * @param bus The bus.
866 * @param direction The direction
867 * @return The number of sockets.
868 */
869int
871
872 typedef std::set<Socket*> SocketSet;
873 SocketSet sockets;
874
875 for (int i = 0; i < bus.segmentCount(); i++) {
876 Segment* segment = bus.segment(i);
877 for (int i = 0; i < segment->connectionCount(); i++) {
878 Socket* socket = segment->connection(i);
879 if (socket->direction() == direction) {
880 sockets.insert(socket);
881 }
882 }
883 }
884
885 return sockets.size();
886}
887
888
889/**
890 * By the given index, returns a socket that is attached to the
891 * given bus and has the given direction.
892 *
893 * @param index The index.
894 * @param bus The bus.
895 * @param direction Direction of the sockets being returned.
896 * @return The socket.
897 */
898Socket&
900 int index,
901 const Bus& bus,
902 Socket::Direction direction) {
903
904 typedef std::vector<Socket*> SocketTable;
905
906 assert(index >= 0);
907 SocketTable connectedSockets;
908
909 for (int i = 0; i < bus.segmentCount(); i++) {
910 Segment* segment = bus.segment(i);
911 for (int i = 0; i < segment->connectionCount(); i++) {
912 Socket* socket = segment->connection(i);
913 if (socket->direction() == direction) {
915 connectedSockets, socket)) {
916 connectedSockets.push_back(socket);
917 }
918 }
919 }
920 }
921
922 assert(connectedSockets.size() > static_cast<size_t>(index));
923 return *connectedSockets[index];
924}
925
926
927/**
928 * Tells whether the given socket needs a socket code table.
929 *
930 * @return True if the socket needs a socket code table, otherwise false.
931 */
932bool
934
935 if (socket.portCount() > 1) {
936 return true;
937
938 } else if (socket.portCount() == 1) {
939
940 // socket code table is needed if the port is opcode setting with
941 // more than one possible opcode or if the port is a data port of
942 // register file with more than one register
943 Port* port = socket.port(0);
944 FUPort* fuPort = dynamic_cast<FUPort*>(port);
945 RFPort* rfPort = dynamic_cast<RFPort*>(port);
946 if (fuPort != NULL && fuPort->isOpcodeSetting() &&
947 fuPort->parentUnit()->operationCount() > 1) {
948 return true;
949 } else if (rfPort != NULL &&
950 rfPort->parentUnit()->numberOfRegisters() > 1) {
951 return true;
952 } else {
953 return false;
954 }
955
956 } else {
957 return false;
958 }
959}
960
961
962/**
963 * Adds the port codes to the given socket code table.
964 *
965 * @param table The socket code table.
966 * @param socket The socket that will refer to the table.
967 */
968void
970 SocketCodeTable& table,
971 const Socket& socket) const {
972
973 // create a set of register index widths for each port code
974 multiset<int> indexWidths;
975 for (int i = 0; i < socket.portCount(); i++) {
976 Port* port = socket.port(i);
977 Unit* parentUnit = port->parentUnit();
978 BaseRegisterFile* rfParent = dynamic_cast<BaseRegisterFile*>(
979 parentUnit);
980 FunctionUnit* fuParent = dynamic_cast<FunctionUnit*>(parentUnit);
981
982 if (fuParent != NULL) {
983 int encodingsNeeded(0);
984 if (dynamic_cast<BaseFUPort*>(port)->isOpcodeSetting() &&
986 encodingsNeeded = fuParent->operationCount();
987 } else {
988 encodingsNeeded = 1;
989 }
990 for (int i = 0; i < encodingsNeeded; i++) {
991 indexWidths.insert(0);
992 }
993 } else {
994 assert(rfParent != NULL);
995 unsigned int indexWidth = requiredIndexWidth(*rfParent);
996 indexWidths.insert(indexWidth);
997 }
998 }
999
1000 // calculate port IDs
1001 multiset<Encoding> encodings;
1002 calculateEncodings(indexWidths, true, encodings);
1003
1004 // set the encodings
1005 if (encodings.size() == 0) {
1006 assert(socket.portCount() == 1);
1007 Port* port = socket.port(0);
1008 ImmediateUnit* iu = dynamic_cast<ImmediateUnit*>(port->parentUnit());
1009 RegisterFile* rf = dynamic_cast<RegisterFile*>(port->parentUnit());
1010 assert(iu != NULL || rf != NULL);
1011 // iu must be first because iu is inherited from rf
1012 if (iu != NULL) {
1013 new IUPortCode(iu->name(), requiredIndexWidth(*iu), table);
1014 } else {
1015 new RFPortCode(rf->name(), requiredIndexWidth(*rf), table);
1016 }
1017 } else {
1018 set<Port*> handledPorts;
1019 multiset<int>::const_reverse_iterator indexWidthIter =
1020 indexWidths.rbegin();
1021 for (multiset<Encoding>::const_iterator encIter = encodings.begin();
1022 encIter != encodings.end();) {
1023 int indexWidth = *indexWidthIter;
1024 Encoding enc = *encIter;
1025 for (int portIndex = 0; portIndex < socket.portCount();
1026 portIndex++) {
1027 Port* port = socket.port(portIndex);
1028 if (AssocTools::containsKey(handledPorts, port)) {
1029 continue;
1030 }
1031 RegisterFile* rfParent = dynamic_cast<RegisterFile*>(
1032 port->parentUnit());
1033 ImmediateUnit* iuParent = dynamic_cast<ImmediateUnit*>(
1034 port->parentUnit());
1035 FunctionUnit* fuParent = dynamic_cast<FunctionUnit*>(
1036 port->parentUnit());
1037 // iu must be first because iu is inherited from rf
1038 if (iuParent != NULL) {
1039 int reqIndexWidth = requiredIndexWidth(*iuParent);
1040 if (reqIndexWidth == indexWidth) {
1041 new IUPortCode(
1042 iuParent->name(), enc.first, enc.second,
1043 reqIndexWidth, table);
1044 indexWidthIter++;
1045 encIter++;
1046 handledPorts.insert(port);
1047 break;
1048 }
1049 } else if (rfParent != NULL) {
1050 int reqIndexWidth = requiredIndexWidth(*rfParent);
1051 if (reqIndexWidth == indexWidth) {
1052 new RFPortCode(
1053 rfParent->name(), enc.first, enc.second,
1054 reqIndexWidth, table);
1055 indexWidthIter++;
1056 encIter++;
1057 handledPorts.insert(port);
1058 break;
1059 }
1060 } else {
1061 if (indexWidth != 0) {
1062 continue;
1063 }
1064 assert(fuParent != NULL);
1065 BaseFUPort* fuPort = dynamic_cast<BaseFUPort*>(port);
1066 assert(fuPort != NULL);
1067 if (fuPort->isOpcodeSetting()) {
1068 // map<operation name, operation index in FU>
1069 map<string,int> opcodeSet;
1070 assert(*indexWidthIter == 0);
1071 // operation indeces are numbered according to the
1072 // alphabetical order of opertations
1073 for (int opIndex = 0;
1074 opIndex < fuParent->operationCount();
1075 opIndex++) {
1076 opcodeSet.insert(
1077 make_pair(
1078 fuParent->operation(opIndex)->name(),
1079 opIndex));
1080 }
1081
1082 for (map<string,int>::iterator
1083 iter = opcodeSet.begin();
1084 iter != opcodeSet.end(); iter++) {
1085 Encoding enc = *encIter;
1086 HWOperation* operation =
1087 fuParent->operation(iter->second);
1088 assert(operation->name() == iter->first);
1089 new FUPortCode(
1090 fuParent->name(), fuPort->name(),
1091 operation->name(), enc.first, enc.second,
1092 table);
1093 indexWidthIter++;
1094 encIter++;
1095 }
1096 } else {
1097 new FUPortCode(
1098 fuParent->name(), fuPort->name(), enc.first,
1099 enc.second, table);
1100 indexWidthIter++;
1101 encIter++;
1102 }
1103 handledPorts.insert(port);
1104 break;
1105 }
1106 }
1107 }
1108 }
1109}
1110
1111
1112/**
1113 * Returns a multiset containing the socket code widths for sockets of
1114 * the given direction that are connected to the given bus.
1115 *
1116 * @param bus The bus.
1117 * @param socket The direction.
1118 * @return The multiset.
1119 */
1120std::multiset<int>
1122 const TTAMachine::Bus& bus,
1123 Socket::Direction socketDir) const {
1124
1125 std::multiset<int> socketCodeWidths;
1126 int socketCount = BEMGenerator::socketCount(bus, socketDir);
1127 for (int i = 0; i < socketCount; i++) {
1128 Socket& socket = BEMGenerator::socket(i, bus, socketDir);
1130 if (scTable == NULL) {
1131 socketCodeWidths.insert(0);
1132 } else {
1133 socketCodeWidths.insert(scTable->width());
1134 }
1135 }
1136
1137 return socketCodeWidths;
1138}
1139
1140
1141/**
1142 * Checks whether the given sockets have equal port connections.
1143 *
1144 * @param socket1 The first socket.
1145 * @param socket2 The second socket.
1146 * @return True if the sockets have equal port connections, otherwise false.
1147 */
1148bool
1150 const Socket& socket1,
1151 const Socket& socket2) {
1152
1153 std::set<Port*> socket1Ports;
1154 std::set<Port*> socket2Ports;
1155
1156 for (int i = 0; i < socket1.portCount(); i++) {
1157 socket1Ports.insert(socket1.port(i));
1158 }
1159
1160 for (int i = 0; i < socket2.portCount(); i++) {
1161 socket2Ports.insert(socket2.port(i));
1162 }
1163
1164 if (socket1Ports == socket2Ports) {
1165 return true;
1166 } else {
1167 return false;
1168 }
1169}
1170
1171
1172/**
1173 * Tells how many source bridges the given bus has.
1174 *
1175 * @param bus The bus.
1176 * @return The number of source bridges.
1177 */
1178int
1180
1181 Machine* mach = bus.machine();
1182 assert(mach != NULL);
1183 Machine::BridgeNavigator bridgeNav = mach->bridgeNavigator();
1184
1185 int count(0);
1186
1187 for (int i = 0; i < bridgeNav.count(); i++) {
1188 Bridge* bridge = bridgeNav.item(i);
1189 if (bridge->destinationBus() == &bus) {
1190 count++;
1191 }
1192 }
1193
1194 assert(count <= 2);
1195 return count;
1196}
1197
1198
1199/**
1200 * By the given index returns a source bridge for the given bus.
1201 *
1202 * @param index The index (0 or 1).
1203 * @param bus The bus.
1204 */
1205Bridge&
1206BEMGenerator::sourceBridge(int index, const Bus& bus) {
1207
1208 Machine* mach = bus.machine();
1209 assert(mach != NULL);
1210 Machine::BridgeNavigator bridgeNav = mach->bridgeNavigator();
1211
1212 int count(0);
1213
1214 for (int i = 0; i < bridgeNav.count(); i++) {
1215 Bridge* bridge = bridgeNav.item(i);
1216 if (bridge->destinationBus() == &bus) {
1217 if (count == index) {
1218 return *bridge;
1219 } else {
1220 count++;
1221 }
1222 }
1223 }
1224
1225 assert(false);
1226 // dummy return
1227 return *bridgeNav.item(0);
1228}
1229
1230
1231/**
1232 * Tells whether the given bus has an unconditional guard.
1233 *
1234 * @param bus The bus.
1235 * @return True if the bus has an unconditional guard, otherwise false.
1236 */
1237bool
1239 for (int i = 0; i < bus.guardCount(); i++) {
1240 Guard* guard = bus.guard(i);
1241 if (dynamic_cast<UnconditionalGuard*>(guard) != NULL) {
1242 return true;
1243 }
1244 }
1245 return false;
1246}
1247
1248
1249/**
1250 * Returns the number of bits needed to identify a register in the given
1251 * register file.
1252 *
1253 * @param regFile The register file.
1254 * @return The number of bits needed for register index.
1255 */
1256int
1258 if (regFile.numberOfRegisters() <= 1) {
1259 return 0;
1260 } else {
1261 return MathTools::bitLength(regFile.numberOfRegisters() - 1);
1262 }
1263}
1264
1265
1266/**
1267 * Calculates unambiguous encodings when the encodings have opposite
1268 * fields of the given widths.
1269 *
1270 * Minimizes both the total width of the field and the width of the
1271 * encodings. Currently supports only left aligment of encodings.
1272 *
1273 * @param oppositeFieldWidths Widths of the opposite fields.
1274 * @param alignment Tells whether the encodings are aligned to left (true)
1275 * or right (false).
1276 * @param encoding The encodings are added here.
1277 */
1278void
1280 const std::multiset<int>& oppositeFieldWidths,
1281 bool alignment,
1282 std::multiset<Encoding>& encodings) {
1283
1284 if (oppositeFieldWidths.size() < 1) {
1285 return;
1286 }
1287
1288 assert(alignment);
1289
1290 unsigned int remainder = 0;
1291 unsigned int encodingsLeft = oppositeFieldWidths.size();
1292 unsigned int prevEncoding = 0;
1293 unsigned int nextEncoding = 0;
1294 unsigned int prevOppositeFieldWidth = 0;
1295
1296 for (multiset<int>::reverse_iterator iter = oppositeFieldWidths.rbegin();
1297 iter != oppositeFieldWidths.rend(); iter++) {
1298 unsigned int oppositeFieldWidth = *iter;
1299 if (iter == oppositeFieldWidths.rbegin()) {
1300 nextEncoding = 0;
1301 encodings.insert(Encoding(nextEncoding, 0));
1302 remainder = 1;
1303 } else {
1304 nextEncoding = prevEncoding + 1;
1305 if (MathTools::bitLength(nextEncoding) >
1306 MathTools::bitLength(prevEncoding)) {
1307 addExtraBits(encodings, 1);
1308 unsigned int setEncodingCount =
1309 oppositeFieldWidths.size() - encodingsLeft;
1310 remainder = (remainder << 1) + setEncodingCount;
1311 }
1312
1313 if (oppositeFieldWidth == prevOppositeFieldWidth) {
1314 encodings.insert(Encoding(nextEncoding, 0));
1315 } else {
1316 assert(oppositeFieldWidth < prevOppositeFieldWidth);
1317 unsigned int freeBits =
1318 prevOppositeFieldWidth - oppositeFieldWidth;
1319 // calculate the number of bits the encoding has to be
1320 // expanded
1321 unsigned int expansion = 0;
1322 while (remainder << expansion < encodingsLeft) {
1323 if (expansion < freeBits) {
1324 expansion++;
1325 } else {
1326 break;
1327 }
1328 }
1329 nextEncoding = nextEncoding << expansion;
1330 encodings.insert(Encoding(nextEncoding, 0));
1331 remainder = remainder << expansion;
1332 }
1333 }
1334 prevOppositeFieldWidth = oppositeFieldWidth;
1335 encodingsLeft--;
1336 remainder--;
1337 prevEncoding = nextEncoding;
1338 }
1339
1340 assert(encodings.size() == oppositeFieldWidths.size());
1341}
1342
1343
1344/**
1345 * Adds the given number of extra bits to the encodings in the given set.
1346 *
1347 * @param encodings The encodings.
1348 * @param bitLength The number of bits.
1349 */
1350void
1352 std::multiset<Encoding>& encodings,
1353 int bitCount) {
1354
1355 multiset<Encoding> newSet;
1356 for (multiset<Encoding>::iterator iter = encodings.begin();
1357 iter != encodings.end(); iter++) {
1358 unsigned int encoding = iter->first;
1359 unsigned int extraBits = iter->second;
1360 extraBits += bitCount;
1361 newSet.insert(Encoding(encoding, extraBits));
1362 }
1363
1364 encodings.clear();
1365 encodings.insert(newSet.begin(), newSet.end());
1366}
1367
1368
1369/**
1370 * Returns the width of the longest long immediate template being encoded in a
1371 * slot given as parameter.
1372 *
1373 * @param slot Move slot where to check if it's used to store long immediates.
1374 * @return Width of the longest long immediate width stored in a move slot.
1375 */
1376unsigned int
1380 int maxWidth = 0;
1381
1382 for (int i = 0; i < itNav.count(); i++) {
1383 InstructionTemplate* iTemp = itNav.item(i);
1384 for (int i = 0; i < iTemp->slotCount(); ++i) {
1385 if (slot.name() == iTemp->slot(i)->slot() &&
1386 maxWidth < iTemp->slot(i)->width()) {
1387
1388 maxWidth = iTemp->slot(i)->width();
1389 }
1390 }
1391 }
1392
1393 return maxWidth;
1394}
1395
#define assert(condition)
TTAMachine::Machine * machine
the architecture definition of the estimated processor
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
BinaryEncoding * generate()
const TTAMachine::Machine * machine_
The machine for which the BEM is generated.
void addSubfields(MoveSlot &slot) const
void addRiscvFormat(TTAMachine::OperationTriggeredFormat *format, BinaryEncoding &bem, unsigned &amountOfRCustomOps, unsigned &amountOfR3RCustomOps) const
static bool needsSocketCodeTable(const TTAMachine::Socket &socket)
static int socketCount(const TTAMachine::Bus &bus, TTAMachine::Socket::Direction direction)
std::multiset< int > socketCodeWidthsForBus(const TTAMachine::Bus &bus, TTAMachine::Socket::Direction socketDir) const
static void addExtraBits(std::multiset< Encoding > &encodings, int bitCount)
static TTAMachine::Socket & socket(int index, const TTAMachine::Bus &bus, TTAMachine::Socket::Direction direction)
void addPortCodes(SocketCodeTable &table, const TTAMachine::Socket &socket) const
BEMGenerator(const TTAMachine::Machine &machine)
SCTableMap scTableMap_
A map which tells which socket code table belongs to a socket.
static int requiredIndexWidth(const TTAMachine::BaseRegisterFile &regFile)
static bool haveEqualConnections(const TTAMachine::Socket &socket1, const TTAMachine::Socket &socket2)
virtual ~BEMGenerator()
static void calculateEncodings(const std::multiset< int > &oppositeFieldWidths, bool leftAlignment, std::multiset< Encoding > &encodings)
void addSocketCodeTables(BinaryEncoding &bem)
void addEncodings(ImmediateControlField &field) const
void addTopLevelFields(BinaryEncoding &bem) const
static int sourceBridgeCount(const TTAMachine::Bus &bus)
static TTAMachine::Bridge & sourceBridge(int index, const TTAMachine::Bus &bus)
std::pair< unsigned int, unsigned int > Encoding
Typedef for encoding (first = encoding, second = extra bits).
SocketCodeTable * socketCodeTable(const TTAMachine::Socket &socket) const
SocketCodeTable * suitableSocketCodeTable(const TTAMachine::Socket &socket) const
static bool hasUnconditionalGuard(const TTAMachine::Bus &bus)
void assignSocketCodeTable(const TTAMachine::Socket *socket, SocketCodeTable *table)
unsigned int maxLongImmSlotWidth(const MoveSlot &slot) const
void addLongImmDstRegisterFields(BinaryEncoding &bem) const
int moveSlotCount() const
MoveSlot & moveSlot(int index) const
static bool containsValue(const ContainerType &aContainer, const ElementType &aKey)
MoveSlot * parent() const
void addTemplateEncoding(const std::string &name, unsigned int encoding)
void setExtraBits(int bits)
void addOperation(std::string op, int encoding)
void addDestination(const std::string &instructionTemplate, const std::string &immediateUnit)
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
static unsigned int bitLength(long unsigned int number)
virtual int width() const
Definition MoveSlot.cc:406
std::string name() const
Definition MoveSlot.cc:136
MoveSlot * parent() const
Definition SlotField.cc:98
void setSocketCodes(SocketCodeTable &codeTable)
FunctionUnit * parentUnit() const
Definition BaseFUPort.cc:96
virtual bool isOpcodeSetting() const =0
virtual int numberOfRegisters() const
Bus * destinationBus() const
virtual Segment * segment(int index) const
Definition Bus.cc:329
int immediateWidth() const
Definition Bus.cc:160
Guard * guard(int index) const
Definition Bus.cc:456
virtual int segmentCount() const
Definition Bus.cc:385
int guardCount() const
Definition Bus.cc:441
virtual Machine * machine() const
virtual TCEString name() const
virtual bool isOpcodeSetting() const
Definition FUPort.cc:195
virtual HWOperation * operation(const std::string &name) const
virtual int operationCount() const
virtual bool isInverted() const
const std::string & name() const
virtual bool isOneOfDestinations(const ImmediateUnit &dstUnit) const
virtual TemplateSlot * slot(int index) const
ComponentType * item(int index) const
bool hasItem(const std::string &name) const
virtual ImmediateSlotNavigator immediateSlotNavigator() const
Definition Machine.cc:462
virtual BridgeNavigator bridgeNavigator() const
Definition Machine.cc:404
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition Machine.cc:428
virtual SocketNavigator socketNavigator() const
Definition Machine.cc:368
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual OperationTriggeredFormatNavigator operationTriggeredFormatNavigator() const
Definition Machine.cc:439
FUPort * port() const
Unit * parentUnit() const
virtual std::string name() const
Definition Port.cc:141
BaseRegisterFile * parentUnit() const
Definition RFPort.cc:93
const RegisterFile * registerFile() const
const Connection & connection(const Socket &socket) const
Definition Segment.cc:250
int connectionCount() const
@ OUTPUT
Data goes from port to bus.
Definition Socket.hh:60
@ INPUT
Data goes from bus to port.
Definition Socket.hh:59
Direction direction() const
Port * port(int index) const
Definition Socket.cc:266
int portCount() const
std::string slot() const
const std::string RISCV_S_TYPE_NAME
const std::string RISCV_R1R_TYPE_NAME
const std::string RISCV_R3R_TYPE_NAME
const std::map< std::string, int > RISCVSTypeOperations
const std::string RISCV_B_TYPE_NAME
const std::map< std::string, int > RISCVJTypeOperations
const std::map< std::string, int > RISCVITypeOperations
const std::string RISCV_J_TYPE_NAME
const std::map< std::string, int > RISCVUTypeOperations
const std::string RISCV_R_TYPE_NAME
const std::string RISCV_R1_TYPE_NAME
const std::string RISCV_I_TYPE_NAME
const std::string RISCV_U_TYPE_NAME
const std::map< std::string, int > RISCVRTypeOperations
Definition RISCVFields.hh:8
const std::map< std::string, int > RISCVBTypeOperations