diff --git a/crlcore/etc/45/freepdk_45/technology.conf b/crlcore/etc/45/freepdk_45/technology.conf index e9487027..bc537d9f 100644 --- a/crlcore/etc/45/freepdk_45/technology.conf +++ b/crlcore/etc/45/freepdk_45/technology.conf @@ -233,51 +233,71 @@ layersExtensionsTable = \ ) -gdsLayersTable = \ - ( ("nWell" , "NTUB" , 5) - , ("nImplant", "NPLUS" , 23) - , ("pImplant", "PPLUS" , 24) - , ("active" , "DIFF" , 10) - , ("poly" , "POLY1" , 20) - , ("cut0" , "CONT" , 34) - , ("metal1" , "MET1" , 35) - , ("cut1" , "VIA1" , 36) - , ("metal2" , "MET2" , 37) - , ("metcap" , "METCAP" , 55) - , ("cut2" , "VIA2" , 38) - , ("metal3" , "MET3" , 39) - , ("cut3" , "VIA3" , 41) - , ("metal4" , "MET4" , 42) - ) +# Table guessed from the Cadence configuration files: +# FreePDK45/ncsu_basekit/techfile/FreePDK45.tf +# +# Format of an entry in the table: +# (Symbolic_Name, CIF_Name, GDSII_Number) +#gdsLayersTable = \ +# ( ("pWell" , "CWN" , 2, 0) +# , ("nWell" , "CWP" , 3, 0) +# , ("active" , "CAA" , 1, 0) +# , ("pImplant", "CSP" , 5, 0) +# , ("nImplant", "CSN" , 4, 0) +# , ("poly" , "CPG" , 9, 0) +# , ("cut0" , "CCC" , 10, 0) +# , ("metal1" , "CM1" , 11, 0) +# , ("cut1" , "CV1" , 12, 0) +# , ("metal2" , "CM2" , 13, 0) +# , ("cut2" , "CV2" , 14, 0) +# , ("metal3" , "CM3" , 15, 0) +# , ("cut3" , "CV3" , 16, 0) +# , ("metal4" , "CM4" , 17, 0) +# , ("cut4" , "CV4" , 18, 0) +# , ("metal5" , "CM5" , 19, 0) +# , ("cut5" , "CV5" , 20, 0) +# , ("metal6" , "CM6" , 21, 0) +# , ("cut6" , "CV6" , 22, 0) +# , ("metal7" , "CM7" , 23, 0) +# , ("cut7" , "CV7" , 24, 0) +# , ("metal8" , "CM8" , 25, 0) +# , ("cut8" , "CV8" , 26, 0) +# , ("metal9" , "CM9" , 27, 0) +# , ("cut9" , "CV9" , 28, 0) +# , ("metal10" , "CM10" , 29, 0) +# ) +# Table guessed from the GDSII layouts of the cells. +# FreePDK45/osu_soc/lib/source/gds/*.gds +# # Format of an entry in the table: # (Symbolic_Name, CIF_Name, GDSII_Number) gdsLayersTable = \ ( ("pWell" , "CWN" , 2, 0) - , ("nWell" , "CWP" , 3, 0) - , ("active" , "CAA" , 1, 0) - , ("pImplant", "CSP" , 5, 0) - , ("nImplant", "CSN" , 4, 0) - , ("poly" , "CPG" , 9, 0) - , ("cut0" , "CCC" , 10, 0) - , ("metal1" , "CM1" , 11, 0) - , ("cut1" , "CV1" , 12, 0) - , ("metal2" , "CM2" , 13, 0) - , ("cut2" , "CV2" , 14, 0) - , ("metal3" , "CM3" , 15, 0) - , ("cut3" , "CV3" , 16, 0) - , ("metal4" , "CM4" , 17, 0) - , ("cut4" , "CV4" , 18, 0) - , ("metal5" , "CM5" , 19, 0) - , ("cut5" , "CV5" , 20, 0) - , ("metal6" , "CM6" , 21, 0) - , ("cut6" , "CV6" , 22, 0) - , ("metal7" , "CM7" , 23, 0) - , ("cut7" , "CV7" , 24, 0) - , ("metal8" , "CM8" , 25, 0) - , ("cut8" , "CV8" , 26, 0) - , ("metal9" , "CM9" , 27, 0) - , ("cut9" , "CV9" , 28, 0) - , ("metal10" , "CM10" , 29, 0) + , ("nWell" , "CWP" , 1, 0) + , ("active" , "CAA" , 5, 0) + , ("pImplant", "CSP" , 8, 0) + , ("nImplant", "CSN" , 7, 0) + , ("poly" , "CPG" , 15, 0) + , ("cut0" , "CCC" , 16, 0) + , ("metal1" , "CM1" , 21, 0) + , ("cut1" , "CV1" , 22, 0) + , ("metal2" , "CM2" , 23, 0) + , ("cut2" , "CV2" , 24, 0) + , ("metal3" , "CM3" , 25, 0) + , ("cut3" , "CV3" , 26, 0) + , ("metal4" , "CM4" , 27, 0) + , ("cut4" , "CV4" , 28, 0) + , ("metal5" , "CM5" , 29, 0) + , ("cut5" , "CV5" , 30, 0) + , ("metal6" , "CM6" , 31, 0) + , ("cut6" , "CV6" , 32, 0) + , ("metal7" , "CM7" , 33, 0) + , ("cut7" , "CV7" , 34, 0) + , ("metal8" , "CM8" , 35, 0) + , ("cut8" , "CV8" , 36, 0) + , ("metal9" , "CM9" , 37, 0) + , ("cut9" , "CV9" , 38, 0) + , ("metal10" , "CM10" , 39, 0) ) diff --git a/crlcore/src/ccore/CMakeLists.txt b/crlcore/src/ccore/CMakeLists.txt index 9db9d78e..3ed2f839 100644 --- a/crlcore/src/ccore/CMakeLists.txt +++ b/crlcore/src/ccore/CMakeLists.txt @@ -117,6 +117,7 @@ alliance/ap/ApDriver.cpp ) set ( gds_cpps gds/GdsDriver.cpp + gds/GdsParser.cpp ) set ( cif_cpps cif/CifDriver.cpp ) diff --git a/crlcore/src/ccore/crlcore/Gds.h b/crlcore/src/ccore/crlcore/Gds.h index 107c758d..d4401841 100644 --- a/crlcore/src/ccore/crlcore/Gds.h +++ b/crlcore/src/ccore/crlcore/Gds.h @@ -22,17 +22,20 @@ namespace Hurricane { class Cell; + class Library; } namespace CRL { using Hurricane::Cell; + using Hurricane::Library; class Gds { public: static bool save ( Cell* ); + static bool load ( Library*, std::string gdsPath ); }; diff --git a/crlcore/src/ccore/gds/GdsParser.cpp b/crlcore/src/ccore/gds/GdsParser.cpp new file mode 100644 index 00000000..e3f889bc --- /dev/null +++ b/crlcore/src/ccore/gds/GdsParser.cpp @@ -0,0 +1,1109 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2018-2018, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | G D S I I / Hurricane Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./gds/GdsParser.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +#include "vlsisapd/configuration/Configuration.h" +#include "hurricane/Warning.h" +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/BasicLayer.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "hurricane/Diagonal.h" +#include "hurricane/Rectilinear.h" +#include "hurricane/Pad.h" +#include "hurricane/Net.h" +#include "hurricane/Cell.h" +#include "hurricane/Library.h" +#include "hurricane/Plug.h" +#include "hurricane/Instance.h" +#include "hurricane/UpdateSession.h" +using namespace Hurricane; + +#include "crlcore/Utilities.h" +#include "crlcore/NetExtension.h" +#include "crlcore/ToolBox.h" +#include "crlcore/Gds.h" +using namespace CRL; + + +namespace { + + +// ------------------------------------------------------------------- +// Class : "::GdsRecord". + + class GdsRecord { + public: + // Data Types. + static const uint16_t NoData = 0x0000; + static const uint16_t BitArray = 0x0001; + static const uint16_t TwoByteInteger = 0x0002; // Signed, 16 bits. + static const uint16_t FourByteInteger = 0x0003; // Signed, 32 bits. + static const uint16_t FourByteReal = 0x0004; // Unused. + static const uint16_t EightByteReal = 0x0005; + static const uint16_t String = 0x0006; + // Record Types. + static const uint16_t HEADER = 0x0000 | TwoByteInteger; + static const uint16_t BGNLIB = 0x0100 | TwoByteInteger; + static const uint16_t LIBNAME = 0x0200 | String; + static const uint16_t UNITS = 0x0300 | EightByteReal; + static const uint16_t ENDLIB = 0x0400 | NoData; + static const uint16_t BGNSTR = 0x0500 | TwoByteInteger; + static const uint16_t STRNAME = 0x0600 | String; + static const uint16_t ENDSTR = 0x0700 | NoData; + static const uint16_t BOUNDARY = 0x0800 | NoData; + static const uint16_t PATH = 0x0900 | NoData; + static const uint16_t SREF = 0x0a00 | NoData; + static const uint16_t AREF = 0x0b00 | NoData; + static const uint16_t TEXT = 0x0c00 | NoData; + static const uint16_t LAYER = 0x0d00 | TwoByteInteger; + static const uint16_t DATATYPE = 0x0e00 | TwoByteInteger; + static const uint16_t WIDTH = 0x0f00 | FourByteInteger; + static const uint16_t XY = 0x1000 | FourByteInteger; + static const uint16_t ENDEL = 0x1100 | NoData; + static const uint16_t SNAME = 0x1200 | String; + static const uint16_t COLROW = 0x1300 | TwoByteInteger; + static const uint16_t TEXTNODE = 0x1400 | NoData; // Unused. + static const uint16_t NODE = 0x1500 | NoData; + static const uint16_t TEXTTYPE = 0x1600 | TwoByteInteger; + static const uint16_t PRESENTATION = 0x1700 | BitArray; + static const uint16_t SPACING = 0x1800 | NoData; // Discontinued. + static const uint16_t STRING = 0x1900 | String; + static const uint16_t STRANS = 0x1a00 | BitArray; + static const uint16_t MAG = 0x1b00 | EightByteReal; + static const uint16_t ANGLE = 0x1c00 | EightByteReal; + static const uint16_t REFLIBS = 0x1f00 | String; + static const uint16_t FONTS = 0x2000 | String; + static const uint16_t PATHTYPE = 0x2100 | TwoByteInteger; + static const uint16_t GENERATIONS = 0x2200 | TwoByteInteger; + static const uint16_t ATTRTABLE = 0x2300 | String; + static const uint16_t STYPTABLE = 0x2400 | String; // Unreleased. + static const uint16_t STRTYPE = 0x2500 | TwoByteInteger; // Unreleased. + static const uint16_t ELFLAGS = 0x2600 | BitArray; + static const uint16_t ELKEY = 0x2700 | FourByteInteger; // Unreleased. + static const uint16_t LINKTYPE = 0x2800 | TwoByteInteger; // Unreleased. + static const uint16_t LINKKEYS = 0x2900 | FourByteInteger; // Unreleased. + static const uint16_t NODETYPE = 0x2a00 | TwoByteInteger; + static const uint16_t PROPATTR = 0x2b00 | TwoByteInteger; + static const uint16_t PROPVALUE = 0x2c00 | String; + static const uint16_t BOX = 0x2d00 | NoData; + static const uint16_t BOXTYPE = 0x2e00 | TwoByteInteger; + static const uint16_t PLEX = 0x2f00 | FourByteInteger; + static const uint16_t BGNEXTN = 0x3000 | FourByteInteger; // CustomPlus. + static const uint16_t ENDEXTN = 0x3100 | FourByteInteger; // CustomPlus. + static const uint16_t TAPENUM = 0x3200 | TwoByteInteger; + static const uint16_t TAPECODE = 0x3300 | TwoByteInteger; + static const uint16_t STRCLASS = 0x3400 | BitArray; // CustomPlus. + static const uint16_t RESERVED = 0x3500 | FourByteInteger; // Future use. + static const uint16_t FORMAT = 0x3600 | TwoByteInteger; + static const uint16_t MASK = 0x3700 | String; // Filtered format. + static const uint16_t ENDMASKS = 0x3800 | NoData; // Filtered format. + static const uint16_t LIBDIRSIZE = 0x3900 | TwoByteInteger; + static const uint16_t SRFNAME = 0x3a00 | String; + static const uint16_t LIBSECUR = 0x3b00 | TwoByteInteger; + public: + GdsRecord (); + inline bool isHEADER () const; + inline bool isBGNLIB () const; + inline bool isLIBNAME () const; + inline bool isUNITS () const; + inline bool isENDLIB () const; + inline bool isBGNSTR () const; + inline bool isSTRNAME () const; + inline bool isENDSTR () const; + inline bool isBOUNDARY () const; + inline bool isPATH () const; + inline bool isSREF () const; + inline bool isAREF () const; + inline bool isTEXT () const; + inline bool isLAYER () const; + inline bool isDATATYPE () const; + inline bool isWIDTH () const; + inline bool isXY () const; + inline bool isENDEL () const; + inline bool isSNAME () const; + inline bool isCOLROW () const; + inline bool isTEXTNODE () const; + inline bool isNODE () const; + inline bool isTEXTTYPE () const; + inline bool isPRESENTATION () const; + inline bool isSPACING () const; + inline bool isSTRING () const; + inline bool isSTRANS () const; + inline bool isMAG () const; + inline bool isANGLE () const; + inline bool isREFLIBS () const; + inline bool isFONTS () const; + inline bool isPATHTYPE () const; + inline bool isGENERATIONS () const; + inline bool isATTRTABLE () const; + inline bool isSTYPTABLE () const; + inline bool isSTRTYPE () const; + inline bool isELFLAGS () const; + inline bool isELKEY () const; + inline bool isLINKTYPE () const; + inline bool isLINKKEYS () const; + inline bool isNODETYPE () const; + inline bool isPROPATTR () const; + inline bool isPROPVALUE () const; + inline bool isBOX () const; + inline bool isBOXTYPE () const; + inline bool isPLEX () const; + inline bool isBGNEXTN () const; + inline bool isENDEXTN () const; + inline bool isTAPENUM () const; + inline bool isTAPECODE () const; + inline bool isSTRCLASS () const; + inline bool isRESERVED () const; + inline bool isFORMAT () const; + inline bool isMASK () const; + inline bool isENDMASKS () const; + inline bool isLIBDIRSIZE () const; + inline bool isSRFNAME () const; + inline bool isLIBSECUR () const; + inline uint16_t getType () const; + inline uint16_t getLength () const; + inline const vector& getMasks () const; + inline const vector& getInt16s () const; + inline const vector& getInt32s () const; + inline const vector& getDoubles () const; + inline string getName () const; + void clear (); + void read ( istream* ); + void readDummy ( bool showError ); + void readUnits (); + void readLayer (); + void readStrname (); + void readXy (); + static string toStrType ( uint16_t ); + GdsRecord& operator= ( const GdsRecord& ); + private: + template< typename IntType> IntType _readInt (); + string _readString (); + double _readDouble (); + private: + istream* _stream; + uint16_t _length; + uint16_t _count; + uint16_t _type; + string _name; + vector _masks; + vector _int16s; + vector _int32s; + vector _doubles; + }; + + + inline bool GdsRecord::isHEADER () const { return (_type == HEADER ); } + inline bool GdsRecord::isBGNLIB () const { return (_type == BGNLIB ); } + inline bool GdsRecord::isLIBNAME () const { return (_type == LIBNAME ); } + inline bool GdsRecord::isUNITS () const { return (_type == UNITS ); } + inline bool GdsRecord::isENDLIB () const { return (_type == ENDLIB ); } + inline bool GdsRecord::isBGNSTR () const { return (_type == BGNSTR ); } + inline bool GdsRecord::isSTRNAME () const { return (_type == STRNAME ); } + inline bool GdsRecord::isENDSTR () const { return (_type == ENDSTR ); } + inline bool GdsRecord::isBOUNDARY () const { return (_type == BOUNDARY ); } + inline bool GdsRecord::isPATH () const { return (_type == PATH ); } + inline bool GdsRecord::isSREF () const { return (_type == SREF ); } + inline bool GdsRecord::isAREF () const { return (_type == AREF ); } + inline bool GdsRecord::isTEXT () const { return (_type == TEXT ); } + inline bool GdsRecord::isLAYER () const { return (_type == LAYER ); } + inline bool GdsRecord::isDATATYPE () const { return (_type == DATATYPE ); } + inline bool GdsRecord::isWIDTH () const { return (_type == WIDTH ); } + inline bool GdsRecord::isXY () const { return (_type == XY ); } + inline bool GdsRecord::isENDEL () const { return (_type == ENDEL ); } + inline bool GdsRecord::isSNAME () const { return (_type == SNAME ); } + inline bool GdsRecord::isCOLROW () const { return (_type == COLROW ); } + inline bool GdsRecord::isTEXTNODE () const { return (_type == TEXTNODE ); } + inline bool GdsRecord::isNODE () const { return (_type == NODE ); } + inline bool GdsRecord::isTEXTTYPE () const { return (_type == TEXTTYPE ); } + inline bool GdsRecord::isPRESENTATION () const { return (_type == PRESENTATION); } + inline bool GdsRecord::isSPACING () const { return (_type == SPACING ); } + inline bool GdsRecord::isSTRING () const { return (_type == STRING ); } + inline bool GdsRecord::isSTRANS () const { return (_type == STRANS ); } + inline bool GdsRecord::isMAG () const { return (_type == MAG ); } + inline bool GdsRecord::isANGLE () const { return (_type == ANGLE ); } + inline bool GdsRecord::isREFLIBS () const { return (_type == REFLIBS ); } + inline bool GdsRecord::isFONTS () const { return (_type == FONTS ); } + inline bool GdsRecord::isPATHTYPE () const { return (_type == PATHTYPE ); } + inline bool GdsRecord::isGENERATIONS () const { return (_type == GENERATIONS ); } + inline bool GdsRecord::isATTRTABLE () const { return (_type == ATTRTABLE ); } + inline bool GdsRecord::isSTYPTABLE () const { return (_type == STYPTABLE ); } + inline bool GdsRecord::isSTRTYPE () const { return (_type == STRTYPE ); } + inline bool GdsRecord::isELFLAGS () const { return (_type == ELFLAGS ); } + inline bool GdsRecord::isELKEY () const { return (_type == ELKEY ); } + inline bool GdsRecord::isLINKTYPE () const { return (_type == LINKTYPE ); } + inline bool GdsRecord::isLINKKEYS () const { return (_type == LINKKEYS ); } + inline bool GdsRecord::isNODETYPE () const { return (_type == NODETYPE ); } + inline bool GdsRecord::isPROPATTR () const { return (_type == PROPATTR ); } + inline bool GdsRecord::isPROPVALUE () const { return (_type == PROPVALUE ); } + inline bool GdsRecord::isBOX () const { return (_type == BOX ); } + inline bool GdsRecord::isBOXTYPE () const { return (_type == BOXTYPE ); } + inline bool GdsRecord::isPLEX () const { return (_type == PLEX ); } + inline bool GdsRecord::isBGNEXTN () const { return (_type == BGNEXTN ); } + inline bool GdsRecord::isENDEXTN () const { return (_type == ENDEXTN ); } + inline bool GdsRecord::isTAPENUM () const { return (_type == TAPENUM ); } + inline bool GdsRecord::isTAPECODE () const { return (_type == TAPECODE ); } + inline bool GdsRecord::isSTRCLASS () const { return (_type == STRCLASS ); } + inline bool GdsRecord::isRESERVED () const { return (_type == RESERVED ); } + inline bool GdsRecord::isFORMAT () const { return (_type == FORMAT ); } + inline bool GdsRecord::isMASK () const { return (_type == MASK ); } + inline bool GdsRecord::isENDMASKS () const { return (_type == ENDMASKS ); } + inline bool GdsRecord::isLIBDIRSIZE () const { return (_type == LIBDIRSIZE ); } + inline bool GdsRecord::isSRFNAME () const { return (_type == SRFNAME ); } + inline bool GdsRecord::isLIBSECUR () const { return (_type == LIBSECUR ); } + inline uint16_t GdsRecord::getType () const { return _type; } + inline uint16_t GdsRecord::getLength () const { return _length; } + inline const vector& GdsRecord::getMasks () const { return _masks; } + inline const vector& GdsRecord::getInt16s () const { return _int16s; } + inline const vector& GdsRecord::getInt32s () const { return _int32s; } + inline const vector& GdsRecord::getDoubles () const { return _doubles; } + inline string GdsRecord::getName () const { return _name; } + + + GdsRecord::GdsRecord () + : _stream (NULL) + , _length (0) + , _count (0) + , _type (0) + , _name () + , _masks () + , _int16s () + , _int32s () + , _doubles () + { } + + + void GdsRecord::clear () + { + _stream = NULL; + _length = 0; + _count = 0; + _type = 0; + _name .clear(); + _masks .clear(); + _int16s .clear(); + _int32s .clear(); + _doubles .clear(); + } + + + void GdsRecord::read ( istream* stream ) + { + clear(); + + _stream = stream; + _length = _readInt(); + _type = _readInt(); + + switch ( _type ) { + case HEADER: readDummy( false ); break; + case BGNLIB: readDummy( false ); break; + case LIBNAME: readDummy( false ); break; + case UNITS: readUnits(); break; + case ENDLIB: readDummy( false ); break; + case BGNSTR: readDummy( false ); break; + case STRNAME: readStrname(); break; + case ENDSTR: readDummy( false ); break; + case BOUNDARY: readDummy( false ); break; + case PATH: readDummy( false ); break; + case SREF: readDummy( false ); break; + case AREF: readDummy( false ); break; + case TEXT: readDummy( false ); break; + case LAYER: readLayer(); break; + case DATATYPE: readDummy( false ); break; + case WIDTH: readDummy( false ); break; + case XY: readXy(); break; + case ENDEL: readDummy( false ); break; + case SNAME: readDummy( false ); break; + case COLROW: readDummy( false ); break; + case TEXTNODE: readDummy( false ); break; + case NODE: readDummy( false ); break; + case TEXTTYPE: readDummy( false ); break; + case PRESENTATION: readDummy( false ); break; + case SPACING: readDummy( false ); break; + case STRING: readDummy( false ); break; + case STRANS: readDummy( false ); break; + case MAG: readDummy( false ); break; + case ANGLE: readDummy( false ); break; + case REFLIBS: readDummy( false ); break; + case FONTS: readDummy( false ); break; + case PATHTYPE: readDummy( false ); break; + case GENERATIONS: readDummy( false ); break; + case ATTRTABLE: readDummy( false ); break; + case STYPTABLE: readDummy( false ); break; + case STRTYPE: readDummy( false ); break; + case ELFLAGS: readDummy( false ); break; + case ELKEY: readDummy( false ); break; + case LINKTYPE: readDummy( false ); break; + case LINKKEYS: readDummy( false ); break; + case NODETYPE: readDummy( false ); break; + case PROPATTR: readDummy( false ); break; + case PROPVALUE: readDummy( false ); break; + case BOX: readDummy( false ); break; + case BOXTYPE: readDummy( false ); break; + case PLEX: readDummy( false ); break; + case BGNEXTN: readDummy( false ); break; + case ENDEXTN: readDummy( false ); break; + case TAPENUM: readDummy( false ); break; + case TAPECODE: readDummy( false ); break; + case STRCLASS: readDummy( false ); break; + case RESERVED: readDummy( false ); break; + case FORMAT: readDummy( false ); break; + case MASK: readDummy( false ); break; + case ENDMASKS: readDummy( false ); break; + case LIBDIRSIZE: readDummy( false ); break; + case SRFNAME: readDummy( false ); break; + case LIBSECUR: readDummy( false ); break; + } + + //cerr << " GdsRecord::read() " << toStrType(_type) << endl; + } + + + GdsRecord& GdsRecord::operator= ( const GdsRecord& other ) + { + _length = other._length; + _count = other._count; + _type = other._type; + _name = other._name; + _masks = other._masks; + _int16s = other._int16s; + _int32s = other._int32s; + _doubles = other._doubles; + return *this; + } + + + template< typename IntType> + IntType GdsRecord::_readInt () + { + const size_t typeSize = sizeof(IntType); + + union UType { + IntType integer; + unsigned char bytes[ typeSize ]; + }; + + char bytes[typeSize]; + _stream->read( bytes, typeSize ); + _count += typeSize; + + UType uvalue; + // Little endian (x86). + for ( size_t i=0 ; iread( bytes, 8 ); + _count += 8; + + gdsUInt64 mantisse; + for ( size_t i=0 ; i<7 ; ++i ) mantisse.bytes[i] = bytes[7-i]; + mantisse.bytes[7] = 0; + double value = mantisse.uint64; + + if (bytes[0] & 0x80) value = -value; + + int32_t exponent = (bytes[0] & 0x7f) - (64+14); + if (exponent) value *= pow( 16.0, (double)exponent ); + + return value; + } + + + string GdsRecord::_readString () + { + string s; + char c; + for ( ; _count<_length ; ++_count ) { + _stream->get( c ); + if (c != (char)0) s.push_back(c); + } + return s; + } + + + void GdsRecord::readDummy ( bool showError ) + { + char c; + for ( ; _count<_length ; ++_count ) _stream->get( c ); + + if (showError) { + cerr << Error( "GdsRecord type %s unsupported.", toStrType(_type).c_str() ) << endl; + } + } + + + void GdsRecord::readUnits () + { for ( size_t i=0 ; i<2 ; ++i ) _doubles.push_back( _readDouble() ); } + + + void GdsRecord::readStrname () + { _name = _readString(); } + + + void GdsRecord::readLayer () + { _int16s.push_back( _readInt() ); } + + + void GdsRecord::readXy () + { while ( _count < _length ) _int32s.push_back( _readInt() ); } + + + string GdsRecord::toStrType ( uint16_t type ) + { + switch ( type ) { + case HEADER: return "HEADER"; + case BGNLIB: return "BGNLIB"; + case LIBNAME: return "LIBNAME"; + case UNITS: return "UNITS"; + case ENDLIB: return "ENDLIB"; + case BGNSTR: return "BGNSTR"; + case STRNAME: return "STRNAME"; + case ENDSTR: return "ENDSTR"; + case BOUNDARY: return "BOUNDARY"; + case PATH: return "PATH"; + case SREF: return "SREF"; + case AREF: return "AREF"; + case TEXT: return "TEXT"; + case LAYER: return "LAYER"; + case DATATYPE: return "DATATYPE"; + case WIDTH: return "WIDTH"; + case XY: return "XY"; + case ENDEL: return "ENDEL"; + case SNAME: return "SNAME"; + case COLROW: return "COLROW"; + case TEXTNODE: return "TEXTNODE"; + case NODE: return "NODE"; + case TEXTTYPE: return "TEXTTYPE"; + case PRESENTATION:return "PRESENTATION"; + case SPACING: return "SPACING"; + case STRING: return "STRING"; + case STRANS: return "STRANS"; + case MAG: return "MAG"; + case ANGLE: return "ANGLE"; + case REFLIBS: return "REFLIBS"; + case FONTS: return "FONTS"; + case PATHTYPE: return "PATHTYPE"; + case GENERATIONS: return "GENERATIONS"; + case ATTRTABLE: return "ATTRTABLE"; + case STYPTABLE: return "STYPTABLE"; + case STRTYPE: return "STRTYPE"; + case ELFLAGS: return "ELFLAGS"; + case ELKEY: return "ELKEY"; + case LINKTYPE: return "LINKTYPE"; + case LINKKEYS: return "LINKKEYS"; + case NODETYPE: return "NODETYPE"; + case PROPATTR: return "PROPATTR"; + case PROPVALUE: return "PROPVALUE"; + case BOX: return "BOX"; + case BOXTYPE: return "BOXTYPE"; + case PLEX: return "PLEX"; + case BGNEXTN: return "BGNEXTN"; + case ENDEXTN: return "ENDEXTN"; + case TAPENUM: return "TAPENUM"; + case TAPECODE: return "TAPECODE"; + case STRCLASS: return "STRCLASS"; + case RESERVED: return "RESERVED"; + case FORMAT: return "FORMAT"; + case MASK: return "MASK"; + case ENDMASKS: return "ENDMASKS"; + case LIBDIRSIZE: return "LIBDIRSIZE"; + case SRFNAME: return "SRFNAME"; + case LIBSECUR: return "LIBSECUR"; + } + + ostringstream error; + error << "undefined GDS record type (0x" << hex << type << ")"; + return error.str(); + } + + + istream& operator>> ( istream& stream, GdsRecord& record ) + { record.read( &stream ); return stream; } + + +// ------------------------------------------------------------------- +// Class : "::GdsStream". + + class GdsStream { + public: + static const Layer* gdsToLayer ( uint16_t ); + public: + static void _staticInit (); + GdsStream ( string gdsPath ); + inline bool isValidSyntax () const; + bool misplacedRecord (); + bool read ( Library* ); + bool readFormatType (); + bool readStructure (); + bool readBoundary (); + bool readPath (); + bool readSref (); + bool readAref (); + bool readNode (); + bool readBox (); + bool readText (); + bool readTextbody (); + bool readStrans (); + bool readProperty (); + void xyToComponent ( const Layer* ); + Net* anonymousNet (); + private: + static vector _gdsLayerTable; + string _gdsPath; + ifstream _stream; + GdsRecord _record; + Library* _library; + Cell* _cell; + DbU::Unit _scale; + int64_t _netCount; + bool _validSyntax; + }; + + + vector GdsStream::_gdsLayerTable; + + + void GdsStream::_staticInit () + { + _gdsLayerTable = vector( 64, NULL ); + for ( const BasicLayer* layer : DataBase::getDB()->getTechnology()->getBasicLayers() ) { + unsigned int gdsNumber = layer->getGds2Layer(); + if (gdsNumber < 64) _gdsLayerTable[gdsNumber] = layer; + } + } + + + const Layer* GdsStream::gdsToLayer ( uint16_t gdsLayer ) + { return (gdsLayer < _gdsLayerTable.size()) ? _gdsLayerTable[gdsLayer] : NULL; } + + + inline bool GdsStream::isValidSyntax () const { return _validSyntax; } + + + GdsStream::GdsStream ( string gdsPath ) + : _gdsPath (gdsPath) + , _stream () + , _record () + , _library (NULL) + , _cell (NULL) + , _scale (1) + , _netCount (0) + , _validSyntax(true) + { + if (_gdsLayerTable.empty()) _staticInit(); + + _stream.open( gdsPath, ios_base::in ); + + _stream >> _record; + if (not _record.isHEADER()) { + cerr << Error( "GdsStream::GdsStream(): First record is not a HEADER.\n" + " in \"%s\"" + , _gdsPath.c_str() ) << endl; + _validSyntax = false; + return; + } + _stream >> _record; + } + + + bool GdsStream::misplacedRecord () + { + cerr << Error( "GdsStream: Misplaced record %s.\n" + " in \"%s\"" + , GdsRecord::toStrType(_record.getType()).c_str() + , _gdsPath.c_str() ) << endl; + _validSyntax = false; + return _validSyntax; + } + + + bool GdsStream::read ( Library* library ) + { + //cerr << "GdsStream::read(Library*)" << endl; + + _library = library; + + if (not _record.isBGNLIB()) { + cerr << Error( "GdsStream::read(Library*): Starting record is not a BGNLIB.\n" + " in \"%s\"" + , _gdsPath.c_str() ) << endl; + _validSyntax = false; + return _validSyntax; + } + _stream >> _record; + + if (_record.isLIBDIRSIZE ()) { _stream >> _record; } + if (_record.isSRFNAME ()) { _stream >> _record; } + if (_record.isLIBSECUR ()) { _stream >> _record; } + if (_record.isLIBNAME ()) { _stream >> _record; } + else { + cerr << Error( "GdsStream::read(Library*): Missing LIBNAME record.\n" + " in \"%s\"" + , _gdsPath.c_str() ) << endl; + _validSyntax = false; + return _validSyntax; + } + if (_record.isREFLIBS ()) { _stream >> _record; } + if (_record.isFONTS ()) { _stream >> _record; } + if (_record.isATTRTABLE ()) { _stream >> _record; } + if (_record.isGENERATIONS()) { _stream >> _record; } + if (_record.isFORMAT ()) { readFormatType(); if (not _validSyntax) return _validSyntax; } + + if (_record.isUNITS()) { + _scale = DbU::fromPhysical( _record.getDoubles()[1], DbU::Unity ); + _stream >> _record; + } + + while ( _validSyntax and _record.isBGNSTR() ) { + _stream >> _record; + readStructure(); + } + + if (_validSyntax and not _record.isENDLIB()) { misplacedRecord(); } + + _library = NULL; + //cerr << "GdsStream::read(Library*) - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readFormatType () + { + //cerr << "GdsStream::readFormatType()" << endl; + + if (_record.isMASK()) { + _stream >> _record; + while ( _record.isMASK() ) { + _stream >> _record; + } + + if (_record.isENDMASKS()) { _stream >> _record; } + else { _validSyntax = false; return _validSyntax; } + } + + //cerr << "GdsStream::readFormatType() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readStructure () + { + //cerr << "GdsStream::readStructure()" << endl; + + if (_record.isSTRNAME()) { + if (_library) { + _cell = _library->getCell( _record.getName() ); + if (not _cell) { + cerr << Warning( "GdsStream::readStructure(): No Cell named \"%s\" in Library \"%s\" (skipped)." + , _record.getName().c_str() + , getString(_library).c_str() + ) << endl; + } + } + _stream >> _record; + } + + if (_record.isSTRCLASS()) { _stream >> _record; } + + while ( not _record.isENDSTR() ) { + switch ( _record.getType() ) { + case GdsRecord::BOUNDARY: _stream >> _record; readBoundary(); break; + case GdsRecord::PATH: _stream >> _record; readPath (); break; + case GdsRecord::SREF: _stream >> _record; readSref (); break; + case GdsRecord::AREF: _stream >> _record; readAref (); break; + case GdsRecord::TEXT: _stream >> _record; readText (); break; + case GdsRecord::NODE: _stream >> _record; readNode (); break; + case GdsRecord::BOX: _stream >> _record; readBox (); break; + case GdsRecord::PROPATTR: _stream >> _record; readProperty(); break; + } + if (_record.isENDEL()) { _stream >> _record; } + else { + _validSyntax = false; break; + } + } + + if (_validSyntax) _stream >> _record; + + _cell = NULL; + //cerr << "GdsStream::readStructure() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readText () + { + //cerr << "GdsStream::readText()" << endl; + + if (_record.isELFLAGS()) { _stream >> _record; } + if (_record.isPLEX ()) { _stream >> _record; } + + if (_record.isLAYER ()) { _stream >> _record; } + else { _validSyntax = false; return _validSyntax; } + + readTextbody(); + + //cerr << "GdsStream::readText() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readTextbody () + { + //cerr << "GdsStream::readTextbody()" << endl; + + if (_record.isTEXTTYPE()) { _stream >> _record; } + else { _validSyntax = false; return _validSyntax; } + + if (_record.isPRESENTATION()) { _stream >> _record; } + if (_record.isPATH ()) { _stream >> _record; } + if (_record.isWIDTH ()) { _stream >> _record; } + + if (_record.isSTRANS()) { + _stream >> _record; + readStrans(); + if (not _validSyntax) return _validSyntax; + } + + if (_record.isXY()) { _stream >> _record; } + else { _validSyntax = false; return _validSyntax; } + + if (_record.isSTRING()) { _stream >> _record; } + else { _validSyntax = false; return _validSyntax; } + + //cerr << "GdsStream::readTextbody() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readStrans () + { + //cerr << "GdsStream::readStrans()" << endl; + + if (_record.isMAG ()) { _stream >> _record; } + if (_record.isANGLE()) { _stream >> _record; } + + //cerr << "GdsStream::readStrans() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readBoundary () + { + //cerr << "GdsStream::readBoundary()" << endl; + + const Layer* layer = NULL; + + if (_record.isELFLAGS()) { _stream >> _record; } + if (_record.isPLEX ()) { _stream >> _record; } + + if (_record.isLAYER()) { + layer = gdsToLayer( _record.getInt16s()[0] ); + if (not layer) { + cerr << Error( "GdsStream::readBoundary(): No BasicLayer id:%d in GDS conversion table (skipped)." + , _record.getInt16s()[0] + ) << endl; + } + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + if (_record.isDATATYPE()) { _stream >> _record; } + else { _validSyntax = false; return _validSyntax; } + + if (_record.isXY()) { + if (_cell and layer) xyToComponent( layer ); + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + //cerr << "GdsStream::readBoundary() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readPath () + { + //cerr << "GdsStream::readPath()" << endl; + + const Layer* layer = NULL; + + if (_record.isELFLAGS()) { _stream >> _record; } + if (_record.isPLEX ()) { _stream >> _record; } + + if (_record.isLAYER()) { + layer = gdsToLayer( _record.getInt16s()[0] ); + if (not layer) { + cerr << Error( "GdsStream::readPath(): No BasicLayer id \"%d\" in GDS conversion table (skipped)." + , _record.getInt16s()[0] + ) << endl; + } + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + if (_record.isDATATYPE()) { _stream >> _record; } + else { _validSyntax = false; return _validSyntax; } + + if (_record.isPATHTYPE()) { _stream >> _record; } + if (_record.isWIDTH ()) { _stream >> _record; } + if (_record.isBGNEXTN ()) { _stream >> _record; } + if (_record.isENDEXTN ()) { _stream >> _record; } + + if (_record.isXY()) { + if (_cell and layer) xyToComponent( layer ); + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + //cerr << "GdsStream::readPath() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readSref () + { + //cerr << "GdsStream::readSref()" << endl; + + const Layer* layer = NULL; + + if (_record.isELFLAGS()) { _stream >> _record; } + if (_record.isPLEX ()) { _stream >> _record; } + + if (_record.isSNAME()) { + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + if (_record.isSTRANS()) { + _stream >> _record; + readStrans(); + if (not _validSyntax) return _validSyntax; + } + + if (_record.isXY()) { + if (_cell and layer) xyToComponent( layer ); + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + //cerr << "GdsStream::readSref() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readAref () + { + //cerr << "GdsStream::readAref()" << endl; + + const Layer* layer = NULL; + + if (_record.isELFLAGS()) { _stream >> _record; } + if (_record.isPLEX ()) { _stream >> _record; } + + if (_record.isSNAME()) { + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + if (_record.isSTRANS()) { + _stream >> _record; + readStrans(); + if (not _validSyntax) return _validSyntax; + } + + if (_record.isCOLROW()) { + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + if (_record.isXY()) { + if (_cell and layer) xyToComponent( layer ); + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + //cerr << "GdsStream::readAref() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readNode () + { + //cerr << "GdsStream::readNode()" << endl; + + const Layer* layer = NULL; + + if (_record.isELFLAGS()) { _stream >> _record; } + if (_record.isPLEX ()) { _stream >> _record; } + + if (_record.isLAYER ()) { _stream >> _record; } + else { _validSyntax = false; return _validSyntax; } + + if (_record.isNODETYPE()) { + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + if (_record.isXY()) { + if (_cell and layer) xyToComponent( layer ); + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + //cerr << "GdsStream::readNode() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readBox () + { + //cerr << "GdsStream::readBox()" << endl; + + const Layer* layer = NULL; + + if (_record.isELFLAGS()) { _stream >> _record; } + if (_record.isPLEX ()) { _stream >> _record; } + + if (_record.isLAYER ()) { _stream >> _record; } + else { _validSyntax = false; return _validSyntax; } + + if (_record.isBOXTYPE()) { + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + if (_record.isXY()) { + if (_cell and layer) xyToComponent( layer ); + _stream >> _record; + } else { + _validSyntax = false; return _validSyntax; + } + + //cerr << "GdsStream::readBox() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + bool GdsStream::readProperty () + { + //cerr << "GdsStream::readProperty()" << endl; + + if (_record.isPROPVALUE ()) { _stream >> _record; } + else { _validSyntax = false; return _validSyntax; } + + //cerr << "GdsStream::readProperty() - return:" << _validSyntax << endl; + return _validSyntax; + } + + + void GdsStream::xyToComponent ( const Layer* layer ) + { + vector points; + vector coordinates = _record.getInt32s(); + for ( size_t i=0 ; i 2) { + bool isRectilinear = true; + for ( size_t i=1 ; i +#include + + +namespace CRL { + + using std::cerr; + using std::endl; + using std::hex; + using std::string; + using std::ostringstream; + using Hurricane::tab; + using Hurricane::Exception; + using Hurricane::Bug; + using Hurricane::Error; + using Hurricane::Warning; + using Isobar::ProxyProperty; + using Isobar::ProxyError; + using Isobar::ConstructorError; + using Isobar::HurricaneError; + using Isobar::HurricaneWarning; + using Isobar::ParseOneArg; + using Isobar::ParseTwoArg; + using Isobar::__cs; + using Isobar::PyCell; + using Isobar::PyTypeCell; + using Isobar::PyCell_Link; + using Isobar::PyLibrary; + using Isobar::PyTypeLibrary; + using Isobar::PyLibrary_Link; + + +extern "C" { + + +#if defined(__PYTHON_MODULE__) + +// +=================================================================+ +// | "PyGds" Python Module Code Part | +// +=================================================================+ + + + static PyObject* PyGds_save ( PyObject*, PyObject* args ) + { + cdebug_log(30,0) << "PyGds_save()" << endl; + + Cell* cell = NULL; + + HTRY + PyObject* pyCell = NULL; + if (PyArg_ParseTuple( args, "O:Gds.save", &pyCell )) { + if (IsPyCell(pyCell)) { + Gds::save( PYCELL_O(pyCell) ); + } else { + PyErr_SetString( ConstructorError, "Gds.load(): Bad parameter type (not a Cell)." ); + return NULL; + } + } else { + PyErr_SetString( ConstructorError, "Gds.load(): Bad number of parameters." ); + return NULL; + } + HCATCH + + Py_RETURN_NONE; + } + + + static PyObject* PyGds_load ( PyObject*, PyObject* args ) + { + cdebug_log(30,0) << "PyGds_load()" << endl; + + Library* library = NULL; + char* path = NULL; + + HTRY + PyObject* pyLibrary = NULL; + if (PyArg_ParseTuple( args, "Os:Gds.load", &pyLibrary, &path )) { + if (IsPyLibrary(pyLibrary)) { + Gds::load( PYLIBRARY_O(pyLibrary), string(path) ); + } else { + PyErr_SetString( ConstructorError, "Gds.load(): Bad parameter type (not a Library)." ); + return NULL; + } + } else { + PyErr_SetString( ConstructorError, "Gds.load(): Bad number of parameters." ); + return NULL; + } + HCATCH + + Py_RETURN_NONE; + } + + + // Standart Destroy (Attribute). + + + PyMethodDef PyGds_Methods[] = + { { "save" , (PyCFunction)PyGds_save , METH_VARARGS|METH_STATIC + , "Save a complete Gds design." } + , { "load" , (PyCFunction)PyGds_load , METH_VARARGS|METH_STATIC + , "Load a Gds layout inside a Cell (cumulative)." } + , {NULL, NULL, 0, NULL} /* sentinel */ + }; + + + NoObjectDeleteMethod(Gds) + PyTypeObjectLinkPyTypeWithoutObject(Gds,Gds) + + +#else // End of Python Module Code Part. + + +// +=================================================================+ +// | "PyGds" Shared Library Code Part | +// +=================================================================+ + + // Type Definition. + PyTypeObjectDefinitionsOfModule(CRL,Gds) + + +#endif // End of Shared Library Code Part. + +} // extern "C". + +} // CRL namespace. diff --git a/crlcore/src/pyCRL/crlcore/PyGds.h b/crlcore/src/pyCRL/crlcore/PyGds.h new file mode 100644 index 00000000..5ade37c9 --- /dev/null +++ b/crlcore/src/pyCRL/crlcore/PyGds.h @@ -0,0 +1,55 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2018-2018, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Alliance / Hurricane Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/PyGds.h" | +// +-----------------------------------------------------------------+ + + +#ifndef CRL_PY_GDS_H +#define CRL_PY_GDS_H + +#include "hurricane/isobar/PyHurricane.h" +#include "crlcore/Gds.h" + + +namespace CRL { + +extern "C" { + + +// ------------------------------------------------------------------- +// Python Object : "PyGds". + + typedef struct { + PyObject_HEAD + } PyGds; + + +// ------------------------------------------------------------------- +// Functions & Types exported to "PyCRL.ccp". + + extern PyTypeObject PyTypeGds; + extern PyMethodDef PyGds_Methods[]; + + extern void PyGds_LinkPyType(); + + +#define IsPyGds(v) ( (v)->ob_type == &PyTypeGds ) +#define PY_GDS(v) ( (PyGds*)(v) ) + + +} // extern "C". + +} // Hurricane namespace. + +#endif // CRL_PY_GDS_H diff --git a/documentation/examples/scripts/diagonals.py b/documentation/examples/scripts/diagonals.py index 9c2311c3..a57865b2 100644 --- a/documentation/examples/scripts/diagonals.py +++ b/documentation/examples/scripts/diagonals.py @@ -76,8 +76,7 @@ def buildDiagonals ( editor ): UpdateSession.close() - #AllianceFramework.get().saveCell( cell, Catalog.State.Views ) - # No saving as we don't have a GDSII driver (yet). + Gds.save( cell ) return diff --git a/documentation/examples/scripts/fulladder.py b/documentation/examples/scripts/fulladder.py index 8155c099..c4154b5a 100644 --- a/documentation/examples/scripts/fulladder.py +++ b/documentation/examples/scripts/fulladder.py @@ -44,11 +44,11 @@ def buildFulladder ( editor ): vss = Net.create( fulladder, "vss" ) vss.setExternal( True ) vss.setGlobal ( True ) - + vdd = Net.create( fulladder, "vdd" ) vdd.setExternal( True ) vdd.setGlobal ( True ) - + cin = Net.create( fulladder, "cin" ) cin.setExternal( True ) xr2_2.getPlug( xr2_x2.getNet('i0') ).setNet( cin ) @@ -72,11 +72,11 @@ def buildFulladder ( editor ): carry_1 = Net.create( fulladder, 'carry_1' ) a2_1.getPlug( a2_x2.getNet('q' ) ).setNet( carry_1 ) o2_1.getPlug( o2_x2.getNet('i1') ).setNet( carry_1 ) - + carry_2 = Net.create( fulladder, 'carry_2' ) a2_2.getPlug( a2_x2.getNet('q' ) ).setNet( carry_2 ) o2_1.getPlug( o2_x2.getNet('i0') ).setNet( carry_2 ) - + sout = Net.create( fulladder, 'sout' ) sout.setExternal( True ) xr2_2.getPlug( xr2_x2.getNet('q') ).setNet( sout ) @@ -90,56 +90,56 @@ def buildFulladder ( editor ): , toDbU(0.0) , Transformation.Orientation.ID ) ) a2_1.setPlacementStatus( Instance.PlacementStatus.PLACED ) - doBreak( 1, 'Placed a2_1' ) - + #doBreak( 1, 'Placed a2_1' ) + xr2_1.setTransformation( Transformation( toDbU( 0.0) , toDbU(100.0) , Transformation.Orientation.MY ) ) xr2_1.setPlacementStatus( Instance.PlacementStatus.PLACED ) - doBreak( 1, 'Placed xr2_1' ) - + #doBreak( 1, 'Placed xr2_1' ) + a2_2.setTransformation( Transformation( toDbU(25.0) , toDbU( 0.0) , Transformation.Orientation.ID ) ) a2_2.setPlacementStatus( Instance.PlacementStatus.PLACED ) - doBreak( 1, 'Placed a2_2' ) - + #doBreak( 1, 'Placed a2_2' ) + xr2_2.setTransformation( Transformation( toDbU( 45.0) , toDbU(100.0) , Transformation.Orientation.MY ) ) xr2_2.setPlacementStatus( Instance.PlacementStatus.PLACED ) - doBreak( 1, 'Placed xr2_2' ) - + #doBreak( 1, 'Placed xr2_2' ) + o2_1.setTransformation( Transformation( toDbU(65.0) , toDbU( 0.0) , Transformation.Orientation.ID ) ) o2_1.setPlacementStatus( Instance.PlacementStatus.PLACED ) - doBreak( 1, 'Placed o2_1' ) + #doBreak( 1, 'Placed o2_1' ) # Add filler cells. tie_x0 = af.getCell( 'tie_x0', Catalog.State.Views ) rowend_x0 = af.getCell( 'rowend_x0', Catalog.State.Views ) filler_1 = Instance.create( fulladder, 'filler_1', tie_x0 ) filler_2 = Instance.create( fulladder, 'filler_2', rowend_x0 ) - + filler_1.setTransformation( Transformation( toDbU(50.0) , toDbU( 0.0) , Transformation.Orientation.ID ) ) filler_1.setPlacementStatus( Instance.PlacementStatus.PLACED ) - + filler_2.setTransformation( Transformation( toDbU(60.0) , toDbU( 0.0) , Transformation.Orientation.ID ) ) filler_2.setPlacementStatus( Instance.PlacementStatus.PLACED ) - doBreak( 1, 'Filler cell placeds' ) - + #doBreak( 1, 'Filler cell placeds' ) + # # Getting the layers. technology = DataBase.getDB().getTechnology() metal2 = technology.getLayer( "METAL2" ) metal3 = technology.getLayer( "METAL3" ) via12 = technology.getLayer( "VIA12" ) via23 = technology.getLayer( "VIA23" ) - + # Build wiring for a. # Create RoutingPads first. rp1 = RoutingPad.create( a @@ -148,7 +148,7 @@ def buildFulladder ( editor ): rp2 = RoutingPad.create( a , Occurrence( a2_1.getPlug( a2_x2.getNet("i0")) ) , RoutingPad.BiggestArea ) - + # Then regular wiring. contact1 = Contact.create( rp1, via12, toDbU( 0.0), toDbU(-15.0) ) contact2 = Contact.create( rp2, via12, toDbU( 0.0), toDbU( 10.0) ) @@ -159,6 +159,7 @@ def buildFulladder ( editor ): UpdateSession.close() af.saveCell( fulladder, Catalog.State.Views ) + Gds.save( fulladder ) return diff --git a/hurricane/src/hurricane/CMakeLists.txt b/hurricane/src/hurricane/CMakeLists.txt index b6c2e920..09c4c720 100644 --- a/hurricane/src/hurricane/CMakeLists.txt +++ b/hurricane/src/hurricane/CMakeLists.txt @@ -79,6 +79,7 @@ hurricane/Relation.h hurricane/RoutingPad.h hurricane/RoutingPads.h hurricane/Diagonal.h + hurricane/Rectilinear.h hurricane/Rubber.h hurricane/Rubbers.h hurricane/Segment.h hurricane/Segments.h hurricane/Selectors.h @@ -163,6 +164,7 @@ Pad.cpp RoutingPad.cpp Diagonal.cpp + Rectilinear.cpp Polygon.cpp NetExternalComponents.cpp NetRoutingProperty.cpp diff --git a/hurricane/src/hurricane/Component.cpp b/hurricane/src/hurricane/Component.cpp index 23678d95..8548f38d 100644 --- a/hurricane/src/hurricane/Component.cpp +++ b/hurricane/src/hurricane/Component.cpp @@ -280,6 +280,57 @@ class Component_SlaveComponents : public Collection { }; +// ------------------------------------------------------------------- +// Class : "Component::Points_Contour". + + Component::Points_Contour::Locator::Locator ( const Component* component ) + : PointHL () + , _component(component) + , _iPoint (0) + { } + + + PointHL* Component::Points_Contour::Locator::getClone () const + { return new Locator(*this); } + + + Point Component::Points_Contour::Locator::getElement () const + { return _component->getPoint(_iPoint); } + + + bool Component::Points_Contour::Locator::isValid () const + { return (_iPoint < _component->getPointsSize()); } + + + void Component::Points_Contour::Locator::progress () + { if (isValid()) ++_iPoint; } + + + string Component::Points_Contour::Locator::_getString () const + { + string s = "<" + _TName("Points_Contour::Locator") + + getString(getElement()) + + ">"; + return s; + } + + + PointHC* Component::Points_Contour::getClone () const + { return new Points_Contour(*this); } + + + PointHL* Component::Points_Contour::getLocator () const + { return new Locator(_component); } + + + string Component::Points_Contour::_getString () const + { + string s = "<" + _TName("Points_Contour") + " " + + getString(_component) + + ">"; + return s; + } + // **************************************************************************************************** // Component implementation @@ -463,6 +514,35 @@ void Component::_preDestroy() cdebug_tabw(18,-1); } + +bool Component::isNonRectangle () const +{ return false; } + + +bool Component::isManhattanized () const +{ return false; } + + +size_t Component::getPointsSize () const { return 4; } + + +Point Component::getPoint ( size_t i ) const +{ + Box bb = getBoundingBox(); + switch ( i % getPointsSize() ) { + default: // To shut up gcc. + case 0: return bb.getCornerBL(); + case 1: return bb.getCornerTL(); + case 2: return bb.getCornerTR(); + case 3: return bb.getCornerBR(); + } +} + + +Points Component::getMContour () const +{ return getContour(); } + + void Component::_toJson( JsonWriter* writer ) const // ************************************************ { diff --git a/hurricane/src/hurricane/Diagonal.cpp b/hurricane/src/hurricane/Diagonal.cpp index 3b02597a..833e9cec 100644 --- a/hurricane/src/hurricane/Diagonal.cpp +++ b/hurricane/src/hurricane/Diagonal.cpp @@ -78,6 +78,7 @@ namespace Hurricane { } + bool Diagonal::isNonRectangle () const { return true; } DbU::Unit Diagonal::getX () const { return (_target.getX() + _source.getX()) / 2; } DbU::Unit Diagonal::getY () const { return (_target.getX() + _source.getX()) / 2; } DbU::Unit Diagonal::getSourceX () const { return _source.getX(); } @@ -276,58 +277,6 @@ namespace Hurricane { return record; } - -// ------------------------------------------------------------------- -// Class : "Diagonal::Points_Contour". - - Diagonal::Points_Contour::Locator::Locator ( const Diagonal* diagonal ) - : PointHL () - , _diagonal(diagonal) - , _iPoint (0) - { } - - - PointHL* Diagonal::Points_Contour::Locator::getClone () const - { return new Locator(*this); } - - - Point Diagonal::Points_Contour::Locator::getElement () const - { return _diagonal->getPoint(_iPoint); } - - - bool Diagonal::Points_Contour::Locator::isValid () const - { return (_iPoint < _diagonal->getPointsSize()); } - - - void Diagonal::Points_Contour::Locator::progress () - { if (isValid()) ++_iPoint; } - - - string Diagonal::Points_Contour::Locator::_getString () const - { - string s = "<" + _TName("Points_Contour::Locator") - + getString(getElement()) - + ">"; - return s; - } - - - PointHC* Diagonal::Points_Contour::getClone () const - { return new Points_Contour(*this); } - - - PointHL* Diagonal::Points_Contour::getLocator () const - { return new Locator(_diagonal); } - - - string Diagonal::Points_Contour::_getString () const - { - string s = "<" + _TName("Points_Contour") + " " - + getString(_diagonal) - + ">"; - return s; - } - // ------------------------------------------------------------------- // Class : "JsonDiagonal". diff --git a/hurricane/src/hurricane/Polygon.cpp b/hurricane/src/hurricane/Polygon.cpp index 65bc9e6d..e832bad0 100644 --- a/hurricane/src/hurricane/Polygon.cpp +++ b/hurricane/src/hurricane/Polygon.cpp @@ -232,10 +232,26 @@ namespace Hurricane { } + bool Polygon::isNonRectangle () const + { return true; } + + + bool Polygon::isManhattanized () const + { return not _edges.empty(); } + + const Layer* Polygon::getLayer () const { return _layer; }; + size_t Polygon::getPointsSize () const + { return _points.size(); } + + + Point Polygon::getPoint ( size_t i ) const + { return _points[ i % _points.size() ]; } + + DbU::Unit Polygon::getX () const { DbU::Unit center = 0; @@ -276,6 +292,10 @@ namespace Hurricane { return getBoundingBox(); } + + Points Polygon::getMContour () const + { return Points_Manhattan(this); } + void Polygon::translate ( const DbU::Unit& dx, const DbU::Unit& dy ) { diff --git a/hurricane/src/hurricane/Rectilinear.cpp b/hurricane/src/hurricane/Rectilinear.cpp new file mode 100644 index 00000000..68d21855 --- /dev/null +++ b/hurricane/src/hurricane/Rectilinear.cpp @@ -0,0 +1,239 @@ +// -*- 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 +// . +// +// +-----------------------------------------------------------------+ +// | 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 : "./Rectilinear.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/Rectilinear.h" +#include "hurricane/Net.h" +#include "hurricane/BasicLayer.h" +#include "hurricane/Layer.h" +#include "hurricane/Error.h" + + +namespace Hurricane { + + +// ------------------------------------------------------------------- +// Class : "Rectilinear". + + Rectilinear::Rectilinear ( Net* net, const Layer* layer, const vector& points ) + : Super (net) + , _layer (layer) + , _points(points) + { } + + + Rectilinear* Rectilinear::create ( Net* net, const Layer* layer, const vector& points ) + { + if (not layer) + throw Error( "Rectilinear::create(): Can't create, NULL layer" ); + + for ( size_t i=0 ; i_postCreate(); + + return rectilinear; + } + + + + + bool Rectilinear::isNonRectangle () const { return true; } + const Layer* Rectilinear::getLayer () const { return _layer; } + DbU::Unit Rectilinear::getX () const { return getBoundingBox().getCenter().getX(); } + DbU::Unit Rectilinear::getY () const { return getBoundingBox().getCenter().getY(); } + + + Box Rectilinear::getBoundingBox() const + { + DbU::Unit xmin = DbU::Max; + DbU::Unit ymin = DbU::Max; + DbU::Unit xmax = DbU::Min; + DbU::Unit ymax = DbU::Min; + + for ( Point p : _points ) { + xmin = std::min( xmin, p.getX() ); + ymin = std::min( ymin, p.getY() ); + xmax = std::max( xmax, p.getX() ); + ymax = std::max( ymax, p.getY() ); + } + + return Box( xmin, ymin, xmax, ymax ); + } + + + Box Rectilinear::getBoundingBox ( const BasicLayer* basicLayer ) const + { + if (not _layer->contains(basicLayer)) return Box(); + return getBoundingBox(); + } + + + void Rectilinear::translate ( const DbU::Unit& dx, const DbU::Unit& dy ) + { + if ( (dx != 0) or (dy != 0) ) { + invalidate( true ); + for ( Point& p : _points ) p.translate( dx, dy ); + } + } + + + void Rectilinear::setLayer ( const Layer* layer ) + { + if (not layer) throw Error( "Rectilinear::setLayer(): Can't set layer, NULL layer" ); + + if (layer != _layer) { + invalidate( false ); + _layer = layer; + } + } + + + void Rectilinear::setPoints ( const vector& points ) + { + for ( size_t i=0 ; igetName() ); + } + + + string Rectilinear::_getTypeName () const + { return _TName( "Rectilinear" ); } + + + string Rectilinear::_getString () const + { + string s = Super::_getString(); + s.insert( s.length() - 1, " " + getString(_layer->getName()) ); + s.insert( s.length() - 1, " points:" + getString(_points.size()) ); + return s; + } + + + Record* Rectilinear::_getRecord () const + { + Record* record = Super::_getRecord(); + if (record) { + record->add( getSlot("_layer" , _layer ) ); + record->add( getSlot("_points", &_points) ); + } + return record; + } + + +// ------------------------------------------------------------------- +// Class : "JsonRectilinear". + + + Initializer jsonRectilinearInit ( 0 ); + + + void JsonRectilinear::initialize () + { JsonTypes::registerType( new JsonRectilinear (JsonWriter::RegisterMode) ); } + + + JsonRectilinear::JsonRectilinear ( unsigned long flags ) + : JsonComponent(flags) + { + add( "_layer" , typeid(string) ); + } + + + string JsonRectilinear::getTypeName () const + { return "Rectilinear"; } + + + JsonRectilinear* JsonRectilinear::clone ( unsigned long flags ) const + { return new JsonRectilinear ( flags ); } + + + void JsonRectilinear::toData ( JsonStack& stack ) + { + check( stack, "JsonRectilinear::toData" ); + unsigned int jsonId = presetId( stack ); + + vector points; + + // Have to loop over all the points. + //points.push_back( get(stack,".Point") ); + + Rectilinear* rectilinear = Rectilinear::create + ( get(stack,".Net") + , DataBase::getDB()->getTechnology()->getLayer( get(stack,"_layer") ) + , points + ); + + JsonNet* jnet = jget( stack ); + if (jnet) { + jnet->addHookLink( rectilinear->getBodyHook (), jsonId, get(stack,"_bodyHook" ) ); + } else { + cerr << Error( "Jsonrectilinear::toData(): Missing (Json)Net in stack context." ) << endl; + } + + // Hook/Ring rebuild are done as a post-process. + update( stack, rectilinear ); +} + + +} // Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Box.h b/hurricane/src/hurricane/hurricane/Box.h index 0c5daf39..cbe646fe 100644 --- a/hurricane/src/hurricane/hurricane/Box.h +++ b/hurricane/src/hurricane/hurricane/Box.h @@ -70,6 +70,10 @@ class Box { public: DbU::Unit getXCenter() const {return ((_xMin + _xMax) / 2);}; public: DbU::Unit getYCenter() const {return ((_yMin + _yMax) / 2);}; public: Point getCenter() const {return Point(getXCenter(), getYCenter());}; + public: Point getCornerBL() const { return Point(_xMin,_yMin); } + public: Point getCornerTL() const { return Point(_xMin,_yMax); } + public: Point getCornerTR() const { return Point(_xMax,_yMax); } + public: Point getCornerBR() const { return Point(_xMax,_yMin); } public: DbU::Unit getWidth() const {return (_xMax - _xMin);}; public: DbU::Unit getHalfWidth() const {return (getWidth() / 2);}; diff --git a/hurricane/src/hurricane/hurricane/Component.h b/hurricane/src/hurricane/hurricane/Component.h index faf9118a..328e865c 100644 --- a/hurricane/src/hurricane/hurricane/Component.h +++ b/hurricane/src/hurricane/hurricane/Component.h @@ -17,136 +17,167 @@ // not, see . // **************************************************************************************************** -#ifndef HURRICANE_COMPONENT -#define HURRICANE_COMPONENT +#ifndef HURRICANE_COMPONENT_H +#define HURRICANE_COMPONENT_H + +#include "hurricane/Points.h" #include "hurricane/Go.h" #include "hurricane/Components.h" #include "hurricane/Hook.h" #include "hurricane/Hooks.h" #include "hurricane/Interval.h" + namespace Hurricane { -class Net; -class Rubber; -class Layer; + class Net; + class Rubber; + class Layer; -// **************************************************************************************************** -// Component declaration -// **************************************************************************************************** +// ------------------------------------------------------------------- +// Class : "Component". -class Component : public Go { -// ************************ + class Component : public Go { + public: + typedef Go Inherit; -// Types -// ***** + public: + class Points_Contour : public PointHC { + public: + class Locator : public PointHL { + public: + Locator ( const Component* ); + inline Locator ( const Locator& ); + virtual Point getElement () const; + virtual PointHL* getClone () const; + virtual bool isValid () const; + virtual void progress (); + virtual string _getString () const; + protected: + const Component* _component; + size_t _iPoint; + }; + public: + inline Points_Contour ( const Component* ); + inline Points_Contour ( const Points_Contour& ); + virtual PointHC* getClone () const; + virtual PointHL* getLocator () const; + virtual string _getString () const; + protected: + const Component* _component; + }; - public: typedef Go Inherit; + public: + class BodyHook : public Hook { + friend class Component; + public: + typedef Hook Inherit; + public: + virtual Component* getComponent () const; + virtual bool isMaster () const {return true;}; + virtual string _getTypeName () const { return "Component::BodyHook"; }; + virtual string _getString () const; + static Hook* _compToHook ( Component* ); + private: + BodyHook ( Component* ); + }; - public: class BodyHook : public Hook { - // ********************************* - - friend class Component; - - public: typedef Hook Inherit; - - private: BodyHook(Component* component); - - public: virtual Component* getComponent() const; - - public: virtual bool isMaster() const {return true;}; - - public: virtual string _getTypeName() const { return "Component::BodyHook"; }; - public: virtual string _getString() const; - public: static Hook* _compToHook(Component*); - - }; - -// Attributes -// ********** - - private: Net* _net; - private: Rubber* _rubber; - private: BodyHook _bodyHook; - private: Component* _nextOfNetComponentSet; - -// Constructors -// ************ - - protected: Component(Net* net, bool inPlugCreate = false); - -// Accessors -// ********* - - public: virtual Cell* getCell() const; - public: Net* getNet() const {return _net;}; - public: Rubber* getRubber() const {return _rubber;}; - public: Hook* getBodyHook() {return &_bodyHook;}; - public: virtual Hooks getHooks() const; - public: virtual DbU::Unit getX() const = 0; - public: virtual DbU::Unit getY() const = 0; - public: virtual Point getPosition() const {return Point(getX(), getY());}; - public: virtual Point getCenter() const {return getPosition();}; - public: virtual const Layer* getLayer() const = 0; - public: virtual Box getBoundingBox() const = 0; - public: virtual Box getBoundingBox(const BasicLayer* basicLayer) const = 0; - public: Components getConnexComponents() const; - public: Components getSlaveComponents() const; - -// Updators -// ******** - - public: virtual void materialize(); - public: virtual void unmaterialize(); - public: virtual void invalidate(bool propagateFlag = true); - public: virtual void forceId(unsigned int id); - -// Filters -// ******* - - public: static ComponentFilter getIsUnderFilter(const Box& area); - -// Others -// ****** - - protected: virtual void _postCreate(); - - protected: virtual void _preDestroy(); - - public: virtual void _toJson ( JsonWriter* ) const; - public: virtual void _toJsonSignature(JsonWriter*) const; - public: virtual string _getString() const; - public: virtual Record* _getRecord() const; - public: Component* _getNextOfNetComponentSet() const {return _nextOfNetComponentSet;}; - - public: void _setNet(Net* net); - public: void _setRubber(Rubber* rubber); - public: void _setNextOfNetComponentSet(Component* component) {_nextOfNetComponentSet = component;}; - -}; + protected: + Component ( Net* , bool inPlugCreate = false ); + public: + // Accessors. + virtual bool isManhattanized () const; + virtual bool isNonRectangle () const; + virtual Cell* getCell () const; + Net* getNet () const { return _net; }; + Rubber* getRubber () const { return _rubber; }; + Hook* getBodyHook () { return &_bodyHook; }; + virtual Hooks getHooks () const; + virtual DbU::Unit getX () const = 0; + virtual DbU::Unit getY () const = 0; + virtual Point getPosition () const { return Point( getX(), getY() ); }; + virtual Point getCenter () const { return getPosition(); }; + virtual const Layer* getLayer () const = 0; + virtual size_t getPointsSize () const; + virtual Point getPoint ( size_t ) const; + virtual Box getBoundingBox () const = 0; + virtual Box getBoundingBox ( const BasicLayer* ) const = 0; + inline Points getContour () const; + virtual Points getMContour () const; + Components getConnexComponents () const; + Components getSlaveComponents () const; + // Mutators. + virtual void materialize (); + virtual void unmaterialize (); + virtual void invalidate ( bool propagateFlag = true ); + virtual void forceId ( unsigned int id ); + // Filters + static ComponentFilter getIsUnderFilter ( const Box& area ); + // Others + protected: + virtual void _postCreate (); + virtual void _preDestroy (); + public: + virtual void _toJson ( JsonWriter* ) const; + virtual void _toJsonSignature ( JsonWriter* ) const; + virtual string _getString () const; + virtual Record* _getRecord () const; + Component* _getNextOfNetComponentSet () const {return _nextOfNetComponentSet;}; + void _setNet ( Net* ); + void _setRubber ( Rubber* ); + void _setNextOfNetComponentSet ( Component* component ) { _nextOfNetComponentSet = component; }; + private: + Net* _net; + Rubber* _rubber; + BodyHook _bodyHook; + Component* _nextOfNetComponentSet; + }; -double getArea ( Component* component ); + inline Points Component::getContour () const { return Points_Contour(this); } + + + inline Component::Points_Contour::Locator::Locator ( const Locator &locator ) + : PointHL () + , _component(locator._component) + , _iPoint (locator._iPoint) + { } -class JsonComponent : public JsonEntity { -// ************************************ - - public: JsonComponent(unsigned long flags); -}; + inline Component::Points_Contour::Points_Contour ( const Component* component ) + : PointHC () + , _component(component) + { } -} // End of Hurricane namespace. + inline Component::Points_Contour::Points_Contour ( const Points_Contour& other ) + : PointHC () + , _component(other._component) + { } + + + double getArea ( Component* component ); + + +// ------------------------------------------------------------------- +// Class : "JsonComponent". + + class JsonComponent : public JsonEntity { + public: + JsonComponent ( unsigned long flags ); + }; + + +} // Hurricane namespace. INSPECTOR_P_SUPPORT(Hurricane::Component); INSPECTOR_P_SUPPORT(Hurricane::Component::BodyHook); -#endif // HURRICANE_COMPONENT - +#endif // HURRICANE_COMPONENT_H // **************************************************************************************************** // Copyright (c) BULL S.A. 2000-2018, All Rights Reserved diff --git a/hurricane/src/hurricane/hurricane/Diagonal.h b/hurricane/src/hurricane/hurricane/Diagonal.h index 4ae70c9f..f87d43d2 100644 --- a/hurricane/src/hurricane/hurricane/Diagonal.h +++ b/hurricane/src/hurricane/hurricane/Diagonal.h @@ -32,7 +32,6 @@ #ifndef HURRICANE_DIAGONAL_H #define HURRICANE_DIAGONAL_H -#include "hurricane/Points.h" #include "hurricane/Component.h" @@ -47,36 +46,11 @@ namespace Hurricane { class Diagonal : public Component { public: typedef Component Super; - - public: - class Points_Contour : public PointHC { - public: - class Locator : public PointHL { - public: - Locator ( const Diagonal* ); - inline Locator ( const Locator& ); - virtual Point getElement () const; - virtual PointHL* getClone () const; - virtual bool isValid () const; - virtual void progress (); - virtual string _getString () const; - protected: - const Diagonal* _diagonal; - size_t _iPoint; - }; - public: - inline Points_Contour ( const Diagonal* ); - inline Points_Contour ( const Points_Contour& ); - virtual PointHC* getClone () const; - virtual PointHL* getLocator () const; - virtual string _getString () const; - protected: - const Diagonal* _diagonal; - }; public: static Diagonal* create ( Net*, const Layer*, const Point& source, const Point& target, DbU::Unit width ); // Accessors. + virtual bool isNonRectangle () const; virtual DbU::Unit getX () const; virtual DbU::Unit getY () const; virtual DbU::Unit getSourceX () const; @@ -87,11 +61,10 @@ namespace Hurricane { virtual Point getTargetPosition () const; virtual Box getBoundingBox () const; virtual Box getBoundingBox ( const BasicLayer* ) const; - size_t getPointsSize () const; - Point getPoint ( size_t i ) const; + virtual size_t getPointsSize () const; + virtual Point getPoint ( size_t i ) const; DbU::Unit getWidth () const; virtual const Layer* getLayer () const; - inline Points getContour () const; // Mutators. void setLayer ( const Layer* ); void setWidth ( DbU::Unit ); @@ -116,28 +89,6 @@ namespace Hurricane { }; - inline Points Diagonal::getContour () const { return Points_Contour(this); } - - - inline Diagonal::Points_Contour::Locator::Locator ( const Locator &locator ) - : PointHL () - , _diagonal(locator._diagonal) - , _iPoint (locator._iPoint) - { } - - - inline Diagonal::Points_Contour::Points_Contour ( const Diagonal* diagonal ) - : PointHC () - , _diagonal(diagonal) - { } - - - inline Diagonal::Points_Contour::Points_Contour ( const Points_Contour& other ) - : PointHC () - , _diagonal(other._diagonal) - { } - - // ------------------------------------------------------------------- // Class : "JsonRoutingDiagonal". diff --git a/hurricane/src/hurricane/hurricane/Polygon.h b/hurricane/src/hurricane/hurricane/Polygon.h index 03542970..0a885777 100644 --- a/hurricane/src/hurricane/hurricane/Polygon.h +++ b/hurricane/src/hurricane/hurricane/Polygon.h @@ -32,7 +32,6 @@ #ifndef HURRICANE_POLYGON_H #define HURRICANE_POLYGON_H -#include "hurricane/Points.h" #include "hurricane/Component.h" #include "hurricane/Polygons.h" @@ -109,12 +108,14 @@ namespace Hurricane { static Polygon* create ( Net*, const Layer*, const std::vector& ); static float getSlope ( const Point&, const Point& ); public: - inline bool isManhattanized () const; + virtual bool isNonRectangle () const; + virtual bool isManhattanized () const; virtual DbU::Unit getX () const; virtual DbU::Unit getY () const; inline const vector& getPoints () const; inline const vector& getEdges () const; - inline const Point& getPoint ( size_t ) const; + virtual size_t getPointsSize () const; + virtual Point getPoint ( size_t ) const; virtual Box getBoundingBox () const; virtual Box getBoundingBox ( const BasicLayer* ) const; virtual const Layer* getLayer () const; @@ -124,7 +125,7 @@ namespace Hurricane { static float getSign ( const vector&, size_t ); float getSlope ( size_t i ) const; void manhattanize (); - inline Points getContour () const; + virtual Points getMContour () const; virtual void _toJson ( JsonWriter* ) const; static JsonObject* getJsonObject ( unsigned long flags ); virtual string _getTypeName () const; @@ -140,11 +141,8 @@ namespace Hurricane { }; - inline bool Polygon::isManhattanized () const { return not _edges.empty(); } inline const vector& Polygon::getEdges () const { return _edges; } inline const vector& Polygon::getPoints () const { return _points; } - inline const Point& Polygon::getPoint ( size_t i ) const { return _points[ (i<_points.size()) ? i : 0 ]; } - inline Points Polygon::getContour () const { return Points_Manhattan(this); } inline bool Polygon::Edge::isClockwise () const { return (_flags & Polygon::Clockwise); } inline bool Polygon::Edge::isYIncrease () const { return (_flags & Polygon::YIncrease); } diff --git a/hurricane/src/hurricane/hurricane/Rectilinear.h b/hurricane/src/hurricane/hurricane/Rectilinear.h new file mode 100644 index 00000000..670e4a85 --- /dev/null +++ b/hurricane/src/hurricane/hurricane/Rectilinear.h @@ -0,0 +1,98 @@ +// -*- 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 +// . +// +// +-----------------------------------------------------------------+ +// | 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/Rectilinear.h" | +// +-----------------------------------------------------------------+ + + +#ifndef HURRICANE_RECTILINEAR_H +#define HURRICANE_RECTILINEAR_H + +#include "hurricane/Component.h" + + +namespace Hurricane { + + class Layer; + + +// ------------------------------------------------------------------- +// Class : "Rectilinear". + + class Rectilinear : public Component { + public: + typedef Component Super; + + public: + static Rectilinear* create ( Net*, const Layer*, const vector& ); + // Accessors. + virtual bool isNonRectangle () const; + virtual DbU::Unit getX () const; + virtual DbU::Unit getY () const; + virtual Box getBoundingBox () const; + virtual Box getBoundingBox ( const BasicLayer* ) const; + virtual size_t getPointsSize () const; + virtual Point getPoint ( size_t i ) const; + virtual const Layer* getLayer () const; + inline Points getContour () const; + // Mutators. + void setLayer ( const Layer* ); + virtual void translate ( const DbU::Unit& dx, const DbU::Unit& dy ); + void setPoints ( const vector& ); + // Hurricane management. + virtual void _toJson ( JsonWriter* ) const; + static JsonObject* getJsonObject ( unsigned long flags ); + virtual string _getTypeName () const; + virtual string _getString () const; + virtual Record* _getRecord () const; + protected: + Rectilinear ( Net*, const Layer*, const vector& ); + private: + const Layer* _layer; + vector _points; + }; + + +// ------------------------------------------------------------------- +// Class : "JsonRoutingRectilinear". + + class JsonRectilinear : public JsonComponent { + public: + static void initialize (); + JsonRectilinear ( unsigned long flags ); + virtual std::string getTypeName () const; + virtual JsonRectilinear* clone ( unsigned long ) const; + virtual void toData ( JsonStack& ); + }; + + +} // Hurricane namespace. + + +INSPECTOR_P_SUPPORT(Hurricane::Rectilinear); + +#endif // HURRICANE_RECTILINEAR_H diff --git a/hurricane/src/isobar/CMakeLists.txt b/hurricane/src/isobar/CMakeLists.txt index 22612fe2..5a078754 100644 --- a/hurricane/src/isobar/CMakeLists.txt +++ b/hurricane/src/isobar/CMakeLists.txt @@ -67,6 +67,7 @@ PySegmentCollection.cpp PyTechnology.cpp PyTransformation.cpp + PyRectilinear.cpp PyPolygon.cpp PyOrientation.cpp PyDbU.cpp @@ -135,6 +136,7 @@ hurricane/isobar/PySegmentCollection.h hurricane/isobar/PyTechnology.h hurricane/isobar/PyTransformation.h + hurricane/isobar/PyRectilinear.h hurricane/isobar/PyPolygon.h hurricane/isobar/PyOrientation.h hurricane/isobar/PyDbU.h diff --git a/hurricane/src/isobar/PyHurricane.cpp b/hurricane/src/isobar/PyHurricane.cpp index 240470c0..a3e0aff4 100644 --- a/hurricane/src/isobar/PyHurricane.cpp +++ b/hurricane/src/isobar/PyHurricane.cpp @@ -73,6 +73,7 @@ #include "hurricane/isobar/PyVertical.h" #include "hurricane/isobar/PyPad.h" #include "hurricane/isobar/PyDiagonal.h" +#include "hurricane/isobar/PyRectilinear.h" #include "hurricane/isobar/PyPolygon.h" #include "hurricane/isobar/PyPath.h" #include "hurricane/isobar/PyOccurrence.h" @@ -572,7 +573,7 @@ extern "C" { PyHorizontal_LinkPyType (); PyContact_LinkPyType (); PyPin_LinkPyType (); - PyPolygon_LinkPyType (); + PyRectilinear_LinkPyType (); PyPlug_LinkPyType (); PyPolygon_LinkPyType (); PyBreakpoint_LinkPyType (); @@ -658,6 +659,7 @@ extern "C" { PYTYPE_READY_SUB ( Plug , Component) PYTYPE_READY_SUB ( Pad , Component) PYTYPE_READY_SUB ( Diagonal , Component) + PYTYPE_READY_SUB ( Rectilinear , Component) PYTYPE_READY_SUB ( Polygon , Component) // Identifier string can take up to 10 characters ! @@ -711,6 +713,7 @@ extern "C" { __cs.addType ( "segment" , &PyTypeSegment , "" , false, "comp" ); __cs.addType ( "pad " , &PyTypePad , "" , false, "comp" ); __cs.addType ( "diagonal" , &PyTypeDiagonal , "" , false, "comp" ); + __cs.addType ( "rectilin" , &PyTypeRectilinear , "" , false, "comp" ); __cs.addType ( "polygon" , &PyTypePolygon , "" , false, "comp" ); __cs.addType ( "segmentCol" , &PyTypeSegmentCollection , "" , false ); __cs.addType ( "db" , &PyTypeDataBase , "" , false ); @@ -812,6 +815,8 @@ extern "C" { PyModule_AddObject ( module, "Pad" , (PyObject*)&PyTypePad ); Py_INCREF ( &PyTypeDiagonal ); PyModule_AddObject ( module, "Diagonal" , (PyObject*)&PyTypeDiagonal ); + Py_INCREF ( &PyTypeRectilinear ); + PyModule_AddObject ( module, "Rectilinear" , (PyObject*)&PyTypeRectilinear ); Py_INCREF ( &PyTypePolygon ); PyModule_AddObject ( module, "Polygon" , (PyObject*)&PyTypePolygon ); diff --git a/hurricane/src/isobar/PyRectilinear.cpp b/hurricane/src/isobar/PyRectilinear.cpp new file mode 100644 index 00000000..f0d518e1 --- /dev/null +++ b/hurricane/src/isobar/PyRectilinear.cpp @@ -0,0 +1,209 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2018-2018, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | I s o b a r - Hurricane / Python Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./PyRectilinear.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/isobar/PyPoint.h" +#include "hurricane/isobar/PyNet.h" +#include "hurricane/isobar/PyLayer.h" +#include "hurricane/isobar/PyBox.h" +#include "hurricane/isobar/PyRectilinear.h" + + +namespace Isobar { + + using namespace Hurricane; + + + template< typename CppType > + bool ListToVector ( PyObject* list, PyTypeObject* itemType, std::vector& v ) + { + if (not PyList_Check(list)) return false; + + int length = PyList_Size( list ); + for ( int i=0 ; iob_type != itemType) { + string message = "Rectilinear: Item at position " + getString(i) + "has wrong type."; + PyErr_SetString( ConstructorError, message.c_str() ); + return false; + } + v.push_back( *PYPOINT_O(item) ); + } + return true; + } + + +extern "C" { + + +#undef ACCESS_OBJECT +#undef ACCESS_CLASS +#define ACCESS_OBJECT _baseObject._baseObject._object +#define ACCESS_CLASS(_pyObject) &(_pyObject->_baseObject._baseObject) +#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(Rectilinear,rectilinear,function) + + +// +=================================================================+ +// | "PyRectilinear" Python Module Code Part | +// +=================================================================+ + +#if defined(__PYTHON_MODULE__) + + // Standard Accessors (Attributes). + DirectGetLongAttribute(PyRectilinear_getX, getX, PyRectilinear, Rectilinear) + DirectGetLongAttribute(PyRectilinear_getY, getY, PyRectilinear, Rectilinear) + + // Standard Destroy (Attribute). + DBoDestroyAttribute(PyRectilinear_destroy, PyRectilinear) + + + static PyObject* PyRectilinear_create ( PyObject*, PyObject *args ) + { + cdebug_log(20,0) << "PyRectilinear_create()" << endl; + + PyObject* arg0 = NULL; + PyObject* arg1 = NULL; + PyObject* arg2 = NULL; + Rectilinear* rectilinear = NULL; + + HTRY + if (not PyArg_ParseTuple(args, "OOO:Rectilinear.create" ,&arg0 ,&arg1 ,&arg2 )) { + PyErr_SetString( ConstructorError, "Invalid number of parameters for Rectilinear constructor." ); + return NULL; + } + if (not IsPyNet(arg0)) { + PyErr_SetString( ConstructorError, "First parameter of Rectilinear constructor must be a Net." ); + return NULL; + } + if (not IsPyDerivedLayer(arg1)) { + PyErr_SetString( ConstructorError, "Second parameter of Rectilinear constructor must be a Layer." ); + return NULL; + } + + vector points; + if (not ListToVector(arg2,&PyTypePoint,points)) return NULL; + + rectilinear = Rectilinear::create( PYNET_O(arg0), PYDERIVEDLAYER_O(arg1), points ); + HCATCH + + return PyRectilinear_Link(rectilinear); + } + + + static PyObject* PyRectilinear_getBoundingBox ( PyRectilinear *self ) + { + cdebug_log(20,0) << "PyRectilinear_getBoundingBox()" << endl; + + METHOD_HEAD( "Rectilinear.BoundingBox()" ) + + PyBox* pyBox = PyObject_NEW( PyBox, &PyTypeBox ); + if (pyBox == NULL) { return NULL; } + + HTRY + pyBox->_object = new Box ( rectilinear->getBoundingBox() ); + HCATCH + + return (PyObject*)pyBox; + } + + + static PyObject* PyRectilinear_setPoints ( PyRectilinear *self, PyObject* args ) + { + cdebug_log(20,0) << "Rectilinear.setPoints()" << endl; + + HTRY + METHOD_HEAD( "Rectilinear.setPoints()" ) + + PyObject* arg0 = NULL; + PyObject* arg1 = NULL; + PyObject* arg2 = NULL; + if (not PyArg_ParseTuple( args, "O:Rectilinear.setPoints", &arg0 )) { + PyErr_SetString( ConstructorError, "Invalid number of parameters for Rectilinear.setPoints()." ); + return NULL; + } + + vector points; + if (not ListToVector(arg0,&PyTypePoint,points)) return NULL; + + rectilinear->setPoints( points ); + HCATCH + + Py_RETURN_NONE; + } + + + static PyObject* PyRectilinear_translate ( PyRectilinear *self, PyObject* args ) + { + cdebug_log(20,0) << "PyRectilinear_translate ()" << endl; + + HTRY + METHOD_HEAD ( "Rectilinear.translate()" ) + PyObject* arg0 = NULL; + PyObject* arg1 = NULL; + __cs.init ("Rectilinear.translate"); + if (PyArg_ParseTuple(args,"O&O&:Rectilinear.translate", Converter, &arg0, Converter, &arg1)) { + if (__cs.getObjectIds() == INTS2_ARG) rectilinear->translate( PyAny_AsLong(arg0), PyAny_AsLong(arg1) ); + else { + PyErr_SetString ( ConstructorError, "Rectilinear.translate(): Invalid type for parameter(s)." ); + return NULL; + } + } else { + PyErr_SetString ( ConstructorError, "Rectilinear.translate(): Invalid number of parameters." ); + return NULL; + } + HCATCH + + Py_RETURN_NONE; + } + + + // --------------------------------------------------------------- + // PyRectilinear Attribute Method table. + + PyMethodDef PyRectilinear_Methods[] = + { { "create" , (PyCFunction)PyRectilinear_create , METH_VARARGS|METH_STATIC + , "Create a new Rectilinear polygon." } + , { "getX" , (PyCFunction)PyRectilinear_getX , METH_NOARGS , "Return the Rectilinear X value." } + , { "getY" , (PyCFunction)PyRectilinear_getY , METH_NOARGS , "Return the Rectilinear Y value." } + , { "getBoundingBox", (PyCFunction)PyRectilinear_getBoundingBox, METH_NOARGS , "Return the Rectilinear Bounding Box." } + , { "setPoints" , (PyCFunction)PyRectilinear_setPoints , METH_VARARGS, "Sets the Rectilinear Bounding Box." } + , { "translate" , (PyCFunction)PyRectilinear_translate , METH_VARARGS, "Translates the Rectilinear of dx and dy." } + , { "destroy" , (PyCFunction)PyRectilinear_destroy , METH_NOARGS + , "Destroy associated hurricane object, the python object remains." } + , {NULL, NULL, 0, NULL} /* sentinel */ + }; + + + DBoDeleteMethod(Rectilinear) + PyTypeObjectLinkPyType(Rectilinear) + + +#else // Python Module Code Part. + + +// +=================================================================+ +// | "PyRectilinear" Shared Library Code Part | +// +=================================================================+ + + + // Link/Creation Method. + DBoLinkCreateMethod(Rectilinear) + PyTypeInheritedObjectDefinitions(Rectilinear,Component) + +#endif // Shared Library Code Part. + +} // extern "C". + +} // Isobar namespace. diff --git a/hurricane/src/isobar/hurricane/isobar/PyRectilinear.h b/hurricane/src/isobar/hurricane/isobar/PyRectilinear.h new file mode 100644 index 00000000..a3938f19 --- /dev/null +++ b/hurricane/src/isobar/hurricane/isobar/PyRectilinear.h @@ -0,0 +1,56 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2018-2018, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | I s o b a r - Hurricane / Python Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/isobar/PyRectilinear.h" | +// +-----------------------------------------------------------------+ + + +#ifndef PY_RECTILINEAR_H +#define PY_RECTILINEAR_H + +#include "hurricane/isobar/PyComponent.h" +#include "hurricane/Rectilinear.h" + + +namespace Isobar { + + extern "C" { + + +// ------------------------------------------------------------------- +// Python Object : "PyRectilinear". + + typedef struct { + PyComponent _baseObject; + } PyRectilinear; + + +// ------------------------------------------------------------------- +// Functions & Types exported to "PyHurricane.ccp". + + extern PyTypeObject PyTypeRectilinear; + extern PyMethodDef PyRectilinear_Methods[]; + + extern PyObject* PyRectilinear_Link ( Hurricane::Rectilinear* object ); + extern void PyRectilinear_LinkPyType (); + + +#define IsPyRectilinear(v) ( (v)->ob_type == &PyTypeRectilinear ) +#define PYRECTILINEAR(v) ( (PyRectilinear*)(v) ) +#define PYRECTILINEAR_O(v) ( PYRECTILINEAR(v)->_baseObject._baseObject._object ) + + + } // extern "C". + +} // Isobar namespace. + +#endif // PY_RECTILINEAR_H diff --git a/hurricane/src/viewer/CellWidget.cpp b/hurricane/src/viewer/CellWidget.cpp index 2083805f..57a2937c 100644 --- a/hurricane/src/viewer/CellWidget.cpp +++ b/hurricane/src/viewer/CellWidget.cpp @@ -40,6 +40,7 @@ #include "hurricane/Contact.h" #include "hurricane/Pad.h" #include "hurricane/Diagonal.h" +#include "hurricane/Rectilinear.h" #include "hurricane/Polygon.h" #include "hurricane/RoutingPad.h" #include "hurricane/ExtensionGo.h" @@ -666,47 +667,30 @@ namespace Hurricane { static QRect rectangle; static unsigned int state; - const Diagonal* diagonal = dynamic_cast(go); - if (diagonal) { - _goCount++; - Box bb = transformation.getBox(diagonal->getBoundingBox(basicLayer)); - rectangle = _cellWidget->dbuToScreenRect( bb ); - if ( (rectangle.width() > 4) and (rectangle.height() > 4) ) { - QPolygon contour; - for ( Point point : diagonal->getContour() ) - contour << _cellWidget->dbuToScreenPoint( point ); - _cellWidget->drawScreenPolygon( contour ); - } - return; - } - - const Polygon* polygon = dynamic_cast(go); - if (polygon) { - _goCount++; - Box bb = transformation.getBox(polygon->getBoundingBox(basicLayer)); - rectangle = _cellWidget->dbuToScreenRect( bb ); - if ( (rectangle.width() > 4) and (rectangle.height() > 4) ) { - QPolygon contour; - const vector& points = polygon->getPoints(); - for ( Point point : points ) contour << _cellWidget->dbuToScreenPoint( point ); - _cellWidget->drawScreenPolygon( contour ); - contour.clear(); - - if (_cellWidget->dbuToScreenLength(DbU::getPolygonStep()) > 4) { - for ( Point point : polygon->getContour() ) - contour << _cellWidget->dbuToScreenPoint( point ); - _cellWidget->drawScreenPolygon( contour ); - } - } - return; - } - const Component* component = dynamic_cast(go); if (component) { _goCount++; Box bb = transformation.getBox(component->getBoundingBox(basicLayer)); rectangle = _cellWidget->dbuToScreenRect( bb ); - state = ( (rectangle.width() > 2) ? 1:0) | ( (rectangle.height() > 2) ? 2:0); + + if (component->isNonRectangle()) { + if ( (rectangle.width() > 4) and (rectangle.height() > 4) ) { + QPolygon contour; + for ( Point point : component->getContour() ) + contour << _cellWidget->dbuToScreenPoint( point ); + _cellWidget->drawScreenPolygon( contour ); + + if ( component->isManhattanized() + and (_cellWidget->dbuToScreenLength(DbU::getPolygonStep()) > 4) ) { + for ( Point point : component->getMContour() ) + contour << _cellWidget->dbuToScreenPoint( point ); + _cellWidget->drawScreenPolygon( contour ); + } + } + return; + } + + state = ( (rectangle.width() > 2) ? 1:0) | ( (rectangle.height() > 2) ? 2:0); switch ( state ) { case 0: break; case 1: _cellWidget->drawScreenLine( rectangle.bottomLeft(), rectangle.bottomRight() ); break;