OpenASIP 2.2
Loading...
Searching...
No Matches
NetlistGenerator.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 NetlistGenerator.cc
26 *
27 * Implementation of NetlistGenerator class.
28 *
29 * @author Lasse Laasonen 2005 (lasse.laasonen-no.spam-tut.fi)
30 * @author Otto Esko 2008 (otto.esko-no.spam-tut.fi)
31 * @note rating: red
32 */
33
34#include <boost/format.hpp>
35#include <iostream>
36#include <set>
37#include <string>
38#include <utility> // for make_pair()
39
41#include "Netlist.hh"
42#include "NetlistBlock.hh"
43#include "NetlistGenerator.hh"
44#include "NetlistPort.hh"
45#include "NetlistPortGroup.hh"
46#include "Parameter.hh"
47#include "ProcessorGenerator.hh"
48#include "SignalGroupTypes.hh"
49
52
53#include "ControlUnit.hh"
54#include "FUPort.hh"
55#include "FunctionUnit.hh"
56#include "HWOperation.hh"
57#include "ImmediateUnit.hh"
58#include "Machine.hh"
60
61#include "FUArchitecture.hh"
62#include "FUEntry.hh"
63#include "FUExternalPort.hh"
64#include "FUImplementation.hh"
66#include "HDBManager.hh"
67#include "HDBRegistry.hh"
68#include "RFArchitecture.hh"
69#include "RFEntry.hh"
70#include "RFExternalPort.hh"
71#include "RFImplementation.hh"
73
74#include "BinaryEncoding.hh"
75
76#include "Conversion.hh"
77#include "MapTools.hh"
78#include "MathTools.hh"
79#include "ProGeContext.hh"
80
81#include "MemoryBusInterface.hh"
82
84#include "ProGeTools.hh"
85
86using namespace IDF;
87using namespace HDB;
88using namespace TTAMachine;
89
90using std::set;
91using std::string;
92using boost::format;
93
94const string TOPLEVEL_BLOCK_DEFAULT_NAME = "toplevel";
95const string CLOCK_PORT_NAME = "clk";
96const string RESET_PORT_NAME = "rstx";
97const string RA_OUT_PORT_NAME = "ra_out";
98const string BUSY_PORT_NAME = "busy";
99const string READ_ENABLE_PORT_NAME = "imem_en_x";
100const string ADDRESS_PORT_NAME = "imem_addr";
101const string DATA_PORT_NAME = "imem_data";
102const string PC_IN_PORT_NAME = "pc_in";
103const string RA_IN_PORT_NAME = "ra_in";
104const string FETCH_PORT_NAME = "fetch_en";
105const string LOCK_PORT_NAME = "lock";
106const string FETCHBLOCK_PORT_NAME = "fetchblock";
107const string PC_READ_PORT_NAME = "pc_r";
108const string PC_LOAD_PORT_NAME = "pc_load";
109const string RA_LOAD_PORT_NAME = "ra_load";
110const string PC_OPCODE_PORT_NAME = "pc_opcode";
111const string INSTRUCTIONWORD_PORT_NAME = "instructionword";
112const string GLOBAL_LOCK_PORT_NAME = "glock";
113const string LOCK_REQUEST_PORT_NAME = "lock_r";
114const string LOCK_STATUS_PORT_NAME = "locked";
115
116const string IMEMADDRWIDTH = "IMEMADDRWIDTH";
117const string IMEMWIDTHFORMULA = "IMEMWIDTHINMAUS*IMEMMAUWIDTH";
118const string INSTRUCTIONWIDTH = "INSTRUCTIONWIDTH";
119
120const string IFETCH_BLOCK_NAME = "ifetch";
121const string DECOMPRESSOR_BLOCK_NAME = "decompressor";
122const string DECODER_BLOCK_NAME = "decoder";
123
124const string CALL = "CALL";
125const string JUMP = "JUMP";
126
127const string FU_NAME_PREFIX = "fu_";
128const string RF_NAME_PREFIX = "rf_";
129const string IU_NAME_PREFIX = "iu_";
130
131const TCEString INSTANCE_SUFFIX = "_instance";
132
133namespace ProGe {
134
153 const std::string NetlistGenerator::DECOMP_GLOCK_PORT =
157 const std::string NetlistGenerator::FETCHBLOCK_PORT_NAME = "fetchblock";
158
160 const ProGeContext& context, ICDecoderGeneratorPlugin& plugin)
161 : context_(context), plugin_(plugin), coreBlock_(NULL),
162 instructionDecoder_(NULL), instructionDecompressor_(NULL),
163 instructionFetch_(NULL), raInPort_(NULL), raOutPort_(NULL) {}
164
165 /**
166 * The destructor.
167 */
172
173 /**
174 * Generates the netlist block of the processor.
175 *
176 * @param imemWidthInMAUs Width of instruction memory in MAUs.
177 * @param entityNameStr The name string used to make the netlist blocks
178 * uniquely named.
179 * @return The newly generated netlist block representing a single TTA Core.
180 * @exception IOException If some of the HDBs given in IDF cannot be
181 * accessed.
182 * @exception InvalidData If HDB or IDF is invalid.
183 * @exception OutOfRange If the given width of instruction memory is not
184 * positive
185 * @exception InstanceNotFound Something missing missing from HDB.
186 */
189 const ProGeOptions& options, int imemWidthInMAUs,
191 std::ostream& warningStream = std::cerr) {
192 if (imemWidthInMAUs < 1) {
193 string errorMsg =
194 "Instruction memory width in MAUs must be positive.";
195 throw OutOfRange(__FILE__, __LINE__, __func__, errorMsg);
196 }
197
198 // add toplevel block
199 coreBlock_ = new NetlistBlock(entityNameStr, "tta_core");
202
203 // add GCU to the netlist
204 addGCUToNetlist(*coreBlock_, imemWidthInMAUs);
205
206 // add Genrated FUs to the toplevel netlist.
207 for (auto fug : context_.idf().FUGenerations()) {
209 }
210
211 // add function units to the netlist
212 for (int i = 0; i < context_.idf().fuImplementationCount(); i++) {
215 addFUToNetlist(location, *coreBlock_, warningStream);
216 }
217
218 // add register files to the netlist
219 for (int i = 0; i < context_.idf().rfImplementationCount(); i++) {
220 RFImplementationLocation& location =
222 addRFToNetlist(options, location, *coreBlock_);
223 }
224
225 // add immediate units to the netlist
226 for (int i = 0; i < context_.idf().iuImplementationCount(); i++) {
227 RFImplementationLocation& location =
229 addIUToNetlist(options, location, *coreBlock_);
230 }
231
233
234 return coreBlock_;
235 }
236
237 /**
238 * Returns the netlist port which is corresponding to the given port in
239 * the
240 * machine object model.
241 *
242 * @param port The port in the machine object model
243 * @return The corresponding port in the netlist.
244 * @exception InstanceNotFound If the netlist does not contain the port.
245 */
248 const TTAMachine::Port& port, Direction dir) const {
249 if (portCorrespondenceMap_.count(&port) > 0) {
250 // Override direction with port direction if the port is
251 // unidirectional
252 if (!(port.isInput() && port.isOutput())) {
253 dir = port.isInput() ? IN : OUT;
254 }
255
256 auto range = portCorrespondenceMap_.equal_range(&port);
257 for (auto i = range.first; i != range.second; ++i) {
258 if(i->second->direction() == dir)
259 return *i->second;
260 }
263 }
264
265 throw InstanceNotFound(__FILE__, __LINE__, __func__,
266 (boost::format(
267 "Cannot find netlist port '%s' in parent unit: '%s'") %
268 port.name() % port.parentUnit()->name())
269 .str());
270 }
271
272 /**
273 * Returns the netlist block which is corresponding to the given unit in
274 * the
275 * machine object model.
276 *
277 * @param unit The Unit in the machine object model
278 * @return The corresponding block in the netlist.
279 * @exception InstanceNotFound If the netlist does not contain the
280 * block.
281 */
284 try {
287 } catch (const Exception&) {
288 throw InstanceNotFound(__FILE__, __LINE__, __func__,
289 (boost::format(
290 "Cannot find corresponding netlist block for '%s'") %
291 unit.name())
292 .str());
293 }
294 }
295
296 /**
297 * Returns the load enable port of the given port in the netlist.
298 *
299 * @param port The architectural port in the netlist.
300 * @return The load enable port of the given port.
301 * @exception InstanceNotFound If the netlist does not contain the port.
302 */
305 try {
307 } catch (const Exception&) {
308 throw InstanceNotFound(__FILE__, __LINE__, __func__,
309 (boost::format(
310 "Cannot find load port '%s' in instance name: '%s', "
311 "module name: '%s'") %
312 port.name() % port.parentBlock().instanceName() %
313 port.parentBlock().moduleName())
314 .str());
315 }
316 }
317
318 /**
319 * Returns true if the given RF port has opcode port. Otherwise, returns
320 * false.
321 */
324 }
325
326 /**
327 * Returns the opcode port of the given RF port in the netlist.
328 *
329 * @param port The architectural RF port in the netlist.
330 * @return The opcode port of the given port.
331 * @exception InstanceNotFound If the netlist does not contain the port.
332 */
335 try {
337 rfOpcodePortMap_, &port);
338 } catch (const Exception&) {
339 throw InstanceNotFound(__FILE__, __LINE__, __func__,
340 (boost::format("Cannot find rf opcode port '%s' in "
341 "instance name: '%s', "
342 "module name: '%s'") %
343 port.name() % port.parentBlock().instanceName() %
344 port.parentBlock().moduleName())
345 .str());
346 }
347 }
348
349 /**
350 * Returns the guard port of the given RF block in the netlist.
351 *
352 * @param rfBlock The RF block in the netlist.
353 * @return The guard port of the given block.
354 * @exception InstanceNotFound If the netlist does not contain the port.
355 */
358 try {
360 rfGuardPorts_, &rfBlock);
361 } catch (const Exception&) {
362 throw InstanceNotFound(__FILE__, __LINE__, __func__,
363 (boost::format("Cannot find guard port in register file "
364 "instance name: '%s',"
365 "module name: '%s'") %
366 rfBlock.instanceName() % rfBlock.moduleName())
367 .str());
368 }
369 }
370
371 /**
372 * Returns the opcode port of the given FU.
373 *
374 * @param fuBlock The FU.
375 * @return The opcode port.
376 * @exception InstanceNotFound If the given FU does not have an opcode
377 * port.
378 */
381 try {
383 fuOpcodePorts_, &fuBlock);
384 } catch (const Exception&) {
385 throw InstanceNotFound(__FILE__, __LINE__, __func__,
386 (boost::format("Cannot find opcode port in function unit "
387 "instance name: '%s',"
388 "module name: '%s'") %
389 fuBlock.instanceName() % fuBlock.moduleName())
390 .str());
391 }
392 }
393
394 /**
395 * Returns the guard port of the given FU data port.
396 *
397 * @param fuPort The FU data port.
398 * @return The guard port.
399 * @exception InstanceNotFound If the netlist does not contain the port.
400 */
403 try {
405 fuGuardPortMap_, &fuPort);
406 } catch (const Exception&) {
407 throw InstanceNotFound(__FILE__, __LINE__, __func__,
408 (boost::format(
409 "Cannot find guard port '%s' in instance name: '%s', "
410 "module name: '%s'") %
411 fuPort.name() % fuPort.parentBlock().instanceName() %
412 fuPort.parentBlock().moduleName())
413 .str());
414 }
415 }
416
417 /**
418 * Returns the clock port of the given block in the netlist.
419 *
420 * @param block The block in the netlist.
421 * @return The clock port of the given block.
422 * @exception InstanceNotFound If the netlist does not contain the port.
423 */
426 try {
428 } catch (const Exception&) {
429 throw InstanceNotFound(__FILE__, __LINE__, __func__,
430 (boost::format("Cannot find clock port in netlist block "
431 "instance name: "
432 "'%s', module name: '%s'") %
433 block.instanceName() % block.moduleName())
434 .str());
435 }
436 }
437
438 /**
439 * Returns the reset port of the given block in the netlist.
440 *
441 * @param block The block in the netlist.
442 * @return The reset port of the given block.
443 * @exception InstanceNotFound If the netlist does not contain the port.
444 */
447 try {
449 } catch (const Exception&) {
450 throw InstanceNotFound(__FILE__, __LINE__, __func__,
451 (boost::format("Cannot find reset port in netlist block "
452 "instance name: "
453 "'%s', module name: '%s'") %
454 block.instanceName() % block.moduleName())
455 .str());
456 }
457 }
458
459 /**
460 * Tells whether the given netlist block has a global lock port.
461 *
462 * @param block The netlist block.
463 * @return True if the block has a global lock port, otherwise false.
464 */
466 return MapTools::containsKey(glockPorts_, &block);
467 }
468
469 /**
470 * Returns the global lock port of the given block in the netlist.
471 *
472 * @param block The block in the netlist.
473 * @return The global lock port of the given block.
474 * @exception InstanceNotFound If the netlist does not contain the port.
475 */
478 try {
480 } catch (const Exception&) {
481 throw InstanceNotFound(__FILE__, __LINE__, __func__,
482 (boost::format("Cannot find global lock port in netlist block "
483 "instance name:"
484 " '%s', module name: '%s'") %
485 block.instanceName() % block.moduleName())
486 .str());
487 }
488 }
489
490 /**
491 * Tells whether the given netlist block has global lock request port.
492 *
493 * @param block The netlist block.
494 * @return True if the block has a global lock request port, otherwise
495 * false.
496 */
499 }
500
501 /**
502 * Returns the global lock request port of the given block in the
503 * netlist.
504 *
505 * @param block The block in the netlist.
506 * @return The global lock request port of the given block.
507 * @exception InstanceNotFound If the netlist does not contain the port.
508 */
511 try {
513 } catch (const Exception&) {
514 throw InstanceNotFound(__FILE__, __LINE__, __func__,
515 (boost::format("Cannot find global lock request port in "
516 "netlist block "
517 "instance name: '%s', module name: '%s'") %
518 block.instanceName() % block.moduleName())
519 .str());
520 }
521 }
522
523 /**
524 * Returns a netlist port that is the write port of the given immediate
525 * unit.
526 *
527 * @param iu The immediate unit.
528 * @return The netlist port.
529 * @exception InstanceNotFound If the port is not found.
530 */
533 const TTAMachine::ImmediateUnit& iu) const {
534 try {
536 } catch (const Exception&) {
537 throw InstanceNotFound(__FILE__, __LINE__, __func__,
538 (boost::format("Cannot find immediate unit '%s' write port.") %
539 iu.name())
540 .str());
541 }
542 }
543
544 /**
545 * Returns the return address in port of GCU.
546 *
547 * @return The return address in port.
548 * @exception InstanceNotFound If GCU does not have the port.
549 */
552 if (raInPort_ != NULL) {
553 return *raInPort_;
554 } else {
555 throw InstanceNotFound(__FILE__, __LINE__, __func__,
556 "Cannot find return address of in port of GCU");
557 }
558 }
559
560 /**
561 * Returns the return address out port of GCU.
562 *
563 * @return The return address out port.
564 * @exception InstanceNotFound If GCU does not have the port.
565 */
568 if (raOutPort_ != NULL) {
569 return *raOutPort_;
570 } else {
571 throw InstanceNotFound(__FILE__, __LINE__, __func__,
572 "Cannot find return address of out port of GCU");
573 }
574 }
575
576 /**
577 * Returns the TTA core block in the netlist.
578 *
579 * @return The TTA core block.
580 * @exception InstanceNotFound If there is no instruction decoder in the
581 * netlist.
582 */
585 if (coreBlock_ == NULL) {
586 throw InstanceNotFound(__FILE__, __LINE__, __func__,
587 "Cannot find TTA core block from the netlist.");
588 }
589 return *coreBlock_;
590 }
591
592 /**
593 * Returns the instruction decoder block in the netlist.
594 *
595 * @return The instruction decoder block.
596 * @exception InstanceNotFound If there is no instruction decoder in the
597 * netlist.
598 */
601 if (instructionDecoder_ == NULL) {
602 throw InstanceNotFound(__FILE__, __LINE__, __func__,
603 "Cannot find instruction decoder block from the netlist.");
604 } else {
605 return *instructionDecoder_;
606 }
607 }
608
609 /**
610 * Returns the instruction fetch block in the netlist.
611 *
612 * @return The instruction fetch block.
613 * @exception InstanceNotFound If there is no instruction fetch in the
614 * netlist.
615 */
618 if (instructionFetch_ == NULL) {
619 throw InstanceNotFound(__FILE__, __LINE__, __func__,
620 "Cannot find instruction fetch block from the netlist.");
621 } else {
622 return *instructionFetch_;
623 }
624 }
625
626 /**
627 * Returns the instruction decompressor block in the netlist.
628 *
629 * @return The instruction decompressor block.
630 * @exception InstanceNotFound If there is no instruction decompressor
631 * in
632 * the
633 * netlist.
634 */
637 if (instructionDecompressor_ == NULL) {
638 throw InstanceNotFound(__FILE__, __LINE__, __func__,
639 "Cannot find instruction decompressor block from the "
640 "netlist.");
641 } else {
643 }
644 }
645
646 /**
647 * Returns the FU entry which was selected to represent the given FU.
648 *
649 * @param fuName Name of the FU in ADF.
650 * @return The FU entry.
651 * @exception InstanceNotFound If the netlist is not created yet or if
652 * there
653 * was
654 * no FU entry for the given FU.
655 */
656 FUEntry&
657 NetlistGenerator::fuEntry(const std::string& fuName) const {
658 try {
660 } catch (const Exception&) {
661 throw InstanceNotFound(__FILE__, __LINE__, __func__,
662 "Cannot find function unit entry from the netlist.");
663 }
664 }
665
666 /**
667 * Returns the RF entry which was selected to represent the given RF.
668 *
669 * @param fuName Name of the RF in ADF.
670 * @return The RF entry.
671 * @exception InstanceNotFound If the netlist is not created yet or if
672 * there
673 * was no RF entry for the given RF.
674 */
676 NetlistGenerator::rfEntry(const std::string& rfName) const {
677 try {
679 } catch (const Exception&) {
680 throw InstanceNotFound(__FILE__, __LINE__, __func__,
681 "Cannot find register file entry from the netlist.");
682 }
683 }
684
685 /**
686 * Adds the global control unit to the netlist as sub-block of the given
687 * top-level block.
688 *
689 * @param toplevelBlock The top-level block of the netlist.
690 * @param imemWidthInMAUs Width of the instruction memory in MAUs.
691 */
693 NetlistBlock& toplevelBlock, int imemWidthInMAUs) {
694 if (imemWidthInMAUs != 4 && context_.adf().isRISCVMachine()) {
695 throw InvalidData(__FILE__, __LINE__, __func__,
696 "Imem width fixed to 4 MAUs for RISC-V machines");
697 } else if (imemWidthInMAUs != 1 && !context_.adf().isRISCVMachine()) {
698 throw InvalidData(__FILE__, __LINE__, __func__,
699 "Imem width is currently fixed to 1 MAU");
700 }
701 Netlist& netlist = toplevelBlock.netlist();
702
703 Parameter coreIdParam("core_id", "integer", "0", "0");
704 toplevelBlock.addParameter(coreIdParam);
705
706 NetlistPort* tlClkPort =
707 new InBitPort(CLOCK_PORT_NAME, toplevelBlock, SignalType::CLOCK);
708 NetlistPort* tlRstPort = new InBitPort(RESET_PORT_NAME, toplevelBlock,
710
711 // Instruction fetch bus //
712 NetlistPort* tlBusyPort = new InBitPort(BUSY_PORT_NAME,
714 NetlistPort* tlReadEnablePort = new OutBitPort(READ_ENABLE_PORT_NAME,
716 NetlistPort* tlAddressPort = new OutPort(ADDRESS_PORT_NAME,
720 NetlistPortGroup* toplevelInstructionLine =
722 tlReadEnablePort, tlAddressPort, tlDataPort);
723 toplevelBlock.addPortGroup(toplevelInstructionLine);
724
725 NetlistPort* tlLockStatusPort = new NetlistPort(LOCK_STATUS_PORT_NAME,
726 "1", BIT, OUT, toplevelBlock, SignalType::CORE_HALT_STATUS);
727
728 mapClockPort(toplevelBlock, *tlClkPort);
729 mapResetPort(toplevelBlock, *tlRstPort);
730
731 // add ifetch block
734 context_.coreEntityName() + "_" + IFETCH_BLOCK_NAME, "inst_fetch");
735 toplevelBlock.addSubBlock(instructionFetch_);
736 NetlistPort* ifetchClkPort =
738 NetlistPort* ifetchRstPort =
740 NetlistPort* ifetchRAOutPort = new NetlistPort(RA_OUT_PORT_NAME,
742 raOutPort_ = ifetchRAOutPort;
743 NetlistPort* ifetchRAInPort = new NetlistPort(
745 raInPort_ = ifetchRAInPort;
746
747 NetlistPort* ifetchBusyPort = new InBitPort(BUSY_PORT_NAME,
749 NetlistPort* ifetchReadEnablePort =
752 NetlistPort* ifetchAddressPort = new OutPort(ADDRESS_PORT_NAME,
754 NetlistPort* ifetchDataPort = new InPort(DATA_PORT_NAME,
756 NetlistPortGroup* ifetchInstructionLine = new NetlistPortGroup(
757 SignalGroupType::INSTRUCTION_LINE, ifetchBusyPort,
758 ifetchReadEnablePort, ifetchAddressPort, ifetchDataPort);
759 instructionFetch_->addPortGroup(ifetchInstructionLine);
760
761 NetlistPort* ifetchPCInPort = new NetlistPort(
763 NetlistPort* ifetchPCLoadPort = new NetlistPort(
765 NetlistPort* ifetchRALoadPort = new NetlistPort(
767 NetlistPort* ifetchPCOpcodePort = new NetlistPort(PC_OPCODE_PORT_NAME,
770 NetlistPort* ifetchFetchPort =
772 NetlistPort* ifetchGlockPort = new NetlistPort(
774 NetlistPort* ifetchFetchBlockPort =
777
778 // connect ifetch to toplevel
779 netlist.connect(*tlClkPort, *ifetchClkPort);
780 netlist.connect(*tlRstPort, *ifetchRstPort);
781
782 netlist.connect(*toplevelInstructionLine, *ifetchInstructionLine);
783
784 if (gcu->operationPortCount() > 0) {
785 mapNetlistPort(*gcu->triggerPort(), *ifetchPCInPort);
786 }
787
788 // Add non-standard GCU ports to the block.
789 for (int i = 0; i < gcu->portCount(); i++) {
790 Port* port = gcu->port(i);
791 if (gcu->returnAddressPort()->name() == port->name()) {
792 continue;
793 }
794 if (!netlistPortIsMapped(*port)) {
795 Direction dir;
796 if (port->isInput()) {
797 dir = IN;
798 } else if (port->isOutput()) {
799 dir = OUT;
800 } else {
801 assert(false && "Unconneced ADF port.");
802 }
803 // Data port
804 NetlistPort* dataPort = new NetlistPort(port->name() + "_data",
807 mapNetlistPort(*port, *dataPort);
808
809 // Load port if port is input
810 if (port->isInput()) {
812 new NetlistPort(port->name() + "_load", "1", BIT, dir,
814 mapLoadPort(*dataPort, *loadPort);
815 }
816 }
817 }
818
819 // add decompressor block
820 NetlistBlock* decompressorBlock = new NetlistBlock(
822 "decomp");
823 instructionDecompressor_ = decompressorBlock;
824 toplevelBlock.addSubBlock(decompressorBlock);
825 NetlistPort* decFetchPort =
826 new NetlistPort(FETCH_PORT_NAME, "1", BIT, OUT, *decompressorBlock);
827 NetlistPort* decLockPort =
828 new NetlistPort(LOCK_PORT_NAME, "1", BIT, IN, *decompressorBlock);
829 NetlistPort* decFetchBlockPort = new NetlistPort(FETCHBLOCK_PORT_NAME,
830 IMEMWIDTHFORMULA, BIT_VECTOR, IN, *decompressorBlock);
831 NetlistPort* decClkPort =
832 new NetlistPort(CLOCK_PORT_NAME, "1", BIT, IN, *decompressorBlock);
833 NetlistPort* decRstPort =
834 new NetlistPort(RESET_PORT_NAME, "1", BIT, IN, *decompressorBlock);
836 INSTRUCTIONWIDTH, BIT_VECTOR, OUT, *decompressorBlock);
837 NetlistPort* decGlockPort = new NetlistPort(
838 GLOBAL_LOCK_PORT_NAME, "1", BIT, OUT, *decompressorBlock);
839 NetlistPort* decLockReqPort = new NetlistPort(
840 LOCK_REQUEST_PORT_NAME, "1", BIT, IN, *decompressorBlock);
841
842 // connect ifetch to decompressor
843 netlist.connect(*ifetchFetchPort, *decFetchPort);
844 netlist.connect(*ifetchGlockPort, *decLockPort);
845 netlist.connect(*ifetchFetchBlockPort, *decFetchBlockPort);
846
847 // connect toplevel to decompressor
848 netlist.connect(*tlClkPort, *decClkPort);
849 netlist.connect(*tlRstPort, *decRstPort);
850
851 // add decoder block
852 NetlistBlock* decoderBlock = new NetlistBlock(
854 "inst_decoder");
855 toplevelBlock.addSubBlock(decoderBlock);
856 instructionDecoder_ = decoderBlock;
857 NetlistPort* decodIWordPort = new NetlistPort(DECODER_INSTR_WORD_PORT,
858 INSTRUCTIONWIDTH, BIT_VECTOR, IN, *decoderBlock);
859 NetlistPort* decodPCLoadPort =
860 new NetlistPort(DECODER_PC_LOAD_PORT, "1", BIT, OUT, *decoderBlock);
861 NetlistPort* decodRALoadPort =
862 new NetlistPort(DECODER_RA_LOAD_PORT, "1", BIT, OUT, *decoderBlock);
863 NetlistPort* decodPCOpcodePort = new NetlistPort(DECODER_PC_OPCODE_PORT,
865 BIT_VECTOR, OUT, *decoderBlock);
866 NetlistPort* decodLockPort = new NetlistPort(
867 DECODER_LOCK_REQ_IN_PORT, "1", BIT, IN, *decoderBlock);
868 NetlistPort* decodLockReqPort = new NetlistPort(
869 DECODER_LOCK_REQ_OUT_PORT, "1", BIT, OUT, *decoderBlock);
870 NetlistPort* decodClkPort =
871 new NetlistPort(DECODER_CLOCK_PORT, "1", BIT, IN, *decoderBlock);
872 NetlistPort* decodRstPort =
873 new NetlistPort(DECODER_RESET_PORT, "1", BIT, IN, *decoderBlock);
874 NetlistPort* decodLockedPort = new NetlistPort(
875 DECODER_LOCK_STATUS_PORT, "1", BIT, OUT, *decoderBlock);
876
877 // connect decoder to decompressor
878 netlist.connect(*decIWordPort, *decodIWordPort);
879 netlist.connect(*decGlockPort, *decodLockPort);
880 netlist.connect(*decLockReqPort, *decodLockReqPort);
881
882 // connect decoder to top-level
883 netlist.connect(*decodClkPort, *tlClkPort);
884 netlist.connect(*decodRstPort, *tlRstPort);
885
886 // connect decoder to ifetch
887 netlist.connect(*decodPCLoadPort, *ifetchPCLoadPort);
888 netlist.connect(*decodRALoadPort, *ifetchRALoadPort);
889 netlist.connect(*decodPCOpcodePort, *ifetchPCOpcodePort);
890
891 // connect lock status signal port
892 netlist.connect(*tlLockStatusPort, *decodLockedPort);
893
894 Netlist::connectClocks(toplevelBlock);
895 Netlist::connectResets(toplevelBlock);
896 }
897
899 const IDF::FUGenerated& fug, NetlistBlock& coreBlock) {
900
901 std::string fuName = "fu_" + fug.name();
902 std::transform(fuName.begin(), fuName.end(), fuName.begin(), ::tolower);
903
905 fuName, fuName + "_generated", *this);
906 coreBlock.addSubBlock(block);
907
908 FunctionUnit* fu =
910
911 mapNetlistBlock(*fu, *block);
912
913 // add clock port
914 NetlistPort* clkPort = new NetlistPort("clk", "1", 1, BIT, IN, *block);
915 mapClockPort(*block, *clkPort);
916 // connect clock port
917 NetlistPort& tlClkPort = this->clkPort(coreBlock);
918 coreBlock.netlist().connect(*clkPort, tlClkPort);
919
920 // add reset port
921 NetlistPort* rstPort = new NetlistPort("rstx", "1", 1, BIT, IN, *block);
922 mapResetPort(*block, *rstPort);
923 // connect reset port
924 NetlistPort& tlRstPort = this->rstPort(coreBlock);
925 coreBlock.netlist().connect(*rstPort, tlRstPort);
926
927 // add global lock port
929 new NetlistPort("glock_in", "1", 1, BIT, IN, *block);
931
932 // opcode port.
933 int opcodeWidth = static_cast<int>(std::ceil(
934 std::log2(fu->operationCount())));
935 if (fu->operationCount() > 1) {
936 NetlistPort* opcodePort = new NetlistPort("operation_in",
937 std::to_string(opcodeWidth), BIT_VECTOR, IN, *block);
938 mapFUOpcodePort(*block, *opcodePort);
939 }
940
941 // global lock request port
943 "glockreq_out", "1", 1, BIT, OUT, *block);
945
946 // operand ports.
947 for (int i = 0; i < fu->portCount(); ++i) {
948 FUPort* adfPort = dynamic_cast<FUPort*>(fu->port(i));
949
950 if (adfPort->isInput()) {
951 block->addInOperand(adfPort, i);
952 } else {
953 block->addOutOperand(adfPort);
954 }
955 }
956
957 return block;
958 }
959
960 /**
961 * Adds the FU identified by the given FUImplementationLocation
962 * instance to the netlist.
963 *
964 * @param location The FUImplementationLocation instance.
965 * @param netlist The netlist block under where FU is added.
966 * @exception IOException If the HDB that contains the implementation
967 * cannot
968 * be accessed.
969 * @exception InvalidData If the MachineImplementation instance is
970 * erroneous
971 * or if HDB erroneous.
972 */
973 void
975 const FUImplementationLocation& location, NetlistBlock& coreBlock,
976 std::ostream& warningStream) {
977 string hdbFile = location.hdbFile();
978 int id = location.id();
979 FUEntry* entry = NULL;
980
981 try {
982 HDBManager& manager = HDBRegistry::instance().hdb(hdbFile);
983 entry = manager.fuByEntryID(id);
984 } catch (const KeyNotFound& e) {
985 throw InvalidData(__FILE__, __LINE__, __func__, e.errorMessage());
986 }
987
988 if (!entry->hasImplementation() || !entry->hasArchitecture()) {
989 string errorMsg;
990 if (!entry->hasImplementation()) {
991 errorMsg = "FU entry " + Conversion::toString(id) +
992 " does not "
993 "have an implementation in HDB " +
994 hdbFile + ".";
995 } else {
996 errorMsg = "FU entry " + Conversion::toString(id) +
997 " does not "
998 "have architecture definition in HDB " +
999 hdbFile + ".";
1000 }
1001 throw InvalidData(__FILE__, __LINE__, __func__, errorMsg);
1002 }
1003
1005 location.unitName())) {
1006 string errorMsg = "ADF does not have FU '" + location.unitName() +
1007 "' which is referred to in the IDF.";
1008 throw InvalidData(__FILE__, __LINE__, __func__, errorMsg);
1009 }
1010
1011 fuEntryMap_.insert(std::make_pair(location.unitName(), entry));
1012 FUImplementation& fuImplementation = entry->implementation();
1013 FUArchitecture& architecture = entry->architecture();
1014 const FunctionUnit* adfFU =
1016 TCEString instanceName = FU_NAME_PREFIX + location.unitName();
1017 TCEString moduleName = fuImplementation.moduleName();
1018 instanceName = checkInstanceName(instanceName, moduleName);
1019 NetlistBlock* block = new NetlistBlock(moduleName, instanceName);
1020 coreBlock.addSubBlock(block);
1021 mapNetlistBlock(*adfFU, *block);
1022
1023 format architecturesDontMatch("Architectures of FU entry %1% in "
1024 "%2% and FU '%3%' don't match.");
1025
1026 // add parameters
1027 for (int i = 0; i < fuImplementation.parameterCount(); i++) {
1028 FUImplementation::Parameter parameter =
1029 fuImplementation.parameter(i);
1030 string paramName = parameter.name;
1031 string paramType = parameter.type;
1032 string paramValue = parameter.value;
1033 if (paramValue == "" || isParameterizable(paramName, entry)) {
1034 bool parameterResolved = false;
1035 // find the port which uses this parameter
1036 for (int j = 0; j < fuImplementation.architecturePortCount();
1037 j++) {
1038 FUPortImplementation& port =
1039 fuImplementation.architecturePort(j);
1040
1041 // Special case if the FU is an LSU and it has
1042 // parametrizable
1043 // address width. This sets the ADF port width according
1044 // to
1045 // address space width in ADF
1046 if (adfFU->hasAddressSpace() && isLSU(*adfFU)) {
1047 FUPort& adfPort = findCorrespondingPort(*adfFU,
1048 architecture.architecture(),
1049 port.architecturePort());
1050 // Assume address port is the triggering port
1051 if (adfPort.isTriggering() &&
1052 port.widthFormula() == paramName) {
1053 int ASWidth = calculateAddressWidth(adfFU);
1054 block->setParameter(paramName, paramType,
1055 Conversion::toString(ASWidth));
1056 // Fix the FU port width
1057 adfPort.setWidth(ASWidth);
1058 parameterResolved = true;
1059 break;
1060 }
1061 }
1062 if (port.widthFormula() == paramName) {
1063 try {
1064 FUPort& adfPort = findCorrespondingPort(*adfFU,
1065 architecture.architecture(),
1066 port.architecturePort());
1067 block->setParameter(paramName, paramType,
1068 Conversion::toString(adfPort.width()));
1069 parameterResolved = true;
1070 break;
1071 } catch (const InstanceNotFound&) {
1072 architecturesDontMatch % id % hdbFile %
1073 adfFU->name();
1074 throw InvalidData(__FILE__, __LINE__, __func__,
1075 architecturesDontMatch.str());
1076 }
1077 }
1078 }
1079
1080 if (!parameterResolved) {
1081 format errorMsg("Unable to resolve the value of "
1082 "parameter %1% of FU "
1083 "entry %2%.");
1084 errorMsg % paramName % id;
1085 throw InvalidData(
1086 __FILE__, __LINE__, __func__, errorMsg.str());
1087 }
1088
1089 } else {
1090 block->setParameter(paramName, paramType, paramValue);
1091 }
1092 }
1093
1094 // add ports to the netlist block
1095 for (int i = 0; i < fuImplementation.architecturePortCount(); i++) {
1096
1097 FUPortImplementation& port = fuImplementation.architecturePort(i);
1098
1099 // add architectural port
1100 string architecturePort = port.architecturePort();
1101
1102 FUPort* adfPort;
1103 try {
1104 adfPort = &findCorrespondingPort(
1105 *adfFU, architecture.architecture(), architecturePort);
1106 } catch (const InstanceNotFound&) {
1107 architecturesDontMatch % id % hdbFile % adfFU->name();
1108 throw InvalidData(
1109 __FILE__, __LINE__, __func__, architecturesDontMatch.str());
1110 }
1111 NetlistPort* newPort = new NetlistPort(port.name(),
1112 port.widthFormula(), adfPort->width(), BIT_VECTOR,
1114 architecture.portDirection(architecturePort)),
1115 *block);
1116 mapNetlistPort(*adfPort, *newPort);
1117
1118 // add load port
1119 if (port.loadPort() != "") {
1121 new NetlistPort(port.loadPort(), "1", 1, BIT, IN, *block);
1122 mapLoadPort(*newPort, *loadPort);
1123 }
1124
1125 // add guard port
1126 if (port.guardPort() != "") {
1127 NetlistPort* guardPort =
1128 new NetlistPort(port.guardPort(), "1", 1, BIT, OUT, *block);
1129 mapFUGuardPort(*newPort, *guardPort);
1130 }
1131 }
1132
1133 // add opcode port
1134 if (fuImplementation.opcodePort() != "") {
1135 NetlistPort* opcodePort = new NetlistPort(
1136 fuImplementation.opcodePort(),
1137 Conversion::toString(opcodePortWidth(*entry, warningStream)),
1138 opcodePortWidth(*entry, warningStream), BIT_VECTOR, IN, *block);
1139 mapFUOpcodePort(*block, *opcodePort);
1140 }
1141
1142 // add external ports
1144 fuImplementation, coreBlock, *block, *adfFU);
1145
1146 // add clock port
1147 if (fuImplementation.clkPort() != "") {
1149 fuImplementation.clkPort(), "1", 1, BIT, IN, *block);
1150 mapClockPort(*block, *clkPort);
1151 // connect clock port
1152 NetlistPort& tlClkPort = this->clkPort(coreBlock);
1153 coreBlock.netlist().connect(*clkPort, tlClkPort);
1154 }
1155
1156 // add reset port
1157 if (fuImplementation.rstPort() != "") {
1159 fuImplementation.rstPort(), "1", 1, BIT, IN, *block);
1160 mapResetPort(*block, *rstPort);
1161 // connect reset port
1162 NetlistPort& tlRstPort = this->rstPort(coreBlock);
1163 coreBlock.netlist().connect(*rstPort, tlRstPort);
1164 }
1165
1166 // add global lock port
1167 if (fuImplementation.glockPort() != "") {
1169 fuImplementation.glockPort(), "1", 1, BIT, IN, *block);
1170 mapGlobalLockPort(*block, *glockPort);
1171 }
1172
1173 // add global lock request port
1174 if (fuImplementation.glockReqPort() != "") {
1176 fuImplementation.glockReqPort(), "1", 1, BIT, OUT, *block);
1178 }
1179 }
1180
1181 /**
1182 * Adds external ports defined in HDB into netlist.
1183 *
1184 * Also attempts to recognize LSU memory bus ports and assign them into
1185 * corresponding NetlistGroup. Recognition is now done by seeking
1186 * external
1187 * ports having specific patterns (see inferLSUSignal()).
1188 */
1190 const HDB::FUImplementation& fuImplementation, NetlistBlock& coreBlock,
1191 NetlistBlock& fuBlock, const FunctionUnit& adfFU) {
1192
1193 // external ports recognized as LSU' data memory ports.
1194 set<std::pair<NetlistPort*, NetlistPort*>> lsuPorts;
1195 // Other unrecognized ports.
1196 set<std::pair<NetlistPort*, NetlistPort*>> otherPorts;
1197
1198 // for each external port, a port is added to top-level block too
1199 for (int i = 0; i < fuImplementation.externalPortCount(); i++) {
1200 FUExternalPort& externalPort = fuImplementation.externalPort(i);
1201 // if external port uses parameter, it must be added as netlist
1202 // parameter too and create new width formula for the top-level
1203 // port
1204 // by replacing parameter names with the corresponding names in
1205 // netlist.
1206 string tlPortWidth = externalPort.widthFormula();
1207 for (int i = 0; i < externalPort.parameterDependencyCount(); i++) {
1208 string paramName = externalPort.parameterDependency(i);
1209 Parameter param = fuBlock.parameter(paramName);
1210 string nlParamName = fuBlock.instanceName() + "_" + paramName;
1211 if (!coreBlock.netlist().hasParameter(nlParamName)) {
1212 coreBlock.netlist().setParameter(
1213 nlParamName, param.type(), param.value());
1214 }
1215 fuBlock.setParameter(param.name(), param.type(), nlParamName);
1216 size_t replaceStart = tlPortWidth.find(param.name(), 0);
1217 if (replaceStart == std::string::npos) {
1218 throw InvalidData(__FILE__, __LINE__, __func__,
1219 (boost::format("FU external port parameter "
1220 "dependencies do not "
1221 "seem "
1222 "to be right: Tried to find "
1223 "parameter named '%s'"
1224 " from external port width formula "
1225 "'%s' in unit "
1226 "'%s'") %
1227 param.name() % tlPortWidth % nlParamName)
1228 .str());
1229 }
1230 size_t replaceLength = param.name().length();
1231 tlPortWidth = tlPortWidth.replace(
1232 replaceStart, replaceLength, nlParamName);
1233 }
1234
1235 NetlistPort* extPort = new NetlistPort(externalPort.name(),
1236 externalPort.widthFormula(), BIT_VECTOR,
1237 translateDirection(externalPort.direction()), fuBlock);
1238 string tlPortName =
1239 fuBlock.instanceName() + "_" + externalPort.name();
1240 if (isLSUDataPort(adfFU, externalPort.name())) {
1241 NetlistPort* tlPort = new NetlistPort(tlPortName, tlPortWidth,
1242 BIT_VECTOR, translateDirection(externalPort.direction()),
1243 coreBlock, inferLSUSignal(externalPort.name()));
1244 lsuPorts.insert(std::make_pair(extPort, tlPort));
1245 } else {
1246 NetlistPort* tlPort = new NetlistPort(tlPortName, tlPortWidth,
1247 BIT_VECTOR, translateDirection(externalPort.direction()),
1248 coreBlock);
1249 coreBlock.netlist().connect(*extPort, *tlPort);
1250 }
1251 }
1252
1253 // Handle LSU data ports.
1254 TCEString asName("");
1255 if (adfFU.hasAddressSpace()) {
1256 asName = adfFU.addressSpace()->name();
1257 }
1258
1259 NetlistPortGroup* dmemPortGroup = nullptr;
1260 for (auto portPair : lsuPorts) {
1261 dmemPortGroup =
1262 dmemPortGroup
1263 ? dmemPortGroup
1264 : (new MemoryBusInterface(
1266 dmemPortGroup->addPort(*portPair.second);
1267 coreBlock.netlist().connect(*portPair.first, *portPair.second);
1268 }
1269 if (dmemPortGroup != nullptr) {
1270 coreBlock.addPortGroup(dmemPortGroup);
1271 dmemPortGroup = nullptr;
1272 }
1273 }
1274
1275 /**
1276 * Adds the RF identified by the given RFImplementationLocation
1277 * instance to the netlist.
1278 *
1279 * @param location The RFImplementationLocation instance.
1280 * @param netlist The netlist.
1281 * @exception IOException If the HDB that contains the implementation
1282 * cannot
1283 * be accessed.
1284 * @exception InvalidData If the MachineImplementation instance or HDB
1285 * is
1286 * erroneous.
1287 */
1288 void
1290 const ProGeOptions& options, const RFImplementationLocation& location,
1291 NetlistBlock& netlistBlock) {
1293 location.unitName())) {
1294 string errorMsg = "ADF does not contain register file '" +
1295 location.unitName() + "' referred to in IDF.";
1296 throw InvalidData(__FILE__, __LINE__, __func__, errorMsg);
1297 }
1298 RegisterFile* rf =
1300 addBaseRFToNetlist(options, *rf, location, netlistBlock,
1302 }
1303
1304 /**
1305 * Adds the IU identified by the given RFImplementationLocation
1306 * instance to the netlist.
1307 *
1308 * @param location The RFImplementationLocation instance.
1309 * @param netlist The netlist.
1310 * @exception IOException If the HDB that contains the implementation
1311 * cannot
1312 * be accessed.
1313 * @exception InvalidData If the MachineImplementation instance or HDB
1314 * is
1315 * erroneous.
1316 */
1317 void
1319 const ProGeOptions& options, const RFImplementationLocation& location,
1320 NetlistBlock& netlistBlock) {
1322 location.unitName())) {
1323 string errorMsg = "ADF does not contain immediate unit '" +
1324 location.unitName() + "' referred to in IDF.";
1325 throw InvalidData(__FILE__, __LINE__, __func__, errorMsg);
1326 }
1327 ImmediateUnit* iu =
1329 addBaseRFToNetlist(options, *iu, location, netlistBlock,
1331 }
1332
1333 /**
1334 * Adds the RF or IU identified by the given RFImplementationLocation
1335 * instance to the netlist.
1336 *
1337 * @param regFile The corresponding RF (or IU) in ADF.
1338 * @param location The RFImplementationLocation instance.
1339 * @param netlist The netlist.
1340 * @param blockNamePrefix Prefix to be added to the block name.
1341 * @exception IOException If the HDB that contains the implementation
1342 * cannot
1343 * be accessed.
1344 * @exception InvalidData If the RF entry in HDB does not have an
1345 * implementation or architecture or if the HDB
1346 * does
1347 * not have the entry defined in the
1348 * RFImplementationLocation instance at all.
1349 */
1350 void
1352 const ProGeOptions& options,
1353 const TTAMachine::BaseRegisterFile& regFile,
1354 const RFImplementationLocation& location, NetlistBlock& targetBlock,
1355 const std::string& blockNamePrefix) {
1356 RFEntry* entry = NULL;
1357 try {
1358 HDBManager& manager =
1359 HDBRegistry::instance().hdb(location.hdbFile());
1360 entry = manager.rfByEntryID(location.id());
1361 } catch (const KeyNotFound& e) {
1362 throw InvalidData(__FILE__, __LINE__, __func__, e.errorMessage());
1363 }
1364
1365 if (!entry->hasImplementation() || !entry->hasArchitecture()) {
1366 format text("RF entry %1% does not have an implementation or "
1367 "architecture "
1368 "defined in HDB %2%.");
1369 text % location.id() % location.hdbFile();
1370 throw InvalidData(__FILE__, __LINE__, __func__, text.str());
1371 }
1372
1373 rfEntryMap_.insert(std::make_pair(location.unitName(), entry));
1375 RFArchitecture& architecture = entry->architecture();
1376 TCEString instanceName = blockNamePrefix + location.unitName();
1377 TCEString moduleName = implementation.moduleName();
1378 instanceName = checkInstanceName(instanceName, moduleName);
1379 NetlistBlock* block = new NetlistBlock(moduleName, instanceName);
1380 targetBlock.addSubBlock(block);
1381 mapNetlistBlock(regFile, *block);
1382
1383 // Add parameters (generics) to the block.
1384 for (int i = 0; i < implementation.parameterCount(); i++) {
1385 RFImplementation::Parameter param = implementation.parameter(i);
1386
1387 // Check if parameter matches size or width parameter reference
1388 // and set/override its parameter value according to
1389 // architecture.
1390 if (param.name == implementation.sizeParameter()) {
1391 block->setParameter(implementation.sizeParameter(), "integer",
1393 } else if (param.name == implementation.widthParameter()) {
1394 block->setParameter(implementation.widthParameter(), "integer",
1395 Conversion::toString(regFile.width()));
1396 } else if (param.value == "") {
1397 format errorMsg(
1398 "Unable to resolve the value of parameter %1% of RF "
1399 "entry %2%.");
1400 errorMsg % param.name % location.id();
1401 throw InvalidData(__FILE__, __LINE__, __func__, errorMsg.str());
1402 } else {
1403 block->setParameter(param.name, param.type, param.value);
1404 }
1405 }
1406
1407 // add ports
1408 for (int i = 0; i < implementation.portCount(); i++) {
1409 RFPortImplementation& port = implementation.port(i);
1410 NetlistPort* newInputPort = NULL;
1411 NetlistPort* newOutputPort = NULL;
1412 if (!implementation.widthParameter().empty()) {
1413 switch (port.direction()) {
1414 case HDB::BIDIR:
1415 newInputPort = new NetlistPort(port.name()+"_in",
1416 implementation.widthParameter(), regFile.width(),
1417 BIT_VECTOR, IN, *block);
1418 newOutputPort = new NetlistPort(port.name()+"_out",
1419 implementation.widthParameter(), regFile.width(),
1420 BIT_VECTOR, OUT, *block);
1421 break;
1422 case HDB::IN:
1423 newInputPort = new NetlistPort(port.name(),
1424 implementation.widthParameter(), regFile.width(),
1425 BIT_VECTOR, IN,
1426 *block);
1427 break;
1428 case HDB::OUT:
1429 newOutputPort = new NetlistPort(port.name(),
1430 implementation.widthParameter(), regFile.width(),
1431 BIT_VECTOR, OUT, *block);
1432 break;
1433 }
1434 } else {
1435 switch (port.direction()) {
1436 case HDB::BIDIR:
1437 newInputPort = new NetlistPort(port.name(),
1438 Conversion::toString(architecture.width()),
1439 BIT_VECTOR, IN, *block);
1440 newOutputPort = new NetlistPort(port.name(),
1441 Conversion::toString(architecture.width()),
1442 BIT_VECTOR, OUT, *block);
1443 break;
1444 case HDB::IN:
1445 newInputPort = new NetlistPort(port.name(),
1446 Conversion::toString(architecture.width()),
1447 BIT_VECTOR, IN, *block);
1448 break;
1449 case HDB::OUT:
1450 newOutputPort = new NetlistPort(port.name(),
1451 Conversion::toString(architecture.width()),
1452 BIT_VECTOR, OUT, *block);
1453 break;
1454 }
1455 }
1456 assert(newInputPort || newOutputPort);
1457
1458 RFPort* rfPort = NULL;
1459 // map the port if it is not input port of IU (not visible in
1460 // ADF)
1461 if (dynamic_cast<const ImmediateUnit*>(&regFile) == NULL ||
1462 port.direction() != HDB::IN) {
1463
1464 bool mapped = false;
1465 for (int i = 0; i < regFile.portCount(); i++) {
1466 rfPort = regFile.port(i);
1467 if (portCorrespondenceMap_.count(rfPort) == 0) {
1468 if ((port.direction() == HDB::IN &&
1469 rfPort->inputSocket() != NULL &&
1470 rfPort->outputSocket() == NULL) ||
1471 (port.direction() == HDB::OUT &&
1472 rfPort->outputSocket() != NULL &&
1473 rfPort->inputSocket() == NULL) ||
1474 (port.direction() == HDB::BIDIR &&
1475 rfPort->outputSocket() != NULL &&
1476 rfPort->inputSocket() != NULL)) {
1477 mapped = true;
1478 break;
1479 }
1480 }
1481 }
1482
1483 if (!mapped) {
1484 format text("Unable to map port '%1%' of RF entry '%2%' in "
1485 "HDB '%3%' "
1486 "to any port in %4% '%5%'.");
1487 text % port.name() % location.id() % location.hdbFile();
1488 if (dynamic_cast<const ImmediateUnit*>(&regFile) != NULL) {
1489 text % "immediate unit";
1490 } else {
1491 text % "register file";
1492 }
1493 text % regFile.name();
1494 throw InvalidData(__FILE__, __LINE__, __func__, text.str());
1495 }
1496 }
1497
1498 // if the given BaseRegisterFile is ImmediateUnit, keep track of
1499 // the
1500 // data ports that does not appear in ADF
1501 const ImmediateUnit* iu =
1502 dynamic_cast<const ImmediateUnit*>(&regFile);
1503 if (iu != NULL && newInputPort) {
1504 mapImmediateUnitWritePort(*iu, *newInputPort);
1505 }
1506
1507 // add load port
1509 new NetlistPort(port.loadPort(), "1", BIT, IN, *block);
1510
1511
1512 // Map data (unless it is IU's write port) and load port
1513 if (rfPort != NULL) {
1514 if (newInputPort)
1515 mapNetlistPort(*rfPort, *newInputPort);
1516 if (newOutputPort)
1517 mapNetlistPort(*rfPort, *newOutputPort);
1518 }
1519 if (newInputPort)
1520 mapLoadPort(*newInputPort, *loadPort);
1521 if (newOutputPort)
1522 mapLoadPort(*newOutputPort, *loadPort);
1523
1524 // add opcode port
1525 NetlistPort* opcodePort = NULL;
1526 if (!port.opcodePort().empty()) {
1527 opcodePort = new NetlistPort(port.opcodePort(),
1530 BIT_VECTOR, IN, *block);
1531 if (newInputPort)
1532 mapRFOpcodePort(*newInputPort, *opcodePort);
1533 if (newOutputPort)
1534 mapRFOpcodePort(*newOutputPort, *opcodePort);
1535 } else if (regFile.numberOfRegisters() == 1) {
1536 // Special case for single register RFs which do not need
1537 // opcode
1538 // port. For legacy support the opcode port is left out if
1539 // opcode
1540 // port field is empty in HDB.
1541 // Do nothing.
1542 } else {
1543 format text("RF entry '%1%' in HDB '%2%' does not have "
1544 "opcode port required for RFs of size > 1.");
1545 text % location.id() % location.hdbFile();
1546 throw InvalidData(__FILE__, __LINE__, __func__, text.str());
1547 }
1548 }
1549
1550 // add guard port
1551 if (architecture.hasGuardSupport()) {
1552 string guardPortName = implementation.guardPort();
1553 string size;
1554 if (!implementation.sizeParameter().empty()) {
1555 size = implementation.sizeParameter();
1556 } else {
1557 size = Conversion::toString(architecture.size());
1558 }
1559 NetlistPort* guardPort = new NetlistPort(guardPortName, size,
1560 regFile.numberOfRegisters(), BIT_VECTOR, OUT, *block);
1561 mapRFGuardPort(*block, *guardPort);
1562 }
1563
1564 // Add external ports
1565 string component_type("");
1566 if (dynamic_cast<const ImmediateUnit*>(&regFile) != NULL) {
1567 component_type = IU_NAME_PREFIX;
1568 } else {
1569 component_type = RF_NAME_PREFIX;
1570 }
1571 for (int i = 0; i < implementation.externalPortCount(); i++) {
1572 RFExternalPort& externalPort = implementation.externalPort(i);
1573 // if external port uses parameter, it must be added as netlist
1574 // parameter too and create new width formula for the top-level
1575 // port
1576 // by replacing parameter names with the corresponding names in
1577 // netlist.
1578 string tlPortWidth = externalPort.widthFormula();
1579 for (int i = 0; i < externalPort.parameterDependencyCount(); i++) {
1580 string hdbParamName = externalPort.parameterDependency(i);
1581 Parameter param = block->parameter(hdbParamName);
1582 string nlParamName =
1583 component_type + location.unitName() + "_" + hdbParamName;
1584 if (!targetBlock.netlist().hasParameter(nlParamName)) {
1585 targetBlock.netlist().setParameter(
1586 nlParamName, param.type(), param.value());
1587 }
1588 block->setParameter(param.name(), param.type(), nlParamName);
1589 size_t replaceStart = tlPortWidth.find(param.name(), 0);
1590 if (replaceStart == std::string::npos) {
1591 throw InvalidData(__FILE__, __LINE__, __func__,
1592 (boost::format("RF external port parameter "
1593 "dependencies do not "
1594 "seem "
1595 "to be right: Tried to find "
1596 "parameter named '%s'"
1597 " from external port width formula "
1598 "'%s' in unit "
1599 "'%s'") %
1600 param.name() % tlPortWidth % nlParamName)
1601 .str());
1602 }
1603 size_t replaceLength = param.name().length();
1604 tlPortWidth = tlPortWidth.replace(
1605 replaceStart, replaceLength, nlParamName);
1606 }
1607
1608 NetlistPort* extPort = new NetlistPort(externalPort.name(),
1609 externalPort.widthFormula(), BIT_VECTOR,
1610 translateDirection(externalPort.direction()), *block);
1611 // connect the external port to top level
1612 string tlPortName = component_type + location.unitName() + "_" +
1613 externalPort.name();
1614 NetlistPort* tlPort =
1615 new NetlistPort(tlPortName, tlPortWidth, BIT_VECTOR,
1616 translateDirection(externalPort.direction()), targetBlock);
1617 targetBlock.netlist().connect(*tlPort, *extPort);
1618 }
1619
1620 // add clock port
1621 NetlistPort* clockPort =
1622 new NetlistPort(implementation.clkPort(), "1", BIT, IN, *block);
1623 mapClockPort(*block, *clockPort);
1624 // connect clock port
1625 NetlistPort& tlClockPort = clkPort(targetBlock);
1626 targetBlock.netlist().connect(tlClockPort, *clockPort);
1627
1628 // add reset port
1629 NetlistPort* resetPort =
1630 new NetlistPort(implementation.rstPort(), "1", BIT, IN, *block);
1631 mapResetPort(*block, *resetPort);
1632 // connect reset port
1633 NetlistPort& tlResetPort = rstPort(targetBlock);
1634 targetBlock.netlist().connect(tlResetPort, *resetPort);
1635
1636 // add glock port
1637 if (implementation.glockPort() != "") {
1639 implementation.glockPort(), "1", BIT, IN, *block);
1640 mapGlobalLockPort(*block, *glockPort);
1641 }
1642 }
1643
1644 /**
1645 * Maps the given ADF port to the given netlist port.
1646 *
1647 * @param adfPort The port in ADF (Machine Object Model).
1648 * @param netlistPort The corresponding port in the netlist.
1649 */
1651 const TTAMachine::Port& adfPort, NetlistPort& netlistPort) {
1652
1653 if (portCorrespondenceMap_.count(&adfPort) != 0) {
1654 auto range = portCorrespondenceMap_.equal_range(&adfPort);
1655 for (auto i = range.first; i != range.second; ++i) {
1656 assert(i->second->direction() != netlistPort.direction());
1657 }
1658 }
1659 portCorrespondenceMap_.emplace(&adfPort, &netlistPort);
1660 }
1661
1662 /**
1663 * Maps the given ADF Function Unit to the given netlist block.
1664 *
1665 * @param adfFU The Function Unit in ADF (Machine Object Model).
1666 * @param netlistBlock The corresponding block in the netlist.
1667 */
1669 const TTAMachine::Unit& unit, NetlistBlock& netlistBlock) {
1672 std::pair<const Unit*, NetlistBlock*>(&unit, &netlistBlock));
1673 }
1674
1675 /**
1676 * Returns true if the given ADF port is mapped to some netlist port.
1677 *
1678 * @param adfPort The port in ADF (Machine Object Model).
1679 */
1680 bool
1682 return portCorrespondenceMap_.count(&adfPort) != 0;
1683 }
1684
1685 /**
1686 * Maps the given load port for the given architectural port.
1687 *
1688 * @param port The architectural port in the netlist.
1689 * @param loadPort The load port of the architectural port.
1690 */
1692 const NetlistPort& port, NetlistPort& loadPort) {
1693
1695 loadPortMap_.insert(
1696 std::pair<const NetlistPort*, NetlistPort*>(&port, &loadPort));
1697 }
1698
1699 /**
1700 * Maps the given opcode port for the given architectural RF port.
1701 *
1702 * @param port The architectural port in the netlist.
1703 * @param opcodePort The opcode port of the architectural port.
1704 */
1706 const NetlistPort& port, NetlistPort& opcodePort) {
1707
1709 rfOpcodePortMap_.insert(
1710 std::pair<const NetlistPort*, NetlistPort*>(&port, &opcodePort));
1711 }
1712
1713 /**
1714 * Maps the given opcode port for the given FU block.
1715 *
1716 * @param block The FU block.
1717 * @param opcodePort The opcode port of the FU block.
1718 */
1720 const NetlistBlock& block, NetlistPort& port) {
1721
1723 fuOpcodePorts_.insert(
1724 std::pair<const NetlistBlock*, NetlistPort*>(&block, &port));
1725 }
1726
1727 /**
1728 * Maps the given clock port for the given block.
1729 *
1730 * @param block The netlist block.
1731 * @param clkPort The clock port of the block.
1732 */
1734 const NetlistBlock& block, NetlistPort& clkPort) {
1735
1737 clkPorts_.insert(
1738 std::pair<const NetlistBlock*, NetlistPort*>(&block, &clkPort));
1739 }
1740
1741 /**
1742 * Maps the given reset port for the given block.
1743 *
1744 * @param block The netlist block.
1745 * @param resetPort The reset port of the block.
1746 */
1748 const NetlistBlock& block, NetlistPort& resetPort) {
1749
1751 rstPorts_.insert(
1752 std::pair<const NetlistBlock*, NetlistPort*>(&block, &resetPort));
1753 }
1754
1755 /**
1756 * Maps the given global lock port for the given block.
1757 *
1758 * @param block The netlist block.
1759 * @param glockPort The global lock port of the block.
1760 */
1762 const NetlistBlock& block, NetlistPort& glockPort) {
1763
1765 glockPorts_.insert(
1766 std::pair<const NetlistBlock*, NetlistPort*>(&block, &glockPort));
1767 }
1768
1769 /**
1770 * Maps the given global lock request port for the given block.
1771 *
1772 * @param block The netlist block.
1773 * @param glockReqPort The global lock request port of the block.
1774 */
1776 const NetlistBlock& block, NetlistPort& glockReqPort) {
1777
1779 glockReqPorts_.insert(std::pair<const NetlistBlock*, NetlistPort*>(
1780 &block, &glockReqPort));
1781 }
1782
1783 /**
1784 * Maps the given guard port for the given RF block.
1785 *
1786 * @param block The netlist block.
1787 * @param guardPort The guard port of the block.
1788 */
1790 const NetlistBlock& block, NetlistPort& guardPort) {
1791
1793 rfGuardPorts_.insert(
1794 std::pair<const NetlistBlock*, NetlistPort*>(&block, &guardPort));
1795 }
1796
1797 /**
1798 * Maps the given guard port for the given FU data port.
1799 *
1800 * @param dataPort The data port.
1801 * @param guardPort The guard port.
1802 */
1804 const NetlistPort& dataPort, NetlistPort& guardPort) {
1805
1807 fuGuardPortMap_.insert(
1808 std::pair<const NetlistPort*, NetlistPort*>(&dataPort, &guardPort));
1809 }
1810
1811 /**
1812 * Maps the given netlist port as a write port of the given immediate
1813 * unit.
1814 *
1815 * @param iu The immediate unit.
1816 * @param port The netlist port.
1817 */
1819 const TTAMachine::ImmediateUnit& iu, NetlistPort& port) {
1820
1821 iuPortMap_.insert(
1822 std::pair<const ImmediateUnit*, NetlistPort*>(&iu, &port));
1823 }
1824
1825 /**
1826 * Checks if the given parameter is defined parametrizable in the given
1827 * FUImplementation
1828 *
1829 * @param paramName Name of the parameter
1830 * @param fuImplementation FUImplementation to be tested
1831 */
1833 const string& paramName, const FUEntry* fuEntry) const {
1834 FUImplementation& fuImplementation = fuEntry->implementation();
1835
1836 for (int i = 0; i < fuImplementation.architecturePortCount(); i++) {
1837
1838 FUPortImplementation& port = fuImplementation.architecturePort(i);
1839 string widthFormula = port.widthFormula();
1840 if (widthFormula == paramName) {
1842 port.architecturePort());
1843 }
1844 }
1845 return false;
1846 }
1847
1848 /**
1849 * Calculates the address width of an address space in FU
1850 *
1851 * @exception Invalid data If the FU doesn't have an address space or
1852 * the
1853 * address space is invalid
1854 *
1855 */
1857 TTAMachine::FunctionUnit const* fu) const {
1858 if (fu->hasAddressSpace() && fu->addressSpace() != NULL) {
1859 AddressSpace* AS = fu->addressSpace();
1860 unsigned int highestAddr = AS->end();
1861 unsigned int lowestAddr = AS->start();
1862 if (highestAddr == 0 || lowestAddr >= highestAddr) {
1863 string errorMessage = "Invalid address space";
1864 throw InvalidData(
1865 __FILE__, __LINE__, __func__, errorMessage.c_str());
1866 }
1867 return static_cast<unsigned int>(ceil(log(highestAddr) / log(2)));
1868 } else {
1869 string errorMessage = "Tried to resolve address space width "
1870 "from FU '" +
1871 fu->name() +
1872 "' that doesn't have address space";
1873 throw InvalidData(
1874 __FILE__, __LINE__, __func__, errorMessage.c_str());
1875 }
1876 // never reached
1877 return 0;
1878 }
1879
1880 /**
1881 * Calculates the required opcode port width for the given FU.
1882 *
1883 * @param fu The FU.
1884 * @param warningStream Output stream where warnings are written
1885 * @return The required width of opcode port.
1886 * @exception InvalidData If the HDB is missing some information.
1887 */
1888 int
1890 const FUEntry& fu, std::ostream& warningStream) {
1892 assert(fu.hasArchitecture());
1894 FunctionUnit& architecture = fu.architecture().architecture();
1895 int portWidth = 0;
1896
1897 // operation codes are now numbered according to their alphabetical
1898 // order
1899 set<string> opcodeSet;
1900 for (int i = 0; i < architecture.operationCount(); i++) {
1901 HWOperation* operation = architecture.operation(i);
1902 opcodeSet.insert(operation->name());
1903 }
1904
1905 int opcode = 0;
1906 for (set<string>::iterator iter = opcodeSet.begin();
1907 iter != opcodeSet.end(); iter++) {
1908 // there is an old opcode value in hdb
1909 if (opcodeSet.size() != 1 && implementation.hasOpcode(*iter)) {
1910 // old value differs from current guide line
1911 if (opcode != implementation.opcode(*iter)) {
1912 warningStream << "Warning: Opcode defined in HDB for "
1913 << "operation " << *iter
1914 << " does not comply with the requirement "
1915 << "for numbering the operation codes "
1916 << "according to alphabetical order of "
1917 << "operations. Please fix the vhdl and "
1918 << "hdb entry." << std::endl;
1919 }
1920 }
1921 int requiredBits = MathTools::requiredBits(opcode);
1922 if (requiredBits > portWidth) {
1923 portWidth = requiredBits;
1924 }
1925 opcode++;
1926 }
1927
1928 return portWidth;
1929 }
1930
1931 /**
1932 * Calculates the required opcode port width for the given GCU.
1933 *
1934 * @param gcu The GCU.
1935 * @return The required width of opcode port.
1936 */
1938 set<string> opcodeSet;
1939 for (int i = 0; i < gcu.operationCount(); i++) {
1940 HWOperation* operation = gcu.operation(i);
1941 opcodeSet.insert(operation->name());
1942 }
1943
1944 // Assumes that operations of GCU are coded as
1945 // 0..operationCount()-1.
1946 if (opcodeSet.size() < 2) {
1947 return 1;
1948 } else {
1949 return MathTools::requiredBits(opcodeSet.size() - 1);
1950 }
1951 }
1952
1953 /**
1954 * Finds the corresponding ports from the given function units.
1955 *
1956 * @param fuToSearch The FU that is searched for the corresponding port.
1957 * @param origFU The original FU.
1958 * @param portName Name of the port in the original FU.
1959 * @return The corresponding port in fuToSearch FU.
1960 * @exception InstanceNotFound If there is no corresponding port.
1961 */
1964 const TTAMachine::FunctionUnit& fuToSearch,
1965 const TTAMachine::FunctionUnit& origFU, const std::string& portName) {
1966 FUPort* correspondingPort = NULL;
1967 assert(origFU.hasOperationPort(portName));
1968 const FUPort* origPort = origFU.operationPort(portName);
1969 for (int i = 0; i < origFU.operationCount(); i++) {
1970 HWOperation* origOperation = origFU.operation(i);
1971 string opName = origOperation->name();
1972 if (fuToSearch.hasOperation(opName)) {
1973 HWOperation* operation = fuToSearch.operation(opName);
1974 if (!origOperation->isBound(*origPort)) {
1975 continue;
1976 }
1977 int origIO = origOperation->io(*origPort);
1978 FUPort* port = operation->port(origIO);
1979 if (port == NULL) {
1980 throw InstanceNotFound(__FILE__, __LINE__, __func__);
1981 }
1982 if (correspondingPort == NULL) {
1983 correspondingPort = port;
1984 } else if (correspondingPort != port) {
1985 throw InstanceNotFound(__FILE__, __LINE__, __func__);
1986 }
1987 }
1988 }
1989
1990 if (correspondingPort == NULL) {
1992 std::string("Corresponding port for [") + portName +
1993 "] defined in HDB was not found in FU of ADF: [" +
1994 fuToSearch.name() + "].");
1995 }
1996
1997 return *correspondingPort;
1998 }
1999
2000 /**
2001 * Explores the given machine for the width of the instruction memory
2002 * address.
2003 *
2004 * @param machine The machine.
2005 * @return The width of the instruction memory address.
2006 * @exception IllegalMachine If the machine is erroneous.
2007 */
2008 int
2014
2015 /**
2016 * Explores the given machine for the width of the instruction memory.
2017 *
2018 * @param machine The machine.
2019 * @return The width of the instruction memory.
2020 * @exception IllegalMachine If the machine is erroneous.
2021 */
2022 int
2028
2029 /**
2030 * Returns the address space that represents the instruction memory of
2031 * the
2032 * given machine.
2033 *
2034 * @param machine The machine.
2035 * @return The address space.
2036 * @exception IllegalMachine If the machine does not have the
2037 * instruction
2038 * memory address space.
2039 */
2043 if (cu == NULL) {
2044 string errorMsg = "The machine does not have a control unit.";
2045 throw IllegalMachine(__FILE__, __LINE__, __func__, errorMsg);
2046 }
2047
2048 AddressSpace* iMem = cu->addressSpace();
2049 if (iMem == NULL) {
2050 string errorMsg =
2051 "The control unit does not have an address space.";
2052 throw IllegalMachine(__FILE__, __LINE__, __func__, errorMsg);
2053 }
2054
2055 return *iMem;
2056 }
2057
2060 switch (direction) {
2061 case HDB::IN:
2062 return IN;
2063 case HDB::OUT:
2064 return OUT;
2065 case HDB::BIDIR:
2066 return BIDIR;
2067 default:
2068 assert(false && "Unknown HDB::direction.");
2069 return IN;
2070 }
2071 }
2072
2073 /**
2074 * Return fixed instance name if instance name is equal to module name.
2075 *
2076 * @param baseInstanceName Default name for a component instance
2077 * @param moduleName Name for the component module defined in HDB
2078 * @return Instance name differing from the module name.
2079 */
2081 const TCEString& baseInstanceName, const TCEString& moduleName) const {
2082
2083 TCEString newInstanceName;
2084 if (baseInstanceName.lower() == moduleName.lower()) {
2085 newInstanceName = baseInstanceName + INSTANCE_SUFFIX;
2086 } else {
2087 newInstanceName = baseInstanceName;
2088 }
2089 return newInstanceName;
2090 }
2091
2092 /**
2093 * (Ugly) heursitics for identifying an LSU.
2094 *
2095 * If it has an address space and implements a memory operation, it is
2096 * an
2097 * LSU
2098 *
2099 * @param fu Function unit to be tested
2100 * @return Is the fu an LSU
2101 */
2103
2104 if (!fu.hasAddressSpace()) {
2105 return false;
2106 }
2107
2108 const int opCount = 18;
2109 TCEString ops[opCount] = {
2110 "ldw", "ldh", "ldq", "ldw2", "ldw4",
2111 "stw", "sth", "stq", "stw2", "stw4",
2112 "ld8", "ldu8", "ld16","ldu16", "ld32",
2113 "st8", "st16", "st32"
2114 };
2115
2116 for (auto& op : ops) {
2117 if (fu.hasOperationLowercase(op)) {
2118 return true;
2119 }
2120 }
2121 return false;
2122 }
2123
2124 /**
2125 * (Ugly) heuristics for identifying an LSU data memory port.
2126 *
2127 * The identification is made by partial match of the port's name.
2128 *
2129 * @param portName The port name given in HDB.
2130 * @return True if the port is LSU data memory port.
2131 */
2133 const TTAMachine::FunctionUnit& adfFU, const std::string& portName) {
2134
2135 if (!adfFU.hasAddressSpace()) {
2136 return false;
2137 }
2138
2139 static const std::set<std::string> magicWords{
2140 "addr", "data", "mem_en", "wr_en", "wr_mask"};
2141
2142 for (auto magicWord : magicWords) {
2143 if (portName.find(magicWord) != std::string::npos) {
2144 return true;
2145 }
2146 }
2147
2148 return false;
2149 }
2150
2151 Signal NetlistGenerator::inferLSUSignal(const std::string& portName) {
2152 size_t pos = 0;
2153 if (((pos = portName.find("addr")) != std::string::npos)) {
2154 return SignalType::ADDRESS;
2155 } else if (((pos = portName.find("data")) != std::string::npos)) {
2156 if ((portName.find("_in", pos + 4)) != std::string::npos) {
2157 return SignalType::READ_DATA;
2158 } else if ((portName.find("_out", pos + 4)) != std::string::npos) {
2160 }
2161 } else if (((pos = portName.find("mem_en")) != std::string::npos)) {
2162 if ((portName.find("_x", pos + 6)) != std::string::npos) {
2164 } else {
2166 }
2167 } else if (((pos = portName.find("wr_mask")) != std::string::npos)) {
2168 if ((portName.find("_x", pos + 7)) != std::string::npos) {
2170 } else {
2172 }
2173 } else if (((pos = portName.find("wr_en")) != std::string::npos)) {
2174 if ((portName.find("_x", pos + 5)) != std::string::npos) {
2176 } else {
2177 return SignalType::WRITEMODE;
2178 }
2179 }
2180 return SignalType::UNDEFINED;
2181 }
2182
2183} // namespace ProGe
#define __func__
#define assert(condition)
IDF::MachineImplementation * implementation
the implementation definition of the estimated processor
TTAMachine::Machine * machine
the architecture definition of the estimated processor
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition Exception.hh:39
static MachInfoCmdLineOptions options
Definition MachInfo.cc:46
const string IMEMADDRWIDTH
const string RA_OUT_PORT_NAME
const string PC_READ_PORT_NAME
const string RA_IN_PORT_NAME
const string RF_NAME_PREFIX
const string FETCH_PORT_NAME
const string INSTRUCTIONWIDTH
const string DATA_PORT_NAME
const string TOPLEVEL_BLOCK_DEFAULT_NAME
const string IU_NAME_PREFIX
const string GLOBAL_LOCK_PORT_NAME
const string PC_IN_PORT_NAME
const string LOCK_PORT_NAME
const TCEString INSTANCE_SUFFIX
const string FU_NAME_PREFIX
const string DECODER_BLOCK_NAME
const string INSTRUCTIONWORD_PORT_NAME
const string PC_OPCODE_PORT_NAME
const string JUMP
const string PC_LOAD_PORT_NAME
const string IMEMWIDTHFORMULA
const string LOCK_REQUEST_PORT_NAME
const string ADDRESS_PORT_NAME
const string IFETCH_BLOCK_NAME
const string CLOCK_PORT_NAME
const string RESET_PORT_NAME
const string DECOMPRESSOR_BLOCK_NAME
const string LOCK_STATUS_PORT_NAME
const string RA_LOAD_PORT_NAME
const string READ_ENABLE_PORT_NAME
const string FETCHBLOCK_PORT_NAME
const string BUSY_PORT_NAME
const string CALL
static std::string toString(const T &source)
std::string errorMessage() const
Definition Exception.cc:123
std::string widthFormula() const
std::string parameterDependency(int index) const
int parameterDependencyCount() const
std::string name() const
Direction direction() const
HDB::Direction portDirection(const std::string &port) const
bool hasParameterizedWidth(const std::string &port) const
TTAMachine::FunctionUnit & architecture() const
FUImplementation & implementation() const
Definition FUEntry.cc:86
virtual bool hasImplementation() const
Definition FUEntry.cc:74
FUArchitecture & architecture() const
Definition FUEntry.cc:129
virtual bool hasArchitecture() const
Definition FUEntry.cc:117
FUPortImplementation & architecturePort(int index) const
Parameter parameter(int index) const
std::string glockReqPort() const
FUExternalPort & externalPort(int index) const
std::string opcodePort() const
std::string architecturePort() const
FUEntry * fuByEntryID(RowID id) const
RFEntry * rfByEntryID(RowID id) const
static HDBRegistry & instance()
CachedHDBManager & hdb(const std::string fileName)
std::string loadPort() const
bool hasGuardSupport() const
virtual bool hasImplementation() const
Definition RFEntry.cc:74
RFArchitecture & architecture() const
Definition RFEntry.cc:145
virtual bool hasArchitecture() const
Definition RFEntry.cc:117
RFImplementation & implementation() const
Definition RFEntry.cc:102
std::string opcodePortWidthFormula() const
std::string name() const
RFImplementationLocation & iuImplementation(const std::string &iu) const
RFImplementationLocation & rfImplementation(const std::string &rf) const
FUImplementationLocation & fuImplementation(const std::string &fu) const
const std::vector< FUGenerated > & FUGenerations() const
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
static void deleteAllValues(MapType &aMap)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
static int requiredBits(unsigned long int number)
const std::string & instanceName() const
const std::string & moduleName() const
void addOutOperand(TTAMachine::FUPort *port)
void addInOperand(TTAMachine::FUPort *port, int id)
virtual void completeNetlist(NetlistBlock &netlistBlock, const NetlistGenerator &generator)=0
Convenience class for input bit ports.
Convenience class for input ports.
virtual const Parameter & parameter(const std::string &name) const
void addSubBlock(BaseNetlistBlock *subBlock, const std::string &instanceName="")
void setParameter(const std::string &name, const std::string &type, const std::string &value)
void addParameter(const Parameter &param)
void addPackage(const std::string &packageName)
void addPortGroup(NetlistPortGroup *portGroup)
virtual const Netlist & netlist() const
friend class GeneratableFUNetlistBlock
NetlistPort & fuGuardPort(const NetlistPort &fuPort) const
PortPurposeMap clkPorts_
Maps clock ports.
IUPortMap iuPortMap_
Maps the created netlist ports to immediate units.
PortRelationMap loadPortMap_
Maps loads ports.
static const std::string DECOMP_GLOCK_PORT
Global lock out port name in decompressor.
static int instructionMemoryAddressWidth(const TTAMachine::Machine &machine)
void addFUExternalPortsToNetlist(const HDB::FUImplementation &fuImplementation, NetlistBlock &coreBlock, NetlistBlock &fuBlock, const TTAMachine::FunctionUnit &adfFU)
PortPurposeMap fuOpcodePorts_
Maps FU opcode ports.
static const std::string DECODER_LOCK_REQ_OUT_PORT
Lock request out port name in instruction decoder.
FUEntryMap fuEntryMap_
Maps FU implementations for different FU's.
void mapLoadPort(const NetlistPort &port, NetlistPort &loadPort)
RFEntryMap rfEntryMap_
Maps RF implementations for different RF's.
static bool isLSUDataPort(const TTAMachine::FunctionUnit &adfFU, const std::string &portName)
NetlistPort & rstPort(const NetlistBlock &block) const
void mapRFOpcodePort(const NetlistPort &port, NetlistPort &opcodePort)
NetlistBlock & netlistBlock(const TTAMachine::Unit &unit) const
ICDecoderGeneratorPlugin & plugin_
The generator plugin.
GeneratableFUNetlistBlock * addGeneratableFUsToNetlist(const IDF::FUGenerated &fug, NetlistBlock &netlistBlock)
NetlistBlock * generate(const ProGeOptions &options, int imemWidthInMAUs, TCEString entityNameStr, std::ostream &warningStream)
bool isParameterizable(const std::string &paramName, const HDB::FUEntry *fuEntry) const
static const std::string DECODER_PC_LOAD_PORT
PC load port name in instruction decoder.
const ProGeContext & context_
void mapFUOpcodePort(const NetlistBlock &block, NetlistPort &opcodePort)
void addRFToNetlist(const ProGeOptions &options, const IDF::RFImplementationLocation &location, NetlistBlock &netlistBlock)
PortPurposeMap glockPorts_
Maps global lock ports.
static const std::string FETCHBLOCK_PORT_NAME
TCEString checkInstanceName(const TCEString &baseInstanceName, const TCEString &moduleName) const
unsigned int calculateAddressWidth(TTAMachine::FunctionUnit const *fu) const
NetlistPort & loadPort(const NetlistPort &port) const
void mapGlobalLockPort(const NetlistBlock &block, NetlistPort &glockPort)
static const std::string DECODER_PC_OPCODE_PORT
PC opcode port name in instruction decoder.
bool hasGlockPort(const NetlistBlock &block) const
static const std::string DECODER_CLOCK_PORT
Clock port name in instruction decoder.
static const std::string DECODER_INSTR_WORD_PORT
Instruction word port name in instruction decoder.
NetlistBlock & ttaCore() const
PortPurposeMap rfGuardPorts_
Maps RF guard ports.
static const std::string DECODER_RA_LOAD_PORT
RA load port name in instruction decoder.
static const std::string DECOMP_INSTR_WORD_PORT
Instruction word port name in decompressor.
void mapNetlistPort(const TTAMachine::Port &adfPort, NetlistPort &netlistPort)
NetlistGenerator(const ProGeContext &context, ICDecoderGeneratorPlugin &plugin)
NetlistBlock * coreBlock_
The TTA core block.
NetlistPort * raOutPort_
Returns address out port in GCU (ifetch).
static Signal inferLSUSignal(const std::string &portName)
void mapNetlistBlock(const TTAMachine::Unit &unit, NetlistBlock &netlistBlock)
NetlistPort & gcuReturnAddressInPort() const
UnitCorrespondenceMap unitCorrespondenceMap_
Maps the ADF units to the netlist blocks.
NetlistPort & rfOpcodePort(const NetlistPort &port) const
bool hasGlockReqPort(const NetlistBlock &block) const
NetlistBlock * instructionDecompressor_
The instruction decompressor block.
bool isLSU(const TTAMachine::FunctionUnit &fu) const
NetlistBlock & instructionDecompressor() const
void addFUToNetlist(const IDF::FUImplementationLocation &location, NetlistBlock &netlistBlock, std::ostream &warningStream)
HDB::FUEntry & fuEntry(const std::string &fuName) const
static int instructionMemoryWidth(const TTAMachine::Machine &machine)
NetlistBlock & instructionDecoder() const
PortPurposeMap rstPorts_
Maps reset ports.
void addBaseRFToNetlist(const ProGeOptions &options, const TTAMachine::BaseRegisterFile &regFile, const IDF::RFImplementationLocation &location, NetlistBlock &netlistBlock, const std::string &blockNamePrefix)
void mapRFGuardPort(const NetlistBlock &block, NetlistPort &guardPort)
NetlistPort & immediateUnitWritePort(const TTAMachine::ImmediateUnit &iu) const
static const std::string DECODER_LOCK_REQ_IN_PORT
Lock request in port name in instruction decoder.
NetlistPort & glockReqPort(const NetlistBlock &block) const
void mapResetPort(const NetlistBlock &block, NetlistPort &resetPort)
static TTAMachine::AddressSpace & instructionMemory(const TTAMachine::Machine &machine)
NetlistBlock & instructionFetch() const
void mapImmediateUnitWritePort(const TTAMachine::ImmediateUnit &iu, NetlistPort &port)
NetlistBlock * instructionDecoder_
The instruction decoder block.
NetlistPort & gcuReturnAddressOutPort() const
PortRelationMap rfOpcodePortMap_
Maps opcode ports.
void mapGlobalLockRequestPort(const NetlistBlock &block, NetlistPort &glockReqPort)
NetlistPort & netlistPort(const TTAMachine::Port &port, Direction dir=IN) const
static const std::string DECOMP_LOCK_REQ_IN_PORT
Lock request in port name in decompressor.
void mapClockPort(const NetlistBlock &block, NetlistPort &clkPort)
PortCorrespondenceMap portCorrespondenceMap_
Maps the ADF ports to the netlist ports.
bool hasOpcodePort(const NetlistPort &port) const
void mapFUGuardPort(const NetlistPort &dataPort, NetlistPort &guardPort)
void addGCUToNetlist(NetlistBlock &toplevelBlock, int imemWidthInMAUs)
void addIUToNetlist(const ProGeOptions &options, const IDF::RFImplementationLocation &location, NetlistBlock &netlistBlock)
NetlistPort & fuOpcodePort(const NetlistBlock &fuBlock) const
static int opcodePortWidth(const HDB::FUEntry &fu, std::ostream &warningStream)
NetlistPort & glockPort(const NetlistBlock &block) const
PortPurposeMap glockReqPorts_
Maps global lock request ports.
static TTAMachine::FUPort & findCorrespondingPort(const TTAMachine::FunctionUnit &fuToSearch, const TTAMachine::FunctionUnit &origFU, const std::string &portName)
NetlistPort * raInPort_
Return address in port in GCU (ifetch).
NetlistPort & clkPort(const NetlistBlock &block) const
bool netlistPortIsMapped(const TTAMachine::Port &adfPort)
NetlistBlock * instructionFetch_
The instruction fetch block.
NetlistPort & rfGuardPort(const NetlistBlock &rfBlock) const
PortRelationMap fuGuardPortMap_
Maps FU guard ports.
HDB::RFEntry & rfEntry(const std::string &rfName) const
static const std::string DECODER_LOCK_STATUS_PORT
static Direction translateDirection(HDB::Direction direction)
static const std::string DECODER_RESET_PORT
Reset port name in instruction decoder.
void addPort(NetlistPort &port)
const BaseNetlistBlock & parentBlock() const
Direction direction() const
std::string name() const
static void connectResets(NetlistBlock &block)
Definition Netlist.cc:511
bool connect(const NetlistPort &port1, const NetlistPort &port2, int port1FirstBit, int port2FirstBit, int width=1)
Definition Netlist.cc:83
void setParameter(const std::string &name, const std::string &type, const std::string &value)
Definition Netlist.cc:362
static void connectClocks(NetlistBlock &block)
Definition Netlist.cc:483
bool hasParameter(const std::string &name) const
Definition Netlist.cc:403
Convenience class for output bit ports.
Convenience class for output ports.
const TCEString & value() const
Definition Parameter.cc:143
const TCEString & type() const
Definition Parameter.cc:138
const TCEString & name() const
Definition Parameter.cc:133
const std::string & coreEntityName() const
const IDF::MachineImplementation & idf() const
const TTAMachine::Machine & adf() const
static unsigned replace(std::string &str, const std::string &oldPattern, const std::string &newPattern)
Definition TCEString.cc:251
TCEString lower() const
Definition TCEString.cc:78
virtual ULongWord end() const
virtual int width() const
virtual ULongWord start() const
virtual int width() const
void setWidth(int width)
virtual int numberOfRegisters() const
virtual int width() const
virtual RFPort * port(const std::string &name) const
virtual TCEString name() const
SpecialRegisterPort * returnAddressPort() const
virtual bool isTriggering() const
Definition FUPort.cc:182
virtual AddressSpace * addressSpace() const
virtual BaseFUPort * triggerPort() const
virtual HWOperation * operation(const std::string &name) const
virtual int operationCount() const
virtual bool hasOperationLowercase(const std::string &name) const
virtual FUPort * operationPort(const std::string &name) const
virtual bool hasOperationPort(const std::string &name) const
virtual bool hasOperation(const std::string &name) const
virtual int operationPortCount() const
virtual bool hasAddressSpace() const
virtual BaseFUPort * port(const std::string &name) const
virtual FUPort * port(int operand) const
int io(const FUPort &port) const
const std::string & name() const
bool isBound(const FUPort &port) const
ComponentType * item(int index) const
bool hasItem(const std::string &name) 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 ControlUnit * controlUnit() const
Definition Machine.cc:345
bool isRISCVMachine() const
Definition Machine.cc:1057
virtual Socket * outputSocket() const
Definition Port.cc:281
virtual bool isInput() const
Definition Port.cc:298
virtual bool isOutput() const
Definition Port.cc:308
virtual int width() const =0
Unit * parentUnit() const
virtual Socket * inputSocket() const
Definition Port.cc:261
virtual std::string name() const
Definition Port.cc:141
virtual int portCount() const
Definition Unit.cc:135
Direction
Direction of port.
Definition HDBTypes.hh:40
@ OUT
Output port.
Definition HDBTypes.hh:42
@ BIDIR
Bidirectional port.
Definition HDBTypes.hh:43
@ IN
Input port.
Definition HDBTypes.hh:41
Definition FUGen.hh:54
@ BIT
One bit.
Definition ProGeTypes.hh:47
@ BIT_VECTOR
Several bits.
Definition ProGeTypes.hh:48
@ BITMASKED_SRAM_PORT
Signal group type for one port SRAM having read and write capability and bitmask for writing.
@ INSTRUCTION_LINE
Signal group type for serial TTA instruction bus.
Direction
Direction of the port.
Definition ProGeTypes.hh:52
@ OUT
Output port.
Definition ProGeTypes.hh:54
@ IN
Input port.
Definition ProGeTypes.hh:53
@ BIDIR
Bidirectional port.
Definition ProGeTypes.hh:55
@ UNDEFINED
Signal does not have specified usage.
@ READ_REQUEST
Signal to make read request.
@ ADDRESS
Signal holds address.
@ READ_REQUEST_READY
Signal to tell that requested data can be read.
@ READ_WRITE_REQUEST
Signal to make either read or write request.
@ WRITEMODE
Signal to choose mode for READ_WRITE_REQUEST or similar.
@ FETCHBLOCK
Signal is TTA instruction block block containing (compressed) instruction.
@ RESET
Reset signal.
@ CLOCK
Clock signal.
@ CORE_HALT_STATUS
Signal that tell if core is halted.
std::string value
Value of the parameter.
Definition HDBTypes.hh:49
std::string type
Type of the parameter.
Definition HDBTypes.hh:48
std::string name
Name of the parameter.
Definition HDBTypes.hh:47