OpenASIP 2.2
Loading...
Searching...
No Matches
VHDLNetlistWriter.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 VHDLNetlistWriter.cc
26 *
27 * Implementation of VHDLNetlistWriter 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 * @note rating: red
33 */
34
35#include <iostream>
36#include <fstream>
37#include <string>
38#include <set>
39#include <cctype>
40#include <algorithm>
41
42#include "VHDLNetlistWriter.hh"
43#include "Netlist.hh"
44#include "BaseNetlistBlock.hh"
45#include "NetlistPort.hh"
46#include "Parameter.hh"
47
48#include "FileSystem.hh"
49#include "Conversion.hh"
50#include "ContainerTools.hh"
51#include "AssocTools.hh"
52#include "StringTools.hh"
53
54using std::string;
55using std::endl;
56using std::ofstream;
57using std::set;
58using std::pair;
59
60const std::string GROUND_SIGNAL = "ground_signal";
61const std::string PARAM_STRING = "string";
62
63namespace ProGe {
64
65/**
66 * Constructor. Records the input netlist for which it can generate VHDL.
67 *
68 * @param netlist The input netlist.
69 */
71 : NetlistWriter(targetBlock), groundWidth_(0) {}
72
73/**
74 * The destructor.
75 */
78
79
80/**
81 * Generates the VHDL files and writes them to the given directory.
82 *
83 * @param dstDirectory The destination directory.
84 * @exception IOException If an IO error occurs.
85 * @exception InvalidData If the netlist is invalid.
86 */
87void
88VHDLNetlistWriter::write(const std::string& dstDirectory) {
89 if (targetNetlistBlock().netlist().isEmpty()) {
90 string errorMsg = "Empty input netlist.";
91 throw InvalidData(__FILE__, __LINE__, __func__, errorMsg);
92 }
93 writeNetlistParameterPackage(dstDirectory);
94 writeBlock(targetNetlistBlock(), dstDirectory);
95}
96
97/**
98 * Writes the package that defines parameters of the netlist.
99 *
100 * @param dstDirectory The destination directory.
101 */
102void
104 const std::string& dstDirectory) const {
105
106 string fileName = dstDirectory + FileSystem::DIRECTORY_SEPARATOR +
107 netlistParameterPkgName() + "_pkg.vhdl";
108 ofstream outFile;
109 outFile.open(fileName.c_str(), ofstream::out);
110
111 outFile << "package " << netlistParameterPkgName() << " is" << endl;
112 for (size_t i = 0; i < targetNetlistBlock().netlist().parameterCount();
113 i++) {
115 outFile << indentation(1) << "constant " << param.name() << " : "
116 << param.type() << " := " << param.value() << ";" << endl;
117 }
118 outFile << "end " << netlistParameterPkgName() << ";" << endl;
119}
120
121
122/**
123 * Returns the name of the netlist parameter package.
124 *
125 * @return The name.
126 */
127std::string
131
132
133/**
134 * Writes the given block of the netlist to the given destination directory.
135 *
136 * @param block The netlist block.
137 * @param dstDirectory The destination directory.
138 * @exception IOException If the file cannot be created.
139 */
140void
142 const BaseNetlistBlock& block, const std::string& dstDirectory) {
143 string fileName = dstDirectory + FileSystem::DIRECTORY_SEPARATOR +
144 block.moduleName() + ".vhdl";
145 if (!FileSystem::fileIsCreatable(fileName) &&
146 !(FileSystem::fileExists(fileName) &&
147 FileSystem::fileIsWritable(fileName))) {
148
149 string errorMsg = "Unable to create file: " + fileName;
150 throw IOException(__FILE__, __LINE__, __func__, errorMsg);
151 }
152
153 const string entityName = block.moduleName();
154
155 ofstream outFile;
156 outFile.open(fileName.c_str(), ofstream::out);
157
158 outFile << "library IEEE;" << endl;
159 outFile << "use IEEE.std_logic_1164.all;" << endl;
160 outFile << "use IEEE.std_logic_arith.all;" << endl;
161 outFile << "use work.tce_util.all;" << endl;
162
163 for (size_t i = 0; i < block.packageCount(); i++) {
164 outFile << "use work." << block.package(i) << ".all;" << endl;
165 }
166
167 if (block.netlist().parameterCount() > 0) {
168 outFile << "use work." << netlistParameterPkgName() << ".all;"
169 << endl;
170 }
171
172 outFile << endl;
173
174 // create entity
175 outFile << "entity " + entityName + " is" << endl;
176
177 // create generics
178 writeGenericDeclaration(block, 1, indentation(1), outFile);
179
180 // create port declarations
181 outFile << endl;
182 writePortDeclaration(block, 1, indentation(1), outFile);
183
184 outFile << endl << "end " << entityName << ";" << endl;
185
186 // create architecture
187 outFile << endl;
188 string architectureName = "structural";
189 outFile << "architecture " << architectureName << " of "
190 << entityName << " is" << endl << endl;
191
192 writeSignalDeclarations(block, outFile);
193 outFile << endl;
194 writeComponentDeclarations(block, outFile);
195 outFile << endl;
196 outFile << "begin" << endl << endl;
197 writeSignalAssignments(block, outFile);
198 outFile << endl;
199 writePortMappings(block, outFile);
200 outFile << "end " + architectureName + ";" << endl;
201 outFile.close();
202}
203
204/**
205 * Writes the generic declarations of the given netlist block.
206 *
207 * @param block The netlist block.
208 * @param indentationLevel The indentation level where the generic declaration
209 * is written.
210 * @param indentation The string used as indentation (one level).
211 * @param stream The stream to write.
212 */
213void
215 const BaseNetlistBlock& block, unsigned int indentationLevel,
216 const std::string& indentation, std::ostream& stream) {
217 if (block.parameterCount() > 0) {
218 stream << endl;
219 stream << generateIndentation(indentationLevel, indentation)
220 << "generic (" << endl;
221 for (size_t i = 0; i < block.parameterCount(); i++) {
222 Parameter param = block.parameter(i);
223 stream << generateIndentation(indentationLevel + 1, indentation)
224 << param.name() << " : " << param.type();
225 if (param.defaultValue() != "") {
226 stream << " := ";
227 if (param.type().lower() == PARAM_STRING) {
228 // string literal needs quot. marks
229 if (!param.defaultValue().startsWith("\""))
230 stream << "\"";
231 stream << param.value();
232 if (!param.defaultValue().endsWith("\"")) stream << "\"";
233 } else {
234 stream << param.defaultValue();
235 }
236 }
237 if (i + 1 == block.parameterCount()) {
238 stream << ");";
239 } else {
240 stream << ";";
241 }
242 stream << endl;
243 }
244 }
245}
246
247/**
248 * Writes the port declaration of the given netlist block.
249 *
250 * @param block The netlist block.
251 * @param indentationLevel The indentation level where the generic declaration
252 * is written.
253 * @param indentation The string used as indentation (one level).
254 * @param stream The stream to write.
255 */
256void
258 const BaseNetlistBlock& block, unsigned int indentationLevel,
259 const std::string& indentation, std::ostream& stream) {
260 stream << generateIndentation(indentationLevel, indentation) << "port ("
261 << endl;
262
263 for (size_t i = 0; i < block.portCount(); i++) {
264 const NetlistPort& port = block.port(i);
265 string portName = port.name();
266 string direction = directionString(port.direction());
267 stream << generateIndentation(indentationLevel+1, indentation)
268 << portName << " : " << direction << " ";
269 if (port.dataType() == BIT) {
270 stream << "std_logic";
271 } else {
272 stream << "std_logic_vector(";
273 // zero width ports as (0 downto 0)
274 if (isNumber(port.widthFormula()) &&
275 Conversion::toInt(port.widthFormula()) == 0) {
276 stream << "0";
277 } else if (isNumber(port.widthFormula())) {
278 stream << Conversion::toInt(port.widthFormula()) - 1;
279 } else {
280 stream << port.widthFormula() << "-1";
281 }
282 stream << " downto 0)";
283 }
284 if (i + 1 == block.portCount()) {
285 stream << ");";
286 } else {
287 stream << ";";
288 }
289 stream << endl;
290 }
291}
292
293/**
294 * Writes the VHDL signal declarations to the given stream.
295 *
296 * @param block The block of which the signals are written.
297 * @param stream The stream to write.
298 */
299void
301 const BaseNetlistBlock& block, std::ofstream& stream) {
302 // collect all the sub blocks to a set, lexicographical sort.
303 typedef std::set<const BaseNetlistBlock*, NetlistBlockNameComparator>
304 BlockSet;
305 BlockSet subBlocks;
306 for (size_t i = 0; i < block.subBlockCount(); i++) {
307 // ports belonging to virtual blocks have static values, thus they are
308 // excluded
309 if (!block.subBlock(i).isVirtual()) {
310 subBlocks.insert(&block.subBlock(i));
311 }
312 }
313
314 // create a signal for each port in the sub-blocks
315 for (BlockSet::const_iterator iter = subBlocks.begin();
316 iter != subBlocks.end(); iter++) {
317 const BaseNetlistBlock* subBlock = *iter;
318
319 for (size_t i = 0; i < subBlock->portCount(); i++) {
320 const NetlistPort& port = subBlock->port(i);
321
322 size_t vertexDescriptor = block.netlist().descriptor(port);
323 std::pair<out_edge_iterator, out_edge_iterator> edges =
324 boost::out_edges(vertexDescriptor, block.netlist());
325
326 if (edges.first != edges.second) {
327 edge_descriptor edgeDescriptor = *edges.first;
328 vertex_descriptor dstVertex =
329 boost::target(edgeDescriptor, block.netlist());
330 const NetlistPort* dstPort = block.netlist()[dstVertex];
331
332 if (&dstPort->parentBlock() != &block ||
333 boost::out_degree(vertexDescriptor, block.netlist()) >
334 1) {
335 stream << indentation(1) << "signal "
336 << portSignalName(port) << " : "
337 << portSignalType(port) << ";" << endl;
338 }
339 } else if (!port.hasStaticValue()) {
340 // assume the port is connected to ground if is is
341 // unconnected in the netlist
342 if (port.realWidthAvailable()) {
343 groundWidth_ =
344 std::max(port.realWidth(), groundWidth_);
345 }
346 stream << indentation(1) << "signal "
347 << portSignalName(port) << " : "
348 << portSignalType(port) << ";" << endl;
349 }
350 }
351 }
352
353 // create a ground signal
354 if (groundWidth_ > 0) {
355 stream << indentation(1) << "signal " << GROUND_SIGNAL
356 << " : std_logic_vector" << signalRange(groundWidth_ - 1, 0)
357 << ";" << endl;
358 }
359}
360
361/**
362 * Writes the signal assignments of the given block to the given stream.
363 *
364 * @param block The netlist block.
365 * @param stream The stream.
366 */
367void
369 const BaseNetlistBlock& block, std::ofstream& stream) const {
370 set<const BaseNetlistBlock*, NetlistBlockNameComparator> subBlocks;
371 for (size_t i = 0; i < block.subBlockCount(); i++) {
372 subBlocks.insert(&block.subBlock(i));
373 }
374
375 typedef std::vector<edge_descriptor> EdgeTable;
376 EdgeTable handledEdges;
377
378 for (size_t i = 0; i < block.subBlockCount(); i++) {
379 const BaseNetlistBlock& subBlock = block.subBlock(i);
380 for (size_t i = 0; i < subBlock.portCount(); i++) {
381 const NetlistPort& port = subBlock.port(i);
382 size_t vertexDescriptor = block.netlist().descriptor(port);
383 std::pair<out_edge_iterator, out_edge_iterator> edges =
384 boost::out_edges(vertexDescriptor, block.netlist());
385
386 while (edges.first != edges.second) {
387 edge_descriptor edgeDescriptor = *edges.first;
388 edges.first++;
390 handledEdges, edgeDescriptor)) {
391 vertex_descriptor srcVertex =
392 boost::source(edgeDescriptor, block.netlist());
393 vertex_descriptor dstVertex =
394 boost::target(edgeDescriptor, block.netlist());
395 NetlistPort* srcPort = block.netlist()[srcVertex];
396 NetlistPort* dstPort = block.netlist()[dstVertex];
397
398 if (&dstPort->parentBlock() == &block) {
399 if (boost::out_degree(
400 vertexDescriptor, block.netlist()) > 1) {
401 // Handle the rare case of multiple outputs
402 // through a wire signal. This isn't done normally
403 // because there would be an ugly wire signal for
404 // every clk, rstx, etc.
405 if (dstPort->direction() == OUT ||
406 srcPort->dataType() != dstPort->dataType()) {
408 block, stream, edgeDescriptor, srcPort,
409 dstPort);
410 }
411 }
412 continue;
413 }
414
415 assert(srcPort == &port);
417 subBlocks, &srcPort->parentBlock()) &&
419 subBlocks, &dstPort->parentBlock())) {
420 handledEdges.push_back(edgeDescriptor);
421 // add the opposite edge too
422 std::pair<edge_descriptor, bool> opposite =
423 boost::edge(
424 dstVertex, srcVertex, block.netlist());
425 assert(opposite.second);
426 assert(opposite.first != edgeDescriptor);
427 handledEdges.push_back(opposite.first);
428
430 block, stream, edgeDescriptor, srcPort, dstPort);
431 }
432 }
433 }
434 }
435 }
436
437 if (groundWidth_ > 0) {
438 stream << indentation(1) << GROUND_SIGNAL << " <= (others => '0');"
439 << endl;
440 }
441}
442
443void
445 const BaseNetlistBlock& block, std::ofstream& stream,
446 edge_descriptor edgeDescriptor, NetlistPort* srcPort,
447 NetlistPort* dstPort) const {
448 PortConnectionProperty property = block.netlist()[edgeDescriptor];
449 if (property.fullyConnected()) {
450 if (&dstPort->parentBlock() == &block) {
451 if (srcPort->direction() == OUT) {
452 stream << indentation(1) << dstPort->name()
453 << " <= " << portSignalName(*srcPort) << ";" << endl;
454 } else {
455 stream << indentation(1) << portSignalName(*srcPort)
456 << " <= " << dstPort->name() << ";" << endl;
457 }
458 } else {
459 if (srcPort->direction() == OUT) {
460 stream << indentation(1)
461 << signalAssignment(*dstPort, *srcPort) << endl;
462 } else {
463 stream << indentation(1)
464 << signalAssignment(*srcPort, *dstPort) << endl;
465 }
466 }
467 } else {
468 string srcPortSignal;
469 if (srcPort->dataType() == BIT) {
470 srcPortSignal = portSignalName(*srcPort);
471 } else {
472 if (dstPort->dataType() == BIT) {
473 srcPortSignal =
474 portSignalName(*srcPort) + "(" +
475 Conversion::toString(property.port1FirstBit()) + ")";
476 } else {
477 int high = property.port1FirstBit() + property.width() - 1;
478 int low = property.port1FirstBit();
479 srcPortSignal =
480 portSignalName(*srcPort) + signalRange(high, low, true);
481 }
482 }
483 string dstPortSignal;
484
485 if (&dstPort->parentBlock() == &block) {
486 dstPortSignal = dstPort->name();
487 } else {
488 dstPortSignal = portSignalName(*dstPort);
489 }
490 if (dstPort->dataType() != BIT) {
491 if (srcPort->dataType() == BIT) {
492 dstPortSignal +=
493 "(" + Conversion::toString(property.port2FirstBit()) +
494 ")";
495 } else {
496 int high = property.port2FirstBit() + property.width() - 1;
497 int low = property.port2FirstBit();
498 dstPortSignal += signalRange(high, low, true);
499 }
500 }
501
502 if (srcPort->direction() == OUT) {
503 stream << indentation(1) << dstPortSignal
504 << " <= " << srcPortSignal << ";" << endl;
505 } else {
506 stream << indentation(1) << srcPortSignal
507 << " <= " << dstPortSignal << ";" << endl;
508 }
509 }
510}
511
512/**
513 * Writes the component declarations of the given netlist block to the
514 * given stream.
515 *
516 * @param block The netlist block.
517 * @param stream The stream to write.
518 */
519void
521 const BaseNetlistBlock& block, std::ofstream& stream) const {
522 std::set<string> declaredModules;
523 for (size_t i = 0; i < block.subBlockCount(); i++) {
524 const BaseNetlistBlock& component = block.subBlock(i);
525 if (AssocTools::containsKey(declaredModules, component.moduleName())) {
526 continue;
527 }
528 // virtual NetlistBlocks are omitted
529 if (component.isVirtual()) {
530 continue;
531 }
532
533 declaredModules.insert(component.moduleName());
534 stream << indentation(1) << "component " << component.moduleName()
535 << " is" << endl;
536 if (component.parameterCount() > 0) {
537 stream << indentation(2) << "generic (" << endl;
538 for (size_t i = 0; i < component.parameterCount(); i++) {
539 Parameter param = component.parameter(i);
540 stream << indentation(3) << param.name() << " : "
541 << param.type();
542 if (i + 1 == component.parameterCount()) {
543 stream << ");";
544 } else {
545 stream << ";";
546 }
547 stream << endl;
548 }
549 }
550 stream << indentation(2) << "port (" << endl;
551 for (size_t i = 0; i < component.portCount(); i++) {
552 const NetlistPort& port = component.port(i);
553 stream << indentation(3) << port.name() << " : "
554 << directionString(port.direction()) << " ";
555 if (port.dataType() == BIT) {
556 stream << "std_logic";
557 } else {
558 stream << "std_logic_vector(";
559 stream << port.widthFormula();
560 if ((isNumber(port.widthFormula()) &&
561 (Conversion::toInt(port.widthFormula()) != 0)) ||
562 !isNumber(port.widthFormula())) {
563 stream << "-1";
564 }
565 stream << " downto 0)";
566 }
567 if (i + 1 == component.portCount()) {
568 stream << ");";
569 } else {
570 stream << ";";
571 }
572 stream << endl;
573 }
574 stream << indentation(1) << "end component;" << endl << endl;
575 }
576}
577
578/**
579 * Writes the port mappings of the given block to the given stream.
580 *
581 * @param block The netlist block.
582 * @param stream The stream to write.
583 */
584void
586 const BaseNetlistBlock& block, std::ofstream& stream) const {
587 for (size_t i = 0; i < block.subBlockCount(); i++) {
588 const BaseNetlistBlock& component = block.subBlock(i);
589
590 // virtual NetlistBlocks are omitted
591 if (component.isVirtual()) {
592 continue;
593 }
594
595 stream << indentation(1) << component.instanceName() << " : "
596 << component.moduleName() << endl;
597
598 // create generic map
599 if (component.parameterCount() > 0) {
600 stream << indentation(2) << "generic map (" << endl;
601 for (size_t i = 0; i < component.parameterCount(); i++) {
602 Parameter param = component.parameter(i);
603 stream << indentation(3) << param.name() << " => ";
604 if (param.type().lower() == PARAM_STRING) {
605 stream << genericMapStringValue(param.value());
606 } else {
607 stream << param.value();
608 }
609 if (i == component.parameterCount() - 1) {
610 stream << ")" << endl;
611 } else {
612 stream << "," << endl;
613 }
614 }
615 }
616
617 // create port map
618 stream << indentation(2) << "port map (" << endl;
619 for (size_t i = 0; i < component.portCount(); i++) {
620 const NetlistPort& port = component.port(i);
621 size_t vertexDescriptor = block.netlist().descriptor(port);
622 std::pair<out_edge_iterator, out_edge_iterator> edges =
623 boost::out_edges(vertexDescriptor, block.netlist());
624
625 string srcConn = port.name();
626 string dstConn = "";
627 if (edges.first != edges.second) {
628 edge_descriptor edgeDescriptor = *edges.first;
629 vertex_descriptor dstVertex =
630 boost::target(edgeDescriptor, block.netlist());
631 const NetlistPort* dstPort = block.netlist()[dstVertex];
632 PortConnectionProperty property =
633 block.netlist()[edgeDescriptor];
634
635 if (&dstPort->parentBlock() == &block) {
636 if (port.dataType() != dstPort->dataType()) {
637 int index = 0;
638 if (!property.fullyConnected() &&
639 dstPort->dataType() == BIT_VECTOR &&
640 port.dataType() == BIT) {
641 index = property.port2FirstBit();
642 }
643
644 if (port.dataType() == BIT) {
645 assert(dstPort->dataType() == BIT_VECTOR);
646 dstConn = dstPort->name() + "(" +
647 Conversion::toString(index) + ")";
648 } else {
649 assert(dstPort->dataType() == BIT);
650 if (port.widthFormula() == "1") {
651 srcConn += "(0)";
652 dstConn = dstPort->name();
653 } else {
654 dstConn = portSignalName(port);
655 }
656 }
657 } else {
658 if ((!property.fullyConnected() ||
659 dstPort->direction() == OUT) &&
660 boost::out_degree(
661 vertexDescriptor, block.netlist()) > 1) {
662 dstConn = portSignalName(port);
663 } else {
664 dstConn = dstPort->name();
665 }
666 }
667 } else {
668 dstConn = portSignalName(port);
669 }
670 } else {
671 dstConn = portSignalName(port);
672 }
673 stream << indentation(3) << srcConn << " => " << dstConn;
674 if (i+1 < component.portCount()) {
675 stream << "," << endl;
676 }
677 }
678 stream << ");" << endl << endl;
679 }
680}
681
682/**
683 * Returns the string that means the same direction as the given one in VHDL.
684 *
685 * @return The direction string.
686 */
687std::string
689 switch (direction) {
690 case IN:
691 return "in";
692 case OUT:
693 return "out";
694 case BIDIR:
695 return "inout";
696 default:
697 assert(false);
698 }
699
700 // dummy return
701 assert(false);
702 return "";
703}
704
705/**
706 * Tells whether the given string is a non-negative integer number.
707 *
708 * @param formula The string.
709 * @return True if the given string is a non-negative integer number.
710 */
711bool
712VHDLNetlistWriter::isNumber(const std::string& formula) {
713 int length = formula.length();
714 for (int i = 0; i < length; i++) {
715 if (!isdigit(formula[i])) {
716 return false;
717 }
718 }
719
720 return true;
721}
722
723/**
724 * Returns true if port uses single parameter of its parent block as port
725 * width.
726 */
727bool
729 const BaseNetlistBlock& parent = port.parentBlock();
730 return parent.hasParameter(port.widthFormula());
731}
732
733/**
734 * Returns a string which makes indetation of the given level.
735 *
736 * @param level The indentation level.
737 */
738std::string
739VHDLNetlistWriter::indentation(unsigned int level) const {
740 return StringTools::indent(level);
741}
742
743/**
744 * Generates an indentation string with the given parameters.
745 *
746 * @param indentationLevel The level of indentation.
747 * @param indentation The string used as indentation (one level).
748 * @return The indentation of the given level.
749 */
750std::string
752 unsigned int indentationLevel,
753 const std::string& indentation) {
754
755 string generatedInd("");
756 for (size_t i = 0; i < indentationLevel; i++) {
757 generatedInd += indentation;
758 }
759 return generatedInd;
760}
761
762
763/**
764 * Returns the name of the signal mapped to the given port.
765 *
766 * @param port The port.
767 */
768std::string
770 const BaseNetlistBlock* parentBlock = &port.parentBlock();
771 string signalName = "";
772 if (port.hasStaticValue()) {
773 string bit = "";
774 if (port.staticValue().is(StaticSignal::VCC)) {
775 bit = "1";
776 } else {
777 bit = "0";
778 }
779 if (port.dataType() == BIT) {
780 signalName = "'" + bit + "'";
781 } else {
782 signalName = "(others => '" + bit + "')";
783 }
784 } else {
785 signalName = parentBlock->instanceName() + "_" + port.name() +
786 "_wire";
787 }
788 return signalName;
789}
790
791
792/**
793 * Returns the type of the signal mapped to the given port.
794 *
795 * @param port The port.
796 */
797std::string
799 if (port.dataType() == BIT) {
800 return "std_logic";
801 } else {
802 if (port.realWidthAvailable()) {
803 int width = port.realWidth();
804 return "std_logic_vector" +
805 signalRange((width ? width - 1 : 0), 0);
806 } else if (isNumber(port.widthFormula()) &&
807 (Conversion::toInt(port.widthFormula()) == 0)) {
808 return "std_logic_vector" + signalRange(0, 0);
809 } else if (usesParameterWidth(port)) {
810 return "std_logic_vector(" + parameterWidthValue(port) +
811 "-1 downto 0)";
812 } else {
813 return "std_logic_vector(" + port.widthFormula() + "-1 downto 0)";
814 }
815 }
816}
817
818/**
819 * Tries to determine whether the string generic needs quot marks for
820 * generic mapping
821 *
822 * If string literal contains '.', or "__" it cannot be a valid
823 * VHDL label (i.e. another generic), thus it needs quotation marks.
824 *
825 * @param generic String generic value
826 * @return Generic mapping string
827 */
830
831 if (generic.startsWith("\"") && generic.endsWith("\"")) {
832 return generic;
833 }
834 std::vector<TCEString> unallowed;
835 unallowed.push_back(".");
836 unallowed.push_back("__");
837 for (size_t i = 0; i < unallowed.size(); i++) {
838 if (generic.find(unallowed.at(i)) != TCEString::npos) {
839 TCEString quoted;
840 quoted << "\"" << generic << "\"";
841 return quoted;
842 }
843 }
844 return generic;
845}
846
847/**
848 * Returns signal range i.e. (<high> downto <low>).
849 *
850 * Does not -1 the high index!
851 * If high == low and allowShort is true, just (<low>) is returned
852 *
853 * @param high MSB index
854 * @param low LSB index
855 * @param allowShort If true, skips 'downto' if high == low
856 * @return Signal range string
857 */
859VHDLNetlistWriter::signalRange(int high, int low, bool allowShort) {
860 if (high < low) {
861 TCEString msg;
862 msg << "High (" << high << ") boundary is smaller than low (" << low
863 << ") boundary!";
864 throw InvalidData(__FILE__, __LINE__, __func__, msg);
865 }
866
867 TCEString range = "(";
868 if (allowShort && high == low) {
869 range << low;
870 } else {
871 range << high << " downto " << low;
872 }
873 return range << ")";
874}
875
876/**
877 * Returns port width value of port that uses parameter as width.
878 */
883
884/**
885 * Writes suitable signal assignment code of two signals.
886 *
887 * The written code piece is "dst <= src;" with additional signal indexing
888 * in case the data types does not macth (i.e. BIT vs. BIT_VECTOR).
889 *
890 */
891std::string
893 const NetlistPort& dst, const NetlistPort& src) {
894 using std::string;
895
896 if (dst.dataType() == src.dataType()) {
897 return string(portSignalName(dst)) + " <= " + portSignalName(src) +
898 ";";
899 } else {
900 // Note assuming that one port is data type of BIT and other is
901 // BIT_VECTOR of width og one.
902 bool indexDst = (dst.dataType() == BIT_VECTOR);
903 return string(portSignalName(dst)) +
904 (indexDst ? string("(0) <= ") : string(" <= ")) +
905 portSignalName(src) +
906 (indexDst ? string(";") : string("(0);"));
907 }
908}
909
910} /* namespace ProGe */
#define __func__
#define assert(condition)
const std::string GROUND_SIGNAL
const std::string PARAM_STRING
const std::string GROUND_SIGNAL
const std::string PARAM_STRING
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
static bool containsValue(const ContainerType &aContainer, const ElementType &aKey)
static std::string toString(const T &source)
static int toInt(const T &source)
static const std::string DIRECTORY_SEPARATOR
static bool fileIsWritable(const std::string fileName)
static bool fileIsCreatable(const std::string fileName)
static bool fileExists(const std::string fileName)
virtual const BaseNetlistBlock & subBlock(size_t index) const
virtual size_t parameterCount() const
virtual bool hasParameter(const std::string &name) const
virtual size_t subBlockCount() const
virtual size_t packageCount() const
virtual const Parameter & parameter(const std::string &name) const
virtual const std::string & package(size_t idx) const
virtual bool isVirtual() const
virtual const NetlistPort & port(size_t index) const
const std::string & instanceName() const
virtual size_t portCount() const
const std::string & moduleName() const
virtual const Netlist & netlist() const
bool hasStaticValue() const
bool realWidthAvailable() const
std::string widthFormula() const
DataType dataType() const
const BaseNetlistBlock & parentBlock() const
Direction direction() const
std::string name() const
StaticSignal staticValue() const
int realWidth() const
const BaseNetlistBlock & targetNetlistBlock() const
size_t parameterCount() const
Definition Netlist.cc:422
size_t descriptor(const NetlistPort &port) const
Definition Netlist.cc:325
Parameter parameter(size_t index) const
Definition Netlist.cc:434
const TCEString & value() const
Definition Parameter.cc:143
const TCEString & defaultValue() const
Definition Parameter.cc:148
const TCEString & type() const
Definition Parameter.cc:138
const TCEString & name() const
Definition Parameter.cc:133
bool is(State state)
@ VCC
All port signals set to high.
static TCEString signalRange(int high, int low, bool allowShort=false)
boost::graph_traits< Netlist >::edge_descriptor edge_descriptor
virtual void write(const std::string &dstDirectory)
static void writePortDeclaration(const BaseNetlistBlock &block, unsigned int indentationLevel, const std::string &indentation, std::ostream &stream)
std::string indentation(unsigned int level) const
static std::string directionString(Direction direction)
void writeNetlistParameterPackage(const std::string &dstDirectory) const
VHDLNetlistWriter(const BaseNetlistBlock &targetBlock)
int groundWidth_
Width of the ground signal.
boost::graph_traits< Netlist >::vertex_descriptor vertex_descriptor
void writeComponentDeclarations(const BaseNetlistBlock &block, std::ofstream &stream) const
void writeSignalDeclarations(const BaseNetlistBlock &block, std::ofstream &stream)
static void writeGenericDeclaration(const BaseNetlistBlock &block, unsigned int indentationLevel, const std::string &indentation, std::ostream &stream)
static std::string signalAssignment(const NetlistPort &dst, const NetlistPort &src)
void writePortMappings(const BaseNetlistBlock &block, std::ofstream &stream) const
static std::string portSignalType(const NetlistPort &port)
std::string netlistParameterPkgName() const
void writeBlock(const BaseNetlistBlock &block, const std::string &dstDirectory)
static TCEString parameterWidthValue(const NetlistPort &port)
static bool usesParameterWidth(const NetlistPort &port)
static std::string portSignalName(const NetlistPort &port)
TCEString genericMapStringValue(const TCEString &generic) const
void writeSignalAssignments(const BaseNetlistBlock &block, std::ofstream &stream) const
void writeConnection(const BaseNetlistBlock &block, std::ofstream &stream, edge_descriptor edgeDescriptor, NetlistPort *srcPort, NetlistPort *dstPort) const
static bool isNumber(const std::string &formula)
static std::string generateIndentation(unsigned int level, const std::string &indentation)
static std::string indent(int level)
TCEString lower() const
Definition TCEString.cc:78
bool startsWith(const std::string &str) const
bool endsWith(const std::string &str) const
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
@ BIDIR
Bidirectional port.
Definition ProGeTypes.hh:55