* ./crlcore:
- New: In AllianceFramework constructor, now look for an XML configuration file in the current directory (<cwd>/.environment.alliance.xml). - New: DefParser, DefDriver & LefDriver are replaced by DefImport, DefExport and LefExport (resp.). LEF/DEF parser/driver are no longer integrated in among Alliance ones due to too much difference in data organisation. Instead they are build as Import/Export utilities. - New: Iccad04Lefdef import the ICCAD'04 benchmarks into the SxLib format suitable for Knik/Kite. They are derived from the ISPD'98 (ibm01--ibm18) benchmarks. Many corrections are applieds to ensure a more realistic representation. Generate a new library from the LEF file "on the fly". - New: Ispd04Bookshelf import the ISPD'04 benchmarks in SxLib from bookshelf. Thoses benchmarks can be placeds whith fastplace. Unfortunatly fastplace do not manage blocks and reduce them to standard cell which is not usable for detailed placement. Too bad, the parser exists still. Make uses of the new vlsisapd/bookshelf parser. A whole library is generated "on the fly" on the basis of "one node, one Cell" (so we have a bijection between Cell and Instance). The result of this parsing is different from the one of the stand-alone ispd04 binary in the sense it fits the circuit to the SxLib gauge thus changing the routing capacity: from 16 to 20. - Change: In ApDriver, the lookup modify the lookup table for matching Alliance layers against Hurricane ones, "OBSTACLEx" became "BLOCKAGEx". - Change: In default <enviromnent.alliance.xml> adds the name of the blockage net: "^obstacleNet$". Some work over the coherency of the blockage managment remains to be done. - Change: In AllianceFramework, partial rewrite of the get/creation of AllianceLibrary to fit the requirements of the "on the fly" generation from the benchmarks loaders. And correct some bugs by the way. - Change: In Environment, suppress any reference to LEF technology as LEF/ DEF is now used as import/exports. - Bug: In VstDriver, perform only one lookup for global signals among all nets and not for each instance master cell. That was making the driver quadratic! Now it's linear and reasonably fast.
This commit is contained in:
parent
dd405e619f
commit
4426fc4f0c
|
@ -1,4 +1,3 @@
|
||||||
install ( FILES FindCORIOLIS.cmake
|
install ( FILES FindCORIOLIS.cmake
|
||||||
FindOPENACCESS.cmake
|
FindOPENACCESS.cmake
|
||||||
FindLEFDEF.cmake
|
|
||||||
DESTINATION share/cmake/Modules )
|
DESTINATION share/cmake/Modules )
|
||||||
|
|
|
@ -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 )
|
|
|
@ -8,9 +8,6 @@
|
||||||
<real>
|
<real>
|
||||||
<config>${CORIOLIS_TOP}/etc/coriolis2/technology.cmos130.s2r.xml</config>
|
<config>${CORIOLIS_TOP}/etc/coriolis2/technology.cmos130.s2r.xml</config>
|
||||||
</real>
|
</real>
|
||||||
<lef>
|
|
||||||
<config>${CORIOLIS_TOP}/etc/coriolis2/cmos.lef</config>
|
|
||||||
</lef>
|
|
||||||
<display>
|
<display>
|
||||||
<config>${CORIOLIS_TOP}/etc/coriolis2/display.xml</config>
|
<config>${CORIOLIS_TOP}/etc/coriolis2/display.xml</config>
|
||||||
</display>
|
</display>
|
||||||
|
@ -46,5 +43,6 @@
|
||||||
<vdd>vdd</vdd>
|
<vdd>vdd</vdd>
|
||||||
<vss>vss</vss>
|
<vss>vss</vss>
|
||||||
<clock>^do_not_find_ck$</clock>
|
<clock>^do_not_find_ck$</clock>
|
||||||
|
<obstacle>^obstacleNet$</obstacle>
|
||||||
</signals>
|
</signals>
|
||||||
</environment>
|
</environment>
|
||||||
|
|
|
@ -70,10 +70,12 @@
|
||||||
<parameter id="mauka.annealingRowMult" type="percentage" value="5" min="0"/>
|
<parameter id="mauka.annealingRowMult" type="percentage" value="5" min="0"/>
|
||||||
<!-- Katabatic -->
|
<!-- Katabatic -->
|
||||||
<parameter id="katabatic.saturateRatio" type="percentage" value="80"/>
|
<parameter id="katabatic.saturateRatio" type="percentage" value="80"/>
|
||||||
|
<parameter id="katabatic.saturateRp" type="int" value="8"/>
|
||||||
<parameter id="katabatic.globalLengthThreshold" type="int" value="1450"/>
|
<parameter id="katabatic.globalLengthThreshold" type="int" value="1450"/>
|
||||||
<!-- Kite -->
|
<!-- Kite -->
|
||||||
<parameter id="kite.edgeCapacity" type="percentage" value="65" min="0" max="100"/>
|
<parameter id="kite.edgeCapacity" type="percentage" value="65" min="0" max="100"/>
|
||||||
<parameter id="kite.expandStep" type="percentage" value="100" min="0" max="100"/>
|
<parameter id="kite.expandStep" type="percentage" value="100" min="0" max="100"/>
|
||||||
|
<parameter id="kite.globalMinBreak" type="int" value="1450"/>
|
||||||
<parameter id="kite.ripupCost" type="int" value="3" min="0"/>
|
<parameter id="kite.ripupCost" type="int" value="3" min="0"/>
|
||||||
<parameter id="kite.borderRipupLimit" type="int" value="26" min="1"/>
|
<parameter id="kite.borderRipupLimit" type="int" value="26" min="1"/>
|
||||||
<parameter id="kite.strapRipupLimit" type="int" value="16" min="1"/>
|
<parameter id="kite.strapRipupLimit" type="int" value="16" min="1"/>
|
||||||
|
@ -127,19 +129,21 @@
|
||||||
<tab name="kite">
|
<tab name="kite">
|
||||||
<widget type="title" label="Katabatic - Routing Database"/>
|
<widget type="title" label="Katabatic - Routing Database"/>
|
||||||
<widget id="katabatic.saturateRatio" label="Saturate Ratio (%)" column="0"/>
|
<widget id="katabatic.saturateRatio" label="Saturate Ratio (%)" column="0"/>
|
||||||
|
<widget id="katabatic.saturateRp" label="Saturate RoutingPad" column="0"/>
|
||||||
<widget id="katabatic.globalLengthThreshold" label="Global Length Threshold" column="0"/>
|
<widget id="katabatic.globalLengthThreshold" label="Global Length Threshold" column="0"/>
|
||||||
<widget type="rule"/>
|
<widget type="rule"/>
|
||||||
<widget type="title" label="Kite - Detailed Router"/>
|
<widget type="title" label="Kite - Detailed Router"/>
|
||||||
<widget id="kite.edgeCapacity" label="Edge Capacity (%)" column="0"/>
|
<widget id="kite.edgeCapacity" label="Edge Capacity (%)" column="0"/>
|
||||||
<widget id="kite.expandStep" label="Expand Step (%)" column="0"/>
|
<widget id="kite.expandStep" label="Expand Step (%)" column="0"/>
|
||||||
<widget id="kite.eventsLimit" label="Events Limit" column="0"/>
|
<widget id="kite.globalMinBreak" label="Global Length Min Break" column="0"/>
|
||||||
<widget id="kite.ripupCost" label="Ripup Cost" column="1" spinbox="true"/>
|
<widget id="kite.eventsLimit" label="Events Limit" column="0"/>
|
||||||
|
<widget id="kite.ripupCost" label="Ripup Cost" column="1" spinbox="true"/>
|
||||||
<widget type="section" label="Ripup Limits" column="1"/>
|
<widget type="section" label="Ripup Limits" column="1"/>
|
||||||
<widget id="kite.borderRipupLimit" label="Borders" column="1" spinbox="true"/>
|
<widget id="kite.borderRipupLimit" label="Borders" column="1" spinbox="true"/>
|
||||||
<widget id="kite.strapRipupLimit" label="Straps" column="1" spinbox="true"/>
|
<widget id="kite.strapRipupLimit" label="Straps" column="1" spinbox="true"/>
|
||||||
<widget id="kite.localRipupLimit" label="Locals" column="1" spinbox="true"/>
|
<widget id="kite.localRipupLimit" label="Locals" column="1" spinbox="true"/>
|
||||||
<widget id="kite.globalRipupLimit" label="Globals" column="1" spinbox="true"/>
|
<widget id="kite.globalRipupLimit" label="Globals" column="1" spinbox="true"/>
|
||||||
<widget id="kite.longGlobalRipupLimit" label="Long Globals" column="1" spinbox="true"/>
|
<widget id="kite.longGlobalRipupLimit" label="Long Globals" column="1" spinbox="true"/>
|
||||||
<widget type="rule"/>
|
<widget type="rule"/>
|
||||||
</tab>
|
</tab>
|
||||||
<tab name="Stratus1">
|
<tab name="Stratus1">
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
// x-----------------------------------------------------------------x
|
// x-----------------------------------------------------------------x
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
#include "hurricane/Warning.h"
|
#include "hurricane/Warning.h"
|
||||||
#include "hurricane/Technology.h"
|
#include "hurricane/Technology.h"
|
||||||
#include "hurricane/DataBase.h"
|
#include "hurricane/DataBase.h"
|
||||||
|
@ -78,6 +79,11 @@ namespace CRL {
|
||||||
string userEnvironment = Environment::getEnv ( "HOME", "<HomeDirectory>" );
|
string userEnvironment = Environment::getEnv ( "HOME", "<HomeDirectory>" );
|
||||||
_environment.loadFromXml ( userEnvironment+"/.environment.alliance.xml", false );
|
_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() );
|
SymbolicTechnologyParser::load ( db, _environment.getSYMBOLIC_TECHNOLOGY() );
|
||||||
RealTechnologyParser::load ( db, _environment.getREAL_TECHNOLOGY() );
|
RealTechnologyParser::load ( db, _environment.getREAL_TECHNOLOGY() );
|
||||||
GraphicsParser::load ( _environment.getDISPLAY() );
|
GraphicsParser::load ( _environment.getDISPLAY() );
|
||||||
|
@ -85,9 +91,9 @@ namespace CRL {
|
||||||
if ( !_environment.getDisplayStyle().empty() )
|
if ( !_environment.getDisplayStyle().empty() )
|
||||||
Graphics::setStyle ( _environment.getDisplayStyle() );
|
Graphics::setStyle ( _environment.getDisplayStyle() );
|
||||||
|
|
||||||
bool hasCatalog;
|
unsigned int flags = InSearchPath;
|
||||||
SearchPath& LIBRARIES = _environment.getLIBRARIES ();
|
SearchPath& LIBRARIES = _environment.getLIBRARIES ();
|
||||||
Library* rootLibrary = db->getRootLibrary ();
|
Library* rootLibrary = db->getRootLibrary ();
|
||||||
|
|
||||||
cmess2 << " o Creating Alliance Framework root library." << endl;
|
cmess2 << " o Creating Alliance Framework root library." << endl;
|
||||||
if ( !rootLibrary )
|
if ( !rootLibrary )
|
||||||
|
@ -99,15 +105,13 @@ namespace CRL {
|
||||||
|
|
||||||
cmess2 << " o Loading libraries (working first)." << endl;
|
cmess2 << " o Loading libraries (working first)." << endl;
|
||||||
for ( unsigned i=0 ; i<LIBRARIES.getSize() ; i++ ) {
|
for ( unsigned i=0 ; i<LIBRARIES.getSize() ; i++ ) {
|
||||||
Name libraryName = LIBRARIES[i];
|
createLibrary ( LIBRARIES[i], flags );
|
||||||
|
|
||||||
_libraries.push_back ( getAllianceLibrary(libraryName,hasCatalog) );
|
cmess2 << " - \"" << LIBRARIES[i] << "\"";
|
||||||
|
|
||||||
cmess2 << " - \"" << libraryName._getString() << "\"";
|
|
||||||
cmess2.flush();
|
cmess2.flush();
|
||||||
|
|
||||||
if ( hasCatalog ) cmess2 << " [have CATAL]." << endl;
|
if ( flags&HasCatalog ) cmess2 << " [have CATAL]." << endl;
|
||||||
else cmess2 << " [no CATAL]" << endl;
|
else cmess2 << " [no CATAL]" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary: create the SxLib routing gauge.
|
// Temporary: create the SxLib routing gauge.
|
||||||
|
@ -187,6 +191,35 @@ namespace CRL {
|
||||||
, DbU::lambda(2) // Wire width.
|
, DbU::lambda(2) // Wire width.
|
||||||
, DbU::lambda(3) // Via width.
|
, DbU::lambda(3) // Via width.
|
||||||
) );
|
) );
|
||||||
|
|
||||||
|
routingLayer = technology->getLayer("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 );
|
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 );
|
string spath = getString ( path );
|
||||||
size_t slash = spath.rfind ( '/' );
|
size_t slash = spath.rfind ( '/' );
|
||||||
string sname = spath.substr ( (slash!=string::npos)?slash+1:0 );
|
string sname = spath.substr ( (slash!=string::npos)?slash+1:0 );
|
||||||
|
|
||||||
AllianceLibrary* library = new AllianceLibrary ( path, Library::create(getParentLibrary(),sname) );
|
for ( size_t ilib=0 ; ilib<_libraries.size() ; ++ilib ) {
|
||||||
string catalog = spath + "/" + _environment.getCATALOG();
|
if ( _libraries[ilib]->getLibrary()->getName() == sname )
|
||||||
|
return _libraries[ilib];
|
||||||
|
}
|
||||||
|
|
||||||
flag = false;
|
return (flags&CreateLibrary) ? createLibrary ( getString(path), flags ) : NULL;
|
||||||
if ( _catalog.loadFromFile(catalog,library->getLibrary()) ) flag = true;
|
}
|
||||||
|
|
||||||
ParserFormatSlot& parser = _parsers.getParserSlot ( spath, Catalog::State::Physical, _environment );
|
|
||||||
|
|
||||||
if ( !parser.loadByLib() ) return library;
|
AllianceLibrary* AllianceFramework::getAllianceLibrary ( Library* library )
|
||||||
|
{
|
||||||
size_t base = spath.find_last_of ( '/' );
|
for ( size_t ilib=0 ; ilib<_libraries.size() ; ++ilib ) {
|
||||||
if ( base == spath.npos ) return library;
|
if ( _libraries[ilib]->getLibrary() == library ) return _libraries[ilib];
|
||||||
|
}
|
||||||
string file = spath.substr(base+1,spath.size()-base);
|
return NULL;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 ; i<LIBRARIES.getIndex() ; ++i, ++ilib );
|
||||||
|
|
||||||
|
_libraries.insert ( ilib, library );
|
||||||
|
|
||||||
|
string catalog = path + "/" + _environment.getCATALOG();
|
||||||
|
|
||||||
|
if ( _catalog.loadFromFile(catalog,library->getLibrary()) ) 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 );
|
Catalog::State* state = _catalog.getState ( name );
|
||||||
|
|
||||||
// The cell is not in the CATAL : add an entry.
|
// The cell is not in the CATAL : add an entry.
|
||||||
if ( state == NULL ) state = _catalog.getState ( name, true );
|
if ( state == NULL ) state = _catalog.getState ( name, true );
|
||||||
|
|
||||||
|
if ( library == NULL )
|
||||||
|
library = _libraries[0];
|
||||||
|
|
||||||
if ( !state->getCell() ) {
|
if ( !state->getCell() ) {
|
||||||
state->setPhysical ( true );
|
state->setPhysical ( true );
|
||||||
state->setLogical ( true );
|
state->setLogical ( true );
|
||||||
state->setDepth ( 1 );
|
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 ()->put ( CatalogProperty::create(state) );
|
||||||
state->getCell ()->setFlattenLeaf ( false );
|
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());
|
string name = getString(cell->getName());
|
||||||
DriverSlot* driver;
|
DriverSlot* driver;
|
||||||
unsigned int saveMode;
|
unsigned int saveMode = 0;
|
||||||
unsigned int savedViews = 0;
|
unsigned int savedViews = 0;
|
||||||
|
AllianceLibrary* library = getAllianceLibrary ( cell->getLibrary() );
|
||||||
|
|
||||||
for ( int i=0 ; i<2 ; i++ ) {
|
for ( int i=0 ; i<2 ; i++ ) {
|
||||||
// Check is the view is requested for saving or already saved.
|
// Check is the view is requested for saving or already saved.
|
||||||
|
@ -381,6 +496,8 @@ namespace CRL {
|
||||||
driver = & ( _drivers.getDriverSlot ( name, saveMode, _environment ) );
|
driver = & ( _drivers.getDriverSlot ( name, saveMode, _environment ) );
|
||||||
|
|
||||||
// Try to open cell file (file extention is supplied by the parser).
|
// 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;
|
if ( !_writeLocate(name,saveMode,false) ) continue;
|
||||||
|
|
||||||
// Call the driver function.
|
// Call the driver function.
|
||||||
|
@ -473,7 +590,7 @@ namespace CRL {
|
||||||
// Try to open using the library driver.
|
// Try to open using the library driver.
|
||||||
name = file + "." + getString(format.getExtLib());
|
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;
|
if ( LIBRARIES.hasSelected() ) return true;
|
||||||
} else {
|
} else {
|
||||||
if ( !format.getDrivCell() ) return false;
|
if ( !format.getDrivCell() ) return false;
|
||||||
|
@ -481,7 +598,7 @@ namespace CRL {
|
||||||
// Try to open using the cell driver.
|
// Try to open using the cell driver.
|
||||||
name = file + "." + getString(format.getExtCell());
|
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;
|
if ( LIBRARIES.hasSelected() ) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
${CRLCORE_SOURCE_DIR}/src/ccore/properties
|
${CRLCORE_SOURCE_DIR}/src/ccore/properties
|
||||||
${CRLCORE_SOURCE_DIR}/src/ccore/bookshelf
|
${CRLCORE_SOURCE_DIR}/src/ccore/bookshelf
|
||||||
${CRLCORE_SOURCE_DIR}/src/ccore/acmsigda
|
${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/cspice
|
||||||
${CRLCORE_SOURCE_DIR}/src/ccore/lefdef
|
${CRLCORE_SOURCE_DIR}/src/ccore/lefdef
|
||||||
${CRLCORE_SOURCE_DIR}/src/ccore/alliance/ap
|
${CRLCORE_SOURCE_DIR}/src/ccore/alliance/ap
|
||||||
|
@ -52,6 +54,11 @@
|
||||||
crlcore/AllianceLibrary.h
|
crlcore/AllianceLibrary.h
|
||||||
crlcore/ParsersDrivers.h
|
crlcore/ParsersDrivers.h
|
||||||
crlcore/LefDefExtension.h
|
crlcore/LefDefExtension.h
|
||||||
|
crlcore/DefImport.h
|
||||||
|
crlcore/DefExport.h
|
||||||
|
crlcore/LefExport.h
|
||||||
|
crlcore/Iccad04Lefdef.h
|
||||||
|
crlcore/Ispd04Bookshelf.h
|
||||||
crlcore/Ioc.h
|
crlcore/Ioc.h
|
||||||
crlcore/NetExtension.h
|
crlcore/NetExtension.h
|
||||||
crlcore/Measures.h
|
crlcore/Measures.h
|
||||||
|
@ -123,20 +130,28 @@
|
||||||
# liberty/TimingEvent.cpp
|
# liberty/TimingEvent.cpp
|
||||||
# liberty/LuTable.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/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 )
|
if ( LEFDEF_FOUND )
|
||||||
include_directories ( ${LEFDEF_INCLUDE_DIR} )
|
include_directories ( ${LEFDEF_INCLUDE_DIR} )
|
||||||
endif ( LEFDEF_FOUND )
|
endif ( LEFDEF_FOUND )
|
||||||
if ( OA_FOUND )
|
if ( OA_FOUND )
|
||||||
include_directories ( ${OA_INCLUDE_DIR} )
|
include_directories ( ${OA_INCLUDE_DIR} )
|
||||||
endif ( OA_FOUND )
|
endif ( OA_FOUND )
|
||||||
set (openaccess_cpps openaccess/OpenAccessDriver.cpp
|
set (openaccess_cpps openaccess/OpenAccessParser.cpp
|
||||||
openaccess/OpenAccessParser.cpp )
|
openaccess/OpenAccessDriver.cpp
|
||||||
|
)
|
||||||
|
|
||||||
set ( VstParserSourceDir ${CRLCORE_SOURCE_DIR}/src/ccore/alliance/vst )
|
set ( VstParserSourceDir ${CRLCORE_SOURCE_DIR}/src/ccore/alliance/vst )
|
||||||
set ( VstParserBinaryDir ${CRLCORE_BINARY_DIR}/src/ccore/alliance/vst )
|
set ( VstParserBinaryDir ${CRLCORE_BINARY_DIR}/src/ccore/alliance/vst )
|
||||||
|
@ -269,6 +284,8 @@
|
||||||
${liberty_parser_cpps}
|
${liberty_parser_cpps}
|
||||||
${bookshelf_cpps}
|
${bookshelf_cpps}
|
||||||
${acmsigda_parser_cpps}
|
${acmsigda_parser_cpps}
|
||||||
|
${iccad04_cpps}
|
||||||
|
${ispd04_cpps}
|
||||||
${spice_cpps}
|
${spice_cpps}
|
||||||
${lefdef_cpps}
|
${lefdef_cpps}
|
||||||
${openaccess_cpps}
|
${openaccess_cpps}
|
||||||
|
@ -276,6 +293,7 @@
|
||||||
target_link_libraries ( crlcore ${HURRICANE_PYTHON_LIBRARIES}
|
target_link_libraries ( crlcore ${HURRICANE_PYTHON_LIBRARIES}
|
||||||
${HURRICANE_GRAPHICAL_LIBRARIES}
|
${HURRICANE_GRAPHICAL_LIBRARIES}
|
||||||
${HURRICANE_LIBRARIES}
|
${HURRICANE_LIBRARIES}
|
||||||
|
${BOOKSHELF_LIBRARY}
|
||||||
${CONFIGURATION_LIBRARY}
|
${CONFIGURATION_LIBRARY}
|
||||||
${CIF_LIBRARY}
|
${CIF_LIBRARY}
|
||||||
${AGDS_LIBRARY}
|
${AGDS_LIBRARY}
|
||||||
|
|
|
@ -73,7 +73,6 @@ namespace {
|
||||||
, TagsTechnologies
|
, TagsTechnologies
|
||||||
, TagsHurricane
|
, TagsHurricane
|
||||||
, TagsReal
|
, TagsReal
|
||||||
, TagsLEF
|
|
||||||
, TagsDisplay
|
, TagsDisplay
|
||||||
, TagsConfig
|
, TagsConfig
|
||||||
, TagsLibraries
|
, TagsLibraries
|
||||||
|
@ -96,7 +95,6 @@ namespace {
|
||||||
};
|
};
|
||||||
enum State { HurricaneTechnology = 1
|
enum State { HurricaneTechnology = 1
|
||||||
, RealTechnology
|
, RealTechnology
|
||||||
, LEFTechnology
|
|
||||||
, Display
|
, Display
|
||||||
, WorkingLibrary
|
, WorkingLibrary
|
||||||
, SystemLibrary
|
, SystemLibrary
|
||||||
|
@ -124,7 +122,6 @@ namespace {
|
||||||
void parseTechnologies ();
|
void parseTechnologies ();
|
||||||
void parseHurricane ();
|
void parseHurricane ();
|
||||||
void parseReal ();
|
void parseReal ();
|
||||||
void parseLEF ();
|
|
||||||
void parseDisplay ();
|
void parseDisplay ();
|
||||||
void parseDisplayStyle ();
|
void parseDisplayStyle ();
|
||||||
void parseConfig ();
|
void parseConfig ();
|
||||||
|
@ -164,8 +161,6 @@ namespace {
|
||||||
addTagEntry ( TagsHurricane , "config" , (tagParser_t)&XmlEnvironmentParser::parseConfig );
|
addTagEntry ( TagsHurricane , "config" , (tagParser_t)&XmlEnvironmentParser::parseConfig );
|
||||||
addTagEntry ( TagsTechnologies, "real" , (tagParser_t)&XmlEnvironmentParser::parseReal );
|
addTagEntry ( TagsTechnologies, "real" , (tagParser_t)&XmlEnvironmentParser::parseReal );
|
||||||
addTagEntry ( TagsReal , "config" , (tagParser_t)&XmlEnvironmentParser::parseConfig );
|
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 ( TagsTechnologies, "display" , (tagParser_t)&XmlEnvironmentParser::parseDisplay );
|
||||||
addTagEntry ( TagsDisplay , "config" , (tagParser_t)&XmlEnvironmentParser::parseConfig );
|
addTagEntry ( TagsDisplay , "config" , (tagParser_t)&XmlEnvironmentParser::parseConfig );
|
||||||
addTagEntry ( TagsDisplay , "displaystyle", (tagParser_t)&XmlEnvironmentParser::parseDisplayStyle );
|
addTagEntry ( TagsDisplay , "displaystyle", (tagParser_t)&XmlEnvironmentParser::parseDisplayStyle );
|
||||||
|
@ -323,13 +318,6 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XmlEnvironmentParser::parseLEF ()
|
|
||||||
{
|
|
||||||
_state = LEFTechnology;
|
|
||||||
parseTags ( TagsLEF );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void XmlEnvironmentParser::parseDisplay ()
|
void XmlEnvironmentParser::parseDisplay ()
|
||||||
{
|
{
|
||||||
_state = Display;
|
_state = Display;
|
||||||
|
@ -357,7 +345,6 @@ namespace {
|
||||||
expandVariables ( config );
|
expandVariables ( config );
|
||||||
switch ( _state ) {
|
switch ( _state ) {
|
||||||
case HurricaneTechnology: _environment.setSYMBOLIC_TECHNOLOGY ( config.c_str() ); break;
|
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 RealTechnology: _environment.setREAL_TECHNOLOGY ( config.c_str() ); break;
|
||||||
case Display: _environment.setDISPLAY ( config.c_str() ); break;
|
case Display: _environment.setDISPLAY ( config.c_str() ); break;
|
||||||
}
|
}
|
||||||
|
@ -528,7 +515,6 @@ namespace CRL {
|
||||||
, _displayStyle ()
|
, _displayStyle ()
|
||||||
, _SCALE_X (10)
|
, _SCALE_X (10)
|
||||||
, _SYMBOLIC_TECHNOLOGY("")
|
, _SYMBOLIC_TECHNOLOGY("")
|
||||||
, _LEF_TECHNOLOGY ("")
|
|
||||||
, _DISPLAY ("")
|
, _DISPLAY ("")
|
||||||
, _IN_LO ("vst")
|
, _IN_LO ("vst")
|
||||||
, _IN_PH ("ap")
|
, _IN_PH ("ap")
|
||||||
|
@ -644,8 +630,6 @@ namespace CRL {
|
||||||
<< " \"" << _CORIOLIS_TOP << "\"\n"
|
<< " \"" << _CORIOLIS_TOP << "\"\n"
|
||||||
<< " - Symbolic Technology:\n"
|
<< " - Symbolic Technology:\n"
|
||||||
<< " \"" << _SYMBOLIC_TECHNOLOGY << "\"\n"
|
<< " \"" << _SYMBOLIC_TECHNOLOGY << "\"\n"
|
||||||
<< " - LEF Technology:\n"
|
|
||||||
<< " \"" << _LEF_TECHNOLOGY << "\"\n"
|
|
||||||
<< " - Display configuration:\n"
|
<< " - Display configuration:\n"
|
||||||
<< " \"" << _DISPLAY << "\"\n";
|
<< " \"" << _DISPLAY << "\"\n";
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace CRL {
|
||||||
OADriver::OADriver(Cell* cell) : _cell(cell) {}
|
OADriver::OADriver(Cell* cell) : _cell(cell) {}
|
||||||
|
|
||||||
void OADriver::save(const std::string& filePath) {
|
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,
|
OAParser::OAParser(const std::string& cellLibPath,const std::string& cellLibName,
|
||||||
|
|
|
@ -51,19 +51,18 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# include "hurricane/DBo.h"
|
#include "hurricane/DBo.h"
|
||||||
|
|
||||||
# include "crlcore/Utilities.h"
|
#include "crlcore/Utilities.h"
|
||||||
# include "crlcore/Environment.h"
|
#include "crlcore/Environment.h"
|
||||||
# include "crlcore/Catalog.h"
|
#include "crlcore/Catalog.h"
|
||||||
# include "crlcore/ParsersDrivers.h"
|
#include "crlcore/ParsersDrivers.h"
|
||||||
# include "Ap.h"
|
#include "Ap.h"
|
||||||
# include "Vst.h"
|
#include "Vst.h"
|
||||||
# include "Spice.h"
|
#include "Spice.h"
|
||||||
# include "Bookshelf.h"
|
#include "Bookshelf.h"
|
||||||
# include "AcmSigda.h"
|
#include "AcmSigda.h"
|
||||||
# include "LefDef.h"
|
#include "openaccess/OpenAccess.h"
|
||||||
# include "openaccess/OpenAccess.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -214,15 +213,13 @@ namespace CRL {
|
||||||
ParsersMap::ParsersMap (): map<Name,ParserFormatSlot>()
|
ParsersMap::ParsersMap (): map<Name,ParserFormatSlot>()
|
||||||
{
|
{
|
||||||
// Register the Alliance default parsers.
|
// Register the Alliance default parsers.
|
||||||
registerSlot ( "ap" , (CellParser_t*)apParser , "ap" );
|
registerSlot ( "ap" , (CellParser_t*)apParser , "ap" );
|
||||||
registerSlot ( "vst", (CellParser_t*)vstParser , "vst" );
|
registerSlot ( "vst" , (CellParser_t*)vstParser , "vst" );
|
||||||
registerSlot ( "vst", (CellParser_t*)vstParser , "vbe" );
|
registerSlot ( "vst" , (CellParser_t*)vstParser , "vbe" );
|
||||||
registerSlot ( "spi", (CellParser_t*)spiceParser , "spi" );
|
registerSlot ( "spi" , (CellParser_t*)spiceParser , "spi" );
|
||||||
registerSlot ( "def", (CellParser_t*)defParser , "def" );
|
registerSlot ( "oa" , (CellParser_t*)OpenAccess::oaCellParser , "oa" );
|
||||||
registerSlot ( "def", (LibraryParser_t*)lefParser , "lef" );
|
//registerSlot ( "oa" , (LibraryParser_t*)OpenAccess::oaLibParser, "oa" );
|
||||||
registerSlot ( "oa", (CellParser_t*)OpenAccess::oaCellParser , "oa" );
|
registerSlot ( "aux" , (CellParser_t*)bookshelfParser, "aux" );
|
||||||
// registerSlot ( "oa", (LibraryParser_t*)OpenAccess::oaLibParser , "oa" );
|
|
||||||
registerSlot ( "aux", (CellParser_t*)bookshelfParser, "aux" );
|
|
||||||
registerSlot ( "bench", (CellParser_t*)acmSigdaParser , "bench" );
|
registerSlot ( "bench", (CellParser_t*)acmSigdaParser , "bench" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,10 +330,10 @@ namespace CRL {
|
||||||
// Register the Alliance default drivers.
|
// Register the Alliance default drivers.
|
||||||
registerSlot ( "ap" , (CellDriver_t*)apDriver , "ap" );
|
registerSlot ( "ap" , (CellDriver_t*)apDriver , "ap" );
|
||||||
registerSlot ( "vst", (CellDriver_t*)vstDriver , "vst" );
|
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 ( "aux", (CellDriver_t*)bookshelfDriver, "test.aux" );
|
||||||
registerSlot ( "spi", (CellDriver_t*)spiceDriver , "spi" );
|
registerSlot ( "spi", (CellDriver_t*)spiceDriver , "spi" );
|
||||||
registerSlot ( "oa" , (CellDriver_t*)OpenAccess::oaDriver, "oa");
|
//registerSlot ( "oa" , (CellDriver_t*)OpenAccess::oaDriver, "oa");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,42 +26,86 @@
|
||||||
# include "crlcore/SearchPath.h"
|
# include "crlcore/SearchPath.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
} // End of anonymous namespace.
|
||||||
|
|
||||||
|
|
||||||
namespace CRL {
|
namespace CRL {
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
const size_t SearchPath::npos = (size_t)-1;
|
const size_t SearchPath::npos = (size_t)-1;
|
||||||
|
const string SearchPath::_selectFailed = "<File or directory not found>";
|
||||||
|
|
||||||
|
|
||||||
SearchPath::SearchPath ()
|
SearchPath::SearchPath ()
|
||||||
: _paths ()
|
: _paths ()
|
||||||
, _index (npos)
|
, _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<string>::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 )
|
void SearchPath::replace ( const string& path, size_t index )
|
||||||
{
|
{
|
||||||
|
_index = index;
|
||||||
if ( index < _paths.size() )
|
if ( index < _paths.size() )
|
||||||
_paths[index] = path;
|
_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++ ) {
|
for ( size_t ipath=0 ; ipath < _paths.size() ; ++ipath ) {
|
||||||
string path = _paths[i] + "/" + file;
|
if ( _paths[ipath] == path ) {
|
||||||
|
_selected = _paths[ipath];
|
||||||
|
_index = ipath;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fstream filestream ( path.c_str(), mode );
|
_selected = _selectFailed;
|
||||||
if ( filestream.is_open() ) {
|
_index = npos;
|
||||||
filestream.close ();
|
}
|
||||||
_selected = path;
|
|
||||||
|
|
||||||
|
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;
|
return _index = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_selected = "<File not found>";
|
|
||||||
return _index = npos;
|
return _index = npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,12 +95,12 @@ bool toMBKLayer ( const char*& mbkLayer
|
||||||
tableLayer [ "METAL5" ] = "ALU5";
|
tableLayer [ "METAL5" ] = "ALU5";
|
||||||
tableLayer [ "METAL6" ] = "ALU6";
|
tableLayer [ "METAL6" ] = "ALU6";
|
||||||
|
|
||||||
tableLayer [ "OBSTACLE1" ] = "TALU1";
|
tableLayer [ "BLOCKAGE1" ] = "TALU1";
|
||||||
tableLayer [ "OBSTACLE2" ] = "TALU2";
|
tableLayer [ "BLOCKAGE2" ] = "TALU2";
|
||||||
tableLayer [ "OBSTACLE3" ] = "TALU3";
|
tableLayer [ "BLOCKAGE3" ] = "TALU3";
|
||||||
tableLayer [ "OBSTACLE4" ] = "TALU4";
|
tableLayer [ "BLOCKAGE4" ] = "TALU4";
|
||||||
tableLayer [ "OBSTACLE5" ] = "TALU5";
|
tableLayer [ "BLOCKAGE5" ] = "TALU5";
|
||||||
tableLayer [ "OBSTACLE6" ] = "TALU6";
|
tableLayer [ "BLOCKAGE6" ] = "TALU6";
|
||||||
|
|
||||||
tableConnector [ "METAL1" ] = "CALU1";
|
tableConnector [ "METAL1" ] = "CALU1";
|
||||||
tableConnector [ "METAL2" ] = "CALU2";
|
tableConnector [ "METAL2" ] = "CALU2";
|
||||||
|
|
|
@ -50,6 +50,48 @@ namespace {
|
||||||
using namespace CRL;
|
using namespace CRL;
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalNetLookup {
|
||||||
|
public:
|
||||||
|
inline void addLookup ( Net* );
|
||||||
|
inline Net* lookup ( const string& );
|
||||||
|
inline bool isGlobal ( Net* );
|
||||||
|
inline void clear ();
|
||||||
|
private:
|
||||||
|
map<string,Net*> _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<string,Net*>::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) {
|
void FilterPointsInStrings(string& s) {
|
||||||
// Problem in VST... : the . which seems to represent hierachy paths
|
// Problem in VST... : the . which seems to represent hierachy paths
|
||||||
// in ap is not supported...
|
// in ap is not supported...
|
||||||
|
@ -297,18 +339,20 @@ void DumpSignalList(ofstream &ccell, Cell* cell)
|
||||||
{
|
{
|
||||||
StringPtVector netsString;
|
StringPtVector netsString;
|
||||||
NetSet netSet;
|
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);
|
FilterPointsInStrings(*stringName);
|
||||||
netsString.push_back(stringName);
|
netsString.push_back(stringName);
|
||||||
NetSet::iterator nsit = netSet.find(net);
|
NetSet::iterator nsit = netSet.find(*inet);
|
||||||
if (nsit != netSet.end())
|
if (nsit != netSet.end())
|
||||||
{
|
throw Error("two times the same name");
|
||||||
throw Error("two times the same name");
|
netSet.insert(*inet);
|
||||||
}
|
}
|
||||||
netSet.insert(net);
|
if ( (*inet)->isGlobal() ) {
|
||||||
end_for;
|
__globalNets.addLookup ( *inet );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sort(netsString.begin(), netsString.end(), StringSort());
|
sort(netsString.begin(), netsString.end(), StringSort());
|
||||||
|
|
||||||
|
@ -412,7 +456,7 @@ void DumpConnectionList(ofstream &ccell, Instance*instance)
|
||||||
throw Error("Cannot find net named " + *string1);
|
throw Error("Cannot find net named " + *string1);
|
||||||
}
|
}
|
||||||
if (string1OpenPar == string::npos)
|
if (string1OpenPar == string::npos)
|
||||||
{
|
{
|
||||||
Plug* plug = spmit->second;
|
Plug* plug = spmit->second;
|
||||||
string connectedNetName;
|
string connectedNetName;
|
||||||
if (plug->isConnected()) {
|
if (plug->isConnected()) {
|
||||||
|
@ -430,19 +474,21 @@ void DumpConnectionList(ofstream &ccell, Instance*instance)
|
||||||
Net* masterNet = plug->getMasterNet();
|
Net* masterNet = plug->getMasterNet();
|
||||||
if (masterNet->isGlobal()) // connection by name
|
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());
|
connectedNetName = string(masterNet->getName()._getString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
end_for;
|
end_for;
|
||||||
}
|
|
||||||
if (connectedNetName == string())
|
|
||||||
{
|
|
||||||
throw Error("No global net " + masterNet->getName()._getString() + " in cell " + instance->getCell()->getName()._getString());
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
if ( connectedNetName.empty() )
|
||||||
|
throw Error("No global net " + masterNet->getName()._getString() + " in cell " + instance->getCell()->getName()._getString());
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -616,6 +662,8 @@ namespace CRL {
|
||||||
|
|
||||||
void vstDriver ( const string cellPath, Cell *cell, unsigned int &saveState )
|
void vstDriver ( const string cellPath, Cell *cell, unsigned int &saveState )
|
||||||
{
|
{
|
||||||
|
__globalNets.clear ();
|
||||||
|
|
||||||
::std::ofstream ccell ( cellPath.c_str() );
|
::std::ofstream ccell ( cellPath.c_str() );
|
||||||
ccell << "entity " << cell->getName() << " is" << endl;
|
ccell << "entity " << cell->getName() << " is" << endl;
|
||||||
DumpPortList(ccell, cell);
|
DumpPortList(ccell, cell);
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include "crlcore/Environment.h"
|
#include "crlcore/Environment.h"
|
||||||
#include "crlcore/AllianceLibrary.h"
|
#include "crlcore/AllianceLibrary.h"
|
||||||
|
@ -45,6 +46,7 @@ namespace CRL {
|
||||||
class AllianceFramework {
|
class AllianceFramework {
|
||||||
public:
|
public:
|
||||||
enum InstancesCountFlags { Recursive=0x1, IgnoreFeeds=0x2 };
|
enum InstancesCountFlags { Recursive=0x1, IgnoreFeeds=0x2 };
|
||||||
|
enum LibraryFlags { CreateLibrary=0x1, InSearchPath=0x2, HasCatalog=0x4 };
|
||||||
public:
|
public:
|
||||||
// Constructors.
|
// Constructors.
|
||||||
static AllianceFramework* create ();
|
static AllianceFramework* create ();
|
||||||
|
@ -71,8 +73,13 @@ namespace CRL {
|
||||||
inline Catalog* getCatalog ();
|
inline Catalog* getCatalog ();
|
||||||
inline const Name& getParentLibraryName () const;
|
inline const Name& getParentLibraryName () const;
|
||||||
inline Library* getParentLibrary ();
|
inline Library* getParentLibrary ();
|
||||||
Library* getLibrary ( unsigned index );
|
Library* getLibrary ( unsigned int index );
|
||||||
AllianceLibrary* getAllianceLibrary ( const Name& path, bool& flag );
|
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="" );
|
RoutingGauge* getRoutingGauge ( const Name& name="" );
|
||||||
CellGauge* getCellGauge ( const Name& name="" );
|
CellGauge* getCellGauge ( const Name& name="" );
|
||||||
inline const Name getDefaultCGPinLayerName () const;
|
inline const Name getDefaultCGPinLayerName () const;
|
||||||
|
@ -83,11 +90,11 @@ namespace CRL {
|
||||||
Cell* getCell ( const string& name
|
Cell* getCell ( const string& name
|
||||||
, unsigned int mode
|
, unsigned int mode
|
||||||
, unsigned int depth=(unsigned int)-1 );
|
, unsigned int depth=(unsigned int)-1 );
|
||||||
Cell* createCell ( const string& name );
|
Cell* createCell ( const string& name, AllianceLibrary* library=NULL );
|
||||||
void saveCell ( Cell* cell , unsigned int mode );
|
void saveCell ( Cell* , unsigned int mode );
|
||||||
unsigned int loadLibraryCells ( Library* library );
|
unsigned int loadLibraryCells ( Library* );
|
||||||
unsigned int loadLibraryCells ( const Name& name );
|
unsigned int loadLibraryCells ( const Name& );
|
||||||
static size_t getInstancesCount ( Cell* cell, unsigned int flags );
|
static size_t getInstancesCount ( Cell*, unsigned int flags );
|
||||||
|
|
||||||
// Internals - Attributes.
|
// Internals - Attributes.
|
||||||
protected:
|
protected:
|
||||||
|
@ -115,6 +122,7 @@ namespace CRL {
|
||||||
// Internals - Methods.
|
// Internals - Methods.
|
||||||
bool _readLocate ( const string& file, unsigned int mode, bool isLib=false );
|
bool _readLocate ( const string& file, unsigned int mode, bool isLib=false );
|
||||||
bool _writeLocate ( 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 );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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__
|
|
@ -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 <string>
|
||||||
|
|
||||||
|
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__
|
|
@ -53,7 +53,6 @@ namespace CRL {
|
||||||
inline long getSCALE_X () const;
|
inline long getSCALE_X () const;
|
||||||
inline const std::string& getSYMBOLIC_TECHNOLOGY () const;
|
inline const std::string& getSYMBOLIC_TECHNOLOGY () const;
|
||||||
inline const std::string& getREAL_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& getDISPLAY () const;
|
||||||
inline const std::string& getIN_LO () const;
|
inline const std::string& getIN_LO () const;
|
||||||
inline const std::string& getIN_PH () const;
|
inline const std::string& getIN_PH () const;
|
||||||
|
@ -79,7 +78,6 @@ namespace CRL {
|
||||||
inline void setSCALE_X ( long value );
|
inline void setSCALE_X ( long value );
|
||||||
inline void setSYMBOLIC_TECHNOLOGY ( const char* value );
|
inline void setSYMBOLIC_TECHNOLOGY ( const char* value );
|
||||||
inline void setREAL_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 setDISPLAY ( const char* value );
|
||||||
inline void setIN_LO ( const char* value );
|
inline void setIN_LO ( const char* value );
|
||||||
inline void setIN_PH ( const char* value );
|
inline void setIN_PH ( const char* value );
|
||||||
|
@ -102,7 +100,6 @@ namespace CRL {
|
||||||
std::string _displayStyle;
|
std::string _displayStyle;
|
||||||
long _SCALE_X;
|
long _SCALE_X;
|
||||||
std::string _SYMBOLIC_TECHNOLOGY;
|
std::string _SYMBOLIC_TECHNOLOGY;
|
||||||
std::string _LEF_TECHNOLOGY;
|
|
||||||
std::string _REAL_TECHNOLOGY;
|
std::string _REAL_TECHNOLOGY;
|
||||||
std::string _DISPLAY;
|
std::string _DISPLAY;
|
||||||
std::string _IN_LO;
|
std::string _IN_LO;
|
||||||
|
@ -134,7 +131,6 @@ namespace CRL {
|
||||||
inline long Environment::getSCALE_X () const { return _SCALE_X; }
|
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::getSYMBOLIC_TECHNOLOGY () const { return _SYMBOLIC_TECHNOLOGY; }
|
||||||
inline const std::string& Environment::getREAL_TECHNOLOGY () const { return _REAL_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::getDISPLAY () const { return _DISPLAY; }
|
||||||
inline const std::string& Environment::getIN_LO () const { return _IN_LO; }
|
inline const std::string& Environment::getIN_LO () const { return _IN_LO; }
|
||||||
inline const std::string& Environment::getIN_PH () const { return _IN_PH; }
|
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::setSCALE_X ( long value ) { _SCALE_X = value; }
|
||||||
inline void Environment::setSYMBOLIC_TECHNOLOGY ( const char* value ) { _SYMBOLIC_TECHNOLOGY = 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::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::setDISPLAY ( const char* value ) { _DISPLAY = value; }
|
||||||
inline void Environment::setIN_LO ( const char* value ) { _IN_LO = value; }
|
inline void Environment::setIN_LO ( const char* value ) { _IN_LO = value; }
|
||||||
inline void Environment::setIN_PH ( const char* value ) { _IN_PH = value; }
|
inline void Environment::setIN_PH ( const char* value ) { _IN_PH = value; }
|
||||||
|
|
|
@ -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 <string>
|
||||||
|
|
||||||
|
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__
|
|
@ -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 <string>
|
||||||
|
|
||||||
|
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__
|
||||||
|
|
|
@ -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__
|
|
@ -48,24 +48,30 @@ namespace CRL {
|
||||||
public:
|
public:
|
||||||
inline void reset ();
|
inline void reset ();
|
||||||
inline void append ( const std::string& path );
|
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 );
|
void replace ( const std::string& path, size_t index );
|
||||||
size_t locate ( const std::string& file
|
size_t locate ( const std::string& file
|
||||||
, std::ios::openmode mode =std::ios::in
|
, std::ios::openmode mode =std::ios::in
|
||||||
, int first=0
|
, int first=0
|
||||||
, int last =64 );
|
, int last =64 );
|
||||||
|
void select ( const std::string& );
|
||||||
inline size_t getSize () const;
|
inline size_t getSize () const;
|
||||||
inline const std::string& getSelected () const;
|
inline const std::string& getSelected () const;
|
||||||
inline size_t getIndex () const;
|
inline size_t getIndex () const;
|
||||||
bool hasSelected () const;
|
inline bool hasSelected () const;
|
||||||
size_t hasPath ( const std::string& path ) const;
|
size_t hasPath ( const std::string& path ) const;
|
||||||
const std::string& operator[] ( size_t index ) const;
|
const std::string& operator[] ( size_t index ) const;
|
||||||
private:
|
private:
|
||||||
|
static const std::string _selectFailed;
|
||||||
std::vector<std::string> _paths;
|
std::vector<std::string> _paths;
|
||||||
size_t _index;
|
size_t _index;
|
||||||
std::string _selected;
|
std::string _selected;
|
||||||
private:
|
private:
|
||||||
SearchPath ( const SearchPath& );
|
SearchPath ( const SearchPath& );
|
||||||
|
bool _canOpen ( const std::string& directory
|
||||||
|
, const std::string& file
|
||||||
|
, std::ios::openmode mode
|
||||||
|
);
|
||||||
public:
|
public:
|
||||||
inline std::string _getTypeName () const;
|
inline std::string _getTypeName () const;
|
||||||
std::string _getString () const;
|
std::string _getString () const;
|
||||||
|
@ -75,7 +81,6 @@ namespace CRL {
|
||||||
|
|
||||||
// Inline Functions.
|
// Inline Functions.
|
||||||
inline void SearchPath::reset () { _paths.resize(1); }
|
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 void SearchPath::append ( const std::string& path ) { _paths.push_back(path); }
|
||||||
inline size_t SearchPath::getSize () const { return _paths.size(); }
|
inline size_t SearchPath::getSize () const { return _paths.size(); }
|
||||||
inline const std::string& SearchPath::getSelected () const { return _selected; }
|
inline const std::string& SearchPath::getSelected () const { return _selected; }
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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 <memory>
|
||||||
|
#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<size_t,Bookshelf::Pin*>& pins = node->getPins();
|
||||||
|
map<size_t,Bookshelf::Pin*>::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<Bookshelf::Circuit> circuit ( Bookshelf::Circuit::parse(benchmark) );
|
||||||
|
|
||||||
|
Cell* cell = af->createCell ( benchmark );
|
||||||
|
|
||||||
|
addSupplyNets ( cell );
|
||||||
|
|
||||||
|
vector<Bookshelf::Net*>& nets = circuit->getNets ();
|
||||||
|
vector<Bookshelf::Net*>::iterator inet = nets.begin();
|
||||||
|
for ( ; inet != nets.end() ; ++inet ) {
|
||||||
|
Net::create ( cell, (*inet)->getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
map<string,Bookshelf::Node*>& nodes = circuit->getNodes();
|
||||||
|
map<string,Bookshelf::Node*>::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<size_t,Bookshelf::Pin*>& pins = node->getPins();
|
||||||
|
map<size_t,Bookshelf::Pin*>::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.
|
|
@ -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 <memory>
|
||||||
|
#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<RoutingLayerGauge*>& rg
|
||||||
|
= AllianceFramework::get()->getRoutingGauge("sxlib")->getLayerGauges();
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
const char* layerName[1];
|
||||||
|
for ( size_t ilayer=0 ; ilayer<rg.size() ; ++ilayer ) {
|
||||||
|
string name = getString ( rg[ilayer]->getLayer()->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<DefDriver> 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.
|
|
@ -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 <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#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<string>& 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<string,Net*> _netsLookup;
|
||||||
|
vector<string> _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<string>& 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<string,Net*>::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 ; icon<numConnections ; ++icon ) {
|
||||||
|
string instanceName = net->instance(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<DefParser> 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.
|
|
@ -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 <memory>
|
||||||
|
#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<Cell*>&
|
||||||
|
, 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<Cell*>&
|
||||||
|
, const string& libraryName
|
||||||
|
, unsigned int flags
|
||||||
|
, FILE*
|
||||||
|
);
|
||||||
|
inline unsigned int getFlags () const;
|
||||||
|
inline const set<Cell*> 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<Cell*> _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<Cell*> LefDriver::getCells () const { return _cells; }
|
||||||
|
inline int LefDriver::getStatus () const { return _status; }
|
||||||
|
inline const string& LefDriver::getLibraryName () const { return _libraryName; }
|
||||||
|
|
||||||
|
|
||||||
|
LefDriver::LefDriver ( const set<Cell*>& 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 ; islice<slices ; ++islice ) {
|
||||||
|
_status = lefwMacroSitePatternStr ( "core" // site name.
|
||||||
|
, originX // X origin.
|
||||||
|
, originY + sliceHeight*islice // Y origin.
|
||||||
|
, (islice % 2) ? "FS" : "N" // orientation.
|
||||||
|
, pitchs // num X.
|
||||||
|
, 1 // num Y.
|
||||||
|
, pitchWidth // space X (STEP X).
|
||||||
|
, sliceHeight // space Y (STEP Y).
|
||||||
|
);
|
||||||
|
CHECK_STATUS(_status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Net* obstacleNet = NULL;
|
||||||
|
|
||||||
|
forEach ( Net*, inet, cell->getNets() ) {
|
||||||
|
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<Segment*>(*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<RoutingLayerGauge*>& rg
|
||||||
|
= driver->getFramework()->getRoutingGauge("sxlib")->getLayerGauges();
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
for ( size_t ilayer=0 ; ilayer<rg.size() ; ++ilayer ) {
|
||||||
|
if ( 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<Cell*>& cells = driver->getCells ();
|
||||||
|
set<Cell*>::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<RoutingLayerGauge*>& rg
|
||||||
|
= driver->getFramework()->getRoutingGauge("sxlib")->getLayerGauges();
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
for ( size_t ilayer=1 ; ilayer<rg.size() ; ++ilayer ) {
|
||||||
|
const Layer* topLayer = rg[ilayer]->getLayer();
|
||||||
|
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<Cell*>& 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<LefDriver> 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<Cell*> 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<Cell*> 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.
|
|
@ -143,7 +143,7 @@ int main ( int argc, char *argv[] )
|
||||||
|
|
||||||
dbo_ptr<AllianceFramework> af ( AllianceFramework::create() );
|
dbo_ptr<AllianceFramework> af ( AllianceFramework::create() );
|
||||||
|
|
||||||
// Technology* technology = DataBase::getDB()->getTechnology();
|
Technology* technology = DataBase::getDB()->getTechnology();
|
||||||
// technology->setWorkingLayer ( "cut0" );
|
// technology->setWorkingLayer ( "cut0" );
|
||||||
// technology->setWorkingLayer ( "cut1" );
|
// technology->setWorkingLayer ( "cut1" );
|
||||||
// technology->setWorkingLayer ( "cut2" );
|
// technology->setWorkingLayer ( "cut2" );
|
||||||
|
@ -162,6 +162,11 @@ int main ( int argc, char *argv[] )
|
||||||
// technology->setWorkingLayer ( "VIA45" );
|
// technology->setWorkingLayer ( "VIA45" );
|
||||||
// technology->setWorkingLayer ( "VIA56" );
|
// 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* metal2 = technology->getLayer("METAL2");
|
||||||
// Layer* above = technology->getLayer("METAL2")->getMetalAbove();
|
// Layer* above = technology->getLayer("METAL2")->getMetalAbove();
|
||||||
// cerr << above << " is above METAL2" << endl;
|
// cerr << above << " is above METAL2" << endl;
|
||||||
|
|
Loading…
Reference in New Issue