coriolis/hurricane/src/hurricane/Cell.cpp

1763 lines
54 KiB
C++

// ****************************************************************************************************
// File: ./Cell.cpp
// Authors: R. Escassut
// Copyright (c) BULL S.A. 2000-2016, All Rights Reserved
//
// This file is part of Hurricane.
//
// Hurricane is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License as published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// Hurricane is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU
// General Public License for more details.
//
// You should have received a copy of the Lesser GNU General Public License along with Hurricane. If
// not, see <http://www.gnu.org/licenses/>.
// ****************************************************************************************************
//#define TEST_INTRUSIVESET
#include "hurricane/Warning.h"
#include "hurricane/SharedName.h"
#include "hurricane/DataBase.h"
#include "hurricane/Cell.h"
#include "hurricane/Library.h"
#include "hurricane/Instance.h"
#include "hurricane/Net.h"
#include "hurricane/Pin.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Contact.h"
#include "hurricane/Pad.h"
#include "hurricane/Layer.h"
#include "hurricane/Slice.h"
#include "hurricane/Rubber.h"
#include "hurricane/Marker.h"
#include "hurricane/Component.h"
#include "hurricane/UpdateSession.h"
#include "hurricane/Error.h"
#include "hurricane/JsonReader.h"
namespace Hurricane {
// ****************************************************************************************************
// UniquifyRelation implementation
// ****************************************************************************************************
const Name Cell::UniquifyRelation::_name = "Cell::UniquifyRelation";
Cell::UniquifyRelation::UniquifyRelation ( Cell* masterOwner )
: Relation (masterOwner)
, _duplicates(1)
{ }
Cell::UniquifyRelation* Cell::UniquifyRelation::create ( Cell* masterOwner )
{
UniquifyRelation* relation = new UniquifyRelation(masterOwner);
relation->_postCreate();
return relation;
}
void Cell::UniquifyRelation::_preDestroy ()
{
Relation::_preDestroy();
}
Cell::UniquifyRelation* Cell::UniquifyRelation::get ( const Cell* cell )
{
if (not cell)
throw Error( "Can't get Cell::UniquifyRelation : empty cell" );
Property* property = cell->getProperty( staticGetName() );
if (property) {
UniquifyRelation* relation = dynamic_cast<UniquifyRelation*>(property);
if (not relation )
throw Error ( "Bad Property type: Must be a UniquifyRelation" );
return relation;
}
return NULL;
}
Name Cell::UniquifyRelation::staticGetName () { return _name; }
Name Cell::UniquifyRelation::getName () const { return _name; }
string Cell::UniquifyRelation::_getTypeName () const { return "Cell::UniquifyRelation"; }
Name Cell::UniquifyRelation::getUniqueName ()
{
Cell* owner = dynamic_cast<Cell*>( getMasterOwner() );
ostringstream name;
name << getString(owner->getName()) << "_u" << setw(2) << setfill('0') << _duplicates++;
return Name(name.str());
}
string Cell::UniquifyRelation::getTrunkName ( Name name )
{
string trunk = getString(name);
size_t suffix = trunk.rfind( "_u" );
if (suffix != string::npos)
trunk = trunk.substr( 0, suffix );
return trunk;
}
Record* Cell::UniquifyRelation::_getRecord () const
{
Record* record = Relation::_getRecord();
if (record) {
record->add( getSlot( "_duplicates", &_duplicates ) );
}
return record;
}
bool Cell::UniquifyRelation::hasJson () const
{ return true; }
void Cell::UniquifyRelation::toJson ( JsonWriter* w, const DBo* owner ) const
{
w->startObject();
std::string tname = getString( staticGetName() );
if (getMasterOwner() == owner) {
jsonWrite( w, "@typename" , tname );
jsonWrite( w, "_refcount" , getOwners().getSize() );
jsonWrite( w, "_duplicates", _duplicates );
} else {
tname.insert( 0, "&" );
jsonWrite( w, "@typename", tname );
Cell* masterOwner = dynamic_cast<Cell*>( getMasterOwner() );
if (masterOwner) {
jsonWrite( w, "_masterOwner", masterOwner->getHierarchicalName() );
} else {
cerr << Error( "UniquifyRelation::toJson(): Master owner is not a Cell (%s)."
, getString(owner).c_str()
) << endl;
jsonWrite( w, "_masterOwner", "" );
}
}
w->endObject();
}
// ****************************************************************************************************
// UniquifyRelation::JsonProperty implementation
// ****************************************************************************************************
Initializer<Cell::UniquifyRelation::JsonProperty> jsonUniquifyRelationInit ( 10 );
Cell::UniquifyRelation::JsonProperty::JsonProperty ( unsigned long flags )
: JsonObject(flags)
{
add( "_refcount" , typeid(int64_t) );
add( "_duplicates", typeid(int64_t) );
}
string Cell::UniquifyRelation::JsonProperty::getTypeName () const
{ return getString(Cell::UniquifyRelation::staticGetName()); }
void Cell::UniquifyRelation::JsonProperty::initialize ()
{ JsonTypes::registerType( new Cell::UniquifyRelation::JsonProperty (JsonWriter::RegisterMode) ); }
Cell::UniquifyRelation::JsonProperty* Cell::UniquifyRelation::JsonProperty::clone ( unsigned long flags ) const
{ return new Cell::UniquifyRelation::JsonProperty ( flags ); }
void Cell::UniquifyRelation::JsonProperty::toData ( JsonStack& stack )
{
check( stack, "Cell::UniquifyRelation::JsonProperty::toData" );
DBo* dbo = stack.back_dbo();
unsigned int refcount = get<int64_t>( stack, "_refcount" );
unsigned int duplicates = get<int64_t>( stack, "_duplicates" );
UniquifyRelation* relation = NULL;
Cell* cell = dynamic_cast<Cell*>( dbo );
cdebug_log(19,0) << "topDBo:" << dbo << endl;
if (cell) {
relation = UniquifyRelation::get( cell );
if (not relation) {
string tag = cell->getHierarchicalName()+"::"+getString(UniquifyRelation::staticGetName());
relation = dynamic_cast<UniquifyRelation*>( SharedProperty::getOrphaned( tag ) );
if (not relation) {
relation = Cell::UniquifyRelation::create( cell );
SharedProperty::addOrphaned( tag, relation );
}
SharedProperty::refOrphaned( tag );
SharedProperty::countOrphaned( tag, refcount );
cell->put( relation );
}
relation->_setMasterOwner( cell );
relation->_setDuplicates ( duplicates );
}
update( stack, relation );
}
// ****************************************************************************************************
// UniquifyRelation::JsonPropertyRef implementation
// ****************************************************************************************************
Initializer<Cell::UniquifyRelation::JsonPropertyRef> jsonUniquifyRelationRefInit ( 10 );
Cell::UniquifyRelation::JsonPropertyRef::JsonPropertyRef ( unsigned long flags )
: JsonObject(flags)
{
add( "_masterOwner", typeid(string) );
}
string Cell::UniquifyRelation::JsonPropertyRef::getTypeName () const
{ return string("&")+getString(Cell::UniquifyRelation::staticGetName()); }
void Cell::UniquifyRelation::JsonPropertyRef::initialize ()
{ JsonTypes::registerType( new Cell::UniquifyRelation::JsonPropertyRef (JsonWriter::RegisterMode) ); }
Cell::UniquifyRelation::JsonPropertyRef* Cell::UniquifyRelation::JsonPropertyRef::clone ( unsigned long flags ) const
{ return new Cell::UniquifyRelation::JsonPropertyRef ( flags ); }
void Cell::UniquifyRelation::JsonPropertyRef::toData ( JsonStack& stack )
{
check( stack, "Cell::UniquifyRelation::JsonPropertyRef::toData" );
DBo* dbo = stack.back_dbo();
string masterName = get<string>( stack, "_masterOwner" );
UniquifyRelation* relation = NULL;
Cell* cell = dynamic_cast<Cell*>( dbo );
string tag = masterName+"::"+getString(UniquifyRelation::staticGetName());
if (cell) {
if (not relation) {
relation = dynamic_cast<UniquifyRelation*>( SharedProperty::getOrphaned( tag ) );
if (not relation) {
relation = Cell::UniquifyRelation::create( cell );
SharedProperty::addOrphaned( tag, relation );
}
}
if (relation) {
cell->put( relation );
SharedProperty::refOrphaned( tag );
}
}
update( stack, relation );
}
// ****************************************************************************************************
// SlavedsRelation implementation
// ****************************************************************************************************
const Name Cell::SlavedsRelation::_name = "Cell::SlavedsRelation";
Cell::SlavedsRelation::SlavedsRelation ( Cell* masterOwner )
: Relation (masterOwner)
{ }
Cell::SlavedsRelation* Cell::SlavedsRelation::create ( Cell* masterOwner )
{
SlavedsRelation* relation = new SlavedsRelation(masterOwner);
relation->_postCreate();
return relation;
}
void Cell::SlavedsRelation::_preDestroy ()
{
Relation::_preDestroy();
}
Cell::SlavedsRelation* Cell::SlavedsRelation::get ( const Cell* cell )
{
if (not cell)
throw Error( "Can't get Cell::SlavedsRelation : empty cell" );
Property* property = cell->getProperty( staticGetName() );
if (property) {
SlavedsRelation* relation = dynamic_cast<SlavedsRelation*>(property);
if (not relation )
throw Error ( "Bad Property type: Must be a SlavedsRelation" );
return relation;
}
return NULL;
}
Name Cell::SlavedsRelation::staticGetName () { return _name; }
Name Cell::SlavedsRelation::getName () const { return _name; }
string Cell::SlavedsRelation::_getTypeName () const { return "Cell::SlavedsRelation"; }
Record* Cell::SlavedsRelation::_getRecord () const
{
Record* record = Relation::_getRecord();
return record;
}
bool Cell::SlavedsRelation::hasJson () const
{ return true; }
void Cell::SlavedsRelation::toJson ( JsonWriter* w, const DBo* owner ) const
{
w->startObject();
std::string tname = getString( staticGetName() );
if (getMasterOwner() == owner) {
jsonWrite( w, "@typename" , tname );
jsonWrite( w, "_refcount" , getOwners().getSize() );
} else {
tname.insert( 0, "&" );
jsonWrite( w, "@typename", tname );
Cell* masterOwner = dynamic_cast<Cell*>( getMasterOwner() );
if (masterOwner) {
jsonWrite( w, "_masterOwner", masterOwner->getHierarchicalName() );
} else {
cerr << Error( "SlavedsRelation::toJson(): Master owner is not a Cell (%s)."
, getString(owner).c_str()
) << endl;
jsonWrite( w, "_masterOwner", "" );
}
}
w->endObject();
}
// ****************************************************************************************************
// SlavedsRelation::JsonProperty implementation
// ****************************************************************************************************
Initializer<Cell::SlavedsRelation::JsonProperty> jsonSlavedsRelationInit ( 10 );
Cell::SlavedsRelation::JsonProperty::JsonProperty ( unsigned long flags )
: JsonObject(flags)
{
add( "_refcount" , typeid(int64_t) );
}
string Cell::SlavedsRelation::JsonProperty::getTypeName () const
{ return getString(Cell::SlavedsRelation::staticGetName()); }
void Cell::SlavedsRelation::JsonProperty::initialize ()
{ JsonTypes::registerType( new Cell::SlavedsRelation::JsonProperty (JsonWriter::RegisterMode) ); }
Cell::SlavedsRelation::JsonProperty* Cell::SlavedsRelation::JsonProperty::clone ( unsigned long flags ) const
{ return new Cell::SlavedsRelation::JsonProperty ( flags ); }
void Cell::SlavedsRelation::JsonProperty::toData ( JsonStack& stack )
{
check( stack, "Cell::SlavedsRelation::JsonProperty::toData" );
DBo* dbo = stack.back_dbo();
unsigned int refcount = get<int64_t>( stack, "_refcount" );
SlavedsRelation* relation = NULL;
Cell* cell = dynamic_cast<Cell*>( dbo );
cdebug_log(19,0) << "topDBo:" << dbo << endl;
if (cell) {
relation = SlavedsRelation::get( cell );
if (not relation) {
string tag = cell->getHierarchicalName()+"::"+getString(SlavedsRelation::staticGetName());
relation = dynamic_cast<SlavedsRelation*>( SharedProperty::getOrphaned( tag ) );
if (not relation) {
relation = Cell::SlavedsRelation::create( cell );
SharedProperty::addOrphaned( tag, relation );
}
SharedProperty::refOrphaned( tag );
SharedProperty::countOrphaned( tag, refcount );
cell->put( relation );
}
relation->_setMasterOwner( cell );
}
update( stack, relation );
}
// ****************************************************************************************************
// SlavedsRelation::JsonPropertyRef implementation
// ****************************************************************************************************
Initializer<Cell::SlavedsRelation::JsonPropertyRef> jsonSlavedsRelationRefInit ( 10 );
Cell::SlavedsRelation::JsonPropertyRef::JsonPropertyRef ( unsigned long flags )
: JsonObject(flags)
{
add( "_masterOwner", typeid(string) );
}
string Cell::SlavedsRelation::JsonPropertyRef::getTypeName () const
{ return string("&")+getString(Cell::SlavedsRelation::staticGetName()); }
void Cell::SlavedsRelation::JsonPropertyRef::initialize ()
{ JsonTypes::registerType( new Cell::SlavedsRelation::JsonPropertyRef (JsonWriter::RegisterMode) ); }
Cell::SlavedsRelation::JsonPropertyRef* Cell::SlavedsRelation::JsonPropertyRef::clone ( unsigned long flags ) const
{ return new Cell::SlavedsRelation::JsonPropertyRef ( flags ); }
void Cell::SlavedsRelation::JsonPropertyRef::toData ( JsonStack& stack )
{
check( stack, "Cell::SlavedsRelation::JsonPropertyRef::toData" );
DBo* dbo = stack.back_dbo();
string masterName = get<string>( stack, "_masterOwner" );
SlavedsRelation* relation = NULL;
Cell* cell = dynamic_cast<Cell*>( dbo );
string tag = masterName+"::"+getString(SlavedsRelation::staticGetName());
if (cell) {
if (not relation) {
relation = dynamic_cast<SlavedsRelation*>( SharedProperty::getOrphaned( tag ) );
if (not relation) {
relation = Cell::SlavedsRelation::create( cell );
SharedProperty::addOrphaned( tag, relation );
}
}
if (relation) {
cell->put( relation );
SharedProperty::refOrphaned( tag );
}
}
update( stack, relation );
}
// ****************************************************************************************************
// Cell Slice related implementation
// ****************************************************************************************************
void Cell::_insertSlice ( ExtensionSlice* slice )
{
ExtensionSliceMap::iterator islice = _extensionSlices.find ( slice->getName() );
if ( islice != _extensionSlices.end() )
throw Error ( "Attempt to re-create ExtensionSlice %s in Cell %s."
, getString(slice->getName()).c_str()
, getString(slice->getCell()->getName()).c_str()
);
_extensionSlices.insert ( pair<Name,ExtensionSlice*>(slice->getName(),slice) );
}
void Cell::_removeSlice ( ExtensionSlice* slice )
{
ExtensionSliceMap::iterator islice = _extensionSlices.find ( slice->getName() );
if ( islice != _extensionSlices.end() ) {
_extensionSlices.erase ( islice );
}
}
ExtensionSlice* Cell::getExtensionSlice ( const Name& name ) const
{
ExtensionSliceMap::const_iterator islice = _extensionSlices.find ( name );
if ( islice != _extensionSlices.end() )
return islice->second;
return NULL;
}
ExtensionSlice::Mask Cell::getExtensionSliceMask ( const Name& name ) const
{
ExtensionSliceMap::const_iterator islice = _extensionSlices.find ( name );
if ( islice != _extensionSlices.end() )
return islice->second->getMask();
return 0;
}
// ****************************************************************************************************
// Cell implementation
// ****************************************************************************************************
Cell::Cell(Library* library, const Name& name)
// *******************************************
: Inherit(),
_library(library),
_name(name),
_shuntedPath(),
_instanceMap(),
_quadTree(new QuadTree()),
_slaveInstanceSet(),
_netMap(),
_sliceMap(new SliceMap()),
_extensionSlices(),
_markerSet(),
//_viewSet(),
_abutmentBox(),
_boundingBox(),
_nextOfLibraryCellMap(NULL),
_nextOfSymbolCellSet(NULL),
_slaveEntityMap(),
_observers(),
_flags(Flags::Terminal)
{
if (!_library)
throw Error("Can't create " + _TName("Cell") + " : null library");
if (name.isEmpty())
throw Error("Can't create " + _TName("Cell") + " : empty name");
if (_library->getCell(_name))
throw Error("Can't create " + _TName("Cell") + " " + getString(_name) + " : already exists");
}
Cell* Cell::create(Library* library, const Name& name)
// ***************************************************
{
Cell* cell = new Cell(library, name);
cell->_postCreate();
return cell;
}
Cell* Cell::fromJson(const string& filename)
// *****************************************
{
UpdateSession::open();
JsonReader reader ( JsonWriter::CellMode );
reader.parse( filename );
UpdateSession::close();
const JsonStack& stack = reader.getStack();
if (stack.rhas(".Cell")) return stack.as<Cell*>(".Cell");
return NULL;
}
Box Cell::getBoundingBox() const
// *****************************
{
if (_boundingBox.isEmpty()) {
Box& boundingBox = (Box&)_boundingBox;
boundingBox = _abutmentBox;
boundingBox.merge(_quadTree->getBoundingBox());
for_each_slice(slice, getSlices()) {
boundingBox.merge(slice->getBoundingBox());
end_for;
}
}
return _boundingBox;
}
bool Cell::isLeaf() const
// **********************
{
return _instanceMap.isEmpty();
}
bool Cell::isCalledBy(Cell* cell) const
// ************************************
{
for_each_instance(instance, cell->getInstances()) {
Cell* masterCell = instance->getMasterCell();
if (masterCell == this) return true;
if (isCalledBy(masterCell)) return true;
end_for;
}
return false;
}
bool Cell::isNetAlias ( const Name& name ) const
// *********************************************
{
NetAliasName key(name);
return _netAliasSet.find(&key) != _netAliasSet.end();
}
bool Cell::isUnique() const
// ************************
{
// ltrace(10) << "Cell::isUnique() " << this << endl;
// for ( Instance* instance : getSlaveInstances() ) {
// ltrace(10) << "| Slave instance:" << instance << endl;
// }
return getSlaveInstances().getSize() < 2;
}
bool Cell::isUniquified() const
// ****************************
{
UniquifyRelation* relation = UniquifyRelation::get( this );
return relation and (relation->getMasterOwner() != this);
}
bool Cell::isUniquifyMaster() const
// ********************************
{
UniquifyRelation* relation = UniquifyRelation::get( this );
return (not relation) or (relation->getMasterOwner() == this);
}
string Cell::getHierarchicalName () const
// **************************************
{
return getLibrary()->getHierarchicalName() + "." + getString(getName());
}
Entity* Cell::getEntity(const Signature& signature) const
// ******************************************************
{
if ( (signature.getType() == Signature::TypeContact )
or (signature.getType() == Signature::TypeHorizontal)
or (signature.getType() == Signature::TypeVertical )
or (signature.getType() == Signature::TypePad ) ) {
Net* net = getNet( signature.getName() );
if (not net) {
cerr << Error( "Cell::getEntity(): Cell %s do have Net %s, signature incoherency."
, getString(getName()).c_str()
, signature.getName().c_str() ) << endl;
return NULL;
}
cdebug_log(18,0) << "Cell::getEntity(): <" << getName() << ">, Net:<" << net->getName() << ">" << endl;
if (signature.getType() == Signature::TypeContact) {
cdebug_log(18,0) << "Looking in Contacts..." << endl;
for ( Contact* component : getComponents().getSubSet<Contact*>() ) {
cdebug_log(18,0) << "| " << component << endl;
if ( (component->getLayer () == signature.getLayer())
and (component->getDx () == signature.getDim(Signature::ContactDx))
and (component->getDy () == signature.getDim(Signature::ContactDy))
and (component->getWidth () == signature.getDim(Signature::ContactWidth))
and (component->getHeight() == signature.getDim(Signature::ContactHeight)) )
return component;
}
}
if (signature.getType() == Signature::TypeVertical) {
cdebug_log(18,0) << "Looking in Verticals..." << endl;
for ( Vertical* component : getComponents().getSubSet<Vertical*>() ) {
cdebug_log(18,0) << "| " << component << endl;
if ( (component->getLayer () == signature.getLayer())
and (component->getWidth () == signature.getDim(Signature::VerticalWidth))
and (component->getX () == signature.getDim(Signature::VerticalX))
and (component->getDySource() == signature.getDim(Signature::VerticalDySource))
and (component->getDyTarget() == signature.getDim(Signature::VerticalDyTarget)) )
return component;
}
}
if (signature.getType() == Signature::TypeHorizontal) {
cdebug_log(18,0) << "Looking in Horizontals..." << endl;
for ( Horizontal* component : getComponents().getSubSet<Horizontal*>() ) {
cdebug_log(18,0) << "| " << component << endl;
if ( (component->getLayer () == signature.getLayer())
and (component->getWidth () == signature.getDim(Signature::HorizontalWidth))
and (component->getY () == signature.getDim(Signature::HorizontalY))
and (component->getDxSource() == signature.getDim(Signature::HorizontalDxSource))
and (component->getDxTarget() == signature.getDim(Signature::HorizontalDxTarget)) )
return component;
}
}
if (signature.getType() == Signature::TypePad) {
cdebug_log(18,0) << "Looking in Pads..." << endl;
for ( Pad* component : getComponents().getSubSet<Pad*>() ) {
cdebug_log(18,0) << "| " << component << endl;
if ( (component->getLayer() == signature.getLayer())
and (component->getBoundingBox().getXMin() == signature.getDim(Signature::PadXMin))
and (component->getBoundingBox().getYMin() == signature.getDim(Signature::PadYMin))
and (component->getBoundingBox().getXMax() == signature.getDim(Signature::PadXMax))
and (component->getBoundingBox().getYMax() == signature.getDim(Signature::PadYMax)) )
return component;
}
}
cerr << Error( "Cell::getEntity(): Cannot find a Component of type %d matching Signature."
, signature.getType() ) << endl;
} else {
cerr << Error( "Cell::getEntity(): Signature type %d is unsupported yet."
, signature.getType() ) << endl;
}
return NULL;
}
Net* Cell::getNet ( const Name& name ) const
//******************************************
{
Net* net = _netMap.getElement(name);
if (net) return net;
NetAliasName key(name);
AliasNameSet::iterator ialias = _netAliasSet.find( &key );
if (ialias != _netAliasSet.end())
return (*ialias)->getNet();
return NULL;
}
void Cell::setName(const Name& name)
// *********************************
{
if (name != _name) {
if (name.isEmpty())
throw Error("Can't change " + _TName("Cell") + " name : empty name");
if (_library->getCell(name))
throw Error("Can't change " + _TName("Cell") + " name : already exists");
_library->_getCellMap()._remove(this);
_name = name;
_library->_getCellMap()._insert(this);
}
}
void Cell::setAbutmentBox(const Box& abutmentBox)
// ***********************************************
{
SlavedsRelation* slaveds = SlavedsRelation::get( this );
if (not slaveds or (this == slaveds->getMasterOwner())) {
_setAbutmentBox( abutmentBox );
if (getFlags().isset(Flags::SlavedAb)) return;
for ( Cell* slavedCell : SlavedsSet(this) )
slavedCell->_setAbutmentBox( abutmentBox );
} else {
cerr << Error( "Cell::setAbutmentBox(): Abutment box of \"%s\" is slaved to \"%s\"."
, getString(getName()).c_str()
, getString(static_cast<Cell*>(slaveds->getMasterOwner())->getName()).c_str()
) << endl;
}
}
void Cell::_setAbutmentBox(const Box& abutmentBox)
// ***********************************************
{
if (abutmentBox != _abutmentBox) {
if (not _abutmentBox.isEmpty() and
(abutmentBox.isEmpty() or not abutmentBox.contains(_abutmentBox)))
_unfit( _abutmentBox );
_abutmentBox = abutmentBox;
_fit( _abutmentBox );
}
}
DeepNet* Cell::getDeepNet ( Path path, const Net* leafNet ) const
// **************************************************************
{
if (not (_flags.isset(Flags::FlattenedNets))) return NULL;
Occurrence rootNetOccurrence ( getHyperNetRootNetOccurrence(Occurrence(leafNet,path)) );
forEach ( Net*, inet, getNets() ) {
DeepNet* deepNet = dynamic_cast<DeepNet*>( *inet );
if (not deepNet) continue;
Occurrence deepNetOccurrence = deepNet->getRootNetOccurrence();
if ( (rootNetOccurrence.getEntity() == deepNetOccurrence.getEntity())
and (rootNetOccurrence.getPath () == deepNetOccurrence.getPath ()) )
return deepNet;
}
return NULL;
}
void Cell::flattenNets(uint64_t flags)
// ***************************************
{
cdebug_log(18,0) << "Cell::flattenNets() flags:0x" << hex << flags << endl;
UpdateSession::open();
bool reFlatten = _flags.isset(Flags::FlattenedNets);
_flags |= Flags::FlattenedNets;
vector<HyperNet> hyperNets;
vector<HyperNet> topHyperNets;
for ( Occurrence occurrence : getHyperNetRootNetOccurrences() ) {
Net* net = static_cast<Net*>(occurrence.getEntity());
if (net->isClock() and (flags & Flags::NoClockFlatten)) continue;
HyperNet hyperNet ( occurrence );
if ( not occurrence.getPath().isEmpty() ) {
Net* duplicate = getNet( occurrence.getName() );
if (not duplicate) {
hyperNets.push_back( HyperNet(occurrence) );
} else {
if (not reFlatten)
cerr << Warning( "Cell::flattenNets(): In \"%s\", found duplicate: %s for %s."
, getString(duplicate->getCell()->getName()).c_str()
, getString(duplicate).c_str()
, getString(net).c_str()
) << endl;
}
continue;
}
bool hasRoutingPads = false;
for ( Component* component : net->getComponents() ) {
RoutingPad* rp = dynamic_cast<RoutingPad*>( component );
if (rp) {
// At least one RoutingPad is present: assumes that the net is already
// flattened (completly).
hasRoutingPads = true;
break;
}
}
if (hasRoutingPads) continue;
topHyperNets.push_back( HyperNet(occurrence) );
}
for ( size_t i=0 ; i<hyperNets.size() ; ++i ) {
DeepNet* deepNet = DeepNet::create( hyperNets[i] );
if (deepNet) deepNet->_createRoutingPads( flags );
}
for ( size_t i=0 ; i<topHyperNets.size() ; ++i ) {
Net* net = static_cast<Net*>(topHyperNets[i].getNetOccurrence().getEntity());
for ( Occurrence plugOccurrence : topHyperNets[i].getLeafPlugOccurrences() ) {
RoutingPad* rp = RoutingPad::create( net, plugOccurrence, RoutingPad::BiggestArea );
rp->materialize();
if (flags & Flags::WarnOnUnplacedInstances)
rp->isPlacedOccurrence( RoutingPad::ShowWarning );
}
for ( Component* component : net->getComponents() ) {
Pin* pin = dynamic_cast<Pin*>( component );
if (pin) {
RoutingPad::create( pin );
}
}
}
UpdateSession::close();
}
void Cell::createRoutingPadRings(uint64_t flags)
// *************************************************
{
flags &= Flags::MaskRings;
UpdateSession::open();
for ( Net* net : getNets() ) {
RoutingPad* previousRp = NULL;
bool buildRing = false;
if (net->isGlobal()) {
if ( (flags & Cell::Flags::BuildClockRings ) and net->isClock () ) buildRing = true;
else if ( (flags & Cell::Flags::BuildSupplyRings) and net->isSupply() ) buildRing = true;
} else {
buildRing = flags & Cell::Flags::BuildRings;
}
if (not buildRing) continue;
for ( Component* component : net->getComponents() ) {
if (dynamic_cast<Segment*>(component)) { buildRing = false; break; }
Plug* primaryPlug = dynamic_cast<Plug*>( component );
if (primaryPlug) {
if (not primaryPlug->getBodyHook()->getSlaveHooks().isEmpty()) {
cerr << "[ERROR] " << primaryPlug << "\n"
<< " has attached components, not managed yet." << endl;
} else {
primaryPlug->getBodyHook()->detach();
}
}
}
if (not buildRing) continue;
for ( RoutingPad* rp : net->getRoutingPads() ) {
if ( previousRp
and ( not rp ->getBodyHook()->isAttached()
or not previousRp->getBodyHook()->isAttached()) ) {
rp->getBodyHook()->attach( previousRp->getBodyHook() );
}
previousRp = rp;
}
}
UpdateSession::close();
}
Cell* Cell::getCloneMaster() const
// *******************************
{
UniquifyRelation* uniquify = UniquifyRelation::get( this );
if (not uniquify) return const_cast<Cell*>(this);
return dynamic_cast<Cell*>( uniquify->getMasterOwner() );
}
bool Cell::updatePlacedFlag()
// **************************
{
bool isPlaced = true;
for ( Instance* instance : getInstances() ) {
if (instance->getPlacementStatus() == Instance::PlacementStatus::UNPLACED) {
isPlaced = false;
break;
}
}
if (isPlaced) setFlags( Cell::Flags::Placed );
return isPlaced;
}
Cell* Cell::getClone()
// *******************
{
UpdateSession::open();
UniquifyRelation* uniquify = UniquifyRelation::get( this );
if (not uniquify) {
uniquify = UniquifyRelation::create( this );
}
Cell* clone = Cell::create( getLibrary(), uniquify->getUniqueName() );
clone->put ( uniquify );
clone->setTerminal ( isTerminal () );
clone->setFlattenLeaf( isFlattenLeaf () );
clone->setPad ( isPad () );
clone->setAbutmentBox( getAbutmentBox() );
for ( Net* inet : getNets() ) {
if (dynamic_cast<DeepNet*>(inet)) continue;
inet->getClone( clone );
}
bool isPlaced = true;
for ( Instance* iinstance : getInstances() ) {
if (iinstance->getClone(clone)->getPlacementStatus() == Instance::PlacementStatus::UNPLACED)
isPlaced = false;
}
if (isPlaced) clone->setFlags( Flags::Placed );
UpdateSession::close();
return clone;
}
void Cell::uniquify(unsigned int depth)
// ************************************
{
cdebug_log(18,1) << "Cell::uniquify() " << this << endl;
vector<DeepNet*> deepNets;
for ( DeepNet* deepNet : getNets().getSubSet<DeepNet*>() ) {
deepNets.push_back( deepNet );
}
while ( not deepNets.empty() ) {
deepNets.back()->destroy();
deepNets.pop_back();
}
vector<Instance*> toUniquify;
set<Cell*> masterCells;
for ( Instance* instance : getInstances() ) {
Cell* masterCell = instance->getMasterCell();
cdebug_log(18,0) << "| " << instance << endl;
if (masterCell->isTerminal()) continue;
if (masterCells.find(masterCell) == masterCells.end()) {
masterCells.insert( masterCell );
masterCell->updatePlacedFlag();
}
if ( (masterCell->getSlaveInstances().getSize() > 1) and not masterCell->isPlaced() ) {
toUniquify.push_back( instance );
}
}
for ( auto instance : toUniquify ) {
instance->uniquify();
masterCells.insert( instance->getMasterCell() );
}
if (depth > 0) {
for ( auto cell : masterCells )
cell->uniquify( depth-1 );
}
cdebug_tabw(18,-1);
cdebug_log(18,0) << "Cell::uniquify() END " << this << endl;
}
void Cell::materialize()
// *********************
{
if (_flags.isset(Flags::Materialized)) return;
cdebug_log(18,1) << "Cell::materialize() " << this << endl;
_flags |= Flags::Materialized;
for ( Instance* instance : getInstances() ) {
if ( instance->getPlacementStatus() != Instance::PlacementStatus::UNPLACED )
instance->materialize();
}
for ( Net* net : getNets () ) net ->materialize();
for ( Marker* marker : getMarkers() ) marker->materialize();
cdebug_tabw(18,-1);
}
void Cell::unmaterialize()
// ***********************
{
if (not _flags.isset(Flags::Materialized)) return;
_flags &= ~Flags::Materialized;
for ( Instance* instance : getInstances()) instance->unmaterialize();
for ( Net* net : getNets() ) net ->unmaterialize();
for ( Marker* marker : getMarkers() ) marker ->unmaterialize();
}
void Cell::slaveAbutmentBox ( Cell* topCell )
// ******************************************
{
if (_flags.isset(Flags::SlavedAb)) {
cerr << Error( "Cell::slaveAbutmentBox(): %s is already slaved, action cancelled."
, getString(this).c_str() ) << endl;
return;
}
if (not isUnique()) {
cerr << Error( "Cell::slaveAbutmentBox(): %s is *not* unique, action cancelled."
, getString(this).c_str() ) << endl;
return;
}
_slaveAbutmentBox( topCell );
}
void Cell::_slaveAbutmentBox ( Cell* topCell )
// *******************************************
{
if (not getAbutmentBox().isEmpty()) {
if ( (getAbutmentBox().getWidth() != topCell->getAbutmentBox().getWidth())
or (getAbutmentBox().getWidth() != topCell->getAbutmentBox().getWidth()) ) {
cerr << Warning( "Slaving abutment boxes of different sizes, fixed blocks may shift.\n"
" topCell: %s (AB:%s)\n"
" slave : %s (AB:%s)"
, getString(topCell->getName()).c_str()
, getString(topCell->getAbutmentBox()).c_str()
, getString(getName()).c_str()
, getString(getAbutmentBox()).c_str()
);
}
Transformation transf ( topCell->getAbutmentBox().getXMin() - getAbutmentBox().getXMin()
, topCell->getAbutmentBox().getYMin() - getAbutmentBox().getYMin() );
for ( Instance* instance : getInstances() ) {
if (instance->getPlacementStatus() != Instance::PlacementStatus::UNPLACED) {
Transformation instanceTransf = instance->getTransformation();
transf.applyOn( instanceTransf );
instance->setTransformation( instanceTransf );
}
}
}
_setAbutmentBox( topCell->getAbutmentBox() );
SlavedsRelation* slaveds = SlavedsRelation::get( topCell );
if (not slaveds) {
slaveds = SlavedsRelation::create( topCell );
}
put( slaveds );
_flags.set( Flags::SlavedAb );
//_changeQuadTree( topCell );
}
void Cell::_changeQuadTree ( Cell* topCell )
// *****************************************
{
bool isMaterialized = _flags.isset(Flags::Materialized);
unmaterialize();
if (topCell or _flags.isset(Flags::MergedQuadTree)) {
delete _sliceMap;
delete _quadTree;
if (topCell) {
_sliceMap = topCell->_getSliceMap();
_quadTree = topCell->_getQuadTree();
} else {
_sliceMap = new SliceMap();
_quadTree = new QuadTree();
}
}
if (isMaterialized) materialize();
}
void Cell::_postCreate()
// *********************
{
Inherit::_postCreate();
_library->_getCellMap()._insert(this);
}
void Cell::_preDestroy()
// ********************
{
notify( Flags::CellDestroyed );
while ( _slaveEntityMap.size() ) {
_slaveEntityMap.begin()->second->destroy();
}
Markers markers = getMarkers (); while ( markers .getFirst() ) markers .getFirst()->destroy();
Instances instances = getSlaveInstances(); while ( instances.getFirst() ) instances.getFirst()->destroy();
instances = getInstances (); while ( instances.getFirst() ) instances.getFirst()->destroy();
Nets nets = getNets();
while ( nets.getFirst() ) {
Net* net = nets.getFirst();
net->_getMainName().detachAll();
net->destroy();
}
for ( auto islave : _netAliasSet ) delete islave;
for ( Slice* slice : getSlices() ) slice->_destroy();
while ( not _extensionSlices.empty() ) _removeSlice( _extensionSlices.begin()->second );
if (not _flags.isset(Flags::MergedQuadTree)) {
delete _sliceMap;
delete _quadTree;
}
_library->_getCellMap()._remove( this );
Inherit::_preDestroy();
}
string Cell::_getString() const
// ****************************
{
string s = Inherit::_getString();
s.insert(s.length() - 1, " " + getString(_name));
return s;
}
Record* Cell::_getRecord() const
// ***********************
{
Record* record = Inherit::_getRecord();
if (record) {
record->add( getSlot("_library" , _library ) );
record->add( getSlot("_name" , &_name ) );
record->add( getSlot("_instances" , &_instanceMap ) );
record->add( getSlot("_quadTree" , _quadTree ) );
record->add( getSlot("_extensionSlices", &_extensionSlices ) );
record->add( getSlot("_slaveInstances" , &_slaveInstanceSet) );
record->add( getSlot("_netMap" , &_netMap ) );
record->add( getSlot("_netAliasSet" , &_netAliasSet ) );
record->add( getSlot("_pinMap" , &_pinMap ) );
record->add( getSlot("_sliceMap" , _sliceMap ) );
record->add( getSlot("_markerSet" , &_markerSet ) );
record->add( getSlot("_slaveEntityMap" , &_slaveEntityMap ) );
record->add( getSlot("_abutmentBox" , &_abutmentBox ) );
record->add( getSlot("_boundingBox" , &_boundingBox ) );
record->add( getSlot("_flags" , &_flags ) );
}
return record;
}
void Cell::_fit(const Box& box)
// ****************************
{
if (box.isEmpty()) return;
if (_boundingBox.isEmpty()) return;
if (_boundingBox.contains(box)) return;
_boundingBox.merge(box);
for ( Instance* iinstance : getSlaveInstances() ) {
iinstance->getCell()->_fit(iinstance->getTransformation().getBox(box));
}
}
void Cell::_unfit(const Box& box)
// ******************************
{
if (box.isEmpty()) return;
if (_boundingBox.isEmpty()) return;
if (!_boundingBox.isConstrainedBy(box)) return;
_boundingBox.makeEmpty();
for ( Instance* iinstance : getSlaveInstances() ) {
iinstance->getCell()->_unfit(iinstance->getTransformation().getBox(box));
}
}
void Cell::_addSlaveEntity(Entity* entity, Entity* slaveEntity)
// ************************************************************************
{
assert(entity->getCell() == this);
_slaveEntityMap.insert(pair<Entity*,Entity*>(entity,slaveEntity));
}
void Cell::_removeSlaveEntity(Entity* entity, Entity* slaveEntity)
// ***************************************************************************
{
assert(entity->getCell() == this);
pair<SlaveEntityMap::iterator,SlaveEntityMap::iterator>
bounds = _slaveEntityMap.equal_range(entity);
SlaveEntityMap::iterator it = bounds.first;
for(; it != bounds.second ; it++ ) {
if (it->second == slaveEntity) {
_slaveEntityMap.erase(it);
break;
}
}
}
void Cell::_getSlaveEntities(SlaveEntityMap::iterator& begin, SlaveEntityMap::iterator& end)
// *********************************************************************************************************
{
begin = _slaveEntityMap.begin();
end = _slaveEntityMap.end();
}
void Cell::_getSlaveEntities(Entity* entity, SlaveEntityMap::iterator& begin, SlaveEntityMap::iterator& end)
// *********************************************************************************************************
{
begin = _slaveEntityMap.lower_bound(entity);
end = _slaveEntityMap.upper_bound(entity);
}
void Cell::addObserver(BaseObserver* observer)
// *******************************************
{
_observers.addObserver(observer);
}
void Cell::removeObserver(BaseObserver* observer)
// **********************************************
{
_observers.removeObserver(observer);
}
void Cell::notify(unsigned flags)
// ******************************
{
_observers.notify(flags);
}
void Cell::_toJson(JsonWriter* writer) const
// *****************************************
{
Inherit::_toJson( writer );
jsonWrite( writer, "_library" , getLibrary()->getHierarchicalName() );
jsonWrite( writer, "_name" , getName() );
jsonWrite( writer, "_abutmentBox", &_abutmentBox );
}
void Cell::_toJsonCollections(JsonWriter* writer) const
// *****************************************
{
writer->setFlags( JsonWriter::CellObject );
jsonWrite( writer, "+instanceMap", getInstances() );
jsonWrite( writer, "+netMap" , getNets() );
Inherit::_toJsonCollections( writer );
writer->resetFlags( JsonWriter::CellObject );
}
// ****************************************************************************************************
// Cell::Flags implementation
// ****************************************************************************************************
Cell::Flags::Flags ( uint64_t flags)
: BaseFlags(flags)
{ }
Cell::Flags::~Flags ()
{ }
string Cell::Flags::_getTypeName () const
{ return _TName("Cell::Flags"); }
string Cell::Flags::_getString () const
{
if (not _flags) return "<NoFlags>";
string s = "<";
if (_flags & Pad ) { s += "Pad"; }
if (_flags & Terminal ) { if (s.size() > 1) s += "|"; s += "Terminal"; }
if (_flags & FlattenLeaf ) { if (s.size() > 1) s += "|"; s += "FlattenLeaf"; }
if (_flags & FlattenedNets) { if (s.size() > 1) s += "|"; s += "FlattenedNets"; }
if (_flags & Placed ) { if (s.size() > 1) s += "|"; s += "Placed"; }
if (_flags & Routed ) { if (s.size() > 1) s += "|"; s += "Routed"; }
if (_flags & SlavedAb ) { if (s.size() > 1) s += "|"; s += "SlavedAb"; }
if (_flags & Materialized ) { if (s.size() > 1) s += "|"; s += "Materialized"; }
s += ">";
return s;
}
// ****************************************************************************************************
// Cell::ClonedSet implementation
// ****************************************************************************************************
Cell::ClonedSet::Locator::Locator ( const Cell* cell )
: Hurricane::Locator<Cell*>()
, _dboLocator (NULL)
{
UniquifyRelation* uniquify = UniquifyRelation::get( cell );
if (uniquify) {
_dboLocator = uniquify->getSlaveOwners().getLocator();
}
}
Locator<Cell*>* Cell::ClonedSet::Locator::getClone () const
{ return new Locator(*this); }
Cell* Cell::ClonedSet::Locator::getElement () const
{ return (_dboLocator and _dboLocator->isValid())
? dynamic_cast<Cell*>(_dboLocator->getElement()) : NULL; }
bool Cell::ClonedSet::Locator::isValid () const
{ return (_dboLocator and _dboLocator->isValid()); }
void Cell::ClonedSet::Locator::progress ()
{
_dboLocator->progress();
}
string Cell::ClonedSet::Locator::_getString () const
{
string s = "<" + _TName("Cell::ClonedSet::Locator")
+ getString(getElement())
+ ">";
return s;
}
Collection<Cell*>* Cell::ClonedSet::getClone () const
{ return new ClonedSet(*this); }
Locator<Cell*>* Cell::ClonedSet::getLocator () const
{ return new Locator(_cell); }
string Cell::ClonedSet::_getString () const
{
string s = "<" + _TName("Cell_ClonedSet") + " "
+ getString(_cell->getName())
+ ">";
return s;
}
// ****************************************************************************************************
// Cell::SlavedsSet implementation
// ****************************************************************************************************
Cell::SlavedsSet::Locator::Locator ( const Cell* cell )
: Hurricane::Locator<Cell*>()
, _dboLocator (NULL)
{
SlavedsRelation* slaveds = SlavedsRelation::get( cell );
if (slaveds) {
_dboLocator = slaveds->getSlaveOwners().getLocator();
}
}
Locator<Cell*>* Cell::SlavedsSet::Locator::getClone () const
{ return new Locator(*this); }
Cell* Cell::SlavedsSet::Locator::getElement () const
{ return (_dboLocator and _dboLocator->isValid())
? dynamic_cast<Cell*>(_dboLocator->getElement()) : NULL; }
bool Cell::SlavedsSet::Locator::isValid () const
{ return (_dboLocator and _dboLocator->isValid()); }
void Cell::SlavedsSet::Locator::progress ()
{
_dboLocator->progress();
}
string Cell::SlavedsSet::Locator::_getString () const
{
string s = "<" + _TName("Cell::SlavedsSet::Locator")
+ getString(getElement())
+ ">";
return s;
}
Collection<Cell*>* Cell::SlavedsSet::getClone () const
{ return new SlavedsSet(*this); }
Locator<Cell*>* Cell::SlavedsSet::getLocator () const
{ return new Locator(_cell); }
string Cell::SlavedsSet::_getString () const
{
string s = "<" + _TName("Cell_SlavedsSet") + " "
+ getString(_cell->getName())
+ ">";
return s;
}
// ****************************************************************************************************
// Cell::InstanceMap implementation
// ****************************************************************************************************
Cell::InstanceMap::InstanceMap()
// *****************************
: Inherit()
{
}
Name Cell::InstanceMap::_getKey(Instance* instance) const
// ******************************************************
{
return instance->getName();
}
unsigned int Cell::InstanceMap::_getHashValue(Name name) const
// *******************************************************
{
return name._getSharedName()->getId() / 8;
}
Instance* Cell::InstanceMap::_getNextElement(Instance* instance) const
// *******************************************************************
{
return instance->_getNextOfCellInstanceMap();
}
void Cell::InstanceMap::_setNextElement(Instance* instance, Instance* nextInstance) const
// **************************************************************************************
{
instance->_setNextOfCellInstanceMap(nextInstance);
}
// ****************************************************************************************************
// Cell::SlaveInstanceSet implementation
// ****************************************************************************************************
Cell::SlaveInstanceSet::SlaveInstanceSet()
// ***************************************
: Inherit()
{
}
unsigned Cell::SlaveInstanceSet::_getHashValue(Instance* slaveInstance) const
// **************************************************************************
{
return slaveInstance->getId() / 8;
}
Instance* Cell::SlaveInstanceSet::_getNextElement(Instance* slaveInstance) const
// *****************************************************************************
{
return slaveInstance->_getNextOfCellSlaveInstanceSet();
}
void Cell::SlaveInstanceSet::_setNextElement(Instance* slaveInstance, Instance* nextSlaveInstance) const
// ****************************************************************************************************
{
slaveInstance->_setNextOfCellSlaveInstanceSet(nextSlaveInstance);
}
// ****************************************************************************************************
// Cell::NetMap implementation
// ****************************************************************************************************
Cell::NetMap::NetMap()
// *******************
: Inherit()
{
}
Name Cell::NetMap::_getKey(Net* net) const
// ***************************************
{
return net->getName();
}
unsigned Cell::NetMap::_getHashValue(Name name) const
// **************************************************
{
return (unsigned int)name._getSharedName()->getId() / 8;
}
Net* Cell::NetMap::_getNextElement(Net* net) const
// ***********************************************
{
return net->_getNextOfCellNetMap();
}
void Cell::NetMap::_setNextElement(Net* net, Net* nextNet) const
// *************************************************************
{
net->_setNextOfCellNetMap(nextNet);
}
// ****************************************************************************************************
// Cell::PinMap implementation
// ****************************************************************************************************
Cell::PinMap::PinMap()
// *******************
: Inherit()
{
}
Name Cell::PinMap::_getKey(Pin* pin) const
// ***************************************
{
return pin->getName();
}
unsigned Cell::PinMap::_getHashValue(Name name) const
// **************************************************
{
return (unsigned int)name._getSharedName()->getId() / 8;
}
Pin* Cell::PinMap::_getNextElement(Pin* pin) const
// ***********************************************
{
return pin->_getNextOfCellPinMap();
}
void Cell::PinMap::_setNextElement(Pin* pin, Pin* nextPin) const
// *************************************************************
{
pin->_setNextOfCellPinMap(nextPin);
}
// ****************************************************************************************************
// Cell::SliceMap implementation
// ****************************************************************************************************
Cell::SliceMap::SliceMap()
// ***********************
: Inherit()
{
}
const Layer* Cell::SliceMap::_getKey(Slice* slice) const
// *****************************************************
{
return slice->getLayer();
}
unsigned Cell::SliceMap::_getHashValue(const Layer* layer) const
// *************************************************************
{
return (unsigned int)layer->getMask() / 8;
}
Slice* Cell::SliceMap::_getNextElement(Slice* slice) const
// *******************************************************
{
return slice->_getNextOfCellSliceMap();
}
void Cell::SliceMap::_setNextElement(Slice* slice, Slice* nextSlice) const
// ***********************************************************************
{
slice->_setNextOfCellSliceMap(nextSlice);
};
// ****************************************************************************************************
// Cell::MarkerSet implementation
// ****************************************************************************************************
Cell::MarkerSet::MarkerSet()
// *************************
: Inherit()
{
}
unsigned Cell::MarkerSet::_getHashValue(Marker* marker) const
// **********************************************************
{
return (unsigned int)marker->getId() / 8;
}
Marker* Cell::MarkerSet::_getNextElement(Marker* marker) const
// ***********************************************************
{
return marker->_getNextOfCellMarkerSet();
}
void Cell::MarkerSet::_setNextElement(Marker* marker, Marker* nextMarker) const
// ****************************************************************************
{
marker->_setNextOfCellMarkerSet(nextMarker);
}
// ****************************************************************************************************
// JsonCell implementation
// ****************************************************************************************************
Initializer<JsonCell> jsonCellInitialize ( 10 );
JsonCell::JsonCell(unsigned long flags)
// ************************************
: JsonEntity(flags)
, _cell (NULL)
, _materializationState(Go::autoMaterializationIsDisabled())
{
remove( ".Cell" );
add( "_library" , typeid(string) );
add( "_name" , typeid(string) );
add( "_abutmentBox" , typeid(Box) );
add( "+instanceMap" , typeid(JsonArray) );
add( "+netMap" , typeid(JsonArray) );
Go::enableAutoMaterialization();
}
JsonCell::~JsonCell()
// ******************
{
cdebug_log(19,0) << "JsonCell::~JsonCell() " << _cell << endl;
Go::enableAutoMaterialization();
if (_cell) _cell->materialize();
if (_materializationState) Go::disableAutoMaterialization();
}
string JsonCell::getTypeName() const
// *********************************
{ return "Cell"; }
void JsonCell::initialize()
// *************************
{ JsonTypes::registerType( new JsonCell (JsonWriter::RegisterMode) ); }
JsonCell* JsonCell::clone(unsigned long flags) const
// *************************************************
{ return new JsonCell ( flags ); }
void JsonCell::toData(JsonStack& stack)
// ************************************
{
check( stack, "JsonCell::toData" );
presetId( stack );
Library* library = DataBase::getDB()->getLibrary( get<string>(stack,"_library")
, DataBase::CreateLib|DataBase::WarnCreateLib );
_cell = Cell::create( library, get<string>(stack,"_name") );
_cell->setAbutmentBox( stack.as<Box>("_abutmentBox") );
update( stack, _cell );
}
} // End of Hurricane namespace.
// ****************************************************************************************************
// Copyright (c) BULL S.A. 2000-2016, All Rights Reserved
// ****************************************************************************************************