447 lines
13 KiB
C++
447 lines
13 KiB
C++
// ****************************************************************************************************
|
|
// File: ./Occurrence.cpp
|
|
// Authors: R. Escassut
|
|
// Copyright (c) BULL S.A. 2000-2018, 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/>.
|
|
// ****************************************************************************************************
|
|
|
|
#include "hurricane/Occurrence.h"
|
|
#include "hurricane/Entity.h"
|
|
#include "hurricane/Cell.h"
|
|
#include "hurricane/SharedPath.h"
|
|
#include "hurricane/Property.h"
|
|
#include "hurricane/Quark.h"
|
|
#include "hurricane/Error.h"
|
|
|
|
namespace Hurricane {
|
|
|
|
|
|
|
|
// ****************************************************************************************************
|
|
// Occurrence implementation
|
|
// ****************************************************************************************************
|
|
|
|
Occurrence::Occurrence(const Entity* entity)
|
|
// *****************************************
|
|
: _entity(const_cast<Entity*>(entity))
|
|
, _sharedPath(NULL)
|
|
{
|
|
}
|
|
|
|
Occurrence::Occurrence(const Entity* entity, const Path& path)
|
|
// ***********************************************************
|
|
: _entity(const_cast<Entity*>(entity))
|
|
, _sharedPath(path._getSharedPath())
|
|
{
|
|
if (not _entity)
|
|
throw Error( "Occurrence::Occurrence(): NULL Entity." );
|
|
|
|
if (_sharedPath) {
|
|
if (_entity->getCell() != _sharedPath->getMasterCell())
|
|
throw Error( "Occurrence::Occurrence(): Entity incompatible with the path.\n"
|
|
" * Entity %s, master cell %s\n"
|
|
" * Path %s, master cell %s"
|
|
, getString(entity).c_str()
|
|
, getString(entity->getCell()).c_str()
|
|
, getString(path).c_str()
|
|
, getString(_sharedPath->getMasterCell()).c_str()
|
|
);
|
|
}
|
|
}
|
|
|
|
Occurrence::Occurrence(const Occurrence& occurrence)
|
|
// *********************************************
|
|
: _entity(occurrence._entity),
|
|
_sharedPath(occurrence._sharedPath)
|
|
{
|
|
}
|
|
|
|
Occurrence& Occurrence::operator=(const Occurrence& occurrence)
|
|
// ********************************************************
|
|
{
|
|
_entity = occurrence._entity;
|
|
_sharedPath = occurrence._sharedPath;
|
|
return *this;
|
|
}
|
|
|
|
bool Occurrence::operator==(const Occurrence& occurrence) const
|
|
// *********************************************************
|
|
{
|
|
return _entity && occurrence._entity &&
|
|
(_entity == occurrence._entity) &&
|
|
(_sharedPath == occurrence._sharedPath);
|
|
}
|
|
|
|
bool Occurrence::operator!=(const Occurrence& occurrence) const
|
|
// *********************************************************
|
|
{
|
|
return !_entity ||
|
|
!occurrence._entity ||
|
|
(_entity != occurrence._entity) ||
|
|
(_sharedPath != occurrence._sharedPath);
|
|
}
|
|
|
|
bool Occurrence::operator<(const Occurrence& occurrence) const
|
|
// ********************************************************
|
|
{
|
|
if (not _entity and not occurrence._entity) return false;
|
|
if (not _entity) return true;
|
|
if (not occurrence._entity) return false;
|
|
|
|
if (_entity->getId() < occurrence._entity->getId()) return true;
|
|
if (_entity->getId() > occurrence._entity->getId()) return false;
|
|
|
|
if (not _sharedPath and not occurrence._sharedPath) return false;
|
|
if (not _sharedPath) return true;
|
|
if (not occurrence._sharedPath) return false;
|
|
|
|
return _sharedPath->getHash() < occurrence._sharedPath->getHash();
|
|
|
|
//return ((_entity < occurrence._entity) or
|
|
// ((_entity == occurrence._entity) and (_sharedPath < occurrence._sharedPath)));
|
|
}
|
|
|
|
bool Occurrence::isBelowTerminalNetlist() const
|
|
// ********************************************
|
|
{
|
|
SharedPath* tail = _sharedPath;
|
|
while ( tail ) {
|
|
Instance* instance = tail->getHeadInstance();
|
|
tail = tail->getTailSharedPath();
|
|
|
|
if (tail and instance->isTerminalNetlist()) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Cell* Occurrence::getOwnerCell() const
|
|
// **********************************
|
|
{
|
|
if (!_entity) return NULL;
|
|
return (_sharedPath) ? _sharedPath->getOwnerCell() : _entity->getCell();
|
|
}
|
|
|
|
Cell* Occurrence::getMasterCell() const
|
|
// ***********************************
|
|
{
|
|
return (_entity) ? _entity->getCell() : NULL;
|
|
}
|
|
|
|
Property* Occurrence::getProperty(const Name& name) const
|
|
// *****************************************************
|
|
{
|
|
if (_entity) {
|
|
//DBo* quark = _getQuark();
|
|
Quark* quark = _getQuark();
|
|
if (quark) return quark->getProperty(name);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
Properties Occurrence::getProperties() const
|
|
// ****************************************
|
|
{
|
|
if (_entity) {
|
|
Quark* quark = _getQuark();
|
|
if (quark) return quark->getProperties();
|
|
}
|
|
return Properties();
|
|
}
|
|
|
|
Occurrence Occurrence::getNetOccurrence() const
|
|
// ********************************************
|
|
{
|
|
if (isValid()) {
|
|
Entity* entity = getEntity();
|
|
if (dynamic_cast<Net*>(entity)) return *this;
|
|
else {
|
|
Rubber* rubber = dynamic_cast<Rubber*>(entity);
|
|
if (rubber) return Occurrence(rubber->getNet(), getPath());
|
|
else {
|
|
Component* component = dynamic_cast<Component*>(entity);
|
|
if (component) return Occurrence(component->getNet(), getPath());
|
|
}
|
|
}
|
|
}
|
|
|
|
return Occurrence();
|
|
}
|
|
|
|
|
|
|
|
Box Occurrence::getBoundingBox() const
|
|
// **********************************
|
|
{
|
|
if (!_entity) return Box();
|
|
if (!_sharedPath) return _entity->getBoundingBox();
|
|
return _sharedPath->getTransformation().getBox(_entity->getBoundingBox());
|
|
}
|
|
|
|
Box Occurrence::getBoundingBox(const BasicLayer* basicLayer) const
|
|
// ***************************************************************
|
|
{
|
|
const Component* component = dynamic_cast<const Component*>(_entity);
|
|
if ( not component ) return getBoundingBox();
|
|
|
|
if (!_sharedPath) return component->getBoundingBox(basicLayer);
|
|
return _sharedPath->getTransformation().getBox(component->getBoundingBox(basicLayer));
|
|
}
|
|
|
|
bool Occurrence::hasProperty() const
|
|
// ********************************
|
|
{
|
|
return (_getQuark() != NULL);
|
|
}
|
|
|
|
void Occurrence::makeInvalid()
|
|
// **************************
|
|
{
|
|
_entity = NULL;
|
|
_sharedPath = NULL;
|
|
}
|
|
|
|
void Occurrence::put(Property* property)
|
|
// ************************************
|
|
{
|
|
if (!_entity)
|
|
throw Error("Can't put property : invalid occurrence");
|
|
|
|
if (!property)
|
|
throw Error("Can't put property : null property");
|
|
|
|
Quark* quark = _getQuark();
|
|
if (!quark) quark = Quark::_create(*this);
|
|
quark->put(property);
|
|
}
|
|
|
|
void Occurrence::remove(Property* property)
|
|
// ***************************************
|
|
{
|
|
if (!_entity)
|
|
throw Error("Can't remove property : invalid occurrence");
|
|
|
|
if (!property)
|
|
throw Error("Can't remove property : null property");
|
|
|
|
Quark* quark = _getQuark();
|
|
if (quark) quark->remove(property);
|
|
}
|
|
|
|
void Occurrence::removeProperty(const Name& name)
|
|
// *********************************************
|
|
{
|
|
if (!_entity)
|
|
throw Error("Can't remove property : invalid occurrence");
|
|
|
|
Quark* quark = _getQuark();
|
|
if (quark) quark->removeProperty(name);
|
|
}
|
|
|
|
void Occurrence::clearProperties()
|
|
// ******************************
|
|
{
|
|
Quark* quark = _getQuark();
|
|
if (quark) quark->destroy();
|
|
}
|
|
|
|
string Occurrence::_getString() const
|
|
// *********************************
|
|
{
|
|
string s = "<" + _TName("Occurrence");
|
|
if (_entity) {
|
|
s += " ";
|
|
s += getString(getOwnerCell());
|
|
s += ":";
|
|
if (_sharedPath) s += getString(_sharedPath->getName()) + ":";
|
|
s += getString(_entity);
|
|
}
|
|
s += ">";
|
|
return s;
|
|
}
|
|
|
|
string Occurrence::getCompactString() const
|
|
// ****************************************
|
|
{
|
|
string s = "<";
|
|
if (_entity) {
|
|
s += getString(getOwnerCell()->getName());
|
|
s += ":";
|
|
if (_sharedPath) s += getString(_sharedPath->getName()) + ":";
|
|
Instance* instance = dynamic_cast<Instance*>(_entity);
|
|
if (instance) {
|
|
s += "I."+getString(instance->getName());
|
|
} else {
|
|
Net* net = dynamic_cast<Net*>(_entity);
|
|
if (net) {
|
|
s += "N."+getString(net->getName());
|
|
} else {
|
|
s += getString(_entity);
|
|
}
|
|
}
|
|
}
|
|
s += ">";
|
|
return s;
|
|
}
|
|
|
|
void Occurrence::toJson(JsonWriter* w) const
|
|
// ******************************************
|
|
{
|
|
w->startObject();
|
|
jsonWrite( w, "@typename", "Occurrence" );
|
|
jsonWrite( w, "_path" , getPath().getJsonString(w->getFlags()) );
|
|
|
|
w->key( "_entity" );
|
|
if (not w->issetFlags(JsonWriter::DesignBlobMode)) {
|
|
getEntity()->toJsonSignature( w );
|
|
} else {
|
|
jsonWrite( w, getEntity()->getId() );
|
|
}
|
|
|
|
w->endObject();
|
|
}
|
|
|
|
Record* Occurrence::_getRecord() const
|
|
// ****************************
|
|
{
|
|
Record* record = NULL;
|
|
if (_entity) {
|
|
record = new Record(getString(this));
|
|
record->add(getSlot("Entity", _entity));
|
|
record->add(getSlot("SharedPath", _sharedPath));
|
|
Quark* quark = _getQuark();
|
|
if (quark) record->add(getSlot("Quark", quark));
|
|
}
|
|
return record;
|
|
}
|
|
|
|
//DBo* ...
|
|
Quark* Occurrence::_getQuark() const
|
|
// ********************************
|
|
{
|
|
return (_entity) ? _entity->_getQuark(_sharedPath) : NULL;
|
|
}
|
|
|
|
string Occurrence::getName() const
|
|
// *******************************
|
|
{
|
|
string description;
|
|
|
|
if (_sharedPath)
|
|
description=_sharedPath->getName()+SharedPath::getNameSeparator();
|
|
|
|
if (Plug* plug= dynamic_cast<Plug*>(_entity))
|
|
description += plug->getName();
|
|
else if (Pin* pin= dynamic_cast<Pin*>(_entity))
|
|
description += getString(pin->getName());
|
|
else if (Net* net= dynamic_cast<Net*>(_entity))
|
|
description += getString(net->getName());
|
|
else if (Cell* cell= dynamic_cast<Cell*>(_entity))
|
|
description += getString(cell->getName());
|
|
else if (Instance* instance= dynamic_cast<Instance*>(_entity))
|
|
description += getString(instance->getName());
|
|
else
|
|
description+= getString(_entity);
|
|
//throw Error("[Occurrence::getName] No Name for "+getString(_entity));
|
|
|
|
return description;
|
|
}
|
|
|
|
|
|
Initializer<JsonOccurrence> jsonOccurrenceInit ( 0 );
|
|
|
|
|
|
void JsonOccurrence::initialize()
|
|
// *******************************
|
|
{ JsonTypes::registerType( new JsonOccurrence (JsonWriter::RegisterMode) ); }
|
|
|
|
JsonOccurrence::JsonOccurrence(unsigned long flags)
|
|
// ************************************************
|
|
: JsonObject(flags)
|
|
{
|
|
add( ".Cell" , typeid(Cell*) );
|
|
add( "_path" , typeid(string) );
|
|
|
|
if (issetFlags(JsonWriter::DesignBlobMode)) {
|
|
add( "_entity", typeid(uint64_t) );
|
|
} else {
|
|
add( "_entity", typeid(Entity*) );
|
|
}
|
|
}
|
|
|
|
JsonOccurrence* JsonOccurrence::clone(unsigned long flags) const
|
|
// *************************************************************
|
|
{ return new JsonOccurrence ( flags ); }
|
|
|
|
string JsonOccurrence::getTypeName() const
|
|
// ***************************************
|
|
{ return "Occurrence"; }
|
|
|
|
void JsonOccurrence::toData(JsonStack& stack)
|
|
// ******************************************
|
|
{
|
|
check( stack, "JsonOccurrence::toData" );
|
|
|
|
Path path;
|
|
Entity* entity = NULL;
|
|
if (issetFlags(JsonWriter::DesignBlobMode)) {
|
|
entity = stack.getEntity<Entity*>( get<int64_t>(stack,"_entity") );
|
|
|
|
//Cell* cell = get<Cell*>( stack, ".Cell" );
|
|
Instance* instance = NULL;
|
|
char separator = SharedPath::getNameSeparator();
|
|
string pathIds = get<string>( stack, "_path" );
|
|
unsigned long id;
|
|
size_t dot = pathIds.find( separator );
|
|
|
|
if (dot != string::npos) {
|
|
id = stoul( pathIds.substr( 0, dot ) );
|
|
pathIds = pathIds.substr( dot+1 );
|
|
} else
|
|
id = stol( pathIds );
|
|
|
|
instance = stack.getEntity<Instance*>(id);
|
|
if (not instance)
|
|
throw Error( "JsonOccurrence::toData(): No Instance id:lu% (or not an Instance) in stack LUT.", id );
|
|
path = Path( instance );
|
|
|
|
while ( dot != string::npos ) {
|
|
dot = pathIds.find( separator );
|
|
if (dot != string::npos) {
|
|
id = stoul( pathIds.substr( 0, dot ) );
|
|
pathIds = pathIds.substr( dot+1 );
|
|
} else
|
|
id = stol( pathIds );
|
|
|
|
instance = stack.getEntity<Instance*>(id);
|
|
if (not instance)
|
|
throw Error( "JsonOccurrence::toData(): No Instance id:lu% (or not an Instance) in stack LUT.", id );
|
|
path = Path( path, instance );
|
|
}
|
|
} else {
|
|
entity = get<Entity*>(stack,"_entity");
|
|
path = Path( get<Cell*>(stack,".Cell"), get<string>(stack,"_path") );
|
|
}
|
|
|
|
Occurrence occurrence ( entity, path );
|
|
update( stack, occurrence );
|
|
}
|
|
|
|
} // End of Hurricane namespace.
|
|
|
|
|
|
// ****************************************************************************************************
|
|
// Copyright (c) BULL S.A. 2000-2018, All Rights Reserved
|
|
// ****************************************************************************************************
|