Better handling of GDS sub-models, now put into separate library.
In order to better handle colliding cell names coming from multiple GDS files, now, if a topCell is defined, create a sub-library with the name of that top cell and put any other model from *that* GDS file into it. This way, only the top cell will be shown in the library and sub-cells with common names will be separateds. Work needed for loading GF180MCU I/O pads. * New: In Gds::setTopCellname(), specify the name of the top cell we specifically wants to load from the GDS file. * New: In GdsStream::getCell(), function to find/create a Cell in the current library and, if any, the "top cell" dedicated sub-library. * Change: In GdsStream::readTextBody(), if the layer material of the label is "other", do not create a Net with the name of the label. This should be a pure text label. Use the new Hurricane::Text Go for that. Compute the text box in a approximative way. Have to make it smarter in the future. * Change: In LefImport::_macroForeignCbk(), change of policy for loading associated GDS. First, we look if a cell with the right name exists, in which case we use it. If not, *only* then, do we try to load from GDS. This allows to load by ourselves, in a separate way the GDS. This is more flexible when there are naming issues. * New: Hurricane::Text Go class, to display text label without the need of a Net. * New: In Hurricane::CellWidget, add support to display Hurricane::Text. Add a new mode to drawDisplayText() : FillBox so the text is resized to exactly fill the box it is in (in width).
This commit is contained in:
parent
083d9fa7b2
commit
8dc13eab5b
|
@ -31,13 +31,20 @@ namespace CRL {
|
|||
|
||||
class Gds {
|
||||
public:
|
||||
static const uint32_t NoGdsPrefix = (1<<0);
|
||||
static const uint32_t Layer_0_IsBoundary = (1<<1);
|
||||
static const uint32_t NoBlockages = (1<<2);
|
||||
static const uint32_t NoGdsPrefix = (1<<0);
|
||||
static const uint32_t Layer_0_IsBoundary = (1<<1);
|
||||
static const uint32_t NoBlockages = (1<<2);
|
||||
static std::string _topCellName;
|
||||
public:
|
||||
static bool save ( Cell* );
|
||||
static bool load ( Library*, std::string gdsPath, uint32_t flags=0 );
|
||||
static bool save ( Cell* );
|
||||
static bool load ( Library*, std::string gdsPath, uint32_t flags=0 );
|
||||
inline static void setTopCellName ( std::string );
|
||||
inline static std::string getTopCellName ();
|
||||
};
|
||||
|
||||
|
||||
inline void Gds::setTopCellName ( std::string topCellName ) { _topCellName=topCellName; }
|
||||
inline std::string Gds::getTopCellName () { return _topCellName; }
|
||||
|
||||
|
||||
} // CRL namespace.
|
||||
|
|
|
@ -37,6 +37,7 @@ using namespace std;
|
|||
#include "hurricane/Diagonal.h"
|
||||
#include "hurricane/Rectilinear.h"
|
||||
#include "hurricane/Pad.h"
|
||||
#include "hurricane/Text.h"
|
||||
#include "hurricane/Net.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "hurricane/Library.h"
|
||||
|
@ -645,40 +646,41 @@ namespace {
|
|||
|
||||
class GdsStream {
|
||||
public:
|
||||
static const Layer* gdsToLayer ( uint16_t gdsLayer, uint16_t datatype );
|
||||
public:
|
||||
static void _staticInit ();
|
||||
GdsStream ( string gdsPath, uint32_t flags );
|
||||
inline bool useGdsPrefix () const;
|
||||
inline bool useLayer0AsBoundary () const;
|
||||
inline bool isValidSyntax () const;
|
||||
bool misplacedRecord ();
|
||||
inline void resetStrans ();
|
||||
bool read ( Library* );
|
||||
bool readFormatType ();
|
||||
bool readStructure ();
|
||||
const Layer* readLayerAndDatatype ();
|
||||
bool readBoundary ();
|
||||
bool readPath ();
|
||||
bool readSref ();
|
||||
bool readAref ();
|
||||
bool readNode ();
|
||||
bool readBox ();
|
||||
bool readText ();
|
||||
bool readTextbody ( const Layer* );
|
||||
bool readStrans ();
|
||||
bool readProperty ();
|
||||
void xyToAbutmentBox ();
|
||||
void xyToComponent ( const Layer* );
|
||||
void xyToPath ( uint16_t pathtype
|
||||
, const Layer*
|
||||
, DbU::Unit width
|
||||
, DbU::Unit bgnextn
|
||||
, DbU::Unit endextn );
|
||||
void makeInstances ();
|
||||
void makeExternals ();
|
||||
Net* fusedNet ();
|
||||
void addNetReference ( Net*, const Layer*, DbU::Unit x, DbU::Unit y );
|
||||
static const Layer* gdsToLayer ( uint16_t gdsLayer, uint16_t datatype );
|
||||
public:
|
||||
static void _staticInit ();
|
||||
GdsStream ( string gdsPath, uint32_t flags );
|
||||
Cell* getCell ( string cellName, bool create=false );
|
||||
inline bool useGdsPrefix () const;
|
||||
inline bool useLayer0AsBoundary () const;
|
||||
inline bool isValidSyntax () const;
|
||||
bool misplacedRecord ();
|
||||
inline void resetStrans ();
|
||||
bool read ( Library* );
|
||||
bool readFormatType ();
|
||||
bool readStructure ();
|
||||
const Layer* readLayerAndDatatype ();
|
||||
bool readBoundary ();
|
||||
bool readPath ();
|
||||
bool readSref ();
|
||||
bool readAref ();
|
||||
bool readNode ();
|
||||
bool readBox ();
|
||||
bool readText ();
|
||||
bool readTextbody ( const Layer* );
|
||||
bool readStrans ();
|
||||
bool readProperty ();
|
||||
void xyToAbutmentBox ();
|
||||
void xyToComponent ( const Layer* );
|
||||
void xyToPath ( uint16_t pathtype
|
||||
, const Layer*
|
||||
, DbU::Unit width
|
||||
, DbU::Unit bgnextn
|
||||
, DbU::Unit endextn );
|
||||
void makeInstances ();
|
||||
void makeExternals ();
|
||||
Net* fusedNet ();
|
||||
void addNetReference ( Net*, const Layer*, DbU::Unit x, DbU::Unit y );
|
||||
private:
|
||||
struct DelayedInstance {
|
||||
inline DelayedInstance ( Cell* owner, string masterName, const Transformation& );
|
||||
|
@ -800,6 +802,34 @@ namespace {
|
|||
}
|
||||
|
||||
|
||||
Cell* GdsStream::getCell ( string cellName, bool create )
|
||||
{
|
||||
if (not _library) return nullptr;
|
||||
Library* workLibrary = _library;
|
||||
Cell* cell = workLibrary->getCell( cellName );
|
||||
if (cell) return cell;
|
||||
|
||||
if (not Gds::getTopCellName().empty() and (cellName != Gds::getTopCellName())) {
|
||||
workLibrary = _library->getLibrary( Gds::getTopCellName() );
|
||||
if (workLibrary) {
|
||||
cell = workLibrary->getCell( cellName );
|
||||
if (cell) return cell;
|
||||
} else {
|
||||
if (not create) return nullptr;
|
||||
workLibrary = Library::create( _library, Gds::getTopCellName() );
|
||||
}
|
||||
}
|
||||
|
||||
if (not create) return nullptr;
|
||||
|
||||
cparanoid << Warning( "GdsStream::readStructure(): No Cell named \"%s\" in Library \"%s\" (created)."
|
||||
, cellName.c_str()
|
||||
, getString(_library).c_str()
|
||||
) << endl;
|
||||
return Cell::create( workLibrary, cellName );
|
||||
}
|
||||
|
||||
|
||||
bool GdsStream::misplacedRecord ()
|
||||
{
|
||||
cerr << Error( "GdsStream: Misplaced record %s.\n"
|
||||
|
@ -900,17 +930,9 @@ namespace {
|
|||
if (_record.isSTRNAME()) {
|
||||
if (_library) {
|
||||
string cellName = _record.getName();
|
||||
if (useGdsPrefix()) cellName.insert( 0, "gds_" );
|
||||
_cell = _library->getCell( cellName );
|
||||
if (not _cell) {
|
||||
cparanoid << Warning( "GdsStream::readStructure(): No Cell named \"%s\" in Library \"%s\" (created)."
|
||||
, cellName.c_str()
|
||||
, getString(_library).c_str()
|
||||
) << endl;
|
||||
_cell = Cell::create( _library, cellName );
|
||||
}
|
||||
_cell = getCell( cellName, true );
|
||||
_stream >> _record;
|
||||
}
|
||||
_stream >> _record;
|
||||
}
|
||||
|
||||
if (_record.isSTRCLASS()) { _stream >> _record; }
|
||||
|
@ -1075,15 +1097,25 @@ namespace {
|
|||
}
|
||||
|
||||
if (not _text.empty()) {
|
||||
Net* net = _cell->getNet( _text );
|
||||
if (not net) {
|
||||
net = Net::create( _cell, _text );
|
||||
net->setExternal( true );
|
||||
if (_text.substr(0,3) == "vdd") net->setType ( Net::Type::POWER );
|
||||
if (_text.substr(0,3) == "gnd") net->setType ( Net::Type::GROUND );
|
||||
if (_text[ _text.size()-1 ] == '!') net->setGlobal( true );
|
||||
if (static_cast<const BasicLayer*>(layer)->getMaterial() != BasicLayer::Material::other) {
|
||||
Net* net = _cell->getNet( _text );
|
||||
if (not net) {
|
||||
net = Net::create( _cell, _text );
|
||||
net->setExternal( true );
|
||||
if (_text.substr(0,3) == "vdd") net->setType ( Net::Type::POWER );
|
||||
if (_text.substr(0,3) == "gnd") net->setType ( Net::Type::GROUND );
|
||||
if (_text[ _text.size()-1 ] == '!') net->setGlobal( true );
|
||||
}
|
||||
addNetReference( net, layer, xpos, ypos );
|
||||
} else {
|
||||
DbU::Unit textHeight = _scale * 500;
|
||||
DbU::Unit textWidth = _scale * 500 * _text.size();
|
||||
Text::create( _cell, layer, Box( xpos
|
||||
, ypos
|
||||
, xpos + textWidth
|
||||
, ypos + textHeight
|
||||
), _text );
|
||||
}
|
||||
addNetReference( net, layer, xpos, ypos );
|
||||
}
|
||||
|
||||
cdebug_log(101,-1) << "GdsStream::readTextbody() - return:" << _validSyntax << endl;
|
||||
|
@ -1260,7 +1292,6 @@ namespace {
|
|||
// << " XR:" << _xReflection << " angle:" << _angle
|
||||
// << " " << Transformation(xpos,ypos,orient)
|
||||
// << " in " << _cell << endl;
|
||||
if (useGdsPrefix()) masterName.insert( 0, "gds_" );
|
||||
_delayedInstances.push_back( DelayedInstance( _cell
|
||||
, masterName
|
||||
, Transformation(xpos,ypos,orient)) );
|
||||
|
@ -1698,7 +1729,7 @@ namespace {
|
|||
cdebug_log(101,1) << "GdsStream::makeInstances(): " << endl;
|
||||
|
||||
for ( const DelayedInstance& di : _delayedInstances ) {
|
||||
Cell* masterCell = _library->getCell( di._masterName );
|
||||
Cell* masterCell = getCell( di._masterName );
|
||||
|
||||
if (masterCell) {
|
||||
string insName = "sref_" + getString(_SREFCount++);
|
||||
|
@ -1710,6 +1741,9 @@ namespace {
|
|||
, Instance::PlacementStatus::FIXED
|
||||
);
|
||||
cdebug_log(101,0) << "| " << instance << " @" << di._transformation << " in " << di._owner << endl;
|
||||
} else {
|
||||
cerr << Error( "GdsStream::makeInstances(): Delayed sub-model (STRUCTURE) \"%s\" not found."
|
||||
, di._masterName.c_str() ) << endl;
|
||||
}
|
||||
}
|
||||
cdebug_tabw(101,-1);
|
||||
|
@ -1840,6 +1874,10 @@ namespace CRL {
|
|||
// -------------------------------------------------------------------
|
||||
// Class : "CRL::Gds".
|
||||
|
||||
|
||||
std::string Gds::_topCellName = "";
|
||||
|
||||
|
||||
bool Gds::load ( Library* library, string gdsPath, uint32_t flags )
|
||||
{
|
||||
//DebugSession::open( 101, 110 );
|
||||
|
@ -1856,6 +1894,7 @@ namespace CRL {
|
|||
|
||||
Contact::enableCheckMinSize();
|
||||
UpdateSession::close();
|
||||
Gds::setTopCellName( "" );
|
||||
//DebugSession::close();
|
||||
|
||||
return true;
|
||||
|
|
|
@ -357,7 +357,9 @@ namespace {
|
|||
if (not _cell) {
|
||||
if (name.empty())
|
||||
name = "EarlyLEFCell";
|
||||
_cell = Cell::create( getLibrary(true), name );
|
||||
_cell = getLibrary(true)->getCell( name );
|
||||
if (not _cell)
|
||||
_cell = Cell::create( getLibrary(true), name );
|
||||
}
|
||||
return _cell;
|
||||
}
|
||||
|
@ -533,20 +535,25 @@ namespace {
|
|||
{
|
||||
LefParser* parser = (LefParser*)ud;
|
||||
|
||||
if (_gdsForeignDirectory.empty()) {
|
||||
cerr << Warning( "LefParser::_macroForeignCbk(): GDS directory *not* set, ignoring FOREIGN statement." ) << endl;
|
||||
return 0;
|
||||
Cell* cell = parser->earlyGetCell( foreign->cellName() );
|
||||
|
||||
if (cell->getName() == "EarlyLEFCell") {
|
||||
if (_gdsForeignDirectory.empty()) {
|
||||
cerr << Warning( "LefParser::_macroForeignCbk(): GDS directory *not* set, ignoring FOREIGN statement." ) << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
string gdsPath = _gdsForeignDirectory + "/" + foreign->cellName() + ".gds";
|
||||
parser->setForeignPath( gdsPath );
|
||||
|
||||
Gds::setTopCellName( foreign->cellName() );
|
||||
Gds::load( parser->getLibrary(), parser->getForeignPath()
|
||||
, Gds::NoBlockages|Gds::Layer_0_IsBoundary);
|
||||
}
|
||||
|
||||
string gdsPath = _gdsForeignDirectory + "/" + foreign->cellName() + ".gds";
|
||||
parser->setForeignPath( gdsPath );
|
||||
parser->setForeignPosition( Point( parser->fromUnitsMicrons( foreign->px() )
|
||||
, parser->fromUnitsMicrons( foreign->px() )));
|
||||
|
||||
Cell* cell = parser->earlyGetCell( foreign->cellName() );
|
||||
|
||||
Gds::load( parser->getLibrary(), parser->getForeignPath()
|
||||
, Gds::NoGdsPrefix|Gds::NoBlockages|Gds::Layer_0_IsBoundary);
|
||||
for ( Net* net : cell->getNets() ) {
|
||||
if (net->isPower ()) parser->setGdsPower ( net );
|
||||
if (net->isGround()) parser->setGdsGround( net );
|
||||
|
|
|
@ -63,7 +63,6 @@ extern "C" {
|
|||
static PyObject* PyGds_save ( PyObject*, PyObject* args )
|
||||
{
|
||||
cdebug_log(30,0) << "PyGds_save()" << endl;
|
||||
|
||||
HTRY
|
||||
PyObject* pyCell = NULL;
|
||||
if (PyArg_ParseTuple( args, "O:Gds.save", &pyCell )) {
|
||||
|
@ -78,7 +77,6 @@ extern "C" {
|
|||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
@ -86,10 +84,8 @@ extern "C" {
|
|||
static PyObject* PyGds_load ( PyObject*, PyObject* args )
|
||||
{
|
||||
cdebug_log(30,0) << "PyGds_load()" << endl;
|
||||
|
||||
char* path = NULL;
|
||||
uint32_t flags = 0;
|
||||
|
||||
HTRY
|
||||
PyObject* pyLibrary = NULL;
|
||||
if (PyArg_ParseTuple( args, "Os|I:Gds.load", &pyLibrary, &path, &flags )) {
|
||||
|
@ -104,7 +100,23 @@ extern "C" {
|
|||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyObject* PyGds_setTopCellName ( PyObject*, PyObject* args )
|
||||
{
|
||||
cdebug_log(30,0) << "PyGds_setTopCellName()" << endl;
|
||||
char* topCellName = NULL;
|
||||
HTRY
|
||||
PyObject* pyLibrary = NULL;
|
||||
if (PyArg_ParseTuple( args, "s:Gds.setTopCellName", &topCellName )) {
|
||||
Gds::setTopCellName( string(topCellName) );
|
||||
} else {
|
||||
PyErr_SetString( ConstructorError, "Gds.setTopCellName(): Takes *one* str argument only." );
|
||||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
@ -113,10 +125,12 @@ extern "C" {
|
|||
|
||||
|
||||
PyMethodDef PyGds_Methods[] =
|
||||
{ { "save" , (PyCFunction)PyGds_save , METH_VARARGS|METH_STATIC
|
||||
{ { "save" , (PyCFunction)PyGds_save , METH_VARARGS|METH_STATIC
|
||||
, "Save a complete Gds design." }
|
||||
, { "load" , (PyCFunction)PyGds_load , METH_VARARGS|METH_STATIC
|
||||
, { "load" , (PyCFunction)PyGds_load , METH_VARARGS|METH_STATIC
|
||||
, "Load a Gds layout inside a Cell (cumulative)." }
|
||||
, { "setTopCellName" , (PyCFunction)PyGds_setTopCellName, METH_VARARGS|METH_STATIC
|
||||
, "The name of the main cell from the GDS (not to be renamed)." }
|
||||
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
@ -140,6 +154,7 @@ extern "C" {
|
|||
{
|
||||
PyObject* constant;
|
||||
LoadObjectConstant(PyTypeGds.tp_dict,Gds::NoGdsPrefix ,"NoGdsPrefix");
|
||||
LoadObjectConstant(PyTypeGds.tp_dict,Gds::NoBlockages ,"NoBlockages");
|
||||
LoadObjectConstant(PyTypeGds.tp_dict,Gds::Layer_0_IsBoundary,"Layer_0_IsBoundary");
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
hurricane/Filter.h
|
||||
hurricane/Go.h hurricane/Gos.h
|
||||
hurricane/ExtensionGo.h hurricane/ExtensionGos.h
|
||||
hurricane/Text.h
|
||||
hurricane/Hook.h hurricane/Hooks.h
|
||||
hurricane/Horizontal.h hurricane/Horizontals.h
|
||||
hurricane/HyperNet.h
|
||||
|
@ -163,6 +164,7 @@
|
|||
DeepNet.cpp
|
||||
HyperNet.cpp
|
||||
Go.cpp
|
||||
Text.cpp
|
||||
ExtensionGo.cpp
|
||||
Hook.cpp
|
||||
Instance.cpp
|
||||
|
|
|
@ -204,7 +204,7 @@ Instance::Instance(Cell* cell, const Name& name, Cell* masterCell, const Transfo
|
|||
throw Error("Instance::Instance(): Can't create " + _TName("Instance") + ", empty name");
|
||||
|
||||
if (_cell->getInstance(_name))
|
||||
throw Error("Instance::Instance(): Can't create " + _TName("Instance") + " " + getString(_name) + ", already exists");
|
||||
throw Error("Instance::Instance(): Can't create " + _TName("Instance") + " " + getString(_name) + ", already exists in " + getString(cell) );
|
||||
|
||||
if (!_masterCell)
|
||||
throw Error("Instance::Instance(): Can't create " + _TName("Instance") + ", NULL master cell");
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// Copyright (c) BULL S.A. 2018-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 MERCHAN-
|
||||
// TABILITY 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/>.
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | H U R R I C A N E |
|
||||
// | V L S I B a c k e n d D a t a - B a s e |
|
||||
// | |
|
||||
// | Authors : Jean-Paul Chaput |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./Text.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include "hurricane/DataBase.h"
|
||||
#include "hurricane/Technology.h"
|
||||
#include "hurricane/Slice.h"
|
||||
#include "hurricane/Text.h"
|
||||
#include "hurricane/Net.h"
|
||||
#include "hurricane/BasicLayer.h"
|
||||
#include "hurricane/Layer.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "hurricane/Error.h"
|
||||
#include "hurricane/Warning.h"
|
||||
|
||||
|
||||
namespace Hurricane {
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Text".
|
||||
|
||||
Text::Text ( Cell* cell, const Layer* layer, const Box& boundingBox, std::string text )
|
||||
: Super ()
|
||||
, _cell (cell)
|
||||
, _layer (layer)
|
||||
, _boundingBox(boundingBox)
|
||||
, _text (text)
|
||||
{ }
|
||||
|
||||
|
||||
Text* Text::create ( Cell* cell, const Layer* layer, const Box& boundingBox, std::string text )
|
||||
{
|
||||
if (not layer)
|
||||
throw Error( "Text::create(): Can't create, NULL layer" );
|
||||
|
||||
Text* goText = new Text ( cell, layer, boundingBox, text );
|
||||
goText->_postCreate();
|
||||
|
||||
return goText;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Cell* Text::getCell () const { return _cell; }
|
||||
const Layer* Text::getLayer () const { return _layer; }
|
||||
DbU::Unit Text::getX () const { return getBoundingBox().getCenter().getX(); }
|
||||
DbU::Unit Text::getY () const { return getBoundingBox().getCenter().getY(); }
|
||||
|
||||
|
||||
Box Text::getBoundingBox() const
|
||||
{ return _boundingBox; }
|
||||
|
||||
|
||||
Box Text::getBoundingBox ( const BasicLayer* basicLayer ) const
|
||||
{
|
||||
if (not _layer->contains(basicLayer)) return Box();
|
||||
return getBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
void Text::translate ( const DbU::Unit& dx, const DbU::Unit& dy )
|
||||
{
|
||||
if ( (dx != 0) or (dy != 0) ) {
|
||||
invalidate( true );
|
||||
_boundingBox.translate( dx, dy );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Text::setLayer ( const Layer* layer )
|
||||
{
|
||||
if (not layer) throw Error( "Text::setLayer(): Can't set layer, NULL layer" );
|
||||
|
||||
if (layer != _layer) {
|
||||
invalidate( false );
|
||||
_layer = layer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Text::materialize()
|
||||
{
|
||||
cdebug_log(18,0) << "Text::materialize() - " << this << endl;
|
||||
|
||||
if (isMaterialized()) return;
|
||||
|
||||
Cell* cell = getCell();
|
||||
const Layer* layer = getLayer();
|
||||
if (not cell or not layer) return;
|
||||
|
||||
Slice* slice = cell->getSlice( layer );
|
||||
if (not slice) slice = Slice::_create( cell, layer );
|
||||
QuadTree* quadTree = slice->_getQuadTree();
|
||||
quadTree->insert( this );
|
||||
cell->_fit( quadTree->getBoundingBox() );
|
||||
}
|
||||
|
||||
|
||||
void Text::unmaterialize()
|
||||
{
|
||||
cdebug_log(18,0) << "Text::unmaterialize() " << this << endl;
|
||||
|
||||
if (not isMaterialized()) return;
|
||||
Cell* cell = getCell();
|
||||
Slice* slice = cell->getSlice(getLayer());
|
||||
if (not slice) return;
|
||||
|
||||
cell->_unfit(getBoundingBox());
|
||||
slice->_getQuadTree()->remove(this);
|
||||
if (slice->isEmpty()) slice->_destroy();
|
||||
}
|
||||
|
||||
string Text::_getTypeName () const
|
||||
{ return _TName( "Text" ); }
|
||||
|
||||
|
||||
string Text::_getString () const
|
||||
{
|
||||
string s = Super::_getString();
|
||||
s.insert( s.length() - 1, " " + getString(_layer->getName()) );
|
||||
s.insert( s.length() - 1, " \"" + _text + "\"" );
|
||||
s.insert( s.length() - 1, " @" + getString(_boundingBox) );
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
Record* Text::_getRecord () const
|
||||
{
|
||||
Record* record = Super::_getRecord();
|
||||
if (record) {
|
||||
record->add( getSlot("_cell" , _cell ) );
|
||||
record->add( getSlot("_layer" , _layer ) );
|
||||
record->add( getSlot("_boundinBox", &_boundingBox) );
|
||||
record->add( getSlot("_text" , _text ) );
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
} // Hurricane namespace.
|
|
@ -0,0 +1,83 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// Copyright (c) BULL S.A. 2018-2023, 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 MERCHAN-
|
||||
// TABILITY 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/>.
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | H U R R I C A N E |
|
||||
// | V L S I B a c k e n d D a t a - B a s e |
|
||||
// | |
|
||||
// | Authors : Jean-Paul Chaput |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./hurricane/Text.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
#pragma once
|
||||
#include "hurricane/Component.h"
|
||||
|
||||
|
||||
namespace Hurricane {
|
||||
|
||||
class Layer;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Text".
|
||||
|
||||
class Text : public Go {
|
||||
public:
|
||||
typedef Go Super;
|
||||
|
||||
public:
|
||||
static Text* create ( Cell*, const Layer*, const Box&, std::string );
|
||||
// Accessors.
|
||||
virtual Cell* getCell () const;
|
||||
virtual DbU::Unit getX () const;
|
||||
virtual DbU::Unit getY () const;
|
||||
virtual Box getBoundingBox () const;
|
||||
virtual Box getBoundingBox ( const BasicLayer* ) const;
|
||||
inline std::string getText () const;
|
||||
// Mutators.
|
||||
void setLayer ( const Layer* );
|
||||
const Layer* getLayer () const;
|
||||
virtual void translate ( const DbU::Unit& dx, const DbU::Unit& dy );
|
||||
virtual void materialize ();
|
||||
virtual void unmaterialize ();
|
||||
// Hurricane management.
|
||||
virtual string _getTypeName () const;
|
||||
virtual string _getString () const;
|
||||
virtual Record* _getRecord () const;
|
||||
protected:
|
||||
Text ( Cell*, const Layer*, const Box&, std::string );
|
||||
private:
|
||||
Cell* _cell;
|
||||
const Layer* _layer;
|
||||
Box _boundingBox;
|
||||
std::string _text;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline std::string Text::getText () const { return _text; }
|
||||
|
||||
|
||||
} // Hurricane namespace.
|
||||
|
||||
|
||||
INSPECTOR_P_SUPPORT(Hurricane::Text);
|
|
@ -45,6 +45,7 @@
|
|||
#include "hurricane/Polygon.h"
|
||||
#include "hurricane/RoutingPad.h"
|
||||
#include "hurricane/ExtensionGo.h"
|
||||
#include "hurricane/Text.h"
|
||||
|
||||
#include "hurricane/viewer/Graphics.h"
|
||||
#include "hurricane/viewer/PaletteItem.h"
|
||||
|
@ -721,6 +722,18 @@ namespace Hurricane {
|
|||
_cellWidget->drawDisplayText( rectangle, netName, BigFont|Bold|Center|Frame );
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const Text* text = dynamic_cast<const Text*>(go);
|
||||
if (text) {
|
||||
_goCount++;
|
||||
Box bb = transformation.getBox(text->getBoundingBox(basicLayer));
|
||||
rectangle = _cellWidget->dbuToScreenRect( bb );
|
||||
if ((rectangle.width() < 5) or (rectangle.height() < 5))
|
||||
return;
|
||||
_cellWidget->drawDisplayText( rectangle, text->getText().c_str(), FillBox|Left );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1388,7 +1401,6 @@ namespace Hurricane {
|
|||
for ( BasicLayer* layer : _technology->getBasicLayers() ) {
|
||||
_drawingPlanes.setPen ( Graphics::getPen (layer->getName(),getDarkening()) );
|
||||
_drawingPlanes.setBrush( Graphics::getBrush(layer->getName(),getDarkening()) );
|
||||
|
||||
if ( isDrawable(layer->getName()) ) {
|
||||
_drawingQuery.setBasicLayer( layer );
|
||||
_drawingQuery.setFilter ( getQueryFilter().unset(Query::DoMasterCells
|
||||
|
@ -1698,67 +1710,84 @@ namespace Hurricane {
|
|||
|
||||
void CellWidget::drawDisplayText ( const QRect& box, const char* text, unsigned int flags )
|
||||
{
|
||||
QFont font = Graphics::getNormalFont(flags&Bold);
|
||||
shared_ptr<QFont> font = shared_ptr<QFont>( new QFont( Graphics::getNormalFont( flags&Bold )));
|
||||
|
||||
if ( flags & BigFont ) font.setPointSize ( Graphics::isHighDpi() ? 7 : 18 );
|
||||
if (flags & BigFont)
|
||||
font->setPointSize( Graphics::isHighDpi() ? 7 : 18 );
|
||||
if (flags & FillBox) {
|
||||
QFontMetrics metrics = QFontMetrics( *font );
|
||||
float width = (float)metrics.width( text );
|
||||
float ptSize = font->pointSizeF();
|
||||
ptSize *= ((float)box.width() / width);
|
||||
font->setPointSizeF( ptSize );
|
||||
}
|
||||
|
||||
QFontMetrics metrics = QFontMetrics(font);
|
||||
QFontMetrics metrics = QFontMetrics( *font );
|
||||
int width = metrics.width( text );
|
||||
//int height = metrics.height ();
|
||||
//int height = metrics.height();
|
||||
int angle = 0;
|
||||
|
||||
if ( (width > box.width()) and (box.height() > 2*box.width()) )
|
||||
angle = -90;
|
||||
|
||||
drawDisplayText ( box.center(), text, flags, angle );
|
||||
QPoint textBL ( box.center() );
|
||||
if (flags & Top) {
|
||||
textBL.ry() += box.height() / 2;
|
||||
}
|
||||
if (flags & Left) {
|
||||
textBL.rx() -= box.width() / 2;
|
||||
}
|
||||
|
||||
drawDisplayText( textBL, text, flags, angle, font );
|
||||
}
|
||||
|
||||
|
||||
void CellWidget::drawDisplayText ( const QPoint& point, const char* text, unsigned int flags, int angle )
|
||||
void CellWidget::drawDisplayText ( const QPoint& point, const char* text, unsigned int flags, int angle, shared_ptr<QFont> font )
|
||||
{
|
||||
QPainter& painter = _drawingPlanes.painter();
|
||||
QPen pen = painter.pen ();
|
||||
QBrush brush = painter.brush ();
|
||||
QFont font = Graphics::getNormalFont(flags&Bold);
|
||||
QPainter& painter = _drawingPlanes.painter();
|
||||
QPen pen = painter.pen();
|
||||
QBrush brush = painter.brush();
|
||||
|
||||
if (not font.get())
|
||||
font = shared_ptr<QFont>( new QFont( Graphics::getNormalFont( flags&Bold )));
|
||||
|
||||
painter.save();
|
||||
if ( flags & Reverse ) painter.setPen ( Graphics::getPen("background") );
|
||||
if ( flags & Reverse ) painter.setBackgroundMode ( Qt::OpaqueMode );
|
||||
if ( flags & BigFont ) font.setPointSize ( Graphics::isHighDpi() ? 7 : 18 );
|
||||
if (flags & Reverse) painter.setPen( Graphics::getPen("background") );
|
||||
if (flags & Reverse) painter.setBackgroundMode( Qt::OpaqueMode );
|
||||
|
||||
QFontMetrics metrics = QFontMetrics(font);
|
||||
int width = metrics.width ( text );
|
||||
int height = metrics.height ();
|
||||
QFontMetrics metrics = QFontMetrics ( *font );
|
||||
int width = metrics.width ( text );
|
||||
int height = metrics.height();
|
||||
|
||||
pen.setStyle ( Qt::SolidLine );
|
||||
pen.setColor ( painter.brush().color() );
|
||||
pen.setStyle( Qt::SolidLine );
|
||||
pen.setColor( painter.brush().color() );
|
||||
|
||||
brush.setStyle ( Qt::NoBrush );
|
||||
brush.setStyle( Qt::NoBrush );
|
||||
|
||||
painter.setPen ( pen );
|
||||
painter.setBrush ( brush );
|
||||
painter.setFont ( font );
|
||||
painter.translate ( point );
|
||||
painter.rotate ( angle );
|
||||
painter.setPen ( pen );
|
||||
painter.setBrush ( brush );
|
||||
painter.setFont ( *font );
|
||||
painter.translate( point );
|
||||
painter.rotate ( angle );
|
||||
|
||||
QPoint bottomLeft ( 0, 0);
|
||||
if ( flags & Center ) {
|
||||
if (flags & Center) {
|
||||
bottomLeft.rx() -= width /2;
|
||||
bottomLeft.ry() += height/2;
|
||||
} else if ( flags & Top ) {
|
||||
} else if (flags & Top) {
|
||||
bottomLeft.ry() += height;
|
||||
} else if ( flags & Left ) {
|
||||
} else if (flags & Left) {
|
||||
}
|
||||
|
||||
if ( flags & Frame ) {
|
||||
if ( flags & Rounded )
|
||||
painter.drawRoundedRect ( bottomLeft.x()-1, bottomLeft.y()-height, width+2, height, 8, 8 );
|
||||
if (flags & Frame) {
|
||||
if (flags & Rounded)
|
||||
painter.drawRoundedRect( bottomLeft.x()-1, bottomLeft.y()-height, width+2, height, 8, 8 );
|
||||
else
|
||||
painter.drawRect ( bottomLeft.x()-1, bottomLeft.y()-height, width+2, height );
|
||||
painter.drawRect( bottomLeft.x()-1, bottomLeft.y()-height, width+2, height );
|
||||
}
|
||||
|
||||
painter.drawText ( bottomLeft.x(), bottomLeft.y()-metrics.descent(), text );
|
||||
painter.restore ();
|
||||
painter.drawText( bottomLeft.x(), bottomLeft.y()-metrics.descent(), text );
|
||||
painter.restore ();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ namespace Hurricane {
|
|||
, Left =0x0040
|
||||
, Right =0x0080
|
||||
, Top =0x0100
|
||||
, FillBox =0x0200
|
||||
};
|
||||
enum Flag { NoFlags =0x0000
|
||||
, NoResetCommands=0x0001
|
||||
|
@ -193,7 +194,7 @@ namespace Hurricane {
|
|||
void drawRuler ( shared_ptr<Ruler> );
|
||||
void drawRulers ( QRect );
|
||||
void drawDisplayText ( const QRect& , const char*, unsigned int flags=0 );
|
||||
void drawDisplayText ( const QPoint&, const char*, unsigned int flags=0, int angle=0 );
|
||||
void drawDisplayText ( const QPoint&, const char*, unsigned int flags=0, int angle=0, std::shared_ptr<QFont> font=std::shared_ptr<QFont>() );
|
||||
void drawScreenPolygon ( const QPoint*, int count, size_t plane=PlaneId::Working );
|
||||
void drawScreenPolygon ( const QPolygon&, size_t plane=PlaneId::Working );
|
||||
void drawScreenLine ( const QPoint&, const QPoint&, size_t plane=PlaneId::Working, bool mode=true );
|
||||
|
|
Loading…
Reference in New Issue