OpenASIP 2.2
Loading...
Searching...
No Matches
ProgrammabilityValidator.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 ProgrammabilityValidator.cc
26 *
27 * Implementation of ProgrammabilityValidator class.
28 *
29 * @author Jari Mäntyneva 2006 (jari.mantyneva-no.spam-tut.fi)
30 * @note rating: red
31 */
32
33#include <iostream>
34#include "Application.hh"
35#include "SetTools.hh"
36#include "ContainerTools.hh"
39#include "FunctionUnit.hh"
40#include "ControlUnit.hh"
41#include "Segment.hh"
42#include "Bus.hh"
43#include "Unit.hh"
44#include "HWOperation.hh"
45#include "Instruction.hh"
46#include "Program.hh"
47#include "TerminalRegister.hh"
48#include "TerminalFUPort.hh"
49#include "FUPort.hh"
50#include "Move.hh"
51#include "Procedure.hh"
52#include "ProgramWriter.hh"
53#include "MoveGuard.hh"
54#include "Binary.hh"
55#include "BinaryEncoding.hh"
56#include "MachineValidator.hh"
58#include "MinimalOpSetCheck.hh"
59#include "Guard.hh"
60
61using std::set;
62using std::vector;
63using std::string;
64using std::pair;
65using std::cout;
66using std::cerr;
67using std::endl;
68using namespace TTAMachine;
69using namespace TTAProgram;
70
71
72/**
73 * The constructor.
74 *
75 * @param machine The machine that will be profiled.
76 * @param procedure ProgrammabilityValidator generates procedure.
77 */
79 : machine_(machine), minimalOpSetCheck_(new MinimalOpSetCheck()) {
80 directCounter = 0;
81 gcrCounter = 0;
82 booleanRegister_ = NULL;
83 MachineValidator machineValidator(machine);
84 set<MachineValidator::ErrorCode> errorsToCheck;
85 errorsToCheck.insert(MachineValidator::GCU_MISSING);
86 errorsToCheck.insert(MachineValidator::GCU_AS_MISSING);
87
88 MachineValidatorResults* results =
89 machineValidator.validate(errorsToCheck);
90
91 for (int i = 0; i < results->errorCount(); i++) {
92 MachineValidator::ErrorCode code = results->error(i).first;
94 string msg = "ADF file doesn't have a GCU.";
95 throw IllegalMachine(__FILE__, __LINE__, __func__, msg);
96 }
98 string msg = "No address space bound to GCU.";
99 throw IllegalMachine(__FILE__, __LINE__, __func__, msg);
100 }
101 }
102 delete results;
103
105 program_ = new Program(*space);
106 procedure_ = new Procedure("programmabilityValidator", *space);
108
109 FUConnections.clear();
110 GCUConnections.clear();
111 RFConnections.clear();
112 IMMConnections.clear();
113}
114
115/**
116 * The destructor.
117 */
127
128
129
130/**
131 * Does all validations of ProgrammabilityValidator.
132 *
133 * @return Returns pointer to ProgrammabilityValidatorResults where all error
134 * messages are stored.
135 */
138
141
142 checkPrimitiveSet(*results);
143 checkBooleanRegister(*results);
146
147 if (globalConnectionRegister_ == NULL) {
149 "Can't determine global connection register.");
150 }
151
153
154 vector<pair<string, string> > missingInputs;
155 vector<pair<string, string> > missingOutputs;
158 missingInputs,
159 missingOutputs);
160
161 if ((missingInputs.size() > 0) || (missingOutputs.size() > 0)) {
162 for (unsigned int i = 0; i < missingInputs.size(); i++) {
163 string missing = "";
164 missing.append("Missing connection: ");
165 missing.append(missingInputs[i].first);
166 missing.append(" : ");
167 missing.append(missingInputs[i].second);
168 missing.append(" -> ");
169 missing.append(globalConnectionRegister_->name());
170 results->addError(MISSING_CONNECTION, missing);
171 }
172 for (unsigned int i = 0; i < missingOutputs.size(); i++) {
173 string missing = "";
174 missing.append("Missing connection: ");
175 missing.append(globalConnectionRegister_->name());
176 missing.append(" -> ");
177 missing.append(missingOutputs[i].first);
178 missing.append(" : ");
179 missing.append(missingOutputs[i].second);
180 results->addError(MISSING_CONNECTION, missing);
181 }
182 }
183 return results;
184}
185
186
187/**
188 * Does selected validations of ProgrammabilityValidator.
189 *
190 * @param errorsToCheck Contains the error codes for the errors to check.
191 * @return Returns pointer to ProgrammabilityValidatorResults where all error
192 * messages are stored.
193 */
195ProgrammabilityValidator::validate(const std::set<ErrorCode>& errorsToCheck) {
196
199
200 for (std::set<ErrorCode>::const_iterator iter = errorsToCheck.begin();
201 iter != errorsToCheck.end(); iter++) {
202 ErrorCode code = *iter;
204 checkPrimitiveSet(*results);
205 } else if (code == BOOLEAN_REGISTER_ERROR ||
207 checkBooleanRegister(*results);
208 } else if (code == GLOBAL_CONNECTION_REGISTER_NOT_FOUND) {
211 if (globalConnectionRegister_ == NULL) {
213 "Can't determine global connection register.");
214 }
215 } else if (code == MISSING_CONNECTION) {
218 if (globalConnectionRegister_ == NULL) {
220 "Can't determine global connection register.");
221 break;
222 }
223 vector<pair<string, string> > missingInputs;
224 vector<pair<string, string> > missingOutputs;
227 missingInputs,
228 missingOutputs);
229
230 if ((missingInputs.size() > 0) || (missingOutputs.size() > 0)) {
231 for (unsigned int i = 0; i < missingInputs.size(); i++) {
232 string missing = "";
233 missing.append("Missing connection: ");
234 missing.append(missingInputs[i].first);
235 missing.append(" : ");
236 missing.append(missingInputs[i].second);
237 missing.append(" -> ");
238 missing.append(globalConnectionRegister_->name());
239 results->addError(MISSING_CONNECTION, missing);
240 }
241 for (unsigned int i = 0; i < missingOutputs.size(); i++) {
242 string missing = "";
243 missing.append("Missing connection: ");
244 missing.append(globalConnectionRegister_->name());
245 missing.append(" -> ");
246 missing.append(missingOutputs[i].first);
247 missing.append(" : ");
248 missing.append(missingOutputs[i].second);
249 results->addError(MISSING_CONNECTION, missing);
250 }
251 }
252 } else {
253 assert(false);
254 }
255 }
256 return results;
257}
258
259
260/**
261 * Does all the steps needed to check maintaining the programmability.
262 *
263 * @param results Possible error messages are added here.
264 * @return Returns the binary.
265 * @exception NotAvailable Thrown if binary creation is failed.
266 * @exception InvalidData Thrown if the binary can't be created.
267 */
270 checkPrimitiveSet(results);
271
272 if (!checkBooleanRegister(results)) {
273 // error found in boolean register check.
274 string msg = "Error found in boolean register check.";
275 throw InvalidData(__FILE__, __LINE__, __func__, msg);
276 }
277
280
281 if (globalConnectionRegister_ == NULL) {
283 "Can't determine global connection register.");
284 string msg = "Global connection register can't be determined.";
285 throw InvalidData(__FILE__, __LINE__, __func__, msg);
286 }
287
289
290 vector<pair<string, string> > missingInputs;
291 vector<pair<string, string> > missingOutputs;
294 missingInputs,
295 missingOutputs);
296
297
298 if ((missingInputs.size() > 0) || (missingOutputs.size() > 0)) {
299 for (unsigned int i = 0; i < missingInputs.size(); i++) {
300 string missing = "";
301 missing.append("Missing connection: ");
302 missing.append(missingInputs[i].first);
303 missing.append(" : ");
304 missing.append(missingInputs[i].second);
305 missing.append(" -> ");
306 missing.append(globalConnectionRegister_->name());
307 results.addError(MISSING_CONNECTION, missing);
308 }
309 for (unsigned int i = 0; i < missingOutputs.size(); i++) {
310 string missing = "";
311 missing.append("Missing connection: ");
312 missing.append(globalConnectionRegister_->name());
313 missing.append(" -> ");
314 missing.append(missingOutputs[i].first);
315 missing.append(" : ");
316 missing.append(missingOutputs[i].second);
317 results.addError(MISSING_CONNECTION, missing);
318 }
319 }
320 ProgramWriter progWriter(*program_);
321 try {
322 TPEF::Binary* binaryProgram = progWriter.createBinary();
323 return binaryProgram;
324 } catch (NotAvailable& e) {
325 throw e;
326 }
327}
328
329/**
330 * Checks the machine which primitive operations are missing.
331 *
332 * @param results Results of the validation are added to the given instance.
333 */
334void
336 ProgrammabilityValidatorResults& results) const {
337
338 std::vector<std::string> missingOps;
340
341 string msg = "Operation missing from the minimal operation set: ";
342 std::vector<std::string>::iterator it = missingOps.begin();
343 std::vector<std::string>::iterator end = missingOps.end();
344 while (it != end) {
345 results.addError(
347 msg.append(*it++));
348 }
349}
350
351
352/**
353 * Check the machine for a boolean register file. Only one is allowed.
354 * Boolean register should have size and width of one.
355 *
356 * @param results Results of the validation are added to the given instance.
357 * @return Returns true if check is passed. False is returned if error
358 * is found.
359 */
360bool
363
364 bool returnValue = true;
367 bool found = false;
368 for (int i = 0; i < nav.count(); i++) {
369 RegisterFile* rf = nav.item(i);
370 if (rf->width() == 1) {
371 if (!found) {
372 found = true;
373 booleanRegister_ = rf;
374 } else {
376 "Multiple boolean registers.");
377 returnValue = false;
378 break;
379 }
380 }
381 }
382
383 if (!found) {
385 "No boolean register found.");
386 returnValue = false;
387 }
388
389 string buses = "";
390 const Machine::BusNavigator& busNav =
392 for (int i = 0; i < busNav.count(); i++) {
393 Bus* bus = busNav.item(i);
394 for (int n = 0; n < bus->guardCount(); n++) {
395 RegisterGuard* registerGuard =
396 dynamic_cast<RegisterGuard*>(bus->guard(n));
397 if (registerGuard != NULL) {
398 if (registerGuard->parentBus() == bus &&
399 registerGuard->registerFile() == booleanRegister_ &&
400 registerGuard->registerIndex() == 0) {
401 continue;
402 } else {
403 string message =
404 "Missing boolean register guard on bus: ";
406 message.append(bus->name()));
407 returnValue = false;
408 break;
409 }
410 }
411 }
412 if (bus->guardCount() == 0) {
413 string message =
414 "Missing boolean register guard on bus: ";
416 message.append(bus->name()));
417 returnValue = false;
418 }
419 }
420 return returnValue;
421}
422
423
424/**
425 * Prints one connection.
426 *
427 * @param sourcePort The source port of the connection.
428 * @param destPort The destination port of the connection.
429 * @param segment The segment which is used in the connection.
430 * @param counter Updates the amount of printed connections.
431 */
432void
434 const Port* sourcePort,
435 const Port* destPort,
436 Segment* segment,
437 int& counter) {
438
439 const Unit* sourceUnit = sourcePort->parentUnit();
440 const Unit* destUnit = destPort->parentUnit();
441 const BaseRegisterFile* destRF =
442 dynamic_cast<const BaseRegisterFile*>(destUnit);
443 const BaseRegisterFile* sourceRF =
444 dynamic_cast<const BaseRegisterFile*>(sourceUnit);
445 const FunctionUnit* destFU =
446 dynamic_cast<const FunctionUnit*>(destUnit);
447 const FunctionUnit* sourceFU =
448 dynamic_cast<const FunctionUnit*>(sourceUnit);
449 const BaseFUPort* destBaseFUPort =
450 dynamic_cast<const BaseFUPort*>(destPort);
451 const BaseFUPort* sourceBaseFUPort =
452 dynamic_cast<const BaseFUPort*>(sourcePort);
453
454
455 if (sourceFU != 0) {
456 // move is from FU or GCU
457 if (sourceBaseFUPort->isTriggering()) {
458 // move is from trigger port
459 // this is not supported
460 return;
461 }
462 // else
463 // move is from FUPort
464
465 if (destFU != 0) {
466 // move is to FU or GCU
467
468 if (destBaseFUPort->isTriggering()) {
469 // move is to FU of CGU trigger port
470
471 for (int n = 0; n < destFU->operationCount(); n++) {
472
473 HWOperation* destOperation = destFU->operation(n);
474 counter++;
475 std::cout << sourceUnit->name() << " : "
476 << sourcePort->outputSocket()->name()
477 << " -> "
478 << destPort->inputSocket()->name() << " ("
479 << destOperation->name()
480 << ") ("
481 << segment->parentBus()->name() << ","
482 << segment->name() << ") "
483 << std::endl;
484 }
485
486 }
487 else {
488 // move is to FUPort or Special register port
489 // move is to FUPort
490 counter++;
491 std::cout << sourceUnit->name() << " : "
492 << sourcePort->outputSocket()->name()
493 << " -> "
494 << destPort->inputSocket()->name() << " ("
495 << segment->parentBus()->name() << ","
496 << segment->name() << ") "
497 << std::endl;
498 }
499
500 }
501 else { //if (destRF != 0)
502 // move is to RF
503 for (int i = 0; i < destRF->numberOfRegisters(); i++) {
504 counter++;
505 std::cout << sourceUnit->name() << " : "
506 << sourcePort->outputSocket()->name()
507 << " -> "
508 << destPort->inputSocket()->name() << "("
509 << i
510 << ") ("
511 << segment->parentBus()->name() << ","
512 << segment->name() << ") "
513 << std::endl;
514 }
515 }
516 }
517 else if (sourceRF != 0) {
518 // move is from RF or IMM
519 for (int i = 0; i < sourceRF->numberOfRegisters(); i++) {
520 if (destFU != 0) {
521 // move is to FU or GCU
522 if (destBaseFUPort->isTriggering()) {
523 // move is to FU of CGU trigger port
524
525 for (int n = 0; n < destFU->operationCount(); n++) {
526 HWOperation* destOperation = destFU->operation(n);
527 counter++;
528 std::cout << sourceUnit->name() << " : "
529 << sourcePort->outputSocket()->name()
530 << "("
531 << i << ")"
532 << " -> "
533 << destPort->inputSocket()->name() << "("
534 << destOperation->name()
535 << ") ("
536 << segment->parentBus()->name() << ","
537 << segment->name() << ") "
538 << std::endl;
539 }
540 }
541 else {
542 // move is to FUPort or Special register port
543 counter++;
544 std::cout << sourceUnit->name() << " : "
545 << sourcePort->outputSocket()->name() << "("
546 << i << ")"
547 << " -> "
548 << destPort->inputSocket()->name() << " ("
549 << segment->parentBus()->name() << ","
550 << segment->name() << ") "
551 << std::endl;
552 }
553 }
554 else { //if (destRF != 0)
555 // move is to RF
556 for (int j = 0; j < destRF->numberOfRegisters(); j++) {
557 counter++;
558 std::cout << sourceUnit->name() << " : "
559 << sourcePort->outputSocket()->name() << "("
560 << i << ")"
561 << " -> "
562 << destPort->inputSocket()->name() << "("
563 << j << ") ("
564 << segment->parentBus()->name() << ","
565 << segment->name() << ") "
566 << std::endl;
567 }
568 }
569 }
570 }
571}
572
573
574/**
575 * Finds the guard of the boolean register file.
576 *
577 * @param segment The segment where the guard is searched from.
578 * @param guard The found guard is put here.
579 */
580void
582 Segment* segment, RegisterGuard*& guard) {
583
584 Bus* bus = segment->parentBus();
585 for (int i = 0; i < bus->guardCount(); i++) {
586 RegisterGuard* registerGuard =
587 dynamic_cast<RegisterGuard*>(bus->guard(i));
588 if (registerGuard != NULL) {
589 if (registerGuard->parentBus() == bus &&
590 registerGuard->registerFile() == booleanRegister_ &&
591 registerGuard->registerIndex() == 0) {
592 guard = registerGuard;
593 }
594 }
595 }
596}
597
598
599/**
600 * Adds connection to program. Generates instruction that
601 * is given to procedure.
602 *
603 * @param sourcePort The source port of the connection.
604 * @param destPort The destination port of the connection.
605 * @param segment The segment which is used in the connection.
606 * @param counter Counter that is updated when an instruction is added.
607 */
608void
610 const Port* sourcePort,
611 const Port* destPort,
612 Segment* segment,
613 int& counter) {
614
615 const Unit* sourceUnit = sourcePort->parentUnit();
616 const Unit* destUnit = destPort->parentUnit();
617 const BaseRegisterFile* destRF =
618 dynamic_cast<const BaseRegisterFile*>(destUnit);
619 const BaseRegisterFile* sourceRF =
620 dynamic_cast<const BaseRegisterFile*>(sourceUnit);
621 const FunctionUnit* destFU = dynamic_cast<const FunctionUnit*>(destUnit);
622 const FunctionUnit* sourceFU =
623 dynamic_cast<const FunctionUnit*>(sourceUnit);
624 const BaseFUPort* destBaseFUPort =
625 dynamic_cast<const BaseFUPort*>(destPort);
626 const BaseFUPort* sourceBaseFUPort =
627 dynamic_cast<const BaseFUPort*>(sourcePort);
628
629 if (sourceFU != 0) {
630 // move is from FU or GCU
631 if (sourceBaseFUPort->isTriggering()) {
632 // move is from trigger port
633 // this is not supported
634 return;
635 }
636 // else
637 // move is from FUPort
638
639 if (destFU != 0) {
640 // move is to FU or GCU
641 const FUPort* destFUPort =
642 dynamic_cast<const FUPort*>(destBaseFUPort);
643
644 if (destBaseFUPort->isTriggering()) {
645 // move is to FU of CGU trigger port
646
647 for (int n = 0; n < destFU->operationCount(); n++) {
648 counter++;
649 HWOperation* destOperation = destFU->operation(n);
650 Instruction* instruction =
652 int destOperand = destOperation->io(*destFUPort);
653 Terminal* source =
654 new TerminalFUPort(*sourceBaseFUPort);
655 Terminal* destination =
656 new TerminalFUPort(*destOperation, destOperand);
657 RegisterGuard* guard;
658 findRegisterGuard(segment, guard);
659 MoveGuard* moveGuard = new MoveGuard(*guard);
660 auto move = std::make_shared<Move>(source,
661 destination,
662 *segment->parentBus(),
663 moveGuard);
664 instruction->addMove(move);
665 procedure_->add(instruction);
666 }
667
668 }
669 else {
670 // move is to FUPort or Special register port
671 // move is to FUPort
672 counter++;
673 Instruction* instruction =
675 Terminal* source =
676 new TerminalFUPort(*sourceBaseFUPort);
677 Terminal* destination =
678 new TerminalFUPort(*destBaseFUPort);
679 RegisterGuard* guard;
680 findRegisterGuard(segment, guard);
681 MoveGuard* moveGuard = new MoveGuard(*guard);
682 auto move = std::make_shared<Move>(source,
683 destination,
684 *segment->parentBus(),
685 moveGuard);
686 instruction->addMove(move);
687 procedure_->add(instruction);
688 }
689 }
690 else { //if (destRF != 0)
691 // move is to RF
692 for (int i = 0; i < destRF->numberOfRegisters(); i++) {
693 Instruction* instruction
695 Terminal* source = new TerminalFUPort(*sourceBaseFUPort);
696 Terminal* destination = new TerminalRegister(*destPort, i);
697 RegisterGuard* guard;
698 findRegisterGuard(segment, guard);
699 MoveGuard* moveGuard = new MoveGuard(*guard);
700 auto move = std::make_shared<Move>(source,
701 destination,
702 *segment->parentBus(),
703 moveGuard);
704 instruction->addMove(move);
705 procedure_->add(instruction);
706 counter++;
707 }
708 }
709 }
710 else if (sourceRF != 0) {
711 // move is from RF or IMM
712 for (int i = 0; i < sourceRF->numberOfRegisters(); i++) {
713 if (destFU != 0) {
714 // move is to FU or GCU
715 if (destBaseFUPort->isTriggering()) {
716 // move is to FU of CGU trigger port
717 const FUPort* destFUPort =
718 dynamic_cast<const FUPort*>(destBaseFUPort);
719 for (int n = 0; n < destFU->operationCount(); n++) {
720
721 counter++;
722 HWOperation* destOperation = destFU->operation(n);
723 Instruction* instruction =
724 new Instruction(
726 int destOperand = destOperation->io(*destFUPort);
727 Terminal* source =
728 new TerminalRegister(*sourcePort, i);
729 Terminal* destination =
730 new TerminalFUPort(*destOperation, destOperand);
731 RegisterGuard* guard;
732 findRegisterGuard(segment, guard);
733 MoveGuard* moveGuard = new MoveGuard(*guard);
734 auto move = std::make_shared<Move>(source,
735 destination,
736 *segment->parentBus(),
737 moveGuard);
738 instruction->addMove(move);
739 procedure_->add(instruction);
740 }
741 }
742 else {
743 // move is to FUPort or Special register port
744
745 counter++;
746 Instruction* instruction =
748 Terminal* source =
749 new TerminalRegister(*sourcePort, i);
750 Terminal* destination =
751 new TerminalFUPort(*destBaseFUPort);
752 RegisterGuard* guard;
753 findRegisterGuard(segment, guard);
754 MoveGuard* moveGuard = new MoveGuard(*guard);
755 auto move = std::make_shared<Move>(source,
756 destination,
757 *segment->parentBus(),
758 moveGuard);
759 instruction->addMove(move);
760 procedure_->add(instruction);
761 }
762 }
763 else { //if (destRF != 0)
764 // move is to RF
765 for (int j = 0; j < destRF->numberOfRegisters(); j++) {
766 counter++;
767 Instruction* instruction =
769 Terminal* source =
770 new TerminalRegister(*sourcePort, i);
771 Terminal* destination =
772 new TerminalRegister(*destPort, j);
773 RegisterGuard* guard;
774 findRegisterGuard(segment, guard);
775 MoveGuard* moveGuard = new MoveGuard(*guard);
776 auto move = std::make_shared<Move>(source,
777 destination,
778 *segment->parentBus(),
779 moveGuard);
780 instruction->addMove(move);
781 procedure_->add(instruction);
782 }
783 }
784 }
785 }
786}
787
788
789/**
790 * Gererates a set of segments where the socket is connected.
791 *
792 * @param connections Segments where the socket is connected
793 * is collected here.
794 * @param socket Socket which connections are searched.
795 */
796void
798 set<Segment*>& connections,
799 const Socket* socket) {
800
801 const Machine::BusNavigator& busNav =
803 for (int i = 0; i < busNav.count(); i++) {
804 Bus* bus = busNav.item(i);
805 if (socket->isConnectedTo(*bus)) {
806 for (int j = 0; j < bus->segmentCount(); j++) {
807 Segment* segment = bus->segment(j);
808 if (socket->isConnectedTo(*segment)) {
809 // we have found the bus and the segment where
810 // the socket is connected
811 connections.insert(segment);
812 }
813 }
814 }
815 }
816}
817
818
819/**
820 * Search and lists all the missing connections to the register file.
821 *
822 * @param rf The register file which connections are handled.
823 * @param toConnections Missing inputs to the register file.
824 * @param fromConnections Missing outputs from the register file.
825 */
826void
828 const RegisterFile* rf,
829 vector<pair<string, string> >& toConnections,
830 vector<pair<string, string> >& fromConnections) {
831
832 if (booleanRegister_ == NULL) {
834 checkBooleanRegister(results);
835 }
836
837 map<const Socket*, Connections> rfConnections =
838 RFConnections[rf->name()];
839
840 for (mapIter i = FUConnections.begin(); i != FUConnections.end(); i++) {
841 for (map<const Socket*,
842 Connections>::iterator n = (*i).second.begin();
843 n != (*i).second.end(); n++) {
844 if ((*n).first->direction() == Socket::OUTPUT) {
845
846 // one connection to register file is enough
847 set<Segment*> outputIntersection;
848 for (map<const Socket*,
849 Connections>::iterator m = rfConnections.begin();
850 m != rfConnections.end(); m++) {
851 if ((*m).first->direction() == Socket::INPUT) {
853 (*n).second.outputs,
854 (*m).second.inputs,
855 outputIntersection);
856 }
857 }
858 if (outputIntersection.size() == 0) {
859 toConnections.push_back(
860 pair<string, string>(
861 (*i).first,
862 (*n).first->name()));
863 }
864 } else if ((*n).first->direction() == Socket::INPUT) {
865 set<Segment*> inputIntersection;
866 for (map<const Socket*,
867 Connections>::iterator m = rfConnections.begin();
868 m != rfConnections.end(); m++) {
869 if ((*m).first->direction() == Socket::OUTPUT) {
871 (*n).second.inputs,
872 (*m).second.outputs,
873 inputIntersection);
875 (*n).second.triggeredInputs,
876 (*m).second.outputs,
877 inputIntersection);
878 }
879 }
880 if (inputIntersection.size() == 0) {
881 fromConnections.push_back(
882 pair<string, string>((*i).first,
883 (*n).first->name()));
884 }
885 }
886 }
887 }
888
889 for (mapIter i = GCUConnections.begin();
890 i != GCUConnections.end(); i++) {
891
892 for (map<const Socket*,
893 Connections>::iterator n = (*i).second.begin();
894 n != (*i).second.end(); n++) {
895 if ((*n).first->direction() == Socket::OUTPUT) {
896
897 // one connection to register file is enough
898 set<Segment*> outputIntersection;
899 for (map<const Socket*,
900 Connections>::iterator m = rfConnections.begin();
901 m != rfConnections.end(); m++) {
902 if ((*m).first->direction() == Socket::INPUT) {
904 (*n).second.outputs,
905 (*m).second.inputs,
906 outputIntersection);
907 }
908 }
909 if (outputIntersection.size() == 0) {
910 toConnections.push_back(
911 pair<string, string>(
912 (*i).first, (*n).first->name()));
913 }
914 } else if ((*n).first->direction() == Socket::INPUT) {
915 set<Segment*> inputIntersection;
916 for (map<const Socket*,
917 Connections>::iterator m = rfConnections.begin();
918 m != rfConnections.end(); m++) {
919 if ((*m).first->direction() == Socket::OUTPUT) {
921 (*n).second.inputs,
922 (*m).second.outputs,
923 inputIntersection);
925 (*n).second.triggeredInputs,
926 (*m).second.outputs,
927 inputIntersection);
928 }
929 }
930 if (inputIntersection.size() == 0) {
931 fromConnections.push_back(
932 pair<string, string>(
933 (*i).first, (*n).first->name()));
934 }
935 }
936 }
937 }
938
939 for (mapIter i = IMMConnections.begin();
940 i != IMMConnections.end(); i++) {
941
942 set<Segment*> outputIntersection;
943 set<Segment*> inputIntersection;
944 for (map<const Socket*,
945 Connections>::iterator n = (*i).second.begin();
946 n != (*i).second.end(); n++) {
947 if ((*n).first->direction() == Socket::OUTPUT) {
948
949 // one connection to register file is enough
950 for (map<const Socket*,
951 Connections>::iterator m = rfConnections.begin();
952 m != rfConnections.end(); m++) {
953 if ((*m).first->direction() == Socket::INPUT) {
955 (*n).second.outputs,
956 (*m).second.inputs,
957 outputIntersection);
958 }
959 }
960 }
961 }
962 if (outputIntersection.size() == 0) {
963 toConnections.push_back(pair<string, string>((*i).first, "-"));
964 }
965 }
966
967
968 for (mapIter i = RFConnections.begin(); i != RFConnections.end(); i++) {
969 set<Segment*> outputIntersection;
970 set<Segment*> inputIntersection;
971 for (map<const Socket*,
972 Connections>::iterator n = (*i).second.begin();
973 n != (*i).second.end(); n++) {
974
975 if ((*n).first->direction() == Socket::OUTPUT) {
976
977 // one connection to register file is enough
978 for (map<const Socket*,
979 Connections>::iterator m = rfConnections.begin();
980 m != rfConnections.end(); m++) {
981
982 if ((*m).first->direction() == Socket::INPUT) {
984 (*n).second.outputs,
985 (*m).second.inputs,
986 outputIntersection);
987 }
988 }
989 } else if ((*n).first->direction() == Socket::INPUT) {
990 for (map<const Socket*,
991 Connections>::iterator m = rfConnections.begin();
992 m != rfConnections.end(); m++) {
993
994 if ((*m).first->direction() == Socket::OUTPUT) {
996 (*n).second.inputs,
997 (*m).second.outputs,
998 inputIntersection);
999 }
1000 }
1001 }
1002 }
1003 if (outputIntersection.size() == 0) {
1004 toConnections.push_back(pair<string, string>((*i).first, "-"));
1005 }
1006 if (inputIntersection.size() == 0) {
1007
1008 // Connection to the boolean register file is not needed
1009 if (booleanRegister_ != NULL &&
1010 (*i).first != booleanRegister_->name()) {
1011 fromConnections.push_back(
1012 pair<string, string>((*i).first, "-"));
1013 }
1014 }
1015 }
1016}
1017
1018
1019/**
1020 * Prints the missing connections to the register file.
1021 *
1022 * @param rf The register file which connections are handled.
1023 */
1024void
1026
1027 map<const Socket*, Connections> rfConnections =
1028 RFConnections[rf->name()];
1029
1030 for (mapIter i = FUConnections.begin(); i != FUConnections.end(); i++) {
1031 for (map<const Socket*,
1032 Connections>::iterator n = (*i).second.begin();
1033 n != (*i).second.end(); n++) {
1034
1035 if ((*n).first->direction() == Socket::OUTPUT) {
1036
1037 // one connection to register file is enough
1038 set<Segment*> outputIntersection;
1039 for (map<const Socket*,
1040 Connections>::iterator m = rfConnections.begin();
1041 m != rfConnections.end(); m++) {
1042
1043 if ((*m).first->direction() == Socket::INPUT) {
1045 (*n).second.outputs,
1046 (*m).second.inputs,
1047 outputIntersection);
1048 }
1049 }
1050 if (outputIntersection.size() == 0) {
1051 cout << "Missing connection: " << (*i).first
1052 << ": " << (*n).first->name()
1053 << " -> " << rf->name() << ": " << endl;
1054 }
1055 } else if ((*n).first->direction() == Socket::INPUT) {
1056 set<Segment*> inputIntersection;
1057 for (map<const Socket*,
1058 Connections>::iterator m = rfConnections.begin();
1059 m != rfConnections.end(); m++) {
1060
1061 if ((*m).first->direction() == Socket::OUTPUT) {
1063 (*n).second.inputs,
1064 (*m).second.outputs,
1065 inputIntersection);
1067 (*n).second.triggeredInputs,
1068 (*m).second.outputs,
1069 inputIntersection);
1070 }
1071 }
1072 if (inputIntersection.size() == 0) {
1073 cout << "Missing connection: " << rf->name()
1074 << " -> " << (*i).first
1075 << ": " << (*n).first->name() << endl;
1076 }
1077 }
1078 }
1079 }
1080
1081 for (mapIter i = GCUConnections.begin();
1082 i != GCUConnections.end(); i++) {
1083
1084 for (map<const Socket*,
1085 Connections>::iterator n = (*i).second.begin();
1086 n != (*i).second.end(); n++) {
1087
1088 if ((*n).first->direction() == Socket::OUTPUT) {
1089
1090 // one connection to register file is enough
1091 set<Segment*> outputIntersection;
1092 for (map<const Socket*,
1093 Connections>::iterator m = rfConnections.begin();
1094 m != rfConnections.end(); m++) {
1095
1096 if ((*m).first->direction() == Socket::INPUT) {
1098 (*n).second.outputs,
1099 (*m).second.inputs,
1100 outputIntersection);
1101 }
1102 }
1103 if (outputIntersection.size() == 0) {
1104 cout << "Missing connection: " << (*i).first
1105 << ": " << (*n).first->name()
1106 << " -> " << rf->name() << endl;
1107 }
1108 } else if ((*n).first->direction() == Socket::INPUT) {
1109 set<Segment*> inputIntersection;
1110 for (map<const Socket*,
1111 Connections>::iterator m = rfConnections.begin();
1112 m != rfConnections.end(); m++) {
1113
1114 if ((*m).first->direction() == Socket::OUTPUT) {
1116 (*n).second.inputs,
1117 (*m).second.outputs,
1118 inputIntersection);
1120 (*n).second.triggeredInputs,
1121 (*m).second.outputs,
1122 inputIntersection);
1123 }
1124 }
1125 if (inputIntersection.size() == 0) {
1126 cout << "Missing connection: " << rf->name()
1127 << " -> " << (*i).first
1128 << ": " << (*n).first->name() << endl;
1129 }
1130 }
1131 }
1132 }
1133
1134 for (mapIter i = IMMConnections.begin();
1135 i != IMMConnections.end(); i++) {
1136
1137 set<Segment*> outputIntersection;
1138 set<Segment*> inputIntersection;
1139 for (map<const Socket*,
1140 Connections>::iterator n = (*i).second.begin();
1141 n != (*i).second.end(); n++) {
1142
1143 if ((*n).first->direction() == Socket::OUTPUT) {
1144
1145 // one connection to register file is enough
1146 for (map<const Socket*,
1147 Connections>::iterator m = rfConnections.begin();
1148 m != rfConnections.end(); m++) {
1149
1150 if ((*m).first->direction() == Socket::INPUT) {
1152 (*n).second.outputs,
1153 (*m).second.inputs,
1154 outputIntersection);
1155 }
1156 }
1157 }
1158 }
1159 if (outputIntersection.size() == 0) {
1160 cout << "Missing connection: " << (*i).first
1161 << " -> " << rf->name() << endl;
1162 }
1163 }
1164
1165 for (mapIter i = RFConnections.begin(); i != RFConnections.end(); i++) {
1166 set<Segment*> outputIntersection;
1167 set<Segment*> inputIntersection;
1168 for (map<const Socket*,
1169 Connections>::iterator n = (*i).second.begin();
1170 n != (*i).second.end(); n++) {
1171
1172 if ((*n).first->direction() == Socket::OUTPUT) {
1173
1174 // one connection to register file is enough
1175 for (map<const Socket*,
1176 Connections>::iterator m = rfConnections.begin();
1177 m != rfConnections.end(); m++) {
1178
1179 if ((*m).first->direction() == Socket::INPUT) {
1181 (*n).second.outputs,
1182 (*m).second.inputs,
1183 outputIntersection);
1184 }
1185 }
1186 } else if ((*n).first->direction() == Socket::INPUT) {
1187 for (map<const Socket*,
1188 Connections>::iterator m = rfConnections.begin();
1189 m != rfConnections.end(); m++) {
1190
1191 if ((*m).first->direction() == Socket::OUTPUT) {
1193 (*n).second.inputs,
1194 (*m).second.outputs,
1195 inputIntersection);
1196 }
1197 }
1198 }
1199 }
1200 if (outputIntersection.size() == 0) {
1201 cout << "Missing connection: " << (*i).first
1202 << " -> " << rf->name() << endl;
1203 }
1204 if (inputIntersection.size() == 0) {
1205 cout << "Missing connection: " << rf->name()
1206 << " -> " << (*i).first << endl;
1207 }
1208 }
1209}
1210
1211
1212/**
1213 * Adds new connections to all connections holding set.
1214 *
1215 * @param newConnections New connections that can be added.
1216 * @param connections All connections holding set.
1217 */
1218void
1220 set<Segment*>& newConnections,
1221 set<Segment*>& connections) {
1222
1223 set<Segment*>::iterator i = newConnections.begin();
1224 for (; i != newConnections.end(); i++) {
1225 connections.insert(*i);
1226 }
1227}
1228
1229
1230/**
1231 * Adds operations to connections.
1232 *
1233 * @param fu The function unit that is the parentunit for the operations.
1234 * @param opertations Set of FWOperations where new operations are added.
1235 */
1236void
1238 const FunctionUnit* fu,
1239 set<HWOperation*>& operations) {
1240
1241 for (int i = 0; i < fu->operationCount(); i++) {
1242 operations.insert(fu->operation(i));
1243 }
1244}
1245
1246
1247/**
1248 * Finds out the connections to the register file and stores
1249 * those in the procedure.
1250 */
1251void
1253
1254 vector<ConnectionSet>::iterator connectionIter = directConnections.begin();
1255 for (; connectionIter != directConnections.end(); connectionIter++) {
1256 if ((*connectionIter).sourcePort->parentUnit() ==
1258 (*connectionIter).destPort->parentUnit() ==
1260
1262 (*connectionIter).sourcePort,
1263 (*connectionIter).destPort,
1264 (*connectionIter).segment);
1265 }
1266 }
1268}
1269
1270
1271/**
1272 * Adds global connection register connection to list of GCR connections.
1273 * Moves can be genetated from these connections.
1274 *
1275 * @param sourcePort Source port of the move.
1276 * @param destPort Destionation port of the move.
1277 * @param segment The segment of the move.
1278 */
1279void
1281 const Port* sourcePort,
1282 const Port* destPort,
1283 Segment* segment) {
1284
1285 pair<const Port*, const Port*> connectionPair =
1286 pair<const Port*, const Port*>(sourcePort, destPort);
1287 pair<portSetIter, bool> result = gcrConnections.insert(connectionPair);
1288 // If the insertion was made the connection
1289 // can be added and it is unique.
1290 if (result.second) {
1291
1292 // Find out if the source or destination unit is Register File.
1293 // Only one connection per port to RF and from RF to port is needed.
1294 const Unit* destUnit = destPort->parentUnit();
1295 const RegisterFile* destRegister =
1296 dynamic_cast<const RegisterFile*>(destUnit);
1297 const Unit* sourceUnit = sourcePort->parentUnit();
1298 const RegisterFile* sourceRegister =
1299 dynamic_cast<const RegisterFile*>(sourceUnit);
1300
1301 if (destRegister != NULL) {
1302 if (sourceRegister != NULL) {
1303 pair<const RegisterFile*,
1304 const RegisterFile*> registerRegisterPair =
1305 pair<const RegisterFile*, const RegisterFile*>(
1306 sourceRegister, destRegister);
1307 pair<registerRegisterSetIter, bool> registerRegisterResult =
1308 gcrRegisterConnections.insert(registerRegisterPair);
1309 if (registerRegisterResult.second) {
1310 ConnectionSet newSet;
1311 newSet.sourcePort = sourcePort;
1312 newSet.destPort = destPort;
1313 newSet.segment = segment;
1314 globalRegisterConnections.push_back(newSet);
1315 }
1316 } else {
1317 // destination is a register but source is not
1318 pair<const Port*, const RegisterFile*> portRegisterPair =
1319 pair<const Port*, const RegisterFile*>(
1320 sourcePort, destRegister);
1321 pair<portRegisterSetIter, bool> portRegisterResult =
1322 portGcrConnections.insert(portRegisterPair);
1323 if (portRegisterResult.second) {
1324 ConnectionSet newSet;
1325 newSet.sourcePort = sourcePort;
1326 newSet.destPort = destPort;
1327 newSet.segment = segment;
1328 globalRegisterConnections.push_back(newSet);
1329 }
1330 }
1331 } else if (sourceRegister != NULL) {
1332 pair<const RegisterFile*, const Port*> registerPortPair =
1333 pair<const RegisterFile*, const Port*>(
1334 sourceRegister, destPort);
1335 pair<registerPortSetIter, bool> registerPortResult =
1336 gcrPortConnections.insert(registerPortPair);
1337 if (registerPortResult.second) {
1338 ConnectionSet newSet;
1339 newSet.sourcePort = sourcePort;
1340 newSet.destPort = destPort;
1341 newSet.segment = segment;
1342 globalRegisterConnections.push_back(newSet);
1343 }
1344 } else {
1345 // source or destination should be register
1346 assert(false);
1347 }
1348 }
1349}
1350
1351
1352/**
1353 * Prints connections from and to the global connection register.
1354 */
1355void
1357
1358 int counter = 0;
1359 for (unsigned int i = 0; i < globalRegisterConnections.size(); i++) {
1360 ConnectionSet setToBePrinted = globalRegisterConnections[i];
1361 printConnection(setToBePrinted.sourcePort,
1362 setToBePrinted.destPort,
1363 setToBePrinted.segment,
1364 counter);
1365 }
1366 cout << "----------------------------------------" << endl;
1367 cout << "Total: " << counter << " connections" << endl;
1368}
1369
1370
1371/**
1372 * Finds out all the connections in the machine.
1373 *
1374 * @param printConnections Flag for printing of connections.
1375 */
1376void
1378
1379 const Machine::FunctionUnitNavigator& fuNav =
1381 for (int i = 0; i < fuNav.count(); i++) {
1382 const FunctionUnit* fu = fuNav.item(i);
1383 map<const Socket*, Connections> fuConnections;
1384
1385 // for every port we need to check which kind of socket
1386 // the port is connected to
1387 for (int j = 0; j < fu->portCount(); j++) {
1388 const Port* port = fu->port(j);
1389 const BaseFUPort* baseFUPort =
1390 dynamic_cast<const BaseFUPort*>(port);
1391 const Socket* socket = port->inputSocket();
1392
1393 // if not null, socket is an input socket
1394 if (socket != NULL) {
1395
1396 Connections connections;
1397 set<Segment*> fuInputs;
1398
1399 // connections to the input socket are listed to fuInputs
1400 listConnections(fuInputs, socket);
1401
1402 if (baseFUPort->isTriggering()) {
1403 addConnections(fuInputs, connections.triggeredInputs);
1404 addOperationConnections(fu, connections.operations);
1405 } else {
1406 addConnections(fuInputs, connections.inputs);
1407 }
1408 fuConnections[socket] = connections;
1409 inputs.push_back(pair<const Port*, set<Segment*> >(
1410 port, fuInputs));
1411 }
1412 }
1413 FUConnections[fu->name()] = fuConnections;
1414 }
1415 const Machine::RegisterFileNavigator& rfNav =
1417 for (int i = 0; i < rfNav.count(); i++) {
1418
1419 const RegisterFile* rf = rfNav.item(i);
1420 map<const Socket*, Connections> rfConnections;
1421
1422 for (int j = 0; j < rf->portCount(); j++) {
1423 const Port* port = rf->port(j);
1424 const Socket* socket = port->inputSocket();
1425
1426 // if not null, socket is an input socket
1427 if (socket != NULL) {
1428
1429 Connections connections;
1430 set<Segment*> rfInputs;
1431 listConnections(rfInputs, socket);
1432 addConnections(rfInputs, connections.inputs);
1433 connections.registers = rf->numberOfRegisters();
1434 rfConnections[socket] = connections;
1435 inputs.push_back(
1436 pair<const Port*,
1437 set<Segment*> >(port, rfInputs));
1438 }
1439 }
1440 RFConnections[rf->name()] = rfConnections;
1441
1442 }
1443
1444 const ControlUnit* gcu = machine_.controlUnit();
1445 if (gcu != NULL) {
1446 map<const Socket*, Connections> gcuConnections;
1447 for (int j = 0; j < gcu->portCount(); j++) {
1448 const Port* port = gcu->port(j);
1449 const BaseFUPort* baseFUPort =
1450 dynamic_cast<const BaseFUPort*>(port);
1451 const Socket* socket = port->inputSocket();
1452
1453 // if not null, socket is an input socket
1454 if (socket != NULL) {
1455 Connections connections;
1456 set<Segment*> gcuInputs;
1457 listConnections(gcuInputs, socket);
1458 if (baseFUPort->isTriggering()) {
1459 addConnections(gcuInputs, connections.triggeredInputs);
1460 addOperationConnections(gcu, connections.operations);
1461 } else {
1462 addConnections(gcuInputs, connections.inputs);
1463 }
1464 inputs.push_back(
1465 pair<const Port*,
1466 set<Segment*> >(port, gcuInputs));
1467 connections.registers = 0;
1468 gcuConnections[socket] = connections;
1469 }
1470 }
1471 GCUConnections[gcu->name()] = gcuConnections;
1472 }
1473
1474
1475 // now we look for output sockets
1476
1477 for (int i = 0; i < fuNav.count(); i++) {
1478 const FunctionUnit* fu = fuNav.item(i);
1479 set<const Socket*> outputs;
1480 for (int j = 0; j < fu->portCount(); j++) {
1481 const Port* port = fu->port(j);
1482 const Socket* socket = port->outputSocket();
1483
1484 // if not null, socket is an output socket
1485 if (socket != NULL) {
1486
1487 set<Segment*> outputConnections;
1488 listConnections(outputConnections, socket);
1489 // go through every input
1490 for (unsigned int k = 0; k < inputs.size(); k++) {
1491 set<Segment*> intersection;
1492
1493 // do an intersection between
1494 // inputs and socket connections
1496 outputConnections,
1497 intersection);
1498
1499 // go through all the connections of
1500 // the intersection result
1501 map<const Socket*, Connections> socketConnections =
1502 FUConnections[fu->name()];
1503 Connections connections = socketConnections[socket];
1504
1505 set<Segment*>::iterator iter =
1506 intersection.begin();
1507 for (; iter != intersection.end(); iter++) {
1508
1510 connections.outputs,
1511 *iter)) {
1512 connections.outputs.insert(*iter);
1513 }
1514 addDirectConnection(port, inputs[k].first, *iter);
1515 }
1516 socketConnections[socket] = connections;
1517 FUConnections[fu->name()] = socketConnections;
1518 }
1519 }
1520 }
1521 }
1522 for (int i = 0; i < rfNav.count(); i++) {
1523 const TTAMachine::RegisterFile* rf = rfNav.item(i);
1524 set<const Socket*> outputs;
1525 for (int j = 0; j < rf->portCount(); j++) {
1526 const Port* port = rf->port(j);
1527 const Socket* socket = port->outputSocket();
1528
1529 // if not null, socket is an output socket
1530 if (socket != NULL) {
1531 set<Segment*> outputConnections;
1532 listConnections(outputConnections, socket);
1533
1534 for (unsigned int k = 0; k < inputs.size(); k++) {
1535 set<Segment*> intersection;
1536
1537
1539 outputConnections,
1540 intersection);
1541 map<const Socket*, Connections> socketConnections =
1542 RFConnections[rf->name()];
1543 Connections connections = socketConnections[socket];
1544
1545 set<Segment*>::iterator iter =
1546 intersection.begin();
1547 for (; iter != intersection.end(); iter++) {
1548
1550 connections.outputs,
1551 *iter)) {
1552 connections.outputs.insert(*iter);
1553 }
1554 addDirectConnection(port, inputs[k].first, *iter);
1555 }
1556 socketConnections[socket] = connections;
1557 RFConnections[rf->name()] = socketConnections;
1558 }
1559 }
1560 }
1561 }
1562
1563 const Machine::ImmediateUnitNavigator& immNav =
1565 for (int i = 0; i < immNav.count(); i++) {
1566 const TTAMachine::ImmediateUnit* imm = immNav.item(i);
1567
1568 set<const Socket*> outputs;
1569 for (int j = 0; j < imm->portCount(); j++) {
1570 const Port* port = imm->port(j);
1571 const Socket* socket = port->outputSocket();
1572
1573 // if not null, socket is an output socket
1574 if (socket != NULL) {
1575 set<Segment*> outputConnections;
1576 listConnections(outputConnections, socket);
1577 for (unsigned int k = 0; k < inputs.size(); k++) {
1578 set<Segment*> intersection;
1580 outputConnections,
1581 intersection);
1582 map<const Socket*, Connections> socketConnections =
1583 IMMConnections[imm->name()];
1584 Connections connections = socketConnections[socket];
1585
1586 set<Segment*>::iterator iter =
1587 intersection.begin();
1588 for (; iter != intersection.end(); iter++) {
1589
1591 connections.outputs,
1592 *iter)) {
1593
1594 connections.outputs.insert(*iter);
1595 }
1596 addDirectConnection(port, inputs[k].first, *iter);
1597 }
1598 connections.registers = imm->numberOfRegisters();
1599 socketConnections[socket] = connections;
1600 IMMConnections[imm->name()] = socketConnections;
1601 }
1602 }
1603 }
1604 }
1605 if (gcu != NULL) {
1606 set<const Socket*> outputs;
1607 for (int j = 0; j < gcu->portCount(); j++) {
1608 const Port* port = gcu->port(j);
1609 const Socket* socket = port->outputSocket();
1610
1611 // if not null, socket is an output socket
1612 if (socket != NULL) {
1613 set<Segment*> outputConnections;
1614 listConnections(outputConnections, socket);
1615 for (unsigned int k = 0; k < inputs.size(); k++) {
1616 set<Segment*> intersection;
1618 outputConnections,
1619 intersection);
1620 map<const Socket*, Connections> socketConnections =
1621 GCUConnections[gcu->name()];
1622 Connections connections = socketConnections[socket];
1623
1624 set<Segment*>::iterator iter =
1625 intersection.begin();
1626 for (; iter != intersection.end(); iter++) {
1627
1629 connections.outputs,
1630 *iter)) {
1631 connections.outputs.insert(*iter);
1632 }
1633 addDirectConnection(port, inputs[k].first, *iter);
1634 }
1635 socketConnections[socket] = connections;
1636 GCUConnections[gcu->name()] = socketConnections;
1637 }
1638 }
1639 }
1640 }
1641}
1642
1643
1644/**
1645 * Adds all connections found in the machine to program.
1646 */
1647void
1649
1650 // add all collected source - destination - segment sets to program
1651 for (unsigned int i = 0; i < directConnections.size(); i++) {
1652 ConnectionSet setToBeAdded = directConnections[i];
1654 setToBeAdded.destPort,
1655 setToBeAdded.segment,
1657 }
1658}
1659
1660
1661/**
1662 * Adds global connection registers connections to program.
1663 */
1664void
1666
1667 // add all collected source - destination - segment sets to program
1668 for (unsigned int i = 0; i < globalRegisterConnections.size(); i++) {
1669 ConnectionSet setToBeAdded = globalRegisterConnections[i];
1671 setToBeAdded.destPort,
1672 setToBeAdded.segment,
1673 gcrCounter);
1674 }
1675}
1676
1677
1678/**
1679 * Adds direct connection (unit to unit) to list of direct connections.
1680 * Moves can be genetated from these connections.
1681 *
1682 * @param sourcePort Source port of the move.
1683 * @param destPort Destionation port of the move.
1684 * @param segment The segment of the move.
1685 */
1686void
1688 const Port* sourcePort,
1689 const Port* destPort,
1690 Segment* segment) {
1691
1692 pair<const Port*, const Port*> connectionPair =
1693 pair<const Port*, const Port*>(sourcePort, destPort);
1694 pair<portSetIter, bool> result = allConnections.insert(connectionPair);
1695 // If the insertion was made the connection
1696 // can be added and it is unique.
1697 if (result.second) {
1698
1699 // Find out if the source or destination unit is Register File.
1700 // Only one connection per port to RF and from RF to port is needed.
1701 const Unit* destUnit = destPort->parentUnit();
1702 const RegisterFile* destRegister =
1703 dynamic_cast<const RegisterFile*>(destUnit);
1704 const Unit* sourceUnit = sourcePort->parentUnit();
1705 const RegisterFile* sourceRegister =
1706 dynamic_cast<const RegisterFile*>(sourceUnit);
1707
1708 if (destRegister != NULL) {
1709 if (sourceRegister != NULL) {
1710 pair<const RegisterFile*,
1711 const RegisterFile*> registerRegisterPair =
1712 pair<const RegisterFile*, const RegisterFile*>(
1713 sourceRegister, destRegister);
1714 pair<registerRegisterSetIter, bool> registerRegisterResult =
1715 registerRegisterConnections.insert(registerRegisterPair);
1716 if (registerRegisterResult.second) {
1717 ConnectionSet newSet;
1718 newSet.sourcePort = sourcePort;
1719 newSet.destPort = destPort;
1720 newSet.segment = segment;
1721 directConnections.push_back(newSet);
1722 }
1723 } else {
1724 // destination is a register but source is not
1725 pair<const Port*, const RegisterFile*> portRegisterPair =
1726 pair<const Port*, const RegisterFile*>(
1727 sourcePort, destRegister);
1728 pair<portRegisterSetIter, bool> portRegisterResult =
1729 portRegisterConnections.insert(portRegisterPair);
1730 if (portRegisterResult.second) {
1731 ConnectionSet newSet;
1732 newSet.sourcePort = sourcePort;
1733 newSet.destPort = destPort;
1734 newSet.segment = segment;
1735 directConnections.push_back(newSet);
1736 }
1737 }
1738 } else if (sourceRegister != NULL) {
1739 pair<const RegisterFile*, const Port*> registerPortPair =
1740 pair<const RegisterFile*, const Port*>(
1741 sourceRegister, destPort);
1742 pair<registerPortSetIter, bool> registerPortResult =
1743 registerPortConnections.insert(registerPortPair);
1744 if (registerPortResult.second) {
1745 ConnectionSet newSet;
1746 newSet.sourcePort = sourcePort;
1747 newSet.destPort = destPort;
1748 newSet.segment = segment;
1749 directConnections.push_back(newSet);
1750 }
1751 } else {
1752 ConnectionSet newSet;
1753 newSet.sourcePort = sourcePort;
1754 newSet.destPort = destPort;
1755 newSet.segment = segment;
1756 directConnections.push_back(newSet);
1757 }
1758 }
1759}
1760
1761
1762/**
1763 * Prints all connections found in the machine.
1764 */
1765void
1767
1768 int counter = 0;
1769 for (unsigned int i = 0; i < directConnections.size(); i++) {
1770 ConnectionSet setToBePrinted = directConnections[i];
1771 printConnection(setToBePrinted.sourcePort,
1772 setToBePrinted.destPort,
1773 setToBePrinted.segment,
1774 counter);
1775 }
1776 cout << "---------------------------" << endl;
1777 cout << "Total: " << counter << " connections" << endl;
1778}
1779
1780
1781/**
1782 * Finds the global connection register out of the machine.
1783 *
1784 * The global connection register is register that has the best connecticity.
1785 *
1786 * @return Pointer to the global connection register.
1787 */
1788const RegisterFile*
1790
1791 const RegisterFile* gcRegister = 0;
1792
1793 int maxConnectivity = 0;
1794 int maxInputs = 0;
1795 int maxOutputs = 0;
1796
1797 const Machine::RegisterFileNavigator& rfNav =
1799 const Machine::BusNavigator& busNav =
1801
1802 int maxWidth = 0;
1803
1804 for (int i = 0; i < busNav.count(); i++) {
1805 Bus* bus = busNav.item(i);
1806 int width = bus->width();
1807
1808 // find out the biggest bus width of the machine
1809 if (width > maxWidth) {
1810 maxWidth = width;
1811 }
1812 }
1813
1814 for (int i = 0; i < rfNav.count(); i++) {
1815 const RegisterFile* rf = rfNav.item(i);
1816
1817 if (rf->width() >= maxWidth) {
1818 map<const Socket*, Connections> rfConns =
1819 RFConnections[rf->name()];
1820 set<Segment*> intersection;
1821
1822 int inputs = 0;
1823 int outputs = 0;
1824 for (map<const Socket*,
1825 Connections>::iterator n = rfConns.begin();
1826 n != rfConns.end(); n++) {
1827
1828 inputs += (*n).second.inputs.size();
1829 outputs += (*n).second.outputs.size();
1830 }
1831 int sum = inputs + outputs;
1832 int connectivity = 0;
1833 if (inputs > outputs) {
1834 connectivity = sum - (inputs - outputs);
1835 } else {
1836 connectivity = sum - (outputs - inputs);
1837 }
1838 if (connectivity > maxConnectivity) {
1839 gcRegister = rf;
1840 maxConnectivity = connectivity;
1841 maxInputs = inputs;
1842 maxOutputs = outputs;
1843 } else if (connectivity == maxConnectivity) {
1844 if (sum > (maxInputs + maxOutputs)) {
1845 gcRegister = rf;
1846 maxConnectivity = connectivity;
1847 maxInputs = inputs;
1848 maxOutputs = outputs;
1849 }
1850 }
1851 }
1852 }
1853 globalConnectionRegister_ = const_cast<RegisterFile*>(gcRegister);
1854 return gcRegister;
1855}
#define __func__
#define assert(condition)
TTAMachine::Machine * machine
the architecture definition of the estimated processor
static bool containsValue(const ContainerType &aContainer, const ElementType &aKey)
MachineValidatorResults * validate(const std::set< ErrorCode > &errorsToCheck) const
ErrorCode
Error codes for different errors.
@ GCU_AS_MISSING
Address space missing in GCU.
@ GCU_MISSING
GCU missing in machine.
void missingOperations(const TTAMachine::Machine &machine, std::vector< std::string > &missingOps) const
void addError(ProgrammabilityValidator::ErrorCode code, const std::string &errorMsg)
set< pair< const RegisterFile *, const RegisterFile * > > gcrRegisterConnections
void addOperationConnections(const FunctionUnit *fu, set< HWOperation * > &operations)
void searchMissingRFConnections(const RegisterFile *rf, vector< pair< string, string > > &toConnections, vector< pair< string, string > > &fromConnections)
map< string, map< const Socket *, Connections > > FUConnections
Function unit connections.
int gcrCounter
The counter of global register file connections added to the program.
RegisterFile * booleanRegister_
Boolean register file of the machine.
ProgrammabilityValidator(const Machine &machine)
ErrorCode
Error codes for different errors.
@ BOOLEAN_REGISTER_GUARD_MISSING
Bus is missing a boolean register file guard.
@ OPERATION_MISSING_FROM_THE_PRIMITIVE_OPERATION_SET
Machine don't have all the operations needed to support ANSI C.
@ GLOBAL_CONNECTION_REGISTER_NOT_FOUND
Global connection register could not be determined.
@ MISSING_CONNECTION
Connection is missing to or from the global connection register.
@ BOOLEAN_REGISTER_ERROR
Machine should have one and only one boolean register.
const Machine & machine_
the target machine
map< string, map< const Socket *, Connections > > RFConnections
Register file connections.
void addGlobalRegisterConnection(const Port *sourcePort, const Port *destPort, Segment *segment)
vector< pair< const Port *, set< Segment * > > > inputs
All inputs found in the machine are stored here.
set< pair< const Port *, const Port * > > gcrConnections
bool checkBooleanRegister(ProgrammabilityValidatorResults &results)
int directCounter
The counter of direct connections added to the program.
set< pair< const Port *, const Port * > > allConnections
Set of connections to ensure that same Move is not done in multiple buses.
set< pair< const RegisterFile *, const RegisterFile * > > registerRegisterConnections
void addDirectConnection(const Port *sourcePort, const Port *destPort, Segment *segment)
map< string, map< constSocket *, Connections > >::iterator mapIter
type definition for going through connection maps
RegisterFile * globalConnectionRegister_
The global connection register of the machine.
vector< ConnectionSet > globalRegisterConnections
Storage of all Moves to and from the Global Connection Register.
void checkPrimitiveSet(ProgrammabilityValidatorResults &results) const
void printConnection(const Port *sourcePort, const Port *destPort, Segment *segment, int &counter)
Procedure * procedure_
Procedure of the program.
void printNotConnectedSockets(const RegisterFile *rf)
void addConnectionToProgram(const Port *sourcePort, const Port *destPort, Segment *segment, int &counter)
map< string, map< const Socket *, Connections > > IMMConnections
Immediate unit connections.
void listConnections(set< Segment * > &connections, const Socket *socket)
MinimalOpSetCheck * minimalOpSetCheck_
Minimal operation checker.
const RegisterFile * findGlobalConnectionRegister()
set< pair< const Port *, const RegisterFile * > > portGcrConnections
TPEF::Binary * profile(ProgrammabilityValidatorResults &results)
set< pair< const RegisterFile *, const Port * > > gcrPortConnections
vector< ConnectionSet > directConnections
Storage of all the Moves that are found in the machine.
map< string, map< const Socket *, Connections > > GCUConnections
Global control unit connections.
set< pair< const RegisterFile *, const Port * > > registerPortConnections
Program * program_
Program where moves are generated.
void addConnections(set< Segment * > &newConnections, set< Segment * > &connections)
set< pair< const Port *, const RegisterFile * > > portRegisterConnections
Set of unit connections to ensure that only one connection per register file is added.
ProgrammabilityValidatorResults * validate()
void findRegisterGuard(Segment *segment, RegisterGuard *&guard)
static void intersection(const std::set< ValueType > &firstContainer, const std::set< ValueType > &secondContainer, std::set< ValueType > &intersection)
virtual bool isTriggering() const =0
virtual int numberOfRegisters() const
virtual int width() const
virtual RFPort * port(const std::string &name) const
virtual Segment * segment(int index) const
Definition Bus.cc:329
int width() const
Definition Bus.cc:149
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 TCEString name() const
virtual AddressSpace * addressSpace() const
virtual HWOperation * operation(const std::string &name) const
virtual int operationCount() const
virtual BaseFUPort * port(const std::string &name) const
virtual Bus * parentBus() const
int io(const FUPort &port) const
const std::string & name() const
ComponentType * item(int index) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
static NullInstructionTemplate & instance()
virtual Socket * outputSocket() const
Definition Port.cc:281
Unit * parentUnit() const
virtual Socket * inputSocket() const
Definition Port.cc:261
const RegisterFile * registerFile() const
std::string name() const
Bus * parentBus() const
@ OUTPUT
Data goes from port to bus.
Definition Socket.hh:60
@ INPUT
Data goes from bus to port.
Definition Socket.hh:59
bool isConnectedTo(const Bus &bus) const
Definition Socket.cc:331
virtual int portCount() const
Definition Unit.cc:135
void addMove(std::shared_ptr< Move > move)
void add(Instruction *ins)
Definition Procedure.cc:160
TPEF::Binary * createBinary() const
void addProcedure(Procedure *proc)
Definition Program.cc:524