* ./hurricane/src/hviewer,

./coriolis/src/crlcore,
     ./coriolis/src/knik,
     ./coriolis/src/katabatic,
     ./coriolis/src/kite,
     ./coriolis/src/equinox,
     ./coriolis/src/solstice,
     ./coriolis/src/ispd:
     - SVN MOVE: Source tree simplification & uniformisation. Now all tools
         are at the same level, directly under the root of the repository.
         No more "coriolis/src".
This commit is contained in:
Jean-Paul Chaput 2010-03-09 15:27:00 +00:00
parent 8ba0188821
commit d6389cde14
5 changed files with 1226 additions and 0 deletions

42
ispd/CMakeLists.txt Normal file
View File

@ -0,0 +1,42 @@
PROJECT(UNICORN)
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.0)
IF(COMMAND CMAKE_POLICY)
CMAKE_POLICY(SET CMP0003 NEW)
ENDIF(COMMAND CMAKE_POLICY)
IF(APPLE)
EXECUTE_PROCESS(
COMMAND sw_vers -productVersion
OUTPUT_VARIABLE OSX_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
MESSAGE(STATUS "OSX_VERSION='${OSX_VERSION}'")
IF(${OSX_VERSION} MATCHES "^10\\.[012345]\\.?")
MESSAGE(STATUS "OSX < 10.6")
ELSE(${OSX_VERSION} MATCHES "^10\\.[012345]\\.?")
SET(CMAKE_OSX_ARCHITECTURES "i386;ppc") # for QT4.5 32bits on snow leopard
ENDIF(${OSX_VERSION} MATCHES "^10\\.[012345]\\.?")
ENDIF(APPLE)
SET(CMAKE_C_FLAGS_DEBUG "-g -Wall" CACHE STRING "Debug options." FORCE)
SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall" CACHE STRING "Debug options." FORCE)
#SET(CMAKE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE)
#SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE)
#SET(CMAKE_MODULE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE)
#SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE)
SET(CMAKE_MODULE_PATH "$ENV{HURRICANE_TOP}/share/cmake_modules/")
SET(QT_USE_QTXML "true")
FIND_PACKAGE(Boost 1.33.1 COMPONENTS program_options REQUIRED)
FIND_PACKAGE(Qt4 REQUIRED) # find and setup Qt4 for this project
FIND_PACKAGE(LEFDEF REQUIRED)
FIND_PACKAGE(HURRICANE REQUIRED)
FIND_PACKAGE(CORIOLIS REQUIRED)
FIND_PACKAGE(KNIK REQUIRED)
FIND_PACKAGE(KATABATIC REQUIRED)
SET_LIB_LINK_MODE()
ADD_SUBDIRECTORY(src)

29
ispd/src/CMakeLists.txt Normal file
View File

@ -0,0 +1,29 @@
include ( ${QT_USE_FILE} )
include_directories ( ${Boost_INCLUDE_DIRS}
${HURRICANE_INCLUDE_DIR}
${CORIOLIS_INCLUDE_DIR}
)
set ( mocincludes IspdGui.h
)
set ( cpps IspdGui.cpp
IspdMain.cpp
)
qt4_wrap_cpp ( MOCcpps ${mocincludes} )
add_executable ( ispd ${cpps} ${MOCcpps} )
target_link_libraries ( ispd ${KATABATIC_GRAPHICAL_LIBRARIES}
${KATABATIC_LIBRARIES}
${KNIK_GRAPHICAL_LIBRARIES}
${KNIK_LIBRARIES}
${CORIOLIS_LIBRARIES}
${HURRICANE_GRAPHICAL_LIBRARIES}
${HURRICANE_LIBRARIES}
${OA_LIBRARIES}
${LEFDEF_LIBRARIES}
${QT_LIBRARIES}
${Boost_LIBRARIES} )
install ( TARGETS ispd DESTINATION /bin )

126
ispd/src/IspdGui.cpp Normal file
View File

@ -0,0 +1,126 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2008, All Rights Reserved
//
// ===================================================================
//
// $Id$
//
// x-----------------------------------------------------------------x
// | |
// | C O R I O L I S |
// | I s p d G l o b a l r o u t i n g - M a i n G U I |
// | |
// | Author : Damien Dupuis |
// | E-mail : Damien.Dupuis@lip6.fr |
// | =============================================================== |
// | C++ Module : "./IspdGui.cpp" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
#include <QAction>
#include <QMenu>
#include "hurricane/Warning.h"
#include "hurricane/viewer/CellWidget.h"
#include "crlcore/Catalog.h"
#include "crlcore/GraphicToolEngine.h"
#include "IspdGui.h"
namespace Ispd {
using Hurricane::Warning;
using CRL::Catalog;
// -------------------------------------------------------------------
// Class : "IspdGui".
IspdGui::IspdGui ( QWidget* parent )
: CellViewer(parent)
, _banner ( "Ispd"
, "1.0a"
, "Coriolis Ispd Main GUI"
, "2008"
, "Damien Dupuis"
, ""
)
, _tools()
{ }
IspdGui::~IspdGui ()
{ }
IspdGui* IspdGui::create ( QWidget* parent )
{
IspdGui* ispdgui = new IspdGui ( parent );
ispdgui->_postCreate ();
return ispdgui;
}
void IspdGui::destroy ()
{
_preDestroy ();
delete this;
}
void IspdGui::_postCreate ()
{
setApplicationName ( tr("ispd") );
//QAction* openAction = findChild<QAction*>("viewer.menuBar.file.openCell");
//if ( openAction ) {
// connect ( openAction, SIGNAL(triggered()), this, SLOT(openCell()) );
//}
}
void IspdGui::_preDestroy ()
{
set<GraphicTool*>::iterator itool = _tools.begin();
for ( ; itool != _tools.end() ; itool++ )
(*itool)->release ();
}
void IspdGui::registerTool ( GraphicTool* tool )
{
assert ( tool != NULL );
if ( _tools.find(tool) != _tools.end() ) {
cerr << Warning ( "Tool %s already registered in Ispd (ignored)."
, getString(tool->getName()).c_str() ) << endl;
return;
}
_tools.insert ( tool );
const GraphicTool::DrawGoMap& drawGos = tool->getDrawGos ();
GraphicTool::DrawGoMap::const_iterator idrawGo = drawGos.begin();
for ( ; idrawGo != drawGos.end() ; idrawGo++ )
getCellWidget()->addDrawExtensionGo ( idrawGo->first
, idrawGo->second.getInit()
, idrawGo->second.getDraw()
);
tool->addToMenu ( this );
}
} // End of Ispd namespace.

79
ispd/src/IspdGui.h Normal file
View File

@ -0,0 +1,79 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2008, All Rights Reserved
//
// ===================================================================
//
// $Id$
//
// x-----------------------------------------------------------------x
// | |
// | C O R I O L I S |
// | I s p d G l o b a l r o u t i n g - M a i n G U I |
// | |
// | Author : Damien Dupuis |
// | E-mail : Damien.Dupuis@lip6.fr |
// | =============================================================== |
// | C++ Header : "./IspdGui.h" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
#ifndef __ISPD_ISPD__
#define __ISPD_ISPD__
#include <set>
#include <iostream>
using namespace std;
#include "hurricane/viewer/CellViewer.h"
#include "crlcore/Banner.h"
namespace CRL {
class GraphicTool;
}
namespace Ispd {
using std::set;
using Hurricane::CellViewer;
using Hurricane::Cell;
using CRL::Banner;
using CRL::GraphicTool;
class IspdGui : public CellViewer {
Q_OBJECT;
public:
static IspdGui* create ( QWidget* parent=NULL);
void destroy ();
inline const Banner& getBanner () const;
void registerTool ( GraphicTool* );
protected:
IspdGui ( QWidget* parent );
virtual ~IspdGui ();
virtual void _postCreate ();
virtual void _preDestroy ();
protected:
Banner _banner;
set<GraphicTool*> _tools;
};
inline const Banner& IspdGui::getBanner () const { return _banner; }
} // End of Ispd namespace.
#endif // __ISPD_ISPD__

950
ispd/src/IspdMain.cpp Normal file
View File

@ -0,0 +1,950 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved
//
// ===================================================================
//
// $Id$
//
// x-----------------------------------------------------------------x
// | |
// | C O R I O L I S |
// | I s p d G l o b a l r o u t i n g - M a i n G U I |
// | |
// | Author : Damien Dupuis |
// | E-mail : Damien.Dupuis@lip6.fr |
// | =============================================================== |
// | C++ Module : "./IspdMain.cpp" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
#include <boost/program_options.hpp>
namespace poptions = boost::program_options;
#include <QtGui>
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "hurricane/Cell.h"
#include "hurricane/Warning.h"
#include "hurricane/Net.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/UpdateSession.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/viewer/Graphics.h"
#include "hurricane/viewer/HApplication.h"
using namespace Hurricane;
#include "crlcore/Utilities.h"
#include "crlcore/AllianceFramework.h"
using namespace CRL;
#include "knik/GraphicKnikEngine.h"
#include "knik/KnikEngine.h"
#include "knik/NetExtension.h"
using namespace Knik;
#include "katabatic/GraphicKatabaticEngine.h"
using namespace Katabatic;
#include "IspdGui.h"
using namespace Ispd;
namespace {
// -------------------------------------------------------------------
// Global variables
# define LINE_SIZE 4096
enum ParserState { StateGrid
, StateVerti
, StateHoriz
, StateWidth
, StateSpacing
, StateVia
, StateDim
, StateNet
, StateObs
, StateEOF
};
unsigned __congestion__ = 1;
unsigned __precongestion__ = 2;
float __edge_cost__ = 3.0;
Cell* _cell = NULL;
DataBase::DataBase* _db = NULL;
KnikEngine* _knik = NULL;
AllianceFramework* _af = AllianceFramework::create ();
string _filePath;
int _parserState = StateGrid;
size_t _lineNumber = 0;
char _rawLine[LINE_SIZE];
unsigned _nbGCellsX;
unsigned _nbGCellsY;
unsigned _nbLayers;
DbU::Unit _lowerLeftX;
DbU::Unit _lowerLeftY;
DbU::Unit _tileWidth;
DbU::Unit _tileHeight;
vector<unsigned> _vertiCap;
vector<unsigned> _horizCap;
vector<unsigned> _minWidth;
vector<unsigned> _minSpacing;
vector<unsigned> _viaSpacing;
unsigned _nbNets;
unsigned _nbObs;
Layer* _layers[2];
bool _createRings = true;
// -------------------------------------------------------------------
// Function : "printHelp()".
void printHelp ()
{
cout << endl;
cout << "Usage: unicorn [-v|--verbose] [-V|--very-verbose] [-D|--core-dump] \\\n"
<< " [-l|--trace-level <traceLevel>] [-c|--cell <cellName>] \\\n"
<< endl;
cout << "Options:\n"
<< " o [-v|--verbose] : First level of verbosity.\n"
<< " o [-V|--very-verbose] : Second level of verbosity (very talkative).\n"
<< " o [-D|--core-dump] : Enable core dumping.\n"
<< " o [-l|--trace-level <traceLevel>] :\n"
<< " Sets the level of trace, trace messages with a level superior to\n"
<< " <traceLevel> will be printed on <stderr>.\n"
<< " o [-c|--cell <cellName>] :\n"
<< " The name of the Cell to load, without extention.\n"
<< " o [-k|--knik] : Run the global router : Knik.\n"
<< " o [-K|--KNIK] : Run the global router : Knik, then analyse routing and unroute overflowed segments.\n"
<< endl;
}
void _printWarning ( const char* format, ... )
{
static char formatted [ 8192 ];
va_list args;
va_start ( args, format );
vsnprintf ( formatted, 8191, format, args );
va_end ( args );
cerr << "[WARNING] GrParser(): " << formatted << "\n"
<< " (file: " << _filePath << ", line: " << _lineNumber << ")" << endl;
}
void _printError ( bool interrupt, const char* format, ... )
{
static char formatted [ 8192 ];
va_list args;
va_start ( args, format );
vsnprintf ( formatted, 8191, format, args );
va_end ( args );
cerr << "[ERROR] GrParser(): " << formatted << "\n"
<< " (file: " << _filePath << ", line: " << _lineNumber << ")" << endl;
if ( interrupt )
throw Error ( "GrParser processed" );
}
long _getLong ( const char* s )
{
char* end;
long value = strtol ( s, &end, 10 );
if ( *end != '\0' )
_printError ( false, "Incomplete string to integer conversion for \"%s\" (%ld).", s, value );
return value;
}
vector<char*> _splitString ( char* s )
{
vector<char*> fields;
fields.push_back ( s );
while ( *s != '\0' ) {
unsigned i = 0;
if ( *s == ' ' || *s == '\t' ) {
i++;
*s = '\0';
while ( *(s+i) == ' ' || *(s+i) == '\t' )
i++;
fields.push_back ( s+i );
s += i;
}
else
s++;
}
return fields;
}
vector<char*> _splitSegmentString ( char* s )
{
vector<char*> fields;
//fields.push_back ( s );
while ( *s != '\0' ) {
unsigned i = 0;
if ( *s == '(' || *s == ')' || *s == ',' || *s == '-' ) {
i++;
*s = '\0';
while ( *(s+i) == '(' || *(s+i) == ')' || *(s+i) == ',' || *(s+i) == '-' )
i++;
if ( *(s+i+1) != '\0' )
fields.push_back ( s+i );
s += i;
}
else
s++;
}
return fields;
}
void _parseGrid ()
{
if ( strncmp(_rawLine,"grid", 4) )
_printError ( true, "Missing Grid Declaration." );
vector<char*> fields =_splitString ( _rawLine+5 );
if ( fields.size() != 3 ) {
_printError ( true, "Malformed Grid Line." );
}
else {
_nbGCellsX = _getLong ( fields[0] );
_nbGCellsY = _getLong ( fields[1] );
_nbLayers = _getLong ( fields[2] );
}
if ( _nbLayers != 2 )
_printError ( false, "Global routing only supports two layers right now !" );
}
void _parseVerti ()
{
if ( strncmp(_rawLine, "vertical capacity", 17) )
_printError ( true, "Missing Vertical Declaration." );
vector<char*> fields = _splitString ( _rawLine+18 );
if ( fields.size() < _nbLayers )
_printError ( true, "Malformed Vertical line." );
else
for ( unsigned i = 0 ; i < _nbLayers ; i++ ) {
_vertiCap.push_back ( _getLong ( fields[i] ) );
}
}
void _parseHoriz ()
{
if ( strncmp(_rawLine, "horizontal capacity", 19) )
_printError ( true, "Missing Horizontal Declaration." );
vector<char*> fields = _splitString ( _rawLine+20 );
if ( fields.size() < _nbLayers )
_printError ( true, "Malformed Horizontal line." );
else
for ( unsigned i = 0 ; i < _nbLayers ; i++ ) {
_horizCap.push_back ( _getLong ( fields[i] ) );
}
}
void _parseWidth ()
{
if ( strncmp(_rawLine, "minimum width", 13) )
_printError ( true, "Missing Minimum Width Declaration." );
vector<char*> fields = _splitString ( _rawLine+14 );
if ( fields.size() < _nbLayers )
_printError ( true, "Malformed Minimum Width line." );
else
for ( unsigned i = 0 ; i < _nbLayers ; i++ ) {
_minWidth.push_back ( _getLong ( fields[i] ) );
}
}
void _parseSpacing ()
{
if ( strncmp(_rawLine, "minimum spacing", 15) )
_printError ( true, "Missing Minimum Spacing Declaration." );
vector<char*> fields = _splitString ( _rawLine+16 );
if ( fields.size() < _nbLayers )
_printError ( true, "Malformed Minimum Spacing line." );
else
for ( unsigned i = 0 ; i < _nbLayers ; i++ ) {
_minSpacing.push_back ( _getLong ( fields[i] ) );
}
}
void _parseVia ()
{
if ( strncmp(_rawLine, "via spacing", 11) )
_printError ( true, "Missing Via Spacing Declaration." );
vector<char*> fields = _splitString ( _rawLine+12 );
if ( fields.size() < _nbLayers )
_printError ( true, "Malformed Via Spacing line." );
else
for ( unsigned i = 0 ; i < _nbLayers ; i++ ) {
_viaSpacing.push_back ( _getLong ( fields[i] ) );
}
}
void _parseDim ()
{
vector<char*> fields = _splitString ( _rawLine );
if ( fields.size() < 4 )
_printError ( true, "Malformed Dimension line." );
else {
_lowerLeftX = DbU::lambda ( _getLong ( fields[0] ) );
_lowerLeftY = DbU::lambda ( _getLong ( fields[1] ) );
_tileWidth = DbU::lambda ( _getLong ( fields[2] ) );
_tileHeight = DbU::lambda ( _getLong ( fields[3] ) );
}
DbU::Unit cellWidth = (2*_lowerLeftX)+(_nbGCellsX*_tileWidth);
DbU::Unit cellHeight = (2*_lowerLeftY)+(_nbGCellsY*_tileHeight);
cmess1 << " o Creating cell ..." << endl
<< " - " << _nbGCellsX << "x" << _nbGCellsY << " -> " << DbU::getValueString(cellWidth) << "x" << DbU::getValueString(cellHeight) << endl
<< " - congestion: " << __congestion__ << endl
<< " - precongestion: " << __precongestion__ << endl
<< " - edge cost: " << __edge_cost__ << endl;
_cell = Cell::create ( _af->getLibrary(0), _filePath );
assert ( _cell );
_cell->setTerminal(0);
_cell->setAbutmentBox ( Box ( DbU::lambda(0), DbU::lambda(0), cellWidth, cellHeight ) );
_knik = KnikEngine::get ( _cell );
if ( !_knik )
_knik = KnikEngine::create ( _cell, __congestion__, __precongestion__, true, true, __edge_cost__ );
unsigned hcapacity = 0;
for ( unsigned i = 0 ; i < _horizCap.size() ; i++ )
hcapacity += _horizCap[i];
hcapacity = hcapacity / ( _minWidth[0]+_minSpacing[0] );
unsigned vcapacity = 0;
for ( unsigned i = 0 ; i < _vertiCap.size() ; i++ )
vcapacity += _vertiCap[i];
vcapacity = vcapacity / ( _minWidth[1]+_minSpacing[1] ); // XXX we consider only 2 layers!!!
_knik->createRoutingGrid ( _nbGCellsX, _nbGCellsY, _lowerLeftX, _lowerLeftY, _tileWidth, _tileHeight, hcapacity, vcapacity );
// for ispd07 reload
_knik->createRoutingGraph();
}
void _parseNets ()
{
if ( strncmp(_rawLine, "num net", 7) )
_printError ( true, "Missing Number of Nets Declaration." );
cmess1 << " o Parsing nets ..." << endl;
vector<char*> fields = _splitString ( _rawLine+8 );
if ( fields.size() != 1 )
_printError ( true, "Malformed Number of Nets line." );
else
_nbNets = _getLong ( fields[0] );
cmess1 << " - " << _nbNets << " nets found" << endl;
}
void _parseNet ( Net* &net, unsigned &nbPins)
{
vector<char*> fields = _splitString ( _rawLine );
if ( fields.size() != 4 )
_printError ( true, "Malformed Net Line." );
else {
Name netName = Name ( fields[0] );
long netID = _getLong ( fields[1] );
nbPins = _getLong ( fields[2] );
net = Net::create ( _cell, netName );
//net->put ( StandardPrivateProperty<unsigned>::create(netID) );
NetExtension::setId ( net, netID );
}
}
void _parseNode ( Net* net, RoutingPad* &firstRoutingPad )
{
DbU::Unit x,y;
long layerID;
vector<char*> fields = _splitString ( _rawLine );
if ( fields.size() != 3 ) {
for (unsigned i = 0 ; i < fields.size(); i ++ ){
cerr << fields[i] << ",";
}
cerr << endl;
_printError ( true, "Malformed Node Line." );
}
else {
x = DbU::lambda ( _getLong ( fields[0] ) );
y = DbU::lambda ( _getLong ( fields[1] ) );
layerID = _getLong ( fields[2] ) - 1;
}
//UpdateSession::open();
Contact* contact = Contact::create ( net, _layers[layerID], x, y, DbU::lambda(2), DbU::lambda(2) );
RoutingPad* routingPad = RoutingPad::create ( net, Occurrence ( contact ) );
// Dans le cas d'un chargment de solution, il se peut que le routingPad ne soit pas au centre du vertex -> on crée arbitrairement un contact au centre qu'on attache au vertex
if ( !_createRings )
_knik->addRoutingPadToGraph ( routingPad );
if ( _createRings ) {
if ( firstRoutingPad )
routingPad->getBodyHook()->attach ( firstRoutingPad->getBodyHook() );
else
firstRoutingPad = routingPad;
}
//UpdateSession::close();
}
void _parseObs ()
{
cmess1 << " o Parsing obstacles ..." << endl;
vector<char*> fields = _splitString ( _rawLine );
if ( fields.size() != 1 )
_printError ( true, "Malformed Number of Obstacles line." );
else
_nbObs = _getLong ( fields[0] );
cmess1 << " - " << _nbObs << " obstacles found" << endl;
}
void _parseObstacle ()
{
unsigned col1, row1, lID1, col2, row2, lID2, cap;
vector<char*> fields = _splitString ( _rawLine );
if ( fields.size() != 7 )
_printError ( true, "Malformed Obstacle line." );
else {
col1 = _getLong ( fields[0] );
row1 = _getLong ( fields[1] );
lID1 = _getLong ( fields[2] );
col2 = _getLong ( fields[3] );
row2 = _getLong ( fields[4] );
lID2 = _getLong ( fields[5] );
cap = _getLong ( fields[6] );
if ( lID1 != lID2 )
_printError( true, "Layers must be the same on Obstacle line." );
cap = cap / (_minWidth[lID1-1]+_minSpacing[lID1-1]);
_knik->updateEdgeCapacity ( col1, row1, col2, row2, cap );
}
}
Cell* loadFromFile()
{
string fullPath = _filePath;
fullPath += ".gr";
cmess1 << " o Loading cell :" << fullPath << endl;
IoFile fileStream ( fullPath );
fileStream.open ( "r" );
if ( !fileStream.isOpen() ) {
cerr << " [ERROR] Can't find file : " << fullPath << " !" << endl;
exit (48);
}
_db = DataBase::getDB ();
_layers[0] = _db->getTechnology()->getLayer ( Name ( "metal1" ) );
_layers[1] = _db->getTechnology()->getLayer ( Name ( "metal2" ) );
_lineNumber = 0;
_parserState = StateGrid;
try {
while ( !fileStream.eof() ) {
fileStream.readLine ( _rawLine, LINE_SIZE );
_lineNumber++;
if ( _rawLine[0] == '\0' ) {
if ( _parserState == StateEOF ) break;
continue;
} else {
if ( _parserState == StateEOF )
_printError ( true, "Garbage after EOF." );
}
if ( !strcmp(_rawLine,"EOF") ) { _parserState = StateEOF; continue; }
if ( _parserState == StateGrid ) {
_parseGrid ();
_parserState = StateVerti;
continue;
}
if ( _parserState == StateVerti ) {
_parseVerti ();
_parserState = StateHoriz;
continue;
}
if ( _parserState == StateHoriz ) {
_parseHoriz ();
_parserState = StateWidth;
continue;
}
if ( _parserState == StateWidth ) {
_parseWidth ();
_parserState = StateSpacing;
continue;
}
if ( _parserState == StateSpacing ) {
_parseSpacing ();
_parserState = StateVia;
continue;
}
if ( _parserState == StateVia ) {
_parseVia ();
_parserState = StateDim;
continue;
}
if ( _parserState == StateDim ) {
_parseDim ();
_parserState = StateNet;
continue;
}
if ( _parserState == StateNet ) {
_parseNets ();
for ( unsigned i = 0 ; i < _nbNets ; i++ ) {
fileStream.readLine ( _rawLine, LINE_SIZE );
_lineNumber++;
Net* net = NULL;
RoutingPad* firstRoutingPad = NULL;
unsigned nbPins = 0;
_parseNet( net, nbPins );
for ( unsigned j = 0 ; j < nbPins ; j++ ) {
fileStream.readLine ( _rawLine, LINE_SIZE );
_lineNumber++;
_parseNode ( net, firstRoutingPad );
}
//cmess1 << " [";
//cmess1.width(3);
//cmess1 << floor((float)(i*100/(float)(_nbNets)));
//cmess1 << "%]\r";
}
cmess1 << " [100%] Done." << endl;
_knik->initGlobalRouting();
_parserState = StateObs;
continue;
}
if ( _parserState == StateObs ) {
_parseObs ();
for ( unsigned i = 0 ; i < _nbObs ; i++ )
{
fileStream.readLine ( _rawLine, LINE_SIZE );
_lineNumber++;
_parseObstacle ();
//cmess1 << " [" << floor((float)(i*100/(float)(_nbObs))) << "%]\r";
}
cmess1 << " [100%] Done." << endl;
_parserState = StateEOF;
continue;
}
}
} catch ( Error& e ) {
if ( e.what() != "[ERROR] GrParser processed" )
cerr << e.what() << endl;
}
fileStream.close ();
return _cell;
}
void loadSolutionFile()
// ********************
{
cmess1 << " o Loading solution :" << _filePath << endl;
IoFile fileStream ( _filePath );
fileStream.open ( "r" );
if ( !fileStream.isOpen() ) {
cerr << " [ERROR] Can't find file : " << _filePath << " !" << endl;
exit (48);
}
_db = DataBase::getDB ();
Layer* _gmetalh = _db->getTechnology()->getLayer ( Name ( "gmetalh" ) );
Layer* _gmetalv = _db->getTechnology()->getLayer ( Name ( "gmetalv" ) );
Layer* _gcontact = _db->getTechnology()->getLayer ( Name ( "gcontact" ) );
_lineNumber = 0;
unsigned _uselessContact = 0;
unsigned _illegalVerti = 0;
unsigned _illegalHoriz = 0;
unsigned _illegalDiag = 0;
unsigned _totalVias = 0;
unsigned _validSegments = 0;
try {
while ( !fileStream.eof() ) {
fileStream.readLine ( _rawLine, LINE_SIZE );
_lineNumber++;
if ( _rawLine[0] == '\0' )
break;
if ( _rawLine[0] == '\n' )
continue;
vector<char*> fields = _splitString ( _rawLine );
if ( fields.size() != 3 )
_printError ( true, "Malformed Net Line." );
else {
Name netName = Name ( fields[0] );
long netID = _getLong ( fields[1] );
unsigned nbPins = _getLong ( fields[2] );
Net* net = _cell->getNet ( netName );
if ( !net ) {
string message = "Parse solution failed : cannot find net : ";
message += getString(netName);
_printError ( true , message.c_str() );
}
vector<Segment*> segments;
for ( unsigned i = 0 ; i < nbPins ; i++ ) {
fileStream.readLine ( _rawLine, LINE_SIZE );
_lineNumber++;
fields = _splitSegmentString ( _rawLine );
if ( fields.size() != 6 )
_printError ( true, "Malformed Net Line." );
else {
DbU::Unit xSource = DbU::lambda(_getLong(fields[0]));
DbU::Unit ySource = DbU::lambda(_getLong(fields[1]));
unsigned zSource = (unsigned)(_getLong(fields[2]));
DbU::Unit xTarget = DbU::lambda(_getLong(fields[3]));
DbU::Unit yTarget = DbU::lambda(_getLong(fields[4]));
unsigned zTarget = (unsigned)(_getLong(fields[5]));
if ( xSource == xTarget ) {
if ( ySource == yTarget ) { //contact
if ( zSource != zTarget ) {
//UpdateSession::open();
Contact::create ( net, _gcontact, xSource, ySource );
//UpdateSession::close();
_totalVias++;
}
else
_uselessContact++;
}
else { // segment vertical
if ( zSource != zTarget ) // illegal segment
_illegalVerti++;
else {
//UpdateSession::open();
Vertical* verti = Vertical::create ( net, _gmetalv, xSource );
segments.push_back(verti);
if ( ySource < yTarget ) {
verti->setDySource ( ySource );
verti->setDyTarget ( yTarget );
}
else {
verti->setDySource ( yTarget );
verti->setDyTarget ( ySource );
}
_knik->insertSegment ( verti );
//UpdateSession::close();
_validSegments++;
}
}
}
else { // segment horizontal
if ( ySource != yTarget )
_illegalDiag++;
else {
if ( zSource != zTarget )
_illegalHoriz++;
else {
//UpdateSession::open();
Horizontal* horiz = Horizontal::create ( net, _gmetalh, ySource );
segments.push_back(horiz);
if ( xSource < xTarget ) {
horiz->setDxSource ( xSource );
horiz->setDxTarget ( xTarget );
}
else {
horiz->setDxSource ( xTarget );
horiz->setDxTarget ( xSource );
}
_knik->insertSegment ( horiz );
//UpdateSession::close();
_validSegments++;
}
}
}
}
}
fileStream.readLine ( _rawLine, LINE_SIZE );
_lineNumber++;
if ( _rawLine[0] != '!' )
throw Error ("gnagnagnagnagna"+getString(_lineNumber));
// on va relier les segments et les contacts :
for ( unsigned i = 0 ; i < segments.size() ; i++ ) {
Segment* segment = segments[i];
Point sourcePos = segment->getSourcePosition();
Point targetPos = segment->getTargetPosition();
Contact* source = NULL;
Contact* target = NULL;
forEach ( Contact*, contact, net->getContacts() ) {
Point pos = contact->getPosition();
if ( pos == sourcePos )
source = *contact;
else if ( pos == targetPos )
target = *contact;
if ( source && target )
break;
}
if ( !source ) {
string message = "Cannot find source contact for ";
message += getString(segment);
throw Error (message);
}
if ( !target ) {
string message = "Cannot find target contact for ";
message += getString(segment);
throw Error (message);
}
//UpdateSession::open();
if ( Horizontal* horiz = dynamic_cast<Horizontal*>(segment) ) {
horiz->setDxSource(0);
horiz->setDxTarget(0);
}
else if ( Vertical* verti = dynamic_cast<Vertical*>(segment) ) {
verti->setDySource(0);
verti->setDyTarget(0);
}
else
throw Error ("A segment which is not a Horizontal nor a Vertical !!!");
segment->getSourceHook()->attach(source->getBodyHook());
segment->getTargetHook()->attach(target->getBodyHook());
//UpdateSession::close();
}
}
}
} catch ( Error& e ) {
if ( e.what() != "[ERROR] GrParser processed" )
cerr << e.what() << endl;
}
fileStream.close ();
}
void printToFile(IspdGui* ispd)
// ****************************
{
float width = DbU::getLambda(_cell->getAbutmentBox().getWidth());
float height = DbU::getLambda(_cell->getAbutmentBox().getHeight());
assert(width);
assert(height);
float minSize = 800;
unsigned wWidth = (unsigned int)((width < height) ? minSize : floor(width*minSize/height));
unsigned wHeight = (unsigned int)((width < height) ? floor(height*minSize/width) : minSize);
//unsigned wWidth = floor(width);
//unsigned wHeight = floor(height);
CellWidget* widget = ispd->getCellWidget();
widget->setFixedSize(wWidth, wHeight);
widget->fitToContents();
forEach ( Layer*, layer, DataBase::getDB()->getTechnology()->getLayers() )
widget->setLayerVisible ( layer->getName(), false );
widget->setLayerVisible ( Name("Knik::Edges"), true );
QImage image (wWidth, wHeight+60, QImage::Format_RGB32);
widget->copyToImage(&image);
string savePath = _filePath;
savePath += "_map.png";
image.save(savePath.c_str(),"png");
}
} // End of anonymous namespace.
// x-----------------------------------------------------------------x
// | Fonctions Definitions |
// x-----------------------------------------------------------------x
// -------------------------------------------------------------------
// Function : "main()".
int main ( int argc, char *argv[] )
{
int returnCode = 0;
try {
float edgeCapacity;
unsigned int traceLevel;
bool verbose1;
bool verbose2;
bool coreDump;
bool textMode;
bool graphicMode;
bool knikSimple;
bool knikOverflow;
bool loadSolution;
bool saveSolution;
poptions::options_description options ("Command line arguments & options");
options.add_options()
( "help,h" , "Print this help." )
( "verbose,v" , poptions::bool_switch(&verbose1)->default_value(false)
, "First level of verbosity.")
( "very-verbose,V", poptions::bool_switch(&verbose2)->default_value(false)
, "Second level of verbosity.")
( "text,t" , poptions::bool_switch(&textMode)->default_value(false)
, "Run in pure text mode.")
( "core-dump,D" , poptions::bool_switch(&coreDump)->default_value(false)
, "Enable core dumping.")
( "trace-level,l" , poptions::value<unsigned int>(&traceLevel)->default_value(1000)
, "Set the level of trace, trace messages with a level superior to "
"<arg> will be printed on <stderr>." )
( "cell,c" , poptions::value<string>()
, "The name of the cell to load, whithout extension." )
( "knik,k" , poptions::bool_switch(&knikSimple)->default_value(false)
, "Perform a simple routing pass.");
( "KNIK,K" , poptions::bool_switch(&knikOverflow)->default_value(false)
, "Perform a routing pass, then analyse & re-route overflowed edges.");
( "solution,s" , poptions::bool_switch(&loadSolution)->default_value(true)
, "Load a previously generated routing solution.");
( "Save,S" , poptions::bool_switch(&saveSolution)->default_value(false)
, "Save the routed design.");
( "editor,e" , poptions::bool_switch(&graphicMode)->default_value(false)
, "Launch the graphical editor.");
poptions::variables_map arguments;
poptions::store ( poptions::parse_command_line(argc,argv,options), arguments );
poptions::notify ( arguments );
if ( arguments.count("help") ) {
cout << options << endl;
exit ( 0 );
}
System::getSystem()->setCatchCore ( not coreDump );
if ( verbose1 ) mstream::enable ( mstream::VerboseLevel1 );
if ( verbose2 ) mstream::enable ( mstream::VerboseLevel2 );
ltracelevel ( traceLevel );
_createRings = not loadSolution;
if ( arguments.count("cell") ) {
_filePath = arguments["cell"].as<string>();
UpdateSession::open();
_cell = loadFromFile();
UpdateSession::close();
if (!_cell) {
cerr << "[ERROR] Cell not found: " << arguments["cell"].as<string>() << endl;
exit ( -45 );
}
}
if ( loadSolution ) {
_filePath = arguments["cell"].as<string>();
UpdateSession::open();
loadSolutionFile();
UpdateSession::close();
}
if ( not textMode ) {
QApplication* qa = new HApplication ( argc, argv );
Graphics::enable ();
IspdGui* ispd = IspdGui::create ();
cmess1 << ispd->getBanner() << endl;;
GraphicKnikEngine* grKnik = Knik::GraphicKnikEngine::grab();
ispd->registerTool ( grKnik );
ispd->registerTool ( Katabatic::GraphicKatabaticEngine::grab() );
ispd->setCell ( _cell );
ispd->show();
if ( arguments.count("knik") ) {
grKnik->route();
grKnik->analyse();
}
else if ( arguments.count("KNIK") ) {
grKnik->run();
//bool done = grKnik->analyse();
//while ( !done ) {
// grKnik->unroute();
// grKnik->reroute();
// done = grKnik->analyse();
//}
}
else if ( saveSolution ) {
//grKnik->analyse();
printToFile(ispd);
}
if ( not saveSolution or graphicMode )
returnCode = qa->exec();
ispd->destroy();
delete qa;
} else {
KnikEngine* knik = Knik::KnikEngine::get(_cell);
if ( arguments.count("knik") ) {
knik->Route();
knik->analyseRouting();
if ( saveSolution ) knik->saveSolution();
} else if ( arguments.count("KNIK") ) {
//knik->Route();
//bool done = knik->analyseRouting();
//while ( !done ) {
// knik->unrouteOvSegments();
// knik->reroute();
// done = knik->analyseRouting();
//}
knik->run();
if ( saveSolution )
knik->saveSolution();
} else if ( loadSolution ) {
knik->analyseRouting();
} else
cerr << "[ERROR] Using text mode without -k, -K or -s option is useless." << endl;
}
_af->destroy();
}
catch ( Error& e ) {
cerr << e.what() << endl;
exit ( 1 );
}
catch ( ... ) {
cout << "[ERROR] Abnormal termination: unmanaged exception.\n" << endl;
exit ( 2 );
}
return returnCode;
}