diff --git a/crlcore/src/ccore/gds/GdsDriver.cpp b/crlcore/src/ccore/gds/GdsDriver.cpp index 7c7434a3..b410d56f 100644 --- a/crlcore/src/ccore/gds/GdsDriver.cpp +++ b/crlcore/src/ccore/gds/GdsDriver.cpp @@ -474,6 +474,7 @@ namespace { public: GdsStream ( string filename ); ~GdsStream (); + inline Point putOnGrid ( const Point& ) const; inline int32_t toGdsDbu ( DbU::Unit ) const; static inline GdsRecord PROPATTR ( int16_t ); static inline GdsRecord DATATYPE ( int16_t ); @@ -496,9 +497,10 @@ namespace { GdsStream& operator<< ( const Cell* ); GdsStream& operator<< ( const Transformation& ); private: - ofstream _ostream; - double _dbuPerUu; - double _metricDbU; + ofstream _ostream; + double _dbuPerUu; + double _metricDbU; + DbU::Unit _oneGrid; }; @@ -522,14 +524,31 @@ namespace { inline GdsRecord GdsStream::SNAME ( const Name& n ) { return GdsRecord(GdsRecord::SNAME,getString(n)); } inline GdsRecord GdsStream::STRING ( const Name& n ) { return GdsRecord(GdsRecord::STRING,getString(n)); } inline GdsRecord GdsStream::STRING ( const string s ) { return GdsRecord(GdsRecord::STRING,s); } + inline int32_t GdsStream::toGdsDbu ( DbU::Unit v ) const - { return uint32_t( std::lrint( DbU::toPhysical( v, DbU::UnitPower::Unity ) / _metricDbU )); } + { + if (v % _oneGrid) { + cerr << getString( Error( "Offgrid value %s (DbU=%d), grid %s (DbU=%d)." + , DbU::getValueString(v).c_str(), v + , DbU::getValueString(_oneGrid).c_str(), _oneGrid )) + << endl; + } + return uint32_t( std::lrint( DbU::toPhysical( v, DbU::UnitPower::Unity ) / _metricDbU )); + } + + + inline Point GdsStream::putOnGrid ( const Point& p ) const + { + return Point( p.getX() - (p.getX() % _oneGrid) + , p.getY() - (p.getY() % _oneGrid)); + } GdsStream::GdsStream ( string filename ) : _ostream () , _dbuPerUu (Cfg::getParamDouble("gdsDriver.dbuPerUu" ,0.001)->asDouble()) // 1000 , _metricDbU(Cfg::getParamDouble("gdsDriver.metricDbu",10e-9)->asDouble()) // 1um. + , _oneGrid (DbU::grid(1.0)) { std::fesetround( FE_TONEAREST ); _ostream.open( filename, ios_base::out|ios_base::binary ); @@ -723,7 +742,7 @@ namespace { if (cell->getName() == "control_r") return *this; if (not hasLayout(cell)) return *this; - //cerr << "GdsStream::operator<<(Cell*): " << getString(cell) << endl; + cdebug_log(101,1) << "GdsStream::operator<<(Cell*): " << getString(cell) << endl; Technology* tech = DataBase::getDB()->getTechnology(); @@ -762,7 +781,9 @@ namespace { } for ( Net* net : cell->getNets() ) { + cdebug_log(101,1) << "Writing net " << net << endl; for ( Component* component : net->getComponents() ) { + cdebug_log(101,0) << "Writing " << component << endl; Polygon* polygon = dynamic_cast(component); if (polygon) { vector< vector > subpolygons; @@ -849,7 +870,7 @@ namespace { (*this) << TEXTTYPE( 0 ); cdebug_log(101,0) << "TEXTYPE end record" << endl; (*this) << PRESENTATION( 5 ); - (*this) << bb.getCenter(); + (*this) << putOnGrid( bb.getCenter() ); (*this) << STRING( name ); (*this) << ENDEL; cdebug_log(101,0) << "TEXT ENDEL" << endl; @@ -859,9 +880,11 @@ namespace { } } } + cdebug_tabw(101,-1); } (*this) << ENDSTR; + cdebug_tabw(101,-1); return *this; } diff --git a/crlcore/src/ccore/lefdef/LefImport.cpp b/crlcore/src/ccore/lefdef/LefImport.cpp index c2edc200..1b1e9925 100644 --- a/crlcore/src/ccore/lefdef/LefImport.cpp +++ b/crlcore/src/ccore/lefdef/LefImport.cpp @@ -147,6 +147,7 @@ namespace { Net* _net; string _busBits; double _unitsMicrons; + DbU::Unit _oneGrid; map< string, vector > _pinComponents; static map _layerLut; vector _unmatchedLayers; @@ -179,7 +180,6 @@ namespace { inline void LefParser::setCellGauge ( CellGauge* gauge ) { _cellGauge=gauge; } inline Net* LefParser::getNet () const { return _net; } inline void LefParser::setNet ( Net* net ) { _net=net; } - inline DbU::Unit LefParser::fromUnitsMicrons ( double d ) const { return DbU::fromPhysical(d,DbU::Micro); } inline double LefParser::getUnitsMicrons () const { return _unitsMicrons; } inline void LefParser::setUnitsMicrons ( double precision ) { _unitsMicrons=precision; } inline int LefParser::getNthMetal () const { return _nthMetal; } @@ -200,6 +200,18 @@ namespace { inline void LefParser::addPinComponent ( string name, Component* comp ) { _pinComponents[name].push_back(comp); } inline void LefParser::clearPinComponents () { _pinComponents.clear(); } + inline DbU::Unit LefParser::fromUnitsMicrons ( double d ) const + { + DbU::Unit u = DbU::fromPhysical(d,DbU::Micro); + if (u % _oneGrid) { + cerr << Error( "LefParser::fromUnitsMicrons(): Offgrid value %s (DbU=%d), grid %s (DbU=%d)." + , DbU::getValueString(u).c_str(), u + , DbU::getValueString(_oneGrid).c_str(), _oneGrid ) + << endl; + } + return u; + } + string LefParser::_gdsForeignDirectory = ""; Library* LefParser::_mergeLibrary = nullptr; @@ -264,6 +276,7 @@ namespace { , _net (nullptr) , _busBits ("()") , _unitsMicrons (0.01) + , _oneGrid (DbU::fromGrid(1.0)) , _unmatchedLayers () , _errors () , _nthMetal (0) @@ -497,7 +510,10 @@ namespace { LefParser* parser = (LefParser*)ud; AllianceFramework* af = AllianceFramework::get(); - if (_gdsForeignDirectory.empty()) return 0; + if (_gdsForeignDirectory.empty()) { + cerr << Warning( "LefParser::_macroForeignCbk(): GDS directory *not* set, ignoring FOREIGN statement." ) << endl; + return 0; + } string gdsPath = _gdsForeignDirectory + "/" + foreign->cellName() + ".gds"; parser->setForeignPath( gdsPath );