torc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
VerilogImporterVisitor.cpp
Go to the documentation of this file.
1 // Torc - Copyright 2011-2013 University of Southern California. All Rights Reserved.
2 // $HeadURL$
3 // $Id$
4 
5 // This program is free software: you can redistribute it and/or modify it under the terms of the
6 // GNU General Public License as published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11 // the GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License along with this program. If
14 // not, see <http://www.gnu.org/licenses/>.
15 
16 /// \file
17 /// \brief Source for the VerilogImporterVisitor class.
18 
21 #include "boost/regex.hpp"
22 
23 namespace torc {
24 namespace generic {
25 
26 /// \todo: "assign n1274_n = datain[7];" generates "(property torc_assign_rhs (string "7"))"
27 
28 #define DEBUG true
29 
30  /// \brief Initial file line information.
32 
33  template<class T> std::string compositionTypeString(const T& inPtr) {
34  if(!inPtr) return "null";
35  switch(inPtr->getCompositionType()) {
36  case eCompositionTypeScalar: return "scalar";
37  case eCompositionTypeVector: return "vector";
38  case eCompositionTypeVectorBit: return "vector bit";
39  case eCompositionTypeBundle: return "bundle";
40  default: return "unknown";
41  }
42  }
43 
45  // find all cells that are not instantiated, and make them into top-level designs
46  CellToBoolMap::const_iterator p = mCellInstantiationFlag.begin();
47  CellToBoolMap::const_iterator e = mCellInstantiationFlag.end();
48  while(p != e) {
49  std::pair<const CellSharedPtr, bool> element = *p++;
50  if(element.second) continue;
51  CellSharedPtr cellPtr = element.first;
52  LibrarySharedPtr libraryPtr = cellPtr->getParent();
53  std::string name = cellPtr->getName();
54  //std::cerr << "Found top-level design " << name << std::endl;
55  mObjectFactoryPtr->newDesignPtr(name, mRootPtr, name, libraryPtr->getName(),
56  cellPtr->getOriginalName());
57  }
58  }
59 
60  /// \brief Visit the top-level netlist.
61  void VerilogImporterVisitor::visit(AstNetlist* nodePtr, AstNUser* userPtr) {
62 if(DEBUG) std::cerr << "AstNetlist" << std::endl;
63  (void) userPtr;
64  //std::cerr << "top-level netlist " << std::endl;
65  nodePtr->iterateChildren(*this);
66 
67  // create EDIF designs for non-instantiated non-library cells
68  createDesigns();
69  // delete empty libraries
70  typedef vector<CellSharedPtr> CellSharedPtrVector;
71  CellSharedPtrVector cells;
72  mInferredBlackBoxesLibraryPtr->getCells(cells);
73  if(cells.size() == 0) mRootPtr->removeLibrary(mInferredBlackBoxesLibraryPtr->getName());
74  mImportedCellLibraryPtr->getCells(cells);
75  if(cells.size() == 0) mRootPtr->removeLibrary(mImportedCellLibraryPtr->getName());
76  }
77 
78  /// \brief Visit a Verilog module, and create an EDIF cell and view.
79  void VerilogImporterVisitor::visit(AstModule* nodePtr, AstNUser* userPtr) {
80 if(DEBUG) std::cerr << "AstModule" << std::endl;
81  (void) userPtr;
82  // if the module is already defined, do not attempt to redefine it
83  if(mMasterNameToView[nodePtr->name()]) return;
84  // if the module belongs to a library, define it appropriately
85  bool libraryCell = nodePtr->inLibrary();
86  if(libraryCell && !mImportLibraryCells) return;
88  std::cerr << "module " << nodePtr->name() << std::endl;
89  // create and add the cell
90  mCurrentCellPtr = mObjectFactoryPtr->newCellPtr(nodePtr->name(), mCurrentLibraryPtr,
91  Cell::eTypeGeneric, "");
92  if(nodePtr->prettyName() != nodePtr->name())
93  mCurrentCellPtr->setOriginalName(nodePtr->prettyName());
94 //std::cerr << "Original module name " << mCurrentCellPtr->getOriginalName() << std::endl;
95  if(!libraryCell) mCellInstantiationFlag[mCurrentCellPtr] = false;
96  // create and add the view
99  // map the master name to this view
100  mMasterNameToView[nodePtr->name()] = mCurrentViewPtr;
101  // clear the map of vector bit nets
102  mVectorBitNameToNet.clear();
103  // visit our children
104  nodePtr->iterateChildren(*this);
105  }
106 
107  /// \brief Visit a Verilog instance, and create and EDIF instance with populated pins.
108  void VerilogImporterVisitor::visit(AstCell* nodePtr, AstNUser* userPtr) {
109 if(DEBUG) std::cerr << "AstCell" << std::endl;
110  (void) userPtr;
111  std::cerr << " " << nodePtr->modName() << " " << nodePtr->name();
112  if(nodePtr->prettyName() != nodePtr->name())
113  std::cerr << " \"" << nodePtr->prettyName() << "\"";
114  std::cerr << endl;
115  // import the associated library cell if applicable
116  AstNode* modPtr = nodePtr->modp();
117  bool found = (modPtr != 0 && !modPtr->castNotFoundModule());
118  if(found) {
122  modPtr->accept(*this, userPtr);
123  }
124  // look up the master view (or create/infer it if it doesn't exist)
125  ViewSharedPtr masterViewPtr = findMasterView(nodePtr->modName(), modPtr->prettyName(),
126  !found);
127  // note that this cell has been instantiated
128  mCellInstantiationFlag[masterViewPtr->getParent()] = true;
129  // create and add the instance
130  mCurrentInstancePtr = mObjectFactoryPtr->newSingleInstancePtr(nodePtr->name(),
131  mCurrentViewPtr, masterViewPtr);
132  if(nodePtr->prettyName() != nodePtr->name())
133  mCurrentInstancePtr->setOriginalName(nodePtr->prettyName());
134  // visit our children
135  nodePtr->iterateChildren(*this);
136  }
137 
138  /// \brief Visit a Verilog pin, and add an endpoint to the corresponding EDIF net.
139  void VerilogImporterVisitor::visit(AstPin* nodePtr, AstNUser* userPtr) {
140 if(DEBUG) std::cerr << "AstPin" << std::endl;
141  (void) userPtr;
142  string pinName = nodePtr->name();
143  if(pinName.substr(0, 11) == "__pinNumber") {
144  std::cerr << "Warning: Instance port binding by port order is not currently supported."
145  << std::endl;
146  return;
147  }
148 
149 //std::cerr << " PIN: " << mCurrentCellPtr->getName() << " " << mCurrentInstancePtr->getName() << "." << pinName << std::endl;
150 
151  //std::cerr << " pin " << pinName << std::endl;
152  // visit our children
153  mCurrentIndices.clear();
154  mCurrentNetPtrVector.clear(); mCurrentNetPtr.reset();
156  mCurrentConstNum.setZero(); mCurrentNotFlag = false; mCurrentConcatFlag = false;
157  nodePtr->iterateChildren(*this);
158 
159  // if the binding was a concatenation, we will have a vector of scalar nets or of vector
160  // bit nets; otherwise we may have a scalar net, a vector net, or a vector bit net;
161  // if we have no net at all, the port is open
162 
163  // a non-empty net vector takes precedence over a regular net
164  size_t netSize = 0;
165  bool isConcat = false;
166  bool isVector = false;
167  if(mCurrentNetPtrVector.size()) {
168  // this is a vector of individual nets
169  netSize = mCurrentNetPtrVector.size();
170  isConcat = true;
171  isVector = true;
172  } else if(mCurrentNetPtr) {
173  // this is an individual net
174  netSize = mCurrentNetPtr->getSize();
175  isConcat = false;
176  isVector = mCurrentNetPtr->getCompositionType() == eCompositionTypeVector;
177  } else {
178  // the port must be open - we return without doing anything more
179  return;
180  }
181 //std::cerr << " netSize = " << netSize << ", isConcat = " << isConcat << ", isVector = " << isVector << std::endl;
182 
183  // try to look up the port reference
184  PortReferenceSharedPtr portReferencePtr = mCurrentInstancePtr->findPortReference(pinName);
185 //if(portReferencePtr) std::cerr << "FOUND PORTREF " << portReferencePtr << " FOR INSTANCE " << mCurrentInstancePtr->getName() << " PIN " << pinName << std::endl;
186  // if this instance comes from an inferred library cell, we create any ports that are
187  // undefined -- note that we have no information concerning port directions
188  if(!portReferencePtr) {
189  // look up the master view and library
190  ViewSharedPtr viewPtr = mCurrentInstancePtr->getMaster();
191  LibrarySharedPtr libraryPtr = viewPtr->getParent()->getParent();
192 //std::cerr << " inferring ports for master cell " << viewPtr->getParent()->getName() << std::endl;
193  // may need to infer new ports if this instance originates from an inferred library
194  bool infer = libraryPtr == mInferredBlackBoxesLibraryPtr;
195  // handle vector ports
196  if(isVector) {
197  // look up the port
198  PortSharedPtr portPtr = viewPtr->findPort(pinName);
199  if(!portPtr) {
200  // optionally add a vector port to the master of the inferred instance
201  if(infer) {
202  portPtr = mObjectFactoryPtr->newVectorPortPtr(pinName,
203  ePortDirectionUndefined, viewPtr, netSize, PortBundleSharedPtr(),
204  mObjectFactoryPtr, "");
205  if(nodePtr->name() != nodePtr->prettyName())
206  portPtr->setOriginalName(nodePtr->prettyName());
207  } else ; /// \todo Throw an exception.
208  }
209  // create a new port reference
210  portReferencePtr = mObjectFactoryPtr->newVectorPortReferencePtr(
211  mCurrentInstancePtr, portPtr, netSize,
213  // handle scalar ports or single bits of vector ports
214  } else {
215  // look up the port
216  PortSharedPtr portPtr = viewPtr->findPort(pinName);
217  if(!portPtr) {
218  // optionally add a scalar port to the master of the inferred instance
219  if(infer) {
220  portPtr = mObjectFactoryPtr->newScalarPortPtr(pinName,
222  if(nodePtr->name() != nodePtr->prettyName())
223  portPtr->setOriginalName(nodePtr->prettyName());
224  } else ; /// \todo Throw an exception.
225  }
226  // create a new port reference
227  portReferencePtr = mObjectFactoryPtr->newScalarPortReferencePtr(
229  }
230 //std::cerr << " done inferring ports for master cell." << std::endl;
231  }
232 //PortSharedPtr backPortPtr = viewPtr->findPort(pinName);
233 //std::cerr << "FOUND PORT " << backPortPtr << " FOR VIEW " << viewPtr->getParent()->getName() << " PIN " << pinName << std::endl;
234 //PortReferenceSharedPtr backPortReferencePtr = mCurrentInstancePtr->findPortReference(pinName);
235 //std::cerr << "FOUND PORTREF " << backPortReferencePtr << " FOR INSTANCE " << mCurrentInstancePtr->getName() << " PIN " << pinName << std::endl;
236  // we should have a valid port reference by now
237  if(!portReferencePtr) {
238  std::cerr << "Warning: Unable to find or infer port " << pinName
239  << " for instance " << mCurrentInstancePtr->getName() << std::endl;
240  throw;
241  }
242 
243  // the AstParseRef code should ensure that we never get here with multidimensional nets
244 
245  // determine the port size
246  size_t portSize = portReferencePtr->getSize();
247  // check for mismatched sizes
248  if(portSize != netSize) {
249  std::cerr << "Warning: bundle and pin sizes do not match on "
250  << mCurrentInstancePtr->getName() << "." << pinName << std::endl;
251  }
252 
253  // connect concatenations
254  if(isConcat) {
255  // gather the children
256  NetSharedPtrVector::const_iterator p = mCurrentNetPtrVector.begin();
257  NetSharedPtrVector::const_iterator e = mCurrentNetPtrVector.end();
258  IndexVector portIndices;
259  portIndices.push_back(0);
260  while(p < e) {
261  // look up the current net
262  NetSharedPtr netPtr = *p++;
263  CompositionType compositionType = netPtr->getCompositionType();
264  if(compositionType != eCompositionTypeScalar
265  && compositionType != eCompositionTypeVectorBit) {
266  std::cerr << "Warning: unexpected vector net or bundle remaining in "
267  "concatenation for " << mCurrentInstancePtr->getName() << "." << pinName
268  << std::endl;
269  continue;
270  }
271  // connect the net to the appropriate port member
272  PortReferenceSharedPtr portBitReferencePtr = portReferencePtr->get(portIndices);
273 //std::cerr << " connecting port " << portReferencePtr->getName() << " index "
274 // << portIndices[0] << " of type " << compositionTypeString(portReferencePtr)
275 // << " to scalar net " << netPtr->getName() << " of type " << compositionTypeString(netPtr)
276 // << std::endl;
277  portBitReferencePtr->connect(netPtr);
278  portIndices[0]++;
279  }
280  // connect individual nets
281  } else {
282 //std::cerr << " connecting port " << mCurrentInstancePtr->getName() << "." << pinName << " of type " << compositionTypeString(portReferencePtr)
283 // << " to net " << mCurrentNetPtr->getName() << " of type " << compositionTypeString(mCurrentNetPtr)
284 // << std::endl;
285  portReferencePtr->connect(mCurrentNetPtr);
286  }
287 
288  }
289 
290  /// \brief Visit a Verilog port, and create an EDIF port.
291  void VerilogImporterVisitor::visit(AstPort* nodePtr, AstNUser* userPtr) {
292 if(DEBUG) std::cerr << "AstPort" << std::endl;
293  (void) userPtr;
294 // std::cerr << " port " << nodePtr->name() << std::endl;
295  }
296 
297  /// \brief Visit a Verilog bit index.
298  void VerilogImporterVisitor::visit(AstSelBit* nodePtr, AstNUser* userPtr) {
299 if(DEBUG) std::cerr << "AstSelBit" << std::endl;
300  (void) userPtr;
301  // look up the bit index, and process it if it is a constant
302  AstNode* bitp = nodePtr->bitp();
303  switch(bitp->type()) {
304  case AstType::atCONST:
305  mCurrentIndices.push_back(bitp->castConst()->num().toSInt()); break;
306  default:
307  std::cerr << "FAILED TO PROCESS SELBIT OF TYPE " << bitp->type().ascii(); throw;
308  }
309  // visit our children
310  nodePtr->iterateChildren(*this);
311  }
312 
313  void VerilogImporterVisitor::visit(AstSelExtract* nodePtr, AstNUser* userPtr) {
314 if(DEBUG) std::cerr << "AstSelExtract" << std::endl;
315  (void) userPtr;
316  // visit our children
317  nodePtr->iterateChildren(*this);
318  // look up the bit range, and process it if it consists of two constants
319  AstNode* msbp = nodePtr->msbp();
320  AstNode* lsbp = nodePtr->lsbp();
321  if(msbp->type() == AstType::atCONST && lsbp->type() == AstType::atCONST) {
322  mCurrentRange[0] = msbp->castConst()->num().toSInt();
323  mCurrentRange[1] = lsbp->castConst()->num().toSInt();
324  } else {
325  std::cerr << "FAILED TO PROCESS SELEXTRACT OF TYPES " << msbp->type().ascii()
326  << " and " << lsbp->type().ascii() << std::endl;
327 // throw;
328  }
329 //std::cerr << " leaving AstSelExtract: " << mCurrentText << "[" << mCurrentRange[0] << ":" << mCurrentRange[1] << "]" << std::endl;
330  }
331 
332  /// \brief Visit a Verilog range.
333  void VerilogImporterVisitor::visit(AstRange* nodePtr, AstNUser* userPtr) {
334 if(DEBUG) std::cerr << "AstRange" << std::endl;
335  (void) userPtr;
336  mCurrentRange[0] = nodePtr->msbConst();
337  mCurrentRange[1] = nodePtr->lsbConst();
338  // no need to visit our children
339  //nodePtr->iterateChildren(*this);
340  }
341 
342  void VerilogImporterVisitor::visit(AstDefParam* nodePtr, AstNUser* userPtr) {
343 if(DEBUG) std::cerr << "AstDefParam" << std::endl;
344  (void) userPtr;
345 // std::cerr << " defParam " << nodePtr->path() << ": " << nodePtr->name()
346 // << " = " << nodePtr->rhsp()->name() << std::endl;
347  // look up the relevant instance
348  InstanceSharedPtr instancePtr = mCurrentViewPtr->findInstance(nodePtr->path());
349  if(!instancePtr) {
350  std::cerr << "FAILED TO FIND DEFPARAM INSTANCE " << nodePtr->path() << std::endl;
351  return;
352  }
353  // visit our children
355  mCurrentConstNum.setZero(); mCurrentNotFlag = false;
356  nodePtr->iterateChildren(*this);
357  if(!mCurrentConstStr.length()) {
358  std::cerr << "FAILED TO FIND A CONSTANT FOR DEFPARAM " << nodePtr->path() << std::endl;
359  return;
360  }
361  // convert the defparam into a property
362  if(mCurrentConstNum.isFromString()) {
363  // handle numeric defparams
364  mObjectFactoryPtr->newPropertyPtr(nodePtr->name(), instancePtr,
366  } else {
367  // handle string defparams
368  mObjectFactoryPtr->newPropertyPtr(nodePtr->name(), instancePtr,
370  }
371  }
372 
373  /// \brief Visit a Verilog variable, and create an EDIF wire or port.
374  void VerilogImporterVisitor::visit(AstVar* nodePtr, AstNUser* userPtr) {
375 if(DEBUG) std::cerr << "AstVar" << std::endl;
376 // WARNING: the next line needs to be removed!
377 //return;
378  (void) userPtr;
379  // look up the variable type
380  AstVarType varType = nodePtr->varType();
381  // process wires
382  if(varType == AstVarType::WIRE) {
383  // determine the port width
385  // visit our children
386  nodePtr->iterateChildren(*this);
387  // create and add a scalar net
388  if(mCurrentRange[0] == cUndefined && mCurrentRange[1] == cUndefined) {
389 // std::cerr << " wire " << nodePtr->name() << std::endl;
390  ScalarNetSharedPtr netPtr = mObjectFactoryPtr->newScalarNetPtr(nodePtr->name(),
392  if(nodePtr->prettyName() != nodePtr->name())
393  netPtr->setOriginalName(nodePtr->prettyName());
394  }
395  // create and add a vector net
396  else {
397 // std::cerr << " wire " << nodePtr->name() << "[" << mCurrentRange[0] << ":"
398 // << mCurrentRange[1] << "]" << std::endl;
399  VectorNetSharedPtr netPtr = mObjectFactoryPtr->newVectorNetPtr(nodePtr->name(),
401  mObjectFactoryPtr, "");
402  if(nodePtr->prettyName() != nodePtr->name())
403  netPtr->setOriginalName(nodePtr->prettyName());
404  // attach the original port range in two properties
405  mObjectFactoryPtr->newPropertyPtr(VerilogNames::getTorcRangeMSBPropertyName(),
406  netPtr, Value(Value::eValueTypeInteger, Value::Integer(mCurrentRange[0])));
407  mObjectFactoryPtr->newPropertyPtr(VerilogNames::getTorcRangeLSBPropertyName(),
408  netPtr, Value(Value::eValueTypeInteger, Value::Integer(mCurrentRange[1])));
409  }
410  // process ports
411  } else if(varType == AstVarType::PORT || varType == AstVarType::INPUT
412  || varType == AstVarType::OUTPUT || varType == AstVarType::INOUT) {
413  // determine the direction
415  if(nodePtr->isInout()) { direction = ePortDirectionInOut; }
416  else if(nodePtr->isInput()) { direction = ePortDirectionIn; }
417  else if(nodePtr->isOutput()) { direction = ePortDirectionOut; }
418  // determine the port width
420  // visit our children
421  nodePtr->iterateChildren(*this);
422  // create and add a scalar port
423  if(mCurrentRange[0] == cUndefined && mCurrentRange[1] == cUndefined) {
424 // std::cerr << " port " << nodePtr->name() << std::endl;
425  ScalarPortSharedPtr portPtr = mObjectFactoryPtr->newScalarPortPtr(
426  nodePtr->name(), direction, mCurrentViewPtr, PortBundleSharedPtr(), "");
427  if(nodePtr->prettyName() != nodePtr->name())
428  portPtr->setOriginalName(nodePtr->prettyName());
429  }
430  // create and add a vector port
431  else {
432 // std::cerr << " port " << nodePtr->name() << "[" << mCurrentRange[0] << ":"
433 // << mCurrentRange[1] << "]" << std::endl;
434  VectorPortSharedPtr portPtr = mObjectFactoryPtr->newVectorPortPtr(
435  nodePtr->name(), direction, mCurrentViewPtr, mCurrentRange[0] + 1,
437  //stringstream ss;
438  //ss << nodePtr->name() << "[" << mCurrentRange[0] << ":" << mCurrentRange[1]
439  // << "]";
440  //portPtr->setOriginalName(ss.str());
441  if(nodePtr->prettyName() != nodePtr->name())
442  portPtr->setOriginalName(nodePtr->prettyName());
443  // attach the original port range in two properties
444  mObjectFactoryPtr->newPropertyPtr(VerilogNames::getTorcRangeMSBPropertyName(),
445  portPtr, Value(Value::eValueTypeInteger, Value::Integer(mCurrentRange[0])));
446  mObjectFactoryPtr->newPropertyPtr(VerilogNames::getTorcRangeLSBPropertyName(),
447  portPtr, Value(Value::eValueTypeInteger, Value::Integer(mCurrentRange[1])));
448  }
449  // catch everything else
450  } else {
451  visit(dynamic_cast<AstNode*>(nodePtr), userPtr);
452  }
453  }
454 
455  /// \brief Visit a Verilog assignment, and add an appropriate EDIF property.
456  void VerilogImporterVisitor::visit(AstAssignW* nodePtr, AstNUser* userPtr) {
457 if(DEBUG) std::cerr << "AstAssignW" << std::endl;
458  (void) userPtr;
459  // visit our left-hand side
461  mCurrentConstNum.setZero(); mCurrentNotFlag = false;
462  nodePtr->lhsp()->iterateAndNext(*this, userPtr);
463  string signal = mCurrentText;
464  // visit our right-hand side
466  mCurrentConstNum.setZero(); mCurrentNotFlag = false;
467  nodePtr->rhsp()->iterateAndNext(*this, userPtr);
468  string value = (mCurrentNotFlag ? "~" : "")
470 //nodePtr->rhsp()->dumpTree();
471  // try to look up the left-hand side as a net or port
472  PortSharedPtr portPtr;
473  NetSharedPtr netPtr;
474  portPtr = mCurrentViewPtr->findPort(signal);
475  if(!portPtr) netPtr = mCurrentViewPtr->findNet(signal);
476  if(portPtr) {
479 // std::cerr << " assign " << signal << " = " << value << std::endl;
480  } else if(netPtr) {
483 // std::cerr << " assign " << signal << " = " << value << std::endl;
484  } else {
485  std::cerr << "FAILED TO FIND PORT OR NET ASSIGNMENT TARGET FOR " << signal << std::endl;
486  }
487  }
488 
489  void VerilogImporterVisitor::visit(AstParseRef* nodePtr, AstNUser* userPtr) {
490 if(DEBUG) std::cerr << "AstParseRef" << std::endl;
491  (void) userPtr;
492 // std::cerr << " parseref " << nodePtr->name() << ": "
493 // << nodePtr->lhsp()->type().ascii() << std::endl;
494 
495  // visit our children
496  mCurrentIndices.clear();
499  mCurrentConstNum.setZero(); mCurrentNotFlag = false;
500  nodePtr->iterateChildren(*this);
501 
502  // try to look up the current net based on its name
504  size_t netSize = mCurrentNetPtr ? mCurrentNetPtr->getSize() : 1;
505 
506  // account for nets that are bits of busses
507  string netName = mCurrentText;
508  string indexedNetName;
509  size_t numIndices = mCurrentIndices.size();
510  if(numIndices > 1) {
511  std::cerr << "Warning: Multidimensional arrays and ports are not yet supported."
512  << std::endl;
513  // to-do: throw an exception
514  return;
515  }
516  // a scalar bit of a bus
517  if(numIndices) mCurrentRange[1] = mCurrentRange[0] = mCurrentIndices[0];
518  // a slice of a bus
519  bool hasRange = mCurrentRange[0] != cUndefined && mCurrentRange[1] != cUndefined;
520 
521  // if the net does not exist, try to derive it from an identically named port
522  if(!mCurrentNetPtr) {
523  PortSharedPtr portPtr = mCurrentViewPtr->findPort(mCurrentText);
524  if(portPtr) {
525  // look up the port width
526  netSize = portPtr->getSize();
527  // entire vector ports inside concatenations must be treated as ranges
528  if(mCurrentConcatFlag && !hasRange
529  && portPtr->getCompositionType() == eCompositionTypeVector) {
530  hasRange = true;
531  PropertySharedPtr msbPtr
532  = portPtr->getProperty(VerilogNames::getTorcRangeMSBPropertyName());
533  PropertySharedPtr lsbPtr
534  = portPtr->getProperty(VerilogNames::getTorcRangeLSBPropertyName());
535  mCurrentRange[0] = msbPtr->getValue().get<Value::Integer>();
536  mCurrentRange[1] = lsbPtr->getValue().get<Value::Integer>();
537  }
538  // create a scalar net
539  if(netSize == 1) {
540  mCurrentNetPtr = mObjectFactoryPtr->newScalarNetPtr(netName, mCurrentViewPtr,
541  NetBundleSharedPtr(), "");
543  portPtr->connect(mCurrentNetPtr);
544  // create scalar nets for an index or a slice
545  } else if(hasRange) {
546  // look up the port range
547  PropertySharedPtr msbPtr
548  = portPtr->getProperty(VerilogNames::getTorcRangeMSBPropertyName());
549  PropertySharedPtr lsbPtr
550  = portPtr->getProperty(VerilogNames::getTorcRangeLSBPropertyName());
551  int32_t msb = msbPtr->getValue().get<Value::Integer>();
552  int32_t lsb = lsbPtr->getValue().get<Value::Integer>();
553  // iterate over the range
554 //std::cerr << " creating port bit for " << mCurrentText << "[" << mCurrentRange[0] << ":"
555 // << mCurrentRange[1] << "]" << std::endl;
556  int32_t increment = mCurrentRange[0] < mCurrentRange[1] ? 1 : -1;
557  for(int32_t i = mCurrentRange[0]; ; i += increment) {
558  // look up the appropriate port index (does not support multiple dimensions)
559  int32_t formalIndex = i;
560  int32_t index = 0;
561  if(formalIndex <= msb && formalIndex >= lsb) {
562  index = msb - formalIndex;
563  } else if(formalIndex >= msb && formalIndex <= lsb) {
564  index = formalIndex - msb;
565  } else {
566  // this case would be a bit out of range
567  }
568  // compose the net name
569  stringstream un;
570  stringstream ss;
571  un << mCurrentText << "_" << formalIndex << "_" << mCurrentIndex++;
572  ss << mCurrentText << "[" << formalIndex << "]";
573  netName = un.str();
574  indexedNetName = ss.str();
575  // create a temporary net
576  StringToNetMap::iterator it = mVectorBitNameToNet.find(indexedNetName);
577 //std::cerr << " YOOHOO: got " << (it != mVectorBitNameToNet.end()) << " when looking for " << indexedNetName << std::endl;
578  if(it != mVectorBitNameToNet.end()) { mCurrentNetPtr = it->second; }
579  else {
580  mCurrentNetPtr = mObjectFactoryPtr->newScalarNetPtr(netName,
582  // remember the original name
583  mCurrentNetPtr->setOriginalName(indexedNetName);
584  mVectorBitNameToNet[indexedNetName] = mCurrentNetPtr;
585  IndexVector indices;
586  indices.push_back(index);
587  PortSharedPtr portBitPtr = portPtr->get(indices);
588  portBitPtr->connect(mCurrentNetPtr);
589  }
591  // break out of the loop when we're done
592  if(i == mCurrentRange[1]) break;
593  }
594  // create a vector net
595  } else {
596  // we should never get here if we are in a concatenation
597  if(mCurrentConcatFlag) {
598  std::cerr << "Warning: Encountered vector net within concatenation."
599  << std::endl;
600  }
601  // create a new vector net
602  mCurrentNetPtr = mObjectFactoryPtr->newVectorNetPtr(netName, mCurrentViewPtr,
603  netSize, NetBundleSharedPtr(), mObjectFactoryPtr, "");
604  VectorNetSharedPtr vectorNetPtr
605  = boost::dynamic_pointer_cast<VectorNet>(mCurrentNetPtr);
606  vectorNetPtr->forceAutoBlast();
607  // set the port range as the net range (this can probably be cleaned up)
608  PropertySharedPtr msbPtr
609  = portPtr->getProperty(VerilogNames::getTorcRangeMSBPropertyName());
610  PropertySharedPtr lsbPtr
611  = portPtr->getProperty(VerilogNames::getTorcRangeLSBPropertyName());
612  int32_t msb = msbPtr->getValue().get<Value::Integer>();
613  int32_t lsb = lsbPtr->getValue().get<Value::Integer>();
618  }
619  }
620 else std::cerr << "FAILED TO FIND PORT " << netName << std::endl;
621 
622  // the net already exists
623  } else {
624 //printf("mCurrentConcatFlag = %d, hasRange = %d, compoositionType = %d\n",
625 // mCurrentConcatFlag, hasRange, mCurrentNetPtr->getCompositionType());
626  // entire vector ports inside concatenations must be treated as ranges
627  if(mCurrentConcatFlag && !hasRange
628  && mCurrentNetPtr->getCompositionType() == eCompositionTypeVector) {
629  hasRange = true;
630  PropertySharedPtr msbPtr
632  PropertySharedPtr lsbPtr
634  mCurrentRange[0] = msbPtr->getValue().get<Value::Integer>();
635  mCurrentRange[1] = lsbPtr->getValue().get<Value::Integer>();
636  }
637  // if a range or indices were supplied, we need to extract the relevant children and
638  // add them to the current vector
639  if(hasRange) {
640 //std::cerr << " hasRange mCurrentNetPtr = " << mCurrentNetPtr->getName() << std::endl;
641  // look up the children
642  VectorNet::List children;
643  mCurrentNetPtr->getChildren(children);
644  // look up the port range
645  PropertySharedPtr msbPtr
647  PropertySharedPtr lsbPtr
649  int32_t msb = msbPtr->getValue().get<Value::Integer>();
650  int32_t lsb = lsbPtr->getValue().get<Value::Integer>();
651  // iterate over the range
652  int32_t increment = mCurrentRange[0] < mCurrentRange[1] ? 1 : -1;
653  for(int32_t i = mCurrentRange[0]; ; i += increment) {
654  // look up the appropriate port index (does not support multiple dimensions)
655  int32_t formalIndex = i;
656  int32_t index = 0;
657  if(formalIndex <= msb && formalIndex >= lsb) {
658  index = msb - formalIndex;
659  } else if(formalIndex >= msb && formalIndex <= lsb) {
660  index = formalIndex - msb;
661  } else {
662  // this case would be a bit out of range
663  }
664  (void) index;
665  // compose the net name
666  stringstream un;
667  stringstream ss;
668  un << mCurrentText << "_" << formalIndex << "_" << mCurrentIndex++;
669  ss << mCurrentText << "[" << formalIndex << "]";
670  netName = un.str();
671  indexedNetName = ss.str();
672  // look up the appropriate children
673  NetSharedPtr netPtr;
674  StringToNetMap::iterator it = mVectorBitNameToNet.find(indexedNetName);
675 //std::cerr << " YOOHOO: got " << (it != mVectorBitNameToNet.end()) << " when looking for " << indexedNetName << std::endl;
676  if(it != mVectorBitNameToNet.end()) { netPtr = it->second; }
677  else {
678  //netPtr = children[index];
679  netPtr = mObjectFactoryPtr->newScalarNetPtr(netName,
681 //std::cerr << " created net for " << netName << " of type " << compositionTypeString(netPtr) << std::endl;
682  mCurrentViewPtr->removeNet(netName);
683  mCurrentNetPtr->addSubnet(netPtr);
684  // remember the original name
685  netPtr->setOriginalName(indexedNetName);
686  mVectorBitNameToNet[indexedNetName] = netPtr;
687  }
688  if(mCurrentConcatFlag) mCurrentNetPtrVector.push_back(netPtr);
689  else mCurrentNetPtr = netPtr;
690 //std::cerr << " mCurrentNetPtr is of type " << compositionTypeString(mCurrentNetPtr)
691 // << " in view " << netPtr->getParent() << std::endl;
692  // break out of the loop when we're done
693  if(i == mCurrentRange[1]) break;
694  }
695  // the range has now been added to the current bundle
696 
697  // otherwise, we are using a full scalar or vector net, so we push it if applicable
698  } else {
699  // if the net has no children, auto-blast it
700 //std::cerr << " no range mCurrentNetPtr = " << mCurrentNetPtr->getName() << std::endl;
701  if(mCurrentNetPtr->getCompositionType() == eCompositionTypeVector) {
702  VectorNet::List children;
703  mCurrentNetPtr->getChildren(children);
704  VectorNetSharedPtr vectorNetPtr = boost::dynamic_pointer_cast<VectorNet>(mCurrentNetPtr);
705 // if(!children.size()) vectorNetPtr->forceAutoBlast();
706  }
707  // add the net to the current vector if approriate
709  }
710  }
711 
712  }
713 
714  /// \brief Visit a text node and store it.
715  void VerilogImporterVisitor::visit(AstText* nodePtr, AstNUser* userPtr) {
716 if(DEBUG) std::cerr << "AstText" << std::endl;
717  (void) userPtr;
718  // store the current text
719  mCurrentText = nodePtr->text();
720 //std::cerr << " text: " << mCurrentText << std::endl;
721  // we have no children to visit
722  //nodePtr->iterateChildren(*this);
723  }
724 
725  /// \brief Visit a constant node and store it.
726  void VerilogImporterVisitor::visit(AstConst* nodePtr, AstNUser* userPtr) {
727 if(DEBUG) std::cerr << "AstConst" << std::endl;
728  (void) userPtr;
729  // store the current constant
730  int widthMin = nodePtr->widthMin();
731  mCurrentConstNum = nodePtr->num();
732  mCurrentConstStr = mCurrentConstNum.ascii(false);
733 //std::cerr << " number: " << nodePtr->name() << std::endl;
734 //std::cerr << " AstConst 0: widthMin = " << mCurrentConstNum.widthMin() << std::endl;
735 //std::cerr << " AstConst 1: width = " << mCurrentConstNum.width() << std::endl;
736 //std::cerr << " AstConst 2: ascii = " << mCurrentConstStr << std::endl;
737 // WARNING: the next line needs to be removed!
738 //if(widthMin > 64) return;
739  mCurrentConstInt = widthMin > 32
740  ? cUndefined : nodePtr->num().toSInt();
741  // we have no children to visit
742  //nodePtr->iterateChildren(*this);
743  }
744 
745  /// \brief Visit a NOT node and store it.
746  void VerilogImporterVisitor::visit(AstNot* nodePtr, AstNUser* userPtr) {
747 if(DEBUG) std::cerr << "AstNot" << std::endl;
748  (void) userPtr;
749  // store the flag
750  mCurrentNotFlag = true;
751  // we have no children to visit
752  nodePtr->iterateChildren(*this);
753  }
754 
755  void VerilogImporterVisitor::visit(AstNotFoundModule* nodePtr, AstNUser* userPtr) {
756 if(DEBUG) std::cerr << "AstNotFoundModule" << std::endl;
757  (void) userPtr;
758 // std::cerr << "not found module " << nodePtr->name() << std::endl;
759  std::cerr << "// NOTICE: black-boxed module " << nodePtr->name() << std::endl;
760  // visit our children
761  nodePtr->iterateChildren(*this);
762  }
763 
764  void VerilogImporterVisitor::visit(AstBasicDType* nodePtr, AstNUser* userPtr) {
765 if(DEBUG) std::cerr << "AstBasicDType" << std::endl;
766  (void) userPtr;
767  // nodePtr->name() is typically "logic" -- I'm not sure that helps us out a lot
768  if(nodePtr->name() != "logic")
769  std::cerr << " UNPROCESSED: basicdtype " << nodePtr->name() << std::endl;
770  // visit our children
771  nodePtr->iterateChildren(*this);
772  }
773 
774  void VerilogImporterVisitor::visit(AstConcat* nodePtr, AstNUser* userPtr) {
775 if(DEBUG) std::cerr << "AstConcat" << std::endl;
776  (void) userPtr;
777  // we are now in a concatenation
778  mCurrentConcatFlag = true;
779  // visit our children
780  nodePtr->iterateChildren(*this);
781  }
782 
783  void VerilogImporterVisitor::visit(AstNode* nodePtr, AstNUser* userPtr) {
784 if(DEBUG) std::cerr << "AstNode" << std::endl;
785  (void) userPtr;
786 // std::cerr << " " << nodePtr->verilogKwd() << std::endl;
787  std::cerr << "FAILED TO PROCESS NODE "; nodePtr->dump(std::cerr); std::cerr
788  << " in line " << nodePtr->fileline() << std::endl;
789  // visit our children
790  nodePtr->iterateChildren(*this);
791  }
792 
793 } // namespace generic
794 } // namespace torc
V3Number mCurrentConstNum
The current constant number object.
NetSharedPtr mCurrentNetPtr
The current net shared pointer;.
boost::shared_ptr< Instance > InstanceSharedPtr
InstanceSharedPtr mCurrentInstancePtr
The current instance shared pointer.
ViewSharedPtr findMasterView(std::string inMasterName, std::string inOriginalName, bool inCreate)
Find the specified view, or optionally create it.
Header for the TemporaryAssignment class.
static string getTorcAssignRHSPropertyName(void)
Property name for the wire assignment right-hand-side.
std::string compositionTypeString(const T &inPtr)
static string getTorcRangeMSBPropertyName(void)
Property name for the vector range MSB.
bool mCurrentNotFlag
The current inversion flag.
boost::shared_ptr< ScalarPort > ScalarPortSharedPtr
boost::shared_ptr< ScalarNet > ScalarNetSharedPtr
boost::shared_ptr< PortBundle > PortBundleSharedPtr
LibrarySharedPtr mCurrentLibraryPtr
The current library shared pointer.
ViewSharedPtr mCurrentViewPtr
The current view shared pointer.
void createDesigns(void)
Create top-level designs for all Verilog modules that are never instantiated.
static const int32_t cUndefined
Undefined index constant.
virtual void forceAutoBlast(void)
Definition: Vector.hpp:479
NetSharedPtrVector mCurrentNetPtrVector
The current net vector.
std::string String
Definition: Value.hpp:61
std::string string
static string getTorcRangeLSBPropertyName(void)
Property name for the vector range LSB.
CompositionType
Defines possible Composition types.
static FileLine sNullFileLine
Initial file line information.
Header for the VerilogImporterVisitor class.
Template class that stores the current value of a variable and restores that value when this object g...
boost::shared_ptr< VectorPort > VectorPortSharedPtr
boost::shared_ptr< VectorNet > VectorNetSharedPtr
string mCurrentConstStr
The current constant string.
bool mImportLibraryCells
A flag to indicate whether we should currently allow library cells.
boost::shared_ptr< Net > NetSharedPtr
boost::shared_ptr< Library > LibrarySharedPtr
bool mCurrentConcatFlag
The current concatenation flag.
boost::shared_ptr< PortReference > PortReferenceSharedPtr
Represents a net array.
Definition: VectorNet.hpp:42
int32_t mCurrentRange[2]
The current range.
CellToBoolMap mCellInstantiationFlag
A map of cell shared pointers to instantiation settings.
LibrarySharedPtr mInferredBlackBoxesLibraryPtr
The inferred black-box library shared pointer.
RootSharedPtr mRootPtr
The root shared pointer.
StringToNetMap mVectorBitNameToNet
A map of net bit names to net shared pointers.
IndexVector mCurrentIndices
The current array indices.
string mCurrentText
The current text string.
int32_t mCurrentConstInt
The current constant signed integer.
virtual void visit(AstNetlist *nodePtr, AstNUser *userPtr)
Visit the top-level netlist.
uint32_t mCurrentIndex
A unique index to avoid name collisions.
#define DEBUG
vector< size_t > IndexVector
A vector of element indices.
LibrarySharedPtr mImportedCellLibraryPtr
The cell library shared pointer.
boost::shared_ptr< View > ViewSharedPtr
boost::shared_ptr< Cell > CellSharedPtr
boost::shared_ptr< Port > PortSharedPtr
ObjectFactorySharedPtr mObjectFactoryPtr
The object factory shared pointer.
boost::shared_ptr< Property > PropertySharedPtr
StringToViewMap mMasterNameToView
A map from module name to master view pointer.
static string getImportedVerilogViewName(void)
Returns the imported Verilog view name.
boost::shared_ptr< NetBundle > NetBundleSharedPtr
CellSharedPtr mCurrentCellPtr
The current cell shared pointer.
boost::shared_ptr< PortBundleReference > PortBundleReferenceSharedPtr
std::vector< Pointer > List
Definition: Composite.hpp:61