diff --git a/crlcore/cmake_modules/CMakeLists.txt b/crlcore/cmake_modules/CMakeLists.txt index 96455ade..d5e3deea 100644 --- a/crlcore/cmake_modules/CMakeLists.txt +++ b/crlcore/cmake_modules/CMakeLists.txt @@ -1,4 +1,3 @@ install ( FILES FindCORIOLIS.cmake FindOPENACCESS.cmake - FindLEFDEF.cmake DESTINATION share/cmake/Modules ) diff --git a/crlcore/cmake_modules/FindLEFDEF.cmake b/crlcore/cmake_modules/FindLEFDEF.cmake deleted file mode 100644 index a4e04f63..00000000 --- a/crlcore/cmake_modules/FindLEFDEF.cmake +++ /dev/null @@ -1,119 +0,0 @@ -# - Find the LEF/DEF includes and libraries. -# The following variables are set if LEF/DEF is found. If LEF/DEF is not -# found, LEFDEF_FOUND is set to false. -# LEFDEF_FOUND - True when LEF/DEF is found. -# LEFDEF_INCLUDE_DIR - the path to where the LEF/DEF include files are. -# LEFDEF_LIBRARIES - The path to where the LEF/DEF library files are. -# -# The DEF C API library: LEFDEF_CDEF_LIBRARY -# LEFDEF_CDEF_LIBRARY_RELEASE -# LEFDEF_CDEF_LIBRARY_DEBUG -# -# The DEF C API library (zlib) : LEFDEF_ZCDEF_LIBRARY -# LEFDEF_ZCDEF_LIBRARY_RELEASE -# LEFDEF_ZCDEF_LIBRARY_DEBUG -# -# The DEF C++ API library: LEFDEF_DEF_LIBRARY -# LEFDEF_DEF_LIBRARY_RELEASE -# LEFDEF_DEF_LIBRARY_DEBUG -# -# The DEF C++ API library (zlib) : LEFDEF_ZDEF_LIBRARY -# LEFDEF_ZDEF_LIBRARY_RELEASE -# LEFDEF_ZDEF_LIBRARY_DEBUG -# -# The LEF C API library: LEFDEF_CLEF_LIBRARY -# LEFDEF_CLEF_LIBRARY_RELEASE -# LEFDEF_CLEF_LIBRARY_DEBUG -# -# The LEF C API library (zlib) : LEFDEF_ZCLEF_LIBRARY -# LEFDEF_ZCLEF_LIBRARY_RELEASE -# LEFDEF_ZCLEF_LIBRARY_DEBUG -# -# The LEF C++ API library: LEFDEF_LEF_LIBRARY -# LEFDEF_LEF_LIBRARY_RELEASE -# LEFDEF_LEF_LIBRARY_DEBUG -# -# The LEF C++ API library (zlib) : LEFDEF_ZLEF_LIBRARY -# LEFDEF_ZLEF_LIBRARY_RELEASE -# LEFDEF_ZLEF_LIBRARY_DEBUG - - -macro ( _find_lefdef_lib varname libname ) - find_library ( LEFDEF_${varname}_LIBRARY_RELEASE NAMES ${libname} PATHS ${LEFDEF_LIBRARY_DIR} ) - find_library ( LEFDEF_${varname}_LIBRARY_DEBUG NAMES ${libname}_Debug PATHS ${LEFDEF_LIBRARY_DIR} ) - - if ( LEFDEF_${varname}_LIBRARY_RELEASE AND NOT LEFDEF_${varname}_LIBRARY_DEBUG ) - set ( LEFDEF_${varname}_LIBRARY_DEBUG ${LEFDEF_${varname}_LIBRARY_RELEASE} - CACHE STRING "Path to a library" FORCE ) - endif ( LEFDEF_${varname}_LIBRARY_RELEASE AND NOT LEFDEF_${varname}_LIBRARY_DEBUG ) - - if ( LEFDEF_${varname}_LIBRARY_DEBUG AND NOT LEFDEF_${varname}_LIBRARY_RELEASE ) - set ( LEFDEF_${varname}_LIBRARY_RELEASE LEFDEF_${varname}_LIBRARY_DEBUG - CACHE STRING "Path to a library" FORCE ) - endif ( LEFDEF_${varname}_LIBRARY_DEBUG AND NOT LEFDEF_${varname}_LIBRARY_RELEASE ) - - if ( LEFDEF_${varname}_LIBRARY_RELEASE ) - list ( APPEND LEFDEF_LIBRARIES "optimized" ${LEFDEF_${varname}_LIBRARY_RELEASE} - "debug" ${LEFDEF_${varname}_LIBRARY_DEBUG} ) - set ( LEFDEF_${varname}_LIBRARY_FOUND 1 ) - mark_as_advanced ( LEFDEF_${varname}_LIBRARY_RELEASE - LEFDEF_${varname}_LIBRARY_DEBUG ) - else ( LEFDEF_${varname}_LIBRARY_RELEASE ) - set ( LEFDEF_FOUND "NO" ) - endif ( LEFDEF_${varname}_LIBRARY_RELEASE ) -endmacro ( _find_lefdef_lib ) - - -set ( LEFDEF_INCLUDE_DIR_DESCRIPTION "directory containing the LEF/DEF include files. E.g /opt/lefdef-5.6/include" ) -set ( LEFDEF_LIBRARY_DIR_DESCRIPTION "directory containing the LEF/DEF library files. E.g /opt/lefdef-5.6/lib" ) -set ( LEFDEF_DIR_MESSAGE "Set the LEFDEF_INCLUDE_DIR cmake cache entry to the ${LEFDEF_INCLUDE_DIR_DESCRIPTION}" ) - -# Don't even bother under Win32 -if ( UNIX ) - set ( LEFDEF_FOUND "YES" ) - set ( LEFDEF_SEARCH_PATH $ENV{LEFDEF_TOP} - "/opt/lefdef-5.6" - "/opt/lefdef-5.7" - "/opt/lefdef") - - set ( LEFDEF_LIBRARIES "" ) - set ( LEFDEF_LIBRARY_SEARCH_PATH "" ) - foreach ( element ${LEFDEF_SEARCH_PATH} ) - list ( APPEND LEFDEF_LIBRARY_SEARCH_PATH "${element}/lib" ) - endforeach ( element ${LEFDEF_SEARCH_PATH} ) - - find_path ( LEFDEF_INCLUDE_DIR NAMES "defiDefs.h" - PATHS ${LEFDEF_SEARCH_PATH} - PATH_SUFFIXES "include" - DOC "The ${LEFDEF_INCLUDE_DIR_DESCRIPTION}" ) - - find_path ( LEFDEF_LIBRARY_DIR NAMES "libdef.a" "libdef_Debug.a" - PATHS ${LEFDEF_LIBRARY_SEARCH_PATH} - DOC "The ${LEFDEF_LIBRARY_DIR_DESCRIPTION}" ) - - if ( LEFDEF_INCLUDE_DIR AND LEFDEF_LIBRARY_DIR ) - _find_lefdef_lib ( "CDEF" "cdef" ) - _find_lefdef_lib ( "ZCDEF" "cdefzlib" ) - _find_lefdef_lib ( "DEF" "def" ) - _find_lefdef_lib ( "ZDEF" "defzlib" ) - _find_lefdef_lib ( "CLEF" "clef" ) - _find_lefdef_lib ( "ZCLEF" "clefzlib" ) - _find_lefdef_lib ( "LEF" "lef" ) - _find_lefdef_lib ( "ZLEF" "lefzlib" ) - else ( LEFDEF_INCLUDE_DIR AND LEFDEF_LIBRARY_DIR ) - set ( LEFDEF_FOUND "NO" ) - endif ( LEFDEF_INCLUDE_DIR AND LEFDEF_LIBRARY_DIR ) - - mark_as_advanced ( LEFDEF_INCLUDE_DIR LEFDEF_LIBRARY_DIR LEFDEF_LIBRARIES ) - - if ( LEFDEF_FOUND ) - add_definitions ( -DHAVE_LEFDEF ) - if ( NOT LEFDEF_FIND_QUIETLY ) - message ( STATUS "Found LEF/DEF" ) - endif ( NOT LEFDEF_FIND_QUIETLY ) - else ( LEFDEF_FOUND ) - if ( LEFDEF_FIND_REQUIRED ) - message ( STATUS "LEF/DEF libraries and/or includes NOT found!" ) - endif ( LEFDEF_FIND_REQUIRED ) - endif ( LEFDEF_FOUND ) -endif ( UNIX ) diff --git a/crlcore/etc/environment.alliance.xml b/crlcore/etc/environment.alliance.xml index 065d6b1a..889a5c35 100644 --- a/crlcore/etc/environment.alliance.xml +++ b/crlcore/etc/environment.alliance.xml @@ -8,9 +8,6 @@ ${CORIOLIS_TOP}/etc/coriolis2/technology.cmos130.s2r.xml - - ${CORIOLIS_TOP}/etc/coriolis2/cmos.lef - ${CORIOLIS_TOP}/etc/coriolis2/display.xml @@ -46,5 +43,6 @@ vdd vss ^do_not_find_ck$ + ^obstacleNet$ diff --git a/crlcore/etc/tools.configuration.xml b/crlcore/etc/tools.configuration.xml index fc279eb7..10e00439 100644 --- a/crlcore/etc/tools.configuration.xml +++ b/crlcore/etc/tools.configuration.xml @@ -70,10 +70,12 @@ + + @@ -127,19 +129,21 @@ + - - - - + + + + + - - - - - + + + + + diff --git a/crlcore/src/ccore/AllianceFramework.cpp b/crlcore/src/ccore/AllianceFramework.cpp index 1735e0af..2b3c215f 100644 --- a/crlcore/src/ccore/AllianceFramework.cpp +++ b/crlcore/src/ccore/AllianceFramework.cpp @@ -23,6 +23,7 @@ // x-----------------------------------------------------------------x +#include #include "hurricane/Warning.h" #include "hurricane/Technology.h" #include "hurricane/DataBase.h" @@ -78,6 +79,11 @@ namespace CRL { string userEnvironment = Environment::getEnv ( "HOME", "" ); _environment.loadFromXml ( userEnvironment+"/.environment.alliance.xml", false ); + char cwd[1024]; + getcwd ( cwd, 1024 ); + string cwdEnvironment = cwd; + _environment.loadFromXml ( cwdEnvironment+"/.environment.alliance.xml", false ); + SymbolicTechnologyParser::load ( db, _environment.getSYMBOLIC_TECHNOLOGY() ); RealTechnologyParser::load ( db, _environment.getREAL_TECHNOLOGY() ); GraphicsParser::load ( _environment.getDISPLAY() ); @@ -85,9 +91,9 @@ namespace CRL { if ( !_environment.getDisplayStyle().empty() ) Graphics::setStyle ( _environment.getDisplayStyle() ); - bool hasCatalog; - SearchPath& LIBRARIES = _environment.getLIBRARIES (); - Library* rootLibrary = db->getRootLibrary (); + unsigned int flags = InSearchPath; + SearchPath& LIBRARIES = _environment.getLIBRARIES (); + Library* rootLibrary = db->getRootLibrary (); cmess2 << " o Creating Alliance Framework root library." << endl; if ( !rootLibrary ) @@ -99,15 +105,13 @@ namespace CRL { cmess2 << " o Loading libraries (working first)." << endl; for ( unsigned i=0 ; igetLayer("METAL6"); + if ( routingLayer == NULL ) break; + + sxlibRg->addLayerGauge ( RoutingLayerGauge::create( routingLayer + , Constant::Horizontal + , Constant::Default + , 5 // Depth (?). + , 0 // Density. + , DbU::lambda(0) // Offset. + , DbU::lambda(5) // Pitch. + , DbU::lambda(2) // Wire width. + , DbU::lambda(3) // Via width. + ) ); +#if 0 + routingLayer = technology->getLayer("METAL7"); + if ( routingLayer == NULL ) break; + + sxlibRg->addLayerGauge ( RoutingLayerGauge::create( routingLayer + , Constant::Vertical + , Constant::Default + , 7 // Depth (?). + , 0 // Density. + , DbU::lambda(0) // Offset. + , DbU::lambda(5) // Pitch. + , DbU::lambda(2) // Wire width. + , DbU::lambda(3) // Via width. + ) ); +#endif } addRoutingGauge ( sxlibRg ); @@ -244,34 +277,37 @@ namespace CRL { } - AllianceLibrary* AllianceFramework::getAllianceLibrary ( const Name &path , bool &flag ) + AllianceLibrary* AllianceFramework::getAllianceLibrary ( unsigned index ) { + if ( index >= _libraries.size() ) + return NULL; + + return _libraries[index]; + } + + + AllianceLibrary* AllianceFramework::getAllianceLibrary ( const Name &path, unsigned int& flags ) + { + string spath = getString ( path ); size_t slash = spath.rfind ( '/' ); string sname = spath.substr ( (slash!=string::npos)?slash+1:0 ); - AllianceLibrary* library = new AllianceLibrary ( path, Library::create(getParentLibrary(),sname) ); - string catalog = spath + "/" + _environment.getCATALOG(); + for ( size_t ilib=0 ; ilib<_libraries.size() ; ++ilib ) { + if ( _libraries[ilib]->getLibrary()->getName() == sname ) + return _libraries[ilib]; + } - flag = false; - if ( _catalog.loadFromFile(catalog,library->getLibrary()) ) flag = true; + return (flags&CreateLibrary) ? createLibrary ( getString(path), flags ) : NULL; + } - ParserFormatSlot& parser = _parsers.getParserSlot ( spath, Catalog::State::Physical, _environment ); - if ( !parser.loadByLib() ) return library; - - size_t base = spath.find_last_of ( '/' ); - if ( base == spath.npos ) return library; - - string file = spath.substr(base+1,spath.size()-base); - - // Load the whole library. - if ( ! _readLocate(file,Catalog::State::State::Logical,true) ) return library; - - // Call the parser function. - (parser.getParsLib())( _environment.getLIBRARIES().getSelected() , library->getLibrary() , _catalog ); - - return library; + AllianceLibrary* AllianceFramework::getAllianceLibrary ( Library* library ) + { + for ( size_t ilib=0 ; ilib<_libraries.size() ; ++ilib ) { + if ( _libraries[ilib]->getLibrary() == library ) return _libraries[ilib]; + } + return NULL; } @@ -336,19 +372,97 @@ namespace CRL { } - Cell* AllianceFramework::createCell ( const string& name ) + AllianceLibrary* AllianceFramework::createLibrary ( const string& path, unsigned int& flags ) + { + size_t slash = path.rfind ( '/' ); + string libName = path.substr ( (slash!=string::npos)?slash+1:0 ); + + flags &= ~HasCatalog; + + AllianceLibrary* library = getAllianceLibrary ( libName, flags ); + if ( library != NULL ) { + cerr << Warning("AllianceFramework::createLibrary(): Attempt to re-create <%s>, using already existing." + ,libName.c_str()) << endl; + return library; + } + + SearchPath& LIBRARIES = _environment.getLIBRARIES (); + if ( not (flags & InSearchPath) ) LIBRARIES.prepend ( path ); + else LIBRARIES.select ( path ); + + library = new AllianceLibrary ( path, Library::create(getParentLibrary(),libName) ); + + AllianceLibraries::iterator ilib = _libraries.begin(); + for ( size_t i=0 ; igetLibrary()) ) flags |= HasCatalog; + + ParserFormatSlot& parser = _parsers.getParserSlot ( path, Catalog::State::Physical, _environment ); + + if ( not parser.loadByLib() ) return library; + + if ( slash == path.npos ) return library; + string file = path.substr(slash+1,path.size()-slash); + + // Load the whole library. + if ( ! _readLocate(file,Catalog::State::State::Logical,true) ) return library; + + // Call the parser function. + (parser.getParsLib())( _environment.getLIBRARIES().getSelected() , library->getLibrary() , _catalog ); + + return library; + } + + + void AllianceFramework::saveLibrary ( Library* library ) + { + if ( library == NULL ) return; + + AllianceLibrary* alibrary = getAllianceLibrary ( library ); + if ( alibrary == NULL ) { + throw Error("AllianceFramework::saveLibrary(): Cannot save non-Alliance library <%s>." + ,getString(library->getName()).c_str()); + } + + saveLibrary ( alibrary ); + } + + + void AllianceFramework::saveLibrary ( AllianceLibrary* library ) + { + if ( library == NULL ) return; + + bfs::path libPath ( getString(library->getPath()) ); + if ( not bfs::exists(libPath) ) { + bfs::create_directory(libPath); + } + + forEach ( Cell*, icell, library->getLibrary()->getCells() ) { + saveCell ( *icell, Catalog::State::Views ); + } + } + + + Cell* AllianceFramework::createCell ( const string& name, AllianceLibrary* library ) { Catalog::State* state = _catalog.getState ( name ); // The cell is not in the CATAL : add an entry. if ( state == NULL ) state = _catalog.getState ( name, true ); + if ( library == NULL ) + library = _libraries[0]; + if ( !state->getCell() ) { state->setPhysical ( true ); state->setLogical ( true ); state->setDepth ( 1 ); - state->setCell ( Cell::create ( _libraries[0]->getLibrary() , name ) ); + state->setCell ( Cell::create ( library->getLibrary() , name ) ); state->getCell ()->put ( CatalogProperty::create(state) ); state->getCell ()->setFlattenLeaf ( false ); } @@ -357,14 +471,15 @@ namespace CRL { } - void AllianceFramework::saveCell ( Cell* cell , unsigned int mode ) + void AllianceFramework::saveCell ( Cell* cell, unsigned int mode ) { - if ( !cell ) return; + if ( cell == NULL ) return; - string name = getString(cell->getName()); - DriverSlot* driver; - unsigned int saveMode; - unsigned int savedViews = 0; + string name = getString(cell->getName()); + DriverSlot* driver; + unsigned int saveMode = 0; + unsigned int savedViews = 0; + AllianceLibrary* library = getAllianceLibrary ( cell->getLibrary() ); for ( int i=0 ; i<2 ; i++ ) { // Check is the view is requested for saving or already saved. @@ -381,6 +496,8 @@ namespace CRL { driver = & ( _drivers.getDriverSlot ( name, saveMode, _environment ) ); // Try to open cell file (file extention is supplied by the parser). + if ( library != NULL ) + _environment.getLIBRARIES().select ( getString(library->getPath()) ); if ( !_writeLocate(name,saveMode,false) ) continue; // Call the driver function. @@ -473,7 +590,7 @@ namespace CRL { // Try to open using the library driver. name = file + "." + getString(format.getExtLib()); - LIBRARIES.locate ( name, ios::out|ios::trunc, 0, 1 ); + LIBRARIES.locate ( name, ios::out|ios::trunc ); if ( LIBRARIES.hasSelected() ) return true; } else { if ( !format.getDrivCell() ) return false; @@ -481,7 +598,7 @@ namespace CRL { // Try to open using the cell driver. name = file + "." + getString(format.getExtCell()); - LIBRARIES.locate ( name, ios::out|ios::trunc, 0, 1 ); + LIBRARIES.locate ( name, ios::out|ios::trunc ); if ( LIBRARIES.hasSelected() ) return true; } return false; diff --git a/crlcore/src/ccore/CMakeLists.txt b/crlcore/src/ccore/CMakeLists.txt index d27fa65b..4b53b40a 100644 --- a/crlcore/src/ccore/CMakeLists.txt +++ b/crlcore/src/ccore/CMakeLists.txt @@ -16,6 +16,8 @@ ${CRLCORE_SOURCE_DIR}/src/ccore/properties ${CRLCORE_SOURCE_DIR}/src/ccore/bookshelf ${CRLCORE_SOURCE_DIR}/src/ccore/acmsigda + ${CRLCORE_SOURCE_DIR}/src/ccore/ispd04 + ${CRLCORE_SOURCE_DIR}/src/ccore/iccad04 ${CRLCORE_SOURCE_DIR}/src/ccore/cspice ${CRLCORE_SOURCE_DIR}/src/ccore/lefdef ${CRLCORE_SOURCE_DIR}/src/ccore/alliance/ap @@ -52,6 +54,11 @@ crlcore/AllianceLibrary.h crlcore/ParsersDrivers.h crlcore/LefDefExtension.h + crlcore/DefImport.h + crlcore/DefExport.h + crlcore/LefExport.h + crlcore/Iccad04Lefdef.h + crlcore/Ispd04Bookshelf.h crlcore/Ioc.h crlcore/NetExtension.h crlcore/Measures.h @@ -123,20 +130,28 @@ # liberty/TimingEvent.cpp # liberty/LuTable.cpp # ) - set ( lefdef_cpps lefdef/LefDef.h +# set ( lefdef_cpps lefdef/LefDef.h +# lefdef/LefDefExtension.cpp +# lefdef/LefParser.cpp +# lefdef/DefParser.cpp +# lefdef/DefDriver.cpp +# ) + set ( lefdef_cpps lefdef/LefExport.cpp + lefdef/DefExport.cpp + lefdef/DefImport.cpp lefdef/LefDefExtension.cpp - lefdef/LefParser.cpp - lefdef/DefParser.cpp - lefdef/DefDriver.cpp - ) + ) + set ( iccad04_cpps iccad04/Iccad04Lefdef.cpp ) + set ( ispd04_cpps ispd04/Ispd04Bookshelf.cpp ) if ( LEFDEF_FOUND ) include_directories ( ${LEFDEF_INCLUDE_DIR} ) endif ( LEFDEF_FOUND ) if ( OA_FOUND ) include_directories ( ${OA_INCLUDE_DIR} ) endif ( OA_FOUND ) - set (openaccess_cpps openaccess/OpenAccessDriver.cpp - openaccess/OpenAccessParser.cpp ) + set (openaccess_cpps openaccess/OpenAccessParser.cpp + openaccess/OpenAccessDriver.cpp + ) set ( VstParserSourceDir ${CRLCORE_SOURCE_DIR}/src/ccore/alliance/vst ) set ( VstParserBinaryDir ${CRLCORE_BINARY_DIR}/src/ccore/alliance/vst ) @@ -269,6 +284,8 @@ ${liberty_parser_cpps} ${bookshelf_cpps} ${acmsigda_parser_cpps} + ${iccad04_cpps} + ${ispd04_cpps} ${spice_cpps} ${lefdef_cpps} ${openaccess_cpps} @@ -276,6 +293,7 @@ target_link_libraries ( crlcore ${HURRICANE_PYTHON_LIBRARIES} ${HURRICANE_GRAPHICAL_LIBRARIES} ${HURRICANE_LIBRARIES} + ${BOOKSHELF_LIBRARY} ${CONFIGURATION_LIBRARY} ${CIF_LIBRARY} ${AGDS_LIBRARY} diff --git a/crlcore/src/ccore/Environment.cpp b/crlcore/src/ccore/Environment.cpp index e950b21a..f553fbf9 100644 --- a/crlcore/src/ccore/Environment.cpp +++ b/crlcore/src/ccore/Environment.cpp @@ -73,7 +73,6 @@ namespace { , TagsTechnologies , TagsHurricane , TagsReal - , TagsLEF , TagsDisplay , TagsConfig , TagsLibraries @@ -96,7 +95,6 @@ namespace { }; enum State { HurricaneTechnology = 1 , RealTechnology - , LEFTechnology , Display , WorkingLibrary , SystemLibrary @@ -124,7 +122,6 @@ namespace { void parseTechnologies (); void parseHurricane (); void parseReal (); - void parseLEF (); void parseDisplay (); void parseDisplayStyle (); void parseConfig (); @@ -164,8 +161,6 @@ namespace { addTagEntry ( TagsHurricane , "config" , (tagParser_t)&XmlEnvironmentParser::parseConfig ); addTagEntry ( TagsTechnologies, "real" , (tagParser_t)&XmlEnvironmentParser::parseReal ); addTagEntry ( TagsReal , "config" , (tagParser_t)&XmlEnvironmentParser::parseConfig ); - addTagEntry ( TagsTechnologies, "lef" , (tagParser_t)&XmlEnvironmentParser::parseLEF ); - addTagEntry ( TagsLEF , "config" , (tagParser_t)&XmlEnvironmentParser::parseConfig ); addTagEntry ( TagsTechnologies, "display" , (tagParser_t)&XmlEnvironmentParser::parseDisplay ); addTagEntry ( TagsDisplay , "config" , (tagParser_t)&XmlEnvironmentParser::parseConfig ); addTagEntry ( TagsDisplay , "displaystyle", (tagParser_t)&XmlEnvironmentParser::parseDisplayStyle ); @@ -323,13 +318,6 @@ namespace { } - void XmlEnvironmentParser::parseLEF () - { - _state = LEFTechnology; - parseTags ( TagsLEF ); - } - - void XmlEnvironmentParser::parseDisplay () { _state = Display; @@ -357,7 +345,6 @@ namespace { expandVariables ( config ); switch ( _state ) { case HurricaneTechnology: _environment.setSYMBOLIC_TECHNOLOGY ( config.c_str() ); break; - case LEFTechnology: _environment.setLEF_TECHNOLOGY ( config.c_str() ); break; case RealTechnology: _environment.setREAL_TECHNOLOGY ( config.c_str() ); break; case Display: _environment.setDISPLAY ( config.c_str() ); break; } @@ -528,7 +515,6 @@ namespace CRL { , _displayStyle () , _SCALE_X (10) , _SYMBOLIC_TECHNOLOGY("") - , _LEF_TECHNOLOGY ("") , _DISPLAY ("") , _IN_LO ("vst") , _IN_PH ("ap") @@ -644,8 +630,6 @@ namespace CRL { << " \"" << _CORIOLIS_TOP << "\"\n" << " - Symbolic Technology:\n" << " \"" << _SYMBOLIC_TECHNOLOGY << "\"\n" - << " - LEF Technology:\n" - << " \"" << _LEF_TECHNOLOGY << "\"\n" << " - Display configuration:\n" << " \"" << _DISPLAY << "\"\n"; diff --git a/crlcore/src/ccore/OAParserDriver.cpp b/crlcore/src/ccore/OAParserDriver.cpp index d38b3e69..7cfd28e9 100644 --- a/crlcore/src/ccore/OAParserDriver.cpp +++ b/crlcore/src/ccore/OAParserDriver.cpp @@ -11,7 +11,7 @@ namespace CRL { OADriver::OADriver(Cell* cell) : _cell(cell) {} void OADriver::save(const std::string& filePath) { - CRL::OpenAccess::oaDriver(filePath, _cell); + //CRL::OpenAccess::oaDriver(filePath, _cell); } OAParser::OAParser(const std::string& cellLibPath,const std::string& cellLibName, diff --git a/crlcore/src/ccore/ParsersDrivers.cpp b/crlcore/src/ccore/ParsersDrivers.cpp index d364f012..d766c292 100644 --- a/crlcore/src/ccore/ParsersDrivers.cpp +++ b/crlcore/src/ccore/ParsersDrivers.cpp @@ -51,19 +51,18 @@ -# include "hurricane/DBo.h" +#include "hurricane/DBo.h" -# include "crlcore/Utilities.h" -# include "crlcore/Environment.h" -# include "crlcore/Catalog.h" -# include "crlcore/ParsersDrivers.h" -# include "Ap.h" -# include "Vst.h" -# include "Spice.h" -# include "Bookshelf.h" -# include "AcmSigda.h" -# include "LefDef.h" -# include "openaccess/OpenAccess.h" +#include "crlcore/Utilities.h" +#include "crlcore/Environment.h" +#include "crlcore/Catalog.h" +#include "crlcore/ParsersDrivers.h" +#include "Ap.h" +#include "Vst.h" +#include "Spice.h" +#include "Bookshelf.h" +#include "AcmSigda.h" +#include "openaccess/OpenAccess.h" namespace { @@ -214,15 +213,13 @@ namespace CRL { ParsersMap::ParsersMap (): map() { // Register the Alliance default parsers. - registerSlot ( "ap" , (CellParser_t*)apParser , "ap" ); - registerSlot ( "vst", (CellParser_t*)vstParser , "vst" ); - registerSlot ( "vst", (CellParser_t*)vstParser , "vbe" ); - registerSlot ( "spi", (CellParser_t*)spiceParser , "spi" ); - registerSlot ( "def", (CellParser_t*)defParser , "def" ); - registerSlot ( "def", (LibraryParser_t*)lefParser , "lef" ); - registerSlot ( "oa", (CellParser_t*)OpenAccess::oaCellParser , "oa" ); -// registerSlot ( "oa", (LibraryParser_t*)OpenAccess::oaLibParser , "oa" ); - registerSlot ( "aux", (CellParser_t*)bookshelfParser, "aux" ); + registerSlot ( "ap" , (CellParser_t*)apParser , "ap" ); + registerSlot ( "vst" , (CellParser_t*)vstParser , "vst" ); + registerSlot ( "vst" , (CellParser_t*)vstParser , "vbe" ); + registerSlot ( "spi" , (CellParser_t*)spiceParser , "spi" ); + registerSlot ( "oa" , (CellParser_t*)OpenAccess::oaCellParser , "oa" ); + //registerSlot ( "oa" , (LibraryParser_t*)OpenAccess::oaLibParser, "oa" ); + registerSlot ( "aux" , (CellParser_t*)bookshelfParser, "aux" ); registerSlot ( "bench", (CellParser_t*)acmSigdaParser , "bench" ); } @@ -333,10 +330,10 @@ namespace CRL { // Register the Alliance default drivers. registerSlot ( "ap" , (CellDriver_t*)apDriver , "ap" ); registerSlot ( "vst", (CellDriver_t*)vstDriver , "vst" ); - registerSlot ( "def", (CellDriver_t*)defDriver , "def" ); + //registerSlot ( "def", (CellDriver_t*)defDriver , "def" ); registerSlot ( "aux", (CellDriver_t*)bookshelfDriver, "test.aux" ); registerSlot ( "spi", (CellDriver_t*)spiceDriver , "spi" ); - registerSlot ( "oa" , (CellDriver_t*)OpenAccess::oaDriver, "oa"); + //registerSlot ( "oa" , (CellDriver_t*)OpenAccess::oaDriver, "oa"); } diff --git a/crlcore/src/ccore/SearchPath.cpp b/crlcore/src/ccore/SearchPath.cpp index ae2aa3d2..43f79c19 100644 --- a/crlcore/src/ccore/SearchPath.cpp +++ b/crlcore/src/ccore/SearchPath.cpp @@ -26,42 +26,86 @@ # include "crlcore/SearchPath.h" +namespace { + + using namespace std; + + +} // End of anonymous namespace. + + namespace CRL { using namespace std; - const size_t SearchPath::npos = (size_t)-1; + const size_t SearchPath::npos = (size_t)-1; + const string SearchPath::_selectFailed = ""; SearchPath::SearchPath () : _paths () , _index (npos) - , _selected("") + , _selected(_selectFailed) + { } + + + bool SearchPath::_canOpen ( const string& directory, const string& file, ios::openmode mode ) { + _selected = directory + "/" + file; + fstream filestream ( _selected.c_str(), mode ); + if ( filestream.is_open() ) { + filestream.close (); + return true; + } + _selected = _selectFailed; + return false; + } + + + void SearchPath::prepend ( const std::string& path ) + { + vector::iterator ipath = _paths.begin(); + + _index = 0; + if ( ipath != _paths.end() ) { ++ipath; ++_index; } + + _paths.insert ( ipath, path ); } void SearchPath::replace ( const string& path, size_t index ) { + _index = index; if ( index < _paths.size() ) _paths[index] = path; } - size_t SearchPath ::locate ( const string& file, ios::openmode mode, int first, int last ) + void SearchPath::select ( const string& path ) { - for ( int i=max(0,first) ; i < min((int)_paths.size(),last) ; i++ ) { - string path = _paths[i] + "/" + file; + for ( size_t ipath=0 ; ipath < _paths.size() ; ++ipath ) { + if ( _paths[ipath] == path ) { + _selected = _paths[ipath]; + _index = ipath; + return; + } + } - fstream filestream ( path.c_str(), mode ); - if ( filestream.is_open() ) { - filestream.close (); - _selected = path; + _selected = _selectFailed; + _index = npos; + } + + + size_t SearchPath::locate ( const string& file, ios::openmode mode, int first, int last ) + { + if ( hasSelected() and _canOpen(_paths[_index],file,mode) ) return _index; + + for ( int i=max(0,first) ; i < min((int)_paths.size(),last) ; i++ ) { + if ( _canOpen(_paths[i],file,mode) ) { return _index = i; } } - _selected = ""; return _index = npos; } diff --git a/crlcore/src/ccore/alliance/ap/ApDriver.cpp b/crlcore/src/ccore/alliance/ap/ApDriver.cpp index 8946c945..1e4b5f22 100644 --- a/crlcore/src/ccore/alliance/ap/ApDriver.cpp +++ b/crlcore/src/ccore/alliance/ap/ApDriver.cpp @@ -95,12 +95,12 @@ bool toMBKLayer ( const char*& mbkLayer tableLayer [ "METAL5" ] = "ALU5"; tableLayer [ "METAL6" ] = "ALU6"; - tableLayer [ "OBSTACLE1" ] = "TALU1"; - tableLayer [ "OBSTACLE2" ] = "TALU2"; - tableLayer [ "OBSTACLE3" ] = "TALU3"; - tableLayer [ "OBSTACLE4" ] = "TALU4"; - tableLayer [ "OBSTACLE5" ] = "TALU5"; - tableLayer [ "OBSTACLE6" ] = "TALU6"; + tableLayer [ "BLOCKAGE1" ] = "TALU1"; + tableLayer [ "BLOCKAGE2" ] = "TALU2"; + tableLayer [ "BLOCKAGE3" ] = "TALU3"; + tableLayer [ "BLOCKAGE4" ] = "TALU4"; + tableLayer [ "BLOCKAGE5" ] = "TALU5"; + tableLayer [ "BLOCKAGE6" ] = "TALU6"; tableConnector [ "METAL1" ] = "CALU1"; tableConnector [ "METAL2" ] = "CALU2"; diff --git a/crlcore/src/ccore/alliance/vst/VstDriver.cpp b/crlcore/src/ccore/alliance/vst/VstDriver.cpp index cc10e026..cdec8351 100644 --- a/crlcore/src/ccore/alliance/vst/VstDriver.cpp +++ b/crlcore/src/ccore/alliance/vst/VstDriver.cpp @@ -50,6 +50,48 @@ namespace { using namespace CRL; + class GlobalNetLookup { + public: + inline void addLookup ( Net* ); + inline Net* lookup ( const string& ); + inline bool isGlobal ( Net* ); + inline void clear (); + private: + map _globalNets; + }; + + + inline void GlobalNetLookup::addLookup ( Net* globalNet ) + { + if ( globalNet == NULL ) return; + _globalNets.insert ( make_pair(getString(globalNet->getName()) + ,globalNet + ) ); + } + + + inline Net* GlobalNetLookup::lookup ( const string& name ) + { + map::iterator inet = _globalNets.find(name); + if ( inet == _globalNets.end() ) return NULL; + return (*inet).second; + } + + + inline bool GlobalNetLookup::isGlobal ( Net* globalNet ) + { + if ( globalNet == NULL ) return false; + return (lookup(getString(globalNet->getName())) != NULL); + } + + + inline void GlobalNetLookup::clear () + { _globalNets.clear (); } + + + GlobalNetLookup __globalNets; + + void FilterPointsInStrings(string& s) { // Problem in VST... : the . which seems to represent hierachy paths // in ap is not supported... @@ -297,18 +339,20 @@ void DumpSignalList(ofstream &ccell, Cell* cell) { StringPtVector netsString; NetSet netSet; - for_each_net(net, cell->getInternalNets()) + forEach(Net*, inet, cell->getNets()) { - string* stringName = new string(net->getName()._getString()); + if ( not (*inet)->isExternal() ) { + string* stringName = new string(inet->getName()._getString()); FilterPointsInStrings(*stringName); netsString.push_back(stringName); - NetSet::iterator nsit = netSet.find(net); + NetSet::iterator nsit = netSet.find(*inet); if (nsit != netSet.end()) - { - throw Error("two times the same name"); - } - netSet.insert(net); - end_for; + throw Error("two times the same name"); + netSet.insert(*inet); + } + if ( (*inet)->isGlobal() ) { + __globalNets.addLookup ( *inet ); + } } sort(netsString.begin(), netsString.end(), StringSort()); @@ -412,7 +456,7 @@ void DumpConnectionList(ofstream &ccell, Instance*instance) throw Error("Cannot find net named " + *string1); } if (string1OpenPar == string::npos) - { + { Plug* plug = spmit->second; string connectedNetName; if (plug->isConnected()) { @@ -430,19 +474,21 @@ void DumpConnectionList(ofstream &ccell, Instance*instance) Net* masterNet = plug->getMasterNet(); if (masterNet->isGlobal()) // connection by name { - for_each_net(globalnet, instance->getCell()->getGlobalNets()) + Net* globalNet = __globalNets.lookup ( getString(masterNet->getName()) ); + if ( globalNet != NULL ) connectedNetName = getString(globalNet->getName()); +#if VERY_SLOW + for_each_net(globalnet, instance->getCell()->getGlobalNets()) { - if (globalnet->getName() == masterNet->getName()) + if (globalnet->getName() == masterNet->getName()) { - connectedNetName = string(masterNet->getName()._getString()); - break; + connectedNetName = string(masterNet->getName()._getString()); + break; } - end_for; - } - if (connectedNetName == string()) - { - throw Error("No global net " + masterNet->getName()._getString() + " in cell " + instance->getCell()->getName()._getString()); + end_for; } +#endif + if ( connectedNetName.empty() ) + throw Error("No global net " + masterNet->getName()._getString() + " in cell " + instance->getCell()->getName()._getString()); } else @@ -616,6 +662,8 @@ namespace CRL { void vstDriver ( const string cellPath, Cell *cell, unsigned int &saveState ) { + __globalNets.clear (); + ::std::ofstream ccell ( cellPath.c_str() ); ccell << "entity " << cell->getName() << " is" << endl; DumpPortList(ccell, cell); diff --git a/crlcore/src/ccore/crlcore/AllianceFramework.h b/crlcore/src/ccore/crlcore/AllianceFramework.h index 7457be1e..0e1f345f 100644 --- a/crlcore/src/ccore/crlcore/AllianceFramework.h +++ b/crlcore/src/ccore/crlcore/AllianceFramework.h @@ -28,6 +28,7 @@ #include +#include #include "crlcore/Environment.h" #include "crlcore/AllianceLibrary.h" @@ -45,6 +46,7 @@ namespace CRL { class AllianceFramework { public: enum InstancesCountFlags { Recursive=0x1, IgnoreFeeds=0x2 }; + enum LibraryFlags { CreateLibrary=0x1, InSearchPath=0x2, HasCatalog=0x4 }; public: // Constructors. static AllianceFramework* create (); @@ -71,8 +73,13 @@ namespace CRL { inline Catalog* getCatalog (); inline const Name& getParentLibraryName () const; inline Library* getParentLibrary (); - Library* getLibrary ( unsigned index ); - AllianceLibrary* getAllianceLibrary ( const Name& path, bool& flag ); + Library* getLibrary ( unsigned int index ); + AllianceLibrary* getAllianceLibrary ( unsigned int index ); + AllianceLibrary* getAllianceLibrary ( const Name& path, unsigned int& flags ); + AllianceLibrary* getAllianceLibrary ( Library* ); + AllianceLibrary* createLibrary ( const string& path, unsigned int& flags ); + void saveLibrary ( Library* ); + void saveLibrary ( AllianceLibrary* ); RoutingGauge* getRoutingGauge ( const Name& name="" ); CellGauge* getCellGauge ( const Name& name="" ); inline const Name getDefaultCGPinLayerName () const; @@ -83,11 +90,11 @@ namespace CRL { Cell* getCell ( const string& name , unsigned int mode , unsigned int depth=(unsigned int)-1 ); - Cell* createCell ( const string& name ); - void saveCell ( Cell* cell , unsigned int mode ); - unsigned int loadLibraryCells ( Library* library ); - unsigned int loadLibraryCells ( const Name& name ); - static size_t getInstancesCount ( Cell* cell, unsigned int flags ); + Cell* createCell ( const string& name, AllianceLibrary* library=NULL ); + void saveCell ( Cell* , unsigned int mode ); + unsigned int loadLibraryCells ( Library* ); + unsigned int loadLibraryCells ( const Name& ); + static size_t getInstancesCount ( Cell*, unsigned int flags ); // Internals - Attributes. protected: @@ -115,6 +122,7 @@ namespace CRL { // Internals - Methods. bool _readLocate ( const string& file, unsigned int mode, bool isLib=false ); bool _writeLocate ( const string& file, unsigned int mode, bool isLib=false ); + AllianceLibrary* _createLibrary ( const string& path, bool& hasCatalog ); }; diff --git a/crlcore/src/ccore/crlcore/DefExport.h b/crlcore/src/ccore/crlcore/DefExport.h new file mode 100644 index 00000000..bddae85d --- /dev/null +++ b/crlcore/src/ccore/crlcore/DefExport.h @@ -0,0 +1,49 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | C a d e n c e D E F E x p o r t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/DefExport.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __CRL_DEF_EXPORT__ +#define __CRL_DEF_EXPORT__ + + +namespace Hurricane { + class Cell; +} + + +namespace CRL { + + + class DefExport { + public: + enum Flag { WithLEF=0x1, ExpandDieArea=0x2 }; + public: + static void drive ( Hurricane::Cell*, unsigned int flags ); + }; + + +} // End of CRL namespace. + + +#endif // __CRL_DEF_EXPORT__ diff --git a/crlcore/src/ccore/crlcore/DefImport.h b/crlcore/src/ccore/crlcore/DefImport.h new file mode 100644 index 00000000..65a0267e --- /dev/null +++ b/crlcore/src/ccore/crlcore/DefImport.h @@ -0,0 +1,50 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | C a d e n c e D E F I m p o r t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/DefImport.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __CRL_DEF_IMPORT__ +#define __CRL_DEF_IMPORT__ + +#include + +namespace Hurricane { + class Cell; +} + + +namespace CRL { + + + class DefImport { + public: + enum Flags { FitAbOnCells=0x1 }; + public: + static Hurricane::Cell* load ( std::string design, unsigned int flags ); + }; + + +} // End of CRL namespace. + + +#endif // __CRL_DEF_IMPORT__ diff --git a/crlcore/src/ccore/crlcore/Environment.h b/crlcore/src/ccore/crlcore/Environment.h index b8d0a209..a4de9fb0 100644 --- a/crlcore/src/ccore/crlcore/Environment.h +++ b/crlcore/src/ccore/crlcore/Environment.h @@ -53,7 +53,6 @@ namespace CRL { inline long getSCALE_X () const; inline const std::string& getSYMBOLIC_TECHNOLOGY () const; inline const std::string& getREAL_TECHNOLOGY () const; - inline const std::string& getLEF_TECHNOLOGY () const; inline const std::string& getDISPLAY () const; inline const std::string& getIN_LO () const; inline const std::string& getIN_PH () const; @@ -79,7 +78,6 @@ namespace CRL { inline void setSCALE_X ( long value ); inline void setSYMBOLIC_TECHNOLOGY ( const char* value ); inline void setREAL_TECHNOLOGY ( const char* value ); - inline void setLEF_TECHNOLOGY ( const char* value ); inline void setDISPLAY ( const char* value ); inline void setIN_LO ( const char* value ); inline void setIN_PH ( const char* value ); @@ -102,7 +100,6 @@ namespace CRL { std::string _displayStyle; long _SCALE_X; std::string _SYMBOLIC_TECHNOLOGY; - std::string _LEF_TECHNOLOGY; std::string _REAL_TECHNOLOGY; std::string _DISPLAY; std::string _IN_LO; @@ -134,7 +131,6 @@ namespace CRL { inline long Environment::getSCALE_X () const { return _SCALE_X; } inline const std::string& Environment::getSYMBOLIC_TECHNOLOGY () const { return _SYMBOLIC_TECHNOLOGY; } inline const std::string& Environment::getREAL_TECHNOLOGY () const { return _REAL_TECHNOLOGY; } - inline const std::string& Environment::getLEF_TECHNOLOGY () const { return _LEF_TECHNOLOGY; } inline const std::string& Environment::getDISPLAY () const { return _DISPLAY; } inline const std::string& Environment::getIN_LO () const { return _IN_LO; } inline const std::string& Environment::getIN_PH () const { return _IN_PH; } @@ -151,7 +147,6 @@ namespace CRL { inline void Environment::setSCALE_X ( long value ) { _SCALE_X = value; } inline void Environment::setSYMBOLIC_TECHNOLOGY ( const char* value ) { _SYMBOLIC_TECHNOLOGY = value; } inline void Environment::setREAL_TECHNOLOGY ( const char* value ) { _REAL_TECHNOLOGY = value; } - inline void Environment::setLEF_TECHNOLOGY ( const char* value ) { _LEF_TECHNOLOGY = value; } inline void Environment::setDISPLAY ( const char* value ) { _DISPLAY = value; } inline void Environment::setIN_LO ( const char* value ) { _IN_LO = value; } inline void Environment::setIN_PH ( const char* value ) { _IN_PH = value; } diff --git a/crlcore/src/ccore/crlcore/Iccad04Lefdef.h b/crlcore/src/ccore/crlcore/Iccad04Lefdef.h new file mode 100644 index 00000000..2da366fb --- /dev/null +++ b/crlcore/src/ccore/crlcore/Iccad04Lefdef.h @@ -0,0 +1,52 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | ICCAD04 IBM Standard Cell Benchmarks | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/Iccad04Lefdef.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __CRL_ICCAD04_LEFDEF__ +#define __CRL_ICCAD04_LEFDEF__ + +#include + +namespace Hurricane { + class Cell; +} + + +namespace CRL { + + using Hurricane::Cell; + + + class Iccad04Lefdef { + public: + enum Flags { NoFlags=0x0 }; + public: + static Cell* load ( std::string benchmark, unsigned int flags=0 ); + }; + + +} // End of CRL namespace. + + +#endif // __CRL_ICCAD04_LEFDEF__ diff --git a/crlcore/src/ccore/crlcore/Ispd04Bookshelf.h b/crlcore/src/ccore/crlcore/Ispd04Bookshelf.h new file mode 100644 index 00000000..d69fc8ac --- /dev/null +++ b/crlcore/src/ccore/crlcore/Ispd04Bookshelf.h @@ -0,0 +1,51 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | ISPD04 IBM Standard Cell Benchmarks | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/Ispd04Bookshelf.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __CRL_ISPD04_BOOKSHELF__ +#define __CRL_ISPD04_BOOKSHELF__ + +#include + +namespace Hurricane { + class Cell; +} + + +namespace CRL { + + using Hurricane::Cell; + + + class Ispd04 { + public: + static Cell* load ( std::string benchmark ); + }; + + +} // End of CRL namespace. + + +#endif // __CRL_ISPD04_BOOKSHELF__ + diff --git a/crlcore/src/ccore/crlcore/LefExport.h b/crlcore/src/ccore/crlcore/LefExport.h new file mode 100644 index 00000000..ca2e49c0 --- /dev/null +++ b/crlcore/src/ccore/crlcore/LefExport.h @@ -0,0 +1,51 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | C a d e n c e D E F E x p o r t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/LefExport.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __CRL_LEF_EXPORT__ +#define __CRL_LEF_EXPORT__ + + +namespace Hurricane { + class Cell; + class Library; +} + + +namespace CRL { + + + class LefExport { + public: + enum Flag { WithTechnology=0x1 }; + public: + static void drive ( Hurricane::Cell* , unsigned int flags ); + static void drive ( Hurricane::Library*, unsigned int flags ); + }; + + +} // End of CRL namespace. + + +#endif // __CRL_LEF_EXPORT__ diff --git a/crlcore/src/ccore/crlcore/SearchPath.h b/crlcore/src/ccore/crlcore/SearchPath.h index 27d48afd..f4bc8f37 100644 --- a/crlcore/src/ccore/crlcore/SearchPath.h +++ b/crlcore/src/ccore/crlcore/SearchPath.h @@ -48,24 +48,30 @@ namespace CRL { public: inline void reset (); inline void append ( const std::string& path ); - inline void prepend ( const std::string& path ); + void prepend ( const std::string& path ); void replace ( const std::string& path, size_t index ); size_t locate ( const std::string& file , std::ios::openmode mode =std::ios::in , int first=0 , int last =64 ); + void select ( const std::string& ); inline size_t getSize () const; inline const std::string& getSelected () const; inline size_t getIndex () const; - bool hasSelected () const; + inline bool hasSelected () const; size_t hasPath ( const std::string& path ) const; const std::string& operator[] ( size_t index ) const; private: + static const std::string _selectFailed; std::vector _paths; size_t _index; std::string _selected; private: SearchPath ( const SearchPath& ); + bool _canOpen ( const std::string& directory + , const std::string& file + , std::ios::openmode mode + ); public: inline std::string _getTypeName () const; std::string _getString () const; @@ -75,7 +81,6 @@ namespace CRL { // Inline Functions. inline void SearchPath::reset () { _paths.resize(1); } - inline void SearchPath::prepend ( const std::string& path ) { _paths.insert ( _paths.begin(), path ); } inline void SearchPath::append ( const std::string& path ) { _paths.push_back(path); } inline size_t SearchPath::getSize () const { return _paths.size(); } inline const std::string& SearchPath::getSelected () const { return _selected; } diff --git a/crlcore/src/ccore/iccad04/Iccad04Lefdef.cpp b/crlcore/src/ccore/iccad04/Iccad04Lefdef.cpp new file mode 100644 index 00000000..b65e67ed --- /dev/null +++ b/crlcore/src/ccore/iccad04/Iccad04Lefdef.cpp @@ -0,0 +1,1126 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | ICCAD04 IBM Standard Cell Benchmarks | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./Iccad04Lefdef.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include +#include +#if HAVE_LEFDEF +# include "lefrReader.hpp" +# include "defrReader.hpp" +#endif +#include "hurricane/Error.h" +#include "hurricane/Warning.h" +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/Net.h" +#include "hurricane/NetExternalComponents.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "hurricane/Cell.h" +#include "hurricane/Library.h" +#include "hurricane/UpdateSession.h" +#include "crlcore/Utilities.h" +#include "crlcore/ToolBox.h" +#include "crlcore/AllianceFramework.h" +#include "crlcore/Iccad04Lefdef.h" + + +#if HAVE_LEFDEF + +namespace { + + using namespace std; + using namespace Hurricane; + using namespace CRL; + + class LefParser; + + + string toLower ( const char* s ) + { + if ( s == NULL ) return ""; + + string lowered; + for ( const char* p=s; (*p) != '\0' ; ++p ) lowered += tolower(*p); + + return lowered; + } + + + void addSupplyNets ( Cell* cell ) + { + Net* vss = Net::create ( cell, "vss" ); + vss->setExternal ( true ); + vss->setGlobal ( true ); + vss->setType ( Net::Type::GROUND ); + + Net* vdd = Net::create ( cell, "vdd" ); + vdd->setExternal ( true ); + vdd->setGlobal ( true ); + vdd->setType ( Net::Type::POWER ); + } + + + class Ports { + public: + Ports ( LefParser* ); + void copyPinNames ( vector& pinNames ); + bool addGeometry ( double x, double y, const char* pinName ); + bool addGeometry ( size_t pitchNb, size_t sliceNb, const char* pinName ); + void normalize (); + void makeTerminals (); + void makeBlockages (); + void clear (); + void toStream ( ostream& ); + private: + typedef pair PinPosition; + typedef map Slice; + typedef vector Area; + private: + LefParser* _parser; + Area _area; + size_t _coronaPitch; + size_t _coronaSlice; + }; + + + class LefParser { + public: + static double getCoreSiteWidth (); + static double getCoreSiteHeight (); + static DbU::Unit getSliceHeight (); + static DbU::Unit getPitchWidth (); + static AllianceFramework* getFramework (); + static bool hasPadMacro (); + static bool isPadMacro ( const char* ); + static bool isPadMacro ( const string& ); + static void setPadMacro ( const string& ); + static void parse ( string file ); + LefParser ( string& file, AllianceLibrary* ); + ~LefParser (); + inline bool hasErrors (); + inline AllianceLibrary* getLibrary (); + inline Cell* getCell (); + inline size_t getPitchs () const; + inline size_t getSlices () const; + inline size_t getReadPins () const; + inline Ports& getPorts (); + inline vector& getErrors (); + inline void pushError ( const string& ); + int flushErrors ( const string& ); + inline void clearErrors (); + inline void clearPorts (); + inline void resetReadPins (); + inline void setPitchs ( size_t ); + inline void setSlices ( size_t ); + inline void incReadPins (); + void makeBlock (); + private: + static int _macroCbk ( lefrCallbackType_e, lefiMacro*, lefiUserData ); + static int _pinCbk ( lefrCallbackType_e, lefiPin* , lefiUserData ); + Cell* _createCell ( const char* name ); + private: + static const double _coreSiteWidth; + static const double _coreSiteHeight; + static DbU::Unit _sliceHeight; + static DbU::Unit _pitchWidth; + static AllianceFramework* _framework; + static Name _padMacro; + string _file; + AllianceLibrary* _library; + Cell* _cell; + size_t _pitchs; + size_t _slices; + size_t _readPins; + Ports _ports; + vector _errors; + }; + + + Ports::Ports ( LefParser* parser ) + : _parser (parser) + , _area () + , _coronaPitch(0) + , _coronaSlice(0) + { + //cerr << "Ports::Ports() - " << _pitch << "," << _sliceHeight << endl; + } + + + void Ports::copyPinNames ( vector& pinNames ) + { + for ( size_t islice=0 ; islice<_area.size() ; ++islice ) { + Slice::iterator ipos = _area[islice].begin (); + for ( ; ipos != _area[islice].end() ; ++ipos ) { + pinNames.push_back ( (*ipos).second.second ); + } + } + } + + + bool Ports::addGeometry ( size_t pitchNb, size_t sliceNb, const char* pinName ) + { + //cerr << "re-addGeom: " << pitchNb << "x" << sliceNb << " " << pinName << endl; + + while ( _area.size() < sliceNb+1 ) _area.push_back ( Slice() ); + + Slice& slice = _area[sliceNb]; + + Slice::iterator ipos = slice.find ( pitchNb ); + while ( ipos != slice.end() ) { + ipos = slice.find ( ++pitchNb ); + } + + slice.insert ( make_pair(pitchNb,PinPosition(pitchNb,pinName)) ); + + if ( pitchNb > _coronaPitch ) _coronaPitch = pitchNb; + if ( sliceNb > _coronaSlice ) _coronaSlice = sliceNb; + + return true; + } + + + bool Ports::addGeometry ( double x, double y, const char* pinName ) + { + size_t pitchNb = (size_t)floor ( x / LefParser::getCoreSiteWidth () ); + size_t sliceNb = (size_t)floor ( y / LefParser::getCoreSiteHeight() ); + + //cerr << "Add Geometry: " << x << "," << y + // << " " << pitchNb << "," << sliceNb << " " + // << pinName << endl; + + while ( _area.size() < sliceNb+1 ) _area.push_back ( Slice() ); + + Slice& slice = _area[sliceNb]; + + Slice::iterator ipos = slice.find ( pitchNb ); + while ( ipos != slice.end() ) { + ipos = slice.find ( ++pitchNb ); + } + + slice.insert ( make_pair(pitchNb,PinPosition(pitchNb,pinName)) ); + + if ( pitchNb > _coronaPitch ) _coronaPitch = pitchNb; + if ( sliceNb > _coronaSlice ) _coronaSlice = sliceNb; + + return true; + } + + + void Ports::normalize () + { + // Check that no terminal is outside the AbutmentBox. + // The corona must be inside the AB. If not, shrink coordinates. + if ( _coronaPitch >= _parser->getPitchs() ) { + cerr << Warning("Some terminals of <%s> are outside the X abutment-box (shrinkeds, " + "X corona %zd vs. %zd)." + ,getString(_parser->getCell()->getName()).c_str() + ,_coronaPitch + ,_parser->getPitchs() + ) << endl; + + double xshrinkFactor = (double)(_parser->getPitchs()-1) / (double)_coronaPitch; + + for ( size_t islice=0 ; islice<_area.size() ; ++islice ) { + if ( _area[islice].empty() ) continue; + if ( _area[islice].size () == _parser->getPitchs() ) continue; + + Slice::iterator ipos = _area[islice].begin(); + for ( ; ipos != _area[islice].end() ; ++ipos ) { + PinPosition& position = (*ipos).second; + + if ( position.first == 0 ) + position.first = 1; + else + position.first = (size_t)round( xshrinkFactor * (double)position.first ); + } + } + } + + // Re-inserting pins to in-range slices. + if ( _coronaSlice > _parser->getSlices()-1 ) { + cerr << Warning("Terminals of block <%s> are outside the Y abutment-box (shrinkeds, " + "Y corona %zd vs. %zd)." + ,getString(_parser->getCell()->getName()).c_str() + ,_coronaSlice + ,_parser->getSlices() + ) << endl; + + double yshrinkFactor = (double)(_parser->getSlices()-1) / (double)_coronaSlice; + + for ( size_t islice=_parser->getSlices() ; islice<_area.size() ; ++islice ) { + if ( _area[islice].empty() ) continue; + + Slice::iterator ipos = _area[islice].begin(); + for ( ; ipos != _area[islice].end() ; ++ipos ) { + PinPosition& position = (*ipos).second; + + size_t isliceShrink = (size_t)round( yshrinkFactor * (double)islice ); + addGeometry ( position.first, isliceShrink, position.second.c_str() ); + } + } + + _area.resize ( _parser->getSlices() ); + } + + if ( _coronaSlice < _parser->getSlices()-1 ) { + cerr << Warning("Terminals of block <%s> are inside the Y abutment-box (shrinkeds, " + "Y corona %zd vs. %zd)." + ,getString(_parser->getCell()->getName()).c_str() + ,_coronaSlice + ,_parser->getSlices() + ) << endl; + size_t missings = _parser->getSlices()-1-_coronaSlice; + for ( ; missings > 0 ; --missings ) + _area.insert ( ++_area.begin(), Slice() ); + } + + // Resolving overlaps + for ( size_t islice=0 ; islice<_area.size() ; ++islice ) { + if ( _area[islice].empty() ) continue; + if ( _area[islice].size () == _parser->getPitchs() ) continue; + + // Fisrt pass: unoverlap from left to right. + size_t lastx = 0; + Slice::iterator ipos = _area[islice].begin(); + for ( ; ipos != _area[islice].end() ; ++ipos ) { + PinPosition& position = (*ipos).second; + + if ( position.first <= lastx ) { + // Shift right overlapping terminals. + ++lastx; + //cerr << " shift right: " << position.second << " " + // << position.first << " -> " << lastx << endl; + position.first = lastx; + } else { + //cerr << " unmoved: " << position.second << " " + // << position.first << endl; + lastx = position.first; + } + } + + // Second pass: unoverlap from right to left. + lastx = _parser->getPitchs(); + Slice::reverse_iterator ripos = _area[islice].rbegin(); + for ( ; ripos != _area[islice].rend() ; ++ripos ) { + PinPosition& position = (*ripos).second; + + if ( position.first >= lastx ) { + // Shift right overlapping terminals. + //cerr << " shift left: " << position.second << " " + // << position.first << " <- " << lastx-1 << endl; + position.first = lastx-1; + } + + lastx = position.first; + } + } + + if ( _parser->getSlices() > 1 ) { + // Block case. + for ( size_t islice=0 ; islice<_area.size() ; ++islice ) { + if ( _area[islice].empty() ) continue; + PinPosition& pos = (*_area[islice].rbegin()).second; + + if ( pos.first < _parser->getPitchs()-1 ) { + pos.first = _parser->getPitchs()-1; + } + } + + // Compact extraneous rows. + bool canCompact = true; + while ( canCompact and (_area.size() > _parser->getSlices()) ) { + canCompact = false; + + Area::iterator islice = _area.begin(); + for ( ; islice != _area.end() ; ++islice ) { + if ( (*islice).empty() ) { + _area.erase ( islice ); + canCompact = true; + break; + } + } + } + } + } + + + void Ports::makeTerminals () + { + Technology* technology = DataBase::getDB()->getTechnology(); + Layer* METAL1 = technology->getLayer ( "METAL1" ); + Box abutmentBox ( _parser->getCell()->getAbutmentBox() ); + + //abutmentBox.inflate ( DbU::lambda(1.0) ); + + for ( size_t islice=0 ; islice<_area.size() ; ++islice ) { + if ( _area[islice].empty() ) continue; + + DbU::Unit ymin = LefParser::getSliceHeight()* islice + LefParser::getPitchWidth()*2; + DbU::Unit ymax = LefParser::getSliceHeight()*(islice+1) - LefParser::getPitchWidth()*2; + + Slice::iterator ipos = _area[islice].begin(); + for ( ; ipos != _area[islice].end() ; ++ipos ) { + PinPosition& pos = (*ipos).second; + + //cerr << " Net: " << toLower(pos.second.c_str()) + // << " [" << pos.first << "] of " << _parser->getCell()->getName() << endl; + + Net* net = Net::create ( _parser->getCell(), toLower(pos.second.c_str()) ); + net->setExternal ( true ); + + Segment* segment = Vertical::create ( net + , METAL1 + , LefParser::getPitchWidth()*pos.first + , DbU::lambda(1.0) + , ymin + , ymax + ); + NetExternalComponents::setExternal ( segment ); + + if ( not abutmentBox.contains(segment->getBoundingBox()) ) { + cerr << Error("Terminal <%s> of <%s> is outside abutment box." + ,getString(net->getName()).c_str() + ,getString(_parser->getCell()->getName()).c_str() + ) << endl; + } + } + } + } + + + void Ports::makeBlockages () + { +#if BLOCKAGES_ENABLEDS + Technology* technology = DataBase::getDB()->getTechnology(); + Layer* BLOCKAGE2 = technology->getLayer ( "BLOCKAGE2" ); + Layer* BLOCKAGE3 = technology->getLayer ( "BLOCKAGE3" ); + Cell* cell = _parser->getCell (); + size_t slices = _parser->getSlices (); + size_t pitchs = _parser->getPitchs (); + DbU::Unit pitch = LefParser::getPitchWidth (); + DbU::Unit sliceHeight = LefParser::getSliceHeight (); + + if ( _parser->getSlices() < 2 ) return; + + DbU::Unit axis = (sliceHeight * (slices-2)) / 2 + sliceHeight; + DbU::Unit width = sliceHeight * (slices-2); + + Net* net = Net::create ( cell, "obstacleNet" ); + + Horizontal::create ( net + , BLOCKAGE2 + , axis + , width + , pitch * 2 + , pitch * (pitchs-2) + ); + + axis = (pitch * (pitchs-4)) / 2 + 2*pitch; + width = pitch * (pitchs-4); + + Vertical::create ( net + , BLOCKAGE3 + , axis + , width + , sliceHeight + , sliceHeight * (slices-1) + ); +#endif + } + + + void Ports::clear () + { + _area.clear (); + _coronaPitch = 0; + _coronaSlice = 0; + } + + + void Ports::toStream ( ostream& out ) + { + for ( size_t islice=0 ; islice<_area.size() ; ++islice ) { + out << "[" << setw(3) << islice << "]: "; + + Slice::iterator ipos = _area[islice].begin (); + for ( ; ipos != _area[islice].end() ; ++ipos ) { + out << (*ipos).first << ":" << (*ipos).second.second << " "; + } + + out << endl; + } + } + + + const double LefParser::_coreSiteWidth = 0.01; + const double LefParser::_coreSiteHeight = 0.16; + DbU::Unit LefParser::_sliceHeight = 0; + DbU::Unit LefParser::_pitchWidth = 0; + AllianceFramework* LefParser::_framework = NULL; + Name LefParser::_padMacro = ""; + + + + LefParser::LefParser ( string& file, AllianceLibrary* library ) + : _file (file) + , _library (library) + , _cell (NULL) + , _pitchs (0) + , _slices (0) + , _readPins(0) + , _ports (this) + , _errors () + { + _sliceHeight = DbU::lambda ( 50.0 ); + _pitchWidth = DbU::lambda ( 5.0 ); + + lefrInit (); + lefrSetMacroCbk ( _macroCbk ); + lefrSetPinCbk ( _pinCbk ); + } + + + LefParser::~LefParser () + { + lefrReset (); + } + + + double LefParser::getCoreSiteWidth () { return _coreSiteWidth; } + double LefParser::getCoreSiteHeight () { return _coreSiteHeight; } + DbU::Unit LefParser::getSliceHeight () { return _sliceHeight; } + DbU::Unit LefParser::getPitchWidth () { return _pitchWidth; } + AllianceFramework* LefParser::getFramework () { return _framework; } + bool LefParser::hasPadMacro () { return _padMacro!=Name(); } + bool LefParser::isPadMacro ( const char* modelName ) { return _padMacro==Name(modelName); } + bool LefParser::isPadMacro ( const string& modelName ) { return _padMacro==Name(modelName); } + void LefParser::setPadMacro ( const string& modelName ) { _padMacro=modelName; } + inline bool LefParser::hasErrors () { return not _errors.empty(); } + inline AllianceLibrary* LefParser::getLibrary () { return _library; } + inline Cell* LefParser::getCell () { return _cell; } + inline size_t LefParser::getPitchs () const { return _pitchs; } + inline size_t LefParser::getSlices () const { return _slices; } + inline size_t LefParser::getReadPins () const { return _readPins; } + inline Ports& LefParser::getPorts () { return _ports; } + inline vector& LefParser::getErrors () { return _errors; } + inline void LefParser::pushError ( const string& error ) { _errors.push_back(error); } + inline void LefParser::clearErrors () { return _errors.clear(); } + inline void LefParser::clearPorts () { return _ports.clear(); } + inline void LefParser::resetReadPins () { _readPins=0; } + inline void LefParser::setPitchs ( size_t pitchs ) { _pitchs=pitchs; } + inline void LefParser::setSlices ( size_t slices ) { _slices=slices; } + inline void LefParser::incReadPins () { ++_readPins; } + + + int LefParser::flushErrors ( const string& macroName ) + { + int code = (hasErrors()) ? 1 : 0; + + for ( size_t ierror=0 ; ierror < _errors.size() ; ++ierror ) { + string message = "Iccad04Lefdef::load(): " + _errors[ierror]; + cerr << Error(message.c_str(),macroName.c_str()) << endl; + } + clearErrors (); + + return code; + } + + + void LefParser::makeBlock () + { + size_t perimeter = _readPins + (_readPins%2); + + _slices = 4; + _pitchs = (perimeter - 8) + 1; + + //cerr << "_slices: " << _slices << endl; + //cerr << "_pitchs: " << _pitchs << endl; + + vector pinNames; + _ports.copyPinNames ( pinNames ); + _ports.clear (); + + size_t bottomCount = _pitchs/2; + size_t rightCount = bottomCount + _slices; + size_t topCount = rightCount + _pitchs/2; + + for ( size_t ipin=0 ; ipincreateCell ( toLower(name), _library ); + + Box abutmentBox ( 0 + , 0 + , _pitchs*LefParser::getPitchWidth () + , _slices*LefParser::getSliceHeight() + ); + _cell->setAbutmentBox ( abutmentBox ); + addSupplyNets ( _cell ); + + Technology* technology = DataBase::getDB()->getTechnology(); + Layer* METAL1 = technology->getLayer ( "METAL1" ); + size_t slices = (size_t)_slices; + DbU::Unit vssWidth = DbU::lambda(6.0); + DbU::Unit vddWidth = DbU::lambda(6.0); + DbU::Unit vssAxis; + DbU::Unit vddAxis; + + Net* vss = _cell->getNet ( "vss" ); + Net* vdd = _cell->getNet ( "vdd" ); + + for ( size_t islice=0 ; islicegetPorts().toStream ( cerr ); + string macroName = toLower(macro->name()); + + if ( not macro->hasSize() ) { + cerr << Error("Iccad04Lefdef::load(): Macro <%s> doesn't have size.",macroName.c_str()) << endl; + return 0; + } + + if ( (macro->originX() != 0.0) or (macro->originY() != 0.0) ) + throw Error("Iccad04Lefdef::load(): Macro <%s> is not at (0,0) origin (%.2f,%.2f)." + ,macroName.c_str() + ,macro->originX() + ,macro->originY() + ); + + parser->setPitchs ( (size_t)round ( macro->sizeX() / LefParser::getCoreSiteWidth () ) ); + parser->setSlices ( (size_t)round ( macro->sizeY() / LefParser::getCoreSiteHeight() ) ); + + if ( (parser->getSlices() == 0) and not LefParser::hasPadMacro() ) { + if ( abs(macro->sizeY() - LefParser::getCoreSiteWidth()) < 1e-9 ) { + parser->setPadMacro ( macroName ); + parser->clearPorts(); + cmess2 << " - Pad/Macro (1x1): " << macroName << endl; + return 0; + } + } + + if ( abs((double)parser->getPitchs()*LefParser::getCoreSiteWidth() - macro->sizeX()) > 1e-9 ) { + parser->_ports.clear (); + cerr << Error("Iccad04Lefdef::load(): Macro <%s> doesn't have a pitched size, %.2f." + ,macroName.c_str(),macro->sizeX()) << endl; + return 0; + } + + if ( abs((double)parser->getSlices()*LefParser::getCoreSiteHeight() - macro->sizeY()) > 1e-9 ) { + parser->clearPorts (); + cerr << Error("Iccad04Lefdef::load(): Macro <%s> doesn't have a sliced size, %.2f." + ,macroName.c_str(),macro->sizeY()) << endl; + return 0; + } + + if ( parser->getReadPins() > parser->getPitchs()-1 ) { + cerr << Error("Iccad04Lefdef::load(): Macro <%s> has more ports than pitches (%zd vs. %zd)." + ,macroName.c_str(),parser->getReadPins(),parser->getPitchs()) << endl; + if ( parser->getReadPins() > 40 ) + parser->makeBlock (); + else + parser->setPitchs ( parser->getReadPins() + 1 ); + } + + parser->flushErrors ( macroName ); + parser->_createCell ( macroName.c_str() ); + + if ( parser->getSlices() > 1 ) { + cmess2 << " - Macro-block: " << macroName + << " " << macro->sizeX() << "x" << macro->sizeY() + << " " << parser->getPitchs() << "x" << parser->getSlices() + << endl; + } + // } else { + // cmess2 << " - Macro: " << macro->name() + // << " " << macro->sizeX() << "x" << macro->sizeY() + // << " " << parser->getPitchs() << "x" << parser->getSlices() + // << endl; + // } + + parser->getPorts().normalize (); + parser->getPorts().makeTerminals (); + parser->getPorts().makeBlockages (); + parser->clearPorts (); + parser->resetReadPins (); + return 0; + } + + + int LefParser::_pinCbk ( lefrCallbackType_e c, lefiPin* pin, lefiUserData ud ) + { + LefParser* parser = (LefParser*)ud; + parser->incReadPins (); + + ostringstream message; + + int numPorts = pin->numPorts (); + for ( int iport=0 ; iportport ( iport ); + + if ( geometries->numItems() > 2 ) { + message << "Pin <" << pin->name() << "> of <%s> have more than one geometries, " + << geometries->numItems() << "."; + parser->pushError ( message.str() ); + message.str ( "" ); + } + if ( geometries->numItems() == 0 ) { + message << "Pin <" << pin->name() << "> of <%s> have no geometries."; + parser->pushError ( message.str() ); + message.str ( "" ); + continue; + } + if ( geometries->itemType(1) != lefiGeomRectE ) { + message << "Geometry [1] of pin <" << pin->name() << "> of <%s> is not a RECT."; + parser->pushError ( message.str() ); + message.str ( "" ); + continue; + } + + lefiGeomRect* rect = geometries->getRect(1); + + // cerr << "RECT " << rect->xl << " " << rect->yl << " " << rect->xh << " " << rect->yh << " " << endl; + parser->_ports.addGeometry ( (rect->xl < 0.0) ? 0.0 : rect->xl + , (rect->yl < 0.0) ? 0.0 : rect->yl + , pin->name() ); + } + + + return 0; + } + + + void LefParser::parse ( string file ) + { + cmess1 << " o LEF: <" << file << ">" << endl; + + size_t iext = file.rfind ( '.' ); + if ( file.compare(iext,4,".lef") != 0 ) + throw Error ("Iccad04Lefdef::load(): LEF files must have \".lef\" extension <%s>.",file.c_str()); + + _framework = AllianceFramework::get (); + + unsigned int libraryFlags = 0; + string libraryPath = "./" + file.substr ( 0, file.size()-4 ) + "lib"; + AllianceLibrary* library = _framework->createLibrary ( libraryPath, libraryFlags ); + auto_ptr parser ( new LefParser(file,library) ); + + FILE* lefStream = fopen ( file.c_str(), "r" ); + if ( lefStream == NULL ) + throw Error ("Iccad04Lefdef::load(): Cannot open LEF file <%s>.",file.c_str()); + + lefrRead ( lefStream, file.c_str(), (lefiUserData)parser.get() ); + + fclose ( lefStream ); + + _framework->saveLibrary ( library ); + } + + + class DefParser { + public: + static AllianceFramework* getFramework (); + static Cell* parse ( string file, unsigned int flags ); + DefParser ( string& file, AllianceLibrary* ); + ~DefParser (); + inline bool hasErrors (); + inline bool isPad ( const string& ); + inline AllianceLibrary* getLibrary (); + inline Cell* getCell (); + inline size_t getPitchs () const; + inline size_t getSlices () const; + inline const Box& getRowsArea () const; + inline vector& getErrors (); + inline void pushError ( const string& ); + inline void addPad ( const string& ); + int flushErrors (); + inline void clearErrors (); + inline void clearPads (); + inline void setPitchs ( size_t ); + inline void setSlices ( size_t ); + void mergeWithRowsArea ( const Box& ); + private: + static int _designEndCbk ( defrCallbackType_e, void* , defiUserData ); + static int _dieAreaCbk ( defrCallbackType_e, defiBox* , defiUserData ); + static int _rowCbk ( defrCallbackType_e, defiRow* , defiUserData ); + static int _componentCbk ( defrCallbackType_e, defiComponent*, defiUserData ); + static int _componentEndCbk ( defrCallbackType_e, void* , defiUserData ); + static int _netCbk ( defrCallbackType_e, defiNet* , defiUserData ); + Cell* _createCell ( const char* name ); + private: + static AllianceFramework* _framework; + string _file; + AllianceLibrary* _library; + Cell* _cell; + size_t _pitchs; + size_t _slices; + Box _rowsArea; + set _pads; + vector _errors; + }; + + + AllianceFramework* DefParser::_framework = NULL; + + + DefParser::DefParser ( string& file, AllianceLibrary* library ) + : _file (file) + , _library (library) + , _cell (NULL) + , _pitchs (0) + , _slices (0) + , _rowsArea() + , _pads () + , _errors () + { + defrInit (); + defrSetDesignEndCbk ( _designEndCbk ); + defrSetDieAreaCbk ( _dieAreaCbk ); + defrSetRowCbk ( _rowCbk ); + defrSetComponentCbk ( _componentCbk ); + defrSetComponentEndCbk ( _componentEndCbk ); + defrSetNetCbk ( _netCbk ); + defrSetNetEndCbk ( _componentEndCbk ); + } + + + DefParser::~DefParser () + { + defrReset (); + } + + + AllianceFramework* DefParser::getFramework () { return _framework; } + inline bool DefParser::hasErrors () { return not _errors.empty(); } + inline bool DefParser::isPad ( const string& pad ) { return _pads.find(pad)!=_pads.end(); } + inline AllianceLibrary* DefParser::getLibrary () { return _library; } + inline Cell* DefParser::getCell () { return _cell; } + inline size_t DefParser::getPitchs () const { return _pitchs; } + inline size_t DefParser::getSlices () const { return _slices; } + inline const Box& DefParser::getRowsArea () const { return _rowsArea; } + inline vector& DefParser::getErrors () { return _errors; } + inline void DefParser::pushError ( const string& error ) { _errors.push_back(error); } + inline void DefParser::addPad ( const string& pad ) { _pads.insert(pad); } + inline void DefParser::clearErrors () { return _errors.clear(); } + inline void DefParser::clearPads () { return _pads.clear(); } + inline void DefParser::setPitchs ( size_t pitchs ) { _pitchs=pitchs; } + inline void DefParser::setSlices ( size_t slices ) { _slices=slices; } + + + Cell* DefParser::_createCell ( const char* name ) + { + _cell = DefParser::getFramework()->createCell ( toLower(name), NULL ); + addSupplyNets ( _cell ); + + return _cell; + } + + + int DefParser::flushErrors () + { + int code = (hasErrors()) ? 1 : 0; + + for ( size_t ierror=0 ; ierror < _errors.size() ; ++ierror ) { + string message = "Iccad04Lefdef::load(): " + _errors[ierror]; + cerr << Error(message.c_str(),getString(_cell->getName()).c_str()) << endl; + } + clearErrors (); + + return code; + } + + + void DefParser::mergeWithRowsArea ( const Box& rowBox ) + { + _rowsArea.merge(rowBox); + } + + + int DefParser::_designEndCbk ( defrCallbackType_e c, void*, lefiUserData ud ) + { + DefParser* parser = (DefParser*)ud; + + Box rowsArea = parser->getRowsArea(); + + if ( not rowsArea.isEmpty() ) { + // Ensure the rowsArea is an integral number of slices/pitchs. + DbU::Unit widthRemainder = rowsArea.getWidth() % LefParser::getPitchWidth(); + if ( widthRemainder != 0 ) widthRemainder -= LefParser::getPitchWidth(); + + DbU::Unit heightRemainder = rowsArea.getWidth() % LefParser::getSliceHeight(); + if ( heightRemainder != 0 ) heightRemainder -= LefParser::getSliceHeight(); + + rowsArea.inflate ( 0, 0, -widthRemainder, -heightRemainder ); + + if ( parser->getCell()->getAbutmentBox().isEmpty() ) { + parser->getCell()->setAbutmentBox ( rowsArea ); + } else { + if ( parser->getCell()->getAbutmentBox().contains(rowsArea ) ) + parser->getCell()->setAbutmentBox ( rowsArea ); + } + } + + return 0; + } + + + int DefParser::_dieAreaCbk ( defrCallbackType_e c, defiBox* box, lefiUserData ud ) + { + DefParser* parser = (DefParser*)ud; + + DbU::Unit width = LefParser::getPitchWidth () * (DbU::Unit)(0.01 * (box->xh() - box->xl()) / LefParser::getCoreSiteWidth ()); + DbU::Unit height = LefParser::getSliceHeight() * (DbU::Unit)(0.01 * (box->yh() - box->yl()) / LefParser::getCoreSiteHeight()); + + parser->getCell()->setAbutmentBox ( Box(0,0,width,height) ); + + return 0; + } + + + int DefParser::_rowCbk ( defrCallbackType_e c, defiRow* row, lefiUserData ud ) + { + DefParser* parser = (DefParser*)ud; + + double rowBoxXMax = row->x(); + double rowBoxYMax = row->y(); + + if ( row->hasDo() ) { + if ( row->hasDoStep() ) { + rowBoxXMax += (row->xNum() - 1.0) * row->xStep() + LefParser::getCoreSiteWidth () * 100.0; + rowBoxYMax += (row->yNum() - 1.0) * row->yStep() + LefParser::getCoreSiteHeight() * 100.0; + } else { + rowBoxXMax += row->xNum() * LefParser::getCoreSiteWidth () * 100.0; + rowBoxYMax += row->yNum() * LefParser::getCoreSiteHeight() * 100.0; + } + } + + //cerr << "[" << row->x() << " " << row->y() + // << " " << rowBoxXMax << " " << rowBoxYMax << "]" << endl; + + parser->mergeWithRowsArea ( Box(DbU::lambda(row->x()) + ,DbU::lambda(row->y()) + ,DbU::lambda(rowBoxXMax) + ,DbU::lambda(rowBoxYMax) + ) ); + + return 0; + } + + + int DefParser::_componentCbk ( defrCallbackType_e c, defiComponent* component, lefiUserData ud ) + { + DefParser* parser = (DefParser*)ud; + + string componentName = toLower(component->name()); + string componentId = toLower(component->id()); + + if ( LefParser::isPadMacro(componentName) ) { + parser->addPad ( componentId ); + return 0; + } + + Cell* masterCell = DefParser::getFramework()->getCell ( componentName, Catalog::State::Views ); + if ( masterCell == NULL ) { + ostringstream message; + message << "Unknown model (LEF MACRO) " << componentName << " in <%s>."; + parser->pushError ( message.str() ); + return 0; + } + + Instance::create ( parser->getCell(), componentId, masterCell ); + + return 0; + } + + + int DefParser::_netCbk ( defrCallbackType_e c, defiNet* net, lefiUserData ud ) + { + DefParser* parser = (DefParser*)ud; + + //cout << " - Net " << net->name() << endl; + + Net* hnet = Net::create ( parser->getCell(), toLower(net->name()) ); + + int numConnections = net->numConnections(); + for ( int icon=0 ; iconinstance(icon)); + string pinName = toLower(net->pin(icon)); + + if ( parser->isPad(net->instance(icon)) ) { + hnet->setExternal ( true ); + continue; + } + + Instance* instance = parser->getCell()->getInstance ( instanceName ); + if ( instance == NULL ) { + ostringstream message; + message << "Unknown instance (DEF COMPONENT) " << instanceName << " in <%s>."; + parser->pushError ( message.str() ); + continue; + } + + Net* masterNet = instance->getMasterCell()->getNet ( pinName ); + if ( masterNet == NULL ) { + ostringstream message; + message << "Unknown PIN <" << pinName << "> in instance <" + << instanceName << "> of <" << instance->getMasterCell()->getName() + << "> (LEF MACRO) in <%s>."; + parser->pushError ( message.str() ); + continue; + } + + instance->getPlug(masterNet)->setNet(hnet); + } + + return 0; + } + + + int DefParser::_componentEndCbk ( defrCallbackType_e c, void*, lefiUserData ud ) + { + DefParser* parser = (DefParser*)ud; + return parser->flushErrors (); + } + + + Cell* DefParser::parse ( string file, unsigned int flags ) + { + cmess1 << " o DEF: <" << file << ">" << endl; + + size_t iext = file.rfind ( '.' ); + if ( file.compare(iext,4,".def") != 0 ) + throw Error ("Iccad04Lefdef::load(): DEF files must have \".def\" extension <%s>.",file.c_str()); + + _framework = AllianceFramework::get (); + + unsigned int libraryFlags = 0; + size_t islash = file.rfind ( '/' ); + string designName = file.substr ( ((islash == string::npos) ? 0 : islash), file.size()-4 ); + AllianceLibrary* library = _framework->getAllianceLibrary ( designName+"lib", libraryFlags ); + auto_ptr parser ( new DefParser(file,library) ); + + FILE* defStream = fopen ( file.c_str(), "r" ); + if ( defStream == NULL ) + throw Error ("Iccad04Lefdef::load(): Cannot open DEF file <%s>.",file.c_str()); + + parser->_createCell ( designName.c_str() ); + defrRead ( defStream, file.c_str(), (defiUserData)parser.get(), 1 ); + + fclose ( defStream ); + + return parser->getCell(); + } + + +} // End of anonymous namespace. + +#endif // HAVE_LEFDEF. + + +namespace CRL { + + using std::string; + using std::cerr; + using std::endl; + using Hurricane::Library; + using Hurricane::Transformation; + using Hurricane::UpdateSession; + + + Cell* Iccad04Lefdef::load ( string benchmark, unsigned int flags ) + { + Cell* cell = NULL; + +#if HAVE_LEFDEF + UpdateSession::open (); + + LefParser::parse ( benchmark+".lef" ); + cell = DefParser::parse ( benchmark+".def", flags ); + + UpdateSession::close (); +#else + cerr << "[ERROR] CRL::Iccad04Lefdef::load(): \n" + << " Coriolis2 hasn't been compiled with LEF/DEF support. To enable LEF/DEF\n" + << " support, you may obtain parser/driver from Si2 (www.si2.org) then recompile." + << endl; +#endif + + return cell; + } + + +} // End of CRL namespace. diff --git a/crlcore/src/ccore/ispd04/Ispd04Bookshelf.cpp b/crlcore/src/ccore/ispd04/Ispd04Bookshelf.cpp new file mode 100644 index 00000000..ca0a9f6d --- /dev/null +++ b/crlcore/src/ccore/ispd04/Ispd04Bookshelf.cpp @@ -0,0 +1,227 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | ISPD04 IBM Standard Cell Benchmarks | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./Ispd04Bookshelf.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include "vlsisapd/bookshelf/Exception.h" +#include "vlsisapd/bookshelf/Node.h" +#include "vlsisapd/bookshelf/Pin.h" +#include "vlsisapd/bookshelf/Net.h" +#include "vlsisapd/bookshelf/Circuit.h" +#include "hurricane/Error.h" +#include "hurricane/Warning.h" +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/Net.h" +#include "hurricane/NetExternalComponents.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "hurricane/Cell.h" +#include "hurricane/Library.h" +#include "hurricane/UpdateSession.h" +#include "crlcore/AllianceFramework.h" +#include "crlcore/ToolBox.h" +#include "crlcore/Ispd04Bookshelf.h" + + +namespace { + + using namespace std; + using namespace Hurricane; + using namespace CRL; + + + void addSupplyNets ( Cell* cell ) + { + Net* vss = Net::create ( cell, "vss" ); + vss->setExternal ( true ); + vss->setGlobal ( true ); + vss->setType ( Net::Type::GROUND ); + + Net* vdd = Net::create ( cell, "vdd" ); + vdd->setExternal ( true ); + vdd->setGlobal ( true ); + vdd->setType ( Net::Type::POWER ); + } + + + Cell* toMasterCell ( AllianceFramework* af, Bookshelf::Node* node ) + { + if ( node->getHeight() > 16.0 ) return NULL; + + Technology* technology = DataBase::getDB()->getTechnology(); + Layer* METAL1 = technology->getLayer ( "METAL1" ); + + Cell* master = af->createCell ( node->getName() ); + Box abutmentBox ( DbU::lambda( 0.0 ) + , DbU::lambda( 0.0 ) + , DbU::lambda( node->getWidth()*5.0 ) + , DbU::lambda( 50.0 ) + ); + master->setAbutmentBox ( abutmentBox ); + + addSupplyNets ( master ); + + Segment* segment = Horizontal::create ( master->getNet("vss") + , METAL1 + , abutmentBox.getYMin()+DbU::lambda(3.0) + , DbU::lambda(6.0) + , abutmentBox.getXMin() + , abutmentBox.getXMax() + ); + NetExternalComponents::setExternal ( segment ); + + segment = Horizontal::create ( master->getNet("vdd") + , METAL1 + , abutmentBox.getYMax()-DbU::lambda(3.0) + , DbU::lambda( 6.0) + , abutmentBox.getXMin() + , abutmentBox.getXMax() + ); + NetExternalComponents::setExternal ( segment ); + + map& pins = node->getPins(); + map::iterator ipin = pins.begin(); + + if ( node->getWidth() < (double)pins.size() ) + throw Error("Ispd04::load(): Node <%s> has only %.1f pitchs, cannot hold %zd terminals." + ,node->getName().c_str(),node->getWidth(),pins.size()); + + DbU::Unit pinXMin = abutmentBox.getXMin() + DbU::lambda(5.0); + DbU::Unit pinXMax = abutmentBox.getXMax() - ((node->getWidth() > (double)pins.size()) ? DbU::lambda(5.0) : 0); + DbU::Unit pinX; + + for ( size_t pinnb=0 ; ipin != pins.end() ; ++ipin, ++pinnb ) { + Net* net = Net::create ( master, (*ipin).second->getNet()->getName() ); + net->setExternal ( true ); + + if ( pinnb % 2 ) { + pinX = pinXMax; + pinXMax -= DbU::lambda(5.0); + } else { + pinX = pinXMin; + pinXMin += DbU::lambda(5.0); + } + + segment = Vertical::create ( net + , METAL1 + , pinX + , DbU::lambda(1.0) + , abutmentBox.getYMin() + DbU::lambda(10.0) + , abutmentBox.getYMax() - DbU::lambda(10.0) + ); + NetExternalComponents::setExternal ( segment ); + } + + return master; + } + + +} // End of anonymous namespace. + + +namespace CRL { + + using std::string; + using std::map; + using std::auto_ptr; + using Hurricane::Library; + using Hurricane::Transformation; + using Hurricane::UpdateSession; + + + Cell* Ispd04::load ( string benchmark ) + { + AllianceFramework* af = AllianceFramework::get (); + + UpdateSession::open (); + + auto_ptr circuit ( Bookshelf::Circuit::parse(benchmark) ); + + Cell* cell = af->createCell ( benchmark ); + + addSupplyNets ( cell ); + + vector& nets = circuit->getNets (); + vector::iterator inet = nets.begin(); + for ( ; inet != nets.end() ; ++inet ) { + Net::create ( cell, (*inet)->getName() ); + } + + map& nodes = circuit->getNodes(); + map::iterator inode = nodes.begin(); + + Box abutmentBox; + + for ( ; inode != nodes.end() ; ++inode ) { + Bookshelf::Node* node = (*inode).second; + + if ( node->isTerminal () ) continue; + Cell* master = toMasterCell ( af, node ); + + if ( master == NULL ) { + cerr << Warning("Skipping megacell <%s>.",node->getName().c_str()) << endl; + continue; + } + + Instance* instance = Instance::create ( cell, node->getName(), master ); + + map& pins = node->getPins(); + map::iterator ipin = pins.begin(); + + for ( size_t pinnb=0 ; ipin != pins.end() ; ++ipin, ++pinnb ) { + Name netName ( (*ipin).second->getNet()->getName()); + Net* masterNet = master->getNet ( netName ); + instance->getPlug ( masterNet )->setNet ( cell->getNet(netName) ); + + DbU::Unit x = DbU::lambda( node->getX() * 5.0); + DbU::Unit y = DbU::lambda((node->getY()/16.0) * 50.0); + + if ( node->getOrientation() != Bookshelf::Orientation::N ) { + cerr << Warning("Skipping cell <%s>, unsupported orientation.",node->getName().c_str()) << endl; + continue; + } + + Box masterABox = master->getAbutmentBox(); + Transformation::Orientation orientation + = ( (int)(node->getY())%32 ) ? Transformation::Orientation::MY + : Transformation::Orientation::ID; + //Transformation::Orientation orientation = Transformation::Orientation::ID; + Transformation instanceTransformation = getTransformation(masterABox, x, y, orientation); + + instance->setTransformation ( instanceTransformation ); + instance->setPlacementStatus ( Instance::PlacementStatus::PLACED ); + + abutmentBox.merge ( instance->getAbutmentBox() ); + } + } + cell->setAbutmentBox ( abutmentBox ); + + UpdateSession::close (); + + return cell; + } + + +} // End of CRL namespace. diff --git a/crlcore/src/ccore/lefdef/DefExport.cpp b/crlcore/src/ccore/lefdef/DefExport.cpp new file mode 100644 index 00000000..898e2f1f --- /dev/null +++ b/crlcore/src/ccore/lefdef/DefExport.cpp @@ -0,0 +1,634 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | C a d e n c e D E F E x p o r t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./crlcore/DefExport.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#if HAVE_LEFDEF +# include "lefwWriter.hpp" +# include "defwWriter.hpp" +# include "defwWriterCalls.hpp" +#endif +#include "hurricane/Error.h" +#include "hurricane/Warning.h" +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/Net.h" +#include "hurricane/NetExternalComponents.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "hurricane/Cell.h" +#include "hurricane/Library.h" +#include "hurricane/UpdateSession.h" +#include "crlcore/Utilities.h" +#include "crlcore/ToolBox.h" +#include "crlcore/RoutingGauge.h" +#include "crlcore/RoutingLayerGauge.h" +#include "crlcore/AllianceFramework.h" +#include "crlcore/LefExport.h" +#include "crlcore/DefExport.h" + + +#if HAVE_LEFDEF + +namespace { + + using namespace std; + using namespace Hurricane; + using namespace CRL; + + +#define CHECK_STATUS_CBK(status) if ((status) != 0) return driver->checkStatus(status); +#define CHECK_STATUS_DRV(status) if ((status) != 0) return checkStatus(status); +#define RETURN_CHECK_STATUS_CBK(status) return driver->checkStatus(status); +#define RETURN_CHECK_STATUS_DRV(status) return checkStatus(status); + + + class DefDriver { + public: + static void drive ( Cell* cell, unsigned int flags ); + static int getUnits (); + static int toDefUnits ( DbU::Unit ); + static DbU::Unit getSliceHeight (); + static DbU::Unit getPitchWidth (); + ~DefDriver (); + int write (); + private: + DefDriver ( Cell*, const string& designName, FILE*, unsigned int flags ); + inline Cell* getCell (); + inline const string& getDesignName () const; + inline unsigned int getFlags () const; + inline int getStatus () const; + int checkStatus ( int status ); + private: + static int _designCbk ( defwCallbackType_e, defiUserData ); + static int _designEndCbk ( defwCallbackType_e, defiUserData ); + static int _historyCbk ( defwCallbackType_e, defiUserData ); + static int _versionCbk ( defwCallbackType_e, defiUserData ); + static int _dividerCbk ( defwCallbackType_e, defiUserData ); + static int _busBitCbk ( defwCallbackType_e, defiUserData ); + static int _unitsCbk ( defwCallbackType_e, defiUserData ); + static int _technologyCbk ( defwCallbackType_e, defiUserData ); + static int _dieAreaCbk ( defwCallbackType_e, defiUserData ); + static int _gcellGridCbk ( defwCallbackType_e, defiUserData ); + static int _rowCbk ( defwCallbackType_e, defiUserData ); + static int _trackCbk ( defwCallbackType_e, defiUserData ); + static int _viaCbk ( defwCallbackType_e, defiUserData ); + static int _pinCbk ( defwCallbackType_e, defiUserData ); + static int _pinPropCbk ( defwCallbackType_e, defiUserData ); + static int _componentCbk ( defwCallbackType_e, defiUserData ); + static int _netCbk ( defwCallbackType_e, defiUserData ); + static int _snetCbk ( defwCallbackType_e, defiUserData ); + static int _extensionCbk ( defwCallbackType_e, defiUserData ); + static int _groupCbk ( defwCallbackType_e, defiUserData ); + static int _propDefCbk ( defwCallbackType_e, defiUserData ); + static int _regionCbk ( defwCallbackType_e, defiUserData ); + static int _scanchainCbk ( defwCallbackType_e, defiUserData ); + private: + static int _units; + static DbU::Unit _sliceHeight; + static DbU::Unit _pitchWidth; + Cell* _cell; + string _designName; + FILE* _defStream; + unsigned int _flags; + int _status; + }; + + + int DefDriver::_units = 100; + + + int DefDriver::getUnits () { return _units; } + int DefDriver::toDefUnits ( DbU::Unit u ) { return (int)round(DbU::getLambda(u)*getUnits()); } + DbU::Unit DefDriver::getSliceHeight () { return _sliceHeight; } + DbU::Unit DefDriver::getPitchWidth () { return _pitchWidth; }; + inline Cell* DefDriver::getCell () { return _cell; } + inline unsigned int DefDriver::getFlags () const { return _flags; } + inline int DefDriver::getStatus () const { return _status; } + inline const string& DefDriver::getDesignName () const { return _designName; } + + + DefDriver::DefDriver ( Cell* cell, const string& designName, FILE* defStream, unsigned int flags ) + : _cell (cell) + , _designName(designName) + , _defStream (defStream) + , _flags (flags) + , _status (0) + { + _sliceHeight = DbU::lambda(50.0); + _pitchWidth = DbU::lambda( 5.0); + + _status = defwInitCbk ( _defStream ); + if ( _status != 0 ) return; + + defwSetDesignCbk ( _designCbk ); + defwSetDesignEndCbk ( _designEndCbk ); + defwSetHistoryCbk ( _historyCbk ); + defwSetVersionCbk ( _versionCbk ); + defwSetDividerCbk ( _dividerCbk ); + defwSetBusBitCbk ( _busBitCbk ); + defwSetUnitsCbk ( _unitsCbk ); + defwSetTechnologyCbk ( _technologyCbk ); + defwSetDieAreaCbk ( _dieAreaCbk ); + defwSetGcellGridCbk ( _gcellGridCbk ); + defwSetRowCbk ( _rowCbk ); + defwSetTrackCbk ( _trackCbk ); + defwSetViaCbk ( _viaCbk ); + defwSetPinCbk ( _pinCbk ); + defwSetPinPropCbk ( _pinPropCbk ); + defwSetComponentCbk ( _componentCbk ); + defwSetNetCbk ( _netCbk ); + defwSetSNetCbk ( _snetCbk ); + defwSetExtCbk ( _extensionCbk ); + defwSetGroupCbk ( _groupCbk ); + defwSetPropDefCbk ( _propDefCbk ); + defwSetRegionCbk ( _regionCbk ); + defwSetScanchainCbk ( _scanchainCbk ); + } + + + DefDriver::~DefDriver () + { } + + + int DefDriver::write () + { + return checkStatus ( defwWrite(_defStream,_designName.c_str(),(void*)this) ); + } + + + int DefDriver::checkStatus ( int status ) + { + if ( (_status=status) != 0 ) { + defwPrintError ( _status ); + cerr << Error("DefDriver::drive(): Error occured while driving <%s>.",_designName.c_str()) << endl; + } + return _status; + } + + + int DefDriver::_versionCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + + defwNewLine (); + defwAddComment ( "DEF generated by Coriolis2 DEF exporter." ); + defwNewLine (); + + return driver->checkStatus ( defwVersion(5,7) ); + } + + + int DefDriver::_designCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + defwNewLine (); + return driver->checkStatus ( defwDesignName(driver->getDesignName().c_str()) ); + } + + + int DefDriver::_designEndCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + return driver->checkStatus ( defwEnd() ); + } + + + int DefDriver::_historyCbk ( defwCallbackType_e, defiUserData udata ) + { + //DefDriver* driver = (DefDriver*)udata; + return 0; + } + + + int DefDriver::_dividerCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + defwNewLine (); + return driver->checkStatus ( defwDividerChar(".") ); + } + + + int DefDriver::_busBitCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + return driver->checkStatus ( defwBusBitChars("()") ); + } + + + int DefDriver::_unitsCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + defwNewLine (); + return driver->checkStatus ( defwUnits (DefDriver::getUnits()) ); + } + + + int DefDriver::_technologyCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + return driver->checkStatus ( defwTechnology("symbolic") ); + } + + + int DefDriver::_dieAreaCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + + Box abutmentBox ( driver->getCell()->getAbutmentBox() ); + if ( driver->getFlags() & DefExport::ExpandDieArea ) { + abutmentBox.inflate ( DefDriver::getPitchWidth() ); + } + + if ( not abutmentBox.isEmpty()) { + defwNewLine (); + driver->checkStatus + ( defwDieArea ( (int)( toDefUnits(abutmentBox.getXMin()) ) + , (int)( toDefUnits(abutmentBox.getYMin()) ) + , (int)( toDefUnits(abutmentBox.getXMax()) ) + , (int)( toDefUnits(abutmentBox.getYMax()) ) + ) + ); + } + return driver->getStatus(); + } + + + int DefDriver::_gcellGridCbk ( defwCallbackType_e, defiUserData udata ) + { + //DefDriver* driver = (DefDriver*)udata; + + return 0; + } + + + int DefDriver::_rowCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + int status = 0; + Cell* cell = driver->getCell(); + Box abutmentBox ( cell->getAbutmentBox() ); + + int origY = (int)( toDefUnits(abutmentBox.getYMin()) ); + int origX = (int)( toDefUnits(abutmentBox.getXMin()) ); + int stepY = (int)( toDefUnits(DefDriver::getSliceHeight()) ); + int stepX = (int)( toDefUnits(DefDriver::getPitchWidth ()) ); + int rowsNb = abutmentBox.getHeight() / DefDriver::getSliceHeight(); + int columnsNb = abutmentBox.getWidth () / DefDriver::getPitchWidth (); + + ostringstream comment; + comment << rowsNb << " rows of " << columnsNb << " pitchs."; + defwNewLine (); + defwAddComment ( comment.str().c_str() ); + + for ( int row=0 ; row < rowsNb ; ++row ) { + ostringstream rowId; + rowId << "row_" << setw(5) << setfill('0') << row; + + status = driver->checkStatus + ( defwRowStr ( rowId.str().c_str() + , "core" + , origX + , origY + , (row%2) ? "FN" : "N" + , columnsNb + , 1 + , stepX + , stepY + ) + ); + + if ( status != 0 ) break; + + origY += stepY; + } + + return 0; + } + + + int DefDriver::_trackCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + Cell* cell = driver->getCell(); + Box abutmentBox ( cell->getAbutmentBox() ); + + const vector& rg + = AllianceFramework::get()->getRoutingGauge("sxlib")->getLayerGauges(); + + int status = 0; + + const char* layerName[1]; + for ( size_t ilayer=0 ; ilayergetLayer()->getName() ); + layerName[0] = name.c_str(); + + const char* master; // i.e. direction. + int doCount; + int doStart; + int doStep = toDefUnits ( rg[ilayer]->getPitch() ); + + if ( rg[ilayer]->getDirection() == Constant::Horizontal ) { + master = "X"; + doStart = toDefUnits ( abutmentBox.getYMin() + rg[ilayer]->getOffset() ); + doCount = toDefUnits ( abutmentBox.getHeight() ) / doStep; + } else { + master = "Y"; + doStart = toDefUnits ( abutmentBox.getXMin() + rg[ilayer]->getOffset() ); + doCount = toDefUnits ( abutmentBox.getWidth() ) / doStep; + } + + status = defwTracks ( master, doStart, doCount, doStep, 1, layerName ); + CHECK_STATUS_CBK(status); + } + + RETURN_CHECK_STATUS_CBK(status); + } + + + int DefDriver::_viaCbk ( defwCallbackType_e, defiUserData udata ) + { + //DefDriver* driver = (DefDriver*)udata; + return 0; + } + + + int DefDriver::_pinCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + int status = 0; + Cell* cell = driver->getCell(); + int pinsNb = 0; + + forEach ( Net*, inet, cell->getNets() ) { + if ( (*inet)->isExternal() ) ++pinsNb; + } + + status = defwStartPins ( pinsNb ); + if ( status != 0 ) return driver->checkStatus(status); + + forEach ( Net*, inet, cell->getNets() ) { + if ( not (*inet)->isExternal() ) continue; + + const char* netUse = NULL; + if ( (*inet)->isGround() ) netUse = "GROUND"; + if ( (*inet)->isPower () ) netUse = "POWER"; + if ( (*inet)->isClock () ) netUse = "CLOCK"; + + status = defwPin ( getString((*inet)->getName()).c_str() // pin name. + , getString((*inet)->getName()).c_str() // net name (same). + , (netUse != NULL) ? 1 : 0 // special. + , (netUse != NULL) ? "INPUT" : "INOUT" // direction. + , netUse // use. + , NULL // placement status. + , 0 // status X. + , 0 // status Y. + , -1 // orient. + , NULL // layer. + , 0, 0, 0, 0 // geometry. + ); + if ( status != 0 ) return driver->checkStatus(status); + } + + return driver->checkStatus ( defwEndPins() ); + } + + + int DefDriver::_pinPropCbk ( defwCallbackType_e, defiUserData udata ) + { + //DefDriver* driver = (DefDriver*)udata; + return 0; + } + + + int DefDriver::_componentCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + int status = 0; + Cell* cell = driver->getCell(); + + status = defwNewLine (); + CHECK_STATUS_CBK(status); + + status = defwStartComponents ( cell->getInstances().getSize() ); + CHECK_STATUS_CBK(status); + + forEach ( Instance*, iinstance, cell->getInstances() ) { + status = defwComponent ( getString((*iinstance)->getName()).c_str() + , getString((*iinstance)->getMasterCell()->getName()).c_str() + , 0 // numNetNames (disabled). + , NULL // netNames (disabled). + , NULL // eeq (electrical equivalence). + , NULL // genName. + , NULL // genParameters. + , NULL // source (who has created it). + , 0 // numForeigns. + , NULL // foreigns. + , NULL // foreignsX[]. + , NULL // foreignsY[]. + , NULL // foreignsOrient[]. + , "UNPLACED" // status (placement status). + , 0 // status X (disabled). + , 0 // status Y (disabled). + , 0 // status orientation (disabled). + , 0.0 // weight (disabled). + , NULL // region (disabled). + , 0, 0, 0, 0 // region coordinates. + ); + if ( status != 0 ) return driver->checkStatus(status); + } + + return driver->checkStatus ( defwEndComponents() ); + } + + + int DefDriver::_netCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + int status = 0; + Cell* cell = driver->getCell(); + int netsNb = 0; + + forEach ( Net*, inet, cell->getNets() ) { + if ( (*inet)->isSupply() or (*inet)->isClock() ) continue; + ++netsNb; + } + + status = defwStartNets ( netsNb ); + if ( status != 0 ) return driver->checkStatus(status); + + forEach ( Net*, inet, cell->getNets() ) { + if ( (*inet)->isSupply() or (*inet)->isClock() ) continue; + + status = defwNet ( getString((*inet)->getName()).c_str() ); + if ( status != 0 ) return driver->checkStatus(status); + + forEach ( Plug*, iplug, (*inet)->getPlugs() ) { + status = defwNetConnection ( getString((*iplug)->getInstance ()->getName()).c_str() + , getString((*iplug)->getMasterNet()->getName()).c_str() + , 0 + ); + if ( status != 0 ) return driver->checkStatus(status); + } + + status = defwNetEndOneNet (); + if ( status != 0 ) return driver->checkStatus(status); + } + + return driver->checkStatus ( defwEndNets() ); + } + + + int DefDriver::_snetCbk ( defwCallbackType_e, defiUserData udata ) + { + DefDriver* driver = (DefDriver*)udata; + int status = 0; + Cell* cell = driver->getCell(); + int netsNb = 0; + + forEach ( Net*, inet, cell->getNets() ) { + if ( (*inet)->isSupply() or (*inet)->isClock() ) ++netsNb; + } + + status = defwStartSpecialNets ( netsNb ); + if ( status != 0 ) return driver->checkStatus(status); + + forEach ( Net*, inet, cell->getNets() ) { + const char* netUse = NULL; + if ( (*inet)->isGround() ) netUse = "GROUND"; + if ( (*inet)->isPower () ) netUse = "POWER"; + if ( (*inet)->isClock () ) netUse = "CLOCK"; + if ( netUse == NULL ) continue; + + status = defwSpecialNet ( getString((*inet)->getName()).c_str() ); + if ( status != 0 ) return driver->checkStatus(status); + + status = defwSpecialNetConnection ( "*" + , getString((*inet)->getName()).c_str() + , 0 + ); + if ( status != 0 ) return driver->checkStatus(status); + + status = defwSpecialNetUse ( netUse ); + if ( status != 0 ) return driver->checkStatus(status); + + status = defwSpecialNetEndOneNet (); + if ( status != 0 ) return driver->checkStatus(status); + } + + return driver->checkStatus ( defwEndSpecialNets() ); + } + + + int DefDriver::_extensionCbk ( defwCallbackType_e, defiUserData udata ) + { + //DefDriver* driver = (DefDriver*)udata; + return 0; + } + + + int DefDriver::_groupCbk ( defwCallbackType_e, defiUserData udata ) + { + //DefDriver* driver = (DefDriver*)udata; + return 0; + } + + + int DefDriver::_propDefCbk ( defwCallbackType_e, defiUserData udata ) + { + //DefDriver* driver = (DefDriver*)udata; + return 0; + } + + + int DefDriver::_regionCbk ( defwCallbackType_e, defiUserData udata ) + { + //DefDriver* driver = (DefDriver*)udata; + return 0; + } + + + int DefDriver::_scanchainCbk ( defwCallbackType_e, defiUserData udata ) + { + //DefDriver* driver = (DefDriver*)udata; + return 0; + } + + + void DefDriver::drive ( Cell* cell, unsigned int flags ) + { + FILE* defStream = NULL; + try { + string designName = getString(cell->getName()) + "export"; + string path = "./" + designName + ".def"; + + cmess1 << " o Export DEF: <" << path << ">" << endl; + + defStream = fopen ( path.c_str(), "w" ); + if ( defStream == NULL ) + throw Error("DefDriver::drive(): Cannot open <%s>.",path.c_str()); + + auto_ptr driver ( new DefDriver(cell,designName,defStream,flags) ); + driver->write (); + } + catch ( ... ) { + if ( defStream != NULL ) fclose ( defStream ); + + throw; + } + fclose ( defStream ); + } + + +} // End of anonymous namespace. + +#endif // HAVE_LEFDEF. + + +namespace CRL { + + using std::cerr; + using std::endl; + using std::string; + using Hurricane::Library; + using Hurricane::Transformation; + using Hurricane::UpdateSession; + + + void DefExport::drive ( Cell* cell, unsigned int flags ) + { +#if HAVE_LEFDEF + DefDriver::drive ( cell, flags ); + + if ( flags & WithLEF ) LefExport::drive ( cell, LefExport::WithTechnology ); +#else + cerr << "[ERROR] CRL::DefExport::drive(): \n" + << " Coriolis2 hasn't been compiled with LEF/DEF support. To enable LEF/DEF\n" + << " support, you may obtain parser/driver from Si2 (www.si2.org) then recompile." + << endl; +#endif + } + + +} // End of CRL namespace. diff --git a/crlcore/src/ccore/lefdef/DefImport.cpp b/crlcore/src/ccore/lefdef/DefImport.cpp new file mode 100644 index 00000000..3da01b6c --- /dev/null +++ b/crlcore/src/ccore/lefdef/DefImport.cpp @@ -0,0 +1,457 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | C a d e n c e D E F I m p o r t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./DefImport.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include +#include +#if HAVE_LEFDEF +# include "lefrReader.hpp" +# include "defrReader.hpp" +#endif +#include "hurricane/Error.h" +#include "hurricane/Warning.h" +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/Net.h" +#include "hurricane/NetExternalComponents.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "hurricane/Cell.h" +#include "hurricane/Library.h" +#include "hurricane/UpdateSession.h" +#include "crlcore/Utilities.h" +#include "crlcore/ToolBox.h" +#include "crlcore/AllianceFramework.h" +#include "crlcore/DefImport.h" + + +#if HAVE_LEFDEF + +namespace { + + using namespace std; + using namespace Hurricane; + using namespace CRL; + + + void addSupplyNets ( Cell* cell ) + { + Net* vss = Net::create ( cell, "vss" ); + vss->setExternal ( true ); + vss->setGlobal ( true ); + vss->setType ( Net::Type::GROUND ); + + Net* vdd = Net::create ( cell, "vdd" ); + vdd->setExternal ( true ); + vdd->setGlobal ( true ); + vdd->setType ( Net::Type::POWER ); + } + + + class DefParser { + public: + static AllianceFramework* getFramework (); + static DbU::Unit fromDefUnits ( int ); + static Transformation::Orientation + fromDefOrientation ( int orient ); + static Transformation getTransformation ( const Box& + , const DbU::Unit x + , const DbU::Unit y + , const Transformation::Orientation + ); + static Cell* parse ( string file, unsigned int flags ); + DefParser ( string& file, AllianceLibrary*, unsigned int flags ); + ~DefParser (); + inline bool hasErrors (); + inline unsigned int getFlags () const; + inline AllianceLibrary* getLibrary (); + inline Cell* getCell (); + inline size_t getPitchs () const; + inline size_t getSlices () const; + inline const Box& getFitOnCellsDieArea () const; + Net* lookupNet ( const string& ); + inline vector& getErrors (); + inline void pushError ( const string& ); + int flushErrors (); + inline void clearErrors (); + inline void setPitchs ( size_t ); + inline void setSlices ( size_t ); + void addNetLookup ( const string& netName, Net* ); + inline void mergeToFitOnCellsDieArea ( const Box& ); + private: + static int _designEndCbk ( defrCallbackType_e, void* , defiUserData ); + static int _dieAreaCbk ( defrCallbackType_e, defiBox* , defiUserData ); + static int _pinCbk ( defrCallbackType_e, defiPin* , defiUserData ); + static int _componentCbk ( defrCallbackType_e, defiComponent*, defiUserData ); + static int _componentEndCbk ( defrCallbackType_e, void* , defiUserData ); + static int _netCbk ( defrCallbackType_e, defiNet* , defiUserData ); + Cell* _createCell ( const char* name ); + private: + static double _defUnits; + static AllianceFramework* _framework; + string _file; + unsigned int _flags; + AllianceLibrary* _library; + Cell* _cell; + size_t _pitchs; + size_t _slices; + Box _fitOnCellsDieArea; + map _netsLookup; + vector _errors; + }; + + + double DefParser::_defUnits = 0.01; + AllianceFramework* DefParser::_framework = NULL; + + + DefParser::DefParser ( string& file, AllianceLibrary* library, unsigned int flags ) + : _file (file) + , _flags (flags) + , _library (library) + , _cell (NULL) + , _pitchs (0) + , _slices (0) + , _fitOnCellsDieArea() + , _netsLookup () + , _errors () + { + defrInit (); + defrSetDesignEndCbk ( _designEndCbk ); + defrSetDieAreaCbk ( _dieAreaCbk ); + defrSetPinCbk ( _pinCbk ); + defrSetComponentCbk ( _componentCbk ); + defrSetComponentEndCbk ( _componentEndCbk ); + defrSetNetCbk ( _netCbk ); + defrSetNetEndCbk ( _componentEndCbk ); + } + + + DefParser::~DefParser () + { + defrReset (); + } + + + AllianceFramework* DefParser::getFramework () { return _framework; } + inline DbU::Unit DefParser::fromDefUnits ( int u ) { return DbU::lambda(_defUnits*(double)u); } + inline bool DefParser::hasErrors () { return not _errors.empty(); } + inline unsigned int DefParser::getFlags () const { return _flags; } + inline AllianceLibrary* DefParser::getLibrary () { return _library; } + inline Cell* DefParser::getCell () { return _cell; } + inline size_t DefParser::getPitchs () const { return _pitchs; } + inline size_t DefParser::getSlices () const { return _slices; } + inline const Box& DefParser::getFitOnCellsDieArea () const { return _fitOnCellsDieArea; } + inline vector& DefParser::getErrors () { return _errors; } + inline void DefParser::pushError ( const string& error ) { _errors.push_back(error); } + inline void DefParser::clearErrors () { return _errors.clear(); } + inline void DefParser::setPitchs ( size_t pitchs ) { _pitchs=pitchs; } + inline void DefParser::setSlices ( size_t slices ) { _slices=slices; } + inline void DefParser::mergeToFitOnCellsDieArea ( const Box& box ) { _fitOnCellsDieArea.merge(box); } + + + Transformation::Orientation DefParser::fromDefOrientation ( int orient ) + { + // Note : the codes between DEF & Hurricane matches. + // This function is just to be clear. + switch ( orient ) { + default: + case 0: break; // N, default. + case 1: return Transformation::Orientation::R1; // W + case 2: return Transformation::Orientation::R2; // S + case 3: return Transformation::Orientation::R3; // E + case 4: return Transformation::Orientation::MX; // FN + case 5: return Transformation::Orientation::XR; // FW + case 6: return Transformation::Orientation::MY; // FS + case 7: return Transformation::Orientation::YR; // FE + } + return Transformation::Orientation::ID; + } + + + Transformation DefParser::getTransformation ( const Box& abox + , DbU::Unit x + , DbU::Unit y + , const Transformation::Orientation orientation + ) + { + switch (orientation) { + default: + case Transformation::Orientation::ID: return Transformation ( x, y, orientation ); + case Transformation::Orientation::R1: return Transformation ( x, y+abox.getWidth(), orientation ); + case Transformation::Orientation::R2: return Transformation ( x+abox.getWidth (), y+abox.getHeight(), orientation ); + case Transformation::Orientation::R3: return Transformation ( x+abox.getHeight(), y, orientation ); + case Transformation::Orientation::MX: return Transformation ( x+abox.getWidth (), y, orientation ); + case Transformation::Orientation::XR: return Transformation ( x+abox.getHeight(), y+abox.getWidth(), orientation ); + case Transformation::Orientation::MY: return Transformation ( x, y+abox.getHeight(), orientation ); + case Transformation::Orientation::YR: return Transformation ( x+abox.getHeight(), y+abox.getWidth(), orientation ); + } + return Transformation (); + } + + + Cell* DefParser::_createCell ( const char* name ) + { + _cell = DefParser::getFramework()->createCell ( name, NULL ); + addSupplyNets ( _cell ); + return _cell; + } + + + int DefParser::flushErrors () + { + int code = (hasErrors()) ? 1 : 0; + + for ( size_t ierror=0 ; ierror < _errors.size() ; ++ierror ) { + string message = "DefImport::load(): " + _errors[ierror]; + cerr << Error(message.c_str(),getString(_cell->getName()).c_str()) << endl; + } + clearErrors (); + + return code; + } + + + Net* DefParser::lookupNet ( const string& netName ) + { + map::iterator imap = _netsLookup.find(netName); + if ( imap == _netsLookup.end() ) return NULL; + + return (*imap).second; + } + + + void DefParser::addNetLookup ( const string& netName, Net* net ) + { + if ( lookupNet(netName) == NULL ) _netsLookup.insert ( make_pair(netName,net) ); + } + + + int DefParser::_designEndCbk ( defrCallbackType_e c, void*, lefiUserData ud ) + { + DefParser* parser = (DefParser*)ud; + + if ( (parser->getFlags() & DefImport::FitAbOnCells) + and not parser->getFitOnCellsDieArea().isEmpty() ) { + parser->getCell()->setAbutmentBox ( parser->getFitOnCellsDieArea() ); + } + + return 0; + } + + + int DefParser::_dieAreaCbk ( defrCallbackType_e c, defiBox* box, lefiUserData ud ) + { + DefParser* parser = (DefParser*)ud; + + parser->getCell()->setAbutmentBox + ( Box ( fromDefUnits(box->xl()) + , fromDefUnits(box->yl()) + , fromDefUnits(box->xh()) + , fromDefUnits(box->yh()) ) ); + + return 0; + } + + + int DefParser::_pinCbk ( defrCallbackType_e c, defiPin* pin, lefiUserData ud ) + { + DefParser* parser = (DefParser*)ud; + + //cout << " - Pin " << pin->pinName() << ":" << pin->netName() << endl; + + Net* hnet = parser->getCell()->getNet ( pin->netName() ); + if ( hnet == NULL ) { + hnet = Net::create ( parser->getCell(), pin->netName() ); + parser->addNetLookup ( pin->netName(), hnet ); + if ( string(pin->netName()).compare(pin->pinName()) != 0 ) + parser->addNetLookup ( pin->pinName(), hnet ); + } + + return 0; + } + + + int DefParser::_componentCbk ( defrCallbackType_e c, defiComponent* component, lefiUserData ud ) + { + DefParser* parser = (DefParser*)ud; + + string componentName = component->name(); + string componentId = component->id(); + + Cell* masterCell = DefParser::getFramework()->getCell ( componentName, Catalog::State::Views ); + if ( masterCell == NULL ) { + ostringstream message; + message << "Unknown model/Cell (LEF MACRO) " << componentName << " in <%s>."; + parser->pushError ( message.str() ); + return 0; + } + + Transformation placement; + Instance::PlacementStatus state ( Instance::PlacementStatus::UNPLACED ); + if ( component->isPlaced() or component->isFixed() ) { + state = (component->isPlaced()) ? Instance::PlacementStatus::PLACED + : Instance::PlacementStatus::FIXED; + + placement = getTransformation ( masterCell->getAbutmentBox() + , fromDefUnits(component->placementX()) + , fromDefUnits(component->placementY()) + , fromDefOrientation ( component->placementOrient() ) + ); + } + + Instance* instance = Instance::create ( parser->getCell() + , componentId + , masterCell + , placement + , state + ); + if ( state != Instance::PlacementStatus::UNPLACED ) { + parser->mergeToFitOnCellsDieArea ( instance->getAbutmentBox() ); + } + + return 0; + } + + + int DefParser::_netCbk ( defrCallbackType_e c, defiNet* net, lefiUserData ud ) + { + static size_t netCount = 0; + + DefParser* parser = (DefParser*)ud; + + //cout << " - Net " << net->name() << endl; + + Net* hnet = parser->lookupNet ( net->name() ); + if ( hnet == NULL ) + hnet = Net::create ( parser->getCell(), net->name() ); + + if (tty::enabled()) { + cmess2 << " " << tty::bold << setw(7) << setfill('0') << ++netCount << ":" << setfill(' ') + << tty::reset << setw(40) << "<" << net->name() << "> " << tty::cr; + cmess2.flush (); + } + + int numConnections = net->numConnections(); + for ( int icon=0 ; iconinstance(icon); + string pinName = net->pin(icon); + + // Connect to an external pin. + if ( instanceName.compare("PIN") == 0 ) continue; + + Instance* instance = parser->getCell()->getInstance ( instanceName ); + if ( instance == NULL ) { + ostringstream message; + message << "Unknown instance (DEF COMPONENT) <" << instanceName << "> in <%s>."; + parser->pushError ( message.str() ); + continue; + } + + Net* masterNet = instance->getMasterCell()->getNet ( pinName ); + if ( masterNet == NULL ) { + ostringstream message; + message << "Unknown PIN <" << pinName << "> in instance <" + << instanceName << "> (LEF MACRO) in <%s>."; + parser->pushError ( message.str() ); + continue; + } + + instance->getPlug(masterNet)->setNet(hnet); + } + + return 0; + } + + + int DefParser::_componentEndCbk ( defrCallbackType_e c, void*, lefiUserData ud ) + { + DefParser* parser = (DefParser*)ud; + return parser->flushErrors (); + } + + + Cell* DefParser::parse ( string file, unsigned int flags ) + { + cmess1 << " o DEF: <" << file << ">" << endl; + + size_t iext = file.rfind ( '.' ); + if ( file.compare(iext,4,".def") != 0 ) + throw Error ("DefImport::load(): DEF files must have \".def\" extension <%s>.",file.c_str()); + + _framework = AllianceFramework::get (); + + size_t islash = file.rfind ( '/' ); + string designName = file.substr ( ((islash == string::npos) ? 0 : islash), file.size()-4 ); + AllianceLibrary* library = _framework->getAllianceLibrary ( (unsigned int)0 ); + auto_ptr parser ( new DefParser(file,library,flags) ); + + FILE* defStream = fopen ( file.c_str(), "r" ); + if ( defStream == NULL ) + throw Error ("DefImport::load(): Cannot open DEF file <%s>.",file.c_str()); + + parser->_createCell ( designName.c_str() ); + defrRead ( defStream, file.c_str(), (defiUserData)parser.get(), 1 ); + + fclose ( defStream ); + + return parser->getCell(); + } + + +} // End of anonymous namespace. + +#endif // HAVE_LEFDEF + + +namespace CRL { + + using std::cerr; + using std::endl; + using std::string; + using Hurricane::UpdateSession; + + + Cell* DefImport::load ( string design, unsigned int flags ) + { + UpdateSession::open (); + + Cell* cell = NULL; +#if HAVE_LEFDEF + cell = DefParser::parse ( design+".def", flags ); +#else + cerr << "[ERROR] CRL::DefImport::load(): \n" + << " Coriolis2 hasn't been compiled with LEF/DEF support. To enable LEF/DEF\n" + << " support, you may obtain parser/driver from Si2 (www.si2.org) then recompile." + << endl; +#endif + + UpdateSession::close (); + + return cell; + } + + +} // End of CRL namespace. diff --git a/crlcore/src/ccore/lefdef/LefExport.cpp b/crlcore/src/ccore/lefdef/LefExport.cpp new file mode 100644 index 00000000..1c254781 --- /dev/null +++ b/crlcore/src/ccore/lefdef/LefExport.cpp @@ -0,0 +1,747 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | C a d e n c e D E F E x p o r t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./crlcore/LefExport.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#ifdef HAVE_LEFDEF +#include "lefwWriter.hpp" +#include "lefwWriterCalls.hpp" +#endif +#include "hurricane/Error.h" +#include "hurricane/Warning.h" +#include "hurricane/DataBase.h" +#include "hurricane/RegularLayer.h" +#include "hurricane/Technology.h" +#include "hurricane/Net.h" +#include "hurricane/NetExternalComponents.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "hurricane/Cell.h" +#include "hurricane/Library.h" +#include "hurricane/UpdateSession.h" +#include "crlcore/Utilities.h" +#include "crlcore/ToolBox.h" +#include "crlcore/RoutingLayerGauge.h" +#include "crlcore/RoutingGauge.h" +#include "crlcore/CellGauge.h" +#include "crlcore/AllianceFramework.h" +#include "crlcore/LefExport.h" + + +#ifdef HAVE_LEFDEF + +namespace { + + using namespace std; + using namespace Hurricane; + using namespace CRL; + + +#define CHECK_STATUS(status) if ((status) != 0) return checkStatus(status); +#define RETURN_CHECK_STATUS(status) return checkStatus(status); + + + class LefDriver { + public: + static void drive ( const set& + , const string& libraryName + , unsigned int flags + ); + static int getUnits (); + static double toLefUnits ( DbU::Unit ); + static DbU::Unit getSliceHeight (); + static DbU::Unit getPitchWidth (); + ~LefDriver (); + int write (); + private: + LefDriver ( const set& + , const string& libraryName + , unsigned int flags + , FILE* + ); + inline unsigned int getFlags () const; + inline const set getCells () const; + inline const string& getLibraryName () const; + inline AllianceFramework* getFramework (); + inline int getStatus () const; + int checkStatus ( int status ); + private: + static int _versionCbk ( lefwCallbackType_e, lefiUserData ); + static int _busBitCharsCbk ( lefwCallbackType_e, lefiUserData ); + static int _clearanceMeasureCbk ( lefwCallbackType_e, lefiUserData ); + static int _dividerCharCbk ( lefwCallbackType_e, lefiUserData ); + static int _unitsCbk ( lefwCallbackType_e, lefiUserData ); + static int _extCbk ( lefwCallbackType_e, lefiUserData ); + static int _propDefCbk ( lefwCallbackType_e, lefiUserData ); + static int _endLibCbk ( lefwCallbackType_e, lefiUserData ); + static int _layerCbk ( lefwCallbackType_e, lefiUserData ); + static int _macroCbk ( lefwCallbackType_e, lefiUserData ); + static int _manufacturingGridCbk ( lefwCallbackType_e, lefiUserData ); + static int _nonDefaultCbk ( lefwCallbackType_e, lefiUserData ); + static int _siteCbk ( lefwCallbackType_e, lefiUserData ); + static int _spacingCbk ( lefwCallbackType_e, lefiUserData ); + static int _useMinSpacingCbk ( lefwCallbackType_e, lefiUserData ); + static int _viaCbk ( lefwCallbackType_e, lefiUserData ); + static int _viaRuleCbk ( lefwCallbackType_e, lefiUserData ); + int _driveRoutingLayer ( RoutingLayerGauge* ); + int _driveCutLayer ( Layer* ); + int _driveMacro ( Cell* ); + private: + static AllianceFramework* _framework; + static int _units; + static DbU::Unit _sliceHeight; + static DbU::Unit _pitchWidth; + unsigned int _flags; + const set _cells; + string _libraryName; + FILE* _lefStream; + int _status; + }; + + + int LefDriver::_units = 100; + AllianceFramework* LefDriver::_framework = NULL; + + + int LefDriver::getUnits () { return _units; } + double LefDriver::toLefUnits ( DbU::Unit u ) { return DbU::getLambda(u)/**getUnits()*/; } + DbU::Unit LefDriver::getSliceHeight () { return _sliceHeight; } + DbU::Unit LefDriver::getPitchWidth () { return _pitchWidth; }; + inline AllianceFramework* LefDriver::getFramework () { return _framework; } + inline unsigned int LefDriver::getFlags () const { return _flags; } + inline const set LefDriver::getCells () const { return _cells; } + inline int LefDriver::getStatus () const { return _status; } + inline const string& LefDriver::getLibraryName () const { return _libraryName; } + + + LefDriver::LefDriver ( const set& cells, const string& libraryName, unsigned int flags, FILE* lefStream ) + : _flags (flags) + , _cells (cells) + , _libraryName(libraryName) + , _lefStream (lefStream) + , _status (0) + { + if ( _framework == NULL ) { + _framework = AllianceFramework::get (); + CellGauge* cg = _framework->getCellGauge("sxlib"); + + _sliceHeight = cg->getSliceHeight (); + _pitchWidth = cg->getPitch (); + } + + _status = lefwInitCbk ( _lefStream ); + if ( _status != 0 ) return; + + lefwSetVersionCbk ( _versionCbk ); + lefwSetBusBitCharsCbk ( _busBitCharsCbk ); + lefwSetDividerCharCbk ( _dividerCharCbk ); + lefwSetSiteCbk ( _siteCbk ); + lefwSetUnitsCbk ( _unitsCbk ); + lefwSetManufacturingGridCbk ( _manufacturingGridCbk ); + lefwSetClearanceMeasureCbk ( _clearanceMeasureCbk ); + lefwSetExtCbk ( _extCbk ); + lefwSetLayerCbk ( _layerCbk ); + lefwSetMacroCbk ( _macroCbk ); + lefwSetPropDefCbk ( _propDefCbk ); + lefwSetSpacingCbk ( _spacingCbk ); + lefwSetUseMinSpacingCbk ( _useMinSpacingCbk ); + lefwSetNonDefaultCbk ( _nonDefaultCbk ); + lefwSetViaCbk ( _viaCbk ); + lefwSetViaRuleCbk ( _viaRuleCbk ); + lefwSetEndLibCbk ( _endLibCbk ); + } + + + LefDriver::~LefDriver () + { } + + + int LefDriver::write () + { + return checkStatus ( lefwWrite(_lefStream,_libraryName.c_str(),(void*)this) ); + } + + + int LefDriver::checkStatus ( int status ) + { + if ( (_status=status) != 0 ) { + lefwPrintError ( _status ); + cerr << Error("LefDriver::drive(): Error occured while driving <%s>.",_libraryName.c_str()) << endl; + } + return _status; + } + + + int LefDriver::_driveRoutingLayer ( RoutingLayerGauge* lg ) + { + if ( lg == NULL ) return 0; + + _status = lefwStartLayerRouting ( getString(lg->getLayer()->getName()).c_str() ); + if ( _status != 0 ) return _status; + + _status = lefwLayerRouting ( (lg->getDirection() == Constant::Horizontal) ? "HORIZONTAL" : "VERTICAL" + , toLefUnits(lg->getWireWidth()) + ); + if ( _status != 0 ) return _status; + + _status = lefwLayerRoutingOffset ( toLefUnits(lg->getOffset()) ); + if ( _status != 0 ) return _status; + + _status = lefwLayerRoutingPitch ( toLefUnits(lg->getPitch()) ); + if ( _status != 0 ) return _status; + + _status = lefwLayerRoutingSpacing ( toLefUnits(lg->getPitch()-lg->getWireWidth()-DbU::lambda(1.0)) ); + if ( _status != 0 ) return _status; + + return _status = lefwEndLayerRouting ( getString(lg->getLayer()->getName()).c_str() ); + } + + + int LefDriver::_driveCutLayer ( Layer* layer ) + { + if ( layer == NULL ) return 0; + + _status = lefwStartLayer ( getString(layer->getName()).c_str(), "CUT" ); + if ( _status != 0 ) return _status; + + _status = lefwLayerWidth ( toLefUnits(DbU::lambda(1.0)) ); + if ( _status != 0 ) return _status; + + return _status = lefwEndLayer ( getString(layer->getName()).c_str() ); + } + + + int LefDriver::_driveMacro ( Cell* cell ) + { + _status = lefwStartMacro ( getString(cell->getName()).c_str() ); + CHECK_STATUS(_status); + + Box abutmentBox ( cell->getAbutmentBox() ); + double pitchWidth = toLefUnits ( LefDriver::getPitchWidth () ); + double sliceHeight = toLefUnits ( LefDriver::getSliceHeight() ); + int slices = (int)floor( abutmentBox.getHeight() / LefDriver::getSliceHeight() ); + int pitchs = (int)floor( abutmentBox.getWidth () / LefDriver::getPitchWidth () ); + _status = lefwMacroClass ( (slices > 1) ? "BLOCK" : "CORE" + , (slices > 1) ? "BLACKBOX" : NULL + ); + CHECK_STATUS(_status); + + double originX = toLefUnits ( abutmentBox.getXMin() ); + double originY = toLefUnits ( abutmentBox.getYMin() ); + if ( (originX != 0.0) or (originY != 0.0) ) + cerr << Warning("Cell <%s> origin is in (%s,%s), shifting to (0,0)." + ,getString(cell->getName()).c_str() + ,DbU::getValueString(abutmentBox.getXMin()).c_str() + ,DbU::getValueString(abutmentBox.getYMin()).c_str() + ) << endl; + _status = lefwMacroOrigin ( 0.0, 0.0 ); + CHECK_STATUS(_status); + + double sizeX = toLefUnits ( abutmentBox.getWidth () ); + double sizeY = toLefUnits ( abutmentBox.getHeight() ); + _status = lefwMacroSize ( sizeX, sizeY ); + CHECK_STATUS(_status); + + _status = lefwMacroSymmetry ( "X Y" ); + CHECK_STATUS(_status); + + _status = lefwMacroSite ( "core" ); + CHECK_STATUS(_status); + + if ( slices > 1 ) { + for ( int islice=0 ; islicegetNets() ) { + Net* net = *inet; + if ( (obstacleNet == NULL) and _framework->isOBSTACLE(net->getName()) ) + obstacleNet = net; + + if ( not net->isExternal() ) continue; + + _status = lefwStartMacroPin ( getString(net->getName()).c_str() ); + CHECK_STATUS(_status); + + _status = lefwMacroPinDirection ( "INPUT" ); + CHECK_STATUS(_status); + + if ( net->isSupply() ) { + _status = lefwMacroPinShape ( "ABUTMENT" ); + CHECK_STATUS(_status); + } + + const char* pinUse = "SIGNAL"; + if ( net->isGround() ) pinUse = "GROUND"; + else if ( net->isPower () ) pinUse = "POWER"; + else if ( net->isClock () ) pinUse = "CLOCK"; + _status = lefwMacroPinUse ( pinUse ); + CHECK_STATUS(_status); + + _status = lefwStartMacroPinPort ( NULL ); + CHECK_STATUS(_status); + + const Layer* layer = NULL; + forEach ( Component*, icomponent, net->getComponents() ) { + if ( not NetExternalComponents::isExternal(*icomponent) ) continue; + + if ( layer != (*icomponent)->getLayer() ) { + layer = (*icomponent)->getLayer(); + _status = lefwMacroPinPortLayer ( getString(layer->getName()).c_str(), 0 ); + CHECK_STATUS(_status); + } + + Box bb ( (*icomponent)->getBoundingBox() ); + _status = lefwMacroPinPortLayerRect ( toLefUnits(bb.getXMin())-originX // xl + , toLefUnits(bb.getYMin())-originY // yl + , toLefUnits(bb.getXMax())-originX // xh + , toLefUnits(bb.getYMax())-originY // yh + , 0 // ITERATE numX + , 0 // ITERATE numY + , 0 // ITERATE spaceX + , 0 // ITERATE spaceY + ); + CHECK_STATUS(_status); + } + + _status = lefwEndMacroPinPort (); + CHECK_STATUS(_status); + + _status = lefwEndMacroPin ( getString(net->getName()).c_str() ); + CHECK_STATUS(_status); + } + +#if 0 + _status = lefwStartMacroObs (); + CHECK_STATUS(_status); + + double supplyHalfWidth = toLefUnits ( DbU::lambda(6.0) ); + double sliceHeight = toLefUnits ( LefDriver::getSliceHeight() ); +#endif + + double METAL1HalfMinDist = toLefUnits ( DbU::lambda(1.0) ); + +#if 0 + _status = lefwMacroObsLayer ( "METAL1", METAL1HalfMinDist ); + CHECK_STATUS(_status); + + _status = lefwMacroObsLayerRect ( METAL1HalfMinDist // xl + , METAL1HalfMinDist + supplyHalfWidth // yl + , sizeX - METAL1HalfMinDist // xh + , sliceHeight - METAL1HalfMinDist - supplyHalfWidth // yh + , 1 // ITERATE columns + , slices // ITERATE rows + , sizeX // ITERATE spaceX + , toLefUnits(LefDriver::getSliceHeight()) // ITERATE spaceY + ); + CHECK_STATUS(_status); +#endif + + if ( obstacleNet != 0 ) { + _status = lefwStartMacroObs (); + CHECK_STATUS(_status); + + const Layer* blockageLayer = NULL; + forEach ( Component*, icomponent, obstacleNet->getComponents() ) { + if ( dynamic_cast(*icomponent) == NULL ) continue; + + if ( blockageLayer != (*icomponent)->getLayer() ) { + blockageLayer = (*icomponent)->getLayer(); + + RegularLayer* routingLayer = NULL; + forEach ( RegularLayer*, ilayer, DataBase::getDB()->getTechnology()->getRegularLayers() ) { + if ( (*ilayer)->getBlockageLayer() == NULL ) continue; + if ( (*ilayer)->getBlockageLayer()->getMask() != blockageLayer->getMask() ) continue; + + routingLayer = *ilayer; + break; + } + + if ( routingLayer != NULL ) { + _status = lefwMacroObsLayer ( getString(routingLayer->getName()).c_str(), METAL1HalfMinDist ); + CHECK_STATUS(_status); + } + } + + Box bb ( (*icomponent)->getBoundingBox() ); + _status = lefwMacroObsLayerRect ( toLefUnits(bb.getXMin())-originX // xl + , toLefUnits(bb.getYMin())-originY // yl + , toLefUnits(bb.getXMax())-originX // xh + , toLefUnits(bb.getYMax())-originY // yh + , 0 // ITERATE numX + , 0 // ITERATE numY + , 0 // ITERATE spaceX + , 0 // ITERATE spaceY + ); + CHECK_STATUS(_status); + } + + _status = lefwEndMacroObs (); + CHECK_STATUS(_status); + } + +#if 0 + _status = lefwEndMacroObs (); + CHECK_STATUS(_status); +#endif + + _status = lefwEndMacro ( getString(cell->getName()).c_str() ); + RETURN_CHECK_STATUS(_status); + } + + + int LefDriver::_versionCbk ( lefwCallbackType_e, lefiUserData udata ) + { + LefDriver* driver = (LefDriver*)udata; + + ostringstream comment; + comment << "For design <" << driver->getLibraryName() << ">."; + + lefwNewLine (); + lefwAddComment ( "LEF generated by Coriolis2 DEF exporter." ); + lefwAddComment ( comment.str().c_str() ); + lefwNewLine (); + + return driver->checkStatus ( lefwVersion(5,7) ); + } + + + int LefDriver::_busBitCharsCbk ( lefwCallbackType_e, lefiUserData udata ) + { + LefDriver* driver = (LefDriver*)udata; + lefwNewLine (); + return driver->checkStatus ( lefwBusBitChars("()") ); + } + + + int LefDriver::_dividerCharCbk ( lefwCallbackType_e, lefiUserData udata ) + { + LefDriver* driver = (LefDriver*)udata; + return driver->checkStatus ( lefwDividerChar(".") ); + } + + + int LefDriver::_unitsCbk ( lefwCallbackType_e, lefiUserData udata ) + { + LefDriver* driver = (LefDriver*)udata; + lefwNewLine (); + + int status = lefwStartUnits (); + if ( status != 0 ) return driver->checkStatus(status); + + status = lefwUnits ( 0 // time. + , 0 // capacitance. + , 0 // resistance. + , 0 // power. + , 0 // current. + , 0 // voltage. + , LefDriver::getUnits() // database. + ); + if ( status != 0 ) return driver->checkStatus(status); + + return driver->checkStatus ( lefwEndUnits() ); + } + + + int LefDriver::_layerCbk ( lefwCallbackType_e, lefiUserData udata ) + { + LefDriver* driver = (LefDriver*)udata; + Technology* technology = DataBase::getDB()->getTechnology(); + const vector& rg + = driver->getFramework()->getRoutingGauge("sxlib")->getLayerGauges(); + + int status = 0; + for ( size_t ilayer=0 ; ilayer 0 ) { + status = driver->_driveCutLayer ( technology->getCutBelow(rg[ilayer]->getLayer()) ); + if ( status != 0 ) return driver->checkStatus(status); + } + + status = driver->_driveRoutingLayer ( rg[ilayer] ); + if ( status != 0 ) return driver->checkStatus(status); + } + + return status; + } + + + int LefDriver::_siteCbk ( lefwCallbackType_e, lefiUserData udata ) + { + LefDriver* driver = (LefDriver*)udata; + int status = lefwSite ( "core" + , "CORE" + , "Y" + , toLefUnits(LefDriver::getPitchWidth ()) + , toLefUnits(LefDriver::getSliceHeight()) + ); + if ( status != 0 ) return driver->checkStatus(status); + + return driver->checkStatus(lefwEndSite("core")); + } + + + int LefDriver::_extCbk ( lefwCallbackType_e, lefiUserData udata ) + { + //LefDriver* driver = (LefDriver*)udata; + return 0; + } + + + int LefDriver::_propDefCbk ( lefwCallbackType_e, lefiUserData udata ) + { + //LefDriver* driver = (LefDriver*)udata; + return 0; + } + + + int LefDriver::_clearanceMeasureCbk ( lefwCallbackType_e, lefiUserData udata ) + { + //LefDriver* driver = (LefDriver*)udata; + return 0; + } + + + int LefDriver::_endLibCbk ( lefwCallbackType_e, lefiUserData udata ) + { + LefDriver* driver = (LefDriver*)udata; + return driver->checkStatus ( lefwEnd() ); + } + + + int LefDriver::_macroCbk ( lefwCallbackType_e, lefiUserData udata ) + { + LefDriver* driver = (LefDriver*)udata; + + const set& cells = driver->getCells (); + set::const_iterator icell = cells.begin(); + for ( ; (icell != cells.end()) and (driver->getStatus() == 0) ; ++icell ) { + driver->_driveMacro ( *icell ); + } + + return driver->getStatus(); + } + + + int LefDriver::_manufacturingGridCbk ( lefwCallbackType_e, lefiUserData udata ) + { +#if 0 + // The driver puts it before UNITS, which seems to displease Cadence Encounter. + // So, as long as it doesn't prevent Encounter to works, disable it. + LefDriver* driver = (LefDriver*)udata; + return driver->checkStatus ( lefwManufacturingGrid ( LefDriver::getUnits()/10.0 ) ); +#else + return 0; +#endif + } + + + int LefDriver::_nonDefaultCbk ( lefwCallbackType_e, lefiUserData udata ) + { + //LefDriver* driver = (LefDriver*)udata; + return 0; + } + + + int LefDriver::_spacingCbk ( lefwCallbackType_e, lefiUserData udata ) + { + //LefDriver* driver = (LefDriver*)udata; + return 0; + } + + + int LefDriver::_useMinSpacingCbk ( lefwCallbackType_e, lefiUserData udata ) + { + //LefDriver* driver = (LefDriver*)udata; + return 0; + } + + + int LefDriver::_viaCbk ( lefwCallbackType_e, lefiUserData udata ) + { + LefDriver* driver = (LefDriver*)udata; + Technology* technology = DataBase::getDB()->getTechnology(); + const vector& rg + = driver->getFramework()->getRoutingGauge("sxlib")->getLayerGauges(); + + int status = 0; + for ( size_t ilayer=1 ; ilayergetLayer(); + const Layer* bottomLayer = topLayer->getMetalBelow(); + const Layer* cutLayer = topLayer->getCutBelow(); + const Layer* viaLayer = technology->getViaBetween ( topLayer, bottomLayer ); + + status = lefwStartVia ( getString(viaLayer->getName()).c_str(), "DEFAULT" ); + if ( status != 0 ) return driver->checkStatus(status); + + // Bottom Layer. + status = lefwViaLayer ( getString(bottomLayer->getName()).c_str() ); + if ( status != 0 ) return driver->checkStatus(status); + + double side = toLefUnits ( (ilayer == 1) ? DbU::lambda(1.0) : DbU::lambda(1.5) ); + status = lefwViaLayerRect ( -side + , -side + , side + , side + ); + if ( status != 0 ) return driver->checkStatus(status); + + // Cut Layer. + status = lefwViaLayer ( getString(cutLayer->getName()).c_str() ); + if ( status != 0 ) return driver->checkStatus(status); + + side = toLefUnits ( DbU::lambda(0.5) ); + status = lefwViaLayerRect ( -side + , -side + , side + , side + ); + if ( status != 0 ) return driver->checkStatus(status); + + // Top Layer. + status = lefwViaLayer ( getString(topLayer->getName()).c_str() ); + if ( status != 0 ) return driver->checkStatus(status); + + side = toLefUnits ( DbU::lambda(1.5) ); + status = lefwViaLayerRect ( -side + , -side + , side + , side + ); + if ( status != 0 ) return driver->checkStatus(status); + + status = lefwEndVia ( getString(viaLayer->getName()).c_str() ); + if ( status != 0 ) return driver->checkStatus(status); + } + + return 0; + return 0; + } + + + int LefDriver::_viaRuleCbk ( lefwCallbackType_e, lefiUserData udata ) + { + //LefDriver* driver = (LefDriver*)udata; + return 0; + } + + + void LefDriver::drive ( const set& cells, const string& libraryName, unsigned int flags ) + { + FILE* lefStream = NULL; + try { + string path = "./" + libraryName + ".lef"; + cmess1 << " o Export LEF: <" << path << ">" << endl; + + lefStream = fopen ( path.c_str(), "w" ); + if ( lefStream == NULL ) + throw Error("LefDriver::drive(): Cannot open <%s>.",path.c_str()); + + auto_ptr driver ( new LefDriver(cells,libraryName,flags,lefStream) ); + driver->write (); + } + catch ( ... ) { + if ( lefStream != NULL ) fclose ( lefStream ); + + throw; + } + fclose ( lefStream ); + } + + +} // End of anonymous namespace. + +#endif // HAVE_LEFDEF. + + +namespace CRL { + + using std::string; + using Hurricane::Library; + using Hurricane::Transformation; + using Hurricane::UpdateSession; + + + void LefExport::drive ( Cell* cell, unsigned int flags ) + { +#if HAVE_LEFDEF + string libraryName = "symbolic"; + set cells; + + if ( cell != NULL ) { + libraryName = getString(cell->getName()) + "export"; + + forEach ( Instance*, iinstance, cell->getInstances() ) { + if ( cells.find((*iinstance)->getMasterCell()) == cells.end()) + cells.insert ( (*iinstance)->getMasterCell() ); + } + } + + LefDriver::drive ( cells, libraryName, flags ); +#else + cerr << "[ERROR] CRL::LefExport::drive(Cell*): \n" + << " Coriolis2 hasn't been compiled with LEF/DEF support. To enable LEF/DEF" + << " support, you may contact Si2 (www.si2.org) then recompile." + << endl; +#endif + } + + + void LefExport::drive ( Library* library, unsigned int flags ) + { +#ifdef HAVE_LEFDEF + string libraryName = "symbolic"; + set cells; + + if ( library != NULL ) { + libraryName = getString(library->getName()); + + forEach ( Cell*, icell, library->getCells() ) { + if ( cells.find(*icell) == cells.end()) + cells.insert ( *icell ); + } + } + + LefDriver::drive ( cells, libraryName, flags ); +#else + cerr << "[ERROR] CRL::LefExport::drive(Library*): \n" + << " Coriolis2 hasn't been compiled with LEF/DEF support. To enable LEF/DEF\n" + << " support, you may obtain parser/driver from Si2 (www.si2.org) then recompile." + << endl; +#endif + } + + +} // End of CRL namespace. diff --git a/crlcore/src/cyclop/CyclopMain.cpp b/crlcore/src/cyclop/CyclopMain.cpp index bb261de6..4a40e493 100644 --- a/crlcore/src/cyclop/CyclopMain.cpp +++ b/crlcore/src/cyclop/CyclopMain.cpp @@ -143,7 +143,7 @@ int main ( int argc, char *argv[] ) dbo_ptr af ( AllianceFramework::create() ); -// Technology* technology = DataBase::getDB()->getTechnology(); + Technology* technology = DataBase::getDB()->getTechnology(); // technology->setWorkingLayer ( "cut0" ); // technology->setWorkingLayer ( "cut1" ); // technology->setWorkingLayer ( "cut2" ); @@ -162,6 +162,11 @@ int main ( int argc, char *argv[] ) // technology->setWorkingLayer ( "VIA45" ); // technology->setWorkingLayer ( "VIA56" ); + Layer* contact = technology->getLayer("CONT_POLY"); + cerr << "CONT_POLY Mask " << contact->getMask() << endl; + cerr << contact->getTop() << " is top of CONT_POLY" << endl; + cerr << contact->getBottom() << " is bottom of CONT_POLY" << endl; + // Layer* metal2 = technology->getLayer("METAL2"); // Layer* above = technology->getLayer("METAL2")->getMetalAbove(); // cerr << above << " is above METAL2" << endl;