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.
This commit is contained in:
Jean-Paul Chaput 2021-03-15 23:57:15 +01:00
parent 11390867f1
commit 1b5327313a
7 changed files with 220 additions and 50 deletions

View File

@ -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;
}

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef CRL_TOOLBOX_H
#define CRL_TOOLBOX_H
#pragma once
#include <functional>
#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

View File

@ -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 <const Cell*,size_t,Entity::CompareById> CellMap;
typedef pair<const Cell*,size_t> 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<CellDepth>& getCellDepths () const;
private:
size_t computeDepth ( CellMap&, const Cell* );
private:
Cell::Flags _stopMask;
vector<CellDepth> _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::CellDepth>& 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<Plug*>( 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<Plug*>( 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<Cell*>( item.first ) );
}
}
} // End of CRL namespace.

View File

@ -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 */
};

View File

@ -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.

View File

@ -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__

View File

@ -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