OpenASIP 2.2
Loading...
Searching...
No Matches
DefaultDecoderGenerator.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 DefaultDecoderGenerator.cc
26 *
27 * Implementation of DefaultDecoderGenerator class.
28 *
29 * @author Lasse Laasonen 2005 (lasse.laasonen-no.spam-tut.fi)
30 * @author Vinogradov Viacheslav(added Verilog generating) 2012
31 * @note rating: red
32 */
33#include <string>
34#include <fstream>
35#include <iostream>
36#include <algorithm>
37#include <set>
38#include <boost/format.hpp>
39
42
43#include "NetlistBlock.hh"
44#include "NetlistGenerator.hh"
45#include "NetlistPort.hh"
46#include "Netlist.hh"
47#include "VHDLNetlistWriter.hh"
49#include "CUOpcodeGenerator.hh"
50
51#include "Machine.hh"
52#include "MachineInfo.hh"
53#include "Bus.hh"
54#include "Segment.hh"
55#include "Socket.hh"
56#include "Guard.hh"
57#include "FUPort.hh"
59#include "ControlUnit.hh"
60#include "HWOperation.hh"
61
62#include "BinaryEncoding.hh"
64#include "MoveSlot.hh"
65#include "SourceField.hh"
66#include "DestinationField.hh"
67#include "GuardField.hh"
68#include "SocketEncoding.hh"
69#include "ImmediateEncoding.hh"
70#include "SocketCodeTable.hh"
71#include "ImmediateSlotField.hh"
73#include "GPRGuardEncoding.hh"
74#include "FUGuardEncoding.hh"
76#include "FUPortCode.hh"
77#include "RFPortCode.hh"
78#include "IUPortCode.hh"
79#include "NOPEncoding.hh"
80#include "BEMTools.hh"
81
82#include "FUEntry.hh"
83#include "FUImplementation.hh"
84
85#include "RFEntry.hh"
86#include "RFImplementation.hh"
87
88#include "FileSystem.hh"
89#include "MathTools.hh"
90#include "AssocTools.hh"
91#include "StringTools.hh"
92#include "TCEString.hh"
93#include "Conversion.hh"
94#include "MapTools.hh"
95
96using namespace ProGe;
97using namespace TTAMachine;
98using namespace HDB;
99
100using std::string;
101using std::endl;
102using std::set;
103using boost::format;
104
105const string LIMM_TAG_SIGNAL = "limm_tag";
106const string GLOCK_PORT_NAME = "glock";
107const string LOCK_REQ_PORT_NAME = "lock_req";
108const string INTERNAL_MERGED_GLOCK_REQ_SIGNAL = "merged_glock_req";
109const string PRE_DECODE_MERGED_GLOCK_SIGNAL = "pre_decode_merged_glock";
110const string POST_DECODE_MERGED_GLOCK_SIGNAL = "post_decode_merged_glock";
111const string POST_DECODE_MERGED_GLOCK_OUTREG = "post_decode_merged_glock_r";
112const string PIPELINE_FILL_LOCK_SIGNAL = "decode_fill_lock_reg";
113
114const string JUMP = "jump";
115const string CALL = "call";
116const string BZ = "bz";
117const string BNZ = "bnz";
118const string BZ1 = "bz1";
119const string BNZ1 = "bnz1";
120const string BEQ = "beq";
121const string BGE = "bge";
122const string BGEU = "bgeu";
123const string BGT = "bgt";
124const string BGTU = "bgtu";
125const string BLE = "ble";
126const string BLEU = "bleu";
127const string BLT = "blt";
128const string BLTU = "bltu";
129const string BNE = "bne";
130const string JUMPR = "jumpr";
131const string CALLR = "callr";
132const string CALLA = "calla";
133const string BEQR = "beqr";
134const string BNER = "bner";
135const string BGTR = "bgtr";
136const string BLTR = "bltr";
137const string BGTUR = "bgtur";
138const string BLTUR = "bltur";
139const string BLER = "bler";
140const string BGER = "bger";
141const string BLEUR = "bleur";
142const string BGEUR = "bgeur";
143const string APC = "apc";
144
146const string DefaultDecoderGenerator::GLOCK_PORT_NAME = "glock";
147
148/**
149 * The constructor.
150 *
151 * @param machine The machine.
152 * @param bem The binary encoding map.
153 * @param icGenerator The IC generator.
154 */
156 const TTAMachine::Machine& machine, const BinaryEncoding& bem,
157 const CentralizedControlICGenerator& icGenerator)
158 : machine_(machine),
159 bem_(bem),
160 icGenerator_(icGenerator),
161 nlGenerator_(NULL),
162 decoderBlock_(NULL),
163 generateLockTrace_(false),
164 language_(VHDL),
165 generateDebugger_(false),
166 lockTraceStartingCycle_(1),
167 generateAlternateGlockReqHandling_(false),
168 unitGlockBitMap_(),
169 unitGlockReqBitMap_() {}
170
171/**
172 * SetHDL.
173 *
174 * @param language The HDL language.
175 */
176void
180
181void
185
186void
188 syncReset_ = value;
189}
190
191void
195
196/**
197 * Generates alternate global lock wiring where FU will not receive global
198 * lock back if the FU did request the lock unless there are other FUs
199 * requesting global lock.
200 *
201 * @param generate Set to true enables the feature.
202 */
203void
207
208/**
209 * The destructor.
210 */
213
214/**
215 * Completes the decoder block in the given netlist block representing the
216 * TTA core by adding the IC-interface and connecting the decoder to the
217 * interconnection network and machine building units.
218 *
219 * @param nlGenerator The netlist generator that generated the netlist.
220 * @param coreBlock The netlist block that contains the decoder.
221 */
222void
224 const ProGe::NetlistGenerator& nlGenerator,
225 ProGe::NetlistBlock& coreBlock) {
226 nlGenerator_ = &nlGenerator;
227 NetlistBlock& decoder = nlGenerator.instructionDecoder();
228 decoderBlock_ = &decoder;
229
230 entityNameStr_ = coreBlock.moduleName();
231
232 // add ports for short immediates to decoder and connect them to IC
234 for (int i = 0; i < busNav.count(); i++) {
235 Bus* bus = busNav.item(i);
236 if (bus->immediateWidth() > 0) {
238 bus->name());
239 NetlistPort& icSimmCntrlPort = icGenerator_.
240 simmCntrlPort(bus->name());
241 NetlistPort* decSimmPort = new NetlistPort(
242 simmDataPort(bus->name()),
245 coreBlock.netlist().connect(*decSimmPort, icSimmPort);
246 NetlistPort* decSimmCntrlPort = new NetlistPort(
247 simmControlPort(bus->name()), "1", 1, ProGe::BIT_VECTOR,
248 ProGe::OUT, decoder);
249 coreBlock.netlist().connect(*decSimmCntrlPort, icSimmCntrlPort);
250 }
251 }
252
253 // add socket control ports to decoder and connect them to IC
255 for (int i = 0; i < socketNav.count(); i++) {
256 Socket* socket = socketNav.item(i);
257 if ((socket->portCount() == 0 || socket->segmentCount() == 0) &&
258 (socket->direction() == Socket::OUTPUT)) {
259 continue;
260 }
261 if (needsBusControl(*socket)) {
262 NetlistPort* busCntrlPort = new NetlistPort(
263 socketBusControlPort(socket->name()),
266 decoder);
268 socket->name());
269 coreBlock.netlist().connect(icBusCntrlPort, *busCntrlPort);
270 }
271 if (needsDataControl(*socket)) {
272 NetlistPort* dataCntrlPort = new NetlistPort(
273 socketDataControlPort(socket->name()),
276 decoder);
277 NetlistPort& icDataCntrlPort =
279 coreBlock.netlist().connect(icDataCntrlPort, *dataCntrlPort);
280 }
281 }
282
283 // add FU control ports to decoder and connect them to the FUs
286 for (int i = 0; i < fuNav.count(); i++) {
287 FunctionUnit* fu = fuNav.item(i);
288 for (int i = 0; i < fu->portCount(); i++) {
289 BaseFUPort* port = fu->port(i);
290 NetlistPort& nlPort = nlGenerator.netlistPort(*port);
291 if (nlPort.direction() == ProGe::IN) {
292 NetlistPort& loadPort = nlGenerator.loadPort(nlPort);
293 NetlistPort* loadCntrlPort = new NetlistPort(
294 fuLoadCntrlPort(fu->name(), port->name()), "1", 1,
295 ProGe::BIT, ProGe::OUT, decoder);
296 coreBlock.netlist().connect(*loadCntrlPort, loadPort);
297 }
298 }
299
300 if (opcodeWidth(*fu) > 0) {
301 const NetlistBlock& fuBlock = nlGenerator.netlistBlock(*fu);
302 NetlistPort& opcodePort = nlGenerator.fuOpcodePort(fuBlock);
303 NetlistPort* opcodeCntrlPort = new NetlistPort(
304 fuOpcodeCntrlPort(fu->name()),
306 ProGe::BIT_VECTOR, ProGe::OUT, decoder);
307 coreBlock.netlist().connect(opcodePort, *opcodeCntrlPort);
308 }
309 }
310 // Add GCU control ports for operand ports (other than RA ports).
312 for (int i = 0; i < gcu->portCount(); i++) {
313 BaseFUPort* port = gcu->port(i);
314 if (!port->isInput() ||
315 port->name() == gcu->returnAddressPort()->name() ||
316 port->isTriggering()) {
317 continue;
318 }
319 NetlistPort& nlPort = nlGenerator.netlistPort(*port);
320 NetlistPort& loadPort = nlGenerator.loadPort(nlPort);
321 NetlistPort* loadCntrlPort = new NetlistPort(
322 fuLoadCntrlPort(gcu->name(), port->name()), "1", 1, ProGe::BIT,
323 ProGe::OUT, decoder);
324 coreBlock.netlist().connect(*loadCntrlPort, loadPort);
325 }
326
327 // add RF control ports to decoder and connect them to the RFs
330 for (int i = 0; i < rfNav.count(); i++) {
331 RegisterFile* rf = rfNav.item(i);
332 for (int i = 0; i < rf->portCount(); i++) {
333 RFPort* port = rf->port(i);
334 NetlistPort& nlPort = nlGenerator.netlistPort(*port);
335 NetlistPort& loadPort = nlGenerator.loadPort(nlPort);
336
337 NetlistPort* loadCntrlPort = new NetlistPort(
338 rfLoadCntrlPort(rf->name(), port->name()),
339 loadPort.widthFormula(), 1, ProGe::BIT, ProGe::OUT, decoder);
340
341 coreBlock.netlist().connect(loadPort, *loadCntrlPort);
342
343 int opcodeWidth = rfOpcodeWidth(*rf);
344 assert(!(!nlGenerator.hasOpcodePort(nlPort) &&
345 opcodeWidth > 1));
346 if (nlGenerator.hasOpcodePort(nlPort) && opcodeWidth >= 0) {
347 NetlistPort& opcodePort = nlGenerator.rfOpcodePort(nlPort);
348 NetlistPort* opcodeCntrlPort = new NetlistPort(
349 rfOpcodeCntrlPort(rf->name(), port->name()),
351 ProGe::BIT_VECTOR, ProGe::OUT, decoder);
352 coreBlock.netlist().connect(opcodePort, *opcodeCntrlPort);
353 }
354 }
355 }
356
357 // add IU control ports to decoder and connect them to the IU's
360 for (int i = 0; i < iuNav.count(); i++) {
361 ImmediateUnit* iu = iuNav.item(i);
362
363 // add control ports for read ports
364 for (int i = 0; i < iu->portCount(); i++) {
365 RFPort* port = iu->port(i);
366 NetlistPort& iuDataPort = nlGenerator.netlistPort(*port);
367 NetlistPort& loadPort = nlGenerator.loadPort(iuDataPort);
368 std::string portName =
369 iuReadLoadCntrlPort(iu->name(), port->name());
370 NetlistPort* loadCntrlPort = new NetlistPort(
371 portName, "1", 1, ProGe::BIT, ProGe::OUT, decoder);
372 coreBlock.netlist().connect(loadPort, *loadCntrlPort);
373
374 int opcodeWidth = rfOpcodeWidth(*iu);
375 assert(!(!nlGenerator.hasOpcodePort(iuDataPort) &&
376 opcodeWidth > 1));
377 if (nlGenerator.hasOpcodePort(iuDataPort) && opcodeWidth >= 0) {
378 NetlistPort& opcodePort = nlGenerator.rfOpcodePort(
379 iuDataPort);
380 portName = iuReadOpcodeCntrlPort(iu->name(), port->name());
381 NetlistPort* opcodeCntrlPort = new NetlistPort(
383 ProGe::BIT_VECTOR, ProGe::OUT, decoder);
384 coreBlock.netlist().connect(opcodePort, *opcodeCntrlPort);
385 }
386 }
387
388 // add IU data write port and control ports
389 NetlistPort& iuDataPort = nlGenerator.immediateUnitWritePort(*iu);
390 NetlistPort* decIUDataPort = new NetlistPort(
392 iu->width(), ProGe::BIT_VECTOR, ProGe::OUT, decoder);
393 coreBlock.netlist().connect(iuDataPort, *decIUDataPort);
394 NetlistPort& loadPort = nlGenerator.loadPort(iuDataPort);
395 NetlistPort* loadCntrlPort = new NetlistPort(
397 decoder);
398 coreBlock.netlist().connect(loadPort, *loadCntrlPort);
399
400 int opcodeWidth = rfOpcodeWidth(*iu);
401 if (nlGenerator.hasOpcodePort(iuDataPort) && opcodeWidth >= 0) {
402 NetlistPort& opcodePort = nlGenerator.rfOpcodePort(iuDataPort);
403 NetlistPort* opcodeCntrlPort = new NetlistPort(
406 ProGe::BIT_VECTOR, ProGe::OUT, decoder);
407 coreBlock.netlist().connect(opcodePort, *opcodeCntrlPort);
408 }
409 }
410
411 // add guard ports to decoder and connect them to RF's and FU's
412 std::set<PortGuard*> generatedPortGuards;
413 std::set<RegisterGuard*> generatedRegGuards;
414 for (int i = 0; i < busNav.count(); i++) {
415 Bus* bus = busNav.item(i);
416 for (int i = 0; i < bus->guardCount(); i++) {
417 Guard* guard = bus->guard(i);
418 PortGuard* portGuard = dynamic_cast<PortGuard*>(guard);
419 RegisterGuard* regGuard = dynamic_cast<RegisterGuard*>(guard);
420 if (portGuard != NULL) {
422 generatedPortGuards, *portGuard)) {
423 continue;
424 }
425 FUPort* port = portGuard->port();
426 NetlistPort& nlPort = nlGenerator.netlistPort(*port);
427 NetlistPort& nlGuardPort = nlGenerator.fuGuardPort(
428 nlPort);
429 NetlistPort* decGuardPort = new NetlistPort(
430 guardPortName(*guard), "1", 1, ProGe::BIT, ProGe::IN,
431 decoder);
432 coreBlock.netlist().connect(nlGuardPort, *decGuardPort);
433 generatedPortGuards.insert(portGuard);
434 } else if (regGuard != NULL) {
436 generatedRegGuards, *regGuard)) {
437 continue;
438 }
439 const RegisterFile* rf = regGuard->registerFile();
440 assert(rf->portCount() > 0);
441 const NetlistBlock& nlRf = nlGenerator.netlistBlock(*rf);
442 NetlistPort& nlGuardPort = nlGenerator.rfGuardPort(nlRf);
443 NetlistPort* decGuardPort = new NetlistPort(
444 guardPortName(*guard), "1", 1, ProGe::BIT, ProGe::IN,
445 decoder);
446 coreBlock.netlist().connect(
447 nlGuardPort, *decGuardPort, regGuard->registerIndex(), 0,
448 1);
449 generatedRegGuards.insert(regGuard);
450 }
451 }
452 }
453
456
457 if (generateDebugger_) {
458 /*NetlistPort* dbgResetPort = */ new NetlistPort(
459 "db_tta_nreset", "1", 1, ProGe::BIT, ProGe::IN, decoder);
460 }
461}
462
463/**
464 * Adds the lock request input port to decoder and connects the global lock
465 * request ports of FU's to it.
466 */
467void
469
470 int lockReqWidth = glockRequestWidth();
471
472 if (lockReqWidth == 0) {
473 return;
474 }
475
478
479 // add lock request port to decoder
480 NetlistPort* lockReqPort = new NetlistPort(
481 LOCK_REQ_PORT_NAME, Conversion::toString(lockReqWidth), lockReqWidth,
483
484 // connect the glock request ports of FUs to the lock request port
485 int bitToConnect(0);
486 for (int i = 0; i < fuNav.count(); i++) {
487 FunctionUnit* fu = fuNav.item(i);
488 if (fu->portCount() == 0) {
489 continue;
490 }
491 const NetlistBlock& fuBlock = nlGenerator_->netlistBlock(*fu);
492 if (nlGenerator_->hasGlockReqPort(fuBlock)) {
493 NetlistPort& glockReqPort = nlGenerator_->glockReqPort(fuBlock);
494 netlist.connect(*lockReqPort, glockReqPort, bitToConnect, 0, 1);
495 unitGlockReqBitMap_[fu] = bitToConnect;
496 bitToConnect++;
497 }
498 }
499}
500
501/**
502 * Adds the global lock port to decoder and connects it to the glock ports
503 * of units.
504 *
505 * Precondition: addLockReqPortToDecoder() must be called before this.
506 */
507void
509 int glockWidth = glockPortWidth();
510
511 if (glockWidth == 0) {
512 return;
513 }
514 int bitToConnect = 0;
515
518 NetlistPort* decGlockPort = new NetlistPort(
519 GLOCK_PORT_NAME, Conversion::toString(glockWidth), glockWidth,
521
523 for (int i = 0; i < fuNav.count(); i++) {
524 FunctionUnit* fu = fuNav.item(i);
525 if (fu->portCount() == 0) {
526 continue;
527 }
528 const NetlistBlock& fuBlock = nlGenerator_->netlistBlock(*fu);
529 if (nlGenerator_->hasGlockPort(fuBlock)) {
530 NetlistPort& glockPort = nlGenerator_->glockPort(fuBlock);
531 assert(bitToConnect < glockWidth);
532 netlist.connect(*decGlockPort, glockPort, bitToConnect, 0, 1);
533 unitGlockBitMap_[bitToConnect] = fu;
534 bitToConnect++;
535 }
536 }
537
539 for (int i = 0; i < rfNav.count(); i++) {
540 RegisterFile* rf = rfNav.item(i);
541 if (rf->portCount() == 0) {
542 continue;
543 }
544 const NetlistBlock& rfBlock = nlGenerator_->netlistBlock(*rf);
545 if (nlGenerator_->hasGlockPort(rfBlock)) {
546 NetlistPort& glockPort = nlGenerator_->glockPort(rfBlock);
547 assert(bitToConnect < glockWidth);
548 netlist.connect(*decGlockPort, glockPort, bitToConnect, 0, 1);
549 unitGlockBitMap_[bitToConnect] = rf;
550 bitToConnect++;
551 }
552 }
553
555 for (int i = 0; i < iuNav.count(); i++) {
556 ImmediateUnit* iu = iuNav.item(i);
557 if (iu->portCount() == 0) {
558 continue;
559 }
560 const NetlistBlock& iuBlock = nlGenerator_->netlistBlock(*iu);
561 if (nlGenerator_->hasGlockPort(iuBlock)) {
562 NetlistPort& glockPort = nlGenerator_->glockPort(iuBlock);
563 assert(bitToConnect < glockWidth);
564 netlist.connect(*decGlockPort, glockPort, bitToConnect, 0, 1);
565 unitGlockBitMap_[bitToConnect] = iu;
566 bitToConnect++;
567 }
568 }
569
570 // If IC requests glock port.
572 netlist.connect(
573 *decGlockPort, icGenerator_.glockPort(), bitToConnect, 0, 1);
574 bitToConnect++;
575 }
576}
577
578
579/**
580 * Returns the width of the global lock request port.
581 *
582 * @return The bit width.
583 */
584int
586
588
589 int lockReqWidth(0);
590 for (int i = 0; i < fuNav.count(); i++) {
591 FunctionUnit* fu = fuNav.item(i);
592 if (fu->portCount() == 0) {
593 continue;
594 }
595 const NetlistBlock& fuBlock = nlGenerator_->netlistBlock(*fu);
596 if (nlGenerator_->hasGlockReqPort(fuBlock)) {
597 lockReqWidth++;
598 }
599 }
600 if (generateDebugger_) {
601 lockReqWidth++;
602 }
603
604 return lockReqWidth;
605}
606
607/**
608 * Returns the width of the global lock port.
609 *
610 * @return The bit width.
611 */
612int
614 int glockWidth = 0;
615
617 for (int i = 0; i < fuNav.count(); i++) {
618 FunctionUnit* fu = fuNav.item(i);
619 if (fu->portCount() == 0) {
620 continue;
621 }
622 const NetlistBlock& fuBlock = nlGenerator_->netlistBlock(*fu);
623 if (nlGenerator_->hasGlockPort(fuBlock)) {
624 glockWidth++;
625 }
626 }
627
629 for (int i = 0; i < rfNav.count(); i++) {
630 RegisterFile* rf = rfNav.item(i);
631 if (rf->portCount() == 0) {
632 continue;
633 }
634 const NetlistBlock& rfBlock = nlGenerator_->netlistBlock(*rf);
635 if (nlGenerator_->hasGlockPort(rfBlock)) {
636 glockWidth++;
637 }
638 }
639
641 for (int i = 0; i < iuNav.count(); i++) {
642 ImmediateUnit* iu = iuNav.item(i);
643 if (iu->portCount() == 0) {
644 continue;
645 }
646 const NetlistBlock& iuBlock = nlGenerator_->netlistBlock(*iu);
647 if (nlGenerator_->hasGlockPort(iuBlock)) {
648 glockWidth++;
649 }
650 }
651
653 glockWidth++;
654 }
655
656 return glockWidth;
657}
658
659/**
660 * Writes the instruction decoder to the given destination directory.
661 *
662 * @param dstDirectory The destination directory.
663 * @exception IOException If an IO error occurs.
664 */
665void
667 const ProGe::NetlistGenerator& nlGenerator,
668 const std::string& dstDirectory) {
669 nlGenerator_ = &nlGenerator;
670
671 string iDecoderFile = dstDirectory
673 + ((language_==Verilog)?"decoder.v":"decoder.vhdl");
674 bool decCreated = FileSystem::createFile(iDecoderFile);
675 if (!decCreated) {
676 string errorMsg = "Unable to create file " + iDecoderFile;
677 throw IOException(__FILE__, __LINE__, __func__, errorMsg);
678 }
679 std::ofstream decoderStream(
680 iDecoderFile.c_str(), std::ofstream::out);
681 writeInstructionDecoder(decoderStream);
682 decoderStream.close();
683}
684
685/**
686 * Returns the set of acceptable latencies of the hardware implementation
687 * of the given immediate unit.
688 *
689 * @param iu The immediate unit.
690 */
691std::set<int>
693 const TTAMachine::ImmediateUnit& /*iu*/) const {
694 int acceptableLatencies[] = {0, 1};
695 return std::set<int>(acceptableLatencies, acceptableLatencies + 2);
696}
697
698/**
699 * Verifies that the decoder generator is compatible with the machine.
700 *
701 * @exception InvalidData If the decoder generator is incompatible.
702 */
703void
705 // check that the GCU does not have other operations than the ones
706 // specified below.
708 assert(cu != NULL);
710 MachineInfo::OperationSet supportedOps{JUMP, CALL};
712 BLTUR, BGER, BGEUR, APC, CALLR};
713 MachineInfo::OperationSet unsupportedOps;
714 if (machine_.isRISCVMachine()) {
715 supportedOps.insert(riscvOps.begin(), riscvOps.end());
716 }
717 std::set_difference(
718 cuOps.begin(), cuOps.end(), supportedOps.begin(), supportedOps.end(),
719 std::inserter(unsupportedOps, unsupportedOps.begin()));
720 if (!unsupportedOps.empty()) {
721 format errorMsg(
722 "Decoder generator does not support operation %1% in CU.");
723 errorMsg % TCEString::makeString(unsupportedOps, ", ");
724 THROW_EXCEPTION(InvalidData, errorMsg.str());
725 }
726
729 string errorMsg =
730 TCEString("APC operation requires an output port in the GCU");
731 throw InvalidData(__FILE__, __LINE__, __func__, errorMsg);
732 }
733 // check that there are 3 delay slots in the transport pipeline
734 // RISC-V supports 2 "delay slots"
735 if (cu->delaySlots() != 3 &&
736 (!(cu->delaySlots() == 2 && machine_.isRISCVMachine()))) {
737 throw InvalidData(
738 __FILE__, __LINE__, __func__,
739 TCEString("Decoder generator supports only 4-stage transport ") +
740 "pipeline of CU. Given machine has " +
741 Conversion::toString(cu->delaySlots() + 1) + " stages");
742 }
743
744 // check that global guard latency is 1
745 if (!(cu->globalGuardLatency() == 0 || (cu->globalGuardLatency() == 1))) {
746 string errorMsg = TCEString("Decoder generator supports only ") +
747 "global guard latency of 1. Given machine has " +
749 throw InvalidData(__FILE__, __LINE__, __func__, errorMsg);
750 }
751}
752
753/**
754 * Controls whenever global lock trace dump process will be generated.
755 *
756 * @param generate Generate lock trace process if true.
757 */
758void
762
763/**
764 * Sets starting cycle to begin global lock tracing.
765 *
766 * @param startCycle nth cycle to begin tracing.
767 */
768void
770 lockTraceStartingCycle_ = startCycle;
771}
772
773void
775 std::ostream& stream, ProGe::DataType type, std::string sigName,
776 int width) const {
777 if (language_ == VHDL) {
778 stream << indentation(1) << "signal " << sigName;
779 if (type == ProGe::BIT_VECTOR) {
780 stream << " : std_logic_vector(" << width - 1 << " downto 0);"
781 << endl;
782 } else { // BIT
783 stream << " : std_logic;" << endl;
784 }
785 } else { // Verilog
786 stream << indentation(1) << "reg";
787 if (type == ProGe::BIT_VECTOR) {
788 stream << "[" << width - 1 << ":0]";
789 }
790 stream << " " << sigName << ";" << endl;
791 }
792}
793
794void
796 std::ostream& stream, int indent, std::string comment) const {
797 std::string delim = language_ == VHDL ? "-- " : "// ";
798 stream << indentation(indent) << delim << comment << endl;
799}
800
801/**
802 * Writes the instruction decoder to the given stream.
803 *
804 * @param stream The stream.
805 */
806void
808 if (language_ == VHDL) {
809 stream << "library IEEE;" << endl;
810 stream << "use IEEE.std_logic_1164.all;" << endl;
811 stream << "use IEEE.std_logic_arith.all;" << endl;
812 if (generateLockTrace_) {
813 stream << "use STD.textio.all;" << endl;
814 }
815 stream << "use work." << entityNameStr_ << "_globals.all;" << endl;
816 stream << "use work." << entityNameStr_ << "_gcu_opcodes.all;"
817 << endl;
818 stream << "use work.tce_util.all;" << endl << endl;
819
820 string entityName = entityNameStr_ + "_decoder";
821 stream << "entity " << entityName << " is" << endl << endl;
822
823 // create generic and port declarations
825 *decoderBlock_, 1, indentation(1), stream);
827 *decoderBlock_, 1, indentation(1), stream);
828
829 stream << endl;
830 stream << "end " << entityName << ";" << endl << endl;
831 string architectureName = "rtl_andor";
832 stream << "architecture " << architectureName << " of " << entityName
833 << " is" << endl << endl;
834
835 writeMoveFieldSignals(stream);
836 stream << endl;
838 stream << endl;
840 stream << endl;
841 writeSquashSignals(stream);
842 stream << endl;
844 stream << endl;
845 writeFUCntrlSignals(stream);
846 stream << endl;
847 writeRFCntrlSignals(stream);
848 stream << endl;
850 stream << endl;
852
853 stream << "begin" << endl << endl;
854
855 if (generateLockTrace_) {
856 writeLockDumpCode(stream);
857 stream << endl;
858 }
859
861 stream << endl;
863 stream << endl;
865 stream << endl;
867 stream << endl;
869 stream << endl;
871 stream << endl;
872 writeGlockMapping(stream);
873 stream << endl;
875
876 stream << endl << "end " << architectureName << ";" << endl;
877 } else { //language_ == Verilog
878 const std::string DS = FileSystem::DIRECTORY_SEPARATOR;
879 string entityName = entityNameStr_ + "_decoder";
880 stream << "`timescale 1ns/1ns" << endl
881 << "module " << entityName << endl
882 << "#(" << endl
883 << "`include \""
884 << entityNameStr_ << "_globals_pkg.vh\"" << endl
885 << "," << endl
886 << "`include \"" << "gcu_opcodes_pkg.vh\"" << endl
887 << ")" << endl;
888
890 *decoderBlock_, 1, indentation(1), stream);
891
892 // create generic and port declarations
894 *decoderBlock_, 1, indentation(1), stream);
895
896 stream << endl;
897
898 writeMoveFieldSignals(stream);
899 stream << endl;
901 stream << endl;
903 stream << endl;
904 writeSquashSignals(stream);
905 stream << endl;
907 stream << endl;
908 writeFUCntrlSignals(stream);
909 stream << endl;
910 writeRFCntrlSignals(stream);
911 stream << endl;
912
913 if (generateLockTrace_) {
914 writeLockDumpCode(stream);
915 stream << endl;
916 }
917
919 stream << endl;
921 stream << endl;
923 stream << endl;
925 stream << endl;
927 stream << endl;
929 stream << endl;
930
931 int lockReqWidth = glockRequestWidth();
932 stream << indentation(1) << "assign "
934 if (lockReqWidth > 0) {
935 for (int i = 0; i < lockReqWidth; i++) {
936 stream << LOCK_REQ_PORT_NAME << "[" << i << "]";
937 if (i+1 < lockReqWidth) {
938 stream << " | ";
939 }
940 }
941 stream << ";" << endl;
942 } else {
943 stream << "1'b0;" << endl;
944 }
945
946 const int glockWidth = glockPortWidth();
947 stream << indentation(1) << "assign " << GLOCK_PORT_NAME << " = {"
948 << Conversion::toString(glockWidth) << "{"
950 << endl;
951 stream << endl << "endmodule" << endl;
952 }
953}
954
955/**
956 * Writes process that captures state of global lock per clock cycle.
957 *
958 * The captured contents are dumped into an output file.
959 *
960 * @param stream The stream to write.
961 */
962void
964 if (language_==VHDL){
965 stream << indentation(1)
966 << "-- Dump the status of global lock into a file once "
967 "in clock cycle"
968 << endl
969 << indentation(1)
970 << "-- setting DUMP false will disable dumping"
971 << endl << endl;
972
973 stream << indentation(1)
974 << "-- Do not synthesize this process!"
975 << endl
976 << indentation(1)
977 << "-- pragma synthesis_off"
978 << endl << endl;
979
980 stream << indentation(1)
981 << "file_output : process" << endl;
982 stream << indentation(2)
983 << "file fileout : text;" << endl << endl
984 << indentation(2)
985 << "variable lineout : line;" << endl
986 << indentation(2)
987 << "variable start : boolean := true;" << endl
988 << indentation(2)
989 << "variable count : integer := 0;" << endl
990 << indentation(2)
991 << "constant SEPARATOR : string := \" | \";" << endl
992 << indentation(2)
993 << "constant DUMP : boolean := true;" << endl
994 << indentation(2)
995 << "constant DUMPFILE : string := \"lock.dump\";" << endl;
996
997 stream << indentation(1)
998 << "begin" << endl;
999
1000 stream << indentation(2)
1001 << "if DUMP = true then" << endl;
1002
1003 stream << indentation(3)
1004 << "if start = true then" << endl;
1005
1006 stream << indentation(4)
1007 << "file_open(fileout, DUMPFILE, write_mode);" << endl
1008 << indentation(4)
1009 << "start := false;" << endl;
1010
1011 stream << indentation(3)
1012 << "end if;" << endl;
1013
1014 stream << indentation(3)
1015 << "wait on clk until clk = '1' and clk'last_value = '0';"
1016 << endl;
1017
1018 stream << indentation(3)
1019 << "if count > " << (lockTraceStartingCycle_ - 1)
1020 << " then" << endl;
1021
1022 stream << indentation(4) << "write(lineout, count-"
1023 << lockTraceStartingCycle_ << ", right, 12);" << endl
1024 << indentation(4) << "write(lineout, SEPARATOR);" << endl
1025 << indentation(4)
1026 << "write(lineout, conv_integer(unsigned'(\"\" & "
1027 << POST_DECODE_MERGED_GLOCK_SIGNAL << ")), right, 12);" << endl
1028 << indentation(4) << "write(lineout, SEPARATOR);" << endl
1029 << indentation(4) << "writeline(fileout, lineout);" << endl;
1030
1031 stream << indentation(3)
1032 << "end if;" << endl;
1033 stream << indentation(3)
1034 << "count := count + 1;" << endl;
1035
1036 stream << indentation(2)
1037 << "end if;" << endl;
1038
1039 stream << indentation(1)
1040 << "end process file_output;" << endl;
1041
1042 stream << indentation(1)
1043 << "-- pragma synthesis_on"
1044 << endl;
1045
1046 } else { // language_==Verilog
1047 stream << indentation(1)
1048 << "// Dump the status of global lock into a file once "
1049 << "in clock cycle"
1050 << endl
1051 << indentation(1)
1052 << "// setting DUMP false will disable dumping"
1053 << endl << endl
1054 << indentation(1) << "// Do not synthesize!" << endl
1055 << indentation(1) << "//synthesis translate_off" << endl
1056 << indentation(1) << "integer fileout;" << endl << endl
1057 << indentation(1) << "integer count=0;" << endl << endl
1058 << indentation(1) << "`define DUMPFILE \"lock.dump\""
1059 << endl << endl
1060
1061 << indentation(1) << "initial" << endl
1062 << indentation(1) << "begin" << endl
1063 << indentation(2) << "fileout = $fopen(`DUMPFILE,\"w\");"
1064 << endl
1065 << indentation(2) << "$fclose(fileout);" << endl
1066 << indentation(2) << "forever" << endl
1067 << indentation(2) << "begin" << endl
1068 << indentation(3) << "#PERIOD;" << endl
1069 << indentation(3) << "if ( count > "
1070 << (lockTraceStartingCycle_ - 1) << ")" << endl;
1071
1072 stream << indentation(3) << "begin" << endl
1073 << indentation(4) << "fileout = $fopen(`DUMPFILE,\"a\");"
1074 << endl
1075 << indentation(4) << "$fwrite(fileout," << "\""
1076 << " %11d | %11d | \\n\"" << ", count - "
1077 << lockTraceStartingCycle_ << ", "
1079 << endl
1080 << indentation(4) << "$fclose(fileout);" << endl
1081 << indentation(3) << "end" << endl
1082 << indentation(3) << "count = count + 1;" << endl
1083 << indentation(2) << "end" << endl
1084 << indentation(1) << "end" << endl
1085 << indentation(1) << "//synthesis translate_on" << endl;
1086 }
1087}
1088
1089/**
1090 * Writes the signals for source, destination and guard fields to the
1091 * given stream.
1092 *
1093 * @param stream The stream.
1094 */
1095void
1098 stream, 1, "signals for source, destination and guard fields");
1099
1100 for (int i = 0; i < bem_.moveSlotCount(); i++) {
1101 MoveSlot& slot = bem_.moveSlot(i);
1102 if (slot.width() > 0) {
1104 stream, ProGe::BIT_VECTOR, moveFieldSignal(slot.name()),
1105 slot.width());
1106 }
1107 if (slot.hasSourceField() && slot.sourceField().width() != 0) {
1108 SourceField& srcField = slot.sourceField();
1110 stream, ProGe::BIT_VECTOR, srcFieldSignal(slot.name()),
1111 srcField.width());
1112 }
1113 if (slot.hasDestinationField() &&
1114 slot.destinationField().width() != 0) {
1115 DestinationField& dstField = slot.destinationField();
1117 stream, ProGe::BIT_VECTOR, dstFieldSignal(slot.name()),
1118 dstField.width());
1119 }
1120 if (slot.hasGuardField()) {
1121 GuardField& grdField = slot.guardField();
1123 stream, ProGe::BIT_VECTOR, guardFieldSignal(slot.name()),
1124 grdField.width());
1125 }
1126 }
1127}
1128
1129/**
1130 * Writes the signals for dedicated immediate slots to the given stream.
1131 *
1132 * @param stream The stream.
1133 */
1134void
1136 std::ostream& stream) const {
1137 writeComment(stream, 1, "signals for dedicated immediate slots");
1138 for (int i = 0; i < bem_.immediateSlotCount(); i++) {
1141 stream, ProGe::BIT_VECTOR, immSlotSignal(slot.name()),
1142 slot.width());
1143 }
1144}
1145
1146/**
1147 * Writes the signal for long immediate tag to the given stream.
1148 *
1149 * @param stream The stream.
1150 */
1151void
1153 std::ostream& stream) const {
1155 writeComment(stream, 1, "signal for long immediate tag");
1156
1160 }
1161}
1162
1163/**
1164 * Writes the squash signals of guards to the given stream.
1165 *
1166 * @param stream The stream.
1167 */
1168void
1170 std::ostream& stream) const {
1171
1172 TCEString comment = language_ == VHDL ? "-- " : "// ";
1174 stream << indentation(1) << comment << "squash signals" << endl;
1175 for (int i = 0; i < busNav.count(); i++) {
1176 Bus* bus = busNav.item(i);
1177 stream << indentation(1);
1178 if (language_ == VHDL) {
1179 stream << "signal " << squashSignal(bus->name())
1180 << " : std_logic;" << endl;
1181 } else {
1182 assert(bem_.hasMoveSlot(bus->name()));
1183 MoveSlot& slot = bem_.moveSlot(bus->name());
1184 if (slot.hasGuardField()) {
1185 stream << "reg ";
1186 } else {
1187 // Declare guard signal as wire for constant assignment
1188 stream << "wire ";
1189 }
1190 stream << squashSignal(bus->name()) << ";" << endl;
1191 }
1192 }
1193}
1194
1195
1196/**
1197 * Writes the socket control signals to the given stream.
1198 *
1199 * @param stream The stream to write.
1200 */
1201void
1203 writeComment(stream, 1, "socket control signals");
1204
1206 for (int i = 0; i < socketNav.count(); i++) {
1207 Socket* socket = socketNav.item(i);
1208 if (socket->portCount() == 0 || socket->segmentCount() == 0) {
1209 continue;
1210 }
1211
1212 if (needsBusControl(*socket)) {
1213 std::string sigName = socketBusCntrlSignalName(socket->name());
1215 stream, ProGe::BIT_VECTOR, sigName, busControlWidth(*socket));
1216 registerVectors.push_back(sigName);
1217 }
1218 if (needsDataControl(*socket)) {
1219 std::string sigName = socketDataCntrlSignalName(socket->name());
1221 stream, ProGe::BIT_VECTOR, sigName,
1222 dataControlWidth(*socket));
1223 registerVectors.push_back(sigName);
1224 }
1225 }
1226
1227 // write signals for short immediate sockets (not visible in ADF)
1229 for (int i = 0; i < busNav.count(); i++) {
1230 Bus* bus = busNav.item(i);
1231 if (bus->immediateWidth() > 0) {
1233 stream, ProGe::BIT_VECTOR, simmDataSignalName(bus->name()),
1234 simmPortWidth(*bus));
1235 registerVectors.push_back(simmDataSignalName(bus->name()));
1238 1);
1239 registerVectors.push_back(simmCntrlSignalName(bus->name()));
1240 }
1241
1242 if (generateBusEnable_) {
1244 stream, ProGe::BIT, busMuxEnableRegister(*bus), 1);
1245 registerBits.push_back(busMuxEnableRegister(*bus));
1246 }
1247 }
1248}
1249
1250/**
1251 * Writes the FU control signals to the given stream.
1252 *
1253 * @param stream The stream.
1254 */
1255void
1257 writeComment(stream, 1, "FU control signals");
1258
1260 functionUnitNavigator();
1261 for (int i = 0; i < fuNav.count(); i++) {
1262 FunctionUnit* fu = fuNav.item(i);
1263 writeFUCntrlSignals(*fu, stream);
1264 }
1265
1266 if (machine_.controlUnit() != NULL) {
1268 writeFUCntrlSignals(*gcu, stream);
1269 }
1270}
1271
1272/**
1273 * Writes the control signals of the given FU to the given stream.
1274 *
1275 * @param fu The FU.
1276 * @param stream The stream to write.
1277 */
1278void
1280 const TTAMachine::FunctionUnit& fu, std::ostream& stream) {
1281 for (int i = 0; i < fu.portCount(); i++) {
1282 BaseFUPort* port = fu.port(i);
1283
1284 if (port->inputSocket() != NULL) {
1285 // if input port
1286 std::string sigName = fuLoadSignalName(fu.name(), port->name());
1287 writeSignalDeclaration(stream, ProGe::BIT, sigName, 1);
1288 registerBits.push_back(sigName);
1289 }
1290 }
1291
1292 // write opcode signal if the FU needs opcode
1293 int opcWidth = opcodeWidth(fu);
1294 if (opcWidth > 0) {
1295 std::string sigName = fuOpcodeSignalName(fu.name());
1296 writeSignalDeclaration(stream, ProGe::BIT_VECTOR, sigName, opcWidth);
1297 registerVectors.push_back(sigName);
1298 }
1299}
1300
1301/**
1302 * Writes the RF control signals to the given stream.
1303 *
1304 * @param stream The stream.
1305 */
1306void
1308 writeComment(stream, 1, "RF control signals");
1309
1311 registerFileNavigator();
1312 for (int i = 0; i < rfNav.count(); i++) {
1313 RegisterFile* rf = rfNav.item(i);
1314
1315 for (int i = 0; i < rf->portCount(); i++) {
1316 RFPort* port = rf->port(i);
1317 bool async_signal = sacEnabled(rf->name())
1318 && port->outputSocket() != NULL;
1319
1320 // load signal
1321 std::string sigName =
1322 rfLoadSignalName(rf->name(), port->name(), async_signal);
1323 writeSignalDeclaration(stream, ProGe::BIT, sigName, 1);
1324 if (!async_signal) registerBits.push_back(sigName);
1325
1326 // opcode signal
1327 if (0 < rfOpcodeWidth(*rf)) {
1328 std::string sigName = rfOpcodeSignalName(
1329 rf->name(), port->name(), async_signal);
1331 stream, ProGe::BIT_VECTOR, sigName, rfOpcodeWidth(*rf));
1332
1333 if (!async_signal) registerVectors.push_back(sigName);
1334 }
1335 }
1336 }
1337
1339 for (int i = 0; i < iuNav.count(); i++) {
1340 ImmediateUnit* iu = iuNav.item(i);
1341 for (int i = 0; i < iu->portCount(); i++) {
1342 RFPort* port = iu->port(i);
1343 if (port->isOutput()) {
1344 if (language_ == VHDL) {
1345 registerBits.push_back(
1346 iuReadLoadCntrlPort(iu->name(), port->name()));
1347 if (0 < rfOpcodeWidth(*iu)) {
1348 registerVectors.push_back(
1349 iuReadOpcodeCntrlPort(iu->name(), port->name()));
1350 }
1351 } else {
1352 std::string sigName =
1353 iuReadLoadCntrlSignal(iu->name(), port->name());
1354 writeSignalDeclaration(stream, ProGe::BIT, sigName, 1);
1355 registerBits.push_back(sigName);
1356
1357 if (0 < rfOpcodeWidth(*iu)) {
1358 sigName =
1359 iuReadOpcodeCntrlSignal(iu->name(), port->name());
1361 stream, ProGe::BIT_VECTOR, sigName,
1362 rfOpcodeWidth(*iu));
1363 registerVectors.push_back(sigName);
1364 }
1365 }
1366 }
1367 }
1368 if (language_ == Verilog) {
1369 stream << indentation(1) << "reg[" << iu->width()-1 << ":0] "
1370 << iuWriteSignal(iu->name())
1371 << ";" << endl;
1372 stream << indentation(1) << "reg "
1374 << ";" << endl;
1375 if (0 < rfOpcodeWidth(*iu)) {
1376 stream << indentation(1) << "reg["
1377 << rfOpcodeWidth(*iu) - 1 << ":0] "
1379 << ";" << endl;
1380 }
1381 }
1382 }
1383}
1384
1385void
1398
1399/**
1400 * Writes signals used in decode pipeline fill process.
1401 */
1402void
1407
1408/**
1409 * Writes dismembering of instruction word to signals to the given stream.
1410 *
1411 * @param stream The stream.
1412 */
1413void
1415 std::ostream& stream) const {
1416 std::string instructionPort = NetlistGenerator::DECODER_INSTR_WORD_PORT;
1417
1418 if (language_ == VHDL) {
1419 stream << indentation(1) << "-- dismembering of instruction" << endl;
1420 stream << indentation(1) << "process (" << instructionPort << ")"
1421 << endl;
1422 stream << indentation(1) << "begin --process" << endl;
1423
1424 for (int i = 0; i < bem_.moveSlotCount(); i++) {
1425 MoveSlot& slot = bem_.moveSlot(i);
1426 int slotPosition = slot.bitPosition();
1427
1428 if (slot.width() > 0) {
1429 stream << indentation(2) << moveFieldSignal(slot.name())
1430 << " <= " << instructionPort << "("
1431 << slotPosition + slot.width() << "-1 downto "
1432 << slotPosition << ");" << endl;
1433 }
1434 if (slot.hasSourceField() && slot.sourceField().width() != 0) {
1435 SourceField& srcField = slot.sourceField();
1436 stream << indentation(2) << srcFieldSignal(slot.name())
1437 << " <= " << instructionPort << "("
1438 << slotPosition + srcField.bitPosition() +
1439 srcField.width() - 1
1440 << " downto " << slotPosition + srcField.bitPosition()
1441 << ");" << endl;
1442 }
1443 if (slot.hasDestinationField() &&
1444 slot.destinationField().width() != 0) {
1445 DestinationField& dstField = slot.destinationField();
1446 stream << indentation(2) << dstFieldSignal(slot.name())
1447 << " <= " << instructionPort << "("
1448 << slotPosition + dstField.bitPosition() +
1449 dstField.width() - 1
1450 << " downto " << slotPosition + dstField.bitPosition()
1451 << ");" << endl;
1452 }
1453 if (slot.hasGuardField()) {
1454 GuardField& grdField = slot.guardField();
1455 stream << indentation(2) << guardFieldSignal(slot.name())
1456 << " <= " << instructionPort << "("
1457 << slotPosition + grdField.bitPosition() +
1458 grdField.width() - 1
1459 << " downto " << slotPosition + grdField.bitPosition()
1460 << ");" << endl;
1461 }
1462 }
1463 stream << endl;
1464 for (int i = 0; i < bem_.immediateSlotCount(); i++) {
1466 stream << indentation(2) << immSlotSignal(slot.name())
1467 << " <= " << instructionPort << "("
1468 << slot.bitPosition() + slot.width() - 1 << " downto "
1469 << slot.bitPosition() << ");" << endl;
1470 }
1473 stream << indentation(2) << LIMM_TAG_SIGNAL
1474 << " <= " << instructionPort << "("
1475 << icField.bitPosition() + icField.width() - 1
1476 << " downto " << icField.bitPosition() << ");" << endl;
1477 }
1478 stream << indentation(1) << "end process;" << endl;
1479 } else { // language == Verilog
1480 stream << indentation(1) << "// dismembering of instruction" << endl;
1481 stream << indentation(1) << "always@(*)" << endl;
1482 stream << indentation(1) << "begin //process" << endl;
1483
1484 for (int i = 0; i < bem_.moveSlotCount(); i++) {
1485 MoveSlot& slot = bem_.moveSlot(i);
1486 int slotPosition = slot.bitPosition();
1487
1488 if (slot.width() > 0) {
1489 stream << indentation(2) << moveFieldSignal(slot.name())
1490 << " = " << instructionPort << "["
1491 << slotPosition + slot.width() - 1 << " : "
1492 << slotPosition << "];" << endl;
1493 }
1494 if (slot.hasSourceField() && slot.sourceField().width() != 0) {
1495 SourceField& srcField = slot.sourceField();
1496 stream << indentation(2) << srcFieldSignal(slot.name())
1497 << " = " << instructionPort << "["
1498 << slotPosition + srcField.bitPosition() +
1499 srcField.width() - 1
1500 << " : " << slotPosition + srcField.bitPosition()
1501 << "];" << endl;
1502 }
1503 if (slot.hasDestinationField() &&
1504 slot.destinationField().width() != 0) {
1505 DestinationField& dstField = slot.destinationField();
1506 stream << indentation(2) << dstFieldSignal(slot.name())
1507 << " = " << instructionPort << "["
1508 << slotPosition + dstField.bitPosition() +
1509 dstField.width() - 1
1510 << " : " << slotPosition + dstField.bitPosition()
1511 << "];" << endl;
1512 }
1513 if (slot.hasGuardField()) {
1514 GuardField& grdField = slot.guardField();
1515 stream << indentation(2) << guardFieldSignal(slot.name())
1516 << " = " << instructionPort << "["
1517 << slotPosition + grdField.bitPosition() +
1518 grdField.width() - 1
1519 << " : " << slotPosition + grdField.bitPosition()
1520 << "];" << endl;
1521 }
1522 }
1523 stream << endl;
1524 for (int i = 0; i < bem_.immediateSlotCount(); i++) {
1526 stream << indentation(2) << immSlotSignal(slot.name()) << " = "
1527 << instructionPort << "["
1528 << slot.bitPosition() + slot.width() - 1 << " : "
1529 << slot.bitPosition() << "];" << endl;
1530 }
1533 stream << indentation(2) << LIMM_TAG_SIGNAL << " = "
1534 << instructionPort << "["
1535 << icField.bitPosition() + icField.width() - 1 << " : "
1536 << icField.bitPosition() << "];" << endl;
1537 }
1538 stream << indentation(1) << "end" << endl;
1539 }
1540}
1541
1542/**
1543 * Writes the generation processes of squash signals to the given stream.
1544 *
1545 * @param stream The stream.
1546 */
1547void
1549 std::ostream& stream) const {
1550
1552 for (int i = 0; i < busNav.count(); i++) {
1553 Bus* bus = busNav.item(i);
1555 }
1556}
1557
1558
1559/**
1560 * Writes the generation process of squash signal for the given bus.
1561 *
1562 * @param bus The bus.
1563 * @param stream The stream to write.
1564 */
1565void
1567 const TTAMachine::Bus& bus,
1568 std::ostream& stream) const {
1569 if(language_==VHDL){
1570 assert(bem_.hasMoveSlot(bus.name()));
1571 MoveSlot& slot = bem_.moveSlot(bus.name());
1572 GuardField* grdField = nullptr;
1573 std::set<InstructionTemplate*> affectingInstTemplates =
1575 bool ifClauseStarted = false;
1576
1577 if (!slot.hasGuardField() && affectingInstTemplates.size() == 0) {
1578 // the bus contains always true guard so squash has static value
1579 // Synthesis software should optimize it away
1580 string squashName = squashSignal(bus.name());
1581 stream << indentation(1) << "-- generate signal " << squashName
1582 << endl;
1583 stream << indentation(1) << squashName << " <= '0';" << endl;
1584 return;
1585 }
1586
1587 std::set<string> sensitivyList;
1588 for (int i = 0; i < bus.guardCount(); i++) {
1589 sensitivyList.insert(guardPortName(*bus.guard(i)));
1590 }
1591 if (slot.hasGuardField()) {
1592 sensitivyList.insert(guardFieldSignal(slot.name()));
1593 grdField = &slot.guardField();
1594 }
1595
1596 if (affectingInstTemplates.size() > 0) {
1597 sensitivyList.insert(LIMM_TAG_SIGNAL);
1598 }
1599
1600 stream << indentation(1) << "-- generate signal "
1601 << squashSignal(slot.name()) << endl;
1602 stream << indentation(1) << "process (";
1603 string listStr;
1604 for (const string& signal : sensitivyList) {
1605 TCEString::appendToNonEmpty(listStr, ", ");
1606 listStr += signal;
1607 }
1608 assert(!listStr.empty());
1609 stream << listStr << ")" << endl;
1610 if (slot.hasGuardField()) {
1611 stream << indentation(2) << "variable sel : integer;" << endl;
1612 }
1613 stream << indentation(1) << "begin --process" << endl;
1614 int indLevel = 2;
1615 if (affectingInstTemplates.size() > 0) {
1616 ifClauseStarted = true;
1617 stream << indentation(indLevel) << "if (";
1618 for (set<InstructionTemplate*>::const_iterator iter =
1619 affectingInstTemplates.begin();
1620 iter != affectingInstTemplates.end(); iter++) {
1621 if (iter != affectingInstTemplates.begin()) {
1622 stream << " or " << endl
1623 << indentation(indLevel) << " ";
1624 }
1626 InstructionTemplate* affectingTemp = *iter;
1627 stream << "conv_integer(unsigned(" << LIMM_TAG_SIGNAL
1628 << ")) = "
1629 << icField.templateEncoding(affectingTemp->name());
1630 stream << ") then" << endl;
1631 stream << indentation(indLevel+1) << squashSignal(bus.name())
1632 << " <= '1';" << endl;
1633 }
1634 }
1635
1636 if (ifClauseStarted) {
1637 stream << indentation(indLevel) << "else" << endl;
1638 indLevel += 1;
1639 }
1640 if (grdField != nullptr) {
1641 stream << indentation(indLevel) << "sel := conv_integer(unsigned("
1642 << guardFieldSignal(slot.name()) << "));" << endl;
1643 stream << indentation(indLevel) << "case sel is" << endl;
1644 indLevel++;
1645 for (int i = 0; i < grdField->gprGuardEncodingCount(); i++) {
1646 GPRGuardEncoding& enc = grdField->gprGuardEncoding(i);
1647 RegisterGuard& regGuard = findGuard(enc);
1649 bus, enc, regGuard, stream, indLevel);
1650 }
1651
1652 for (int i = 0; i < grdField->fuGuardEncodingCount(); i++) {
1653 FUGuardEncoding& enc = grdField->fuGuardEncoding(i);
1654 PortGuard& portGuard = findGuard(enc);
1656 bus, enc, portGuard, stream, indLevel);
1657 }
1658
1659 if (grdField->hasUnconditionalGuardEncoding(true)) {
1661 grdField->unconditionalGuardEncoding(true);
1662 stream << indentation(indLevel) << "when " << enc.encoding()
1663 << " => " << endl;
1664 stream << indentation(indLevel + 1)
1665 << squashSignal(slot.name()) << " <= '1';" << endl;
1666 }
1667
1668 stream << indentation(indLevel) << "when others =>" << endl;
1669 stream << indentation(indLevel + 1) << squashSignal(slot.name())
1670 << " <= '0';" << endl;
1671 stream << indentation(indLevel-1) << "end case;" << endl;
1672 } else {
1673 stream << indentation(indLevel) << squashSignal(slot.name())
1674 << " <= '0';" << endl;
1675 }
1676
1677 if (ifClauseStarted) {
1678 ifClauseStarted = false;
1679 stream << indentation(2) << "end if;" << endl;
1680 indLevel -= 1;
1681 assert(indLevel >= 0);
1682 }
1683 stream << indentation(1) << "end process;" << endl << endl;
1684 } else { // language == Verilog
1685 std::set<InstructionTemplate*> affectingInstTemplates =
1687 bool ifClauseStarted = false;
1688
1689 assert(bem_.hasMoveSlot(bus.name()));
1690 MoveSlot& slot = bem_.moveSlot(bus.name());
1691 if (slot.hasGuardField() || affectingInstTemplates.size() > 0) {
1692 GuardField& grdField = slot.guardField();
1693
1694 std::set<string> sensitivyList;
1695 for (int i = 0; i < bus.guardCount(); i++) {
1696 sensitivyList.insert(guardPortName(*bus.guard(i)));
1697 }
1698 if (slot.hasGuardField()) {
1699 sensitivyList.insert(guardFieldSignal(slot.name()));
1700 }
1701
1702 if (affectingInstTemplates.size() > 0) {
1703 sensitivyList.insert(LIMM_TAG_SIGNAL);
1704 }
1705
1706 stream << indentation(1) << "// generate signal "
1707 << squashSignal(slot.name()) << endl;
1708 stream << indentation(1) << "always@(";
1709 string listStr;
1710 for (const string& signal : sensitivyList) {
1711 TCEString::appendToNonEmpty(listStr, ", ");
1712 listStr += signal;
1713 }
1714 assert(!listStr.empty());
1715 stream << listStr << ")" << endl;
1716 stream << indentation(1) << "begin" << endl;
1717 int indLevel = 2;
1718
1719 if (affectingInstTemplates.size() > 0) {
1720 ifClauseStarted = true;
1721 stream << indentation(indLevel) << "if (";
1722 for (set<InstructionTemplate*>::const_iterator iter =
1723 affectingInstTemplates.begin();
1724 iter != affectingInstTemplates.end(); iter++) {
1725 if (iter != affectingInstTemplates.begin()) {
1726 stream << " || ";
1727 }
1728 ImmediateControlField& icField =
1730 InstructionTemplate* affectingTemp = *iter;
1731 stream << LIMM_TAG_SIGNAL
1732 << " == "
1733 << icField.templateEncoding(affectingTemp->name());
1734 }
1735 stream << ")" << endl;
1736 stream << indentation(indLevel+1) << squashSignal(bus.name())
1737 << " <= 1'b1;" << endl;
1738 }
1739
1740 if (ifClauseStarted) {
1741 stream << indentation(indLevel) << "else" << endl;
1742 indLevel++;
1743 }
1744 if (slot.hasGuardField()) {
1745 stream << indentation(indLevel) << "case("
1746 << guardFieldSignal(slot.name()) << ")" << endl;
1747 indLevel++;
1748 for (int i = 0; i < grdField.gprGuardEncodingCount(); i++) {
1749 GPRGuardEncoding& enc = grdField.gprGuardEncoding(i);
1750 RegisterGuard& regGuard = findGuard(enc);
1752 Verilog, bus, enc, regGuard, stream, indLevel);
1753 }
1754
1755 for (int i = 0; i < grdField.fuGuardEncodingCount(); i++) {
1756 FUGuardEncoding& enc = grdField.fuGuardEncoding(i);
1757 PortGuard& portGuard = findGuard(enc);
1759 Verilog, bus, enc, portGuard, stream, indLevel);
1760 }
1761
1762 if (grdField.hasUnconditionalGuardEncoding(true)) {
1764 grdField.unconditionalGuardEncoding(true);
1765 stream << indentation(indLevel) << enc.encoding() << " :"
1766 << endl;
1767 stream << indentation(indLevel + 1)
1768 << squashSignal(slot.name()) << " <= 1'b1;"
1769 << endl;
1770 }
1771
1772 stream << indentation(indLevel) << "default:" << endl;
1773 stream << indentation(indLevel + 1)
1774 << squashSignal(slot.name()) << " <= 1'b0;" << endl;
1775 stream << indentation(indLevel - 1) << "endcase" << endl;
1776 } else {
1777 string squashName = squashSignal(bus.name());
1778 stream << indentation(indLevel) << squashName << " <= 1'b0;"
1779 << endl;
1780 }
1781 stream << indentation(1) << "end" << endl << endl;
1782 } else {
1783 // the bus contains always true guard so squash has static value
1784 // Synthesis software should optimize it away
1785 string squashName = squashSignal(bus.name());
1786 stream << indentation(1) << "// generate signal " << squashName
1787 << endl;
1788 stream << indentation(1) << "assign " << squashName
1789 << " = 1'b0;" << endl;
1790 }
1791 }
1792}
1793
1794
1795/**
1796 * Writes the process that writes long immediates to immediate units.
1797 *
1798 * @param stream The stream to write.
1799 */
1800void
1802 std::ostream& stream) const {
1803
1806 if (itNav.count() == 0 || (itNav.count() == 1 &&
1807 itNav.item(0)->isEmpty())) {
1808 return;
1809 }
1810
1811 string resetPort = NetlistGenerator::DECODER_RESET_PORT;
1812 string clockPort = NetlistGenerator::DECODER_CLOCK_PORT;
1813 // If bypass decoder registers, implement combinatorial process
1814 string listStr;
1815 if (language_ == VHDL) {
1816 int indentLevel = 1;
1817 stream << indentation(indentLevel) << "--long immediate write process"
1818 << endl;
1819 stream << indentation(indentLevel) << "process (";
1820 stream << clockPort;
1821 if (!syncReset_) {
1822 stream << ", " << resetPort;
1823 }
1824 stream << ")" << endl;
1825 stream << indentation(indentLevel) << "begin --process" << endl;
1826 // reset
1827 indentLevel += 1;
1828 if (syncReset_) {
1829 stream << indentation(indentLevel)
1830 << "if (clk'event and clk = '1') then" << endl;
1831 indentLevel += 1;
1832 }
1833 stream << indentation(indentLevel) << "if (" << resetPort
1834 << " = '0') then" << endl;
1835 indentLevel += 1;
1838
1839 for (int i = 0; i < iuNav.count(); i++) {
1840 ImmediateUnit* iu = iuNav.item(i);
1841 stream << indentation(indentLevel)
1842 << iuWriteLoadCntrlPort(iu->name()) << " <= '0';" << endl;
1843 stream << indentation(indentLevel) << iuWritePort(iu->name())
1844 << " <= (others => '0');" << endl;
1845 if (rfOpcodeWidth(*iu) != 0)
1846 stream << indentation(indentLevel)
1848 << " <= (others => '0');" << endl;
1849 }
1850 // else
1851 stream << indentation(indentLevel - 1) << "elsif ";
1852 if (!syncReset_) {
1853 stream << "(clk'event and clk = '1') then" << endl
1854 << indentation(indentLevel) << "if ";
1855 indentLevel += 1;
1856 }
1857 // global lock test
1858 stream << PRE_DECODE_MERGED_GLOCK_SIGNAL << " = '0' then" << endl;
1859 for (int i = 0; i < itNav.count(); i++) {
1860 InstructionTemplate* iTemp = itNav.item(i);
1862 if (i == 0) {
1863 stream << indentation(indentLevel) << "if ("
1865 VHDL, iTemp->name())
1866 << ") then" << endl;
1867 } else if (i+1 < itNav.count()) {
1868 stream << indentation(indentLevel) << "elsif ("
1870 VHDL, iTemp->name())
1871 << ") then" << endl;
1872 } else {
1873 stream << indentation(indentLevel) << "else" << endl;
1874 }
1875 }
1877 VHDL, *iTemp, indentLevel + 1, stream);
1878 }
1879
1881 stream << indentation(indentLevel) << "end if;" << endl;
1882 }
1883 // global lock test endif
1884 stream << indentation(3) << "end if;" << endl;
1885 // reset (async) or clk edge (sync) endif
1886 stream << indentation(2) << "end if;" << endl;
1887 stream << indentation(1) << "end process;" << endl;
1888 } else { // language_ == Verilog
1889 stream << indentation(1) << "//long immediate write process" << endl
1890 << indentation(1) << "always@(posedge "
1891 << clockPort << " or negedge " << resetPort << ")" << endl
1892 // reset
1893 << indentation(2) << "if (" << resetPort << " == 0)"
1894 << endl
1895 << indentation(2) << "begin" << endl;
1898
1899 for (int i = 0; i < iuNav.count(); i++) {
1900 ImmediateUnit* iu = iuNav.item(i);
1901 stream << indentation(3) << iuWriteLoadCntrlSignal(iu->name())
1902 << " <= 1'b0;" << endl
1903 << indentation(3) << iuWriteSignal(iu->name())
1904 << " <= 0;" << endl;
1905 if (rfOpcodeWidth(*iu) != 0)
1906 stream << indentation(3) << iuWriteOpcodeCntrlSignal(iu->name())
1907 << " <= 0;" << endl;
1908 }
1909 stream << indentation(2) << "end" << endl
1910 << indentation(2) << "else" << endl
1911 << indentation(2) << "begin" << endl
1912 << indentation(3) << "if ("
1914 << endl
1915 << indentation(3) << "begin" << endl;
1916 for (int i = 0; i < itNav.count(); i++) {
1917 InstructionTemplate* iTemp = itNav.item(i);
1918 int indLevel = 4;
1920 indLevel = 5;
1921 if (i == 0) {
1922 stream << indentation(4) << "if ("
1924 Verilog, iTemp->name())
1925 << ")" << endl;
1926 } else if (i+1 < itNav.count()) {
1927 stream << indentation(4) << "else if ("
1929 Verilog, iTemp->name())
1930 << ")" << endl;
1931 } else {
1932 stream << indentation(4) << "else" << endl;
1933 }
1934 }
1935 stream << indentation(4) << "begin" << endl;
1937 Verilog, *iTemp, indLevel, stream);
1938 stream << indentation(4) << "end" << endl;
1939 }
1940 stream << indentation(3) << "end" << endl
1941 << indentation(2) << "end" << endl;
1942 }
1943}
1944
1945
1946/**
1947 * Writes the procedures required if the instruction is of the given
1948 * instruction template.
1949 *
1950 * @param iTemp The instruction template.
1951 * @param indLevel The indentation level.
1952 * @param stream The stream to write.
1953 */
1954void
1956 const ProGe::HDL language,
1958 int indLevel,
1959 std::ostream& stream) const {
1960
1963 if (language == VHDL) {
1964 if (iTemp.slotCount() == 0) {
1965 for (int i = 0; i < iuNav.count(); i++) {
1966 ImmediateUnit* iu = iuNav.item(i);
1967 stream << indentation(indLevel)
1968 << iuWriteLoadCntrlPort(iu->name()) << " <= '0';"
1969 << endl;
1970
1971 stream << indentation(indLevel) << iuWritePort(iu->name())
1972 << "(" << (iu->width() - 1) << " downto 0"
1973 << ") <= tce_sxt(\"0\", " << iu->width() << ");"
1974 << endl;
1975 }
1976 } else {
1977 for (int i = 0; i < iuNav.count(); i++) {
1978 ImmediateUnit* iu = iuNav.item(i);
1979 if (iTemp.isOneOfDestinations(*iu)) {
1980 int msb = iu->width() - 1;
1981 int lsb = iTemp.supportedWidth(*iu) -
1982 iTemp.supportedWidth(iTemp.slotOfDestination(*iu, 0));
1983 for (int j = 0; j < iTemp.numberOfSlots(*iu); j++) {
1984 string slot = iTemp.slotOfDestination(*iu, j);
1985 if (j != 0) {
1986 msb = lsb-1;
1987 lsb = msb - iTemp.supportedWidth(slot) + 1;
1988 }
1989
1990 int immPartWidth = msb - lsb + 1;
1991 stream << indentation(indLevel)
1992 << iuWritePort(iu->name())
1993 << "(" << msb << " downto " << lsb << ") <= ";
1994 if (j == 0) {
1995 if (iu->extensionMode() == Machine::SIGN) {
1996 stream << "tce_sxt(";
1997 } else {
1998 stream << "tce_ext(";
1999 }
2000 }
2001
2002 if (machine_.busNavigator().hasItem(slot)) {
2003 MoveSlot& mSlot = bem_.moveSlot(slot);
2005 << "(" << mSlot.bitPosition() +
2006 iTemp.supportedWidth(slot) - 1
2007 << " downto " << mSlot.bitPosition() << ")";
2008 } else {
2009 ImmediateSlotField& iSlot =
2010 bem_.immediateSlot(slot);
2012 << "(" << iSlot.bitPosition() +
2013 iTemp.supportedWidth(slot) - 1
2014 << " downto " << iSlot.bitPosition() << ")";
2015 }
2016
2017 if (j == 0) {
2018 stream << ", " << immPartWidth << ");" << endl;
2019 } else {
2020 stream << ";" << endl;
2021 }
2022
2023 }
2024 if (iu->numberOfRegisters() > 1) {
2025 LImmDstRegisterField& field =
2027 iTemp.name(), iu->name());
2028 stream << indentation(indLevel)
2029 << iuWriteOpcodeCntrlPort(iu->name()) << " <= "
2030 << "tce_ext("
2032 << "("
2033 << field.bitPosition() + rfOpcodeWidth(*iu) - 1
2034 << " downto " << field.bitPosition() << "), "
2036 << "'length);" << endl;
2037 }
2038 stream << indentation(indLevel)
2039 << iuWriteLoadCntrlPort(iu->name()) << " <= '1';"
2040 << endl;
2041 } else {
2042 stream << indentation(indLevel)
2043 << iuWriteLoadCntrlPort(iu->name()) << " <= '0';"
2044 << endl;
2045 }
2046 }
2047 }
2048 } else { // language == Verilog
2049 if (iTemp.slotCount() == 0) {
2050 for (int i = 0; i < iuNav.count(); i++) {
2051 ImmediateUnit* iu = iuNav.item(i);
2052 stream << indentation(indLevel)
2054 << " <= 1'b0;" << endl;
2055
2056 stream << indentation(indLevel)
2057 << iuWriteSignal(iu->name())
2058 << "[" << (iu->width() - 1) << " : 0"
2059 << "] <= {" << iu->width() <<"{1'b0}};" << endl;
2060 }
2061 } else {
2062 for (int i = 0; i < iuNav.count(); i++) {
2063 ImmediateUnit* iu = iuNav.item(i);
2064 if (iTemp.isOneOfDestinations(*iu)) {
2065 int msb = iu->width() - 1;
2066 int lsb = iTemp.supportedWidth(*iu) -
2067 iTemp.supportedWidth(iTemp.slotOfDestination(*iu, 0));
2068 for (int j = 0; j < iTemp.numberOfSlots(*iu); j++) {
2069 string slot = iTemp.slotOfDestination(*iu, j);
2070 if (j != 0) {
2071 msb = lsb-1;
2072 lsb = msb - iTemp.supportedWidth(slot) + 1;
2073 }
2074
2075 stream << indentation(indLevel)
2076 << iuWriteSignal(iu->name())
2077 << "[" << msb << " : " << lsb << "] <= ";
2078 if (j == 0) {
2079 if (iu->extensionMode() == Machine::SIGN) {
2080 stream << "$signed(";
2081 } else {
2082 stream << "$unsigned(";
2083 }
2084 }
2085
2086 if (machine_.busNavigator().hasItem(slot)) {
2087 MoveSlot& mSlot = bem_.moveSlot(slot);
2089 << "[" << mSlot.bitPosition() +
2090 iTemp.supportedWidth(slot) - 1
2091 << " : " << mSlot.bitPosition() << "]";
2092 } else {
2093 ImmediateSlotField& iSlot =
2094 bem_.immediateSlot(slot);
2096 << "[" << iSlot.bitPosition() +
2097 iTemp.supportedWidth(slot) - 1
2098 << " : " << iSlot.bitPosition() << "]";
2099 }
2100
2101 if (j == 0) {
2102 stream << ");" << endl;
2103 } else {
2104 stream << ";" << endl;
2105 }
2106 }
2107 if (iu->numberOfRegisters() > 1) {
2108 LImmDstRegisterField& field =
2110 iTemp.name(), iu->name());
2111 stream << indentation(indLevel)
2113 << " <= " << "$unsigned("
2115 << "["
2116 << field.bitPosition() + rfOpcodeWidth(*iu) - 1
2117 << " : " << field.bitPosition() << "]);"
2118 << endl;
2119 }
2120 stream << indentation(indLevel)
2121 << iuWriteLoadCntrlSignal(iu->name()) << " <= 1'b1;"
2122 << endl;
2123 } else {
2124 stream << indentation(indLevel)
2125 << iuWriteLoadCntrlSignal(iu->name()) << " <= 1'b0;"
2126 << endl;
2127 }
2128 }
2129 }
2130 }
2131}
2132
2133/**
2134 * Writes separate combinational decoding process for SRAM register files.
2135 *
2136 * @param stream The stream to write.
2137 */
2138void
2140const {
2141
2142 set<const RegisterFile*> sramRFset;
2143 set<const RegisterFile*>::const_iterator sramrf_it;
2144
2145 // Write only when there is SRAM RFs.
2146 bool hasSramRFs = false;
2147 const Machine::RegisterFileNavigator& rfNav =
2149 for (int i = 0; i < rfNav.count(); i++) {
2150 if(sacEnabled(rfNav.item(i)->name())) {
2151 hasSramRFs = true;
2152 sramRFset.insert(rfNav.item(i));
2153 }
2154 }
2155
2156 if(!hasSramRFs) {
2157 return;
2158 }
2159
2160 if (language_ == VHDL) {
2161 string resetPort = NetlistGenerator::DECODER_RESET_PORT;
2162
2163 // Begin process //
2164 stream << indentation(1)
2165 << "-- separate SRAM RF read decoding process" << endl;
2166 stream << indentation(1) << "process (" << resetPort;
2167
2168 // Sensitivity list //
2169 BusSet connectedToSramRFs;
2170 for (sramrf_it = sramRFset.begin(); sramrf_it != sramRFset.end();
2171 sramrf_it++) {
2172 const RegisterFile& rf = **sramrf_it;
2173 assert(sacEnabled(rf.name()));
2174 for (int ip = 0; ip < rf.portCount(); ip++) {
2175 const RFPort& port = *rf.port(ip);
2176 if (port.outputSocket() != NULL) {
2177 BusSet tmp = connectedBuses(*port.outputSocket());
2178 connectedToSramRFs.insert(tmp.begin(), tmp.end());
2179 }
2180 }
2181 }
2182
2183 BusSet::const_iterator busSet_it;
2184 for (busSet_it = connectedToSramRFs.begin();
2185 busSet_it != connectedToSramRFs.end();
2186 busSet_it++) {
2187 string busName = (*busSet_it)->name();
2188 stream << ", " << srcFieldSignal(busName)
2189 << ", " << squashSignal(busName);
2190 }
2191 stream << ")" << endl;
2192 stream << indentation(1) << "begin" << endl;
2193
2194 // Signal resets //
2195 stream << indentation(2) << "if (" << resetPort << " = '0') then"
2196 << endl;
2197 for (sramrf_it = sramRFset.begin(); sramrf_it != sramRFset.end();
2198 sramrf_it++) {
2199 const RegisterFile& rf = **sramrf_it;
2200 assert(sacEnabled(rf.name()));
2201 for (int i = 0; i < rf.portCount(); i++) {
2202 const RFPort& port = *rf.port(i);
2203 if (port.outputSocket() == NULL) {
2204 continue;
2205 }
2206
2207 stream << indentation(3)
2208 << rfLoadSignalName(rf.name(), port.name(), true)
2209 << " <= '0';" << endl;
2210 if (0 < rfOpcodeWidth(rf)) {
2211 stream << indentation(3)
2212 << rfOpcodeSignalName(rf.name(), port.name(), true)
2213 << " <= (others => '0');" << endl;
2214 }
2215 }
2216 }
2217
2218 // Write decoding rules //
2219 stream << endl << indentation(2) << "else" << endl;
2220 for (sramrf_it = sramRFset.begin(); sramrf_it != sramRFset.end();
2221 sramrf_it++) {
2222 const RegisterFile& rf = **sramrf_it;
2223 assert(sacEnabled(rf.name()));
2224 for(int i = 0; i < rf.portCount(); i++) {
2225 const RFPort& port = *rf.port(i);
2226 if (port.outputSocket() != NULL) {
2227 writeControlRulesOfRFReadPort(port, stream);
2228 }
2229 }
2230 }
2231 stream << indentation(2) << "end if;" << endl;
2232
2233 // End process //
2234 stream << indentation(1) << "end process;" << endl;
2235
2236 } else { // language_ == VERILOG
2237 // Begin process //
2238 string resetPort = NetlistGenerator::DECODER_RESET_PORT;
2239
2240 stream << indentation(1)
2241 << "// separate SRAM RF read decoding process" << endl;
2242 stream << indentation(1) << "always@(" << resetPort;
2243
2244 // Sensitivity list //
2245 BusSet connectedToSramRFs;
2246 for (sramrf_it = sramRFset.begin(); sramrf_it != sramRFset.end();
2247 sramrf_it++) {
2248 const RegisterFile& rf = **sramrf_it;
2249 assert(sacEnabled(rf.name()));
2250 for (int ip = 0; ip < rf.portCount(); ip++) {
2251 const RFPort& port = *rf.port(ip);
2252 if (port.outputSocket() != NULL) {
2253 BusSet tmp = connectedBuses(*port.outputSocket());
2254 connectedToSramRFs.insert(tmp.begin(), tmp.end());
2255 }
2256 }
2257 }
2258
2259 BusSet::const_iterator busSet_it;
2260 for (busSet_it = connectedToSramRFs.begin();
2261 busSet_it != connectedToSramRFs.end();
2262 busSet_it++) {
2263 string busName = (*busSet_it)->name();
2264 stream << ", " << srcFieldSignal(busName)
2265 << ", " << squashSignal(busName);
2266 }
2267 stream << ")" << endl;
2268 stream << indentation(1) << "begin" << endl;
2269
2270 // Signal resets //
2271 stream << indentation(2) << "if (" << resetPort << " == 0)" << endl
2272 << indentation(2) << "begin" << endl;
2273
2274 for (sramrf_it = sramRFset.begin(); sramrf_it != sramRFset.end();
2275 sramrf_it++) {
2276 const RegisterFile& rf = **sramrf_it;
2277 assert(sacEnabled(rf.name()));
2278 for (int i = 0; i < rf.portCount(); i++) {
2279 const RFPort& port = *rf.port(i);
2280 if (port.outputSocket() == NULL) {
2281 continue;
2282 }
2283
2284 stream << indentation(3)
2285 << rfLoadSignalName(rf.name(), port.name(), true)
2286 << " <= 1'b0;" << endl;
2287 if (0 < rfOpcodeWidth(rf)) {
2288 stream << indentation(3)
2289 << rfOpcodeSignalName(rf.name(), port.name(), true)
2290 << " <= 0;" << endl;
2291 }
2292 }
2293 }
2294 stream << indentation(2) << "end" << endl;
2295
2296 // Decoding rules //
2297 stream << indentation(2) << "else" << endl;
2298 stream << indentation(2) << "begin" << endl;
2299 for (sramrf_it = sramRFset.begin(); sramrf_it != sramRFset.end();
2300 sramrf_it++) {
2301 const RegisterFile& rf = **sramrf_it;
2302 assert(sacEnabled(rf.name()));
2303 for(int i = 0; i < rf.portCount(); i++) {
2304 const RFPort& port = *rf.port(i);
2305 if (port.outputSocket() != NULL) {
2306 writeControlRulesOfRFReadPort(port, stream);
2307 }
2308 }
2309 }
2310 stream << indentation(2) << "end" << endl;
2311
2312 // End process //
2313 stream << indentation(1) << "end // process" << endl;
2314 }
2315}
2316
2317/**
2318 * Writes the main decoding process to the given stream.
2319 *
2320 * @param stream The stream to write.
2321 */
2322void
2324 std::ostream& stream) const {
2325 if(language_==VHDL){
2326 string resetPort = NetlistGenerator::DECODER_RESET_PORT;
2327 string clockPort = NetlistGenerator::DECODER_CLOCK_PORT;
2328
2329 stream << indentation(1) << "-- main decoding process" << endl;
2330 string listStr;
2331 stream << indentation(1) << "process (";
2332 stream << clockPort;
2333 if (!syncReset_) {
2334 stream << ", " << resetPort;
2335 }
2336 stream << ")" << endl;
2337 stream << indentation(1) << "begin" << endl;
2338
2339 // if reset is active
2340 if (syncReset_) {
2341 stream << indentation(2) << "if (clk'event and clk = '1') then"
2342 << endl
2343 << indentation(2) << "if (" << resetPort << " = '0') then"
2344 << endl;
2346 stream << endl << indentation(2) << "else" << endl;
2347 } else {
2348 stream << indentation(2) << "if (" << resetPort << " = '0') then"
2349 << endl;
2351 stream << endl
2352 << indentation(2)
2353 << "elsif (clk'event and clk = '1') then "
2354 << "-- rising clock edge" << endl;
2355 }
2356 if (generateDebugger_) {
2357 string softResetPort = "db_tta_nreset";
2358 stream << indentation(3) << "if (" << softResetPort
2359 << " = '0') then"
2360 << endl;
2362 stream << indentation(3) << "elsif ("
2363 << PRE_DECODE_MERGED_GLOCK_SIGNAL << " = '0') then" << endl
2364 << endl;
2365 } else {
2366 stream << indentation(2) << "if ("
2368 stream << " = '0')";
2369 stream << " then" << endl << endl;
2370 }
2371
2373 stream << indentation(3) << "end if;" << endl;
2374 stream << indentation(2) << "end if;" << endl;
2375 stream << indentation(1) << "end process;" << endl;
2376 } else {
2377 string resetPort = NetlistGenerator::DECODER_RESET_PORT;
2378 string clockPort = NetlistGenerator::DECODER_CLOCK_PORT;
2379
2380 stream << indentation(1) << "// main decoding process" << endl
2381 << indentation(1) << "always@(posedge " << clockPort
2382 << " or negedge " << resetPort << ")" << endl
2383 // if reset is active
2384 << indentation(2) << "if (" << resetPort << " == 0)" << endl
2385 << indentation(2) <<"begin" << endl;
2387 stream << indentation(2) << "end" << endl
2388 << indentation(2) << "else" << endl
2389 << indentation(3) << "begin"<< endl
2390 << indentation(3) << "if ("
2392 << " == 0)" << endl << endl
2393 << indentation(3) << "begin"<< endl;
2395 stream << indentation(3) << "end" << endl
2396 << indentation(2) << "end" << endl;
2397 }
2398}
2399
2400/**
2401 * Generates global lock and lock request wiring.
2402 */
2403void
2405 assert(
2406 language_ == VHDL &&
2407 "writeGlockMapping() is not yet implemented "
2408 "for other HDLs.");
2409
2410 // Generate output register for core lock status signal //
2411 string propagateGlock(
2413 " <= " + POST_DECODE_MERGED_GLOCK_SIGNAL + ";");
2414 string assertGlock(POST_DECODE_MERGED_GLOCK_OUTREG + " <= '1'" + ";");
2415 if (syncReset_) {
2416 stream << " lock_reg_proc : process (clk)\n"
2417 << " begin\n"
2418 << " if (clk'event and clk = '1') then\n"
2419 << " if (rstx = '0') then\n"
2420 << " -- Locked during active reset\n"
2421 << " " << assertGlock << "\n"
2422 << " else\n"
2423 << " " << propagateGlock << "\n"
2424 << " end if;\n"
2425 << " end if;\n"
2426 << " end process lock_reg_proc;\n\n";
2427 } else {
2428 stream << " lock_reg_proc : process (clk, rstx)\n"
2429 << " begin\n"
2430 << " if (rstx = '0') then\n"
2431 << " -- Locked during active reset\n"
2432 << " " << assertGlock << "\n"
2433 << " elsif (clk'event and clk = '1') then\n"
2434 << " " << propagateGlock << "\n"
2435 << " end if;\n"
2436 << " end process lock_reg_proc;\n\n";
2437 }
2438
2439 // Generate global lock request wiring //
2440 int lockReqWidth = glockRequestWidth();
2442 << " <= " << INTERNAL_MERGED_GLOCK_REQ_SIGNAL << ";" << endl;
2443 stream << indentation(1) << INTERNAL_MERGED_GLOCK_REQ_SIGNAL << " <= ";
2444 if (lockReqWidth > 0) {
2445 for (int i = 0; i < lockReqWidth; i++) {
2446 stream << LOCK_REQ_PORT_NAME << "(" << i << ")";
2447 if (i + 1 < lockReqWidth) {
2448 stream << " or ";
2449 }
2450 }
2451 stream << ";" << endl;
2452 } else {
2453 stream << "'0';" << endl;
2454 }
2455
2458 if (lockReqWidth > 0) {
2459 stream << " or " << INTERNAL_MERGED_GLOCK_REQ_SIGNAL << ";" << endl;
2460 } else {
2461 stream << ";" << endl;
2462 }
2464 << " <= " << PRE_DECODE_MERGED_GLOCK_SIGNAL << " or "
2465 << PIPELINE_FILL_LOCK_SIGNAL << ";" << endl;
2467 << " <= " << POST_DECODE_MERGED_GLOCK_OUTREG << ";" << endl;
2468
2469 // Generate global lock wiring //
2470 const int glockWidth = glockPortWidth();
2471 for (GlockBitType glockBitToConnect = 0; glockBitToConnect < glockWidth;
2472 glockBitToConnect++) {
2473 stream << indentation(1) << GLOCK_PORT_NAME << "("
2474 << Conversion::toString(glockBitToConnect) << ") <= ";
2475
2476 // If the feature for alternate glock wiring is enabled and current
2477 // glock signal to be wired for the TTA Unit has glock request port.
2479 MapTools::containsKey(unitGlockBitMap_, glockBitToConnect) &&
2482 unitGlockBitMap_.find(glockBitToConnect)->second)) {
2483 // Specialized global lock port map to avoid self-locking of FU.
2484 // Each FU that has global lock request will not receive
2485 // global lock signal unless another FU request global lock.
2486 const Unit* associatedToGlockReq =
2487 unitGlockBitMap_.find(glockBitToConnect)->second;
2488 UnitGlockReqBitMapType::const_iterator gr_it;
2489 for (gr_it = unitGlockReqBitMap_.begin();
2490 gr_it != unitGlockReqBitMap_.end(); gr_it++) {
2491 if (gr_it->first == associatedToGlockReq) {
2492 continue;
2493 }
2494 GlockReqBitType glockReqBitToConnect = gr_it->second;
2495 stream << LOCK_REQ_PORT_NAME << "("
2496 << Conversion::toString(glockReqBitToConnect)
2497 << ") or ";
2498 }
2500 } else {
2501 // Regular global lock port map.
2502 stream << POST_DECODE_MERGED_GLOCK_SIGNAL << ";";
2503 }
2504 if (MapTools::containsKey(unitGlockBitMap_, glockBitToConnect)) {
2505 stream
2506 << " -- to "
2507 << unitGlockBitMap_.find(glockBitToConnect)->second->name();
2508 }
2509 stream << endl;
2510 }
2511}
2512
2513/**
2514 * Writes process that keeps machine locked until first decoded instruction is
2515 * available.
2516 */
2517void
2519 std::ostream& stream) const {
2520 auto indstream = [&](unsigned level) -> std::ostream& {
2521 stream << indentation(level);
2522 return stream;
2523 };
2524 if (language_ == VHDL) {
2525 if (syncReset_) {
2526 indstream(1) << "decode_pipeline_fill_lock: process (clk)"
2527 << endl;
2528 indstream(1) << "begin" << endl;
2529 indstream(2) << "if clk'event and clk = '1' then" << endl;
2530 indstream(3) << "if rstx = '0' then" << endl;
2531 indstream(4) << PIPELINE_FILL_LOCK_SIGNAL << " <= '1';" << endl;
2532 indstream(3) << "elsif lock = '0' then" << endl;
2533 } else {
2534 indstream(1) << "decode_pipeline_fill_lock: process (clk, rstx)"
2535 << endl;
2536 indstream(1) << "begin" << endl;
2537 indstream(2) << "if rstx = '0' then" << endl;
2538 indstream(3) << PIPELINE_FILL_LOCK_SIGNAL << " <= '1';" << endl;
2539 indstream(2) << "elsif clk'event and clk = '1' then" << endl;
2540 indstream(3) << "if lock = '0' then" << endl;
2541 }
2542 indstream(4) << "decode_fill_lock_reg <= '0';" << endl;
2543 indstream(3) << "end if;" << endl;
2544 indstream(2) << "end if;" << endl;
2545 indstream(1) << "end process decode_pipeline_fill_lock;" << endl;
2546
2547 } else { // language_ == Verilog
2548 // todo
2549 }
2550}
2551
2552/**
2553 * Writes resetting of all the control registers to the given stream.
2554 *
2555 * @param stream The stream.
2556 */
2557void
2559 std::ostream& stream) const {
2560 std::string vector_reset = " <= (others => '0');";
2561 std::string bit_reset = " <= '0';";
2562 if (language_ == Verilog) {
2563 vector_reset = " <= 0;";
2564 bit_reset = " <= 1'b0;";
2565 }
2566
2567 for (auto const& signal : registerVectors) {
2568 stream << indentation(3) << signal << vector_reset << endl;
2569 }
2570 stream << endl;
2571 for (auto const& signal : registerBits) {
2572 stream << indentation(3) << signal << bit_reset << endl;
2573 }
2574 stream << endl;
2575}
2576
2577/**
2578 * Writes the instruction decoding section to the main process in decoder.
2579 *
2580 * @param stream The stream to write.
2581 */
2582void
2584 std::ostream& stream) const {
2585
2587 stream << endl;
2589}
2590
2591
2592/**
2593 * Writes the rules for source control signals to the instruction
2594 * decoding section.
2595 *
2596 * @param stream The stream to write.
2597 */
2598void
2600 std::ostream& stream) const {
2601 int indent;
2602 indent = 4;
2603
2605 for (int i = 0; i < socketNav.count(); i++) {
2606 Socket* socket = socketNav.item(i);
2607 if (socket->direction() == Socket::OUTPUT &&
2608 socket->segmentCount() > 0 && socket->portCount() > 0) {
2609 writeBusControlRulesOfOutputSocket(*socket, stream);
2610 }
2611
2613 stream, indent,
2614 "bus control signals for short immediate sockets");
2616 for (int i = 0; i < busNav.count(); i++) {
2617 Bus* bus = busNav.item(i);
2618 if (bus->immediateWidth() > 0) {
2620 }
2621 }
2622 }
2623
2625 stream, indent,
2626 "data control signals for output sockets connected to FUs");
2628 for (int i = 0; i < fuNav.count(); i++) {
2629 FunctionUnit* fu = fuNav.item(i);
2630 for (int i = 0; i < fu->portCount(); i++) {
2631 BaseFUPort* port = fu->port(i);
2632 if (port->outputSocket() != NULL &&
2633 port->outputSocket()->portCount() > 1) {
2634 writeControlRulesOfFUOutputPort(*port, stream);
2635 }
2636 }
2637 }
2638
2640 for (int i = 0; i < gcu->portCount(); i++) {
2641 BaseFUPort* port = gcu->port(i);
2642 if (port->outputSocket() != NULL &&
2643 port->outputSocket()->portCount() > 1) {
2644 writeControlRulesOfFUOutputPort(*port, stream);
2645 }
2646 }
2647
2648 writeComment(stream, indent, "control signals for RF read ports");
2650 for (int i = 0; i < rfNav.count(); i++) {
2651 RegisterFile* rf = rfNav.item(i);
2652 // Skip RFs with separate address cycle flag enabled.
2653 if (sacEnabled(rf->name())) {
2654 continue;
2655 }
2656 for (int i = 0; i < rf->portCount(); i++) {
2657 RFPort* port = rf->port(i);
2658 if (port->outputSocket() != NULL) {
2659 writeControlRulesOfRFReadPort(*port, stream);
2660 }
2661 }
2662 }
2663
2664 stream << endl
2665 << indentation(indent) << ((language_ == VHDL) ? "--" : "//")
2666 << "control signals for IU read ports" << endl;
2667 writeComment(stream, indent, "control signals for IU read ports");
2670 for (int i = 0; i < iuNav.count(); i++) {
2671 ImmediateUnit* iu = iuNav.item(i);
2672 for (int i = 0; i < iu->portCount(); i++) {
2673 RFPort* port = iu->port(i);
2674 if (port->outputSocket() != NULL) {
2675 writeControlRulesOfRFReadPort(*port, stream);
2676 }
2677 }
2678 }
2679}
2680
2681
2682/**
2683 * Writes the rules for destination control signals to the instruction
2684 * decoding section.
2685 *
2686 * @param stream The stream to write.
2687 */
2688void
2690 std::ostream& stream) const {
2691 writeComment(stream, 4, "control signals for FU inputs");
2693 for (int i = 0; i < fuNav.count(); i++) {
2694 FunctionUnit* fu = fuNav.item(i);
2695 for (int i = 0; i < fu->portCount(); i++) {
2696 BaseFUPort* port = fu->port(i);
2697 if (port->inputSocket() != NULL) {
2698 writeControlRulesOfFUInputPort(*port, stream);
2699 }
2700 }
2701 }
2702
2704 for (int i = 0; i < gcu->portCount(); i++) {
2705 BaseFUPort* port = gcu->port(i);
2706 if (port->inputSocket() != NULL) {
2707 writeControlRulesOfFUInputPort(*port, stream);
2708 }
2709 }
2710
2711 writeComment(stream, 4, "control signals for RF inputs");
2713 for (int i = 0; i < rfNav.count(); i++) {
2714 RegisterFile* rf = rfNav.item(i);
2715 for (int i = 0; i < rf->portCount(); i++) {
2716 RFPort* port = rf->port(i);
2717 if (port->inputSocket() != NULL) {
2718 writeControlRulesOfRFWritePort(*port, stream);
2719 }
2720 }
2721 }
2722}
2723
2724/**
2725 * Writes the control signal rules of the given output socket.
2726 *
2727 * @param socket The socket.
2728 * @param stream The stream to write.
2729 */
2730void
2732 const TTAMachine::Socket& socket,
2733 std::ostream& stream) const {
2734
2735 assert(socket.direction() == Socket::OUTPUT);
2736 if(language_==VHDL){
2737 int indent;
2738 indent = 4;
2739 // collect to a set all the buses the socket is connected to
2741 for (BusSet::const_iterator iter = connectedBuses.begin();
2742 iter != connectedBuses.end(); iter++) {
2743 Bus* bus = *iter;
2744 MoveSlot& slot = bem_.moveSlot(bus->name());
2745 SourceField& srcField = slot.sourceField();
2746 stream << indentation(indent) << "if ("
2747 << squashSignal(bus->name()) << " = '0' and ";
2748 stream << socketEncodingCondition(VHDL, srcField, socket.name());
2749 stream << ") then" << endl;
2750 string busCntrlPin = busCntrlSignalPinOfSocket(socket, *bus);
2751 stream << indentation(indent + 1) << busCntrlPin << " <= '1';"
2752 << endl;
2753
2754 stream << indentation(indent) << "else" << endl;
2755 stream << indentation(indent + 1) << busCntrlPin << " <= '0';"
2756 << endl;
2757 stream << indentation(indent) << "end if;" << endl;
2758 }
2759 } else{
2760 // collect to a set all the buses the socket is connected to
2762 for (BusSet::const_iterator iter = connectedBuses.begin();
2763 iter != connectedBuses.end(); iter++) {
2764 Bus* bus = *iter;
2765 MoveSlot& slot = bem_.moveSlot(bus->name());
2766 SourceField& srcField = slot.sourceField();
2767 stream << indentation(4) << "if ("
2768 << squashSignal(bus->name()) << " == 0 && "
2769 << socketEncodingCondition(Verilog, srcField, socket.name()) << ")"
2770 << endl;
2771 string busCntrlPin = busCntrlSignalPinOfSocket(socket, *bus);
2772 stream << indentation(5) << busCntrlPin << " <= 1'b1;" << endl
2773 << indentation(4) << "else" << endl
2774 << indentation(5) << busCntrlPin << " <= 1'b0;" << endl << endl;
2775 }
2776 }
2777}
2778
2779void
2781 const TTAMachine::Bus& bus, std::ostream& stream) const {
2782 int indent;
2783 indent = 4;
2784 SourceField& srcField = bem_.moveSlot(bus.name()).sourceField();
2785 ImmediateEncoding& enc = srcField.immediateEncoding();
2786 stream << indentation(indent) << simmDataSignalName(bus.name()) << " <= ";
2787 if (bus.signExtends()) {
2788 stream << "tce_sxt(";
2789 } else {
2790 stream << "tce_ext(";
2791 }
2792 stream << srcFieldSignal(bus.name()) << "("
2793 << enc.immediatePosition() + enc.immediateWidth() - 1 << " downto "
2794 << enc.immediatePosition() << "), "
2795 << simmDataSignalName(bus.name()) << "'length);" << endl;
2796}
2797
2798/**
2799 * Writes the control signal rules for the socket that transports the short
2800 * immediate to the given bus.
2801 *
2802 * @param bus The bus.
2803 * @param stream The stream to write.
2804 */
2805void
2807 const TTAMachine::Bus& bus,
2808 std::ostream& stream) const {
2809
2810 assert(bus.immediateWidth() > 0);
2811 MoveSlot& slot = bem_.moveSlot(bus.name());
2812 SourceField& srcField = slot.sourceField();
2813 assert(srcField.hasImmediateEncoding());
2814 ImmediateEncoding& enc = srcField.immediateEncoding();
2815
2816 if(language_==VHDL){
2817 int indent = 4;
2818 stream << indentation(indent) << "if (" << squashSignal(bus.name())
2819 << " = '0'";
2820 if (enc.encodingWidth() > 0) {
2821 stream << " and ";
2822 stream << "conv_integer(unsigned(" << srcFieldSignal(bus.name())
2823 << "(" << enc.encodingPosition() + enc.encodingWidth() - 1
2824 << " downto " << enc.encodingPosition()
2825 << "))) = " << enc.encoding();
2826 }
2827
2828 stream << ") then" << endl;
2829 stream << indentation(indent + 1) << simmCntrlSignalName(bus.name())
2830 << "(0) <= '1';" << endl;
2831 writeSimmDataSignal(bus, stream);
2832 stream << indentation(indent) << "else" << endl;
2833 stream << indentation(indent + 1) << simmCntrlSignalName(bus.name())
2834 << "(0) <= '0';" << endl;
2835 stream << indentation(4) << "end if;" << endl;
2836 } else {
2837 stream << indentation(4) << "if ("
2838 << squashSignal(bus.name()) << " == 0";
2839 if (enc.encodingWidth() > 0) {
2840 stream << " && "
2841 << srcFieldSignal(bus.name()) << "["
2842 << enc.encodingPosition() + enc.encodingWidth() - 1 << " : "
2843 << enc.encodingPosition() << "] == " << enc.encoding();
2844 }
2845 stream << ")" << endl << indentation(4) << "begin" << endl;
2846 stream << indentation(5) << simmCntrlSignalName(bus.name())
2847 << "[0] <= 1'b1;" << endl;
2848 stream << indentation(5) << simmDataSignalName(bus.name()) << " <= ";
2849
2850 if (bus.signExtends()) {
2851 stream << "$signed(";
2852 } else {
2853 stream << "$unsigned(";
2854 }
2855 stream << srcFieldSignal(bus.name()) << "["
2856 << enc.immediatePosition() + enc.immediateWidth() - 1
2857 << " : " << enc.immediatePosition() << "]);" << endl
2858 << indentation(4) << "end" << endl
2859 << indentation(4) << "else" << endl
2860 << indentation(4) << "begin" << endl
2861 << indentation(5) << simmCntrlSignalName(bus.name())
2862 << "[0] <= 1'b0;" << endl
2863 << indentation(4) << "end" << endl;
2864 }
2865}
2866
2867
2868/**
2869 * Writes the data control signal rules of the socket connected to the given
2870 * FU output port.
2871 *
2872 * @param port The port.
2873 * @param stream The stream to write.
2874 */
2875void
2877 const TTAMachine::BaseFUPort& port,
2878 std::ostream& stream) const {
2879 int indent = 4;
2880
2881 Socket* socket = port.outputSocket();
2882 assert(socket != NULL);
2884 if(language_==VHDL){
2885 for (BusSet::const_iterator iter = connectedBuses.begin();
2886 iter != connectedBuses.end(); iter++) {
2887 Bus* bus = *iter;
2888 MoveSlot& slot = bem_.moveSlot(bus->name());
2889 SourceField& srcField = slot.sourceField();
2890 SocketEncoding& enc = srcField.socketEncoding(socket->name());
2891 stream << indentation(indent) << "if ("
2892 << squashSignal(bus->name()) << " = '0' and ";
2893 stream << socketEncodingCondition(VHDL, srcField, socket->name());
2894 if (enc.hasSocketCodes()) {
2895 SocketCodeTable& scTable = enc.socketCodes();
2896 FUPortCode& code = scTable.fuPortCode(
2897 port.parentUnit()->name(), port.name());
2898 stream << " and " << portCodeCondition(VHDL, enc, code)
2899 << ") then" << endl;
2900 } else {
2901 stream << ") then" << endl;
2902 }
2903 stream << indentation(indent + 1)
2904 << socketDataCntrlSignalName(socket->name()) << " <= "
2905 << "conv_std_logic_vector("
2907 << ", " << socketDataCntrlSignalName(socket->name())
2908 << "'length);" << endl;
2909 stream << indentation(indent) << "end if;" << endl;
2910 }
2911 } else {
2912 for (BusSet::const_iterator iter = connectedBuses.begin();
2913 iter != connectedBuses.end(); iter++) {
2914 Bus* bus = *iter;
2915 MoveSlot& slot = bem_.moveSlot(bus->name());
2916 SourceField& srcField = slot.sourceField();
2917 SocketEncoding& enc = srcField.socketEncoding(socket->name());
2918 stream << indentation(indent) << "if ("
2919 << squashSignal(bus->name()) << " == 0 && "
2921 Verilog, srcField, socket->name());
2922 if (enc.hasSocketCodes()) {
2923 SocketCodeTable& scTable = enc.socketCodes();
2924 FUPortCode& code = scTable.fuPortCode(
2925 port.parentUnit()->name(), port.name());
2926 stream << " && " << portCodeCondition(Verilog, enc, code) << ")"
2927 << endl;
2928 } else {
2929 stream << ")" << endl;
2930 }
2931 stream << indentation(indent)
2932 << socketDataCntrlSignalName(socket->name()) << " <= "
2934 << ";" << endl;
2935 }
2936 }
2937}
2938
2939
2940/**
2941 * Writes the control signal rules related to the given RF read port.
2942 *
2943 * @param port The RF read port.
2944 * @param stream The stream to write.
2945 */
2946void
2948 const TTAMachine::RFPort& port,
2949 std::ostream& stream) const {
2950 int indent = 4;
2951 assert(port.outputSocket() != NULL);
2952
2953 // Do not write load signal when port is bidirectional
2954 // (where load = write enable)
2955 bool writeLoadSignal = true;
2956 if (port.inputSocket() != NULL) {
2957 writeLoadSignal = false;
2958 }
2959
2960 Socket* socket = port.outputSocket();
2961 BaseRegisterFile* rf = port.parentUnit();
2962 bool async_signal = sacEnabled(rf->name());
2963
2964 // collect to a set all the buses the socket is connected to
2966 string opcodeString = "";
2967 if (language_ == VHDL) {
2968 for (BusSet::const_iterator iter = connectedBuses.begin();
2969 iter != connectedBuses.end();iter++) {
2970 BusSet::const_iterator nextIter = iter;
2971 nextIter++;
2972 if (iter == connectedBuses.begin()) {
2973 stream << indentation(indent) << "if (";
2974 } else {
2975 stream << indentation(indent) << "elsif (";
2976 }
2977
2978 Bus* bus = *iter;
2979 MoveSlot& slot = bem_.moveSlot(bus->name());
2980 SourceField& srcField = slot.sourceField();
2981 SocketEncoding& enc = srcField.socketEncoding(socket->name());
2982 SocketCodeTable* scTable = NULL;
2983 if (enc.hasSocketCodes()) {
2984 scTable = &enc.socketCodes();
2985 }
2986
2987 PortCode* code = NULL;
2988 if (scTable != NULL) {
2989 if (dynamic_cast<ImmediateUnit*>(rf) != NULL) {
2990 code = &scTable->iuPortCode(rf->name());
2991 } else {
2992 code = &scTable->rfPortCode(rf->name());
2993 }
2994 }
2995 stream << squashSignal(bus->name()) << " = '0' and ";
2996 stream << socketEncodingCondition(VHDL, srcField, socket->name());
2997 if (code != NULL && code->hasEncoding()) {
2998 stream << " and " << portCodeCondition(VHDL, enc, *code);
2999 }
3000 stream << ") then" << endl;
3001
3002 string loadSignalName;
3003 string opcodeSignalName;
3004 if (dynamic_cast<ImmediateUnit*>(rf) != NULL) {
3005 loadSignalName =
3006 iuReadLoadCntrlPort(rf->name(), port.name());
3007 opcodeSignalName =
3008 iuReadOpcodeCntrlPort(rf->name(), port.name());
3009 } else {
3010 loadSignalName = rfLoadSignalName(rf->name(), port.name(),
3011 async_signal);
3012 opcodeSignalName = rfOpcodeSignalName(rf->name(), port.name(),
3013 async_signal);
3014 }
3015 if (writeLoadSignal) {
3016 stream << indentation(indent + 1) << loadSignalName
3017 << " <= '1';" << endl;
3018 }
3019 if (code != NULL) {
3020 opcodeString = indentation(indent + 1) + opcodeSignalName +
3021 " <= tce_ext(" +
3022 rfOpcodeFromSrcOrDstField(VHDL, enc, *code) +
3023 ", " + opcodeSignalName + "'length);";
3024 stream << opcodeString << endl;
3025 }
3026
3027 if (needsDataControl(*socket)) {
3028 stream << indentation(indent)
3029 << socketDataCntrlSignalName(socket->name())
3030 << " <= conv_std_logic_vector("
3032 *socket, port)
3033 << ", " << socketDataCntrlSignalName(socket->name())
3034 << "'length);" << endl;
3035 }
3036 }
3037
3038 if (writeLoadSignal) {
3039 stream << indentation(indent) << "else" << endl;
3040 stream << indentation(indent + 1);
3041 if (dynamic_cast<ImmediateUnit*>(rf) != NULL) {
3042 stream << iuReadLoadCntrlPort(rf->name(), port.name());
3043 } else {
3044 stream << rfLoadSignalName(
3045 rf->name(), port.name(), async_signal);
3046 }
3047 stream << " <= '0';" << endl;
3048 }
3049 stream << indentation(indent) << "end if;" << endl;
3050 } else { // language_ == Verilog
3051 for (BusSet::const_iterator iter = connectedBuses.begin();
3052 iter != connectedBuses.end();iter++) {
3053 BusSet::const_iterator nextIter = iter;
3054 nextIter++;
3055 if (iter == connectedBuses.begin()) {
3056 stream << indentation(4) << "if (";
3057 } else {
3058 stream << indentation(4) << "else if(";
3059 }
3060
3061 Bus* bus = *iter;
3062 MoveSlot& slot = bem_.moveSlot(bus->name());
3063 SourceField& srcField = slot.sourceField();
3064 SocketEncoding& enc = srcField.socketEncoding(socket->name());
3065 SocketCodeTable* scTable = NULL;
3066 if (enc.hasSocketCodes()) {
3067 scTable = &enc.socketCodes();
3068 }
3069
3070 PortCode* code = NULL;
3071 if (scTable != NULL) {
3072 if (dynamic_cast<ImmediateUnit*>(rf) != NULL) {
3073 code = &scTable->iuPortCode(rf->name());
3074 } else {
3075 code = &scTable->rfPortCode(rf->name());
3076 }
3077 }
3078 stream << squashSignal(bus->name()) << " == 0 && "
3079 << socketEncodingCondition(Verilog, srcField, socket->name());
3080 if (code != NULL && code->hasEncoding()) {
3081 stream << " && " << portCodeCondition(Verilog, enc, *code);
3082 }
3083 stream << ")" << endl
3084 << indentation(4) << "begin" << endl;
3085
3086 string loadSignalName;
3087 string opcodeSignalName;
3088 if (dynamic_cast<ImmediateUnit*>(rf) != NULL) {
3089 loadSignalName =
3090 iuReadLoadCntrlSignal(rf->name(), port.name());
3091 opcodeSignalName =
3092 iuReadOpcodeCntrlSignal(rf->name(), port.name());
3093 } else {
3094 loadSignalName = rfLoadSignalName(rf->name(), port.name(),
3095 async_signal);
3096 opcodeSignalName = rfOpcodeSignalName(rf->name(), port.name(),
3097 async_signal);
3098 }
3099
3100 stream << indentation(5) << loadSignalName << " <= 1'b1;" << endl;
3101 if (code != NULL) {
3102 stream << indentation(5) << opcodeSignalName
3103 << " <= $unsigned("
3104 << rfOpcodeFromSrcOrDstField(Verilog, enc, *code)
3105 << ");" << endl;
3106 }
3107
3108 if (needsDataControl(*socket)) {
3109 stream << indentation(5)
3110 << socketDataCntrlSignalName(socket->name())
3111 << " <= "
3113 << ";" << endl;
3114 }
3115 stream << indentation(4) << "end" << endl;
3116 }
3117 stream << indentation(4) << "else" << endl
3118 << indentation(4) << "begin" << endl
3119 << indentation(5);
3120 if (dynamic_cast<ImmediateUnit*>(rf) != NULL) {
3121 stream << iuReadLoadCntrlSignal(rf->name(), port.name());
3122 } else {
3123 stream << rfLoadSignalName(rf->name(), port.name(), async_signal);
3124 }
3125 stream << " <= 1'b0;" << endl
3126 << indentation(4) << "end" << endl;
3127 }
3128}
3129
3130
3131/**
3132 * Writes the rules for control signals related to the given FU input port.
3133 *
3134 * @param port The port.
3135 * @param stream The stream to write.
3136 */
3137void
3139 const TTAMachine::BaseFUPort& port,
3140 std::ostream& stream) const {
3141 int indent = 4;
3142 FunctionUnit* fu = port.parentUnit();
3143 Socket* socket = port.inputSocket();
3144 assert(socket != NULL);
3145 BusSet buses = connectedBuses(*socket);
3146 stream << indentation(indent) << "if (";
3147 if(language_==VHDL){
3148 string opcodeAssignString = "";
3149 string cntrlSignalString = "";
3150 for (BusSet::const_iterator iter = buses.begin(); iter != buses.end();
3151 iter++) {
3152 Bus* bus = *iter;
3153 MoveSlot& moveSlot = bem_.moveSlot(bus->name());
3154 DestinationField& dstField = moveSlot.destinationField();
3155 SocketEncoding& enc = dstField.socketEncoding(socket->name());
3156 stream << squashSignal(bus->name()) << " = '0' and ";
3157 stream << socketEncodingCondition(VHDL, dstField, socket->name());
3158 if (enc.hasSocketCodes()) {
3159 SocketCodeTable& scTable = enc.socketCodes();
3160 if (port.isOpcodeSetting()) {
3161 stream << ") then" << endl;
3162
3163 ControlUnit* gcu = dynamic_cast<ControlUnit*>(fu);
3164
3165 // Check
3166 bool ordered=true;
3167 for (int i = 0; i < fu->operationCount(); i++) {
3168 HWOperation* operation = fu->operation(i);
3169 FUPortCode& code = scTable.fuPortCode(
3170 fu->name(), port.name(), operation->name());
3171 if ((int)(code.encoding()) != (int)(opcode(*operation))) {
3172 ordered=false;
3173 break;
3174 }
3175 }
3176 if (!ordered) {
3177 stream << indentation(indent + 1) << "if (";
3178 for (int i = 0; i < fu->operationCount(); i++) {
3179 HWOperation* operation = fu->operation(i);
3180 FUPortCode& code = scTable.fuPortCode(
3181 fu->name(), port.name(), operation->name());
3182 stream << portCodeCondition(VHDL, enc, code) << ") then"
3183 << endl;
3184 stream
3185 << indentation(indent + 2)
3186 << fuLoadSignalName(fu->name(), port.name())
3187 << " <= '1';" << endl;
3188 if (gcu != nullptr) {
3189 if (operation->name() == JUMP) {
3190 stream << indentation(indent + 2)
3191 << fuOpcodeSignalName(fu->name())
3192 << " <= "
3193 "std_logic_vector(conv_"
3194 "unsigned(IFE_JUMP, "
3195 << fuOpcodeSignalName(fu->name())
3196 << "'length));" << endl;
3197 } else if (operation->name() == CALL) {
3198 stream << indentation(indent + 2)
3199 << fuOpcodeSignalName(fu->name())
3200 << " <= "
3201 "std_logic_vector(conv_"
3202 "unsigned(IFE_CALL, "
3203 << fuOpcodeSignalName(fu->name())
3204 << "'length));" << endl;
3205 }
3206 } else {
3207 stream << indentation(indent + 2)
3208 << fuOpcodeSignalName(fu->name())
3209 << " <= conv_std_logic_vector("
3210 << opcode(*operation) << ", "
3211 << fuOpcodeSignalName(fu->name())
3212 << "'length);" << endl;
3213 }
3214 if (i+1 < fu->operationCount()) {
3215 stream << indentation(indent + 1)
3216 << "elsif (";
3217 }
3218 }
3219 stream << indentation(indent + 1) << "else" << endl;
3220 stream << indentation(indent + 2)
3221 << fuLoadSignalName(fu->name(), port.name())
3222 << " <= '0';" << endl;
3223 stream << indentation(indent + 1) << "end if;"
3224 << endl;
3225 } else {
3226 FUPortCode& code = scTable.fuPortCode(
3227 fu->name(), port.name(), fu->operation(0)->name());
3228 SlotField* parent = enc.parent();
3229 string signalName;
3230 if (dynamic_cast<SourceField*>(parent) != NULL) {
3231 signalName = srcFieldSignal(parent->parent()->name());
3232 } else {
3233 signalName = dstFieldSignal(parent->parent()->name());
3234 }
3235
3236 int codeStart;
3237 if (parent->componentIDPosition() == BinaryEncoding::RIGHT) {
3238 codeStart = enc.socketIDWidth() + code.indexWidth();
3239 } else {
3240 codeStart = code.indexWidth();
3241 }
3242 int codeEnd = codeStart + code.encodingWidth() - 1;
3243 assert(codeEnd >= codeStart);
3244 stream << indentation(indent + 1)
3245 << fuLoadSignalName(fu->name(), port.name())
3246 << " <= '1';" << endl;
3247 opcodeAssignString =
3248 indentation(indent + 1) +
3249 fuOpcodeSignalName(fu->name()) +
3250 " <= " + signalName + "(" +
3251 Conversion::toString(codeEnd) + " downto " +
3252 Conversion::toString(codeStart) + ")" + ";";
3253 stream << opcodeAssignString << endl;
3254 }
3255 } else {
3256 FUPortCode& code = scTable.fuPortCode(
3257 fu->name(), port.name());
3258 stream << " and " << portCodeCondition(VHDL, enc, code) << ") then"
3259 << endl;
3260 stream << indentation(indent + 1)
3261 << fuLoadSignalName(fu->name(), port.name())
3262 << " <= '1';" << endl;
3263 }
3264
3265 } else {
3266 stream << ") then" << endl;
3267 stream << indentation(indent + 1)
3268 << fuLoadSignalName(fu->name(), port.name())
3269 << " <= '1';" << endl;
3270 }
3271 if (needsBusControl(*socket)) {
3272 cntrlSignalString =
3273 indentation(indent + 1) +
3274 socketBusCntrlSignalName(socket->name()) +
3275 " <= conv_std_logic_vector(" +
3277 *socket, *bus->segment(0))) +
3278 ", " + socketBusCntrlSignalName(socket->name()) +
3279 "'length);";
3280 stream << cntrlSignalString << endl;
3281 }
3282
3283 BusSet::const_iterator nextIter = iter;
3284 nextIter++;
3285 if (nextIter != buses.end()) {
3286 stream << indentation(indent) << "elsif (";
3287 };
3288 }
3289
3290 stream << indentation(indent) << "else" << endl;
3291 stream << indentation(indent + 1)
3292 << fuLoadSignalName(fu->name(), port.name()) << " <= '0';"
3293 << endl;
3294 stream << indentation(indent) << "end if;" << endl;
3295 } else { // language == Verilog
3296 for (BusSet::const_iterator iter = buses.begin(); iter != buses.end();
3297 iter++) {
3298 Bus* bus = *iter;
3299 MoveSlot& moveSlot = bem_.moveSlot(bus->name());
3300 DestinationField& dstField = moveSlot.destinationField();
3301 SocketEncoding& enc = dstField.socketEncoding(socket->name());
3302 stream << squashSignal(bus->name()) << " == 0 && "
3303 << socketEncodingCondition(Verilog, dstField, socket->name());
3304 if (enc.hasSocketCodes()) {
3305 SocketCodeTable& scTable = enc.socketCodes();
3306 if (port.isOpcodeSetting()) {
3307 stream << ")" << endl
3308 << indentation(4) << "begin" << endl
3309 << indentation(5) << "if (";
3310 for (int i = 0; i < fu->operationCount(); i++) {
3311 HWOperation* operation = fu->operation(i);
3312 FUPortCode& code = scTable.fuPortCode(
3313 fu->name(), port.name(), operation->name());
3314 stream << portCodeCondition(Verilog, enc, code) << ")"
3315 << endl
3316 << indentation(5) << "begin" << endl
3317 << indentation(6)
3318 << fuLoadSignalName(fu->name(), port.name())
3319 << " <= 1'b1;" << endl;
3320 ControlUnit* gcu = dynamic_cast<ControlUnit*>(fu);
3321 if (gcu != NULL) {
3322 if (operation->name() == JUMP) {
3323 stream << indentation(5)
3324 << fuOpcodeSignalName(fu->name())
3325 << " <= IFE_JUMP;" << endl;
3326 } else if (operation->name() == CALL) {
3327 stream << indentation(5)
3328 << fuOpcodeSignalName(fu->name())
3329 << " <= IFE_CALL;" << endl;
3330 }
3331 } else {
3332 stream << indentation(6)
3333 << fuOpcodeSignalName(fu->name())
3334 << " <= "
3335 << opcode(*operation)
3336 << ";"
3337 << endl;
3338 }
3339 if (i+1 < fu->operationCount()) {
3340 stream << indentation(5) << "end" << endl
3341 << indentation(5) << "else if (";
3342 }
3343 }
3344 stream << indentation(5) << "end" << endl
3345 << indentation(5) << "else" << endl
3346 << indentation(6)
3347 << fuLoadSignalName(fu->name(), port.name())
3348 << " <= 1'b0;"
3349 << endl;
3350 } else {
3351 FUPortCode& code = scTable.fuPortCode(
3352 fu->name(), port.name());
3353 stream << " && " << portCodeCondition(Verilog, enc, code) << ")"
3354 << endl
3355 << indentation(4) << "begin" << endl
3356 << indentation(5)
3357 << fuLoadSignalName(fu->name(), port.name())
3358 << " <= 1'b1;" << endl;
3359 }
3360 } else {
3361 stream << ")" << endl
3362 << indentation(4) << "begin" << endl
3363 << indentation(5)
3364 << fuLoadSignalName(fu->name(), port.name()) << " <= 1'b1;"
3365 << endl;
3366 ControlUnit* gcu = dynamic_cast<ControlUnit*>(fu);
3367 if (gcu != NULL) {
3368 if (gcu->hasOperation(JUMP)) {
3369 HWOperation* jumpOp = gcu->operation(JUMP);
3370 if (&port == jumpOp->port(1)) {
3371 stream << indentation(5)
3372 << fuOpcodeSignalName(fu->name())
3373 << " <= IFE_JUMP;" << endl;
3374 }
3375 }
3376 if (gcu->hasOperation(CALL)) {
3377 HWOperation* callOp = gcu->operation(CALL);
3378 if (&port == callOp->port(1)) {
3379 stream << indentation(5)
3380 << fuOpcodeSignalName(fu->name())
3381 << " <= IFE_CALL;" << endl;
3382 }
3383 }
3384 }
3385 }
3386 if (needsBusControl(*socket)) {
3387 stream << indentation(5)
3388 << socketBusCntrlSignalName(socket->name())
3389 << " <= "
3391 *socket, *bus->segment(0)) << ";"
3392 << endl;
3393 }
3394
3395 BusSet::const_iterator nextIter = iter;
3396 nextIter++;
3397 stream << indentation(4) << "end" << endl;
3398 if (nextIter != buses.end()) {
3399 stream << indentation(4) << "else if(";
3400 };
3401 }
3402
3403 stream << indentation(4) << "else" << endl;
3404 stream << indentation(5) << fuLoadSignalName(fu->name(), port.name())
3405 << " <= 1'b0;" << endl;
3406 }
3407}
3408
3409
3410/**
3411 * Writes the rules for control signals related to the given RF write port.
3412 *
3413 * @param port The port.
3414 * @param stream The stream to write.
3415 */
3416void
3418 const TTAMachine::RFPort& port,
3419 std::ostream& stream) const {
3420 int indent = 4;
3421 BaseRegisterFile* rf = port.parentUnit();
3422 Socket* socket = port.inputSocket();
3423 assert(socket != NULL);
3424 BusSet buses = connectedBuses(*socket);
3425 stream << indentation(indent) << "if (";
3426 if(language_==VHDL){
3427 string opcodeSignalString = "";
3428 string controlSignalString = "";
3429 for (BusSet::const_iterator iter = buses.begin(); iter != buses.end();
3430 iter++) {
3431 Bus* bus = *iter;
3432 MoveSlot& moveSlot = bem_.moveSlot(bus->name());
3433 DestinationField& dstField = moveSlot.destinationField();
3434 SocketEncoding& enc = dstField.socketEncoding(socket->name());
3435 stream << squashSignal(bus->name()) << " = '0' and ";
3436 stream << socketEncodingCondition(VHDL, dstField, socket->name());
3437 if (enc.hasSocketCodes()) {
3438 SocketCodeTable& scTable = enc.socketCodes();
3439 RFPortCode& code = scTable.rfPortCode(rf->name());
3440 if (code.hasEncoding()) {
3441 stream << " and " << portCodeCondition(VHDL, enc, code);
3442
3443 }
3444 stream << ") then" << endl;
3445 stream << indentation(indent + 1)
3446 << rfLoadSignalName(rf->name(), port.name())
3447 << " <= '1';" << endl;
3448 opcodeSignalString =
3449 indentation(indent + 1) +
3450 rfOpcodeSignalName(rf->name(), port.name()) +
3451 " <= " + rfOpcodeFromSrcOrDstField(VHDL, enc, code) + ";";
3452 stream << opcodeSignalString << endl;
3453
3454 } else {
3455 stream << ") then" << endl;
3456 stream << indentation(indent + 1)
3457 << rfLoadSignalName(rf->name(), port.name())
3458 << " <= '1';" << endl;
3459 }
3460
3461 if (needsBusControl(*socket)) {
3462 controlSignalString =
3463 indentation(indent + 1) +
3464 socketBusCntrlSignalName(socket->name()) +
3465 " <= conv_std_logic_vector(" +
3467 *socket, *bus->segment(0))) +
3468 ", " + socketBusCntrlSignalName(socket->name()) +
3469 "'length);";
3470
3471 stream << controlSignalString << endl;
3472 }
3473
3474 BusSet::const_iterator nextIter = iter;
3475 nextIter++;
3476 if (nextIter != buses.end()) {
3477 stream << indentation(indent) << "elsif (";
3478 }
3479 }
3480 stream << indentation(indent) << "else" << endl;
3481 stream << indentation(indent + 1)
3482 << rfLoadSignalName(rf->name(), port.name()) << " <= '0';"
3483 << endl;
3484 stream << indentation(indent) << "end if;" << endl;
3485 } else {
3486 for (BusSet::const_iterator iter = buses.begin(); iter != buses.end();
3487 iter++) {
3488 Bus* bus = *iter;
3489 MoveSlot& moveSlot = bem_.moveSlot(bus->name());
3490 DestinationField& dstField = moveSlot.destinationField();
3491 SocketEncoding& enc = dstField.socketEncoding(socket->name());
3492 stream << squashSignal(bus->name()) << " == 0 && "
3493 << socketEncodingCondition(Verilog, dstField, socket->name());
3494 if (enc.hasSocketCodes()) {
3495 SocketCodeTable& scTable = enc.socketCodes();
3496 RFPortCode& code = scTable.rfPortCode(rf->name());
3497 if (code.hasEncoding()) {
3498 stream << " && " << portCodeCondition(Verilog, enc, code);
3499
3500 }
3501 stream << ")" << endl
3502 << indentation(4) << "begin" << endl
3503 << indentation(5)
3504 << rfLoadSignalName(rf->name(), port.name()) << " <= 1'b1;"
3505 << endl
3506 << indentation(5)
3507 << rfOpcodeSignalName(rf->name(), port.name()) << " <= "
3508 << rfOpcodeFromSrcOrDstField(Verilog, enc, code) << ";" << endl;
3509 } else {
3510 stream << ")" << endl
3511 << indentation(4) << "begin" << endl
3512 << indentation(5)
3513 << rfLoadSignalName(rf->name(), port.name()) << " <= 1'b1;"
3514 << endl;
3515 }
3516
3517 if (needsBusControl(*socket)) {
3518 stream << indentation(5)
3519 << socketBusCntrlSignalName(socket->name())
3520 << " <= "
3522 *socket, *bus->segment(0)) << ";"
3523 << endl;
3524 }
3525
3526 BusSet::const_iterator nextIter = iter;
3527 nextIter++;
3528 stream << indentation(4) << "end" << endl;
3529 if (nextIter != buses.end()) {
3530 stream << indentation(4) << "else if (";
3531 }
3532 }
3533 stream << indentation(4) << "else" << endl
3534 << indentation(5) << rfLoadSignalName(rf->name(), port.name())
3535 << " <= 1'b0;" << endl;
3536 }
3537}
3538
3539
3540/**
3541 * Writes the mappings of control registers to control ports to the given
3542 * stream.
3543 *
3544 * @param stream The stream.
3545 */
3546void
3548 std::ostream& stream) const {
3549 if(language_==VHDL){
3550 stream << indentation(1) << "-- map control registers to outputs"
3551 << endl;
3552
3553 // map FU control signals
3555 functionUnitNavigator();
3556 for (int i = 0; i < fuNav.count(); i++) {
3557 FunctionUnit* fu = fuNav.item(i);
3558 for (int i = 0; i < fu->portCount(); i++) {
3559 BaseFUPort* port = fu->port(i);
3560 if (port->inputSocket() != NULL) {
3561 // map load signal
3562 stream << indentation(1)
3563 << fuLoadCntrlPort(fu->name(), port->name())
3564 << " <= "
3565 << fuLoadSignalName(fu->name(), port->name())
3566 << ";" << endl;
3567 }
3568 }
3569
3570 // map opcode signal
3571 if (fu->operationCount() > 1) {
3572 stream << indentation(1) << fuOpcodeCntrlPort(fu->name())
3573 << " <= " << fuOpcodeSignalName(fu->name()) << ";"
3574 << endl;
3575 }
3576 stream << endl;
3577 }
3578
3579 // map pc_load and ra_load signals
3581 if (gcu->hasReturnAddressPort()) {
3582 SpecialRegisterPort* raPort = gcu->returnAddressPort();
3584 << " <= " << fuLoadSignalName(gcu->name(), raPort->name())
3585 << ";" << endl;
3586 }
3587
3588 // find the PC port
3589 BaseFUPort* pcPort = gcu->triggerPort();
3590 if (pcPort != NULL) {
3592 << " <= " << fuLoadSignalName(gcu->name(), pcPort->name())
3593 << ";" << endl;
3594 }
3595
3596 // map pc_opcode signal
3597 if (gcu->hasOperation(JUMP) || gcu->hasOperation(CALL)) {
3598 stream << indentation(1)
3600 << " <= " << fuOpcodeSignalName(gcu->name()) << ";"
3601 << endl;
3602 }
3603
3604 // map other GCU's load signals
3605 for (int i = 0; i < gcu->portCount(); i++) {
3606 BaseFUPort* port = gcu->port(i);
3607 if (!port->isInput() ||
3608 port->name() == gcu->returnAddressPort()->name() ||
3609 port->isTriggering()) {
3610 continue;
3611 }
3612 stream << indentation(1)
3613 << fuLoadCntrlPort(gcu->name(), port->name())
3614 << " <= " << fuLoadSignalName(gcu->name(), port->name())
3615 << ";" << endl;
3616 }
3617
3618 // map other GCU's load signals
3619 for (int i = 0; i < gcu->portCount(); i++) {
3620 BaseFUPort* port = gcu->port(i);
3621 if (!port->isInput() ||
3622 port->name() == gcu->returnAddressPort()->name() ||
3623 port->isTriggering()) {
3624 continue;
3625 }
3626 stream << indentation(1)
3627 << fuLoadCntrlPort(gcu->name(), port->name())
3628 << " <= " << fuLoadSignalName(gcu->name(), port->name())
3629 << ";" << endl;
3630 }
3631
3632 // map RF control signals
3634 registerFileNavigator();
3635 for (int i = 0; i < rfNav.count(); i++) {
3636 RegisterFile* rf = rfNav.item(i);
3637
3638 for (int i = 0; i < rf->portCount(); i++) {
3639 RFPort* port = rf->port(i);
3640 bool async_signal = sacEnabled(rf->name())
3641 && port->outputSocket() != NULL;
3642
3643 // map load signal
3644 stream << indentation(1)
3645 << rfLoadCntrlPort(rf->name(), port->name()) << " <= "
3646 << rfLoadSignalName(rf->name(), port->name(),
3647 async_signal) << ";"
3648 << endl;
3649
3650 // map opcode signal
3651 bool OpcodePortExists = decoderBlock_->port(
3652 rfOpcodeCntrlPort(rf->name(), port->name()));
3653 if (OpcodePortExists) {
3654 stream << indentation(1)
3655 << rfOpcodeCntrlPort(rf->name(), port->name())
3656 << " <= "
3657 << (rfOpcodeWidth(*rf) == 0 ? "\"0\"" :
3658 rfOpcodeSignalName(rf->name(), port->name(),
3659 async_signal))
3660 << ";"
3661 << endl;
3662 }
3663 }
3664 }
3665
3666 // map IU write/read opcode signals (only 0 downto 0) to 0
3667 // TODO: mapping of these ports should probably be elsewhere
3670 for (int i = 0; i < iuNav.count(); i++) {
3671 ImmediateUnit* iu = iuNav.item(i);
3672 for (int i = 0; i < iu->portCount(); i++) {
3673 RFPort* port = iu->port(i);
3674 bool readOpcodePortExists = decoderBlock_->port(
3675 iuReadOpcodeCntrlPort(iu->name(), port->name()));
3676 bool writeOpcodePortExists =
3678 assert(readOpcodePortExists == writeOpcodePortExists);
3679 if (rfOpcodeWidth(*iu) == 0 and readOpcodePortExists and
3680 writeOpcodePortExists) {
3681
3682 stream << indentation(1)
3683 << iuReadOpcodeCntrlPort(iu->name(), port->name())
3684 << " <= \"0\";"
3685 << endl;
3686
3687 stream << indentation(1)
3689 << " <= \"0\";"
3690 << endl;
3691 }
3692 }
3693 }
3694
3695
3696 // map socket control signals
3698 for (int i = 0; i < socketNav.count(); i++) {
3699 Socket* socket = socketNav.item(i);
3700 if (socket->portCount() == 0 || socket->segmentCount() == 0) {
3701 continue;
3702 }
3703
3704 if (needsBusControl(*socket)) {
3705 stream << indentation(1) << socketBusControlPort(socket->name())
3706 << " <= " << socketBusCntrlSignalName(socket->name())
3707 << ";" << endl;
3708 }
3709 if (needsDataControl(*socket)) {
3710 stream << indentation(1) << socketDataControlPort(socket->name())
3711 << " <= " << socketDataCntrlSignalName(socket->name())
3712 << ";" << endl;
3713 }
3714 }
3715 // map short immediate signals
3717 for (int i = 0; i < busNav.count(); i++) {
3718 Bus* bus = busNav.item(i);
3719 if (bus->immediateWidth() > 0) {
3720 stream << indentation(1) << simmControlPort(bus->name())
3721 << " <= " << simmCntrlSignalName(bus->name()) << ";"
3722 << endl;
3723 if (!machine_.isRISCVMachine()) {
3724 stream << indentation(1) << simmDataPort(bus->name())
3725 << " <= " << simmDataSignalName(bus->name()) << ";"
3726 << endl;
3727 } else {
3728 stream << indentation(1) << simmDataPort(bus->name())
3729 << " <= " << RISCV_SIMM_PORT_IN_NAME << ";"
3730 << endl;
3731 }
3732 }
3733 }
3734 } else {
3735 stream << indentation(1) << "// map control registers to outputs"
3736 << endl;
3737
3738 // map FU control signals
3740 functionUnitNavigator();
3741 for (int i = 0; i < fuNav.count(); i++) {
3742 FunctionUnit* fu = fuNav.item(i);
3743 for (int i = 0; i < fu->portCount(); i++) {
3744 BaseFUPort* port = fu->port(i);
3745 if (port->inputSocket() != NULL) {
3746 // map load signal
3747 stream << indentation(1)
3748 << "assign "
3749 << fuLoadCntrlPort(fu->name(), port->name())
3750 << " = "
3751 << fuLoadSignalName(fu->name(), port->name())
3752 << ";" << endl;
3753 }
3754 }
3755
3756 // map opcode signal
3757 if (fu->operationCount() > 1) {
3758 stream << indentation(1)
3759 << "assign "
3760 << fuOpcodeCntrlPort(fu->name())
3761 << " = " << fuOpcodeSignalName(fu->name()) << ";"
3762 << endl;
3763 }
3764 stream << endl;
3765 }
3766
3767 // map pc_load and ra_load signals
3769 if (gcu->hasReturnAddressPort()) {
3770 SpecialRegisterPort* raPort = gcu->returnAddressPort();
3771 stream << indentation(1)
3772 << "assign "
3774 << " = " << fuLoadSignalName(gcu->name(), raPort->name())
3775 << ";" << endl;
3776 }
3777
3778 // find the PC port
3779 FUPort* pcPort = NULL;
3780 if (gcu->hasOperation(CALL)) {
3781 HWOperation* callOp = gcu->operation(CALL);
3782 pcPort = callOp->port(1);
3783 } else if (gcu->hasOperation(JUMP)) {
3784 HWOperation* jumpOp = gcu->operation(JUMP);
3785 pcPort = jumpOp->port(1);
3786 }
3787 if (pcPort != NULL) {
3788 stream << indentation(1)
3789 << "assign "
3791 << " = " << fuLoadSignalName(gcu->name(), pcPort->name())
3792 << ";" << endl;
3793 }
3794
3795 // map pc_opcode signal
3796 if (gcu->hasOperation(JUMP) || gcu->hasOperation(CALL)) {
3797 stream << indentation(1)
3798 << "assign "
3800 << " = " << fuOpcodeSignalName(gcu->name()) << ";" << endl;
3801 }
3802
3803 // map RF control signals
3805 registerFileNavigator();
3806 for (int i = 0; i < rfNav.count(); i++) {
3807 RegisterFile* rf = rfNav.item(i);
3808 for (int i = 0; i < rf->portCount(); i++) {
3809 RFPort* port = rf->port(i);
3810 bool async_signal = sacEnabled(rf->name())
3811 && port->outputSocket() != NULL;
3812
3813 // map load signal
3814 stream << indentation(1)
3815 << "assign "
3816 << rfLoadCntrlPort(rf->name(), port->name()) << " = "
3817 << rfLoadSignalName(rf->name(), port->name(),
3818 async_signal) << ";"
3819 << endl;
3820 // map opcode signal
3821 stream << indentation(1)
3822 << "assign "
3823 << rfOpcodeCntrlPort(rf->name(), port->name())
3824 << " = "
3825 << (rfOpcodeWidth(*rf) == 0 ? "\"0\"" :
3826 rfOpcodeSignalName(rf->name(), port->name(),
3827 async_signal))
3828 << ";"
3829 << endl;
3830 }
3831 }
3832
3835 for (int i = 0; i < iuNav.count(); i++) {
3836 ImmediateUnit* iu = iuNav.item(i);
3837 for (int i = 0; i < iu->portCount(); i++) {
3838 RFPort* port = iu->port(i);
3839
3840 stream << indentation(1) << "assign "
3841 << iuReadLoadCntrlPort(iu->name(), port->name())
3842 << " = "
3843 << iuReadLoadCntrlSignal(iu->name(), port->name())
3844 << ";" << endl;
3845 if (rfOpcodeWidth(*iu) == 0) {
3846 stream << indentation(1) << "assign "
3847 << iuReadOpcodeCntrlPort(iu->name(), port->name())
3848 << " = 1'b0;"
3849 << endl;
3850
3851 } else {
3852 stream << indentation(1) << "assign "
3853 << iuReadOpcodeCntrlPort(iu->name(), port->name())
3854 << " = "
3855 << iuReadOpcodeCntrlSignal(iu->name(), port->name())
3856 << ";" << endl;
3857
3858 }
3859 } // Loop for IU ports
3860 stream << indentation(1) << "assign "
3861 << iuWritePort(iu->name()) << " = "
3862 << iuWriteSignal(iu->name()) << ";" << endl;
3863 stream << indentation(1) << "assign "
3864 << iuWriteLoadCntrlPort(iu->name()) << " = "
3865 << iuWriteLoadCntrlSignal(iu->name()) << ";" << endl;
3866 if (rfOpcodeWidth(*iu) == 0) {
3867 stream << indentation(1) << "assign "
3869 << " = 1'b0;" << endl;
3870 } else {
3871 stream << indentation(1) << "assign "
3873 << " = "
3875 << ";" << endl;
3876 }
3877 } // Loop for IUs
3878
3879
3880 // map socket control signals
3882 for (int i = 0; i < socketNav.count(); i++) {
3883 Socket* socket = socketNav.item(i);
3884 if (socket->portCount() == 0 || socket->segmentCount() == 0) {
3885 continue;
3886 }
3887
3888 if (needsBusControl(*socket)) {
3889 stream << indentation(1)
3890 << "assign "
3891 << socketBusControlPort(socket->name())
3892 << " = " << socketBusCntrlSignalName(socket->name())
3893 << ";" << endl;
3894 }
3895 if (needsDataControl(*socket)) {
3896 stream << indentation(1)
3897 << "assign "
3898 << socketDataControlPort(socket->name())
3899 << " = " << socketDataCntrlSignalName(socket->name())
3900 << ";" << endl;
3901 }
3902 }
3903
3904 // map short immediate signals
3906 for (int i = 0; i < busNav.count(); i++) {
3907 Bus* bus = busNav.item(i);
3908 if (bus->immediateWidth() > 0) {
3909 stream << indentation(1)
3910 << "assign "
3911 << simmControlPort(bus->name())
3912 << " = " << simmCntrlSignalName(bus->name()) << ";"
3913 << endl
3914 << indentation(1)
3915 << "assign "
3916 << simmDataPort(bus->name()) << " = "
3917 << simmDataSignalName(bus->name()) << ";" << endl;
3918 }
3919 }
3920 }
3921}
3922
3923
3924/**
3925 * Writes substitution of guard value to the squash signal of the given
3926 * bus.
3927 *
3928 * @param bus The bus.
3929 * @param enc The guard encoding.
3930 * @param guard The guard.
3931 * @param stream The stream to write.
3932 * @param indLevel The indentation level.
3933 */
3934void
3936 const ProGe::HDL language,
3937 const TTAMachine::Bus& bus,
3938 const GuardEncoding& enc,
3939 const TTAMachine::Guard& guard,
3940 std::ostream& stream,
3941 int indLevel) {
3942 if(language==VHDL){
3943 stream << indentation(indLevel) << "when " << enc.encoding()
3944 << " =>" << endl;
3945 stream << indentation(indLevel+1) << squashSignal(bus.name()) << " <= ";
3946 if (!guard.isInverted()) {
3947 stream << "not ";
3948 }
3949 stream << guardPortName(guard) << ";" << endl;
3950 } else {
3951 stream << indentation(indLevel) << enc.encoding() << " : "
3952 << squashSignal(bus.name()) << " = ";
3953 if (!guard.isInverted()) {
3954 stream << " !";
3955 }
3956 stream << guardPortName(guard) << ";" << endl;
3957 }
3958}
3959
3960
3961/**
3962 * Tells whether the given guard set contains similar guard to the given
3963 * one. Similar means the guard refers to the same FU port.
3964 *
3965 * @param guardSet The guard set.
3966 * @param guard The guard.
3967 * @return True if the set contains similar guard, otherwise false.
3968 */
3969bool
3971 const std::set<TTAMachine::PortGuard*>& guardSet,
3972 const TTAMachine::PortGuard& guard) {
3973
3974 for (std::set<PortGuard*>::const_iterator iter = guardSet.begin();
3975 iter != guardSet.end(); iter++) {
3976 PortGuard* containedGuard = *iter;
3977 if (containedGuard->port() == guard.port()) {
3978 return true;
3979 }
3980 }
3981
3982 return false;
3983}
3984
3985
3986/**
3987 * Tells whether the given guard set contains similar guard to the given
3988 * one. Similar means the guard refers to the same register.
3989 *
3990 * @param guardSet The guard set.
3991 * @param guard The guard.
3992 * @return True if the set contains similar guard, otherwise false.
3993 */
3994bool
3996 const std::set<TTAMachine::RegisterGuard*>& guardSet,
3997 const TTAMachine::RegisterGuard& guard) {
3998
3999 for (std::set<RegisterGuard*>::const_iterator iter = guardSet.begin();
4000 iter != guardSet.end(); iter++) {
4001 RegisterGuard* containedGuard = *iter;
4002 if (containedGuard->registerFile() == guard.registerFile() &&
4003 containedGuard->registerIndex() == guard.registerIndex()) {
4004 return true;
4005 }
4006 }
4007
4008 return false;
4009}
4010
4011
4012/**
4013 * Tells whether the given socket needs controlling from which bus data is
4014 * read or to which it is written.
4015 *
4016 * @param socket The socket.
4017 * @return True if the socket needs controlling, otherwise false.
4018 */
4019bool
4021 if (socket.segmentCount() == 0 || socket.portCount() == 0) {
4022 return false;
4023 }
4024 if (socket.segmentCount() > 1 ||
4025 (socket.segmentCount() == 1 &&
4026 socket.direction() == Socket::OUTPUT)) {
4027 return true;
4028 } else {
4029 return false;
4030 }
4031}
4032
4033
4034/**
4035 * Tells whether the given output socket needs controlling from which
4036 * port the data should be written to a bus.
4037 */
4038bool
4040 if (socket.direction() == Socket::OUTPUT && socket.portCount() > 1) {
4041 return true;
4042 } else {
4043 return false;
4044 }
4045}
4046
4047
4048/**
4049 * Finds the guard that is referred to by the given register guard
4050 * encoding.
4051 *
4052 * @param encoding The encoding.
4053 * @return The guard.
4054 */
4057
4058 GuardField* parent = encoding.parent();
4059 string busName = parent->parent()->name();
4060
4062 Bus* bus = busNav.item(busName);
4063 for (int i = 0; i < bus->guardCount(); i++) {
4064 Guard* guard = bus->guard(i);
4065 RegisterGuard* regGuard = dynamic_cast<RegisterGuard*>(guard);
4066 if (regGuard != NULL) {
4067 if (encoding.registerFile() == regGuard->registerFile()->name()
4068 && encoding.registerIndex() == regGuard->registerIndex() &&
4069 encoding.isGuardInverted() == regGuard->isInverted()) {
4070 return *regGuard;
4071 }
4072 }
4073 }
4074
4075 assert(false);
4076}
4077
4078
4079/**
4080 * Finds the guard that is referred to by the given port guard encoding.
4081 *
4082 * @param encoding The encoding.
4083 * @return The guard.
4084 */
4087
4088 GuardField* parent = encoding.parent();
4089 string busName = parent->parent()->name();
4090
4092 Bus* bus = busNav.item(busName);
4093 for (int i = 0; i < bus->guardCount(); i++) {
4094 Guard* guard = bus->guard(i);
4095 PortGuard* portGuard = dynamic_cast<PortGuard*>(guard);
4096 if (portGuard != NULL) {
4097 if (encoding.functionUnit() ==
4098 portGuard->port()->parentUnit()->name() &&
4099 encoding.port() == portGuard->port()->name() &&
4100 encoding.isGuardInverted() == portGuard->isInverted()) {
4101 return *portGuard;
4102 }
4103 }
4104 }
4105
4106 assert(false);
4107}
4108
4109
4110/**
4111 * Returns the name of the data port for short immediate of the given bus.
4112 *
4113 * @param busName Name of the bus.
4114 * @return The name of the port.
4115 */
4116std::string
4117DefaultDecoderGenerator::simmDataPort(const std::string& busName) {
4118 return "simm_" + busName;
4119}
4120
4121
4122/**
4123 * Returns the name of the control port for short immediate of the given
4124 * bus.
4125 *
4126 * @param busName Name of the bus.
4127 * @return The name of the port.
4128 */
4129std::string
4130DefaultDecoderGenerator::simmControlPort(const std::string& busName) {
4131 return "simm_cntrl_" + busName;
4132}
4133
4134
4135/**
4136 * Returns the required width of the short immediate port of the given bus.
4137 *
4138 * @param bus The bus.
4139 * @return The width of the port.
4140 */
4141int
4143 if (bus.signExtends()) {
4144 return bus.width();
4145 } else if (bus.zeroExtends()) {
4146 return bus.immediateWidth();
4147 } else {
4148 assert(false && "Unknown extension policy.");
4149 return -1;
4150 }
4151}
4152
4153
4154/**
4155 * Returns the name of the short immediate data signal.
4156 *
4157 * @param busName Name of the bus that transports the short immediate.
4158 * @return The name of the signal.
4159 */
4160std::string
4162 return "simm_" + busName + "_reg";
4163}
4164
4165
4166/**
4167 * Returns the name of the short immediate control signal of the given bus.
4168 *
4169 * @param busName Name of the bus.
4170 * @return The name of the signal.
4171 */
4172std::string
4174 return "simm_cntrl_" + busName + "_reg";
4175}
4176
4177
4178/**
4179 * Returns the name of the load control port for the given FU port.
4180 *
4181 * @param fuName Name of the FU.
4182 * @param portName Name of the FU data port.
4183 * @return The name of the load control port in decoder.
4184 */
4185std::string
4187 const std::string& fuName,
4188 const std::string& portName) {
4189
4190 return "fu_" + fuName + "_" + portName + "_load";
4191}
4192
4193
4194/**
4195 * Returns the name for the signal of load control port of the given FU
4196 * port.
4197 *
4198 * @param fuName Name of the FU.
4199 * @param portName Name of the FU data port.
4200 * @return The name of the signal.
4201 */
4202std::string
4204 const std::string& fuName,
4205 const std::string& portName) {
4206
4207 return fuLoadCntrlPort(fuName, portName) + "_reg";
4208}
4209
4210
4211/**
4212 * Returns the name of the opcode control port for the given FU.
4213 *
4214 * @param fu Name of the FU.
4215 * @return The name of the opcode control port in decoder.
4216 */
4217std::string
4219 return "fu_" + fu + "_opc";
4220}
4221
4222
4223/**
4224 * Returns the name for the signal of opcode control port of the given FU.
4225 *
4226 * @param fu Name of the FU.
4227 * @return The name of the opcode control signal.
4228 */
4229std::string
4231 return fuOpcodeCntrlPort(fu) + "_reg";
4232}
4233
4234
4235/**
4236 * Returns the name of the load control port of the given RF data port.
4237 *
4238 * @param rfName Name of the RF.
4239 * @param portName Name of the RF data port.
4240 * @return The name of the load control port in decoder.
4241 */
4242std::string
4244 const std::string& rfName,
4245 const std::string& portName) {
4246
4247 return "rf_" + rfName + "_" + portName + "_load";
4248}
4249
4250
4251/**
4252 * Returns the name for the load control signal for the given RF port.
4253 *
4254 * @param rfName Name of the RF.
4255 * @param portName Name of the RF data port.
4256 * @param async Flag to generate name for asynchronous signal. Default value
4257 * is false.
4258 * @return The name of the signal.
4259 */
4260std::string
4262 const std::string& rfName,
4263 const std::string& portName,
4264 bool async) {
4265
4266 if (async) {
4267 return rfLoadCntrlPort(rfName, portName) + "_wire";
4268 } else {
4269 return rfLoadCntrlPort(rfName, portName) + "_reg";
4270 }
4271}
4272
4273
4274/**
4275 * Returns the name for the signal of opcode control port of the given
4276 * RF port.
4277 *
4278 * @param rfName Name of the register file.
4279 * @param portName Name of the RF data port.
4280 * @param async Flag to generate name for asynchronous signal. Default value
4281 * is false.
4282 * @return The name of the signal.
4283 */
4284std::string
4286 const std::string& rfName,
4287 const std::string& portName,
4288 bool async) {
4289
4290 if (async) {
4291 return rfOpcodeCntrlPort(rfName, portName) + "_wire";
4292 } else {
4293 return rfOpcodeCntrlPort(rfName, portName) + "_reg";
4294 }
4295}
4296
4297/**
4298 * Returns the name of the opcode control port of the given RF port.
4299 *
4300 * @param rfName Name of the RF.
4301 * @param portName Name of the RF data port.
4302 * @return The opcode control port in decoder.
4303 */
4304std::string
4306 const std::string& rfName,
4307 const std::string& portName) {
4308
4309 return "rf_" + rfName + "_" + portName + "_opc";
4310}
4311
4312
4313/**
4314 * Returns the name of the opcode control port of the given IU read port
4315 * in decoder.
4316 *
4317 * @param unitName Name of the IU.
4318 * @param portName Name of the read port.
4319 * @return The name of the opcode control port.
4320 */
4321std::string
4323 const std::string& unitName,
4324 const std::string& portName) {
4325
4326 return "iu_" + unitName + "_" + portName + "_read_opc";
4327}
4328
4329
4330/**
4331 * Returns the name of the opcode control signal of the given IU read port
4332 * in decoder.
4333 *
4334 * @param unitName Name of the IU.
4335 * @param portName Name of the read port.
4336 * @return The name of the opcode control port.
4337 */
4338std::string
4340 const std::string& unitName,
4341 const std::string& portName) {
4342
4343 return iuReadOpcodeCntrlPort(unitName, portName) + "_reg";
4344}
4345
4346
4347/**
4348 * Returns the name of the load control port of the given IU read port in
4349 * in decoder.
4350 *
4351 * @param unitName Name of the IU.
4352 * @param portName Name of the read port.
4353 * @return The name of the load control port.
4354 */
4355std::string
4357 const std::string& unitName,
4358 const std::string& portName) {
4359
4360 return "iu_" + unitName + "_" + portName + "_read_load";
4361}
4362
4363
4364/**
4365 * Returns the name of the load control signal of the given IU read port in
4366 * in decoder.
4367 *
4368 * @param unitName Name of the IU.
4369 * @param portName Name of the read port.
4370 * @return The name of the load control port.
4371 */
4372std::string
4374 const std::string& unitName,
4375 const std::string& portName) {
4376
4377 return iuReadLoadCntrlPort(unitName, portName) + "_reg";
4378}
4379
4380
4381/**
4382 * Returns the name of the IU write port of the given IU in decoder.
4383 *
4384 * @param iuName Name of the IU.
4385 * @return The name of the port.
4386 */
4387std::string
4388DefaultDecoderGenerator::iuWritePort(const std::string& iuName) {
4389 return "iu_" + iuName + "_write";
4390}
4391
4392
4393/**
4394 * Returns the name of the IU write signal of the given IU in decoder.
4395 *
4396 * @param iuName Name of the IU.
4397 * @return The name of the port.
4398 */
4399std::string
4400DefaultDecoderGenerator::iuWriteSignal(const std::string& iuName) {
4401 return iuWritePort(iuName) + "_reg";
4402}
4403
4404
4405/**
4406 * Returns the name of the opcode control port of the write port of the given
4407 * IU in decoder.
4408 *
4409 * @param unitName Name of the IU.
4410 * @return The name of the opcode control port.
4411 */
4412std::string
4414 return iuWritePort(unitName) + "_opc";
4415}
4416
4417
4418/**
4419 * Returns the name of the opcode control signal of the write port of the given
4420 * IU in decoder.
4421 *
4422 * @param unitName Name of the IU.
4423 * @return The name of the opcode control port.
4424 */
4425std::string
4427 const std::string& unitName) {
4428 return iuWriteOpcodeCntrlPort(unitName) + "_reg";
4429}
4430
4431
4432/**
4433 * Returns the name of the load control port of the write port of the given
4434 * IU in decoder.
4435 *
4436 * @param unitName Name of the IU.
4437 * @return The name of the load control port.
4438 */
4439std::string
4441 return iuWritePort(unitName) + "_load";
4442}
4443
4444
4445/**
4446 * Returns the name of the load control Signal of the write port of the given
4447 * IU in decoder.
4448 *
4449 * @param unitName Name of the IU.
4450 * @return The name of the load control port.
4451 */
4452std::string
4454 return iuWriteLoadCntrlPort(unitName) + "_reg";
4455}
4456
4457std::string
4459 return bus.name() + "_src_sel";
4460}
4461
4462std::string
4466
4467std::string
4469 return bus.name() + "_src_ena";
4470}
4471
4472std::string
4476
4477/**
4478 * Returns the name of the signal for the move field of the given bus.
4479 */
4480std::string
4481DefaultDecoderGenerator::moveFieldSignal(const std::string& busName) {
4482 return "move_" + busName;
4483}
4484
4485/**
4486 * Returns the name of the guard port in decoder for the given guard.
4487 *
4488 * @param guard The guard.
4489 * @return The name of the port.
4490 */
4491std::string
4493 const PortGuard* portGuard = dynamic_cast<const PortGuard*>(&guard);
4494 const RegisterGuard* regGuard = dynamic_cast<const RegisterGuard*>(
4495 &guard);
4496 if (portGuard != NULL) {
4497 FUPort* port = portGuard->port();
4498 FunctionUnit* fu = port->parentUnit();
4499 return "fu_guard_" + fu->name() + "_" + port->name();
4500 } else if (regGuard != NULL) {
4501 const RegisterFile* rf = regGuard->registerFile();
4502 return "rf_guard_" + rf->name() + "_" +
4504 } else {
4505 return "";
4506 }
4507}
4508
4509
4510/**
4511 * Returns the name of the bus connection control port of the given
4512 * socket.
4513 *
4514 * @param name Name of the socket.
4515 * @return The name of the control port.
4516 */
4517std::string
4519 return "socket_" + name + "_bus_cntrl";
4520}
4521
4522
4523/**
4524 * Returns the name of the data control port of the given socket.
4525 *
4526 * @param name Name of the socket.
4527 * @return The name of the control port.
4528 */
4529std::string
4531 return "socket_" + name + "_data_cntrl";
4532}
4533
4534
4535/**
4536 * Returns the name of the signal for the source field of the given bus.
4537 *
4538 * @param busName Name of the bus.
4539 * @return The name of the signal.
4540 */
4541std::string
4542DefaultDecoderGenerator::srcFieldSignal(const std::string& busName) {
4543 return "src_" + busName;
4544}
4545
4546
4547/**
4548 * Returns the name of the signal for the destination field of the given
4549 * bus.
4550 *
4551 * @param busName Name of the bus.
4552 * @return The name of the signal.
4553 */
4554std::string
4555DefaultDecoderGenerator::dstFieldSignal(const std::string& busName) {
4556 return "dst_" + busName;
4557}
4558
4559
4560/**
4561 * Returns the name of the signal for the guard field of the given bus.
4562 *
4563 * @param busName Name of the bus.
4564 * @return The name of the signal.
4565 */
4566std::string
4568 return "grd_" + busName;
4569}
4570
4571
4572/**
4573 * Returns the name of the signal for the given immediate slot.
4574 *
4575 * @param immSlot Name of the immediate slot.
4576 * @return The name of the signal.
4577 */
4578std::string
4579DefaultDecoderGenerator::immSlotSignal(const std::string& immSlot) {
4580 return "limmslot_" + immSlot;
4581}
4582
4583
4584/**
4585 * Returns the name of the squash signal for the given bus.
4586 *
4587 * @param busName Name of the bus.
4588 * @return The name of the signal.
4589 */
4590std::string
4591DefaultDecoderGenerator::squashSignal(const std::string& busName) {
4592 return "squash_" + busName;
4593}
4594
4595
4596/**
4597 * Returns the name of the bus connection control signal for the socket
4598 * of the given name.
4599 *
4600 * @param name Name of the socket.
4601 * @return The name of the control signal.
4602 */
4603std::string
4605 return socketBusControlPort(name) + "_reg";
4606}
4607
4608
4609/**
4610 * Returns the name of the data control signal for the socket of the
4611 * given name.
4612 *
4613 * @param name Name of the socket.
4614 * @return The name of the control signal.
4615 */
4616std::string
4618 return socketDataControlPort(name) + "_reg";
4619}
4620
4621
4622/**
4623 * Returns the real name of the GCU data port that has the given name in ADF.
4624 *
4625 * @param nameInADF Name of the port in ADF.
4626 */
4627std::string
4628DefaultDecoderGenerator::gcuDataPort(const std::string& nameInADF) {
4629 return nameInADF;
4630}
4631
4632
4633/**
4634 * Returns the width of the opcode of the given FU.
4635 *
4636 * @param fu The FU.
4637 * @return The width of the operation code.
4638 */
4639int
4641 const TTAMachine::FunctionUnit& fu) const {
4642
4643 if (&fu == machine_.controlUnit()) {
4644 // Derive port width initially set by NetlistGenerator
4645 const NetlistBlock& gcuBlock = nlGenerator_->instructionDecoder();
4647 ->realWidth();
4648 } else {
4649 int ops = fu.operationCount();
4650 return ops > 1 ? static_cast<int>(std::ceil(std::log2(ops))) : 0;
4651 }
4652}
4653
4654
4655/**
4656 * Returns the number of bits required to control the bus connections of
4657 * the given socket.
4658 *
4659 * @param socket The socket.
4660 * @return The control width.
4661 */
4662int
4664 if (socket.direction() == Socket::INPUT) {
4665 return MathTools::bitLength(socket.segmentCount() - 1);
4666 } else {
4667 return socket.segmentCount();
4668 }
4669}
4670
4671
4672/**
4673 * Returns the number of bits required to control from which port the
4674 * data is written to the bus.
4675 *
4676 * @param socket The socket.
4677 * @return The control width.
4678 */
4679int
4681 if (socket.direction() == Socket::OUTPUT) {
4682 return MathTools::bitLength(socket.portCount() - 1);
4683 } else {
4684 return 0;
4685 }
4686}
4687
4688
4689/**
4690 * Returns the width of the opcode port in the given RF.
4691 *
4692 * @param rf The register file.
4693 * @return The bit width of the opcode port.
4694 */
4695int
4699
4700
4701/**
4702 * Returns a set of buses connected to the given socket.
4703 *
4704 * @param socket The socket.
4705 * @return The bus set.
4706 */
4709 BusSet set;
4710 int segmentCount = socket.segmentCount();
4711 for (int i = 0; i < segmentCount; i++) {
4712 set.insert(socket.segment(i)->parentBus());
4713 }
4714 return set;
4715}
4716
4717
4718/**
4719 * Returns the condition when data is transferred by the given socket in the
4720 * given source field.
4721 *
4722 * @param srcField The source field.
4723 * @param socketName Name of the socket.
4724 * @return The conditional clause.
4725 */
4726std::string
4728 const ProGe::HDL language,
4729 const SlotField& slotField,
4730 const std::string& socketName) {
4731
4732 string signalName;
4733 if (dynamic_cast<const SourceField*>(&slotField) != NULL) {
4734 signalName = srcFieldSignal(slotField.parent()->name());
4735 } else {
4736 signalName = dstFieldSignal(slotField.parent()->name());
4737 }
4738 SocketEncoding& enc = slotField.socketEncoding(socketName);
4739 int start = enc.socketIDPosition();
4740 int end = start + enc.socketIDWidth() - 1;
4741 if (language == VHDL) {
4742 if (enc.socketIDWidth() == 0) {
4743 return "true";
4744 } else {
4745 return "conv_integer(unsigned(" + signalName + "("
4746 + Conversion::toString(end) + " downto "
4747 + Conversion::toString(start)
4748 + "))) = " + Conversion::toString(enc.encoding());
4749 }
4750 } else {
4751 if (enc.socketIDWidth() == 0) {
4752 return "1";
4753 } else {
4754 return signalName + "["
4755 + Conversion::toString(end) + " : "
4756 + Conversion::toString(start)
4757 + "] == " + Conversion::toString(enc.encoding());
4758 }
4759 }
4760}
4761
4762
4763/**
4764 * Returns the condition when given port code of the given socket encoding is
4765 * true.
4766 *
4767 * @param socketEnc The socket encoding;
4768 * @param code The RF port code.
4769 * @return The condition.
4770 */
4771std::string
4773 const ProGe::HDL language,
4774 const SocketEncoding& socketEnc,
4775 const PortCode& code) {
4776
4777 // empty encoding is always true
4778 if (!code.encodingWidth()) {
4779 if (language==VHDL) {
4780 return "true";
4781 } else {
4782 return "1";
4783 }
4784 }
4785 SlotField* parent = socketEnc.parent();
4786 string signalName;
4787 if (dynamic_cast<SourceField*>(parent) != NULL) {
4788 signalName = srcFieldSignal(parent->parent()->name());
4789 } else {
4790 signalName = dstFieldSignal(parent->parent()->name());
4791 }
4792
4793 int codeStart;
4794 if (parent->componentIDPosition() == BinaryEncoding::RIGHT) {
4795 codeStart = socketEnc.socketIDWidth() + code.indexWidth();
4796 } else {
4797 codeStart = code.indexWidth();
4798 }
4799 int codeEnd = codeStart + code.encodingWidth() - 1;
4800 assert(codeEnd >= codeStart);
4801
4802 if(language==VHDL)
4803 return "conv_integer(unsigned(" + signalName + "(" +
4804 Conversion::toString(codeEnd) + " downto " +
4805 Conversion::toString(codeStart) + "))) = " +
4807 else
4808 return signalName + "[" +
4809 Conversion::toString(codeEnd) + " : " +
4810 Conversion::toString(codeStart) + "] == " +
4812}
4813
4814
4815/**
4816 * Returns the condition when the instruction is of the given template.
4817 *
4818 * @param iTempName Name of the instruction template.
4819 * @return The condition.
4820 */
4821std::string
4823 const ProGe::HDL language,
4824 const std::string& iTempName) const {
4825
4828 assert(field.hasTemplateEncoding(iTempName));
4829 if(language==VHDL)
4830 return "conv_integer(unsigned(" + LIMM_TAG_SIGNAL + ")) = "
4831 + Conversion::toString(field.templateEncoding(iTempName));
4832 else
4833 return LIMM_TAG_SIGNAL + " == "
4834 + Conversion::toString(field.templateEncoding(iTempName));
4835}
4836
4837
4838/**
4839 * Returns the part of the source or destination field signal that contains the
4840 * opcode of the given RF port code.
4841 *
4842 * @param socketEnc The socket encoding.
4843 * @param code The RF port code.
4844 * @return The part of the source or destination field signal.
4845 */
4846std::string
4848 const ProGe::HDL language,
4849 const SocketEncoding& socketEnc,
4850 const PortCode& code) {
4851
4852 SlotField* slotField = socketEnc.parent();
4853 string signalName;
4854 if (dynamic_cast<SourceField*>(slotField) != NULL) {
4855 signalName = srcFieldSignal(slotField->parent()->name());
4856 } else {
4857 signalName = dstFieldSignal(slotField->parent()->name());
4858 }
4859
4860 int opcStart;
4861 SocketCodeTable& table = socketEnc.socketCodes();
4862 if (slotField->componentIDPosition() == BinaryEncoding::RIGHT) {
4863 opcStart = slotField->width() - table.width();
4864 } else {
4865 opcStart = 0;
4866 }
4867 int opcEnd = opcStart + code.indexWidth() - 1;
4868 if(language==VHDL)
4869 return signalName + "(" + Conversion::toString(opcEnd) + " downto " +
4870 Conversion::toString(opcStart) + ")";
4871 else
4872 return signalName + "[" + Conversion::toString(opcEnd) + " : " +
4873 Conversion::toString(opcStart) + "]";
4874}
4875
4876
4877/**
4878 * Returns the signal pin that controls the bus of the given output socket.
4879 *
4880 * @param socket The socket.
4881 * @param bus The bus.
4882 * @return The signal pin.
4883 */
4884std::string
4886 const TTAMachine::Socket& socket,
4887 const TTAMachine::Bus& bus) const {
4888
4889 assert(socket.direction() == Socket::OUTPUT);
4891 socket, *bus.segment(0));
4892 return socketBusCntrlSignalName(socket.name())
4893 + ((language_==VHDL)?"(":"[")
4895 + ((language_==VHDL)?")":"]");
4896}
4897
4898
4899/**
4900 * Returns the opcode of the given operation.
4901 *
4902 * @param operation The operation.
4903 * @return The opcode.
4904 */
4905int
4907 const TTAMachine::HWOperation& operation) const {
4908
4909 string fuName = operation.parentUnit()->name();
4910 if (fuName == machine_.controlUnit()->name()) {
4911 return CUOpcodeGenerator(machine_).encoding(operation.name());
4912 } else {
4913 // This will make all opcodes based on their alphabetical order!
4914 FunctionUnit* fu =
4915 dynamic_cast<FunctionUnit*>(operation.parentUnit());
4916 std::vector<std::string> operations;
4917 for (int i = 0; i < fu->operationCount(); ++i) {
4918 operations.emplace_back(fu->operation(i)->name());
4919 }
4920 std::sort(operations.begin(), operations.end());
4921 for (size_t i = 0; i < operations.size(); ++i) {
4922 if (operations[i] == operation.name()) {
4923 return i;
4924 }
4925 }
4926 }
4927 assert(false && "should not get here");
4928 return -1; //
4929}
4930
4931/**
4932 * Generates an indentation of the given level.
4933 *
4934 * @param level The level.
4935 */
4936std::string
4938 string indentation("");
4939 for (unsigned int i = 0; i < level; i++) {
4940 indentation += " ";
4941 }
4942 return indentation;
4943}
4944
4945/**
4946 * Queries if given register file by name has separate address cycle (SAC)
4947 * flag enabled.
4948 *
4949 * @param rfName Name of register file in ADF.
4950 * @return Status of the SAC flag.
4951 */
4952bool
4953DefaultDecoderGenerator::sacEnabled(const string& rfName) const
4954{
4955 assert(nlGenerator_ != NULL);
4956 const RFEntry& rfEntry = nlGenerator_->rfEntry(rfName);
4958}
#define __func__
#define assert(condition)
const string BLER
const string BGTUR
const string INTERNAL_MERGED_GLOCK_REQ_SIGNAL
const string PRE_DECODE_MERGED_GLOCK_SIGNAL
const string CALLA
const string POST_DECODE_MERGED_GLOCK_OUTREG
const string LOCK_REQ_PORT_NAME
const string BLEUR
const string BLTUR
const string BGTU
const string JUMPR
const string CALLR
const string BNER
const string BZ
const string BNE
const string BLTU
const string BLT
const string BLEU
const string BEQ
const string JUMP
const string BNZ
const string BLTR
const string BGT
const string PIPELINE_FILL_LOCK_SIGNAL
const string BNZ1
const string BGER
const string POST_DECODE_MERGED_GLOCK_SIGNAL
const string APC
const string BGEUR
const string GLOCK_PORT_NAME
const string BGEU
const string BGE
const string BLE
const string LIMM_TAG_SIGNAL
const string BGTR
const string BZ1
const string BEQR
const string CALL
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
find Finds info of the inner loops in the false
#define DS
const string JUMP
const string CALL
ImmediateControlField & immediateControlField() const
LImmDstRegisterField & longImmDstRegisterField(int index) const
int moveSlotCount() const
int immediateSlotCount() const
MoveSlot & moveSlot(int index) const
ImmediateSlotField & immediateSlot(int index) const
bool hasMoveSlot(const std::string &name) const
bool hasImmediateControlField() const
virtual int inputSocketControlValue(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment) const =0
ProGe::NetlistPort & busCntrlPortOfSocket(const std::string &socketName) const
virtual int outputSocketDataControlValue(const TTAMachine::Socket &socket, const TTAMachine::Port &port) const =0
virtual int outputSocketCntrlPinForSegment(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment) const =0
ProGe::NetlistPort & dataCntrlPortOfSocket(const std::string &socketName) const
ProGe::NetlistPort & simmDataPort(const std::string &busName) const
static std::string toString(const T &source)
void writeImmediateSlotSignals(std::ostream &stream) const
static std::string busMuxEnableRegister(const TTAMachine::Bus &bus)
bool generateAlternateGlockReqHandling_
The flag to generate global lock request handling in decoder. False means delegating the lock request...
static std::string socketDataControlPort(const std::string &name)
static void writeSquashSignalSubstitution(const ProGe::HDL language, const TTAMachine::Bus &bus, const GuardEncoding &enc, const TTAMachine::Guard &guard, std::ostream &stream, int indLevel)
void writeMainDecodingProcess(std::ostream &stream) const
static std::string guardFieldSignal(const std::string &busName)
void writeControlRulesOfRFWritePort(const TTAMachine::RFPort &port, std::ostream &stream) const
static std::string indentation(unsigned int level)
std::string instructionTemplateCondition(const ProGe::HDL language, const std::string &iTempName) const
static std::string squashSignal(const std::string &busName)
static std::string iuWriteLoadCntrlSignal(const std::string &unitName)
void writeResettingOfControlRegisters(std::ostream &stream) const
TTAMachine::RegisterGuard & findGuard(const GPRGuardEncoding &encoding) const
unsigned int lockTraceStartingCycle_
The starting cycle for bus tracing.
void writeSimmDataSignal(const TTAMachine::Bus &bus, std::ostream &stream) const
void writeSignalDeclaration(std::ostream &stream, ProGe::DataType type, std::string sigName, int width) const
void completeDecoderBlock(const ProGe::NetlistGenerator &nlGenerator, ProGe::NetlistBlock &coreBlock)
static BusSet connectedBuses(const TTAMachine::Socket &socket)
static std::string iuWriteOpcodeCntrlPort(const std::string &unitName)
void writeInstructionTemplateProcedures(const ProGe::HDL language, const TTAMachine::InstructionTemplate &iTemp, int indLevel, std::ostream &stream) const
static const std::string RISCV_SIMM_PORT_IN_NAME
static std::string busMuxCntrlSignal(const TTAMachine::Bus &bus)
const CentralizedControlICGenerator & icGenerator_
The IC generator.
static int busControlWidth(const TTAMachine::Socket &socket)
void writeInstructionDismembering(std::ostream &stream) const
UnitGlockReqBitMapType unitGlockReqBitMap_
Maps TTA Units to associated glock request port bits.
static std::string fuLoadCntrlPort(const std::string &fuName, const std::string &portName)
ProGe::NetlistBlock * decoderBlock_
The instruction decoder block in the netlist.
static std::string moveFieldSignal(const std::string &busName)
void writeLongImmediateWriteProcess(std::ostream &stream) const
const BinaryEncoding & bem_
The binary encoding map.
bool syncReset_
Reset synchronously (otherwise asynchronous)
void writeRFSRAMDecodingProcess(std::ostream &stream) const
static std::string iuWriteSignal(const std::string &iuName)
static int rfOpcodeWidth(const TTAMachine::BaseRegisterFile &rf)
std::set< TTAMachine::Bus * > BusSet
Set type for buses.
static std::string iuWriteLoadCntrlPort(const std::string &unitName)
void SetHDL(ProGe::HDL language)
static std::string dstFieldSignal(const std::string &busName)
void writeGlockHandlingSignals(std::ostream &stream) const
static std::string socketEncodingCondition(const ProGe::HDL language, const SlotField &srcField, const std::string &socketName)
void writeInstructionDecoder(std::ostream &stream)
void writeSquashSignalGenerationProcesses(std::ostream &stream) const
static std::string rfOpcodeSignalName(const std::string &rfName, const std::string &portName, bool async=false)
void writePipelineFillProcess(std::ostream &stream) const
static std::string rfLoadCntrlPort(const std::string &rfName, const std::string &portName)
static std::string simmCntrlSignalName(const std::string &busName)
void writeSquashSignalGenerationProcess(const TTAMachine::Bus &bus, std::ostream &stream) const
static std::string iuReadLoadCntrlPort(const std::string &unitName, const std::string &portName)
void writeSocketCntrlSignals(std::ostream &stream)
static std::string iuWritePort(const std::string &iuName)
static std::string iuReadOpcodeCntrlSignal(const std::string &unitName, const std::string &portName)
static std::string iuReadOpcodeCntrlPort(const std::string &unitName, const std::string &portName)
void writeInstructionDecoding(std::ostream &stream) const
static bool containsSimilarGuard(const std::set< TTAMachine::PortGuard * > &guardSet, const TTAMachine::PortGuard &guard)
static std::string portCodeCondition(const ProGe::HDL language, const SocketEncoding &socketEnc, const PortCode &code)
void writeSquashSignals(std::ostream &stream) const
static std::string rfOpcodeCntrlPort(const std::string &rfName, const std::string &portName)
bool sacEnabled(const std::string &rfName) const
static int dataControlWidth(const TTAMachine::Socket &socket)
void writeRulesForDestinationControlSignals(std::ostream &stream) const
static std::string immSlotSignal(const std::string &immSlot)
void writeComment(std::ostream &stream, int indent, std::string comment) const
static std::string fuOpcodeSignalName(const std::string &fu)
void setLockTraceStartingCycle(unsigned int startCycle)
void writePipelineFillSignals(std::ostream &stream) const
static std::string simmDataPort(const std::string &busName)
static std::string gcuDataPort(const std::string &nameInADF)
std::vector< std::string > registerVectors
Bookkeeping for reset-needing signals.
static std::string socketBusControlPort(const std::string &name)
UnitGlockBitMapType unitGlockBitMap_
Maps connected glock port bits to associated TTA Units.
void writeMoveFieldSignals(std::ostream &stream) const
bool generateDebugger_
Generate debugger signals?
void writeBusControlRulesOfSImmSocketOfBus(const TTAMachine::Bus &bus, std::ostream &stream) const
void writeControlRulesOfFUInputPort(const TTAMachine::BaseFUPort &port, std::ostream &stream) const
static std::string iuWriteOpcodeCntrlSignal(const std::string &unitName)
static std::string rfLoadSignalName(const std::string &rfName, const std::string &portName, bool async=false)
void writeLockDumpCode(std::ostream &stream) const
void writeDecompressSignalsVHDL(std::ostream& stream) const; TBR
static const std::string GLOCK_PORT_NAME
static std::string rfOpcodeFromSrcOrDstField(const ProGe::HDL language, const SocketEncoding &socketEnc, const PortCode &code)
static bool needsDataControl(const TTAMachine::Socket &socket)
void writeGlockMapping(std::ostream &stream) const
static int simmPortWidth(const TTAMachine::Bus &bus)
const ProGe::NetlistGenerator * nlGenerator_
The netlist generator.
void generateInstructionDecoder(const ProGe::NetlistGenerator &nlGenerator, const std::string &dstDirectory)
void writeRulesForSourceControlSignals(std::ostream &stream) const
void writeRFCntrlSignals(std::ostream &stream)
std::set< int > requiredRFLatencies(const TTAMachine::ImmediateUnit &iu) const
void setGenerateLockTrace(bool generate)
std::string busCntrlSignalPinOfSocket(const TTAMachine::Socket &socket, const TTAMachine::Bus &bus) const
static std::string socketDataCntrlSignalName(const std::string &name)
void setGenerateNoLoopbackGlock(bool generate)
int GlockBitType
Types for mapping global lock and global lock request signals.
void writeControlRulesOfRFReadPort(const TTAMachine::RFPort &port, std::ostream &stream) const
static std::string socketBusCntrlSignalName(const std::string &name)
static std::string srcFieldSignal(const std::string &busName)
static std::string fuLoadSignalName(const std::string &fuName, const std::string &portName)
int opcode(const TTAMachine::HWOperation &operation) const
void writeControlRulesOfFUOutputPort(const TTAMachine::BaseFUPort &port, std::ostream &stream) const
static std::string fuOpcodeCntrlPort(const std::string &fu)
static std::string guardPortName(const TTAMachine::Guard &guard)
DefaultDecoderGenerator(const TTAMachine::Machine &machine, const BinaryEncoding &bem, const CentralizedControlICGenerator &icGenerator)
std::vector< std::string > registerBits
static std::string iuReadLoadCntrlSignal(const std::string &unitName, const std::string &portName)
static bool needsBusControl(const TTAMachine::Socket &socket)
static std::string simmControlPort(const std::string &busName)
void setGenerateDebugger(bool generate)
void writeLongImmediateTagSignal(std::ostream &stream) const
static std::string simmDataSignalName(const std::string &busName)
bool generateLockTrace_
Tells whether to generate global lock tracing code.
static std::string busMuxCntrlRegister(const TTAMachine::Bus &bus)
static std::string busMuxEnableSignal(const TTAMachine::Bus &bus)
bool generateBusEnable_
Bus enable signals for bustrace.
void writeControlRegisterMappings(std::ostream &stream) const
int opcodeWidth(const TTAMachine::FunctionUnit &fu) const
void writeFUCntrlSignals(std::ostream &stream)
const TTAMachine::Machine & machine_
The machine.
void writeBusControlRulesOfOutputSocket(const TTAMachine::Socket &socket, std::ostream &stream) const
unsigned int encoding() const
Definition Encoding.cc:108
std::string port() const
std::string functionUnit() const
static bool createFile(const std::string &file)
static const std::string DIRECTORY_SEPARATOR
int registerIndex() const
std::string registerFile() const
GuardField * parent() const
unsigned int encoding() const
bool isGuardInverted() const
FUGuardEncoding & fuGuardEncoding(int index) const
bool hasUnconditionalGuardEncoding(bool inverted) const
int gprGuardEncodingCount() const
UnconditionalGuardEncoding & unconditionalGuardEncoding(bool inverted) const
GPRGuardEncoding & gprGuardEncoding(int index) const
virtual int width() const
int fuGuardEncodingCount() const
MoveSlot * parent() const
RFImplementation & implementation() const
Definition RFEntry.cc:102
bool separateAddressCycleParameter() const
unsigned int templateEncoding(const std::string &name) const
bool hasTemplateEncoding(const std::string &name) const
int immediatePosition() const
virtual int width() const
std::string name() const
static std::set< TTAMachine::InstructionTemplate * > templatesUsingSlot(const TTAMachine::Machine &mach, const std::string &slotName)
TCETools::CIStringSet OperationSet
static OperationSet getOpset(const TTAMachine::Machine &mach)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
static unsigned int bitLength(long unsigned int number)
SourceField & sourceField() const
Definition MoveSlot.cc:277
DestinationField & destinationField() const
Definition MoveSlot.cc:341
virtual int width() const
Definition MoveSlot.cc:406
std::string name() const
Definition MoveSlot.cc:136
GuardField & guardField() const
Definition MoveSlot.cc:215
bool hasSourceField() const
Definition MoveSlot.cc:264
bool hasDestinationField() const
Definition MoveSlot.cc:327
bool hasGuardField() const
Definition MoveSlot.cc:202
bool hasEncoding() const
Definition PortCode.cc:151
int indexWidth() const
Definition PortCode.cc:215
int encodingWidth() const
Definition PortCode.cc:204
unsigned int encoding() const
Definition PortCode.cc:164
virtual bool hasParentBlock() const
const std::string & moduleName() const
size_t encoding(const std::string &operName) const
virtual NetlistPort * port(const std::string &portName, bool partialMatch=true)
virtual const NetlistBlock & parentBlock() const override
virtual const Netlist & netlist() const
NetlistPort & fuGuardPort(const NetlistPort &fuPort) const
static const std::string DECODER_LOCK_REQ_OUT_PORT
Lock request out port name in instruction decoder.
NetlistBlock & netlistBlock(const TTAMachine::Unit &unit) const
static const std::string DECODER_PC_LOAD_PORT
PC load port name in instruction decoder.
NetlistPort & loadPort(const NetlistPort &port) const
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.
static const std::string DECODER_RA_LOAD_PORT
RA load port name in instruction decoder.
NetlistPort & rfOpcodePort(const NetlistPort &port) const
bool hasGlockReqPort(const NetlistBlock &block) const
NetlistBlock & instructionDecoder() const
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
NetlistPort & netlistPort(const TTAMachine::Port &port, Direction dir=IN) const
bool hasOpcodePort(const NetlistPort &port) const
NetlistPort & fuOpcodePort(const NetlistBlock &fuBlock) const
NetlistPort & glockPort(const NetlistBlock &block) const
NetlistPort & rfGuardPort(const NetlistBlock &rfBlock) const
HDB::RFEntry & rfEntry(const std::string &rfName) const
static const std::string DECODER_LOCK_STATUS_PORT
static const std::string DECODER_RESET_PORT
Reset port name in instruction decoder.
std::string widthFormula() const
Direction direction() const
int realWidth() const
bool connect(const NetlistPort &port1, const NetlistPort &port2, int port1FirstBit, int port2FirstBit, int width=1)
Definition Netlist.cc:83
static void writePortDeclaration(const BaseNetlistBlock &block, unsigned int indentationLevel, const std::string &indentation, std::ostream &stream)
static void writeGenericDeclaration(const BaseNetlistBlock &block, unsigned int indentationLevel, const std::string &indentation, std::ostream &stream)
static void writeGenericDeclaration(const BaseNetlistBlock &block, unsigned int indentationLevel, const std::string &indentation, std::ostream &stream)
static void writePortDeclaration(const BaseNetlistBlock &block, unsigned int indentationLevel, const std::string &indentation, std::ostream &stream)
MoveSlot * parent() const
Definition SlotField.cc:98
virtual int width() const
Definition SlotField.cc:307
SocketEncoding & socketEncoding(int index) const
Definition SlotField.cc:170
BinaryEncoding::Position componentIDPosition() const
Definition SlotField.cc:296
FUPortCode & fuPortCode(int index) const
RFPortCode & rfPortCode(int index) const
IUPortCode & iuPortCode(int index) const
SocketCodeTable & socketCodes() const
bool hasSocketCodes() const
int socketIDWidth() const
SlotField * parent() const
int socketIDPosition() const
virtual int width() const
ImmediateEncoding & immediateEncoding() const
bool hasImmediateEncoding() const
static std::string & appendToNonEmpty(std::string &toAppend, stringCRef appender)
Definition TCEString.cc:201
static std::string makeString(const IterableContainer &container, const std::string &separator=", ")
FunctionUnit * parentUnit() const
Definition BaseFUPort.cc:96
virtual bool isOpcodeSetting() const =0
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
int immediateWidth() const
Definition Bus.cc:160
bool signExtends() const
Definition Bus.cc:171
Guard * guard(int index) const
Definition Bus.cc:456
bool zeroExtends() const
Definition Bus.cc:182
int guardCount() const
Definition Bus.cc:441
virtual TCEString name() const
SpecialRegisterPort * returnAddressPort() const
bool hasReturnAddressPort() const
int globalGuardLatency() const
virtual BaseFUPort * triggerPort() const
virtual HWOperation * operation(const std::string &name) const
virtual int operationCount() const
virtual bool hasOperation(const std::string &name) const
virtual BaseFUPort * port(const std::string &name) const
virtual bool isInverted() const
virtual FUPort * port(int operand) const
const std::string & name() const
FunctionUnit * parentUnit() const
virtual Machine::Extension extensionMode() const
virtual bool isOneOfDestinations(const ImmediateUnit &dstUnit) const
virtual int numberOfSlots(const ImmediateUnit &dstUnit) const
virtual std::string slotOfDestination(const ImmediateUnit &dstUnit, int index) 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 InstructionTemplateNavigator instructionTemplateNavigator() const
Definition Machine.cc:428
virtual SocketNavigator socketNavigator() const
Definition Machine.cc:368
bool hasOperation(const TCEString &opName) const
Definition Machine.cc:1042
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
@ SIGN
Sign extension.
Definition Machine.hh:82
bool isRISCVMachine() const
Definition Machine.cc:1057
FUPort * port() const
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 Socket * inputSocket() const
Definition Port.cc:261
virtual std::string name() const
Definition Port.cc:141
BaseRegisterFile * parentUnit() const
Definition RFPort.cc:93
const RegisterFile * registerFile() 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
Direction direction() const
Segment * segment(int index) const
Definition Socket.cc:401
int segmentCount() const
int portCount() const
virtual int portCount() const
Definition Unit.cc:135
virtual int outputPortCount(bool countBidir=false) const
Definition Unit.cc:145
Definition FUGen.hh:54
DataType
Data types of hardware ports.
Definition ProGeTypes.hh:46
@ BIT
One bit.
Definition ProGeTypes.hh:47
@ BIT_VECTOR
Several bits.
Definition ProGeTypes.hh:48
@ OUT
Output port.
Definition ProGeTypes.hh:54
@ IN
Input port.
Definition ProGeTypes.hh:53
HDL
HDLs supported by ProGe.
Definition ProGeTypes.hh:40
@ Verilog
Verilog.
Definition ProGeTypes.hh:42
@ VHDL
VHDL.
Definition ProGeTypes.hh:41