coriolis/bora/src/BoraEngine.cpp

382 lines
12 KiB
C++

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2015-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | B o r a - A n a l o g S l i c i n g T r e e |
// | |
// | Authors : Eric LAO |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./BoraEngine.cpp" |
// +-----------------------------------------------------------------+
#include <Python.h>
#include <sstream>
#include <QAction>
#include <QMenu>
#include <QMenuBar>
#include <QLineEdit>
#include <QInputDialog>
#include <QFileDialog>
#include <QMessageBox>
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/DebugSession.h"
#include "hurricane/DataBase.h"
#include "hurricane/Library.h"
#include "hurricane/viewer/HApplication.h"
#include "hurricane/viewer/ExceptionWidget.h"
#include "hurricane/viewer/Script.h"
#include "hurricane/UpdateSession.h"
#include "hurricane/analog/AnalogCellExtension.h"
#include "hurricane/analog/LayoutGenerator.h"
#include "hurricane/analog/TransistorFamily.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/GdsDriver.h"
#include "anabatic/Dijkstra.h"
#include "katana/KatanaEngine.h"
#include "bora/SlicingPlotWidget.h"
#include "bora/SlicingDataWidget.h"
#include "bora/AnalogDistance.h"
#include "bora/BoraEngine.h"
#include "bora/PyBoraEngine.h"
namespace Bora {
using namespace std;
using Hurricane::dbo_ptr;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::Breakpoint;
using Hurricane::DebugSession;
using Hurricane::NetRoutingState;
using Hurricane::NetRoutingExtension;
using Hurricane::Net;
using Hurricane::Cell;
using Hurricane::Box;
using Hurricane::Transformation;
using Hurricane::UpdateSession;
using Analog::AnalogCellExtension;
using Analog::Device;
using CRL::System;
using CRL::GdsDriver;
// -------------------------------------------------------------------
// Class : "BoraEngine".
Name BoraEngine::_toolName = "Bora";
bool first = false;
const Name& BoraEngine::staticGetName ()
{ return _toolName; }
BoraEngine* BoraEngine::get ( const Cell* cell )
{
return static_cast<BoraEngine*>( ToolEngine::get(cell,staticGetName()) );
}
BoraEngine::BoraEngine ( Cell* cell )
: Super (cell)
, _viewer(NULL)
{ }
void BoraEngine::_postCreate ()
{
Super::_postCreate();
_runBoraInit();
}
BoraEngine* BoraEngine::create ( Cell* cell )
{
cdebug_log(539,0) << "BoraEngine* BoraEngine::create( Cell* cell )" << endl;
BoraEngine* bora = new BoraEngine( cell );
bora->_postCreate();
return bora;
}
void BoraEngine::_runBoraInit ()
{
Utilities::Path pythonSitePackages = System::getPath("pythonSitePackages");
Utilities::Path confFile = "coriolis/bora/initHook.py";
Utilities::Path systemConfFile = pythonSitePackages / confFile;
if (systemConfFile.exists()) {
//Isobar::Script::addPath( systemConfDir.toString() );
dbo_ptr<Isobar::Script> script = Isobar::Script::create( confFile.toPyModPath() );
script->addKwArgument( "bora" , (PyObject*)PyBoraEngine_Link(this) );
script->runFunction ( "boraHook", getCell() );
//Isobar::Script::removePath( systemConfDir.toString() );
} else {
cerr << Warning( "Bora system configuration file:\n <%s> not found."
, systemConfFile.toString().c_str() ) << endl;
}
}
BoraEngine::~BoraEngine ()
{ }
void BoraEngine::_preDestroy ()
{
cdebug.log(539,1) << "BoraEngine::_preDestroy()" << endl;
cmess1 << " o Deleting ToolEngine<" << getName() << "> from Cell <"
<< getCell()->getName() << ">" << endl;
cdebug.tabw(539,-1);
Super::_preDestroy();
}
const Name& BoraEngine::getName () const
{ return _toolName; }
void BoraEngine::setViewer ( Hurricane::CellViewer* viewer )
{ _viewer = viewer; }
void BoraEngine::updateSlicingTree()
{
SlicingNode* slicingtree = AnalogCellExtension::get<SlicingNode>( getCell() );
if (slicingtree) {
cmess1 << " o Updating the SlicingTree." << endl;
startMeasures();
slicingtree->updateGlobalSize();
stopMeasures();
printMeasures();
} else {
cerr << Error( "BoraEngine::updateSlicingTree(): "
"Cannot update, the SlicingTree needs to be created first." ) << endl;
}
}
void BoraEngine::updatePlacement ( DbU::Unit width, DbU::Unit height )
{
cdebug_log(536,1) << "BoraEngine::updatePlacement(DbU::Unit,DbU::Unit)" << endl;
SlicingNode* slicingtree = AnalogCellExtension::get<SlicingNode>( getCell() );
if (slicingtree){
BoxSet* bs = slicingtree->getPairHW( width, height );
if (bs) updatePlacement( bs );
} else
cerr << "[Error]: The slicing tree needs to be created first." << endl;
cdebug_tabw(536,-1);
}
void BoraEngine::updatePlacement ( size_t index )
{
cdebug_log(536,1) << "BoraEngine::updatePlacement(int)" << endl;
SlicingNode* slicingtree = AnalogCellExtension::get<SlicingNode>( getCell() );
if (slicingtree) {
cmess2 << Dots::asInt( " o Selecting analog placement (index)", index ) << endl;
BoxSet* bs = slicingtree->getPairHW( index );
if (bs) updatePlacement( bs );
} else
cerr << Error( "BoraEngine::updatePlacement(): The slicing tree needs to be created first." ) << endl;
cdebug_tabw(536,-1);
}
void BoraEngine::updatePlacement ( BoxSet* boxSet )
{
cdebug_log(536,1) << "BoraEngine::updatePlacement(BoxSet*)" << endl;
//DebugSession::addToTrace( getCell(), "vin+" );
SlicingNode* slicingtree = AnalogCellExtension::get<SlicingNode>( getCell() );
if (slicingtree) {
NodeSets nodeSets = slicingtree->getNodeSets();
if (not nodeSets.empty()) {
Cell* cell = SlicingNode::getCell();
Katana::KatanaEngine* katana = Katana::KatanaEngine::get( cell );
if (katana) katana->destroy();
slicingtree->_setGlobalSize( boxSet );
if (_viewer) emitCellPreModificated ();
UpdateSession::open();
slicingtree->clearGlobalRouting();
slicingtree->place();
CRL::RoutingGauge* rg = slicingtree->getRoutingGauge();
DbU::Unit hpitch = rg->getHorizontalPitch();
DbU::Unit vpitch = rg->getVerticalPitch();
slicingtree->expandRoutingChannel( hpitch*2, vpitch*2 );
slicingtree->replace();
slicingtree->updateSymNetAxis();
UpdateSession::close();
katana = Katana::KatanaEngine::create(cell);
katana->openSession();
Anabatic::GCell* gcell = katana->getSouthWestGCell();
slicingtree->setKatana( katana );
slicingtree->setGCell( gcell );
slicingtree->clearRoutingPads();
slicingtree->flattenDigitalNets();
slicingtree->createRoutingPads();
slicingtree->resetWireOccupation();
Katana::Session::close();
katana->openSession();
Anabatic::Dijkstra* dijkstra = new Anabatic::Dijkstra( katana );
AnalogDistance distance = AnalogDistance( cell, hpitch, vpitch );
dijkstra->setDistance ( distance );
dijkstra->setSearchAreaHalo( std::max(hpitch,vpitch) );
for ( Net* net : cell->getNets() ) {
distance.setNet( net );
dijkstra->load( net );
NetRoutingState* state = NetRoutingExtension::get( net );
if ( not (state and state->isSymSlave()) ) {
slicingtree->setVertexRestriction( net, katana );
dijkstra->run();
slicingtree->updateWireOccupation( dijkstra );
}
}
katana->setState( Anabatic::EngineState::EngineGlobalLoaded );
slicingtree->expandRoutingChannel();
slicingtree->replace();
slicingtree->updateSymNetAxis();
katana->updateMatrix();
katana->analogInit();
Katana::Session::close();
if (_viewer) {
getCellWidget()->fitToContents();
emitCellPostModificated();
}
} else
cerr << Error( "BoraEngine::updatePlacement(): The slicing tree can not be placed.\n"
" The slicing tree needs to be updated first." ) << endl;
} else
cerr << Error( "BoraEngine::updatePlacement(): The slicing tree can not be set.\n"
" The slicing tree needs to be created first." ) << endl;
cdebug_tabw(536,-1);
}
void BoraEngine::setToleranceRatio ( DbU::Unit ratioh, DbU::Unit ratiow )
{
SlicingNode* slicingtree = AnalogCellExtension::get<SlicingNode>( _viewer->getCellWidget()->getCell() );
if (slicingtree) {
slicingtree->setToleranceRatioH( ratioh );
slicingtree->setToleranceRatioW( ratiow );
resetPlacement();
} else
cerr << Error( "BoraEngine::setToleranceRatio(): The slicing tree's tolerance ratio cannot be set.\n"
" The slicing tree needs to be created first." ) << endl;
}
void BoraEngine::setToleranceBand ( DbU::Unit bandh, DbU::Unit bandw )
{
SlicingNode* slicingtree = AnalogCellExtension::get<SlicingNode>( _viewer->getCellWidget()->getCell() );
if (slicingtree) {
slicingtree->setToleranceBandH( bandh );
slicingtree->setToleranceBandW( bandw );
resetPlacement();
} else
cerr << Error( "BoraEngine::setToleranceBand(): The slicing tree's tolerance ratio can not be set.\n"
" The slicing tree needs to be created first." ) << endl;
}
void BoraEngine::showPareto ()
{ }
void BoraEngine::resetPlacement ()
{
emitCellPreModificated ();
DbU::Unit y = 0;
for ( Instance* instance : getCell()->getInstances() ) {
UpdateSession::open();
instance->setTransformation ( Transformation( 0, y ) );
instance->setPlacementStatus( Instance::PlacementStatus::PLACED );
UpdateSession::close();
Cell* model = instance->getMasterCell();
if (model) {
Device* device = dynamic_cast<Device*>( model );
if (device) y += device->getAbutmentBox().getHeight();
}
}
getCellWidget()->fitToContents();
emitCellPostModificated();
}
DbU::Unit BoraEngine::getToleranceRatioH () const
{
SlicingNode* slicingtree = AnalogCellExtension::get<SlicingNode>( _viewer->getCellWidget()->getCell() );
if (slicingtree) return slicingtree->getToleranceRatioH();
cerr << Error( "BoraEngine::getToleranceRatioH(): The slicing tree needs to be created first." ) << endl;
return 0;
}
DbU::Unit BoraEngine::getToleranceRatioW () const
{
SlicingNode* slicingtree = AnalogCellExtension::get<SlicingNode>( _viewer->getCellWidget()->getCell() );
if (slicingtree) return slicingtree->getToleranceRatioW();
cerr << Error( "BoraEngine::getToleranceRatioW(): The slicing tree needs to be created first." ) << endl;
return 0;
}
DbU::Unit BoraEngine::getToleranceBandH () const
{
SlicingNode* slicingtree = AnalogCellExtension::get<SlicingNode>( _viewer->getCellWidget()->getCell() );
if (slicingtree) return slicingtree->getToleranceBandH();
cerr << Error( "BoraEngine::getToleranceBandH(): The slicing tree needs to be created first." ) << endl;
return 0;
}
DbU::Unit BoraEngine::getToleranceBandW () const
{
SlicingNode* slicingtree = AnalogCellExtension::get<SlicingNode>( _viewer->getCellWidget()->getCell() );
if (slicingtree) return slicingtree->getToleranceBandW();
cerr << Error( "BoraEngine::getToleranceBandW(): The slicing tree needs to be created first." ) << endl;
return 0;
}
} // Bora namespace.