coriolis/hurricane/src/analog/LayoutGenerator.cpp

365 lines
10 KiB
C++
Raw Normal View History

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2009-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | H u r r i c a n e A n a l o g |
// | |
// | Author : Damien Dupuis |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./LayoutGenerator.cpp" |
// +-----------------------------------------------------------------+
#include <Python.h>
#include <unistd.h>
#include <cerrno>
#include <cstdio>
#include <iostream>
#include <fstream>
#include "hurricane/Warning.h"
#include "hurricane/isobar/PyBox.h"
#include "hurricane/viewer/Script.h"
#include "hurricane/analog/Device.h"
#include "hurricane/analog/PyDevice.h"
#include "hurricane/analog/LayoutGenerator.h"
namespace Analog {
using namespace std;
using namespace Hurricane;
using namespace Isobar;
// -------------------------------------------------------------------
// Class : "::LayoutGenerator::Logger".
LayoutGenerator::Logger::Logger ( LayoutGenerator* generator )
: _generator(generator)
{ }
LayoutGenerator::Logger::~Logger ()
{ }
void LayoutGenerator::Logger::popStatus ( const string& text )
{
if (_generator->getVerboseLevel() >= LayoutGenerator::Verbose)
cerr << text << endl;
}
void LayoutGenerator::Logger::popError ( const string& text )
Analog integration part II. Analog place & route (slicing tree). * Change: In Hurricane::CellWidget, set the minimal size to 350 pixels to fit my normal DPI secondary screen... * Change: In Hurricane::Error(), reactivate the backtrace generation by default. Seriously slow down the program each time an Error is to be constructed. * Bug: In Analog::Device::preCreate(), check for NULL Technology before attempting to use it. * Change: In Hurricane/Analog, remove all '*Arguments*' classes and their Python interface. It was an obsoleted way of passing devices parameters to the Python layout generators (located in Oroshi). Now we just get them straight from the Device with the getParamter() method. * Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze. * Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove all uses of the "Arguments". Directly access the parameters through the device itself. Make the checkCoherency() with identical arguments as of layout(). * New: Bora tool that performs analog place & route. Based on a slicing tree representation. It is the thesis work of Eric Lao. Code beautyfication and some programming cleanup. * New: Karakaze tool, provide the Python base class AnalogDesign used to build an analog design. Create/configure devices and assemble them in a slicing tree. * Change: In Unicorn/cgt.py, display the stack trace in case of an ImportError exception as well as for other exceptions. Add Bora to the set for included tool engines.
2018-10-18 11:10:01 -05:00
{ cerr << text << endl; }
void LayoutGenerator::Logger::popScriptError ()
{
string scriptError = "! An error occured while creating layout. Please check the python console for more information.";
cerr << scriptError << endl;
}
// -------------------------------------------------------------------
// Class : "::LayoutGenerator".
int LayoutGenerator::_verboseLevel = LayoutGenerator::Debug;
LayoutGenerator::LayoutGenerator ()
: _logger (NULL)
, _device (NULL)
, _box (NULL)
, _activeBox(NULL)
, _matrix ()
, _script (NULL)
{
_activeBox = new Hurricane::Box();
_script = Script::create();
setLogger ( new Logger(this) );
}
LayoutGenerator::~LayoutGenerator ()
{
if (_script) _script->destroy();
if (_logger) delete _logger;
}
bool LayoutGenerator::checkScript()
{
if (not _device) {
popError( "Try to check for script but device does not exist." );
return false;
}
FILE* fs = fopen( _device->getLayoutScript().c_str(), "r" );
if (not fs) {
perror( NULL );
popError( "Cannot load script : file does not exist or bad access rights." );
return false;
}
fclose( fs );
popStatus( _device->getLayoutScript()+" found." );
return true;
}
bool LayoutGenerator::checkFunctions()
{
if (not _script->getFunction("checkCoherency")) {
cerr << Error( "LayoutGenerator::drawLayout(): Module <%s> miss checkCoherency()."
, _script->getUserModuleName().c_str() ) << endl;
finalize( ShowTimeTag );
return false;
}
if (not _script->getFunction("layout")) {
cerr << Error( "LayoutGenerator::drawLayout(): Module <%s> miss layout()."
, _script->getUserModuleName().c_str() ) << endl;
finalize( ShowTimeTag );
return false;
}
return true;
}
bool LayoutGenerator::drawLayout ()
{
if (_device == NULL) return false;
//checkScript();
cdebug_log(500,0) << "LayoutGenerator::drawLayout() " << _device->getDeviceName() << endl;
_device->destroyLayout();
initialize();
if (not _script->getUserModule()) {
finalize( ShowTimeTag );
cerr << Error( "LayoutGenerator::drawLayout(): Couldn't load module <%s>"
, _script->getUserModuleName().c_str() ) << endl;
return false;
}
checkFunctions();
Analog integration part II. Analog place & route (slicing tree). * Change: In Hurricane::CellWidget, set the minimal size to 350 pixels to fit my normal DPI secondary screen... * Change: In Hurricane::Error(), reactivate the backtrace generation by default. Seriously slow down the program each time an Error is to be constructed. * Bug: In Analog::Device::preCreate(), check for NULL Technology before attempting to use it. * Change: In Hurricane/Analog, remove all '*Arguments*' classes and their Python interface. It was an obsoleted way of passing devices parameters to the Python layout generators (located in Oroshi). Now we just get them straight from the Device with the getParamter() method. * Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze. * Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove all uses of the "Arguments". Directly access the parameters through the device itself. Make the checkCoherency() with identical arguments as of layout(). * New: Bora tool that performs analog place & route. Based on a slicing tree representation. It is the thesis work of Eric Lao. Code beautyfication and some programming cleanup. * New: Karakaze tool, provide the Python base class AnalogDesign used to build an analog design. Create/configure devices and assemble them in a slicing tree. * Change: In Unicorn/cgt.py, display the stack trace in case of an ImportError exception as well as for other exceptions. Add Bora to the set for included tool engines.
2018-10-18 11:10:01 -05:00
PyObject* pyArgs = NULL;
if (not toPyArguments(pyArgs,NoFlags)) {
finalize( ShowTimeTag );
return false;
}
Analog integration part II. Analog place & route (slicing tree). * Change: In Hurricane::CellWidget, set the minimal size to 350 pixels to fit my normal DPI secondary screen... * Change: In Hurricane::Error(), reactivate the backtrace generation by default. Seriously slow down the program each time an Error is to be constructed. * Bug: In Analog::Device::preCreate(), check for NULL Technology before attempting to use it. * Change: In Hurricane/Analog, remove all '*Arguments*' classes and their Python interface. It was an obsoleted way of passing devices parameters to the Python layout generators (located in Oroshi). Now we just get them straight from the Device with the getParamter() method. * Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze. * Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove all uses of the "Arguments". Directly access the parameters through the device itself. Make the checkCoherency() with identical arguments as of layout(). * New: Bora tool that performs analog place & route. Based on a slicing tree representation. It is the thesis work of Eric Lao. Code beautyfication and some programming cleanup. * New: Karakaze tool, provide the Python base class AnalogDesign used to build an analog design. Create/configure devices and assemble them in a slicing tree. * Change: In Unicorn/cgt.py, display the stack trace in case of an ImportError exception as well as for other exceptions. Add Bora to the set for included tool engines.
2018-10-18 11:10:01 -05:00
if (not callCheckCoherency(pyArgs,ShowError)) {
return false;
}
Analog integration part II. Analog place & route (slicing tree). * Change: In Hurricane::CellWidget, set the minimal size to 350 pixels to fit my normal DPI secondary screen... * Change: In Hurricane::Error(), reactivate the backtrace generation by default. Seriously slow down the program each time an Error is to be constructed. * Bug: In Analog::Device::preCreate(), check for NULL Technology before attempting to use it. * Change: In Hurricane/Analog, remove all '*Arguments*' classes and their Python interface. It was an obsoleted way of passing devices parameters to the Python layout generators (located in Oroshi). Now we just get them straight from the Device with the getParamter() method. * Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze. * Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove all uses of the "Arguments". Directly access the parameters through the device itself. Make the checkCoherency() with identical arguments as of layout(). * New: Bora tool that performs analog place & route. Based on a slicing tree representation. It is the thesis work of Eric Lao. Code beautyfication and some programming cleanup. * New: Karakaze tool, provide the Python base class AnalogDesign used to build an analog design. Create/configure devices and assemble them in a slicing tree. * Change: In Unicorn/cgt.py, display the stack trace in case of an ImportError exception as well as for other exceptions. Add Bora to the set for included tool engines.
2018-10-18 11:10:01 -05:00
if (not callLayout(pyArgs)) {
cerr << "Layout failed" << endl; cerr.flush();
return false;
}
// Eric passed by here
//cerr << "Python driven Layout successfully drawn." << endl;
_device->setAbutmentBox( getDeviceBox() );
Support for separated NDA tree. Big cleanup of the Python init system. * Change: In Hurricane::Script, when running a script, no longer do it inside a Python sun-interpreter, use the current one. This way we no longer have our modules initialized twice or more, which was starting to be unmanageable (with the NDA support). The settings were re-read multiple time to the same value, so it was working, but still... I hope I didn't left some dangling Python objects now. * Bug: In Hurricane::LayoutGenerator::drawLayout(), get the device abutment box though a Pyhon object *before* finalizing which removes that objet. * New: In cumulus/plugins/__init__.py, add a "loadPlugins()" and static initialisation to preload plugins modules. We use that pre-loading step to append to the module __path__ attribute the alternate directory where a NDA covered may be found. This assume that the directory tree under the NDA root is identical to the one under the public root. * New: In cumulus/plugins/chip/__init__.py, small utility function importContants() to import the constants inside another module namespace, to have more consise notations. * Change: In cumulus/plugins/, in the various plugins sub-modules import use the full path from plugins, that is, for example: from plugins.core2chip.CoreToChip import IoPad * Change: In Unicorn/python/unicornInit.py, no longer directly load the plugins modules, this is now done by cumulus/plugins/__init__.py. Instead, iterate through sys.modules for the ones starting by "plugins/" and try to execute a Unicorn hook, if present. * Change: In Karakaze/python/AnalogDesign.py, update for the new Instance.create() prototype (added placement parameter).
2019-10-11 10:36:54 -05:00
finalize( ShowTimeTag|StatusOk );
//string message = _device->checkLayoutOnPhysicalGrid();
//if (not message.empty())
// popError( message.c_str() );
// Eric passed by here
//popStatus( "Layout done." );
return true;
}
bool LayoutGenerator::initialize ()
{
string moduleFullPath = _device->getLayoutScript();
size_t slash = moduleFullPath.rfind( '/' );
slash = (slash!=string::npos) ? slash+1 : 0;
string moduleName = moduleFullPath.substr( slash );
string modulePath = moduleFullPath.substr( 0, slash-1 );
size_t dot = moduleName.rfind( '.' );
dot = (dot!=string::npos) ? dot : moduleName.size();
moduleName = moduleName.substr( 0, dot );
// Eric passed by here
//cerr << "Path: " << modulePath << endl;
//cerr << "Name: " << moduleName << endl;
_script->setUserModuleName( moduleName );
return _script->initialize( Script::NoThrow );
}
void LayoutGenerator::finalize ( unsigned int flags )
{
if (flags & ShowTimeTag) {
string code = "";
// Eric passed by here
//if (flags & StatusOk) code = "import time; print ' -- Script SUCCESS2 --', time.strftime('%H:%M:%S',time.localtime())\n";
if (flags & StatusOk) code = "";
else code = "import time; print ' -- Script FAILED --' , time.strftime('%H:%M:%S',time.localtime())\n";
PyRun_SimpleString( code.c_str() );
}
_script->finalize();
}
Analog integration part II. Analog place & route (slicing tree). * Change: In Hurricane::CellWidget, set the minimal size to 350 pixels to fit my normal DPI secondary screen... * Change: In Hurricane::Error(), reactivate the backtrace generation by default. Seriously slow down the program each time an Error is to be constructed. * Bug: In Analog::Device::preCreate(), check for NULL Technology before attempting to use it. * Change: In Hurricane/Analog, remove all '*Arguments*' classes and their Python interface. It was an obsoleted way of passing devices parameters to the Python layout generators (located in Oroshi). Now we just get them straight from the Device with the getParamter() method. * Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze. * Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove all uses of the "Arguments". Directly access the parameters through the device itself. Make the checkCoherency() with identical arguments as of layout(). * New: Bora tool that performs analog place & route. Based on a slicing tree representation. It is the thesis work of Eric Lao. Code beautyfication and some programming cleanup. * New: Karakaze tool, provide the Python base class AnalogDesign used to build an analog design. Create/configure devices and assemble them in a slicing tree. * Change: In Unicorn/cgt.py, display the stack trace in case of an ImportError exception as well as for other exceptions. Add Bora to the set for included tool engines.
2018-10-18 11:10:01 -05:00
bool LayoutGenerator::toPyArguments ( PyObject*& pyArgs, unsigned int flags )
{
Analog integration part II. Analog place & route (slicing tree). * Change: In Hurricane::CellWidget, set the minimal size to 350 pixels to fit my normal DPI secondary screen... * Change: In Hurricane::Error(), reactivate the backtrace generation by default. Seriously slow down the program each time an Error is to be constructed. * Bug: In Analog::Device::preCreate(), check for NULL Technology before attempting to use it. * Change: In Hurricane/Analog, remove all '*Arguments*' classes and their Python interface. It was an obsoleted way of passing devices parameters to the Python layout generators (located in Oroshi). Now we just get them straight from the Device with the getParamter() method. * Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze. * Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove all uses of the "Arguments". Directly access the parameters through the device itself. Make the checkCoherency() with identical arguments as of layout(). * New: Bora tool that performs analog place & route. Based on a slicing tree representation. It is the thesis work of Eric Lao. Code beautyfication and some programming cleanup. * New: Karakaze tool, provide the Python base class AnalogDesign used to build an analog design. Create/configure devices and assemble them in a slicing tree. * Change: In Unicorn/cgt.py, display the stack trace in case of an ImportError exception as well as for other exceptions. Add Bora to the set for included tool engines.
2018-10-18 11:10:01 -05:00
pyArgs= PyTuple_New( 2 );
PyTuple_SetItem( pyArgs, 0, PyDevice_Link(_device) );
PyTuple_SetItem( pyArgs, 1, (flags & ComputeBbOnly) ? Py_True : Py_False );
return true;
}
bool LayoutGenerator::callCheckCoherency ( PyObject* pArgsCheck, unsigned int flags )
{
PyObject* pTupleCheck = _script->callFunction( "checkCoherency", pArgsCheck );
if (not pTupleCheck) {
string code = "print ' -- Script FAILED --', time.strftime('%H:%M:%S',time.localtime())\n";
PyRun_SimpleString( code.c_str() );
finalize( NoFlags );
popScriptError();
return false;
}
if ( not PyTuple_Check(pTupleCheck) or (PyTuple_Size(pTupleCheck) != 2) ) {
popError( "checkCoherency function must return a tuple: (bool,errorMessage)" );
return false;
}
PyObject* pCheckOk = PyTuple_GetItem( pTupleCheck, 0 );
if (pCheckOk == Py_False) {
if (flags & ShowError)
popError( string(PyString_AsString(PyTuple_GetItem(pTupleCheck,1))) );
return false;
}
return true;
}
Analog integration part II. Analog place & route (slicing tree). * Change: In Hurricane::CellWidget, set the minimal size to 350 pixels to fit my normal DPI secondary screen... * Change: In Hurricane::Error(), reactivate the backtrace generation by default. Seriously slow down the program each time an Error is to be constructed. * Bug: In Analog::Device::preCreate(), check for NULL Technology before attempting to use it. * Change: In Hurricane/Analog, remove all '*Arguments*' classes and their Python interface. It was an obsoleted way of passing devices parameters to the Python layout generators (located in Oroshi). Now we just get them straight from the Device with the getParamter() method. * Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze. * Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove all uses of the "Arguments". Directly access the parameters through the device itself. Make the checkCoherency() with identical arguments as of layout(). * New: Bora tool that performs analog place & route. Based on a slicing tree representation. It is the thesis work of Eric Lao. Code beautyfication and some programming cleanup. * New: Karakaze tool, provide the Python base class AnalogDesign used to build an analog design. Create/configure devices and assemble them in a slicing tree. * Change: In Unicorn/cgt.py, display the stack trace in case of an ImportError exception as well as for other exceptions. Add Bora to the set for included tool engines.
2018-10-18 11:10:01 -05:00
bool LayoutGenerator::callLayout ( PyObject* pArgs )
{
Analog integration part II. Analog place & route (slicing tree). * Change: In Hurricane::CellWidget, set the minimal size to 350 pixels to fit my normal DPI secondary screen... * Change: In Hurricane::Error(), reactivate the backtrace generation by default. Seriously slow down the program each time an Error is to be constructed. * Bug: In Analog::Device::preCreate(), check for NULL Technology before attempting to use it. * Change: In Hurricane/Analog, remove all '*Arguments*' classes and their Python interface. It was an obsoleted way of passing devices parameters to the Python layout generators (located in Oroshi). Now we just get them straight from the Device with the getParamter() method. * Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze. * Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove all uses of the "Arguments". Directly access the parameters through the device itself. Make the checkCoherency() with identical arguments as of layout(). * New: Bora tool that performs analog place & route. Based on a slicing tree representation. It is the thesis work of Eric Lao. Code beautyfication and some programming cleanup. * New: Karakaze tool, provide the Python base class AnalogDesign used to build an analog design. Create/configure devices and assemble them in a slicing tree. * Change: In Unicorn/cgt.py, display the stack trace in case of an ImportError exception as well as for other exceptions. Add Bora to the set for included tool engines.
2018-10-18 11:10:01 -05:00
_matrix = _script->callFunction( "layout", pArgs );
if (not _matrix) {
string code = "print ' -- Script FAILED --', time.strftime('%H:%M:%S',time.localtime())";
PyRun_SimpleString( code.c_str() );
finalize( NoFlags );
popScriptError();
cerr << "There was a problem running layout function" << endl;
return false;
}
return true;
}
unsigned LayoutGenerator::getNumberTransistor ()
{
PyObject* row = getRow(0);
if (row and PyList_Check(row) == 1)
return PyList_Size(row) - 1; // -1 because of the first column for global params
return 0; // else return 0;
}
unsigned LayoutGenerator::getNumberStack ()
{
if (_matrix and PyList_Check(_matrix) == 1)
return PyList_Size(_matrix) - 1; // -1 because of the first row for global params
return 0;
}
Box LayoutGenerator::getDeviceBox ()
{
PyObject* pBox = getParamValue(getDic(getRow(0), 0), "box");
if (pBox == NULL) {
finalize( NoFlags );
popError("Layout function did not returned a valid device box 2!");
return Box();
}
if (pBox->ob_type != &PyTypeBox) {
finalize( NoFlags );
popError("Layout function did not returned a valid device box!");
}
return *((PyBox*)pBox)->_object; //get the hurricane box
}
Box LayoutGenerator::getActiveBox ()
{
PyObject* pBox = getParamValue(getDic(getRow(0), 0), "globalActiveBox");
if (!pBox) {
finalize( NoFlags );
popError("Layout function did not returned a valid active box 2!");
return Box();
}
if (pBox->ob_type != &PyTypeBox) {
finalize( NoFlags );
popError("Layout function did not returned a valid active box!");
}
return *((PyBox*)pBox)->_object; //get the hurricane box
}
double LayoutGenerator::getParameterValue ( unsigned i, unsigned j, string paramName, bool& ok )
{
PyObject* pValue = getParamValue(getDic(getRow(i),j), paramName);
if (pValue == NULL){
ok = false;
return 0.0;
}
ok = true;
return (PyFloat_AsDouble(pValue));
}
PyObject* LayoutGenerator::getRow ( unsigned i )
{
if (_matrix and PyList_Check(_matrix) == 1 and ((int)i < PyList_Size(_matrix))){
return PyList_GetItem(_matrix, i);
}
return NULL;
}
PyObject* LayoutGenerator::getDic ( PyObject* row, unsigned j )
{
if (row and PyList_Check(row) == 1 and ((int)j < PyList_Size(row))){
return PyList_GetItem(row, j);
}
return NULL;
}
PyObject* LayoutGenerator::getParamValue ( PyObject* dic, string paramName )
{
if (dic and (PyDict_Check(dic) == 1) and (PyDict_Contains(dic,PyString_FromString(paramName.c_str()))))
return PyDict_GetItemString(dic,paramName.c_str());
return NULL;
}
} // Analog namespace.