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 {
|
class Gds {
|
||||||
public:
|
public:
|
||||||
static const uint32_t NoGdsPrefix = (1<<0);
|
static const uint32_t NoGdsPrefix = (1<<0);
|
||||||
static const uint32_t Layer_0_IsBoundary = (1<<1);
|
static const uint32_t Layer_0_IsBoundary = (1<<1);
|
||||||
static const uint32_t NoBlockages = (1<<2);
|
static const uint32_t NoBlockages = (1<<2);
|
||||||
|
static std::string _topCellName;
|
||||||
public:
|
public:
|
||||||
static bool save ( Cell* );
|
static bool save ( Cell* );
|
||||||
static bool load ( Library*, std::string gdsPath, uint32_t flags=0 );
|
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.
|
} // CRL namespace.
|
||||||
|
|
|
@ -37,6 +37,7 @@ using namespace std;
|
||||||
#include "hurricane/Diagonal.h"
|
#include "hurricane/Diagonal.h"
|
||||||
#include "hurricane/Rectilinear.h"
|
#include "hurricane/Rectilinear.h"
|
||||||
#include "hurricane/Pad.h"
|
#include "hurricane/Pad.h"
|
||||||
|
#include "hurricane/Text.h"
|
||||||
#include "hurricane/Net.h"
|
#include "hurricane/Net.h"
|
||||||
#include "hurricane/Cell.h"
|
#include "hurricane/Cell.h"
|
||||||
#include "hurricane/Library.h"
|
#include "hurricane/Library.h"
|
||||||
|
@ -645,40 +646,41 @@ namespace {
|
||||||
|
|
||||||
class GdsStream {
|
class GdsStream {
|
||||||
public:
|
public:
|
||||||
static const Layer* gdsToLayer ( uint16_t gdsLayer, uint16_t datatype );
|
static const Layer* gdsToLayer ( uint16_t gdsLayer, uint16_t datatype );
|
||||||
public:
|
public:
|
||||||
static void _staticInit ();
|
static void _staticInit ();
|
||||||
GdsStream ( string gdsPath, uint32_t flags );
|
GdsStream ( string gdsPath, uint32_t flags );
|
||||||
inline bool useGdsPrefix () const;
|
Cell* getCell ( string cellName, bool create=false );
|
||||||
inline bool useLayer0AsBoundary () const;
|
inline bool useGdsPrefix () const;
|
||||||
inline bool isValidSyntax () const;
|
inline bool useLayer0AsBoundary () const;
|
||||||
bool misplacedRecord ();
|
inline bool isValidSyntax () const;
|
||||||
inline void resetStrans ();
|
bool misplacedRecord ();
|
||||||
bool read ( Library* );
|
inline void resetStrans ();
|
||||||
bool readFormatType ();
|
bool read ( Library* );
|
||||||
bool readStructure ();
|
bool readFormatType ();
|
||||||
const Layer* readLayerAndDatatype ();
|
bool readStructure ();
|
||||||
bool readBoundary ();
|
const Layer* readLayerAndDatatype ();
|
||||||
bool readPath ();
|
bool readBoundary ();
|
||||||
bool readSref ();
|
bool readPath ();
|
||||||
bool readAref ();
|
bool readSref ();
|
||||||
bool readNode ();
|
bool readAref ();
|
||||||
bool readBox ();
|
bool readNode ();
|
||||||
bool readText ();
|
bool readBox ();
|
||||||
bool readTextbody ( const Layer* );
|
bool readText ();
|
||||||
bool readStrans ();
|
bool readTextbody ( const Layer* );
|
||||||
bool readProperty ();
|
bool readStrans ();
|
||||||
void xyToAbutmentBox ();
|
bool readProperty ();
|
||||||
void xyToComponent ( const Layer* );
|
void xyToAbutmentBox ();
|
||||||
void xyToPath ( uint16_t pathtype
|
void xyToComponent ( const Layer* );
|
||||||
, const Layer*
|
void xyToPath ( uint16_t pathtype
|
||||||
, DbU::Unit width
|
, const Layer*
|
||||||
, DbU::Unit bgnextn
|
, DbU::Unit width
|
||||||
, DbU::Unit endextn );
|
, DbU::Unit bgnextn
|
||||||
void makeInstances ();
|
, DbU::Unit endextn );
|
||||||
void makeExternals ();
|
void makeInstances ();
|
||||||
Net* fusedNet ();
|
void makeExternals ();
|
||||||
void addNetReference ( Net*, const Layer*, DbU::Unit x, DbU::Unit y );
|
Net* fusedNet ();
|
||||||
|
void addNetReference ( Net*, const Layer*, DbU::Unit x, DbU::Unit y );
|
||||||
private:
|
private:
|
||||||
struct DelayedInstance {
|
struct DelayedInstance {
|
||||||
inline DelayedInstance ( Cell* owner, string masterName, const Transformation& );
|
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 ()
|
bool GdsStream::misplacedRecord ()
|
||||||
{
|
{
|
||||||
cerr << Error( "GdsStream: Misplaced record %s.\n"
|
cerr << Error( "GdsStream: Misplaced record %s.\n"
|
||||||
|
@ -900,17 +930,9 @@ namespace {
|
||||||
if (_record.isSTRNAME()) {
|
if (_record.isSTRNAME()) {
|
||||||
if (_library) {
|
if (_library) {
|
||||||
string cellName = _record.getName();
|
string cellName = _record.getName();
|
||||||
if (useGdsPrefix()) cellName.insert( 0, "gds_" );
|
_cell = getCell( cellName, true );
|
||||||
_cell = _library->getCell( cellName );
|
_stream >> _record;
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_stream >> _record;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_record.isSTRCLASS()) { _stream >> _record; }
|
if (_record.isSTRCLASS()) { _stream >> _record; }
|
||||||
|
@ -1075,15 +1097,25 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not _text.empty()) {
|
if (not _text.empty()) {
|
||||||
Net* net = _cell->getNet( _text );
|
if (static_cast<const BasicLayer*>(layer)->getMaterial() != BasicLayer::Material::other) {
|
||||||
if (not net) {
|
Net* net = _cell->getNet( _text );
|
||||||
net = Net::create( _cell, _text );
|
if (not net) {
|
||||||
net->setExternal( true );
|
net = Net::create( _cell, _text );
|
||||||
if (_text.substr(0,3) == "vdd") net->setType ( Net::Type::POWER );
|
net->setExternal( true );
|
||||||
if (_text.substr(0,3) == "gnd") net->setType ( Net::Type::GROUND );
|
if (_text.substr(0,3) == "vdd") net->setType ( Net::Type::POWER );
|
||||||
if (_text[ _text.size()-1 ] == '!') net->setGlobal( true );
|
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;
|
cdebug_log(101,-1) << "GdsStream::readTextbody() - return:" << _validSyntax << endl;
|
||||||
|
@ -1260,7 +1292,6 @@ namespace {
|
||||||
// << " XR:" << _xReflection << " angle:" << _angle
|
// << " XR:" << _xReflection << " angle:" << _angle
|
||||||
// << " " << Transformation(xpos,ypos,orient)
|
// << " " << Transformation(xpos,ypos,orient)
|
||||||
// << " in " << _cell << endl;
|
// << " in " << _cell << endl;
|
||||||
if (useGdsPrefix()) masterName.insert( 0, "gds_" );
|
|
||||||
_delayedInstances.push_back( DelayedInstance( _cell
|
_delayedInstances.push_back( DelayedInstance( _cell
|
||||||
, masterName
|
, masterName
|
||||||
, Transformation(xpos,ypos,orient)) );
|
, Transformation(xpos,ypos,orient)) );
|
||||||
|
@ -1698,7 +1729,7 @@ namespace {
|
||||||
cdebug_log(101,1) << "GdsStream::makeInstances(): " << endl;
|
cdebug_log(101,1) << "GdsStream::makeInstances(): " << endl;
|
||||||
|
|
||||||
for ( const DelayedInstance& di : _delayedInstances ) {
|
for ( const DelayedInstance& di : _delayedInstances ) {
|
||||||
Cell* masterCell = _library->getCell( di._masterName );
|
Cell* masterCell = getCell( di._masterName );
|
||||||
|
|
||||||
if (masterCell) {
|
if (masterCell) {
|
||||||
string insName = "sref_" + getString(_SREFCount++);
|
string insName = "sref_" + getString(_SREFCount++);
|
||||||
|
@ -1710,6 +1741,9 @@ namespace {
|
||||||
, Instance::PlacementStatus::FIXED
|
, Instance::PlacementStatus::FIXED
|
||||||
);
|
);
|
||||||
cdebug_log(101,0) << "| " << instance << " @" << di._transformation << " in " << di._owner << endl;
|
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);
|
cdebug_tabw(101,-1);
|
||||||
|
@ -1840,6 +1874,10 @@ namespace CRL {
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Class : "CRL::Gds".
|
// Class : "CRL::Gds".
|
||||||
|
|
||||||
|
|
||||||
|
std::string Gds::_topCellName = "";
|
||||||
|
|
||||||
|
|
||||||
bool Gds::load ( Library* library, string gdsPath, uint32_t flags )
|
bool Gds::load ( Library* library, string gdsPath, uint32_t flags )
|
||||||
{
|
{
|
||||||
//DebugSession::open( 101, 110 );
|
//DebugSession::open( 101, 110 );
|
||||||
|
@ -1856,6 +1894,7 @@ namespace CRL {
|
||||||
|
|
||||||
Contact::enableCheckMinSize();
|
Contact::enableCheckMinSize();
|
||||||
UpdateSession::close();
|
UpdateSession::close();
|
||||||
|
Gds::setTopCellName( "" );
|
||||||
//DebugSession::close();
|
//DebugSession::close();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -357,7 +357,9 @@ namespace {
|
||||||
if (not _cell) {
|
if (not _cell) {
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
name = "EarlyLEFCell";
|
name = "EarlyLEFCell";
|
||||||
_cell = Cell::create( getLibrary(true), name );
|
_cell = getLibrary(true)->getCell( name );
|
||||||
|
if (not _cell)
|
||||||
|
_cell = Cell::create( getLibrary(true), name );
|
||||||
}
|
}
|
||||||
return _cell;
|
return _cell;
|
||||||
}
|
}
|
||||||
|
@ -533,20 +535,25 @@ namespace {
|
||||||
{
|
{
|
||||||
LefParser* parser = (LefParser*)ud;
|
LefParser* parser = (LefParser*)ud;
|
||||||
|
|
||||||
if (_gdsForeignDirectory.empty()) {
|
Cell* cell = parser->earlyGetCell( foreign->cellName() );
|
||||||
cerr << Warning( "LefParser::_macroForeignCbk(): GDS directory *not* set, ignoring FOREIGN statement." ) << endl;
|
|
||||||
return 0;
|
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->setForeignPosition( Point( parser->fromUnitsMicrons( foreign->px() )
|
||||||
, 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() ) {
|
for ( Net* net : cell->getNets() ) {
|
||||||
if (net->isPower ()) parser->setGdsPower ( net );
|
if (net->isPower ()) parser->setGdsPower ( net );
|
||||||
if (net->isGround()) parser->setGdsGround( net );
|
if (net->isGround()) parser->setGdsGround( net );
|
||||||
|
|
|
@ -63,7 +63,6 @@ extern "C" {
|
||||||
static PyObject* PyGds_save ( PyObject*, PyObject* args )
|
static PyObject* PyGds_save ( PyObject*, PyObject* args )
|
||||||
{
|
{
|
||||||
cdebug_log(30,0) << "PyGds_save()" << endl;
|
cdebug_log(30,0) << "PyGds_save()" << endl;
|
||||||
|
|
||||||
HTRY
|
HTRY
|
||||||
PyObject* pyCell = NULL;
|
PyObject* pyCell = NULL;
|
||||||
if (PyArg_ParseTuple( args, "O:Gds.save", &pyCell )) {
|
if (PyArg_ParseTuple( args, "O:Gds.save", &pyCell )) {
|
||||||
|
@ -78,7 +77,6 @@ extern "C" {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
HCATCH
|
HCATCH
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,10 +84,8 @@ extern "C" {
|
||||||
static PyObject* PyGds_load ( PyObject*, PyObject* args )
|
static PyObject* PyGds_load ( PyObject*, PyObject* args )
|
||||||
{
|
{
|
||||||
cdebug_log(30,0) << "PyGds_load()" << endl;
|
cdebug_log(30,0) << "PyGds_load()" << endl;
|
||||||
|
|
||||||
char* path = NULL;
|
char* path = NULL;
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
|
||||||
HTRY
|
HTRY
|
||||||
PyObject* pyLibrary = NULL;
|
PyObject* pyLibrary = NULL;
|
||||||
if (PyArg_ParseTuple( args, "Os|I:Gds.load", &pyLibrary, &path, &flags )) {
|
if (PyArg_ParseTuple( args, "Os|I:Gds.load", &pyLibrary, &path, &flags )) {
|
||||||
|
@ -104,7 +100,23 @@ extern "C" {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
HCATCH
|
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;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,10 +125,12 @@ extern "C" {
|
||||||
|
|
||||||
|
|
||||||
PyMethodDef PyGds_Methods[] =
|
PyMethodDef PyGds_Methods[] =
|
||||||
{ { "save" , (PyCFunction)PyGds_save , METH_VARARGS|METH_STATIC
|
{ { "save" , (PyCFunction)PyGds_save , METH_VARARGS|METH_STATIC
|
||||||
, "Save a complete Gds design." }
|
, "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)." }
|
, "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 */
|
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -140,6 +154,7 @@ extern "C" {
|
||||||
{
|
{
|
||||||
PyObject* constant;
|
PyObject* constant;
|
||||||
LoadObjectConstant(PyTypeGds.tp_dict,Gds::NoGdsPrefix ,"NoGdsPrefix");
|
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");
|
LoadObjectConstant(PyTypeGds.tp_dict,Gds::Layer_0_IsBoundary,"Layer_0_IsBoundary");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
hurricane/Filter.h
|
hurricane/Filter.h
|
||||||
hurricane/Go.h hurricane/Gos.h
|
hurricane/Go.h hurricane/Gos.h
|
||||||
hurricane/ExtensionGo.h hurricane/ExtensionGos.h
|
hurricane/ExtensionGo.h hurricane/ExtensionGos.h
|
||||||
|
hurricane/Text.h
|
||||||
hurricane/Hook.h hurricane/Hooks.h
|
hurricane/Hook.h hurricane/Hooks.h
|
||||||
hurricane/Horizontal.h hurricane/Horizontals.h
|
hurricane/Horizontal.h hurricane/Horizontals.h
|
||||||
hurricane/HyperNet.h
|
hurricane/HyperNet.h
|
||||||
|
@ -163,6 +164,7 @@
|
||||||
DeepNet.cpp
|
DeepNet.cpp
|
||||||
HyperNet.cpp
|
HyperNet.cpp
|
||||||
Go.cpp
|
Go.cpp
|
||||||
|
Text.cpp
|
||||||
ExtensionGo.cpp
|
ExtensionGo.cpp
|
||||||
Hook.cpp
|
Hook.cpp
|
||||||
Instance.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");
|
throw Error("Instance::Instance(): Can't create " + _TName("Instance") + ", empty name");
|
||||||
|
|
||||||
if (_cell->getInstance(_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)
|
if (!_masterCell)
|
||||||
throw Error("Instance::Instance(): Can't create " + _TName("Instance") + ", NULL master cell");
|
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/Polygon.h"
|
||||||
#include "hurricane/RoutingPad.h"
|
#include "hurricane/RoutingPad.h"
|
||||||
#include "hurricane/ExtensionGo.h"
|
#include "hurricane/ExtensionGo.h"
|
||||||
|
#include "hurricane/Text.h"
|
||||||
|
|
||||||
#include "hurricane/viewer/Graphics.h"
|
#include "hurricane/viewer/Graphics.h"
|
||||||
#include "hurricane/viewer/PaletteItem.h"
|
#include "hurricane/viewer/PaletteItem.h"
|
||||||
|
@ -721,6 +722,18 @@ namespace Hurricane {
|
||||||
_cellWidget->drawDisplayText( rectangle, netName, BigFont|Bold|Center|Frame );
|
_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() ) {
|
for ( BasicLayer* layer : _technology->getBasicLayers() ) {
|
||||||
_drawingPlanes.setPen ( Graphics::getPen (layer->getName(),getDarkening()) );
|
_drawingPlanes.setPen ( Graphics::getPen (layer->getName(),getDarkening()) );
|
||||||
_drawingPlanes.setBrush( Graphics::getBrush(layer->getName(),getDarkening()) );
|
_drawingPlanes.setBrush( Graphics::getBrush(layer->getName(),getDarkening()) );
|
||||||
|
|
||||||
if ( isDrawable(layer->getName()) ) {
|
if ( isDrawable(layer->getName()) ) {
|
||||||
_drawingQuery.setBasicLayer( layer );
|
_drawingQuery.setBasicLayer( layer );
|
||||||
_drawingQuery.setFilter ( getQueryFilter().unset(Query::DoMasterCells
|
_drawingQuery.setFilter ( getQueryFilter().unset(Query::DoMasterCells
|
||||||
|
@ -1698,67 +1710,84 @@ namespace Hurricane {
|
||||||
|
|
||||||
void CellWidget::drawDisplayText ( const QRect& box, const char* text, unsigned int flags )
|
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 width = metrics.width( text );
|
||||||
//int height = metrics.height ();
|
//int height = metrics.height();
|
||||||
int angle = 0;
|
int angle = 0;
|
||||||
|
|
||||||
if ( (width > box.width()) and (box.height() > 2*box.width()) )
|
if ( (width > box.width()) and (box.height() > 2*box.width()) )
|
||||||
angle = -90;
|
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();
|
QPainter& painter = _drawingPlanes.painter();
|
||||||
QPen pen = painter.pen ();
|
QPen pen = painter.pen();
|
||||||
QBrush brush = painter.brush ();
|
QBrush brush = painter.brush();
|
||||||
QFont font = Graphics::getNormalFont(flags&Bold);
|
|
||||||
|
if (not font.get())
|
||||||
|
font = shared_ptr<QFont>( new QFont( Graphics::getNormalFont( flags&Bold )));
|
||||||
|
|
||||||
painter.save();
|
painter.save();
|
||||||
if ( flags & Reverse ) painter.setPen ( Graphics::getPen("background") );
|
if (flags & Reverse) painter.setPen( Graphics::getPen("background") );
|
||||||
if ( flags & Reverse ) painter.setBackgroundMode ( Qt::OpaqueMode );
|
if (flags & Reverse) painter.setBackgroundMode( Qt::OpaqueMode );
|
||||||
if ( flags & BigFont ) font.setPointSize ( Graphics::isHighDpi() ? 7 : 18 );
|
|
||||||
|
|
||||||
QFontMetrics metrics = QFontMetrics(font);
|
QFontMetrics metrics = QFontMetrics ( *font );
|
||||||
int width = metrics.width ( text );
|
int width = metrics.width ( text );
|
||||||
int height = metrics.height ();
|
int height = metrics.height();
|
||||||
|
|
||||||
pen.setStyle ( Qt::SolidLine );
|
pen.setStyle( Qt::SolidLine );
|
||||||
pen.setColor ( painter.brush().color() );
|
pen.setColor( painter.brush().color() );
|
||||||
|
|
||||||
brush.setStyle ( Qt::NoBrush );
|
brush.setStyle( Qt::NoBrush );
|
||||||
|
|
||||||
painter.setPen ( pen );
|
painter.setPen ( pen );
|
||||||
painter.setBrush ( brush );
|
painter.setBrush ( brush );
|
||||||
painter.setFont ( font );
|
painter.setFont ( *font );
|
||||||
painter.translate ( point );
|
painter.translate( point );
|
||||||
painter.rotate ( angle );
|
painter.rotate ( angle );
|
||||||
|
|
||||||
QPoint bottomLeft ( 0, 0);
|
QPoint bottomLeft ( 0, 0);
|
||||||
if ( flags & Center ) {
|
if (flags & Center) {
|
||||||
bottomLeft.rx() -= width /2;
|
bottomLeft.rx() -= width /2;
|
||||||
bottomLeft.ry() += height/2;
|
bottomLeft.ry() += height/2;
|
||||||
} else if ( flags & Top ) {
|
} else if (flags & Top) {
|
||||||
bottomLeft.ry() += height;
|
bottomLeft.ry() += height;
|
||||||
} else if ( flags & Left ) {
|
} else if (flags & Left) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( flags & Frame ) {
|
if (flags & Frame) {
|
||||||
if ( flags & Rounded )
|
if (flags & Rounded)
|
||||||
painter.drawRoundedRect ( bottomLeft.x()-1, bottomLeft.y()-height, width+2, height, 8, 8 );
|
painter.drawRoundedRect( bottomLeft.x()-1, bottomLeft.y()-height, width+2, height, 8, 8 );
|
||||||
else
|
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.drawText( bottomLeft.x(), bottomLeft.y()-metrics.descent(), text );
|
||||||
painter.restore ();
|
painter.restore ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,7 @@ namespace Hurricane {
|
||||||
, Left =0x0040
|
, Left =0x0040
|
||||||
, Right =0x0080
|
, Right =0x0080
|
||||||
, Top =0x0100
|
, Top =0x0100
|
||||||
|
, FillBox =0x0200
|
||||||
};
|
};
|
||||||
enum Flag { NoFlags =0x0000
|
enum Flag { NoFlags =0x0000
|
||||||
, NoResetCommands=0x0001
|
, NoResetCommands=0x0001
|
||||||
|
@ -193,7 +194,7 @@ namespace Hurricane {
|
||||||
void drawRuler ( shared_ptr<Ruler> );
|
void drawRuler ( shared_ptr<Ruler> );
|
||||||
void drawRulers ( QRect );
|
void drawRulers ( QRect );
|
||||||
void drawDisplayText ( const QRect& , const char*, unsigned int flags=0 );
|
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 QPoint*, int count, size_t plane=PlaneId::Working );
|
||||||
void drawScreenPolygon ( const QPolygon&, 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 );
|
void drawScreenLine ( const QPoint&, const QPoint&, size_t plane=PlaneId::Working, bool mode=true );
|
||||||
|
|
Loading…
Reference in New Issue