OpenASIP  2.0
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 
54 using std::string;
55 using std::endl;
56 using std::ofstream;
57 using std::set;
58 using std::pair;
59 
60 const std::string GROUND_SIGNAL = "ground_signal";
61 const std::string PARAM_STRING = "string";
62 
63 namespace 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  */
77 }
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  */
87 void
88 VHDLNetlistWriter::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  */
102 void
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  */
127 std::string
129  return targetNetlistBlock().moduleName() + "_params";
130 }
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  */
140 void
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  */
213 void
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  */
256 void
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  */
299 void
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  */
367 void
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 
443 void
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  */
519 void
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  */
584 void
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  */
687 std::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  */
711 bool
712 VHDLNetlistWriter::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  */
727 bool
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  */
738 std::string
739 VHDLNetlistWriter::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  */
750 std::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  */
768 std::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  */
797 std::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  */
828 TCEString
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  */
858 TCEString
859 VHDLNetlistWriter::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  */
879 TCEString
881  return port.parentBlock().parameter(port.widthFormula()).value();
882 }
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  */
891 std::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 */
PARAM_STRING
const std::string PARAM_STRING
Definition: VHDLNetlistWriter.cc:61
ProGe::BaseNetlistBlock
Definition: BaseNetlistBlock.hh:59
Netlist.hh
FileSystem.hh
ProGe::NetlistPort::parentBlock
const BaseNetlistBlock & parentBlock() const
Definition: NetlistPort.cc:400
TCEString::lower
TCEString lower() const
Definition: TCEString.cc:78
ProGe::VHDLNetlistWriter::writeGenericDeclaration
static void writeGenericDeclaration(const BaseNetlistBlock &block, unsigned int indentationLevel, const std::string &indentation, std::ostream &stream)
Definition: VHDLNetlistWriter.cc:214
ProGe::VHDLNetlistWriter::writeConnection
void writeConnection(const BaseNetlistBlock &block, std::ofstream &stream, edge_descriptor edgeDescriptor, NetlistPort *srcPort, NetlistPort *dstPort) const
Definition: VHDLNetlistWriter.cc:444
TCEString::startsWith
bool startsWith(const std::string &str) const
ProGe::VHDLNetlistWriter::generateIndentation
static std::string generateIndentation(unsigned int level, const std::string &indentation)
Definition: VHDLNetlistWriter.cc:751
ProGe::BIT_VECTOR
@ BIT_VECTOR
Several bits.
Definition: ProGeTypes.hh:48
ProGe::VHDLNetlistWriter::parameterWidthValue
static TCEString parameterWidthValue(const NetlistPort &port)
Definition: VHDLNetlistWriter.cc:880
ProGe::BaseNetlistBlock::parameterCount
virtual size_t parameterCount() const
Definition: BaseNetlistBlock.cc:231
ProGe::Parameter::type
const TCEString & type() const
Definition: Parameter.cc:138
AssocTools::containsKey
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
ProGe::VHDLNetlistWriter::vertex_descriptor
boost::graph_traits< Netlist >::vertex_descriptor vertex_descriptor
Definition: VHDLNetlistWriter.hh:72
ProGe::NetlistPort::widthFormula
std::string widthFormula() const
Definition: NetlistPort.cc:316
ProGe::VHDLNetlistWriter::~VHDLNetlistWriter
virtual ~VHDLNetlistWriter()
Definition: VHDLNetlistWriter.cc:76
ProGe::VHDLNetlistWriter::directionString
static std::string directionString(Direction direction)
Definition: VHDLNetlistWriter.cc:688
ProGe::NetlistPort::direction
Direction direction() const
Definition: NetlistPort.cc:373
ProGe::BaseNetlistBlock::instanceName
const std::string & instanceName() const
Definition: BaseNetlistBlock.cc:135
ProGe::NetlistWriter
Definition: NetlistWriter.hh:47
ProGe::BIDIR
@ BIDIR
Bidirectional port.
Definition: ProGeTypes.hh:55
StringTools::indent
static std::string indent(int level)
Definition: StringTools.cc:319
ProGe::BaseNetlistBlock::package
virtual const std::string & package(size_t idx) const
Definition: BaseNetlistBlock.cc:699
ProGe::StaticSignal::VCC
@ VCC
All port signals set to high.
Definition: NetlistPort.hh:51
ProGe::VHDLNetlistWriter::write
virtual void write(const std::string &dstDirectory)
Definition: VHDLNetlistWriter.cc:88
ProGe::VHDLNetlistWriter::writeSignalAssignments
void writeSignalAssignments(const BaseNetlistBlock &block, std::ofstream &stream) const
Definition: VHDLNetlistWriter.cc:368
ProGe::BaseNetlistBlock::netlist
virtual const Netlist & netlist() const
Definition: BaseNetlistBlock.cc:348
Conversion::toString
static std::string toString(const T &source)
ProGe::NetlistPort::staticValue
StaticSignal staticValue() const
Definition: NetlistPort.cc:429
FileSystem::fileIsCreatable
static bool fileIsCreatable(const std::string fileName)
Definition: FileSystem.cc:123
StringTools.hh
assert
#define assert(condition)
Definition: Application.hh:86
ProGe::StaticSignal::is
bool is(State state)
Definition: NetlistPort.hh:57
ProGe::NetlistPort::realWidthAvailable
bool realWidthAvailable() const
Definition: NetlistPort.cc:334
ProGe::Netlist::parameterCount
size_t parameterCount() const
Definition: Netlist.cc:422
ProGe::VHDLNetlistWriter::groundWidth_
int groundWidth_
Width of the ground signal.
Definition: VHDLNetlistWriter.hh:122
ProGe::BaseNetlistBlock::hasParameter
virtual bool hasParameter(const std::string &name) const
Definition: BaseNetlistBlock.cc:183
InvalidData
Definition: Exception.hh:149
FileSystem::fileIsWritable
static bool fileIsWritable(const std::string fileName)
TCEString::endsWith
bool endsWith(const std::string &str) const
ProGe::BaseNetlistBlock::parameter
virtual const Parameter & parameter(const std::string &name) const
Definition: BaseNetlistBlock.cc:198
ProGe::VHDLNetlistWriter::isNumber
static bool isNumber(const std::string &formula)
Definition: VHDLNetlistWriter.cc:712
ProGe::VHDLNetlistWriter::indentation
std::string indentation(unsigned int level) const
Definition: VHDLNetlistWriter.cc:739
Conversion.hh
ProGe::Parameter
Definition: Parameter.hh:62
ProGe::VHDLNetlistWriter::portSignalType
static std::string portSignalType(const NetlistPort &port)
Definition: VHDLNetlistWriter.cc:798
ProGe::VHDLNetlistWriter::writePortMappings
void writePortMappings(const BaseNetlistBlock &block, std::ofstream &stream) const
Definition: VHDLNetlistWriter.cc:585
NetlistPort.hh
ProGe::BaseNetlistBlock::portCount
virtual size_t portCount() const
Definition: BaseNetlistBlock.cc:248
ProGe::Parameter::name
const TCEString & name() const
Definition: Parameter.cc:133
ProGe::BaseNetlistBlock::packageCount
virtual size_t packageCount() const
Definition: BaseNetlistBlock.cc:694
ProGe::VHDLNetlistWriter::portSignalName
static std::string portSignalName(const NetlistPort &port)
Definition: VHDLNetlistWriter.cc:769
__func__
#define __func__
Definition: Application.hh:67
ProGe::Netlist::descriptor
size_t descriptor(const NetlistPort &port) const
Definition: Netlist.cc:325
ProGe::Parameter::value
const TCEString & value() const
Definition: Parameter.cc:143
GROUND_SIGNAL
const std::string GROUND_SIGNAL
Definition: VHDLNetlistWriter.cc:60
ProGe::VHDLNetlistWriter::netlistParameterPkgName
std::string netlistParameterPkgName() const
Definition: VHDLNetlistWriter.cc:128
ProGe::BIT
@ BIT
One bit.
Definition: ProGeTypes.hh:47
VHDLNetlistWriter.hh
ProGe::VHDLNetlistWriter::usesParameterWidth
static bool usesParameterWidth(const NetlistPort &port)
Definition: VHDLNetlistWriter.cc:728
ProGe::NetlistPort::name
std::string name() const
Definition: NetlistPort.cc:283
ProGe::PortConnectionProperty
Definition: PortConnectionProperty.hh:51
FileSystem::DIRECTORY_SEPARATOR
static const std::string DIRECTORY_SEPARATOR
Definition: FileSystem.hh:189
ProGe::OUT
@ OUT
Output port.
Definition: ProGeTypes.hh:54
ProGe::VHDLNetlistWriter::genericMapStringValue
TCEString genericMapStringValue(const TCEString &generic) const
Definition: VHDLNetlistWriter.cc:829
ProGe::NetlistPort::dataType
DataType dataType() const
Definition: NetlistPort.cc:362
ProGe::NetlistPort::realWidth
int realWidth() const
Definition: NetlistPort.cc:348
ProGe::VHDLNetlistWriter::writeBlock
void writeBlock(const BaseNetlistBlock &block, const std::string &dstDirectory)
Definition: VHDLNetlistWriter.cc:141
ProGe::NetlistWriter::targetNetlistBlock
const BaseNetlistBlock & targetNetlistBlock() const
Definition: NetlistWriter.cc:64
ProGe
Definition: FUGen.hh:54
BaseNetlistBlock.hh
FileSystem::fileExists
static bool fileExists(const std::string fileName)
AssocTools.hh
ProGe::NetlistPort::hasStaticValue
bool hasStaticValue() const
Definition: NetlistPort.cc:423
TCEString
Definition: TCEString.hh:53
ProGe::Netlist::parameter
Parameter parameter(size_t index) const
Definition: Netlist.cc:434
ProGe::VHDLNetlistWriter::writePortDeclaration
static void writePortDeclaration(const BaseNetlistBlock &block, unsigned int indentationLevel, const std::string &indentation, std::ostream &stream)
Definition: VHDLNetlistWriter.cc:257
ProGe::VHDLNetlistWriter::writeComponentDeclarations
void writeComponentDeclarations(const BaseNetlistBlock &block, std::ofstream &stream) const
Definition: VHDLNetlistWriter.cc:520
ProGe::VHDLNetlistWriter::signalRange
static TCEString signalRange(int high, int low, bool allowShort=false)
Definition: VHDLNetlistWriter.cc:859
ProGe::VHDLNetlistWriter::VHDLNetlistWriter
VHDLNetlistWriter(const BaseNetlistBlock &targetBlock)
Definition: VHDLNetlistWriter.cc:70
ProGe::NetlistPort
Definition: NetlistPort.hh:70
ProGe::VHDLNetlistWriter::signalAssignment
static std::string signalAssignment(const NetlistPort &dst, const NetlistPort &src)
Definition: VHDLNetlistWriter.cc:892
ProGe::BaseNetlistBlock::moduleName
const std::string & moduleName() const
Definition: BaseNetlistBlock.cc:140
ContainerTools::containsValue
static bool containsValue(const ContainerType &aContainer, const ElementType &aKey)
ProGe::BaseNetlistBlock::subBlock
virtual const BaseNetlistBlock & subBlock(size_t index) const
Definition: BaseNetlistBlock.cc:155
Conversion::toInt
static int toInt(const T &source)
IOException
Definition: Exception.hh:130
ProGe::Parameter::defaultValue
const TCEString & defaultValue() const
Definition: Parameter.cc:148
ProGe::BaseNetlistBlock::isVirtual
virtual bool isVirtual() const
Definition: BaseNetlistBlock.hh:112
ProGe::Direction
Direction
Direction of the port.
Definition: ProGeTypes.hh:52
ProGe::VHDLNetlistWriter::writeNetlistParameterPackage
void writeNetlistParameterPackage(const std::string &dstDirectory) const
Definition: VHDLNetlistWriter.cc:103
ProGe::VHDLNetlistWriter::edge_descriptor
boost::graph_traits< Netlist >::edge_descriptor edge_descriptor
Definition: VHDLNetlistWriter.hh:74
Parameter.hh
ProGe::IN
@ IN
Input port.
Definition: ProGeTypes.hh:53
ProGe::BaseNetlistBlock::subBlockCount
virtual size_t subBlockCount() const
Definition: BaseNetlistBlock.cc:150
ProGe::BaseNetlistBlock::port
virtual const NetlistPort & port(size_t index) const
Definition: BaseNetlistBlock.cc:253
ProGe::VHDLNetlistWriter::writeSignalDeclarations
void writeSignalDeclarations(const BaseNetlistBlock &block, std::ofstream &stream)
Definition: VHDLNetlistWriter.cc:300
ContainerTools.hh