From 1b5327313a32927d32ff60825aa3dbbc53427b3b Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Mon, 15 Mar 2021 23:57:15 +0100 Subject: [PATCH] Added Net direction checker/setter in CRL Core. * New: CRL::restoreNetsdirection() (in ToolBox) that checks the coherency of all Nets direction through a complete hierarchy of cells. Stops at Cells flagged "TerminalNetlist". Directions are rebuilt for all the Cells part of the hierarchy in a bottom up fashion. It is also checked that Nets have only one driver (we assume there is no three-state busses). To sort cells in hierarchical order (bottom up according to their depth), copy the DepthOrder class from the GDSII driver. Will unify them later. exported to the Python interface. * New: In cumulus/tools/blif2vst.py, add a call to restoreNetsdirection() before saving. --- crlcore/src/ccore/blif/BlifParser.cpp | 6 +- crlcore/src/ccore/crlcore/ToolBox.h | 7 +- crlcore/src/ccore/toolbox/ToolBox.cpp | 164 +++++++++++++++++++++++++- crlcore/src/pyCRL/PyCRL.cpp | 8 +- crlcore/src/pyCRL/PyToolBox.cpp | 46 ++++++-- crlcore/src/pyCRL/crlcore/PyToolBox.h | 28 ++--- cumulus/src/tools/blif2vst.py | 11 +- 7 files changed, 220 insertions(+), 50 deletions(-) diff --git a/crlcore/src/ccore/blif/BlifParser.cpp b/crlcore/src/ccore/blif/BlifParser.cpp index 4fa9d697..a3489863 100644 --- a/crlcore/src/ccore/blif/BlifParser.cpp +++ b/crlcore/src/ccore/blif/BlifParser.cpp @@ -553,7 +553,8 @@ namespace { net->setDirection( (Net::Direction::Code)direction ); if (isClock) net->setType( Net::Type::CLOCK ); - if (_cell->getName() == "sm0") cerr << "sm0 netPlug:" << name << endl; + // if (_cell->getName() == "ALU_dec19") + // cerr << "ALU_dec19 net create:" << direction << " " << net << endl; } else { net->addAlias( name ); if (isExternal) net->setExternal( true ); @@ -562,7 +563,8 @@ namespace { net->setDirection( (Net::Direction::Code)direction ); if (isClock) net->setType( Net::Type::CLOCK ); - if (_cell->getName() == "sm0") cerr << "sm0 netPlug:" << name << endl; + // if (_cell->getName() == "ALU_dec19") + // cerr << "ALU_dec19 net merge:" << direction << " " << net << endl; } return net; } diff --git a/crlcore/src/ccore/crlcore/ToolBox.h b/crlcore/src/ccore/crlcore/ToolBox.h index d3172396..fccaf815 100644 --- a/crlcore/src/ccore/crlcore/ToolBox.h +++ b/crlcore/src/ccore/crlcore/ToolBox.h @@ -14,9 +14,7 @@ // +-----------------------------------------------------------------+ -#ifndef CRL_TOOLBOX_H -#define CRL_TOOLBOX_H - +#pragma once #include #include "hurricane/Cell.h" #include "hurricane/Net.h" @@ -58,6 +56,7 @@ namespace CRL { void connectPlugHooks ( Cell* ); size_t getInstancesCount ( const Cell* cell ); void setNetsPosition ( Cell* ); + void restoreNetsDirection ( Cell* , Cell::Flags ); class NamingScheme { @@ -89,5 +88,3 @@ namespace CRL { } // CRL namespace. - -#endif // CRL_TOOLBOX_H diff --git a/crlcore/src/ccore/toolbox/ToolBox.cpp b/crlcore/src/ccore/toolbox/ToolBox.cpp index 1a219cb8..857ee604 100644 --- a/crlcore/src/ccore/toolbox/ToolBox.cpp +++ b/crlcore/src/ccore/toolbox/ToolBox.cpp @@ -18,6 +18,7 @@ #include "hurricane/Pin.h" #include "hurricane/Library.h" #include "hurricane/Net.h" +#include "hurricane/HyperNet.h" #include "hurricane/Cell.h" #include "hurricane/Instance.h" #include "hurricane/Segment.h" @@ -26,6 +27,7 @@ #include "hurricane/Warning.h" using namespace Hurricane; +#include "crlcore/Utilities.h" #include "crlcore/ToolBox.h" @@ -54,7 +56,70 @@ namespace { } -} // End of anonymous namespace. +// ------------------------------------------------------------------- +// Class : "::DepthOrder". + + class DepthOrder { + private: + typedef map CellMap; + typedef pair CellDepth; + + class CompareDepth { + public: + inline bool operator() ( const CellDepth& lhs, const CellDepth& rhs ); + }; + public: + DepthOrder ( const Cell*, Cell::Flags stopMask=Cell::Flags::NoFlags ); + inline const vector& getCellDepths () const; + private: + size_t computeDepth ( CellMap&, const Cell* ); + private: + Cell::Flags _stopMask; + vector _cellDepths; + }; + + + inline bool DepthOrder::CompareDepth::operator() ( const CellDepth& lhs, const CellDepth& rhs ) + { + if (lhs.second < rhs.second) return true; + if (lhs.second > rhs.second) return false; + return lhs.first->getId() < rhs.first->getId(); + } + + + inline const vector& DepthOrder::getCellDepths () const { return _cellDepths; } + + + DepthOrder::DepthOrder ( const Cell* top, Cell::Flags stopMask ) + : _stopMask (stopMask) + , _cellDepths() + { + CellMap cellMap; + + computeDepth( cellMap, top ); + + for ( auto element : cellMap ) _cellDepths.push_back( element ); + sort( _cellDepths.begin(), _cellDepths.end(), CompareDepth() ); + } + + + size_t DepthOrder::computeDepth ( CellMap& cellMap, const Cell* cell ) + { + auto ielement = cellMap.find( cell ); + if (ielement != cellMap.end()) return (*ielement).second; + + size_t depth = 0; + for ( const Instance* instance : cell->getInstances() ) { + if (not (instance->getMasterCell()->getFlags() & _stopMask)) { + depth = std::max( depth, computeDepth(cellMap,instance->getMasterCell()) + 1 ); + } + } + cellMap.insert( make_pair(cell,depth) ); + return depth; + } + + +} // Anonymous namespace. namespace CRL { @@ -562,4 +627,101 @@ void ConnectPlugHooks(Cell* cell) } + void _restoreNetsDirection ( Cell* cell ) + { + for ( Net* net : cell->getNets() ) { + if (not net->isExternal()) continue; + if (net->isSupply()) continue; + + size_t drivers = 0; + size_t sinks = 0; + for ( Plug* plug : net->getPlugs() ) { + Net* masterNet = plug->getMasterNet(); + Net::Direction direction = masterNet->getDirection(); + if (direction & Net::Direction::DirIn) { + sinks += 1; + } else { + if (direction & Net::Direction::DirOut) { + drivers += 1; + } + } + if ((direction & Net::Direction::INOUT) == Net::Direction::INOUT) { + cparanoid << Warning( "Net \"%s\" of cell \"%s\" has INOUT plug, considered as IN." + , getString(net->getName()).c_str() + , getString(cell->getName()).c_str() + ) << endl; + } + } + if ((drivers == 0) and (sinks == 0)) { + cparanoid << Warning( "Net \"%s\" of cell \"%s\" has neither driver nor sink, default as IN." + , getString(net->getName()).c_str() + , getString(cell->getName()).c_str() + ) << endl; + net->setDirection( Net::Direction::DirIn ); + continue; + } + Net::Direction direction = net->getDirection(); + if (drivers == 0) { + if (not (direction & Net::Direction::DirIn)) { + cerr << Warning( "In Cell \"%s\" restoring %s as input (d=%d, s=%d)." + , getString(cell->getName()).c_str() + , getString(net).c_str() + , drivers + , sinks + ) << endl; + net->setDirection( Net::Direction::DirIn ); + } + continue; + } + if (not (direction & Net::Direction::DirOut)) { + cerr << Warning( "In Cell \"%s\" restoring %s as output (d=%d, s=%d)." + , getString(cell->getName()).c_str() + , getString(net).c_str() + , drivers + , sinks + ) << endl; + net->setDirection( Net::Direction::DirOut ); + for ( Occurrence occurrence : HyperNet(Occurrence(net)).getComponentOccurrences() ) { + Plug* plug = dynamic_cast( occurrence.getEntity() ); + if (plug) { + cerr << " | " << occurrence.getPath().getCompactString(false) + << "." << plug->getInstance()->getName() + << ":" << plug->getMasterNet()->getName() + << " (" << plug->getMasterNet()->getCell()->getName() << ")" << endl; + } else { + cerr << " | " << occurrence << endl; + } + } + } + if (drivers > 1) { + cerr << Warning( "In Cell \"%s\", %s has more than one driver (%d)." + , getString(cell->getName()).c_str() + , getString(net).c_str() + , drivers + ) << endl; + for ( Occurrence occurrence : HyperNet(Occurrence(net)).getComponentOccurrences() ) { + Plug* plug = dynamic_cast( occurrence.getEntity() ); + if (plug) { + cerr << " | " << occurrence.getPath().getCompactString(false) + << "." << plug->getInstance()->getName() + << ":" << plug->getMasterNet()->getName() + << " (" << plug->getMasterNet()->getCell()->getName() << ")" << endl; + } else { + cerr << " | " << occurrence << endl; + } + } + } + } + } + + + void restoreNetsDirection ( Cell* topCell, Cell::Flags mask ) + { + DepthOrder cellOrder ( topCell, mask ); + for ( auto item : cellOrder.getCellDepths() ) { + _restoreNetsDirection( const_cast( item.first ) ); + } + } + + } // End of CRL namespace. diff --git a/crlcore/src/pyCRL/PyCRL.cpp b/crlcore/src/pyCRL/PyCRL.cpp index b9fc7c1c..084669aa 100644 --- a/crlcore/src/pyCRL/PyCRL.cpp +++ b/crlcore/src/pyCRL/PyCRL.cpp @@ -79,11 +79,9 @@ extern "C" { static PyObject* PyVhdl_destroyAllVHDL ( PyObject* module ) { cdebug_log(30,0) << "PyVhdl_destroyAllVHDL()" << endl; - HTRY EntityExtension::destroyAll(); HCATCH - Py_RETURN_NONE; } @@ -94,9 +92,11 @@ extern "C" { static PyMethodDef PyCRL_Methods[] = - { { "createPartRing" , (PyCFunction)PyToolBox_createPartRing, METH_VARARGS + { { "createPartRing" , (PyCFunction)PyToolBox_createPartRing , METH_VARARGS , "Partial build of a ring" } - , { "destroyAllVHDL" , (PyCFunction)PyVhdl_destroyAllVHDL, METH_NOARGS + , { "restoreNetsDirection", (PyCFunction)PyToolBox_restoreNetsDirection, METH_VARARGS + , "Compute and set nets direction of a complete cell hierarchy." } + , { "destroyAllVHDL" , (PyCFunction)PyVhdl_destroyAllVHDL , METH_NOARGS , "Clear all VHDL informations on all cells." } , {NULL, NULL, 0, NULL} /* sentinel */ }; diff --git a/crlcore/src/pyCRL/PyToolBox.cpp b/crlcore/src/pyCRL/PyToolBox.cpp index fc4eccae..c2ceeb8e 100644 --- a/crlcore/src/pyCRL/PyToolBox.cpp +++ b/crlcore/src/pyCRL/PyToolBox.cpp @@ -33,6 +33,7 @@ namespace CRL { using std::cerr; using std::endl; using std::hex; + using std::string; using std::ostringstream; using Hurricane::tab; using Hurricane::Exception; @@ -45,6 +46,8 @@ namespace CRL { using Isobar::HurricaneError; using Isobar::HurricaneWarning; using Isobar::getPyHash; + using Isobar::__cs; + using Isobar::Converter; using Isobar::ParseOneArg; using Isobar::ParseTwoArg; using Isobar::PyCell; @@ -72,21 +75,44 @@ extern "C" { extern PyObject* PyToolBox_createPartRing ( PyObject* module, PyObject* args ) { cdebug_log(30,0) << "PyToolBox_createPartRing ()" << endl; - HTRY - PyObject* arg0; - PyObject* arg1; - - if ( not ParseTwoArg ( "CRL.createPartRing", args, CELL_STRING_ARG, &arg0, &arg1 ) ) - return NULL; - - createPartRing ( PYCELL_O(arg0), PyString_AsString(arg1) ); - HCATCH - + PyObject* arg0; + PyObject* arg1; + if ( not ParseTwoArg( "CRL.createPartRing", args, CELL_STRING_ARG, &arg0, &arg1 ) ) + return NULL; + createPartRing( PYCELL_O(arg0), PyString_AsString(arg1) ); + HCATCH Py_RETURN_NONE; } + extern PyObject* PyToolBox_restoreNetsDirection ( PyObject* module, PyObject* args ) + { + cdebug_log(30,0) << "PyToolbox_restoreNetsDirection()" << endl; + HTRY + PyObject* arg0 = NULL; + PyObject* arg1 = NULL; + __cs.init( "CRL.restoreNetsDirection" ); + if (not PyArg_ParseTuple(args,"O&O&:CRL.restoreNetsDirection" + ,Converter,&arg0 + ,Converter,&arg1 + )) { + PyErr_SetString( ConstructorError, "CRL.restoreNetsDirection(): Takes exactly two parameters." ); + return NULL; + } + + if (__cs.getObjectIds() == ":ent:int") { + restoreNetsDirection( PYCELL_O(arg0), PyInt_AsLong(arg1) ); + } else { + string message = "CRL.restoreNetsDirection(): Bad type of parameter(s), \"" + __cs.getObjectIds() + "\"."; + PyErr_SetString( ConstructorError, message.c_str() ); + return NULL; + } + HCATCH + Py_RETURN_NONE; + } + + #endif // End of Shared Library Code Part. diff --git a/crlcore/src/pyCRL/crlcore/PyToolBox.h b/crlcore/src/pyCRL/crlcore/PyToolBox.h index ccceaaa0..9b0b2b7f 100644 --- a/crlcore/src/pyCRL/crlcore/PyToolBox.h +++ b/crlcore/src/pyCRL/crlcore/PyToolBox.h @@ -2,49 +2,35 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// Copyright (c) SU/LIP6 2010-2021, All Rights Reserved // -// =================================================================== -// -// $Id$ -// -// x-----------------------------------------------------------------x -// | | +// +-----------------------------------------------------------------+ // | C O R I O L I S | // | Alliance / Hurricane Interface | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Header : "./PyToolBox.h" | -// | *************************************************************** | -// | U p d a t e s | -// | | -// x-----------------------------------------------------------------x +// +-----------------------------------------------------------------+ -#ifndef __PY_CRL_TOOLBOX__ -#define __PY_CRL_TOOLBOX__ - +#pragma once #include "hurricane/isobar/PyHurricane.h" namespace CRL { - extern "C" { // ------------------------------------------------------------------- // Functions & Types exported to "PyCRL.ccp". - extern PyObject* PyToolBox_createPartRing ( PyObject* module, PyObject* args ); + extern PyObject* PyToolBox_createPartRing ( PyObject* module, PyObject* args ); + extern PyObject* PyToolBox_restoreNetsDirection ( PyObject* module, PyObject* args ); } // End of extern "C". - } // End of CRL namespace. - - -#endif // __PY_CRL_TOOLBOX__ diff --git a/cumulus/src/tools/blif2vst.py b/cumulus/src/tools/blif2vst.py index 2dea9c7c..73c1cb72 100755 --- a/cumulus/src/tools/blif2vst.py +++ b/cumulus/src/tools/blif2vst.py @@ -7,16 +7,12 @@ try: import optparse import helpers from helpers import showPythonTrace - from helpers.io import ErrorMessage - from helpers.io import catch + from helpers.io import ErrorMessage, catch helpers.loadUserSettings() import Cfg import Hurricane - from Hurricane import DbU - from Hurricane import UpdateSession - from Hurricane import Breakpoint - from Hurricane import Transformation - from Hurricane import Instance + from Hurricane import DbU, UpdateSession, Breakpoint, Transformation, \ + Cell, Instance import Viewer import CRL import plugins.rsave @@ -73,6 +69,7 @@ if __name__ == '__main__': print ' o Renaming RTLIL anonymous top cell "top" into "%s".' % options.cellName cell.setName( options.cellName ) renameNMigenUniquify( cell ) + CRL.restoreNetsDirection( cell, Cell.Flags_TerminalNetlist ) kw = {} kw['views'] = views