OpenASIP 2.2
Loading...
Searching...
No Matches
DefaultICGenerator.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2011 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 DefaultICGenerator.cc
26 *
27 * Implementation of DefaultICGenerator class.
28 *
29 * @author Lasse Laasonen 2005 (lasse.laasonen-no.spam-tut.fi)
30 * @author Otto Esko 2008 (otto.esko-no.spam-tut.fi)
31 * @author Pekka Jääskeläinen 2011
32 * @author Vinogradov Viacheslav(added Verilog generating) 2012
33 * @author Henry Linjamäki 2014-2017 (henry.linjamaki-no.spam-tut.fi)
34 * @note rating: red
35 */
36
37#include <string>
38#include <fstream>
39#include <iostream>
40#include <boost/format.hpp>
41
42#include "DefaultICGenerator.hh"
43#include "HDBTypes.hh"
44
45#include "NetlistBlock.hh"
46#include "Netlist.hh"
47#include "NetlistPort.hh"
48#include "NetlistGenerator.hh"
49#include "VHDLNetlistWriter.hh"
51
52#include "Machine.hh"
53#include "Socket.hh"
54#include "Segment.hh"
55#include "ControlUnit.hh"
57
58#include "Conversion.hh"
59#include "FileSystem.hh"
60#include "MathTools.hh"
61#include "MapTools.hh"
62#include "AssocTools.hh"
63
64using namespace ProGe;
65using namespace TTAMachine;
66using std::string;
67using std::endl;
68
69const string INPUT_SOCKET_DATAW_GENERIC = "DATAW";
70const string INPUT_SOCKET_DATA_PORT = "data";
71const string SOCKET_BUS_CONTROL_PORT = "databus_cntrl";
72const string SOCKET_DATA_CONTROL_PORT = "data_cntrl";
73
74/**
75 * The constructor.
76 *
77 * Generates the inteconnection network of the given machine.
78 *
79 * @param machine The machine.
80 */
82 : machine_(machine),
83 icBlock_(NULL),
84 generateBusTrace_(false),
85 exportBustrace_(false),
86 busTraceStartingCycle_(0) {}
87
88/**
89 * The destructor.
90 */
92 for (BusAltSignalMap::iterator iter = altSignalMap_.begin();
93 iter != altSignalMap_.end(); iter++) {
94 delete (*iter).second;
95 }
96}
97
98/**
99 * Set HDL
100 * @param language
101 */
102void
104 language_= language;
105}
106/**
107 * Adds the interconnection network block under the given netlist block
108 * representing the TTA core and connects it to the FUs, RFs and IUs.
109 *
110 * @param generator The netlist generator which generated the netlist block.
111 * @param coreBlock The netlist block.
112 */
113void
115 const ProGe::NetlistGenerator& generator,
116 ProGe::NetlistBlock& coreBlock) {
117 entityNameStr_ = coreBlock.moduleName();
118 NetlistBlock* icBlock =
119 new NetlistBlock(entityNameStr_ + "_" + "interconn", "ic");
120 icBlock_ = icBlock;
121 coreBlock.addSubBlock(icBlock);
123
124 // Add clock, reset port and glock port
125 NetlistPort* tlClkPort =
127 NetlistPort* icClkPort = new NetlistPort(
129 coreBlock.netlist().connect(*icClkPort, *tlClkPort);
130
131 NetlistPort* tlResetPort =
133 NetlistPort* icResetPort = new NetlistPort(
135 coreBlock.netlist().connect(*icResetPort, *tlResetPort);
136
137 NetlistPort* icGlockPort =
138 new NetlistPort("glock", "1", BIT, ProGe::IN, *icBlock);
139 setGlockPort(*icGlockPort);
140
141 // add data ports and control ports for sockets
143 for (int i = 0; i < socketNav.count(); i++) {
144 Socket* socket = socketNav.item(i);
145 if (socket->segmentCount() == 0 || socket->portCount() == 0) {
146 continue;
147 }
148
149 ProGe::Direction socketDirection =
150 convertDirection(socket->direction());
151
152 // add the data port(s)
153 if (socket->direction() == Socket::INPUT) {
154 int width = inputSocketDataPortWidth(*socket);
155 if (width == 0) {
157 (boost::format(
158 "data port of the input socket %s is zero!\n") %
159 socket->name())
160 .str());
161 }
162 NetlistPort* socketDataPort = NULL;
163
164 // connect the data port to the units
165 for (int i = 0; i < socket->portCount(); i++) {
166 Port* port = socket->port(i);
167 NetlistPort* unitPort;
168 // RISCV must have 32b pc port due to APC operation
169 if (machine_.isRISCVMachine() && port == gcu->triggerPort()) {
170 socketDataPort = new NetlistPort(
171 this->inputSocketDataPort(socket->name()),
173 socketDirection, *icBlock);
174 }
175 // gcu ports pc and ra must use IMEMADDRWIDTH as width
176 else if (
177 isGcuPort(port) && (port == gcu->triggerPort() ||
178 port == gcu->returnAddressPort())) {
179 socket->setDataPortWidth("IMEMADDRWIDTH");
180 socketDataPort = new NetlistPort(
181 this->inputSocketDataPort(socket->name()),
182 "IMEMADDRWIDTH", ProGe::BIT_VECTOR,
183 socketDirection, *icBlock);
184 } else {
185 socketDataPort = new NetlistPort(
186 this->inputSocketDataPort(socket->name()),
188 socketDirection, *icBlock);
189 }
190
191 // RA port of GCU is special case
192 if (gcu->hasReturnAddressPort() &&
193 port == gcu->returnAddressPort()) {
194 unitPort = &generator.gcuReturnAddressInPort();
195 } else {
196 unitPort = &generator.netlistPort(*port, ProGe::IN);
197 }
198 coreBlock.netlist().connect(*socketDataPort, *unitPort);
199 }
200 } else {
201 for (int i = 0; i < socket->portCount(); i++) {
202 int width = outputSocketDataPortWidth(*socket, i);
203 assert(width > 0);
204 NetlistPort* socketDataPort = NULL;
205
206 // connect the data port to the unit
207 Port* port = socket->port(i);
208 NetlistPort* unitPort;
209 // gcu ports are treated differently
210 if (isGcuPort(port) && port == gcu->returnAddressPort()) {
211 socket->setDataPortWidth("IMEMADDRWIDTH");
212 socketDataPort = new NetlistPort(
213 outputSocketDataPort(socket->name(), i),
214 "IMEMADDRWIDTH", ProGe::BIT_VECTOR,
215 socketDirection, *icBlock);
216 } else {
217 socketDataPort = new NetlistPort(
218 outputSocketDataPort(socket->name(), i),
220 socketDirection, *icBlock);
221 }
222
223 // RA port of GCU is special case
224 if (gcu->hasReturnAddressPort() &&
225 port == gcu->returnAddressPort()) {
226 unitPort = &generator.gcuReturnAddressOutPort();
227 } else {
228 unitPort = &generator.netlistPort(*port, ProGe::OUT);
229 }
230 coreBlock.netlist().connect(*socketDataPort, *unitPort);
231 }
232 }
233
234 // add control ports
235 if (busControlWidth(
236 socket->direction(), socket->segmentCount()) > 0) {
237 int cntrlWidth = busControlWidth(
238 socket->direction(), socket->segmentCount());
239 assert(cntrlWidth > 0);
240 NetlistPort* icSocketCntrlPort = new NetlistPort(
241 socketBusControlPort(socket->name()),
242 Conversion::toString(cntrlWidth), cntrlWidth,
243 ProGe::BIT_VECTOR, ProGe::IN, *icBlock);
244 mapBusCntrlPortOfSocket(socket->name(), *icSocketCntrlPort);
245 }
246 if (dataControlWidth(socket->direction(), socket->portCount()) > 0) {
247 int cntrlWidth = dataControlWidth(
248 socket->direction(), socket->portCount());
249 assert(cntrlWidth > 0);
250 NetlistPort* icSocketCntrlPort = new NetlistPort(
251 socketDataControlPort(socket->name()),
252 Conversion::toString(cntrlWidth), cntrlWidth,
253 ProGe::BIT_VECTOR, ProGe::IN, *icBlock);
254 mapDataCntrlPortOfSocket(socket->name(), *icSocketCntrlPort);
255 }
256 }
257
258 // add ports for short immediates to IC
260 for (int i = 0; i < busNav.count(); i++) {
261 Bus* bus = busNav.item(i);
262 if (bus->immediateWidth() > 0) {
263 NetlistPort* icSimmPort = new NetlistPort(
264 simmDataPort(bus->name()),
266 simmPortWidth(*bus), ProGe::BIT_VECTOR, ProGe::IN, *icBlock);
267 mapSImmDataPort(bus->name(), *icSimmPort);
268 NetlistPort* icSimmCntrlPort = new NetlistPort(
269 simmControlPort(bus->name()), "1", 1, ProGe::BIT_VECTOR,
270 ProGe::IN, *icBlock);
271 mapSImmCntrlPort(bus->name(), *icSimmCntrlPort);
272 }
273 }
274}
275
276/**
277 * Generates the interconnection network to the given destination directory.
278 *
279 * @param dstDirectory The destination directory.
280 * @exception IOException If an IO error occurs.
281 */
282void
284 const std::string& dstDirectory) {
285 generateSocketsAndMuxes(dstDirectory);
286
287 // generate interconnection network
288 string icFile = dstDirectory + FileSystem::DIRECTORY_SEPARATOR +
289 ((language_==Verilog)?"ic.v":"ic.vhdl");
290 bool icCreated = FileSystem::createFile(icFile);
291 if (!icCreated) {
292 string errorMsg = "Unable to create file " + icFile;
293 throw IOException(__FILE__, __LINE__, __func__, errorMsg);
294 }
295 std::ofstream icStream(icFile.c_str(), std::ofstream::out);
297 icStream.close();
298}
299
300/**
301 * Verifies that the IC generator is compatible with the machine.
302 *
303 * @exception InvalidData If the generator is incompatible.
304 */
305void
307 // check that the machine does not use segments or bridges
309 for (int i = 0; i < busNav.count(); i++) {
310 Bus* bus = busNav.item(i);
311 if (bus->segmentCount() > 1) {
312 throw InvalidData(
313 __FILE__, __LINE__, __func__,
314 "IC generator does not support segmented buses.");
315 }
316 }
317
319 if (bridgeNav.count() > 0) {
320 throw InvalidData(
321 __FILE__, __LINE__, __func__,
322 "IC generator does not support bridges.");
323 }
324}
325
326void
328 exportBustrace_ = export_bt;
329}
330
331/**
332 * Enables or disables generating bus trace code.
333 *
334 * @param generate Tells whether to generate the bus tracing code.
335 */
336void
338 generateBusTrace_ = generate;
339}
340
341
342/**
343 * Sets the starting cycle to be generated to the bus trace.
344 *
345 * @param cycle The cycle.
346 */
347void
351
352
353/**
354 * Returns the pin of the socket control port that control the given segment
355 * connection.
356 *
357 * @param socket The socket.
358 * @param segment The segment.
359 * @return The pin of the control port.
360 * @exception NotAvailable If the socket is not output socket or if it is not
361 * connected to the given segment.
362 */
363int
365 const TTAMachine::Socket& socket,
366 const TTAMachine::Segment& segment) const {
367 if (socket.direction() != Socket::OUTPUT) {
368 throw NotAvailable(__FILE__, __LINE__, __func__);
369 }
370
371 for (int i = 0; i < socket.segmentCount(); i++) {
372 Segment* seg = socket.segment(i);
373 if (seg == &segment) {
374 return i;
375 }
376 }
377
378 throw NotAvailable(__FILE__, __LINE__, __func__);
379}
380
381/**
382 * Generates sockets needed in the machine to the given directory.
383 *
384 * @param dstDirectory The destination directory.
385 * @exception IOException If an IO error occurs.
386 */
387void
388DefaultICGenerator::generateSocketsAndMuxes(const std::string& dstDirectory) {
389 bool needSimmSocket = true;
391 for (int i = 0; i < socketNav.count(); i++) {
392 Socket* socket = socketNav.item(i);
393 if (socket->portCount() > 0 && socket->segmentCount() > 0 &&
394 !socketIsGenerated(*socket)) {
396 socket->direction(), socket->portCount(),
397 socket->segmentCount(), dstDirectory);
398
399 if (socket->portCount() == 1 && socket->segmentCount() == 1 &&
401 needSimmSocket = false;
402 }
403 if (socket->direction() == TTAMachine::Socket::OUTPUT) {
405 socket->portCount(), socket->segmentCount());
406 } else {
408 socket->portCount(), socket->segmentCount());
409 }
410 }
411 }
412
413 // generate short immediate sockets if needed
414 if (needSimmSocket) {
416 for (int i = 0; i < busNav.count(); i++) {
417 Bus* bus = busNav.item(i);
418 if (bus->immediateWidth() > 0) {
419 generateSocket(Socket::OUTPUT, 1, 1, dstDirectory);
420 generatedOutputSockets_.emplace(1, 1);
421 }
422 }
423 }
424}
425
426/**
427 * Tests if the given port belongs to GCU
428 *
429 * @param port The port to be tested
430 */
431bool
434 for (int i = 0; i < gcu->portCount(); i++) {
435 TTAMachine::Port* gcuPort = gcu->port(i);
436 if (gcuPort == port) {
437 return true;
438 }
439 }
440 return false;
441}
442
443/**
444 * Generates the given socket to a VHDL file in the given directory.
445 *
446 * @param direction Direction of the socket.
447 * @param portConns The number of port connections.
448 * @param segmentConns The number of segment connections.
449 * @param dstDirectory The destination directory.
450 * @exception IOException If the file cannot be created.
451 */
452void
454 TTAMachine::Socket::Direction direction, int portConns, int segmentConns,
455 const std::string& dstDirectory) const {
456 string fileName = socketFileName(language_,
457 direction, portConns, segmentConns);
458 string pathToFile = dstDirectory + FileSystem::DIRECTORY_SEPARATOR +
459 fileName;
460 bool created = FileSystem::createFile(pathToFile);
461 if (!created) {
462 string errorMsg = "Unable to create file " + pathToFile;
463 throw IOException(__FILE__, __LINE__, __func__, errorMsg);
464 }
465
466 std::ofstream stream(pathToFile.c_str(), std::ofstream::out);
467 if (language_ == VHDL) {
468 stream << "library IEEE;" << endl;
469 stream << "use IEEE.std_logic_1164.all;" << endl;
470 stream << "use IEEE.std_logic_arith.all;" << endl;
471 stream << "use work.tce_util.all;" << endl;
472 } else {
473 //nothing for verilog
474 }
475 stream << endl;
476 if (direction == Socket::INPUT) {
477 generateInputMux(segmentConns, stream);
478 } else if (direction == Socket::OUTPUT) {
479 generateOutputSocket(portConns, segmentConns, stream);
480 } else {
481 assert(false);
482 }
483 stream.close();
484}
485
486/**
487 * Generates the given input socket to the given stream.
488 *
489 * @param segmentConns The number of segment connections.
490 * @param stream The stream.
491 */
492void
494 int segmentConns, std::ofstream& stream) const {
495 assert(segmentConns > 0);
496 if (language_ == VHDL) {
497 string entityName = inputMuxEntityName(segmentConns);
498 stream << "entity " << entityName << " is" << endl << endl;
499 writeInputSocketComponentDeclaration(VHDL,segmentConns, 1, stream);
500 stream << endl << "end " << entityName << ";" << endl << endl;
501
502 stream << "architecture rtl of " << entityName << " is" << endl
503 << "begin" << endl
504 << endl;
505 stream << indentation(2)
506 << "-- If width of input bus is greater than width of output,"
507 << endl;
508 stream << indentation(2) << "-- using the LSB bits." << endl;
509 stream << indentation(2)
510 << "-- If width of input bus is smaller than width of output,"
511 << endl;
512 stream << indentation(2)
513 << "-- using zero extension to generate extra bits." << endl;
514 stream << endl;
515
516 if (segmentConns > 1) {
517 stream << indentation(1) << "sel : process ("
518 << SOCKET_BUS_CONTROL_PORT << ", ";
519
520 for (int i = 0; i < segmentConns; i++) {
521 stream << inputSocketBusPort(i);
522 if (i + 1 < segmentConns) {
523 stream << ", ";
524 } else {
525 stream << ")" << endl;
526 }
527 }
528
529 stream << indentation(1) << "begin" << endl;
530 stream << indentation(2) << INPUT_SOCKET_DATA_PORT
531 << " <= (others => '0');" << endl;
532 stream << indentation(2) << "case " << SOCKET_BUS_CONTROL_PORT
533 << " is" << endl;
534
535 for (int i = 0; i < segmentConns; i++) {
536 if (i+1 < segmentConns) {
537 stream << indentation(3) << "when \""
539 i, busControlWidth(Socket::INPUT, segmentConns))
540 << "\" =>" << endl;
541 } else {
542 stream << indentation(3) << "when others =>" << endl;
543 }
544 generateInputSocketRuleForBus(i, 4, stream);
545 }
546
547 stream << indentation(2) << "end case;" << endl;
548 stream << indentation(1) << "end process sel;" << endl;
549
550 } else {
551 stream << indentation(1) << "process (" << inputSocketBusPort(0)
552 << ")" << endl;
553 stream << indentation(1) << "begin" << endl;
554 stream << indentation(2) << INPUT_SOCKET_DATA_PORT
555 << " <= (others => '0');" << endl;
556 generateInputSocketRuleForBus(0, 2, stream);
557 stream << indentation(1) << "end process;" << endl;
558 }
559
560 stream << "end rtl;" << endl;
561 } else {
562 string entityName = inputMuxEntityName(segmentConns);
563 stream << "`timescale 10ns/1ns" << endl
564 << "module " << entityName << "" << endl << endl;
565 writeInputSocketComponentDeclaration(Verilog,segmentConns, 1, stream);
566 stream << indentation(2)
567 << "// If width of input bus is greater than width of output,"
568 << endl
569 << indentation(2) << "// using the LSB bits." << endl
570 << indentation(2)
571 << "// If width of input bus is smaller than width of output,"
572 << endl
573 << indentation(2)
574 << "// using zero extension to generate extra bits." << endl
575 << endl;
576 if (segmentConns > 1) {
577 stream << indentation(1) << "always@("
578 << SOCKET_BUS_CONTROL_PORT << ", ";
579
580 for (int i = 0; i < segmentConns; i++) {
581 stream << inputSocketBusPort(i);
582 if (i + 1 < segmentConns) {
583 stream << ", ";
584 } else {
585 stream << ")" << endl;
586 }
587 }
588 stream << indentation(1) << "begin" << endl
589 << indentation(2) << "case(" << SOCKET_BUS_CONTROL_PORT
590 << ")" << endl;
591 for (int i = 0; i < segmentConns; i++) {
592 if (i+1 < segmentConns) {
593 stream << indentation(3)
594 << i << " :" << endl;
595 } else {
596 stream << indentation(3) << "default:" << endl;
597 }
598 generateInputSocketRuleForBus(i, 4, stream);
599 }
600 stream << indentation(2) << "endcase" << endl
601 << indentation(1) << "end" << endl;
602 } else {
603 stream << indentation(1) << "always@(" << inputSocketBusPort(0)
604 << ")" << endl
605 << indentation(1) << "begin" << endl;
606 generateInputSocketRuleForBus(0, 2, stream);
607 stream << indentation(1) << "end" << endl;
608 }
609 stream << "endmodule" << endl;
610 }
611}
612
613/**
614 * Generates rule in VHDL for an input socket for the given bus number.
615 *
616 * @param bus The bus.
617 * @param ind Indentation level.
618 * @param stream The stream to write.
619 */
620void
622 int bus, int ind, std::ofstream& stream) const {
623 if (language_ == VHDL) {
624 stream << indentation(ind) << INPUT_SOCKET_DATA_PORT << " <= tce_ext("
626 << "'length);" << endl;
627 } else {
628 stream << indentation(ind) << "if (" << busWidthGeneric(bus) << " < "
629 << INPUT_SOCKET_DATAW_GENERIC << ")" << endl
630 << indentation(ind+1) << INPUT_SOCKET_DATA_PORT << " <= $unsigned("
631 << inputSocketBusPort(bus) << ");"<< endl
632 << indentation(ind) << "else if (" << busWidthGeneric(bus)
633 << " > " << INPUT_SOCKET_DATAW_GENERIC << ")" << endl
634 << indentation(ind+1) << INPUT_SOCKET_DATA_PORT << " <= "
636 << "-1 : 0];" << endl
637 << indentation(ind) << "else" << endl
638 << indentation(ind+1) << INPUT_SOCKET_DATA_PORT << " <= "
639 << inputSocketBusPort(bus) << "[" << busWidthGeneric(bus)
640 << "-1 : 0];" << endl;
641 }
642}
643
644
645/**
646 * Generates the output socket to the given stream.
647 *
648 * @param socket The socket.
649 * @param stream The stream.
650 */
651void
653 int portConns,
654 int segmentConns,
655 std::ofstream& stream) const {
656 string entityName = outputSocketEntityName(segmentConns, portConns);
657 if (language_ == VHDL) {
658 stream << "entity " << entityName << " is" << endl;
660 portConns, segmentConns, 1, stream);
661 stream << "end " << entityName << ";" << endl << endl << endl;
662
663 stream << "architecture output_socket_andor of " << entityName
664 << " is" << endl
665 << endl;
666
667 if (portConns > 1) {
668 stream << indentation(1) << "constant data_widths : integer_array("
669 << portConns - 1 << " downto 0) := (";
670 for (int i = 0; i < portConns; i++) {
671 stream << dataWidthGeneric(i);
672 if (i+1 < portConns) {
673 stream << ", ";
674 }
675 }
676 stream << ");" << endl;
677
678 for (int i = 0; i < segmentConns; i++) {
679 stream << indentation(1) << "signal databus_" << i
680 << "_temp : std_logic_vector(return_highest(data_widths, "
681 << portConns << ")-1 downto 0);" << endl;
682 }
683
684 stream << indentation(1)
685 << "signal data : std_logic_vector(return_highest(data_widths, "
686 << portConns << ")-1 downto 0);" << endl;
687 } else {
688 for (int i = 0; i < segmentConns; i++) {
689 stream << indentation(1) << "signal databus_" << i
690 << "_temp : std_logic_vector(" << dataWidthGeneric(0)
691 << "-1 downto 0);" << endl;
692 }
693 stream << indentation(1) << "signal data : std_logic_vector("
694 << dataWidthGeneric(0) << "-1 downto 0);" << endl;
695 }
696
697 stream << endl;
698 stream << "begin -- output_socket_andor" << endl << endl;
699
700 if (portConns > 1) {
701 stream << indentation(1) << "data_sel : process(";
702 for (int i = 0; i < portConns; i++) {
703 stream << outputSocketDataPort(i) << ", ";
704 }
705 stream << SOCKET_DATA_CONTROL_PORT << ")" << endl;
706 stream << indentation(1) << "begin -- process data_sel" << endl;
707 for (int i = 0; i < portConns; i++) {
708 stream << indentation(2);
709 if (i == 0) {
710 stream << "if conv_integer(unsigned("
711 << SOCKET_DATA_CONTROL_PORT << ")) = 0 then"
712 << endl;
713 } else if (i < portConns-1) {
714 stream << "elsif conv_integer(unsignd("
715 << SOCKET_DATA_CONTROL_PORT << ")) = " << i
716 << endl;
717 } else {
718 stream << "else" << endl;
719 }
720 stream << indentation(3) << "data <= tce_sxt("
721 << outputSocketDataPort(i) << ", data'length);"
722 << endl;
723 }
724 stream << indentation(2) << "end if;" << endl;
725 stream << indentation(1) << "end process data_sel;" << endl
726 << endl;
727 } else {
728 stream << indentation(1) << "data <= " << outputSocketDataPort(0)
729 << ";" << endl << endl;
730 }
731
732 stream << indentation(1) << "internal_signal : process(data, "
733 << SOCKET_BUS_CONTROL_PORT << ")" << endl;
734 stream << indentation(1) << "begin -- process internal_signal"
735 << endl;
736
737 for (int i = 0; i < segmentConns; i++) {
738 stream << indentation(2) << "databus_" << i
739 << "_temp <= data and tce_sxt(" << SOCKET_BUS_CONTROL_PORT
740 << "(" << i << " downto " << i << "), data'length);"
741 << endl;
742 }
743
744 stream << indentation(1) << "end process internal_signal;" << endl
745 << endl;
746
747 stream << indentation(1) << "output : process (";
748
749 for (int i = 0; i < segmentConns; i++) {
750 stream << "databus_" << i << "_temp";
751 if (i+1 < segmentConns) {
752 stream << ",";
753 } else {
754 stream << ")" << endl;
755 }
756 }
757
758 stream << indentation(1) << "begin -- process output" << endl;
759
760 for (int i = 0; i < segmentConns; i++) {
761 stream << indentation(2) << outputSocketBusPort(i)
762 << " <= tce_ext(databus_" << i << "_temp, "
763 << outputSocketBusPort(i) << "'length);" << endl;
764 }
765 stream << indentation(1) << "end process output;" << endl << endl;
766 stream << "end output_socket_andor;" << endl;
767 } else { // language_ == Verilog
768 stream << "`timescale 10ns/1ns" << endl
769 << "module " << entityName << endl;
771 portConns, segmentConns, 1, stream);
772
773 //for avoiding absence of length attribute in verilog 2001
774 std::string data_length = dataWidthGeneric(0);
775
776 stream << "//architecture output_socket_andor of " << entityName
777 << endl << endl;
778 if (portConns > 1) {
779#if 1
780 assert(false &&
781 "Case portConns > 1 not supported by Verilog backend!");
782#else
783//!!!!!!!!!!!!!!!!!!!!!!!!!not finished here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
784 // stream << indentation(1) << "constant data_widths : integer_array("
785 // << portConns - 1 << " : 0] := (";
786 // for (int i = 0; i < portConns; i++) {
787 // stream << dataWidthGeneric(i);
788 // if (i+1 < portConns) {
789 // stream << ", ";
790 // }
791 // }
792 // stream << ");" << endl;
793
794 // for (int i = 0; i < segmentConns; i++) {
795 // stream << indentation(1) << "signal databus_" << i
796 // << "_temp : std_logic_vector(return_highest(data_widths, "
797 // << portConns << ")-1 downto 0);" << endl;
798 // }
799
800 // stream << indentation(1)
801 // << "signal data : std_logic_vector(return_highest(data_widths, "
802 // << portConns << ")-1 downto 0);" << endl;
803#endif
804 } else {
805 for (int i = 0; i < segmentConns; i++) {
806 stream << indentation(1)
807 << "reg["<< dataWidthGeneric(0)
808 << "-1 : 0] "
809 <<" databus_" << i << "_temp;" << endl;
810 }
811 stream << indentation(1)
812 << "reg["<< dataWidthGeneric(0)
813 << "-1 : 0] "
814 << "data;" << endl;
815 }
816
817 stream << endl;
818
819 if (portConns > 1) {
820 stream << indentation(1) << "always@(";
821 // for (int i = 0; i < portConns; i++) {
822 // stream << outputSocketDataPort(i) << ", ";
823 // }
824 // stream << SOCKET_DATA_CONTROL_PORT << ")" << endl;
825 stream << "*" << ")" << endl;
826 stream << indentation(1) << "begin // process data_sel" << endl;
827 for (int i = 0; i < portConns; i++) {
828 stream << indentation(2);
829 if (i == 0) {
830 stream << "if("
831 << SOCKET_DATA_CONTROL_PORT << "== 0)"
832 << endl;
833 } else if (i < portConns-1) {
834 stream << "else if("
835 << SOCKET_DATA_CONTROL_PORT << "== " << i
836 << ")"
837 << endl;
838 } else {
839 stream << "else" << endl;
840 }
841 stream << indentation(3) << "data = $signed("
842 << outputSocketDataPort(i) << ");"
843 << endl;
844 }
845 stream << indentation(1) << "end //process data_sel;" << endl
846 << endl;
847 } else {
848 stream << indentation(1)
849 << "always@(*)" << "data = " << outputSocketDataPort(0)
850 << ";" << endl << endl;
851 }
852
853 // stream << indentation(1) << "always@(data, "
854 // << SOCKET_BUS_CONTROL_PORT << ")" << endl;
855 stream << indentation(1) << "always@(*)" << endl;
856 stream << indentation(1) << "begin //process internal_signal"
857 << endl;
858
859 for (int i = 0; i < segmentConns; i++) {
860 stream << indentation(2)
861 << "databus_" << i << "_temp"
862 << "= data & {" << dataWidthGeneric(0) << "{"
864 << "[" << i << " : " << i << "]}};"
865 << endl;
866 }
867
868 stream << indentation(1) << "end //process internal_signal;" << endl
869 << endl;
870
871 stream << indentation(1) << "always@(*)" << endl;
872 // stream << indentation(1) << "always@(";
873 // for (int i = 0; i < segmentConns; i++) {
874 // stream << "databus_" << i << "_temp";
875 // if (i+1 < segmentConns) {
876 // stream << ",";
877 // } else {
878 // stream << ")" << endl;
879 // }
880 // }
881
882 stream << indentation(1) << "begin // process output" << endl;
883
884 for (int i = 0; i < segmentConns; i++) {
885 stream << indentation(2) << "if(" << busWidthGeneric(i)
886 << " < " << data_length << ")" << endl;
887 stream << indentation(3) << outputSocketBusPort(i)
888 << " = databus_" << i << "_temp;" << endl;
889 //"[" << busWidthGeneric(i) << "-1 : 0];" << endl;
890 stream << indentation(2) << "else" << endl;
891 stream << indentation(3) << outputSocketBusPort(i)
892 << " = $unsigned(databus_" << i << "_temp);"
893 << endl;
894 }
895 stream << indentation(1) << "end //process output;" << endl << endl;
896 stream << "endmodule //output_socket_andor;" << endl;
897 }
898}
899
900/**
901 * Writes the bus dump lines required by the HW debugger.
902 *
903 * @param stream The stream.
904 */
905void
907 stream << indentation(1) << "db_bustraces <= " << endl;
908
910
911 for (int i = 0; i < busNav.count(); i++) {
912 if (i % 4 == 0) {
913 stream << indentation(2);
914 }
915
916 // Reverse order
917 int idx = busNav.count() - 1 - i;
918 int busWidth = busNav.item(idx)->width();
919
920 if (busWidth % 32 !=
921 0) { // Pad busses to multiple of 32b with zeroes
922 stream << "\"" << string(32 - busWidth, '0') << "\"&";
923 }
924
925 stream << busSignal(*busNav.item(idx));
926
927 if (i != busNav.count() - 1) {
928 stream << " & ";
929
930 if (i % 4 == 3) {
931 stream << endl;
932 }
933 } else {
934 stream << ";";
935 }
936
937 }
938 stream << endl;
939}
940
941/**
942 * Writes the interconnection network to the given stream.
943 *
944 * @param stream The stream.
945 */
946void
948 if (language_ == VHDL) {
949 stream << "library IEEE;" << endl;
950 stream << "use IEEE.std_logic_1164.all;" << endl;
951 stream << "use IEEE.std_logic_arith.ext;" << endl;
952 stream << "use IEEE.std_logic_arith.sxt;" << endl;
953 if (generateBusTrace_) {
954 stream << "use IEEE.numeric_std.all;" << endl;
955 stream << "use IEEE.math_real.all;" << endl;
956 stream << "use STD.textio.all;" << endl;
957 stream << "use IEEE.std_logic_textio.all;" << endl;
958 }
959 stream << "use work." << entityNameStr_ << "_globals.all;" << endl
960 << "use work.tce_util.all;" << endl
961 << endl;
962
963 string entityName = entityNameStr_ + "_interconn";
964 stream << "entity " << entityName << " is" << endl << endl;
965
966 if (exportBustrace_ && (icBlock_->port("db_bustraces") == NULL)) {
967 new NetlistPort(
968 "db_bustraces", "BUSTRACE_WIDTH", ProGe::BIT_VECTOR,
970 }
971
973 *icBlock_, 1, indentation(1), stream);
975 *icBlock_, 1, indentation(1), stream);
976
977 stream << endl << "end " << entityName << ";" << endl << endl;
978
979 // create architecture
980 stream << "architecture comb_andor of " << entityName << " is" << endl
981 << endl;
982 createSignalsForIC(stream);
983 stream << endl;
984 declareSocketEntities(stream);
985 stream << endl;
986 stream << "begin -- comb_andor" << endl << endl;
987
988 if (generateBusTrace_) {
989 writeBusDumpCode(stream);
990 stream << endl;
991 }
992
993 if (exportBustrace_) {
995 stream << endl;
996 }
997
998 // Sort sockets by name to get deterministic order in HDL.
1000 std::set<Socket*, Component::ComponentNameComparator> socketsToWrite;
1001 for (int i = 0; i < socketNav.count(); i++) {
1002 socketsToWrite.insert(socketNav.item(i));
1003 }
1004 for (std::set<Socket*,
1005 Component::ComponentNameComparator>::const_iterator iter =
1006 socketsToWrite.begin();
1007 iter != socketsToWrite.end(); iter++) {
1008 Socket* socket = *iter;
1009 int segmentCount = socket->segmentCount();
1010 if (segmentCount == 0 || socket->portCount() == 0) {
1011 continue;
1012 }
1013 stream << indentation(1) << socket->name() << " : "
1014 << socketEntityName(*socket) << endl;
1015 stream << indentation(2) << "generic map (" << endl;
1016 for (int i = 0; i < segmentCount; i++) {
1017 int actualGenericWidth = 0;
1018 if (socket->direction() == Socket::OUTPUT) {
1019 actualGenericWidth = maxOutputSocketDataPortWidth(*socket);
1020 } else if (socket->direction() == Socket::INPUT) {
1021 actualGenericWidth =
1022 socket->segment(i)->parentBus()->width();
1023 }
1024 stream << indentation(3) << busWidthGeneric(i) << " => "
1025 << actualGenericWidth << "," << endl;
1026 }
1027 if (socket->direction() == Socket::OUTPUT) {
1028 for (int i = 0; i < socket->portCount(); i++) {
1029 string socketWidth = "";
1030 if (socket->hasDataPortWidth()) {
1031 socketWidth = socket->dataPortWidth();
1032 } else {
1033 socketWidth =
1034 Conversion::toString(socket->port(i)->width());
1035 }
1036 if (socket->portCount() > 0
1037 && machine_.isRISCVMachine()) {
1039 if (isGcuPort(socket->port(0)) &&
1040 socket->port(0) == gcu->triggerPort()) {
1041 socketWidth = Conversion::toString(32);
1042 }
1043 }
1044 stream << indentation(3) << dataWidthGeneric(i)
1045 << " => " << socketWidth;
1046 if (i+1 == socket->portCount()) {
1047 stream << ")" << endl;
1048 } else {
1049 stream << "," << endl;
1050 }
1051 }
1052 } else { // socket->direction() == Socket::INPUT
1053 string socketWidth;
1054 if (socket->hasDataPortWidth()) {
1055 socketWidth = socket->dataPortWidth();
1056 } else {
1057 socketWidth = Conversion::toString(
1058 inputSocketDataPortWidth(*socket));
1059 }
1061 << " => " << socketWidth << ")"
1062 << endl;
1063 }
1064 stream << indentation(2) << "port map (" << endl;
1065 for (int i = 0; i < segmentCount; i++) {
1066 Bus* bus = socket->segment(i)->parentBus();
1067 stream << indentation(3);
1068 if (socket->direction() == Socket::INPUT) {
1069 stream << inputSocketBusPort(i) << " => "
1070 << busSignal(*bus) << "," << endl;
1071 } else {
1072 stream << outputSocketBusPort(i) << " => "
1073 << busAltSignal(*bus, *socket) << "," << endl;
1074 }
1075 }
1076
1077 if (socket->direction() == Socket::OUTPUT) {
1078 for (int i = 0; i < socket->portCount(); i++) {
1079 stream << indentation(3) << outputSocketDataPort(i)
1080 << " => "
1081 << outputSocketDataPort(socket->name(), i);
1082 if (i+1 < socket->portCount()) {
1083 stream << "," << endl;
1084 }
1085 }
1086 } else {
1087 stream << indentation(3) << INPUT_SOCKET_DATA_PORT << " => "
1088 << inputSocketDataPort(socket->name());
1089 }
1090 if (busControlWidth(
1091 socket->direction(), socket->segmentCount()) > 0) {
1092 stream << "," << endl;
1093 stream << indentation(3) << SOCKET_BUS_CONTROL_PORT << " => "
1094 << socketBusControlPort(socket->name());
1095 }
1096 if (dataControlWidth(socket->direction(), socket->portCount()) > 0) {
1097 stream << "," << endl;
1098 stream << indentation(3) << SOCKET_DATA_CONTROL_PORT << " => "
1099 << socketDataControlPort(socket->name());
1100 }
1101 stream << ");" << endl << endl;
1102 }
1103
1104 // add the sockets for short immediates
1106 for (int i = 0; i < busNav.count(); i++) {
1107 Bus* bus = busNav.item(i);
1108 if (bus->immediateWidth() > 0) {
1109 stream << indentation(1) << simmSocket(*bus) << " : "
1110 << outputSocketEntityName(1, 1) << endl;
1111 stream << indentation(2) << "generic map (" << endl;
1112 stream << indentation(3) << busWidthGeneric(0) << " => "
1113 << simmPortWidth(*bus) << "," << endl;
1114 stream << indentation(3) << dataWidthGeneric(0) << " => "
1115 << simmPortWidth(*bus) << ")" << endl;
1116 stream << indentation(2) << "port map (" << endl;
1117 stream << indentation(3) << outputSocketBusPort(0) << " => "
1118 << simmSignal(*bus) << "," << endl;
1119 stream << indentation(3) << outputSocketDataPort(0) << " => "
1120 << simmDataPort(bus->name()) << "," << endl;
1121 stream << indentation(3) << SOCKET_BUS_CONTROL_PORT << " => "
1122 << simmControlPort(bus->name()) << ");" << endl
1123 << endl;
1124 }
1125 }
1126
1127 // add assignments to data buses
1128 for (int i = 0; i < busNav.count(); i++) {
1129 Bus* bus = busNav.item(i);
1130 std::set<Socket*> outputSockets = this->outputSockets(*bus);
1131 if (outputSockets.size() == 0 && bus->immediateWidth() == 0) {
1132 stream << indentation(1) << busSignal(*bus)
1133 << " <= (others=>'0');" << endl;
1134 continue;
1135 }
1136 // Sort sockets by name to get deterministic HDL output.
1137 std::set<Socket*, Component::ComponentNameComparator> socketsToWrite;
1138 for (std::set<Socket*>::iterator iter = outputSockets.begin();
1139 iter != outputSockets.end(); iter++) {
1140 socketsToWrite.insert(*iter);
1141 }
1142
1143 stream << indentation(1) << busSignal(*bus) << " <= ";
1144 for (auto iter = socketsToWrite.begin();
1145 iter != socketsToWrite.end();) {
1146 Socket* socket = *iter;
1147 stream << "tce_ext(" << busAltSignal(*bus, *socket) << ", "
1148 << busSignal(*bus) << "'length)";
1149 iter++;
1150 if (iter != socketsToWrite.end()) {
1151 stream << " or ";
1152 }
1153 }
1154 if (bus->immediateWidth() > 0) {
1155 if (socketsToWrite.begin() != socketsToWrite.end()) {
1156 stream << " or ";
1157 }
1158 if (bus->signExtends()) {
1159 stream << "tce_sxt(";
1160 } else if (bus->zeroExtends()) {
1161 stream << "tce_ext(";
1162 } else {
1163 assert(false && "Unknown extension policy.");
1164 }
1165 stream << simmSignal(*bus)
1166 << ", " << busSignal(*bus) << "'length)";
1167 }
1168 stream << ";" << endl;
1169 }
1170
1171 stream << endl;
1172 stream << "end comb_andor;" << endl;
1173
1174 } else { // language_ == Verilog
1175 const std::string DS = FileSystem::DIRECTORY_SEPARATOR;
1176 string entityName = entityNameStr_ + "_interconn";
1177 stream << "`timescale 1ns/1ns" << endl
1178 << "module " << entityName << endl
1179 //include parameters here
1180 << "#(" << endl
1181 << "`include \""
1182 << entityNameStr_ << "_globals_pkg.vh\"" << endl
1183 << ")" << endl;
1184
1186 *icBlock_, 1, indentation(1), stream);
1188 *icBlock_, 1, indentation(1), stream);
1189
1190 // create architecture
1191 createSignalsForIC(stream);
1192 stream << endl;
1193
1194 if (generateBusTrace_) {
1195 writeBusDumpCode(stream);
1196 stream << endl;
1197 }
1198
1199 // Sort sockets by name to get deterministic HDL output.
1201 std::set<Socket*, Component::ComponentNameComparator> socketsToWrite;
1202 for (int i = 0; i < socketNav.count(); i++) {
1203 socketsToWrite.insert(socketNav.item(i));
1204 }
1205 for (std::set<Socket*,
1206 Component::ComponentNameComparator>::const_iterator iter =
1207 socketsToWrite.begin(); iter != socketsToWrite.end(); iter++) {
1208 Socket* socket = *iter;
1209 int segmentCount = socket->segmentCount();
1210 if (segmentCount == 0 || socket->portCount() == 0) {
1211 continue;
1212 }
1213 stream << indentation(1) << socketEntityName(*socket) << endl;
1214
1215 //parameters(generics)
1216 stream << indentation(2) << "#(" << endl;
1217 for (int i = 0; i < segmentCount; i++) {
1218 stream << indentation(3) << "." << busWidthGeneric(i) << "("
1219 << socket->segment(i)->parentBus()->width() << "),"
1220 << endl;
1221 }
1222
1223 if (socket->direction() == Socket::OUTPUT) {
1224 for (int i = 0; i < socket->portCount(); i++) {
1225 string socketWidth = "";
1226 if (socket->hasDataPortWidth()) {
1227 socketWidth = socket->dataPortWidth();
1228 } else {
1229 socketWidth =
1230 Conversion::toString(socket->port(i)->width());
1231 }
1232 stream << indentation(3) << "." << dataWidthGeneric(i)
1233 << "(" << socketWidth;
1234 if (i+1 == socket->portCount()) {
1235 stream << ")" << endl;
1236 } else {
1237 stream << ")," << endl;
1238 }
1239 }
1240 } else {
1241 string socketWidth;
1242 if (socket->hasDataPortWidth()) {
1243 socketWidth = socket->dataPortWidth();
1244 } else {
1245 socketWidth =
1247 }
1248 stream << indentation(3) << "." << INPUT_SOCKET_DATAW_GENERIC
1249 << "(" << socketWidth << ")"
1250 << endl;
1251 }
1252 stream << indentation(2) << ")" << endl
1253 << indentation(2) << socket->name() << endl
1254 << indentation(2) << "(" << endl;
1255 for (int i = 0; i < segmentCount; i++) {
1256 Bus* bus = socket->segment(i)->parentBus();
1257 stream << indentation(3);
1258 if (socket->direction() == Socket::INPUT) {
1259 stream << "." << inputSocketBusPort(i) << "("
1260 << busSignal(*bus) << ")," << endl;
1261 } else {
1262 stream << "." << outputSocketBusPort(i) << "("
1263 << busAltSignal(*bus, *socket) << ")," << endl;
1264 }
1265 }
1266
1267 if (socket->direction() == Socket::OUTPUT) {
1268 for (int i = 0; i < socket->portCount(); i++) {
1269 stream << indentation(3) << "." << outputSocketDataPort(i)
1270 << "("
1271 << outputSocketDataPort(socket->name(), i);
1272 if (i+1 < socket->portCount()) {
1273 stream << ")," << endl;
1274 }
1275 }
1276 } else {
1277 stream << indentation(3) << "." << INPUT_SOCKET_DATA_PORT << "("
1278 << inputSocketDataPort(socket->name());
1279 }
1280 if (busControlWidth(
1281 socket->direction(), socket->segmentCount()) > 0) {
1282 stream << ")," << endl;
1283 stream << indentation(3) << "." << SOCKET_BUS_CONTROL_PORT << "("
1284 << socketBusControlPort(socket->name());
1285 }
1286 if (dataControlWidth(socket->direction(), socket->portCount()) > 0) {
1287 stream << ")," << endl;
1288 stream << indentation(3) << "." << SOCKET_DATA_CONTROL_PORT << "("
1289 << socketDataControlPort(socket->name());
1290 }
1291 stream << "));" << endl << endl;
1292 }
1293
1294 // add the sockets for short immediates
1296 for (int i = 0; i < busNav.count(); i++) {
1297 Bus* bus = busNav.item(i);
1298 if (bus->immediateWidth() > 0) {
1299 stream << indentation(1)
1300 << outputSocketEntityName(1, 1)
1301 << " "
1302 << endl
1303
1304 << indentation(2) << "#(" << endl
1305 << indentation(3) << "." << busWidthGeneric(0) << "("
1306 << bus->width() << ")," << endl
1307 << indentation(3) << "." << dataWidthGeneric(0) << "("
1308 << simmPortWidth(*bus) << ")" << endl
1309 << indentation(2) << ")" << endl
1310 << indentation(2) << simmSocket(*bus) << endl
1311 << indentation(2) << "(" << endl
1312 << indentation(3) << "." << outputSocketBusPort(0) << "("
1313 << simmSignal(*bus) << ")," << endl
1314 << indentation(3) << "." << outputSocketDataPort(0) << "("
1315 << simmDataPort(bus->name()) << ")," << endl
1316 << indentation(3) << "." << SOCKET_BUS_CONTROL_PORT << "("
1317 << simmControlPort(bus->name()) << "));" << endl << endl;
1318 }
1319 }
1320
1321 // add assignments to data buses
1322 for (int i = 0; i < busNav.count(); i++) {
1323 Bus* bus = busNav.item(i);
1324 std::set<Socket*> outputSockets = this->outputSockets(*bus);
1325 stream << indentation(1) << "assign " << busSignal(*bus) << " = ";
1326 // Sort sockets by name to get deterministic HDL output.
1327 std::set<Socket*, Component::ComponentNameComparator> socketsToWrite;
1328 for (std::set<Socket*>::iterator iter = outputSockets.begin();
1329 iter != outputSockets.end(); iter++) {
1330 socketsToWrite.insert(*iter);
1331 }
1332
1333 for (std::set<Socket*,
1334 Component::ComponentNameComparator>::const_iterator iter =
1335 socketsToWrite.begin(); iter != socketsToWrite.end();) {
1336 Socket* socket = *iter;
1337 stream << busAltSignal(*bus, *socket);
1338 iter++;
1339 if (iter != socketsToWrite.end()) {
1340 stream << " | ";
1341 }
1342 }
1343 if (bus->immediateWidth() > 0) {
1344 if (socketsToWrite.begin() != socketsToWrite.end()) {
1345 stream << " | ";
1346 }
1347 stream << simmSignal(*bus);
1348 }
1349 stream << ";" << endl;
1350 }
1351 stream << endl;
1352 stream << "endmodule"<< endl;
1353 }
1354}
1355
1356
1357/**
1358 * Writes the signal declarations of interconnection network to the
1359 * given stream.
1360 *
1361 * @param stream The stream.
1362 */
1363void
1366 if (language_ == VHDL){
1367 for (int i = 0; i < busNav.count(); i++) {
1368 Bus* bus = busNav.item(i);
1369
1370 if (isBusConnected(*bus)) {
1371 // create signal for the bus
1372 stream << indentation(1) << "signal " << busSignal(*bus)
1373 << " : std_logic_vector(" << bus->width() - 1
1374 << " downto 0);" << endl;
1375 }
1376
1377 // create a signal for all the output sockets connected to the
1378 // bus
1379 // Sort alphabetically to get deterministic HDL output.
1380 std::set<Socket*> outputSockets = this->outputSockets(*bus);
1381 std::set<Socket*, Component::ComponentNameComparator>
1382 socketsToWrite;
1383 for (std::set<Socket*>::iterator iter = outputSockets.begin();
1384 iter != outputSockets.end(); iter++) {
1385 socketsToWrite.insert(*iter);
1386 }
1387
1388 for (std::set<Socket*, Component::ComponentNameComparator>::
1389 iterator iter = socketsToWrite.begin();
1390 iter != socketsToWrite.end(); iter++) {
1391 stream << indentation(1) << "signal "
1392 << busAltSignal(*bus, **iter) << " : std_logic_vector("
1393 << maxOutputSocketDataPortWidth(**iter) - 1
1394 << " downto 0);" << endl;
1395 }
1396
1397 // create additional signal for short immediate
1398 if (bus->immediateWidth() > 0) {
1399 stream << indentation(1) << "signal " << simmSignal(*bus)
1400 << " : std_logic_vector(" << simmPortWidth(*bus) - 1
1401 << " downto 0);" << endl;
1402 }
1403 }
1404 } else { // language_ == Verilog
1405 for (int i = 0; i < busNav.count(); i++) {
1406 Bus* bus = busNav.item(i);
1407 // create wire for the bus
1408 stream << indentation(1) << "wire[" << bus->width() - 1 << ":0] "
1409 << busSignal(*bus) << ";"<< endl;
1410
1411 // create a wires for all the output sockets connected to the bus
1412 // Sort alphabetically to get deterministic HDL output.
1413 std::set<Socket*> outputSockets = this->outputSockets(*bus);
1414 std::set<Socket*, Component::ComponentNameComparator> socketsToWrite;
1415 for (std::set<Socket*>::iterator iter = outputSockets.begin();
1416 iter != outputSockets.end(); iter++) {
1417 socketsToWrite.insert(*iter);
1418 }
1419
1420 for (std::set<Socket*, Component::ComponentNameComparator>::iterator
1421 iter = socketsToWrite.begin(); iter != socketsToWrite.end();
1422 iter++) {
1423 stream << indentation(1) << "wire[" << bus->width() - 1 <<":0] "
1424 << busAltSignal(*bus, **iter)<<";"<< endl;
1425 }
1426
1427 // create additional wire for short immediate
1428 if (bus->immediateWidth() > 0) {
1429 stream << indentation(1) << "wire[" << bus->width() - 1 << ":0] "
1430 << simmSignal(*bus) << ";" << endl;
1431 }
1432 }
1433 }
1434}
1435
1436
1437/**
1438 * Declares the socket entities used in the IC.
1439 *
1440 * @param stream The stream to write.
1441 */
1442void
1444 for (auto iter = generatedInputSockets_.begin();
1445 iter != generatedInputSockets_.end(); iter++) {
1446 int segmentCount = iter->second;
1447 string entityName = inputMuxEntityName(segmentCount);
1448 stream << indentation(1) << "component " << entityName << " is"
1449 << endl;
1450 writeInputSocketComponentDeclaration(VHDL, segmentCount, 2, stream);
1451 stream << indentation(1) << "end component;" << endl << endl;
1452 }
1453
1454 for (auto iter = generatedOutputSockets_.begin();
1455 iter != generatedOutputSockets_.end(); iter++) {
1456 int portCount = iter->first;
1457 int segmentCount = iter->second;
1458 string entityName = outputSocketEntityName(segmentCount, portCount);
1459 stream << indentation(1) << "component " << entityName << " is"
1460 << endl;
1462 VHDL, portCount, segmentCount, 2, stream);
1463 stream << indentation(1) << "end component;" << endl << endl;
1464 }
1465}
1466
1467
1468/**
1469 * Writes the component interface declaration of the given output socket to
1470 * the given stream.
1471 *
1472 * @param portConns The number of port connections.
1473 * @param segmentConns The number of segment connections.
1474 * @param ind The indentation level.
1475 * @param stream The stream to write.
1476 */
1477void
1479 const ProGe::HDL language,
1480 int portConns,
1481 int segmentConns,
1482 int ind,
1483 std::ostream& stream) {
1484
1485 if (language == VHDL) {
1486 stream << indentation(ind) << "generic (" << endl;
1487
1488 for (int i = 0; i < segmentConns; i++) {
1489 stream << indentation(ind+1) << busWidthGeneric(i)
1490 << " : integer := 32;" << endl;
1491 }
1492
1493 for (int i = 0; i < portConns; i++) {
1494 stream << indentation(ind+1) << dataWidthGeneric(i)
1495 << " : integer := 32";
1496 if (i+1 == portConns) {
1497 stream << ");" << endl;
1498 } else {
1499 stream << ";" << endl;
1500 }
1501 }
1502
1503 stream << indentation(ind) << "port (" << endl;
1504 for (int i = 0; i < segmentConns; i++) {
1505 stream << indentation(ind+1) << outputSocketBusPort(i)
1506 << " : out std_logic_vector(" << busWidthGeneric(i)
1507 << "-1 downto 0);" << endl;
1508 }
1509 for (int i = 0; i < portConns; i++) {
1510 stream << indentation(ind+1) << outputSocketDataPort(i)
1511 << " : in std_logic_vector(" << dataWidthGeneric(i)
1512 << "-1 downto 0);" << endl;
1513 }
1514
1515 const int busControlWidth = segmentConns;
1516 stream << indentation(ind+1) << SOCKET_BUS_CONTROL_PORT
1517 << " : in std_logic_vector(" << busControlWidth - 1
1518 << " downto 0)";
1519
1520 if (portConns > 1) {
1521 stream << ";" << endl;
1523 Socket::OUTPUT, portConns);
1524 stream << indentation(ind+1) << SOCKET_DATA_CONTROL_PORT
1525 << " : in std_logic_vector(" << dataControlWidth - 1
1526 << " downto 0));" << endl;
1527 } else {
1528 stream << ");" << endl;
1529 }
1530 } else {
1531 stream << indentation(ind) << "#( parameter " << endl;
1532
1533 for (int i = 0; i < segmentConns; i++) {
1534 stream << indentation(ind+1) << busWidthGeneric(i)
1535 << " = 32," << endl;
1536 }
1537
1538 for (int i = 0; i < portConns; i++) {
1539 stream << indentation(ind+1) << dataWidthGeneric(i)
1540 << " = 32";
1541 if (i+1 == portConns) {
1542 stream << ")" << endl;
1543 } else {
1544 stream << "," << endl;
1545 }
1546 }
1547
1548 stream << indentation(ind) << "(" << endl;
1549 for (int i = 0; i < segmentConns; i++) {
1550 stream << indentation(ind+1)
1551 << "output reg[" << busWidthGeneric(i)
1552 << "-1 : 0] "
1554 << "," << endl;
1555 }
1556 for (int i = 0; i < portConns; i++) {
1557 stream << indentation(ind+1)
1558 << "input[" << dataWidthGeneric(i)
1559 << "-1 : 0] "
1561 << "," << endl;
1562 }
1563
1564 const int busControlWidth = segmentConns;
1565 stream << indentation(ind+1)
1566 << "input [" << busControlWidth - 1
1567 << " : 0]"
1569
1570 if (portConns > 1) {
1571 stream << "," << endl;
1573 Socket::OUTPUT, portConns);
1574 stream << indentation(ind+1) << SOCKET_DATA_CONTROL_PORT
1575 << "input [" << dataControlWidth - 1
1576 << " : 0]);" << endl;
1577 } else {
1578 stream << ");" << endl;
1579 }
1580 }
1581}
1582
1583
1584/**
1585 * Writes the component interface declaration of the given input socket to
1586 * the given stream.
1587 *
1588 * @param segmentConns The number of segment connections.
1589 * @param ind The indentation level.
1590 * @param stream The stream to write.
1591 */
1592void
1594 const ProGe::HDL language,
1595 int segmentConns,
1596 int ind,
1597 std::ostream& stream) {
1598
1599 if (language == VHDL) {
1600 stream << indentation(ind) << "generic (" << endl;
1601
1602 for (int i = 0; i < segmentConns; i++) {
1603 stream << indentation(ind+1) << busWidthGeneric(i) <<
1604 " : integer := 32;" << endl;
1605 }
1606
1607 stream << indentation(ind+1) << INPUT_SOCKET_DATAW_GENERIC
1608 << " : integer := 32);" << endl;
1609 stream << indentation(ind) << "port (" << endl;
1610
1611 for (int i = 0; i < segmentConns; i++) {
1612 stream << indentation(ind+1) << inputSocketBusPort(i)
1613 << " : in std_logic_vector(" << busWidthGeneric(i)
1614 << "-1 downto 0);" << endl;
1615 }
1616
1617 stream << indentation(ind+1) << INPUT_SOCKET_DATA_PORT
1618 << " : out std_logic_vector(" << INPUT_SOCKET_DATAW_GENERIC
1619 << "-1 downto 0)";
1620 int controlWidth = MathTools::bitLength(segmentConns - 1);
1621 if (segmentConns > 1) {
1622 stream << ";" << endl;
1623 stream << indentation(ind+1) << SOCKET_BUS_CONTROL_PORT
1624 << " : in std_logic_vector(" << controlWidth - 1
1625 << " downto 0));" << endl;
1626 } else {
1627 stream << ");" << endl;
1628 }
1629 } else {
1630 stream << indentation(ind) << "#( parameter " << endl;
1631
1632 for (int i = 0; i < segmentConns; i++) {
1633 stream << indentation(ind+1) << busWidthGeneric(i) <<
1634 " = 32," << endl;
1635 }
1636
1637 stream << indentation(ind+1) << INPUT_SOCKET_DATAW_GENERIC
1638 << " = 32)" << endl;
1639 stream << indentation(ind) << "(" << endl;
1640
1641 for (int i = 0; i < segmentConns; i++) {
1642 stream << indentation(ind+1)
1643 << "input[" << busWidthGeneric(i)
1644 << "-1 : 0] " << inputSocketBusPort(i) << ","
1645 << endl;
1646 }
1647
1648 stream << indentation(ind+1)
1649 << "output reg[" << INPUT_SOCKET_DATAW_GENERIC
1650 << "-1 : 0] "
1652 int controlWidth = MathTools::bitLength(segmentConns - 1);
1653 if (segmentConns > 1) {
1654 stream << "," << endl;
1655 stream << indentation(ind+1)
1656 << "input[" << controlWidth - 1
1657 << " : 0] "
1659 }
1660 stream << ");" << endl;
1661 }
1662}
1663
1664
1665/**
1666 * Writes the code that dumps the bus contents to an output file.
1667 *
1668 * @param stream The stream to write.
1669 */
1670void
1671DefaultICGenerator::writeBusDumpCode(std::ostream& stream) const {
1672 if (language_ == VHDL) {
1673
1674 const std::string vhdlFunctionCeil4 =
1675 " -- Rounds integer up to next multiple of four.\n"
1676 " function ceil4 (\n"
1677 " constant val : natural)\n"
1678 " return natural is\n"
1679 " begin -- function ceil4\n"
1680 " return natural(ceil(real(val)/real(4)))*4;\n"
1681 " end function ceil4;\n";
1682
1683 const std::string vhdlFunctionExt4 =
1684 " -- Extends std_logic_vector to multiple of four.\n"
1685 " function ext_to_multiple_of_4 (\n"
1686 " constant slv : std_logic_vector)\n"
1687 " return std_logic_vector is\n"
1688 " begin\n"
1689 " return std_logic_vector(resize(\n"
1690 " unsigned(slv), ceil4(slv'length)));\n"
1691 " end function ext_to_multiple_of_4;\n";
1692
1693 const std::string vhdlFunctionToHex =
1694 " function to_unsigned_hex (\n"
1695 " constant slv : std_logic_vector) return string is\n"
1696 " variable resized_slv : std_logic_vector(ceil4(slv'length)"
1697 "-1 downto 0);\n"
1698 " variable result : string(1 to ceil4(slv'length)/4)\n"
1699 " := (others => ' ');\n"
1700 " subtype digit_t is std_logic_vector(3 downto 0);\n"
1701 " variable digit : digit_t := \"0000\";\n"
1702 " begin\n"
1703 " resized_slv := ext_to_multiple_of_4(slv);\n"
1704 " for i in result'range loop\n"
1705 " digit := resized_slv(\n"
1706 " resized_slv'length-((i-1)*4)-1 downto "
1707 "resized_slv'length-(i*4));\n"
1708 " case digit is\n"
1709 " when \"0000\" => result(i) := '0';\n"
1710 " when \"0001\" => result(i) := '1';\n"
1711 " when \"0010\" => result(i) := '2';\n"
1712 " when \"0011\" => result(i) := '3';\n"
1713 " when \"0100\" => result(i) := '4';\n"
1714 " when \"0101\" => result(i) := '5';\n"
1715 " when \"0110\" => result(i) := '6';\n"
1716 " when \"0111\" => result(i) := '7';\n"
1717 " when \"1000\" => result(i) := '8';\n"
1718 " when \"1001\" => result(i) := '9';\n"
1719 " when \"1010\" => result(i) := 'a';\n"
1720 " when \"1011\" => result(i) := 'b';\n"
1721 " when \"1100\" => result(i) := 'c';\n"
1722 " when \"1101\" => result(i) := 'd';\n"
1723 " when \"1110\" => result(i) := 'e';\n"
1724 " when \"1111\" => result(i) := 'f';\n"
1725 "\n"
1726 " -- For TTAsim bustrace compatibility\n"
1727 " when others => \n"
1728 " result := (others => '0');\n"
1729 " return result;\n"
1730 " end case;\n"
1731 " end loop; -- i in result'range\n"
1732 " return result;\n"
1733 " end function to_unsigned_hex;\n";
1734
1735 stream << indentation(1)
1736 << "-- Dump the value on the buses into a file once in clock cycle"
1737 << endl;
1738 stream << indentation(1)
1739 << "-- setting DUMP false will disable dumping" << endl << endl;
1740 stream << indentation(1) << "-- Do not synthesize this process!" << endl;
1741 stream << indentation(1) << "-- pragma synthesis_off" << endl;
1742 stream << indentation(1) << "-- pragma translate_off" << endl;
1743
1744 stream << indentation(1) << "file_output : process" << endl << endl;
1745 stream << indentation(2)
1746 << "file regularfileout : text;" << endl;
1747 stream << indentation(2)
1748 << "file executionfileout : text;" << endl << endl;
1749 stream << indentation(2) << "variable lineout : line;" << endl;
1750 stream << indentation(2) << "variable start : boolean := true;" << endl;
1751 stream << indentation(2) << "variable cyclecount : integer := 0;"
1752 << endl;
1753 stream << indentation(2) << "variable executioncount : integer := 0;"
1754 << endl << endl;
1755 stream << indentation(2) << "constant DUMP : boolean := true;" << endl;
1756 stream << indentation(2)
1757 << "constant REGULARDUMPFILE : string := \"bus.dump\";"
1758 << endl;
1759 stream << indentation(2)
1760 << "constant EXECUTIONDUMPFILE : string := \"execbus.dump\";"
1761 << endl << endl;
1762 stream << vhdlFunctionCeil4 << endl;
1763 stream << vhdlFunctionExt4 << endl;
1764 stream << vhdlFunctionToHex << endl;
1765 stream << indentation(1) << "begin" << endl;
1766 stream << indentation(2) << "if DUMP = true then" << endl;
1767 stream << indentation(3) << "if start = true then" << endl;
1768 stream << indentation(4)
1769 << "file_open(regularfileout, REGULARDUMPFILE, write_mode);"
1770 << endl;
1771 stream << indentation(4)
1772 << "file_open(executionfileout, EXECUTIONDUMPFILE, write_mode);"
1773 << endl;
1774 stream << indentation(4) << "start := false;" << endl;
1775 stream << indentation(3) << "end if;" << endl << endl;
1776
1777 stream << indentation(3) << "-- wait until rising edge of clock"
1778 << endl;
1779 stream << indentation(3)
1780 << "wait on clk until clk = '1' and clk'last_value = '0';"
1781 << endl;
1782 int ind = 3;
1783 if (busTraceStartingCycle_ > 0) {
1784 stream << indentation(3) << "if (cyclecount > "
1786 << ") then" << endl;
1787 ind++;
1788 }
1789 stream << indentation(ind) << "write(lineout, cyclecount-"
1790 << busTraceStartingCycle_ << ");"
1791 << endl;
1792
1794 for (int i = 0; i < busNav.count(); i++) {
1795 stream << indentation(ind) << "write(lineout, string'(\",\"));"
1796 << endl;
1797 stream << indentation(ind)
1798 << "write(lineout, to_unsigned_hex("
1799 << busSignal(*busNav.item(i)) << "));" << endl;
1800 }
1801
1802 stream << endl << indentation(ind)
1803 << "writeline(regularfileout, lineout);" << endl;
1804
1805 stream << indentation(ind) << "if glock = '0' then" << endl;
1806 stream << indentation(ind+1) << "write(lineout, executioncount" << ");"
1807 << endl;
1808
1809 for (int i = 0; i < busNav.count(); i++) {
1810 stream << indentation(ind+1) << "write(lineout, string'(\",\"));"
1811 << endl;
1812 stream << indentation(ind+1)
1813 << "write(lineout, to_unsigned_hex("
1814 << busSignal(*busNav.item(i)) << "));" << endl;
1815 }
1816 stream << endl << indentation(ind+1)
1817 << "writeline(executionfileout, lineout);" << endl;
1818 stream << indentation(ind+1) << "executioncount := executioncount + 1;"
1819 << endl;
1820 stream << indentation(ind) << "end if;" << endl;
1821
1822 if (busTraceStartingCycle_ > 0) {
1823 stream << indentation(3) << "end if;" << endl;
1824 }
1825 stream << indentation(3) << "cyclecount := cyclecount + 1;" << endl;
1826 stream << indentation(2) << "end if;" << endl;
1827 stream << indentation(1) << "end process file_output;" << endl;
1828 stream << indentation(1) << "-- pragma translate_on" << endl;
1829 stream << indentation(1) << "-- pragma synthesis_on" << endl;
1830
1831 } else { // language_ == Verilog
1832 stream << indentation(1)
1833 << "// Dump the value on the buses into a file once in clock cycle"
1834 << endl
1835 << indentation(1)
1836 << "// setting DUMP false will disable dumping" << endl << endl
1837 << indentation(1) << "// Do not synthesize!" << endl
1838 << indentation(1) << "//synthesis translate_off" << endl
1839 << indentation(1) << "integer regularfileout;" << endl << endl
1840 << indentation(1) << "integer executionfileout;" << endl << endl
1841 << indentation(1) << "integer count=0;" << endl
1842 << indentation(1) << "integer executioncount=0;" << endl << endl
1843 << indentation(1) << "`define REGULARDUMPFILE \"bus.dump\""
1844 << indentation(1)
1845 << "`define EXECUTIONDUMPFILE \"execbus.dump\""
1846 << endl << endl
1847
1848 << indentation(1) << "initial" << endl
1849 << indentation(1) << "begin" << endl
1850 << indentation(2)
1851 << "regularfileout = $fopen(`REGULARDUMPFILE,\"w\");" << endl
1852 << indentation(2) << "$fclose(regularfileout);" << endl
1853 << indentation(2)
1854 << "executionfileout = $fopen(`EXECUTIONDUMPFILE,\"w\");"
1855 << endl
1856 << indentation(2) << "$fclose(executionfileout);" << endl
1857 << indentation(2) << "forever" << endl
1858 << indentation(2) << "begin" << endl
1859 << indentation(3) << "#PERIOD;" << endl;
1860 if (busTraceStartingCycle_ > 0) {
1861 stream << indentation(3) << "if(count > "
1863 << ")" << endl;
1864 }
1865 std::string format_string = "%0d";
1866 std::string count_string = "count - " +
1868 std::string variable_list = "";
1869
1871 for (int i = 0; i < busNav.count(); i++) {
1872 const Bus& bus = *busNav.item(i);
1873 format_string += ",%0"
1874 + Conversion::toString((bus.width()+3)/4) + "h";
1875 variable_list += ", $unsigned(" +
1877 }
1878
1879 stream << indentation(3) << "begin" << endl
1880 << indentation(4) << "regularfileout = "
1881 "$fopen(`REGULARDUMPFILE,\"a\");" << endl
1882 << indentation(4) << "$fwrite(regularfileout,"
1883 << "\"" << format_string << "\\n\"" << ", "
1884 << count_string << variable_list << ");" << endl
1885 << indentation(4) << "$fclose(regularfileout);" << endl
1886 << indentation(4) << "if(glock == 0)" << endl
1887 << indentation(4) << "begin" << endl
1888 << indentation(5) << "executionfileout = "
1889 "$fopen(`EXECUTIONDUMPFILE,\"a\");" << endl
1890 << indentation(5) << "$fwrite(executionfileout,"
1891 << "\"" << format_string << "\\n\"" << ", executioncount"
1892 << variable_list << ");" << endl
1893 << indentation(5) << "$fclose(executionfileout);" << endl
1894 << indentation(5) << "executioncount = executioncount + 1;"
1895 << endl
1896 << indentation(4) << "end" << endl
1897 << indentation(3) << "end" << endl
1898 << indentation(3) << "count = count + 1;" << endl
1899 << indentation(2) << "end" << endl
1900 << indentation(1) << "end" << endl
1901 << indentation(1) << "//synthesis translate_on" << endl;
1902 }
1903}
1904
1905/**
1906 * Checks if given bus is connected to at least one socket.
1907 *
1908 * @param bus The bus.
1909 * @return True if bus is connected to some socket, false if bus is
1910 * unconnected.
1911 */
1912bool
1914 std::set<Socket*> inputSockets;
1915 for (int i = 0; i < bus.segmentCount(); i++) {
1916 Segment* segment = bus.segment(i);
1917 if (segment->connectionCount() > 0) {
1918 return true;
1919 }
1920 }
1921 return false;
1922}
1923
1924/**
1925 * Returns a set of all the input sockets that are connected to the
1926 * given bus.
1927 *
1928 * @param bus The bus.
1929 * @return The socket set.
1930 */
1931std::set<Socket*>
1933 std::set<Socket*> inputSockets;
1934 for (int i = 0; i < bus.segmentCount(); i++) {
1935 Segment* segment = bus.segment(i);
1936 for (int i = 0; i < segment->connectionCount(); i++) {
1937 Socket* socket = segment->connection(i);
1938 if (socket->direction() == Socket::INPUT) {
1939 inputSockets.insert(socket);
1940 }
1941 }
1942 }
1943 return inputSockets;
1944}
1945
1946/**
1947 * Returns a set of all the output sockets that are connected to the
1948 * given bus.
1949 *
1950 * @param bus The bus.
1951 * @return The socket set.
1952 */
1953std::set<Socket*>
1955 std::set<Socket*> outputSockets;
1956 for (int i = 0; i < bus.segmentCount(); i++) {
1957 Segment* segment = bus.segment(i);
1958 for (int i = 0; i < segment->connectionCount(); i++) {
1959 Socket* socket = segment->connection(i);
1960 if (socket->direction() == Socket::OUTPUT) {
1961 outputSockets.insert(socket);
1962 }
1963 }
1964 }
1965 return outputSockets;
1966}
1967
1968
1969/**
1970 * Tells whether the given socket set contains similar socket to the
1971 * given one.
1972 *
1973 * @param set The socket set.
1974 * @param socket The socket.
1975 * @return True if the set contains similar socket, otherwise false.
1976 */
1977bool
1979 return socketIsGenerated(
1980 socket.segmentCount(), socket.portCount(), socket.direction());
1981}
1982
1983/**
1984 * Tells whether the given socket set contains similar socket to the
1985 * given one.
1986 *
1987 * @param set The socket set.
1988 * @param socket The socket.
1989 * @return True if the set contains similar socket, otherwise false.
1990 */
1991bool
1993 int segmentConns, int portConns, Socket::Direction direction) {
1994 auto test_pair = std::make_pair(portConns, segmentConns);
1995
1996 if (direction == Socket::INPUT) {
1997 return generatedInputSockets_.count(test_pair) == 1;
1998 } else if (direction == Socket::OUTPUT) {
1999 return generatedOutputSockets_.count(test_pair) == 1;
2000 } else {
2001 assert(false);
2002 }
2003}
2004
2005/**
2006 * Returns the control value that selects the given port if the socket
2007 * is connected to several ports.
2008 *
2009 * @param socket The socket.
2010 * @param port The port.
2011 * @return The control value.
2012 * @exception NotAvailable If the given socket does not need data control or if the
2013 * given port is not attached to the socket.
2014 */
2015int
2017 const TTAMachine::Socket& socket, const TTAMachine::Port& port) const {
2018 if (socket.direction() != Socket::OUTPUT) {
2019 throw NotAvailable(__FILE__, __LINE__, __func__);
2020 }
2021
2022 for (int i = 0; i < socket.portCount(); i++) {
2023 if (socket.port(i) == &port) {
2024 return i;
2025 }
2026 }
2027
2028 throw NotAvailable(__FILE__, __LINE__, __func__);
2029}
2030
2031/**
2032 * Returns the control value that selects the given segment if the given input
2033 * socket is connected to several segments.
2034 *
2035 * @param socket The socket.
2036 * @param segment The segment.
2037 * @return The control value.
2038 * @exception NotAvailable If the socket does not need control or if it is not
2039 * connected to the given segment.
2040 */
2041int
2043 const TTAMachine::Socket& socket,
2044 const TTAMachine::Segment& segment) const {
2045 if (busControlWidth(socket.direction(), socket.segmentCount()) < 1) {
2046 throw NotAvailable(__FILE__, __LINE__, __func__);
2047 }
2048
2049 for (int i = 0; i < socket.segmentCount(); i++) {
2050 Segment* seg = socket.segment(i);
2051 if (seg == &segment) {
2052 return i;
2053 }
2054 }
2055
2056 throw NotAvailable(__FILE__, __LINE__, __func__);
2057}
2058
2063/**
2064 * Calculates the width of the data port of the given input socket.
2065 *
2066 * @param socket The socket.
2067 * @return The width of the data port.
2068 */
2069int
2071 assert(socket.direction() == Socket::INPUT);
2072 int width = 0;
2073 for (int i = 0; i < socket.portCount(); i++) {
2074 Port* port = socket.port(i);
2075 if (width < port->width()) {
2076 width = port->width();
2077 }
2078 }
2079 return width;
2080}
2081
2082
2083/**
2084 * Returns the width of the data port of the given output socket.
2085 *
2086 * @param socket The socket.
2087 * @param port The port.
2088 */
2089int
2091 const TTAMachine::Socket& socket,
2092 int port) {
2093
2094 assert(socket.direction() == Socket::OUTPUT);
2095 assert(port < socket.portCount());
2096 return socket.port(port)->width();
2097}
2098
2099
2100/**
2101 * Returns the maximum width of the data ports of the given output socket.
2102 *
2103 * @param socket The socket.
2104 */
2105int
2107 const TTAMachine::Socket& socket) {
2108 int maxPortWidth = 0;
2109 assert(socket.direction() == Socket::OUTPUT);
2110 for (int i = 0; i < socket.portCount(); i++) {
2111 Port* port = socket.port(i);
2112 if (maxPortWidth < port->width()) {
2113 maxPortWidth = port->width();
2114 }
2115 }
2116 return maxPortWidth;
2117}
2118
2119
2120/**
2121 * Returns the number of bits required to control the bus connections of
2122 * the given socket.
2123 *
2124 * @param direction Direction of the socket.
2125 * @param busConns The number of bus connections.
2126 * @return The control width.
2127 */
2128int
2131 int busConns) {
2132
2133 assert(busConns >= 1);
2134
2135 if (direction == Socket::INPUT) {
2136 return MathTools::bitLength(busConns - 1);
2137 } else {
2138 return busConns;
2139 }
2140}
2141
2142
2143/**
2144 * Returns the number of bits required to control from which port the
2145 * data is written to the bus.
2146 *
2147 * @param socket Direction of the socket,
2148 * @param portConns The number of port connections.
2149 * @return The control width.
2150 */
2151int
2154 int portConns) {
2155 if (direction == Socket::OUTPUT) {
2156 return MathTools::bitLength(portConns - 1);
2157 } else {
2158 return 0;
2159 }
2160}
2161
2162
2163/**
2164 * Returns the required width of the short immediate port of the given bus.
2165 *
2166 * @param bus The bus.
2167 * @return The width of the port.
2168 */
2169int
2171 if (bus.signExtends()) {
2172 return bus.width();
2173 } else if (bus.zeroExtends()) {
2174 return bus.immediateWidth();
2175 } else {
2176 assert(false && "Unknown extension policy.");
2177 return -1;
2178 }
2179}
2180
2181
2182/**
2183 * Returns the name of the data port of the given input socket in the
2184 * interconnection network.
2185 *
2186 * @param socket The socket.
2187 * @return The name of the data port.
2188 */
2189std::string
2191 return "socket_" + socket + "_data";
2192}
2193
2194
2195/**
2196 * Returns the name of the data port of the given output socket in the
2197 * interconnection network.
2198 *
2199 * @param socket The socket name.
2200 * @param port The data port number.
2201 * @return The name of the data port.
2202 */
2203std::string
2205 const std::string& socket,
2206 int port) {
2207
2208 return "socket_" + socket + "_data" + Conversion::toString(port);
2209}
2210
2211
2212/**
2213 * Returns the name of the bus connection control port of the given
2214 * socket.
2215 *
2216 * @param name Name of the socket.
2217 * @return The name of the control port.
2218 */
2219std::string
2221 return "socket_" + name + "_bus_cntrl";
2222}
2223
2224
2225/**
2226 * Returns the name of the data control port of the given socket.
2227 *
2228 * @param name Name of the socket.
2229 * @return The name of the control port.
2230 */
2231std::string
2233 return "socket_" + name + "_data_cntrl";
2234}
2235
2236
2237/**
2238 * Returns the name of the data port for short immediate of the given bus.
2239 *
2240 * @param busName Name of the bus.
2241 * @return The name of the port.
2242 */
2243std::string
2244DefaultICGenerator::simmDataPort(const std::string& busName) {
2245 return "simm_" + busName;
2246}
2247
2248
2249/**
2250 * Returns the name of the control port for short immediate of the given
2251 * bus.
2252 *
2253 * @param busName Name of the bus.
2254 * @return The name of the port.
2255 */
2256std::string
2257DefaultICGenerator::simmControlPort(const std::string& busName) {
2258 return "simm_cntrl_" + busName;
2259}
2260
2261
2262/**
2263 * Returns the name of the data bus port in input socket.
2264 *
2265 * @param bus The bus number.
2266 * @return The name of the port.
2267 */
2268std::string
2270 return "databus" + Conversion::toString(bus);
2271}
2272
2273
2274/**
2275 * Returns the name of the data bus port in output socket.
2276 *
2277 * @param bus The bus number.
2278 * @return The name of the port.
2279 */
2280std::string
2282 return "databus" + Conversion::toString(bus) + "_alt";
2283}
2284
2285
2286/**
2287 * Returns the name of the data port in output socket.
2288 *
2289 * @param port The port number.
2290 * @return The name of the port.
2291 */
2292std::string
2294 return "data" + Conversion::toString(port);
2295}
2296
2297std::string
2299 return bus.name() + "_data_" + Conversion::toString(index) + "_in";
2300}
2301
2302std::string
2304 return bus.name() + "_mux_ctrl_in";
2305}
2306
2307std::string
2309 return bus.name() + "_mux_enable_in";
2310}
2311
2312/**
2313 * Returns the name of the signal of the given bus.
2314 *
2315 * @param bus The bus.
2316 * @return The name of the signal.
2317 */
2318std::string
2320 return "databus_" + bus.name();
2321}
2322
2323
2324/**
2325 * Returns the signal name of the given bus for the given output socket.
2326 *
2327 * @param bus The bus.
2328 * @param socket The socket.
2329 * @return The signal name.
2330 */
2331std::string
2333 const TTAMachine::Bus& bus,
2334 const TTAMachine::Socket& socket) {
2335 assert(socket.direction() == Socket::OUTPUT);
2337 SocketSignalMap* newMap = new SocketSignalMap;
2338 altSignalMap_.emplace(&bus, newMap);
2339 }
2340
2341 SocketSignalMap* signalMap = altSignalMap_[&bus];
2342 if (!MapTools::containsKey(*signalMap, &socket)) {
2343 int maxValue = -1;
2344 for (auto iter = signalMap->begin(); iter != signalMap->end();
2345 iter++) {
2346 if ((*iter).second > maxValue) {
2347 maxValue = (*iter).second;
2348 }
2349 }
2350 maxValue++;
2351 signalMap->emplace(&socket, maxValue);
2352 }
2353
2354 int value = signalMap->at(&socket);
2355 return busSignal(bus) + "_alt" + Conversion::toString(value);
2356}
2357
2358
2359/**
2360 * Returns the generic name for width of the given bus.
2361 *
2362 * @param bus The bus number.
2363 * @return The generic name.
2364 */
2365std::string
2367 return "BUSW_" + Conversion::toString(bus);
2368}
2369
2370
2371/**
2372 * Returns the generic name for width of the given port.
2373 *
2374 * @param port The port number.
2375 * @return The generic name.
2376 */
2377std::string
2379 return "DATAW_" + Conversion::toString(port);
2380}
2381
2382
2383/**
2384 * Returns the name of the socket for short immediate of the given bus.
2385 *
2386 * @param bus The bus.
2387 * @return The name of the socket.
2388 */
2389std::string
2391 return "simm_socket_" + bus.name();
2392}
2393
2394
2395/**
2396 * Returns the name of the signal of short immediate of the given bus.
2397 *
2398 * @param bus The bus.
2399 * @return The name of the signal.
2400 */
2401std::string
2403 return "databus_" + bus.name() + "_simm";
2404}
2405
2406
2407/**
2408 * Converts the given socket direction to direction of the corresponding
2409 * data port in the IC block.
2410 *
2411 * @param direction The socket direction.
2412 * @return The direction of the corresponding socket data port in IC
2413 * block.
2414 */
2418 switch (direction) {
2419 case Socket::INPUT:
2420 return ProGe::OUT;
2421 case Socket::OUTPUT:
2422 return ProGe::IN;
2423 case Socket::UNKNOWN:
2424 assert(false);
2425 }
2426
2427 assert(false);
2428}
2429
2430/**
2431 * Generates file where to write VHDL definition of the given socket.
2432 *
2433 * @param direction Direction of the socket.
2434 * @param portConns Number of port connections.
2435 * @param segmentConns Number of segment connections.
2436 * @return The file name.
2437 */
2438std::string
2440 const ProGe::HDL language,
2442 int portConns,
2443 int segmentConns) {
2444
2445 if (direction == Socket::INPUT) {
2446 return "input_mux_" + Conversion::toString(segmentConns) +
2447 ((language == VHDL) ? ".vhdl" : ".v");
2448 } else if (direction == Socket::OUTPUT) {
2449 return "output_socket_" +
2450 Conversion::toString(segmentConns) + "_" +
2451 Conversion::toString(portConns) + ((language==VHDL)?".vhdl":".v");
2452 } else {
2453 assert(false);
2454 }
2455}
2456
2457/**
2458 * Generates VHDL entity name for the given socket.
2459 *
2460 * @param direction Direction of the socket.
2461 * @return The entity name.
2462 */
2463std::string
2465 if (socket.direction() == Socket::INPUT) {
2466 return inputMuxEntityName(socket.segmentCount());
2467 } else if (socket.direction() == Socket::OUTPUT) {
2469 socket.segmentCount(), socket.portCount());
2470 } else {
2471 assert(false);
2472 }
2473}
2474
2475/**
2476 * Returns the entity name of the input socket which has the given number
2477 * of connections.
2478 *
2479 * @param conns The number of connections.
2480 * @return The name of the entity.
2481 */
2482std::string
2484 return entityNameStr_ + "_input_mux_" + Conversion::toString(conns);
2485}
2486
2487/**
2488 * Returns the entity name of the output socket which has the given number
2489 * of connections.
2490 *
2491 * @param busConns The number of bus connections.
2492 * @param portConns The number of port connections.
2493 * @return The name of the entity.
2494 */
2495std::string
2496DefaultICGenerator::outputSocketEntityName(int busConns, int portConns) const {
2497 return entityNameStr_ + "_output_socket_cons_" +
2498 Conversion::toString(busConns) + "_" +
2499 Conversion::toString(portConns);
2500}
2501
2502std::string
2504 return bus.name() + "_bus_mux_inst";
2505}
2506
2507/**
2508 * Generates an indentation of the given level.
2509 *
2510 * @param level The level.
2511 */
2512std::string
2514 string indentation("");
2515 for (unsigned int i = 0; i < level; i++) {
2516 indentation += " ";
2517 }
2518 return indentation;
2519}
2520
#define __func__
#define abortWithError(message)
#define assert(condition)
const string INPUT_SOCKET_DATAW_GENERIC
const string INPUT_SOCKET_DATA_PORT
const string SOCKET_DATA_CONTROL_PORT
const string SOCKET_BUS_CONTROL_PORT
TTAMachine::Machine * machine
the architecture definition of the estimated processor
find Finds info of the inner loops in the false
#define DS
void mapDataCntrlPortOfSocket(const std::string &socketName, ProGe::NetlistPort &port)
void setGlockPort(ProGe::NetlistPort &glockPort)
void mapSImmDataPort(const std::string &busName, ProGe::NetlistPort &port)
void mapSImmCntrlPort(const std::string &busName, ProGe::NetlistPort &port)
void mapBusCntrlPortOfSocket(const std::string &socketName, ProGe::NetlistPort &port)
static std::string toBinary(unsigned int source, unsigned int stringWidth=0)
static std::string toString(const T &source)
void verifyCompatibility() const
static std::set< TTAMachine::Socket * > inputSockets(const TTAMachine::Bus &bus)
static std::string busMuxEntityName(TTAMachine::Bus &bus)
std::string socketEntityName(TTAMachine::Socket &socket) const
static std::string simmSocket(const TTAMachine::Bus &bus)
std::string outputSocketEntityName(int busConns, int portConns) const
static std::string inputSocketBusPort(int bus)
void setBusTraceStartingCycle(unsigned int cycle)
void setGenerateBusTrace(bool generate)
virtual int outputSocketDataControlValue(const TTAMachine::Socket &socket, const TTAMachine::Port &port) const
std::map< const TTAMachine::Socket *, int > SocketSignalMap
static ProGe::Direction convertDirection(TTAMachine::Socket::Direction direction)
static std::string simmSignal(const TTAMachine::Bus &bus)
static std::string simmControlPort(const std::string &busName)
static int maxOutputSocketDataPortWidth(const TTAMachine::Socket &socket)
static std::string socketFileName(const ProGe::HDL language, TTAMachine::Socket::Direction direction, int portConns, int segmentConns)
const TTAMachine::Machine & machine_
The machine.
void SetHDL(ProGe::HDL language)
void declareSocketEntities(std::ostream &stream) const
static int outputSocketDataPortWidth(const TTAMachine::Socket &socket, int port)
virtual int inputSocketControlValue(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment) const
static void writeInputSocketComponentDeclaration(const ProGe::HDL language, int segmentConns, int ind, std::ostream &stream)
static std::string indentation(unsigned int level)
std::string busAltSignal(const TTAMachine::Bus &bus, const TTAMachine::Socket &socket)
static bool isBusConnected(const TTAMachine::Bus &bus)
virtual const BusSocketMap getBusConnections() const
static std::string dataWidthGeneric(int port)
void generateInputSocketRuleForBus(int bus, int ind, std::ofstream &stream) const
BusAltSignalMap altSignalMap_
Signal numbers for controlling sockets.
void generateSocket(TTAMachine::Socket::Direction direction, int portConns, int segmentConns, const std::string &dstDirectory) const
void generateOutputSocket(int portConns, int segmentConns, std::ofstream &stream) const
void createSignalsForIC(std::ostream &stream)
std::set< std::pair< int, int > > generatedOutputSockets_
bool socketIsGenerated(const TTAMachine::Socket &socket)
static std::set< TTAMachine::Socket * > outputSockets(const TTAMachine::Bus &bus)
void writeBusDumpCode(std::ostream &stream) const
void addICToNetlist(const ProGe::NetlistGenerator &generator, ProGe::NetlistBlock &netlistBlock)
static std::string simmDataPort(const std::string &busName)
static std::string outputSocketBusPort(int bus)
virtual int outputSocketCntrlPinForSegment(const TTAMachine::Socket &socket, const TTAMachine::Segment &segment) const
static std::string outputSocketDataPort(const std::string &socket, int port)
void setExportBustrace(bool export_bt)
void generateSocketsAndMuxes(const std::string &dstDirectory)
std::set< std::pair< int, int > > generatedInputSockets_
static int dataControlWidth(TTAMachine::Socket::Direction direction, int portConns)
void generateInterconnectionNetwork(const std::string &dstDirectory)
static std::string busWidthGeneric(int bus)
static int simmPortWidth(const TTAMachine::Bus &bus)
static std::string busMuxDataPort(const TTAMachine::Bus &bus, int index)
ProGe::NetlistBlock * icBlock_
The netlist block of IC.
static std::string socketBusControlPort(const std::string &name)
unsigned int busTraceStartingCycle_
The starting cycle for bus tracing.
static std::string busSignal(const TTAMachine::Bus &bus)
void generateInputMux(int segmentConns, std::ofstream &stream) const
std::string inputMuxEntityName(int conns) const
void writeBustraceExportCode(std::ostream &stream) const
static int busControlWidth(TTAMachine::Socket::Direction direction, int busConns)
static std::string socketDataControlPort(const std::string &name)
static int inputSocketDataPortWidth(const TTAMachine::Socket &socket)
bool generateBusTrace_
Tells whether to generate bus tracing code.
void writeInterconnectionNetwork(std::ostream &stream)
bool isGcuPort(const TTAMachine::Port *port) const
static std::string busMuxControlPort(const TTAMachine::Bus &bus)
static std::string inputSocketDataPort(const std::string &socket)
bool exportBustrace_
Tells whether to export bustraces to debugger.
DefaultICGenerator(const TTAMachine::Machine &machine)
static std::string busMuxEnablePort(const TTAMachine::Bus &bus)
std::map< const TTAMachine::Bus *, std::set< TTAMachine::Socket * > > BusSocketMap
static void writeOutputSocketComponentDeclaration(const ProGe::HDL language, int portConns, int segmentConns, int ind, std::ostream &stream)
static bool createFile(const std::string &file)
static const std::string DIRECTORY_SEPARATOR
static bool containsKey(const MapType &aMap, const KeyType &aKey)
static unsigned int bitLength(long unsigned int number)
const std::string & moduleName() const
void addSubBlock(BaseNetlistBlock *subBlock, const std::string &instanceName="")
virtual NetlistPort * port(const std::string &portName, bool partialMatch=true)
virtual const Netlist & netlist() const
static const std::string DECODER_CLOCK_PORT
Clock port name in instruction decoder.
NetlistPort & gcuReturnAddressInPort() const
NetlistPort & gcuReturnAddressOutPort() const
NetlistPort & netlistPort(const TTAMachine::Port &port, Direction dir=IN) const
static const std::string DECODER_RESET_PORT
Reset port name in instruction decoder.
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)
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
bool zeroExtends() const
Definition Bus.cc:182
virtual int segmentCount() const
Definition Bus.cc:385
virtual TCEString name() const
SpecialRegisterPort * returnAddressPort() const
bool hasReturnAddressPort() const
virtual BaseFUPort * triggerPort() const
virtual BaseFUPort * port(const std::string &name) const
ComponentType * item(int index) const
virtual BridgeNavigator bridgeNavigator() const
Definition Machine.cc:404
virtual SocketNavigator socketNavigator() const
Definition Machine.cc:368
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
bool isRISCVMachine() const
Definition Machine.cc:1057
virtual int width() const =0
const Connection & connection(const Socket &socket) const
Definition Segment.cc:250
int connectionCount() 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
@ UNKNOWN
Unknown direction.
Definition Socket.hh:61
Direction direction() const
bool hasDataPortWidth() const
Definition Socket.cc:410
void setDataPortWidth(const std::string &width)
Definition Socket.cc:420
Port * port(int index) const
Definition Socket.cc:266
Segment * segment(int index) const
Definition Socket.cc:401
int segmentCount() const
int portCount() const
const std::string & dataPortWidth() const
Definition Socket.cc:415
virtual int portCount() const
Definition Unit.cc:135
Definition FUGen.hh:54
@ BIT
One bit.
Definition ProGeTypes.hh:47
@ BIT_VECTOR
Several bits.
Definition ProGeTypes.hh:48
Direction
Direction of the port.
Definition ProGeTypes.hh:52
@ 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