Compare commits

...

109 Commits

Author SHA1 Message Date
Jean-Paul Chaput 947026cced Add technology description for the new LSxLib symbolic layout. 2023-07-14 12:33:03 +02:00
Jean-Paul Chaput ce084fcf73 Add a tile counter in verbose time to monitor the progress. 2023-07-14 12:31:38 +02:00
Jean-Paul Chaput 7b304da14b Check for minimal size in non-anchored Contact CTOR. 2023-07-14 12:28:08 +02:00
Jean-Paul Chaput b734d61a00 Update the RapidJSON git URL. 2023-07-14 12:26:51 +02:00
Jean-Paul Chaput c2750ca127 Finally understood how to update the submodule. 2023-07-09 17:43:00 +02:00
Jean-Paul Chaput cadae8412b Make the Coloquinte submodule follow the coriolis-submodule branch automatically. 2023-07-09 17:19:32 +02:00
Jean-Paul Chaput d258749373 Merge branch 'coloquinte_rebase' into devel
Some merge conflicts did occurs as it seems the latests commits
from "devel" where not applied to the rebase.
2023-07-09 13:42:21 +02:00
Gabriel Gouvine 21deed93f1 Update coloquinte version 2023-07-04 11:04:06 +02:00
Gabriel Gouvine e3d6456ce3 Avoid placement issues on small designs by limiting cell bloat based on row size 2023-07-04 10:22:50 +02:00
Gabriel Gouvine fda7054840 Apply density variation on the whole placement area, avoiding reduced free space under huge bloat 2023-07-04 10:22:50 +02:00
Gabriel Gouvine ffb5e38de2 Apply library bloating during free space computation 2023-07-04 10:22:50 +02:00
Gabriel Gouvine dcf3e7bd77 Report slice height in Etesian logs 2023-07-04 10:22:50 +02:00
Jean-Paul Chaput 605fa5cdd1 Using the right cell gauge name in GF180MCU techn o file. 2023-07-04 10:22:50 +02:00
Jean-Paul Chaput 508adbd00b Small beautification of the Coloquinte bloat factor display. 2023-07-04 10:22:50 +02:00
Jean-Paul Chaput b06e90d122 Call runScript() with unicorn only when there *is* a graphic interface. 2023-07-04 10:22:50 +02:00
Jean-Paul Chaput d8958c3b5a In designflow, re-export LD_LIBRARY_PATH only if there is an ALLIANCE_TOP. 2023-07-04 10:22:50 +02:00
Jean-Paul Chaput 9c8e63c11d Set patterns to account the DFF in cmos & cmos 45 technologies. 2023-07-04 10:22:50 +02:00
Jean-Paul Chaput 373cbe9835 Filter new type of RoutingGauge in KatanaEngine::annotateGlobalGraph().
* Change: RoutingGauge in KatanaEngine::annotateGlobalGraph(), when
    accounting for obstacles, skip new types of RoutingGauges that
    are not accounted either when computing initial edge capacity in
    EdgeCapacity CTOR. Now only take into account the "Default" kind.
2023-07-04 10:22:50 +02:00
Jean-Paul Chaput 5cd83019db Fix bug in NetBuilderHV::_do_1G_xM1_1PinM2(), using bad RoutingPad.
* Bug: In NetBuilderHV::_do_1G_xM1_1PinM2(), using the wrong RoutingPad
    table to build the wires between M1. The topology was not connecting
    some M1.
2023-07-04 10:22:50 +02:00
Gabriel Gouvine d2c2f977f1 Automatic slice height adjustment for multi-row cells 2023-07-04 10:22:15 +02:00
Jean-Paul Chaput a110a286d2 Forgot configuration files for GF180MCU. 2023-07-04 10:21:58 +02:00
Gabriel Gouvine 73cc5c0e76 Specify branch in Coloquinte submodule + update 2023-07-04 10:21:27 +02:00
Gabriel Gouvine 4973d0a181 Compute space margin from bounding box (for user-specified bounding box) 2023-07-04 10:20:52 +02:00
Jean-Paul Chaput 76e9da0b64 Added support for GF180MCU, part 1.
* New: In LefImport::LefParser, add support for LEF Polygons that are
    translated into Hurricane Rectilinears.
* Change: In LefImport::setMergeLibrary(), the default behavior for the
    LEF parser is to create a new separate library under LEF/<lib_name>
    for each file. But if the various cells are put each one in it's own
    cell, this is suitable. So we can now set a library beforehand into
    which they will be all put.
* New: in CRL/technos.node180.gf180mcu, configuration files for the
    GF180MCU open PDK.
* New: in cumulus/designflow.technos, added a setupGF180MCU_GF() to
    initialize the GF PDK.
2023-07-04 10:20:41 +02:00
Jean-Paul Chaput 3243b12abb Try VH topologies for G180MCU. Not working either... 2023-07-03 20:02:33 +02:00
Jean-Paul Chaput 73265c2d68 Quick and DRC unclean hack to manage rectilinear in LefImport. 2023-07-03 20:00:58 +02:00
Jean-Paul Chaput 47aadd8ef4 Give priority of non-pref segments anchored on punctuals over regular ones.
Introduce a new kind of flag "NonPrefOnVSmall" to mark non-preferred
segments anchoreds on small terminals (i.e. punctual). They should have
absolute priority over segments in prefered direction.
2023-07-03 19:59:10 +02:00
Jean-Paul Chaput 30b92ff33a Add a flag througout all the build system to manage manylinux (PyPI).
* New: In boostrap/FindBootstrap.cmake, add a macro setup_qt() to
    share Python detection across the various tools.
      This macro takes into account the USE_MANYLINUX variable to
    slightly change the Python detection. On a "normal" system we
    look for "Development" (search for dynamic libraries) while under
    manylinux we look for "Development.Module"(static linking).
* Change: In bootstrap/ccb.py, add a new option --manylinux.
* Change: Cleanup in the various CMakeLists.txt to use setup_qt().
2023-07-03 19:54:01 +02:00
Jean-Paul Chaput ecdcabb8ad Merge branch 'coloquinte2' into devel 2023-06-29 21:20:35 +02:00
Gabriel Gouvine b7698e7500 Avoid placement issues on small designs by limiting cell bloat based on row size 2023-06-29 15:17:02 +02:00
Gabriel Gouvine e084c1e672 Apply density variation on the whole placement area, avoiding reduced free space under huge bloat 2023-06-29 15:11:00 +02:00
Gabriel Gouvine 7b155d1ecf Apply library bloating during free space computation 2023-06-29 14:37:46 +02:00
Gabriel Gouvine 06433cc914 Report slice height in Etesian logs 2023-06-29 12:38:22 +02:00
Jean-Paul Chaput 554aded65b Uses the public https address for Coloquinte submodule. 2023-06-26 19:03:15 +02:00
Jean-Paul Chaput 9b38590c60 Add init & update of submodules for Coloquinte 2. 2023-06-26 14:29:00 +02:00
Jean-Paul Chaput 014ec72652 First merge of coloquinte2 & tramontana branches.
Needed to merge thoses two branches as I needed to to uses features
from each other to implement GF180MCU.
2023-06-25 18:11:18 +02:00
Jean-Paul Chaput 007677353f Using the right cell gauge name in GF180MCU techn o file. 2023-06-25 15:29:35 +02:00
Jean-Paul Chaput f8637737a0 Small beautification of the Coloquinte bloat factor display. 2023-06-25 11:57:04 +02:00
Jean-Paul Chaput b77d86c931 Call runScript() with unicorn only when there *is* a graphic interface. 2023-06-25 11:55:27 +02:00
Jean-Paul Chaput d019c6aab5 In designflow, re-export LD_LIBRARY_PATH only if there is an ALLIANCE_TOP. 2023-06-25 11:53:26 +02:00
Jean-Paul Chaput b8f15a2c8f Set patterns to account the DFF in cmos & cmos 45 technologies. 2023-06-25 11:51:31 +02:00
Jean-Paul Chaput 70fb5cfe3f Filter new type of RoutingGauge in KatanaEngine::annotateGlobalGraph().
* Change: RoutingGauge in KatanaEngine::annotateGlobalGraph(), when
    accounting for obstacles, skip new types of RoutingGauges that
    are not accounted either when computing initial edge capacity in
    EdgeCapacity CTOR. Now only take into account the "Default" kind.
2023-06-25 11:49:06 +02:00
Jean-Paul Chaput 5cdb8b25f0 Fix bug in NetBuilderHV::_do_1G_xM1_1PinM2(), using bad RoutingPad.
* Bug: In NetBuilderHV::_do_1G_xM1_1PinM2(), using the wrong RoutingPad
    table to build the wires between M1. The topology was not connecting
    some M1.
2023-06-25 11:08:16 +02:00
Jean-Paul Chaput 0aa9010b32 Merge branch 'coloquinte2' of gitlab.lip6.fr:vlsi-eda/coriolis into coloquinte2 2023-06-23 15:39:30 +02:00
Gabriel Gouvine ee2ed63d35 Automatic slice height adjustment for multi-row cells 2023-06-22 18:28:48 +02:00
Jean-Paul Chaput 72b906cb68 Forgor configuartion files for GF180MCU. 2023-06-22 17:38:03 +02:00
Jean-Paul Chaput 30b69f634a Merge branch 'coloquinte2' of gitlab.lip6.fr:vlsi-eda/coriolis into coloquinte2 2023-06-22 17:36:11 +02:00
Gabriel Gouvine 73925094f1 Specify branch in Coloquinte submodule + update 2023-06-22 17:11:42 +02:00
Jean-Paul Chaput 56da5ebe32 Merge branch 'coloquinte2' of gitlab.lip6.fr:vlsi-eda/coriolis into coloquinte2 2023-06-22 17:09:39 +02:00
Gabriel Gouvine 0dc33538a7 Specify branch in Coloquinte submodule 2023-06-22 17:07:42 +02:00
Gabriel Gouvine 7b7e852f67 Compute space margin from bounding box (for user-specified bounding box) 2023-06-22 17:07:36 +02:00
Jean-Paul Chaput 04410f1cc2 Added support for GF180MCU, part 1.
* New: In LefImport::LefParser, add support for LEF Polygons that are
    translated into Hurricane Rectilinears.
* Change: In LefImport::setMergeLibrary(), the default behavior for the
    LEF parser is to create a new separate library under LEF/<lib_name>
    for each file. But if the various cells are put each one in it's own
    cell, this is suitable. So we can now set a library beforehand into
    which they will be all put.
* New: in CRL/technos.node180.gf180mcu, configuration files for the
    GF180MCU open PDK.
* New: in cumulus/designflow.technos, added a setupGF180MCU_GF() to
    initialize the GF PDK.
2023-06-22 14:13:19 +02:00
Jean-Paul Chaput a3c05c0f60 Merge branch 'coloquinte2' of gitlab.lip6.fr:vlsi-eda/coriolis into coloquinte2
Seems to have been strange things occuring.
2023-06-22 14:01:25 +02:00
Gabriel Gouvine 06ea3d6e09 Export polarity of multi-row cells 2023-06-20 18:30:30 +02:00
Gabriel Gouvine 764464911e Handle multi-row height better for default abutment box 2023-06-20 18:17:19 +02:00
Gabriel Gouvine f0c616a5ea Remove dead code 2023-06-20 15:33:30 +02:00
Gabriel Gouvine 1df76cdf5a Fix orientation issues across rows: MX/MY are exchanged between Coriolis and Coloquinte 2023-06-20 12:18:06 +02:00
Gabriel Gouvine 4fe1436e1f Remove uniform density option, replaced by densityVariation 2023-06-20 12:18:06 +02:00
Gabriel Gouvine 5c75a1ffb7 New densityVariation option to replace uniformDensity 2023-06-20 12:18:06 +02:00
Gabriel Gouvine e395069025 Rename tabs in CGT 2023-06-20 12:18:06 +02:00
Gabriel Gouvine 0743e3bbe4 Introduce a new parameter to handle uniform density 2023-06-20 12:18:06 +02:00
Gabriel Gouvine 665331252e Fix enum values for placement effort in graphical mode 2023-06-20 12:18:06 +02:00
Gabriel Gouvine 0fdc8f6d3f Little bit more cleanup 2023-06-20 12:18:06 +02:00
Gabriel Gouvine 093a4161ef Remove unused datastructures in EtesianEngine 2023-06-20 12:18:06 +02:00
Gabriel Gouvine 011b32d1ed Remove OpenMP flags in nix build 2023-06-20 12:18:06 +02:00
Gabriel Gouvine 238d9dfaba Remove dead antenna diode insertion code 2023-06-20 12:18:06 +02:00
Gabriel Gouvine fb6979db19 Fix orientation handling 2023-06-20 12:18:06 +02:00
Gabriel Gouvine 3d43a25bb4 Default to only showing final placement (update is slow) 2023-06-20 12:18:06 +02:00
Gabriel Gouvine 2bc2e4a988 Improve callbacks 2023-06-20 12:18:06 +02:00
Gabriel Gouvine 1b41976ca1 Callbacks in EtesianEngine 2023-06-20 12:18:06 +02:00
Gabriel Gouvine c178b8c720 Add feed cells in command line call too 2023-06-20 12:18:05 +02:00
Gabriel Gouvine a9041cbb7c Remove useKatana option in CGT (not used anymore) 2023-06-20 12:18:05 +02:00
Gabriel Gouvine 495edc6bfe Enable P&R command line options in graphic mode 2023-06-20 12:18:05 +02:00
Gabriel Gouvine d85e7277a4 Add missing cleanup. Seems to take care of non-determinism at restart 2023-06-20 12:18:05 +02:00
Gabriel Gouvine e723a53b69 Setup row polarity (single row cells at the moment) 2023-06-20 12:18:05 +02:00
Gabriel Gouvine 288d89ba93 Setup Coloquinte callbacks + start rewriting antenna code 2023-06-20 12:18:05 +02:00
Gabriel Gouvine c62383c09f Rewrite EtesianEngine for new coloquinte 2023-06-20 12:18:05 +02:00
Gabriel Gouvine 7091ac3a77 Completely replace old coloquinte by new one 2023-06-20 12:18:05 +02:00
Gabriel Gouvine c0b4aad02b Rewrite of the Etesian engine to run the new placer 2023-06-20 12:18:05 +02:00
Gabriel Gouvine a9f55021fd Add Coloquinte2 to the build 2023-06-20 12:18:05 +02:00
Gabriel Gouvine 5d8b994bb6 Fix orientation issues across rows: MX/MY are exchanged between Coriolis and Coloquinte 2023-06-20 10:47:25 +02:00
Gabriel Gouvine 6f793665c2 Remove uniform density option, replaced by densityVariation 2023-06-10 14:45:07 +02:00
Gabriel Gouvine 7f0ab625d2 New densityVariation option to replace uniformDensity 2023-06-10 14:35:55 +02:00
Gabriel Gouvine e497a4d48f Rename tabs in CGT 2023-06-10 13:41:41 +02:00
Gabriel Gouvine 052df5d1c8 Introduce a new parameter to handle uniform density 2023-06-10 13:29:56 +02:00
Gabriel Gouvine 4731e30bb3 Fix enum values for placement effort in graphical mode 2023-06-09 16:12:20 +02:00
Gabriel Gouvine 078e4e0644 Little bit more cleanup 2023-06-09 16:07:19 +02:00
Gabriel Gouvine 23975c541d Remove unused datastructures in EtesianEngine 2023-06-08 18:45:19 +02:00
Gabriel Gouvine 0fe1deac94 Remove OpenMP flags in nix build 2023-06-08 17:11:48 +02:00
Gabriel Gouvine db01b4ff55 Remove dead antenna diode insertion code 2023-06-08 17:11:40 +02:00
Gabriel Gouvine 1f5549d396 Fix orientation handling 2023-06-08 14:21:00 +02:00
Gabriel Gouvine 62e7640a37 Default to only showing final placement (update is slow) 2023-06-08 14:20:56 +02:00
Gabriel Gouvine 1beaaf93e4 Improve callbacks 2023-06-06 15:29:29 +02:00
Gabriel Gouvine fb694e1c3d Callbacks in EtesianEngine 2023-06-06 12:13:07 +02:00
Gabriel Gouvine d873216447 Add feed cells in command line call too 2023-06-04 13:21:42 +02:00
Gabriel Gouvine 49e95115f2 Remove useKatana option in CGT (not used anymore) 2023-06-04 13:19:21 +02:00
Gabriel Gouvine 2ea099afec Enable P&R command line options in graphic mode 2023-06-04 13:18:20 +02:00
Gabriel Gouvine 26184c5016 Add missing cleanup. Seems to take care of non-determinism at restart 2023-06-04 11:01:51 +02:00
Gabriel Gouvine acf6cfe041 Setup row polarity (single row cells at the moment) 2023-06-03 12:41:11 +02:00
Gabriel Gouvine 585489860e Setup Coloquinte callbacks + start rewriting antenna code 2023-06-03 12:00:33 +02:00
Gabriel Gouvine 4f1ce6cfcb Rewrite EtesianEngine for new coloquinte 2023-06-02 14:44:30 +02:00
Jean-Paul Chaput 21eedbcc2b Change in strategy for guessing Alliance top cells directory.
* In cumulus.designflow.technos.setupCMOS(): export back the guessed
    ALLIANCE_TOP *before* importing technos.symbolic.cmos so it is
    used for the CELLS_TOP. This avoid defaulting to /soc/alliance
    which does exists only on LIP6 computers...
2023-05-28 15:31:47 +02:00
Gabriel Gouvine 393204ba0d Completely replace old coloquinte by new one 2023-05-26 15:09:52 +02:00
Gabriel Gouvine 1e71b5fb08 Rewrite of the Etesian engine to run the new placer 2023-05-19 17:31:26 +02:00
Gabriel Gouvine 3830a90482 Add Coloquinte2 to the build 2023-05-16 09:20:52 +02:00
Jean-Paul Chaput d41e328253 Added easier access to devices parameters in AnalogDesign. 2023-05-08 20:00:47 +02:00
Jean-Paul Chaput 7cfd056da2 Completed inspector support on analog transitors. 2023-05-08 20:00:29 +02:00
Jean-Paul Chaput ae5f6ad3de Added some more debug info in capacitors. 2023-04-26 19:34:22 +02:00
Jean-Paul Chaput a31cf3d334 Fix SRAM import hierarchy for new coriolis namespace. 2023-04-26 11:46:53 +02:00
145 changed files with 3168 additions and 45903 deletions

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "coloquinte"]
path = coloquinte
# url = git@github.com:Coloquinte/PlaceRoute.git
url = https://github.com/Coloquinte/PlaceRoute.git
branch = coriolis-submodule
update = merge

View File

@ -18,9 +18,9 @@
set_cmake_policies()
setup_boost(program_options)
setup_qt()
setup_python()
find_package(Libexecinfo REQUIRED)
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
find_package(PythonSitePackages REQUIRED)
find_package(LEFDEF REQUIRED)
find_package(FLUTE REQUIRED)

View File

@ -18,8 +18,8 @@
set_cmake_policies()
setup_boost()
setup_qt()
setup_python()
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
find_package(PythonSitePackages REQUIRED)
find_package(FLUTE REQUIRED)
find_package(HURRICANE REQUIRED)

View File

@ -3069,6 +3069,7 @@ namespace Anabatic {
if (wPitch > 1) segment->setFlags( SegWide );
if (source->canDrag() or target->canDrag()) segment->setFlags( SegDrag );
if (dir & Flags::UseNonPref) segment->setFlags( SegNonPref );
if (dir.contains(Flags::UseNonPref|Flags::OnVSmall)) segment->setFlags( SegOnVSmall );
return segment;
}

View File

@ -14,7 +14,6 @@ endif ( CHECK_DETERMINISM )
${QtX_INCLUDE_DIRS}
${Python_INCLUDE_DIRS}
)
find_package (Python3 COMPONENTS Interpreter Development)
set( includes anabatic/Constants.h
anabatic/Configuration.h
anabatic/Matrix.h

View File

@ -132,6 +132,7 @@ namespace Anabatic {
const BaseFlags Flags::NoMinLength = (1L << 37);
const BaseFlags Flags::NoSegExt = (1L << 38);
const BaseFlags Flags::NullLength = (1L << 39);
const BaseFlags Flags::OnVSmall = (1L << 40);
Flags::~Flags ()

View File

@ -278,6 +278,8 @@ namespace Anabatic {
if (flags & (VSmall|UseNonPref)) {
cdebug_log(145,0) << "case: UseNonPref" << endl;
if (flags & VSmall)
useNonPref.reset( Flags::UseNonPref );
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getBuildContactLayer(rpDepth+1) );
AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical|useNonPref );
rpSourceContact = subContact1;
@ -1155,8 +1157,8 @@ namespace Anabatic {
}
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoContact* leftContact = doRp_Access( getGCell(), rpsM1[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), rpsM1[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}

View File

@ -109,6 +109,7 @@ namespace Anabatic {
static const uint64_t SegNonPref = (1L<<37);
static const uint64_t SegAtMinArea = (1L<<38);
static const uint64_t SegNoMoveUp = (1L<<39);
static const uint64_t SegOnVSmall = (1L<<40);
// Masks.
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
@ -202,6 +203,7 @@ namespace Anabatic {
inline bool isTerminal () const;
inline bool isUnbreakable () const;
inline bool isNonPref () const;
inline bool isNonPrefOnVSmall () const;
inline bool isDrag () const;
inline bool isAtMinArea () const;
inline bool isNotSourceAligned () const;
@ -536,6 +538,7 @@ namespace Anabatic {
inline bool AutoSegment::isLocal () const { return not (_flags & SegGlobal); }
inline bool AutoSegment::isUnbreakable () const { return _flags & SegUnbreakable; }
inline bool AutoSegment::isNonPref () const { return _flags & SegNonPref; }
inline bool AutoSegment::isNonPrefOnVSmall () const { return (_flags & SegNonPref) and (_flags & SegOnVSmall); }
inline bool AutoSegment::isBipoint () const { return _flags & SegBipoint; }
inline bool AutoSegment::isWeakTerminal () const { return (_rpDistance < 2); }
inline bool AutoSegment::isWeakTerminal1 () const { return (_rpDistance == 1); }

View File

@ -110,6 +110,7 @@ namespace Anabatic {
static const BaseFlags NoMinLength ;
static const BaseFlags NoSegExt ;
static const BaseFlags NullLength ;
static const BaseFlags OnVSmall ;
public:
inline Flags ( uint64_t flags = NoFlags );
inline Flags ( const Hurricane::BaseFlags& );

View File

@ -11,8 +11,7 @@
list(INSERT CMAKE_MODULE_PATH 0 "${Bootstrap_SOURCE_DIR}/cmake_modules/")
find_package(Bootstrap REQUIRED)
# find_package(Python 3 REQUIRED COMPONENTS Interpreter Development )
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development )
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development.Module )
find_package(PythonSitePackages REQUIRED)
print_cmake_module_path()

View File

@ -35,6 +35,7 @@ class Builder:
self._noCache = False
self._ninja = False
self._clang = False
self._manylinux = False
self._noSystemBoost = False
self._macports = False
self._devtoolset = 0
@ -62,6 +63,7 @@ class Builder:
elif attribute == "noCache": self._noCache = value
elif attribute == "ninja": self._ninja = value
elif attribute == "clang": self._clang = value
elif attribute == "manylinux": self._manylinux = value
elif attribute == "macports":
self._macports = value
if value: self._noSystemBoost = True
@ -177,6 +179,7 @@ class Builder:
if self._bfd: command += [ "-D", "USE_LIBBFD:STRING=%s" % self._bfd ]
if self._qt4: command += [ "-D", "WITH_QT4:STRING=TRUE" ]
if self._openmp: command += [ "-D", "WITH_OPENMP:STRING=TRUE" ]
if self._manylinux: command += [ "-D", "USE_MANYLINUX:STRING=TRUE" ]
command += [ "-D", "CMAKE_BUILD_TYPE:STRING=%s" % self.buildMode
#, "-D", "BUILD_SHARED_LIBS:STRING=%s" % self.enableShared
, "-D", "CMAKE_INSTALL_PREFIX:STRING=%s" % self.installDir

View File

@ -211,6 +211,7 @@ parser.add_option ( "--bfd" , action="store_true" ,
parser.add_option ( "--openmp" , action="store_true" , dest="openmp" , help="Enable the use of OpenMP in Gcc." )
parser.add_option ( "--ninja" , action="store_true" , dest="ninja" , help="Use Ninja instead of UNIX Makefile." )
parser.add_option ( "--clang" , action="store_true" , dest="clang" , help="Force use of Clang C/C++ compiler instead of system default." )
parser.add_option ( "--manylinux" , action="store_true" , dest="manylinux" , help="Build target is manylinux (PyPY)." )
parser.add_option ( "--make" , action="store" , type="string", dest="makeArguments" , help="Arguments to pass to make (ex: \"-j4 install\")." )
parser.add_option ( "--project" , action="append" , type="string", dest="projects" , help="The name of a project to build (may appears any number of time)." )
parser.add_option ( "-t", "--tool" , action="append" , type="string", dest="tools" , help="The name of a tool to build (may appears any number of time)." )
@ -282,6 +283,7 @@ else:
if options.llvmtoolset: builder.llvmtoolset = options.llvmtoolset
if options.bfd: builder.bfd = "ON"
if options.qt4: builder.qt4 = True
if options.manylinux: builder.manylinux = True
if options.openmp: builder.openmp = True
if options.makeArguments: builder.makeArguments = options.makeArguments
#if options.svnMethod: builder.svnMethod = options.svnMethod

View File

@ -9,6 +9,7 @@
FindQwt.cmake
FindSphinx.cmake
FindPelican.cmake
FindCOLOQUINTE.cmake
GetGitRevisionDescription.cmake
GetGitRevisionDescription.cmake.in
)

View File

@ -84,10 +84,10 @@
set(DEBUG_FLAGS "-g")
if(CYGWIN)
set(ADDITIONAL_FLAGS "-D_GLIBCXX_USE_C99")
set(CXX_STANDARD "gnu++11")
set(CXX_STANDARD "gnu++17")
else()
set(ADDITIONAL_FLAGS "-Wl,--no-undefined")
set(CXX_STANDARD "c++11")
set(CXX_STANDARD "c++17")
endif()
#set(CMAKE_C_FLAGS_DEBUG " -Wall -fsanitize=address ${ADDITIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE)
set(CMAKE_C_FLAGS_DEBUG " -Wall ${ADDITIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE)
@ -223,6 +223,20 @@ endif()
endmacro(setup_boost)
#
# Setup Python, select detection depending on USE_MANYLINUX.
#
macro(setup_python)
set(pydevelArg "Development")
if (USE_MANYLINUX)
message(STATUS "Build for manylinux")
set(pydevelArg "Development.Module")
endif()
find_package(Python 3 REQUIRED COMPONENTS Interpreter ${pydevelArg} )
endmacro()
#
# Find Qt, the union of all the modules we need for the whole project.
#

View File

@ -15,13 +15,14 @@ IF(UNIX)
#
# Look for an installation.
#
FIND_PATH(COLOQUINTE_INCLUDE_PATH NAMES coloquinte/netlist.hxx PATHS
FIND_PATH(COLOQUINTE_INCLUDE_PATH NAMES coloquinte/coloquinte.hpp PATHS
# Look in other places.
${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES include/coriolis2
# Help the user find it if we cannot.
DOC "The ${COLOQUINTE_INCLUDE_PATH_DESCRIPTION}"
)
MESSAGE( "COL ${COLOQUINTE_INCLUDE_PATH}" )
FIND_LIBRARY(COLOQUINTE_LIBRARY_PATH
NAMES coloquinte

View File

@ -180,7 +180,7 @@ Development files for the Coriolis 2 package.
%{coriolisTop}/include/vlsisapd/configuration/*.h
%{coriolisTop}/include/vlsisapd/dtr/*.h
%{coriolisTop}/include/vlsisapd/openChams/*.h
%{coriolisTop}/include/coriolis2/coloquinte/*.hxx
%{coriolisTop}/include/coriolis2/coloquinte/*.hpp
%{coriolisTop}/include/coriolis2/hurricane/*.h
%{coriolisTop}/include/coriolis2/hurricane/viewer/*.h
%{coriolisTop}/include/coriolis2/hurricane/isobar/*.h

View File

@ -284,6 +284,16 @@ class GitRepository ( object ):
Command( [ 'git', 'checkout', branch ], self.fdLog ).execute()
return
def submoduleInit ( self ):
os.chdir( self.localRepoDir )
Command( [ 'git', 'submodule', 'init' ], self.fdLog ).execute()
return
def submoduleUpdate ( self ):
os.chdir( self.localRepoDir )
Command( [ 'git', 'submodule', 'update' ], self.fdLog ).execute()
return
class Configuration ( object ):
@ -303,7 +313,7 @@ class Configuration ( object ):
def __init__ ( self ):
self._sender = 'Jean-Paul.Chaput@soc.lip6.fr'
self._receivers = [ 'Jean-Paul.Chaput@lip6.fr', ]
self._supportRepos = [ 'http://github.com/miloyip/rapidjson' ]
self._supportRepos = [ 'https://github.com/Tencent/rapidjson.git' ]
self._allianceRepo = 'https://gitlab.lip6.fr/jpc/alliance.git'
self._coriolisRepo = 'https://gitlab.lip6.fr/jpc/coriolis.git'
self._benchsRepo = 'https://gitlab.lip6.fr/jpc/alliance-check-toolkit.git'
@ -601,6 +611,8 @@ try:
if conf.rmSource: gitCoriolis.removeLocalRepo()
gitCoriolis.clone ()
gitCoriolis.checkout( 'devel' )
gitCoriolis.submoduleInit()
gitCoriolis.submoduleUpdate()
if conf.rmSource: gitBenchs.removeLocalRepo()
gitBenchs.clone()

View File

@ -18,9 +18,9 @@
setup_boost(program_options)
setup_qt()
setup_qwt()
setup_python()
find_package(Libexecinfo REQUIRED)
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
find_package(PythonSitePackages REQUIRED)
find_package(LEFDEF REQUIRED)
find_package(FLUTE REQUIRED)

1
coloquinte Submodule

@ -0,0 +1 @@
Subproject commit 97bb781ba363303fd6b7254c717f621b137b89e3

View File

@ -1,34 +0,0 @@
# -*- explicit-buffer-name: "CMakeLists.txt<coloquinte>" -*-
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
project(COLOQUINTE)
set(ignoreVariables "${CMAKE_INSTALL_DIR}" "${BUILD_DOC}")
#option(BUILD_DOC "Build the documentation (doxygen)" OFF)
option(USE_LIBBFD "Link with BFD libraries to print stack traces" OFF)
cmake_minimum_required(VERSION 3.16)
list(INSERT CMAKE_MODULE_PATH 0 "${DESTDIR}$ENV{CORIOLIS_TOP}/share/cmake/Modules/")
find_package(Bootstrap REQUIRED)
setup_project_paths(CORIOLIS)
setup_qt()
set_cmake_policies()
setup_boost()
find_package(Libexecinfo REQUIRED)
find_package(Doxygen)
if(WITH_OPENMP)
find_package(OpenMP REQUIRED)
add_definitions(${OpenMP_CXX_FLAGS})
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
add_subdirectory(src)
add_subdirectory(cmake_modules)
#add_subdirectory(doc)

View File

@ -1,2 +0,0 @@
install ( FILES FindCOLOQUINTE.cmake DESTINATION share/cmake/Modules )

View File

@ -1,39 +0,0 @@
# -*- explicit-buffer-name: "CMakeLists.txt<coloquinte/src>" -*-
include_directories( ${COLOQUINTE_SOURCE_DIR}/src
)
set ( includes coloquinte/circuit.hxx
coloquinte/circuit_helper.hxx
coloquinte/common.hxx
coloquinte/netlist.hxx
coloquinte/solvers.hxx
coloquinte/rough_legalizers.hxx
coloquinte/legalizer.hxx
coloquinte/detailed.hxx
coloquinte/topologies.hxx
coloquinte/optimization_subproblems.hxx
coloquinte/piecewise_linear.hxx
)
set ( cpps circuit.cxx
checkers.cxx
rough_legalizers.cxx
solvers.cxx
optimization_subproblems.cxx
piecewise_linear.cxx
orientation.cxx
detailed.cxx
cell_swapping.cxx
#MCF_opt.cxx
row_opt.cxx
topologies.cxx
lookup_table.cxx
legalizer.cxx
)
add_library ( coloquinte ${cpps} )
set_target_properties( coloquinte PROPERTIES VERSION 1.0 SOVERSION 1 )
install( TARGETS coloquinte DESTINATION lib${LIB_SUFFIX} )
install( FILES ${includes} DESTINATION include/coriolis2/coloquinte )

View File

@ -1,185 +0,0 @@
#include "coloquinte/detailed.hxx"
#include "coloquinte/circuit_helper.hxx"
#include <functional>
namespace coloquinte{
namespace dp{
namespace{
// Tries to swap two cells;
inline bool try_swap(netlist const & circuit, detailed_placement & pl, index_t c1, index_t c2, bool try_flip,
std::function<std::int64_t(netlist const &, detailed_placement const &, std::vector<index_t> const &)> get_nets_cost){
assert(pl.cell_height(c1) == 1 and pl.cell_height(c2) == 1);
assert( (circuit.get_cell(c1).attributes & XMovable) != 0 and (circuit.get_cell(c1).attributes & YMovable) != 0);
assert( (circuit.get_cell(c2).attributes & XMovable) != 0 and (circuit.get_cell(c2).attributes & YMovable) != 0);
auto c1_bnds = pl.get_limit_positions(circuit, c1),
c2_bnds = pl.get_limit_positions(circuit, c2);
// Get the possible positions for a swap
int_t swp_min_c1 = c2_bnds.first,
swp_min_c2 = c1_bnds.first,
swp_max_c1 = c2_bnds.second - circuit.get_cell(c1).size.x,
swp_max_c2 = c1_bnds.second - circuit.get_cell(c2).size.x;
if(swp_max_c1 >= swp_min_c1 and swp_max_c2 >= swp_min_c2){
// Check both orientations of the cell
// Get all the nets involved and uniquify them (nets with more than one pin on the cells)
std::vector<index_t> involved_nets;
for(netlist::pin_t p : circuit.get_cell(c1)){
involved_nets.push_back(p.net_ind);
}
for(netlist::pin_t p : circuit.get_cell(c2)){
involved_nets.push_back(p.net_ind);
}
std::sort(involved_nets.begin(), involved_nets.end());
involved_nets.resize(std::distance(involved_nets.begin(), std::unique(involved_nets.begin(), involved_nets.end())));
// Test the cost for the old position and the cost swapping the cells
std::int64_t old_cost = get_nets_cost(circuit, pl, involved_nets);
// Save the old values
point<int_t> p1 = pl.plt_.positions_[c1];
point<int_t> p2 = pl.plt_.positions_[c2];
point<bool> o1 = pl.plt_.orientations_[c1];
point<bool> o2 = pl.plt_.orientations_[c2];
// Warning: won't work if the two cells don't have the same height
pl.plt_.positions_[c1].x = (swp_min_c1 + swp_max_c1) / 2;
pl.plt_.positions_[c2].x = (swp_min_c2 + swp_max_c2) / 2;
pl.plt_.positions_[c1].y = p2.y;
pl.plt_.positions_[c2].y = p1.y;
// For standard cell placement, we want all the rows to be aligned in the same way
if( (circuit.get_cell(c1).attributes & YFlippable) != 0 and (circuit.get_cell(c2).attributes & YFlippable) != 0)
std::swap(pl.plt_.orientations_[c1].y, pl.plt_.orientations_[c2].y);
if(try_flip and (circuit.get_cell(c1).attributes & XFlippable) != 0 and (circuit.get_cell(c2).attributes & XFlippable) != 0){
index_t bst_ind = 4;
for(index_t i=0; i<4; ++i){
pl.plt_.orientations_[c1].x = i % 2;
pl.plt_.orientations_[c2].x = i / 2;
std::int64_t new_cost = get_nets_cost(circuit, pl, involved_nets);
if(new_cost < old_cost){
old_cost = new_cost;
bst_ind = i;
}
}
// One of the orientations with the new positions was better
if(bst_ind < 4){
pl.swap_standard_cell_topologies(c1, c2);
pl.plt_.orientations_[c1].x = bst_ind % 2;
pl.plt_.orientations_[c2].x = bst_ind / 2;
// We kept the swap
return true;
}
else{
pl.plt_.positions_[c1] = p1;
pl.plt_.positions_[c2] = p2;
pl.plt_.orientations_[c1] = o1;
pl.plt_.orientations_[c2] = o2;
return false;
}
}
else if(get_nets_cost(circuit, pl, involved_nets) < old_cost){
pl.swap_standard_cell_topologies(c1, c2);
return true;
}
else{
// Reset the old values since we didn't swap anything
pl.plt_.positions_[c1] = p1;
pl.plt_.positions_[c2] = p2;
pl.plt_.orientations_[c1] = o1;
pl.plt_.orientations_[c2] = o2;
return false;
}
// A better solution would be
// Check the cost on y depending on the position (extremely simple: two positions for each cell)
// Check the cost on x depending on the position: piecewise linear and relatively complex
// * Get all external pins
// * Get all nets involving only one of the cells: piecewise linear cost for each of them
// * For nets involving the two cells, we have an additional cost
}
else{ // We just cannot swap those two cells without pushing anything
return false;
}
}
inline void generic_swaps_global(netlist const & circuit, detailed_placement & pl, index_t row_extent, index_t cell_extent, bool try_flip,
std::function<std::int64_t(netlist const &, detailed_placement const &, std::vector<index_t> const &)> get_nets_cost){
for(index_t main_row = 0; main_row < pl.row_cnt(); ++main_row){
for(index_t other_row = main_row+1; other_row <= std::min(pl.row_cnt()-1, main_row+row_extent) ; ++other_row){
index_t first_oc = pl.get_first_standard_cell_on_row(other_row); // The first candidate cell to be examined
for(index_t c = pl.get_first_standard_cell_on_row(main_row); c != null_ind; c = pl.get_next_standard_cell_on_row(c, main_row)){
assert(pl.cell_rows_[c] == main_row);
if( (circuit.get_cell(c).attributes & XMovable) == 0) continue; // Don't touch fixed cells
// Number of cells after/before the end of the cell
index_t nb_after = 0;
index_t nb_before = 0;
int_t pos_low = pl.plt_.positions_[c].x - circuit.get_cell(c).size.x,
pos_hgh = pl.plt_.positions_[c].x + 2*circuit.get_cell(c).size.x;
for(index_t oc=first_oc; oc != null_ind and nb_after <= row_extent; oc = pl.get_next_standard_cell_on_row(oc, other_row)){
assert(pl.cell_rows_[oc] == other_row);
if( (circuit.get_cell(oc).attributes & XMovable) == 0) continue; // Don't touche fixed cells
// Count the cells which should trigger stop or shouldn't be used at the next iteration
if(pl.plt_.positions_[oc].x >= pos_hgh) ++nb_after;
if(pl.plt_.positions_[oc].x + circuit.get_cell(oc).size.x <= pos_low) ++ nb_before;
if(try_swap(circuit, pl, c, oc, try_flip, get_nets_cost)){
std::swap(c, oc);
if(c == first_oc) first_oc = oc;
}
}
while(nb_before > cell_extent){
nb_before--;
first_oc = pl.get_next_standard_cell_on_row(first_oc, other_row);
}
}
}
}
pl.selfcheck();
}
} // End anonymous namespace
void swaps_global_HPWL(netlist const & circuit, detailed_placement & pl, index_t row_extent, index_t cell_extent, bool try_flip){
generic_swaps_global(circuit, pl, row_extent, cell_extent, try_flip,
[](netlist const & circuit, detailed_placement const & pl, std::vector<index_t> const & involved_nets) -> std::int64_t{
std::int64_t sum = 0;
for(index_t n : involved_nets){
if(circuit.get_net(n).pin_cnt <= 1) continue;
sum += get_HPWL_length(circuit, pl.plt_, n);
}
return sum;
});
}
void swaps_global_RSMT(netlist const & circuit, detailed_placement & pl, index_t row_extent, index_t cell_extent, bool try_flip){
generic_swaps_global(circuit, pl, row_extent, cell_extent, try_flip,
[](netlist const & circuit, detailed_placement const & pl, std::vector<index_t> const & involved_nets) -> std::int64_t{
std::int64_t sum = 0;
for(index_t n : involved_nets){
if(circuit.get_net(n).pin_cnt <= 1) continue;
sum += get_RSMT_length(circuit, pl.plt_, n);
}
return sum;
});
}
} // namespace dp
} // namespace coloquinte

View File

@ -1,96 +0,0 @@
#include "coloquinte/circuit.hxx"
#include <map>
namespace coloquinte{
void netlist::selfcheck() const{
index_t cell_cnt = cell_areas_.size();
assert(cell_cnt+1 == cell_limits_.size());
assert(cell_cnt == cell_sizes_.size());
assert(cell_cnt == cell_attributes_.size());
assert(cell_cnt == cell_internal_mapping_.size());
index_t net_cnt = net_weights_.size();
assert(net_cnt+1 == net_limits_.size());
assert(net_cnt == net_internal_mapping_.size());
index_t pin_cnt = pin_offsets_.size();
assert(pin_cnt == cell_indexes_.size());
assert(pin_cnt == pin_indexes_.size());
assert(pin_cnt == net_indexes_.size());
for(auto const p : pin_offsets_){
assert(std::isfinite(p.x) and std::isfinite(p.y));
}
}
// For compatibility reasons
void placement_t::selfcheck() const{
}
void verify_placement_legality(netlist const & circuit, placement_t const & pl, box<int_t> surface){
std::vector<box<int_t> > cells;
for(index_t i=0; i<circuit.cell_cnt(); ++i){
auto S = circuit.get_cell(i).size;
cells.push_back(box<int_t>(pl.positions_[i], pl.positions_[i] + S));
// Verify that they are within the placement surface; doesn't take fixed macros into account
if( (circuit.get_cell(i).attributes & XMovable) != 0 or (circuit.get_cell(i).attributes & YMovable) != 0){
assert(cells[i].in(surface));
}
}
// Simple sweepline algorithm to verify that there is no overlap
struct event{
int_t x_min, x_max, y;
index_t cell;
bool removal;
bool operator<(event const o) const{
return y < o.y
or (y == o.y and removal and not o.removal); // Remove before inserting
}
};
std::vector<event> all_events;
for(index_t i=0; i<circuit.cell_cnt(); ++i){
event b, e;
b.cell = i; e.cell = i;
b.x_min = cells[i].x_min; e.x_min = cells[i].x_min;
b.x_max = cells[i].x_max; e.x_max = cells[i].x_max;
b.y = cells[i].y_min; b.removal = false;
e.y = cells[i].y_max; e.removal = true;
if(b.x_max > b.x_min and e.y != b.y){
all_events.push_back(b);
all_events.push_back(e);
}
}
std::sort(all_events.begin(), all_events.end());
// Indexed by beginning of interval, with end of interval and cell within
std::map<int_t, std::pair<int_t, index_t> > active_rectangles;
for(event E : all_events){
if(E.removal){
auto it = active_rectangles.find(E.x_min);
assert(it != active_rectangles.end());
active_rectangles.erase(it);
}
else{ // Find anything that intersects with E; if not, add it
auto it = active_rectangles.lower_bound(E.x_min); // First interval after
if(it != active_rectangles.end()){
assert(it->first >= E.x_max); //Intersection between E.cell and it->second->second
}
if(it != active_rectangles.begin()){
--it;
assert(it->second.first <= E.x_min); //Intersection between E.cell and it->second->second
}
active_rectangles.insert(std::pair<int_t, std::pair<int_t, index_t> >(E.x_min, std::pair<int_t, index_t>(E.x_max, E.cell)));
}
}
}
} // namespace coloquinte

View File

@ -1,408 +0,0 @@
#include "coloquinte/circuit_helper.hxx"
#include "coloquinte/circuit.hxx"
#include <cmath>
namespace coloquinte{
std::int64_t get_HPWL_length(netlist const & circuit, placement_t const & pl, index_t net_ind){
if(circuit.get_net(net_ind).pin_cnt <= 1) return 0;
auto pins = get_pins_1D(circuit, pl, net_ind);
auto minmaxX = std::minmax_element(pins.x.begin(), pins.x.end()), minmaxY = std::minmax_element(pins.y.begin(), pins.y.end());
return ((minmaxX.second->pos - minmaxX.first->pos) + (minmaxY.second->pos - minmaxY.first->pos));
}
std::int64_t get_RSMT_length(netlist const & circuit, placement_t const & pl, index_t net_ind){
if(circuit.get_net(net_ind).pin_cnt <= 1) return 0;
auto pins = get_pins_2D(circuit, pl, net_ind);
std::vector<point<int_t> > points;
for(pin_2D const p : pins){
points.push_back(p.pos);
}
return RSMT_length(points, 8);
}
namespace gp{
void add_force(pin_1D const p1, pin_1D const p2, linear_system & L, float_t force){
if(p1.movable && p2.movable){
L.add_force(
force,
p1.cell_ind, p2.cell_ind,
p1.offs, p2.offs
);
}
else if(p1.movable){
L.add_fixed_force(
force,
p1.cell_ind,
p2.pos,
p1.offs
);
}
else if(p2.movable){
L.add_fixed_force(
force,
p2.cell_ind,
p1.pos,
p2.offs
);
}
}
void add_force(pin_1D const p1, pin_1D const p2, linear_system & L, float_t tol, float_t scale){
add_force(p1, p2, L, scale/std::max(tol, static_cast<float_t>(std::abs((float)(p2.pos-p1.pos)))));
}
point<linear_system> empty_linear_systems(netlist const & circuit, placement_t const & pl){
point<linear_system> ret = point<linear_system>(linear_system(circuit.cell_cnt()), linear_system(circuit.cell_cnt()));
for(index_t i=0; i<circuit.cell_cnt(); ++i){
bool found_true_net=false;
for(auto p : circuit.get_cell(i)){
if(circuit.get_net(p.net_ind).pin_cnt > 1){
found_true_net = true;
break;
}
}
if( (XMovable & circuit.get_cell(i).attributes) == 0 or not found_true_net){
ret.x.add_triplet(i, i, 1.0f);
ret.x.add_doublet(i, pl.positions_[i].x);
}
if( (YMovable & circuit.get_cell(i).attributes) == 0 or not found_true_net){
ret.y.add_triplet(i, i, 1.0f);
ret.y.add_doublet(i, pl.positions_[i].y);
}
}
return ret;
}
namespace{ // Anonymous namespace for helper functions
void get_HPWLF(std::vector<pin_1D> const & pins, linear_system & L, float_t tol){
if(pins.size() >= 2){
auto min_elt = std::min_element(pins.begin(), pins.end()), max_elt = std::max_element(pins.begin(), pins.end());
for(auto it = pins.begin(); it != pins.end(); ++it){
// Just comparing the iterator is poorer due to redundancies in the benchmarks!
if(it != min_elt){
add_force(*it, *min_elt, L, tol, 1.0f/(pins.size()-1));
if(it != max_elt){ // Hopefully only one connexion between the min and max pins
add_force(*it, *max_elt, L, tol, 1.0f/(pins.size()-1));
}
}
}
}
}
void get_HPWLR(std::vector<pin_1D> const & pins, linear_system & L, float_t tol){
std::vector<pin_1D> sorted_pins = pins;
std::sort(sorted_pins.begin(), sorted_pins.end());
// Pins are connected to the pin two places away
for(index_t i=0; i+2<sorted_pins.size(); ++i){
add_force(sorted_pins[i], sorted_pins[i+2], L, tol, 0.5f);
}
// The extreme pins are connected with their direct neighbour too
if(sorted_pins.size() > 1){
add_force(sorted_pins[0], sorted_pins[1], L, tol, 0.5f);
add_force(sorted_pins[sorted_pins.size()-1], sorted_pins[sorted_pins.size()-2], L, tol, 0.5f);
}
}
void get_star(std::vector<pin_1D> const & pins, linear_system & L, float_t tol, index_t star_index){
// The net is empty, but we still populate the diagonal to avoid divide by zeros
if(pins.size() < 2){
L.add_triplet(star_index, star_index, 1.0f);
return;
}
for(pin_1D p : pins){
pin_1D star_pin = pin_1D(star_index, 0, 0, true);
add_force(p, star_pin, L, 1.0/pins.size());
}
}
void get_clique(std::vector<pin_1D> const & pins, linear_system & L, float_t tol){
// Pins are connected to the pin two places away
for(index_t i=0; i+1<pins.size(); ++i){
for(index_t j=i+1; j<pins.size(); ++j){
add_force(pins[i], pins[j], L, tol, 1.0f/(pins.size()-1));
}
}
}
} // End anonymous namespace
point<linear_system> get_HPWLF_linear_system (netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s){
point<linear_system> L = empty_linear_systems(circuit, pl);
for(index_t i=0; i<circuit.net_cnt(); ++i){
// Has the net the right pin count?
index_t pin_cnt = circuit.get_net(i).pin_cnt;
if(pin_cnt < min_s or pin_cnt >= max_s) continue;
auto pins = get_pins_1D(circuit, pl, i);
get_HPWLF(pins.x, L.x, tol);
get_HPWLF(pins.y, L.y, tol);
}
return L;
}
point<linear_system> get_HPWLR_linear_system (netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s){
point<linear_system> L = empty_linear_systems(circuit, pl);
for(index_t i=0; i<circuit.net_cnt(); ++i){
// Has the net the right pin count?
index_t pin_cnt = circuit.get_net(i).pin_cnt;
if(pin_cnt < min_s or pin_cnt >= max_s) continue;
auto pins = get_pins_1D(circuit, pl, i);
get_HPWLR(pins.x, L.x, tol);
get_HPWLR(pins.y, L.y, tol);
}
return L;
}
point<linear_system> get_star_linear_system (netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s){
point<linear_system> L = empty_linear_systems(circuit, pl);
L.x.add_variables(circuit.net_cnt());
L.y.add_variables(circuit.net_cnt());
for(index_t i=0; i<circuit.net_cnt(); ++i){
// Has the net the right pin count?
index_t pin_cnt = circuit.get_net(i).pin_cnt;
if(pin_cnt < min_s or pin_cnt >= max_s){
// Put a one in the intermediate variable in order to avoid non-invertible matrices
L.x.add_triplet(i+circuit.cell_cnt(), i+circuit.cell_cnt(), 1.0f);
L.y.add_triplet(i+circuit.cell_cnt(), i+circuit.cell_cnt(), 1.0f);
continue;
}
auto pins = get_pins_1D(circuit, pl, i);
// Provide the index of the star's central pin in the linear system
get_star(pins.x, L.x, tol, i+circuit.cell_cnt());
get_star(pins.y, L.y, tol, i+circuit.cell_cnt());
}
return L;
}
point<linear_system> get_clique_linear_system (netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s){
point<linear_system> L = empty_linear_systems(circuit, pl);
for(index_t i=0; i<circuit.net_cnt(); ++i){
// Has the net the right pin count?
index_t pin_cnt = circuit.get_net(i).pin_cnt;
if(pin_cnt < min_s or pin_cnt >= max_s) continue;
auto pins = get_pins_1D(circuit, pl, i);
get_clique(pins.x, L.x, tol);
get_clique(pins.y, L.y, tol);
}
return L;
}
point<linear_system> get_MST_linear_system(netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s){
point<linear_system> L = empty_linear_systems(circuit, pl);
for(index_t i=0; i<circuit.net_cnt(); ++i){
// Has the net the right pin count?
index_t pin_cnt = circuit.get_net(i).pin_cnt;
if(pin_cnt < min_s or pin_cnt >= max_s or pin_cnt <= 1) continue;
auto pins = get_pins_2D(circuit, pl, i);
std::vector<point<int_t> > points;
for(pin_2D const p : pins){
points.push_back(p.pos);
}
auto const edges = get_MST_topology(points);
for(auto E : edges){
add_force(pins[E.first].x(), pins[E.second].x(), L.x, tol, 1.0f);
add_force(pins[E.first].y(), pins[E.second].y(), L.y, tol, 1.0f);
}
}
return L;
}
point<linear_system> get_RSMT_linear_system(netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s){
point<linear_system> L = empty_linear_systems(circuit, pl);
for(index_t i=0; i<circuit.net_cnt(); ++i){
// Has the net the right pin count?
index_t pin_cnt = circuit.get_net(i).pin_cnt;
if(pin_cnt < min_s or pin_cnt >= max_s or pin_cnt <= 1) continue;
auto pins = get_pins_2D(circuit, pl, i);
std::vector<point<int_t> > points;
for(pin_2D const p : pins){
points.push_back(p.pos);
}
auto const edges = get_RSMT_topology(points, 8);
for(auto E : edges.x){
add_force(pins[E.first].x(), pins[E.second].x(), L.x, tol, 1.0f);
}
for(auto E : edges.y){
add_force(pins[E.first].y(), pins[E.second].y(), L.y, tol, 1.0f);
}
}
return L;
}
std::int64_t get_HPWL_wirelength(netlist const & circuit, placement_t const & pl){
std::int64_t sum = 0;
for(index_t i=0; i<circuit.net_cnt(); ++i){
sum += get_HPWL_length(circuit, pl, i);
}
return sum;
}
// The true wirelength with minimum spanning trees, except for very small nets (<= 3) where we have HPWL == true WL
std::int64_t get_MST_wirelength(netlist const & circuit, placement_t const & pl){
std::int64_t sum = 0;
for(index_t i=0; i<circuit.net_cnt(); ++i){
auto pins = get_pins_2D(circuit, pl, i);
std::vector<point<int_t> > points;
for(pin_2D const p : pins){
points.push_back(p.pos);
}
sum += MST_length(points);
}
return sum;
}
std::int64_t get_RSMT_wirelength(netlist const & circuit, placement_t const & pl){
std::int64_t sum = 0;
for(index_t i=0; i<circuit.net_cnt(); ++i){
sum += get_RSMT_length(circuit, pl, i);
}
return sum;
}
void solve_linear_system(netlist const & circuit, placement_t & pl, point<linear_system> & L, index_t nbr_iter){
std::vector<float_t> x_sol, y_sol;
std::vector<float_t> x_guess(pl.cell_cnt()), y_guess(pl.cell_cnt());
assert(L.x.internal_size() == x_guess.size());
assert(L.y.internal_size() == y_guess.size());
for(index_t i=0; i<pl.cell_cnt(); ++i){
x_guess[i] = static_cast<float_t>(pl.positions_[i].x);
y_guess[i] = static_cast<float_t>(pl.positions_[i].y);
}
#pragma omp parallel sections num_threads(2)
{
#pragma omp section
x_sol = L.x.solve_CG(x_guess, nbr_iter);
#pragma omp section
y_sol = L.y.solve_CG(y_guess, nbr_iter);
}
for(index_t i=0; i<pl.cell_cnt(); ++i){
if( (circuit.get_cell(i).attributes & XMovable) != 0){
assert(std::isfinite(x_sol[i]));
pl.positions_[i].x = static_cast<int_t>(x_sol[i]);
}
if( (circuit.get_cell(i).attributes & YMovable) != 0){
assert(std::isfinite(y_sol[i]));
pl.positions_[i].y = static_cast<int_t>(y_sol[i]);
}
}
}
// Intended to be used by pulling forces to adapt the forces to the cell's areas
std::vector<float_t> get_area_scales(netlist const & circuit){
std::vector<float_t> ret(circuit.cell_cnt());
capacity_t int_tot_area = 0;
for(index_t i=0; i<circuit.cell_cnt(); ++i){
capacity_t A = circuit.get_cell(i).area;
ret[i] = static_cast<float_t>(A);
int_tot_area += A;
}
float_t inv_average_area = circuit.cell_cnt() / static_cast<float_t>(int_tot_area);
for(index_t i=0; i<circuit.cell_cnt(); ++i){
ret[i] *= inv_average_area;
}
return ret;
}
point<linear_system> get_pulling_forces (netlist const & circuit, placement_t const & pl, float_t typical_distance){
point<linear_system> L = empty_linear_systems(circuit, pl);
float_t typical_force = 1.0f / typical_distance;
std::vector<float_t> scaling = get_area_scales(circuit);
for(index_t i=0; i<pl.cell_cnt(); ++i){
L.x.add_anchor(
typical_force * scaling[i],
i, pl.positions_[i].x
);
L.y.add_anchor(
typical_force * scaling[i],
i, pl.positions_[i].y
);
}
return L;
}
point<linear_system> get_linear_pulling_forces (netlist const & circuit, placement_t const & UB_pl, placement_t const & LB_pl, float_t force, float_t min_distance){
point<linear_system> L = empty_linear_systems(circuit, UB_pl);
assert(LB_pl.cell_cnt() == UB_pl.cell_cnt());
std::vector<float_t> scaling = get_area_scales(circuit);
for(index_t i=0; i<LB_pl.cell_cnt(); ++i){
L.x.add_anchor(
force * scaling[i] / (std::max(static_cast<float_t>(std::abs((float)(UB_pl.positions_[i].x - LB_pl.positions_[i].x))), min_distance)),
i, UB_pl.positions_[i].x
);
L.y.add_anchor(
force * scaling[i] / (std::max(static_cast<float_t>(std::abs((float)(UB_pl.positions_[i].y - LB_pl.positions_[i].y))), min_distance)),
i, UB_pl.positions_[i].y
);
}
return L;
}
region_distribution get_rough_legalizer(netlist const & circuit, placement_t const & pl, box<int_t> surface){
return region_distribution::uniform_density_distribution(surface, circuit, pl);
}
void get_rough_legalization(netlist const & circuit, placement_t & pl, region_distribution const & legalizer){
auto exportation = legalizer.export_spread_positions_linear();
for(auto const C : exportation){
pl.positions_[C.index_in_placement_] = static_cast<point<int_t> >(C.pos_ - 0.5f * static_cast<point<float_t> >(circuit.get_cell(C.index_in_placement_).size));
}
}
float_t get_mean_linear_disruption(netlist const & circuit, placement_t const & LB_pl, placement_t const & UB_pl){
float_t tot_cost = 0.0;
float_t tot_area = 0.0;
for(index_t i=0; i<circuit.cell_cnt(); ++i){
float_t area = static_cast<float_t>(circuit.get_cell(i).area);
point<int_t> diff = LB_pl.positions_[i] - UB_pl.positions_[i];
if( (circuit.get_cell(i).attributes & XMovable) == 0) assert(diff.x == 0);
if( (circuit.get_cell(i).attributes & YMovable) == 0) assert(diff.y == 0);
tot_cost += area * (std::abs((float)diff.x) + std::abs((float)diff.y));
tot_area += area;
}
return tot_cost / tot_area;
}
float_t get_mean_quadratic_disruption(netlist const & circuit, placement_t const & LB_pl, placement_t const & UB_pl){
float_t tot_cost = 0.0;
float_t tot_area = 0.0;
for(index_t i=0; i<circuit.cell_cnt(); ++i){
float_t area = static_cast<float_t>(circuit.get_cell(i).area);
point<int_t> diff = LB_pl.positions_[i] - UB_pl.positions_[i];
if( (circuit.get_cell(i).attributes & XMovable) == 0) assert(diff.x == 0);
if( (circuit.get_cell(i).attributes & YMovable) == 0) assert(diff.y == 0);
float_t manhattan = (std::abs((float)diff.x) + std::abs((float)diff.y));
tot_cost += area * manhattan * manhattan;
tot_area += area;
}
return std::sqrt(tot_cost / tot_area);
}
} // namespace gp
} // namespace coloquinte

View File

@ -1,59 +0,0 @@
#ifndef COLOQUINTE_GP_CIRCUIT
#define COLOQUINTE_GP_CIRCUIT
#include "common.hxx"
#include "solvers.hxx"
#include "netlist.hxx"
#include "rough_legalizers.hxx"
#include <vector>
#include <cassert>
namespace coloquinte{
void verify_placement_legality(netlist const & circuit, placement_t const & pl, box<int_t> surface);
namespace gp{
point<linear_system> empty_linear_systems(netlist const & circuit, placement_t const & pl);
// Net models stuff
point<linear_system> get_HPWLF_linear_system (netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s);
point<linear_system> get_HPWLR_linear_system (netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s);
point<linear_system> get_star_linear_system (netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s);
point<linear_system> get_clique_linear_system (netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s);
point<linear_system> get_MST_linear_system (netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s);
point<linear_system> get_RSMT_linear_system (netlist const & circuit, placement_t const & pl, float_t tol, index_t min_s, index_t max_s);
// Additional forces
point<linear_system> get_pulling_forces (netlist const & circuit, placement_t const & pl, float_t typical_distance);
point<linear_system> get_linear_pulling_forces (netlist const & circuit, placement_t const & UB_pl, placement_t const & LB_pl, float_t force, float_t min_distance);
// Solve the final linear system
void solve_linear_system(netlist const & circuit, placement_t & pl, point<linear_system> & L, index_t nbr_iter);
// Cost-related stuff, whether wirelength or disruption
std::int64_t get_HPWL_wirelength (netlist const & circuit, placement_t const & pl);
std::int64_t get_MST_wirelength (netlist const & circuit, placement_t const & pl);
std::int64_t get_RSMT_wirelength (netlist const & circuit, placement_t const & pl);
float_t get_mean_linear_disruption(netlist const & circuit, placement_t const & LB_pl, placement_t const & UB_pl);
float_t get_mean_quadratic_disruption(netlist const & circuit, placement_t const & LB_pl, placement_t const & UB_pl);
// Legalizer-related stuff
region_distribution get_rough_legalizer(netlist const & circuit, placement_t const & pl, box<int_t> surface);
void get_rough_legalization(netlist const & circuit, placement_t & pl, region_distribution const & legalizer);
// Cell orientation optimization
void optimize_x_orientations(netlist const & circuit, placement_t & pl);
void optimize_y_orientations(netlist const & circuit, placement_t & pl);
void optimize_exact_orientations(netlist const & circuit, placement_t & pl);
//void spread_orientations(netlist const & circuit, placement_t & pl);
} // namespace gp
} // namespace coloquinte
#endif

View File

@ -1,92 +0,0 @@
#ifndef COLOQUINTE_GP_HELPERCIRCUIT
#define COLOQUINTE_GP_HELPERCIRCUIT
#include "common.hxx"
#include "netlist.hxx"
#include <cmath>
namespace coloquinte{
struct pin_1D{
index_t cell_ind;
int_t pos;
int_t offs;
bool movable;
bool operator<(pin_1D const o) const { return pos < o.pos; }
pin_1D(index_t c, int_t p, int_t o, bool m) : cell_ind(c), pos(p), offs(o), movable(m){}
};
struct pin_2D{
index_t cell_ind;
point<int_t> pos;
point<int_t> offs;
bool movable;
pin_2D(index_t c, point<int_t> p, point<int_t> o, bool m) : cell_ind(c), pos(p), offs(o), movable(m){}
pin_1D x() const{ return pin_1D(cell_ind, pos.x, offs.x, movable); }
pin_1D y() const{ return pin_1D(cell_ind, pos.y, offs.y, movable); }
};
inline int_t dist(pin_2D const a, pin_2D const b){
point<int_t> diff = a.pos - b.pos;
return std::abs((float)diff.x) + std::abs((float)diff.y);
}
inline std::vector<pin_2D> get_pins_2D(netlist const & circuit, placement_t const & pl, index_t net_ind){
std::vector<pin_2D> ret;
for(auto p : circuit.get_net(net_ind)){
assert(std::isfinite(pl.positions_[p.cell_ind].x) and std::isfinite(pl.positions_[p.cell_ind].y));
assert(std::isfinite(pl.orientations_[p.cell_ind].x) and std::isfinite(pl.orientations_[p.cell_ind].y));
point<int_t> offs;
offs.x = pl.orientations_[p.cell_ind].x ? p.offset.x : circuit.get_cell(p.cell_ind).size.x - p.offset.x;
offs.y = pl.orientations_[p.cell_ind].y ? p.offset.y : circuit.get_cell(p.cell_ind).size.y - p.offset.y;
point<int_t> pos = offs + pl.positions_[p.cell_ind];
assert(std::isfinite(offs.x) and std::isfinite(offs.y));
assert(std::isfinite(pos.x) and std::isfinite(pos.y));
bool movable = (circuit.get_cell(p.cell_ind).attributes & XMovable) != 0 and (circuit.get_cell(p.cell_ind).attributes & YMovable) != 0;
ret.push_back(pin_2D(p.cell_ind, pos, offs, movable));
}
return ret;
}
inline point<std::vector<pin_1D> > get_pins_1D(netlist const & circuit, placement_t const & pl, index_t net_ind){
point<std::vector<pin_1D> > ret;
for(auto p : circuit.get_net(net_ind)){
assert(std::isfinite(pl.positions_[p.cell_ind].x) and std::isfinite(pl.positions_[p.cell_ind].y));
assert(std::isfinite(pl.orientations_[p.cell_ind].x) and std::isfinite(pl.orientations_[p.cell_ind].y));
point<int_t> offs;
offs.x = pl.orientations_[p.cell_ind].x ? p.offset.x : circuit.get_cell(p.cell_ind).size.x - p.offset.x;
offs.y = pl.orientations_[p.cell_ind].y ? p.offset.y : circuit.get_cell(p.cell_ind).size.y - p.offset.y;
point<int_t> pos = offs + pl.positions_[p.cell_ind];
assert(std::isfinite(offs.x) and std::isfinite(offs.y));
assert(std::isfinite(pos.x) and std::isfinite(pos.y));
bool x_movable = (circuit.get_cell(p.cell_ind).attributes & XMovable) != 0;
bool y_movable = (circuit.get_cell(p.cell_ind).attributes & YMovable) != 0;
ret.x.push_back(pin_1D(p.cell_ind, pos.x, offs.x, x_movable));
ret.y.push_back(pin_1D(p.cell_ind, pos.y, offs.y, y_movable));
}
return ret;
}
std::int64_t MST_length(std::vector<point<int_t> > const & pins);
std::int64_t RSMT_length(std::vector<point<int_t> > const & pins, index_t exactitude_limit);
std::int64_t get_HPWL_length(netlist const & circuit, placement_t const & pl, index_t net_ind);
std::int64_t get_RSMT_length(netlist const & circuit, placement_t const & pl, index_t net_ind);
std::vector<std::pair<index_t, index_t> > get_MST_topology(std::vector<point<int_t> > const & pins);
std::vector<std::pair<index_t, index_t> > get_RSMT_horizontal_topology(std::vector<point<int_t> > const & pins, index_t exactitude_limits);
point<std::vector<std::pair<index_t, index_t> > > get_RSMT_topology(std::vector<point<int_t> > const & pins, index_t exactitude_limit);
} // namespace coloquinte
#endif

View File

@ -1,118 +0,0 @@
#ifndef COLOQUINTE_GP_COMMON
#define COLOQUINTE_GP_COMMON
#include <cstdint>
#include <algorithm>
namespace coloquinte{
using float_t = float;
using int_t = std::int32_t;
using index_t = std::uint32_t;
using capacity_t = std::int64_t;
using mask_t = std::uint32_t;
using ext_object = std::uint64_t;
enum PlacementType{
Optimist = 0,
Pessimist = 1
};
enum Movability{
XMovable = 1 ,
YMovable = 1 << 1,
XFlippable = 1 << 2,
YFlippable = 1 << 3,
SoftMacro = 1 << 4
};
template<typename T>
struct point{
T x, y;
point(){}
point(T x, T y): x(x), y(y){}
template<typename S>
operator point<S>() const{
return point<S>(static_cast<S>(x), static_cast<S>(y));
}
void operator+=(point<T> const o){
x += o.x;
y += o.y;
}
};
template<typename T>
point<T> operator+(point<T> const a, point<T> const b){
return point<T>(a.x+b.x, a.y+b.y);
}
template<typename T>
point<T> operator-(point<T> const a, point<T> const b){
return point<T>(a.x-b.x, a.y-b.y);
}
template<typename T>
point<T> operator*(T lambda, point<T> const p){
return point<T>(lambda * p.x, lambda * p.y);
}
template<typename T>
point<T> operator*(point<T> const a, point<T> const b){
return point<T>(a.x*b.x, a.y*b.y);
}
template<typename T>
struct box{
T x_min, x_max, y_min, y_max;
box(){}
box(T x_mn, T x_mx, T y_mn, T y_mx) : x_min(x_mn), x_max(x_mx), y_min(y_mn), y_max(y_mx){}
box(point<T> mn, point<T> mx) : x_min(mn.x), x_max(mx.x), y_min(mn.y), y_max(mx.y){}
bool in(box<T> const o) const{
return x_max <= o.x_max
&& y_max <= o.y_max
&& x_min >= o.x_min
&& y_min >= o.y_min;
}
bool intersects(box<T> const o) const{
return x_min < o.x_max
&& y_min < o.y_max
&& o.x_min < x_max
&& o.y_min < y_max;
}
box<T> intersection(box<T> const o) const{
return box<T>(
std::max(x_min, o.x_min),
std::min(x_max, o.x_max),
std::max(y_min, o.y_min),
std::min(y_max, o.y_max)
);
}
box<T> bounding_box(box<T> const o) const{
return box<T>(
std::min(x_min, o.x_min),
std::max(x_max, o.x_max),
std::min(y_min, o.y_min),
std::max(y_max, o.y_max)
);
}
point<T> dimensions() const{
return point<T>(x_max-x_min, y_max-y_min);
}
bool empty() const{
return dimensions().x <= 0 or dimensions().y <= 0;
}
template<typename S>
operator box<S>() const{
return box<S>(static_cast<S>(x_min), static_cast<S>(x_max), static_cast<S>(y_min), static_cast<S>(y_max));
}
};
using orientation_t = point<bool>;
} // Namespace coloquinte
#endif

View File

@ -1,89 +0,0 @@
#ifndef COLOQUINTE_DETAILED
#define COLOQUINTE_DETAILED
#include "common.hxx"
#include "netlist.hxx"
#include <vector>
#include <limits>
namespace coloquinte{
namespace dp{
const index_t null_ind = std::numeric_limits<index_t>::max();
struct detailed_placement{
// All position and orientation stuff
placement_t plt_;
std::vector<index_t> cell_rows_;
// The placement region
int_t min_x_, max_x_;
int_t y_origin_;
int_t row_height_;
// Encode the topological state of the circuit: which cells are near each other
// Makes extracting part of the circuit or optimizing positions at fixed topology easy
std::vector<std::pair<index_t, index_t> > neighbours_; // The cells before and after on each row; cells spanning multiple columns use several positions
// In order to get the neighbours in the detailed placement
std::vector<index_t> neighbours_limits_;
std::vector<index_t> row_first_cells_, row_last_cells_; // For each row, which cells are the on the boundaries
// Tests the coherency between positions, widths and topological representation
void selfcheck() const;
detailed_placement(
placement_t pl,
std::vector<index_t> placement_rows,
std::vector<index_t> cell_heights,
std::vector<std::vector<index_t> > rows,
int_t min_x, int_t max_x,
int_t y_origin,
index_t nbr_rows, int_t row_height
);
index_t cell_height(index_t c) const{ return neighbours_limits_[c+1] - neighbours_limits_[c]; }
index_t cell_cnt() const{ return cell_rows_.size(); }
index_t row_cnt() const{ return row_first_cells_.size(); }
index_t neighbour_index(index_t c, index_t r) const{
assert(r - cell_rows_[c] < cell_height(c));
return neighbours_limits_[c] + r - cell_rows_[c];
}
void swap_standard_cell_topologies(index_t c1, index_t c2);
std::pair<int_t, int_t> get_limit_positions(netlist const & circuit, index_t c) const;
index_t get_first_cell_on_row(index_t r);
index_t get_next_cell_on_row(index_t c, index_t r);
index_t get_prev_cell_on_row(index_t c, index_t r);
index_t get_first_standard_cell_on_row(index_t r);
index_t get_next_standard_cell_on_row(index_t c, index_t r);
void reorder_standard_cells(std::vector<index_t> const old_order, std::vector<index_t> const new_order);
void reorder_cells(std::vector<index_t> const old_order, std::vector<index_t> const new_order, index_t row);
};
void swaps_global_HPWL(netlist const & circuit, detailed_placement & pl, index_t row_extent, index_t cell_extent, bool try_flip = false);
void swaps_global_RSMT(netlist const & circuit, detailed_placement & pl, index_t row_extent, index_t cell_extent, bool try_flip = false);
void swaps_row_convex_HPWL(netlist const & circuit, detailed_placement & pl, index_t range);
void swaps_row_convex_RSMT(netlist const & circuit, detailed_placement & pl, index_t range);
void swaps_row_noncvx_HPWL(netlist const & circuit, detailed_placement & pl, index_t range);
void swaps_row_noncvx_RSMT(netlist const & circuit, detailed_placement & pl, index_t range);
void OSRP_convex_HPWL(netlist const & circuit, detailed_placement & pl);
void OSRP_convex_RSMT(netlist const & circuit, detailed_placement & pl);
void OSRP_noncvx_HPWL(netlist const & circuit, detailed_placement & pl);
void OSRP_noncvx_RSMT(netlist const & circuit, detailed_placement & pl);
void row_compatible_orientation(netlist const & circuit, detailed_placement & pl, bool first_row_orient);
} // namespace dp
} // namespace coloquinte
#endif

View File

@ -1,12 +0,0 @@
#include "circuit.hxx"
#include "detailed.hxx"
namespace coloquinte{
namespace dp{
detailed_placement legalize(netlist const & circuit, placement_t const & pl, box<int_t> surface, int_t row_height);
void get_result(netlist const & circuit, detailed_placement const & dpl, placement_t & pl);
} // namespace dp
} // namespace coloquinte

View File

@ -1,251 +0,0 @@
#ifndef COLOQUINTE_NETLIST
#define COLOQUINTE_NETLIST
#include "common.hxx"
#include <vector>
#include <cassert>
namespace coloquinte{
// Structures for construction and circuit_loader
struct temporary_pin{
point<int_t> offset;
index_t cell_ind, net_ind;
temporary_pin(){}
temporary_pin(point<int_t> offs, index_t c, index_t n) : offset(offs), cell_ind(c), net_ind(n){}
};
struct temporary_cell{
point<int_t> size;
capacity_t area;
mask_t attributes;
index_t list_index;
temporary_cell(){}
temporary_cell(point<int_t> s, mask_t attr, index_t ind) : size(s), attributes(attr), list_index(ind){ area = static_cast<capacity_t>(s.x) * static_cast<capacity_t>(s.y);}
};
struct temporary_net{
int_t weight;
index_t list_index;
temporary_net(){}
temporary_net(index_t ind, int_t wght) : weight(wght), list_index(ind){}
};
// Main class
class netlist{
std::vector<int_t> net_weights_;
std::vector<capacity_t> cell_areas_;
std::vector<point<int_t> > cell_sizes_;
std::vector<mask_t> cell_attributes_;
// Mapping of the order given at construction time to the internal representation
std::vector<index_t> cell_internal_mapping_;
std::vector<index_t> net_internal_mapping_;
// Optimized sparse storage for nets
std::vector<index_t> net_limits_;
std::vector<index_t> cell_indexes_;
std::vector<point<int_t> > pin_offsets_;
// Sparse storage from cell to net appartenance
std::vector<index_t> cell_limits_;
std::vector<index_t> net_indexes_;
std::vector<index_t> pin_indexes_;
public:
netlist(std::vector<temporary_cell> cells, std::vector<temporary_net> nets, std::vector<temporary_pin> all_pins);
netlist(){}
void selfcheck() const;
struct pin_t{
point<int_t> offset;
index_t cell_ind, net_ind;
pin_t(point<int_t> offs, index_t c, index_t n) : offset(offs), cell_ind(c), net_ind(n){}
};
class net_pin_iterator{
index_t pin_ind, net_ind;
netlist const & N;
public:
pin_t operator*() const{
return pin_t(N.pin_offsets_[pin_ind], N.cell_indexes_[pin_ind], net_ind);
}
net_pin_iterator & operator++(){
pin_ind++;
return *this;
}
bool operator!=(net_pin_iterator const o) const{
return pin_ind != o.pin_ind;
}
net_pin_iterator(index_t net_index, index_t pin_index, netlist const & orig) : pin_ind(pin_index), net_ind(net_index), N(orig){}
};
class cell_pin_iterator{
index_t pin_ind, cell_ind;
netlist const & N;
public:
pin_t operator*() const{
return pin_t(N.pin_offsets_[N.pin_indexes_[pin_ind]], cell_ind, N.net_indexes_[pin_ind]);
}
cell_pin_iterator & operator++(){
pin_ind++;
return *this;
}
bool operator!=(cell_pin_iterator const o) const{
return pin_ind != o.pin_ind;
}
cell_pin_iterator(index_t cell_index, index_t pin_index, netlist const & orig) : pin_ind(pin_index), cell_ind(cell_index), N(orig){}
};
struct internal_cell{
point<int_t> size;
capacity_t area;
mask_t attributes;
netlist const & N;
index_t index;
index_t pin_cnt;
internal_cell(index_t ind, netlist const & orig) :
size(orig.cell_sizes_[ind]),
area(orig.cell_areas_[ind]),
attributes(orig.cell_attributes_[ind]),
N(orig),
index(ind),
pin_cnt(N.cell_limits_[ind+1] - N.cell_limits_[ind])
{}
cell_pin_iterator begin(){ return cell_pin_iterator(index, N.cell_limits_[index], N); }
cell_pin_iterator end(){ return cell_pin_iterator(index, N.cell_limits_[index+1], N); }
};
struct internal_net{
int_t weight;
netlist const & N;
index_t index;
index_t pin_cnt;
internal_net(index_t ind, netlist const & orig) :
weight(orig.net_weights_[ind]),
N(orig),
index(ind),
pin_cnt(N.net_limits_[ind+1] - N.net_limits_[ind])
{}
net_pin_iterator begin(){ return net_pin_iterator(index, N.net_limits_[index], N); }
net_pin_iterator end(){ return net_pin_iterator(index, N.net_limits_[index+1], N); }
};
internal_cell get_cell(index_t ind) const{
return internal_cell(ind, *this);
}
internal_net get_net(index_t ind) const{
return internal_net(ind, *this);
}
index_t cell_cnt() const{ return cell_internal_mapping_.size(); }
index_t net_cnt() const{ return net_internal_mapping_.size(); }
index_t pin_cnt() const{ return pin_offsets_.size(); }
index_t get_cell_ind(index_t external_ind) const{ return cell_internal_mapping_[external_ind]; }
index_t get_net_ind(index_t external_ind) const{ return net_internal_mapping_[external_ind]; }
point<int_t> get_cell_size(index_t external_ind){
return cell_sizes_[ cell_internal_mapping_[external_ind] ];
}
void set_cell_size(index_t external_ind,point<int_t> cell_size){
cell_sizes_[cell_internal_mapping_[external_ind]] = cell_size;
}
};
inline netlist::netlist(std::vector<temporary_cell> cells, std::vector<temporary_net> nets, std::vector<temporary_pin> all_pins){
struct extended_pin : public temporary_pin{
index_t pin_index;
extended_pin(temporary_pin const p) : temporary_pin(p){}
};
std::vector<extended_pin> pins;
for(temporary_pin const p : all_pins){
pins.push_back(extended_pin(p));
}
cell_limits_.resize(cells.size()+1);
net_limits_.resize(nets.size()+1);
net_weights_.resize(nets.size());
cell_areas_.resize(cells.size());
cell_sizes_.resize(cells.size());
cell_attributes_.resize(cells.size());
cell_internal_mapping_.resize(cells.size());
net_internal_mapping_.resize(nets.size());
cell_indexes_.resize(pins.size());
pin_offsets_.resize(pins.size());
net_indexes_.resize(pins.size());
pin_indexes_.resize(pins.size());
for(index_t i=0; i<nets.size(); ++i){
net_internal_mapping_[i] = i;
}
for(index_t i=0; i<cells.size(); ++i){
cell_internal_mapping_[i] = i;
}
std::sort(pins.begin(), pins.end(), [](extended_pin const a, extended_pin const b){ return a.net_ind < b.net_ind; });
for(index_t n=0, p=0; n<nets.size(); ++n){
net_weights_[n] = nets[n].weight;
net_limits_[n] = p;
while(p<pins.size() && pins[p].net_ind == n){
cell_indexes_[p] = pins[p].cell_ind;
pin_offsets_[p] = pins[p].offset;
pins[p].pin_index = p;
++p;
}
}
net_limits_.back() = pins.size();
std::sort(pins.begin(), pins.end(), [](extended_pin const a, extended_pin const b){ return a.cell_ind < b.cell_ind; });
for(index_t c=0, p=0; c<cells.size(); ++c){
cell_areas_[c] = cells[c].area;
cell_attributes_[c] = cells[c].attributes;
cell_sizes_[c] = cells[c].size;
cell_limits_[c] = p;
while(p<pins.size() && pins[p].cell_ind == c){
net_indexes_[p] = pins[p].net_ind;
pin_indexes_[p] = pins[p].pin_index;
++p;
}
}
cell_limits_.back() = pins.size();
}
struct placement_t{
std::vector<point<int_t> > positions_;
std::vector<point<bool> > orientations_;
index_t cell_cnt() const{
assert(positions_.size() == orientations_.size());
return positions_.size();
}
void selfcheck() const;
};
} // namespace coloquinte
#endif

View File

@ -1,161 +0,0 @@
#ifndef COLOQUINTE_GP_OPTSUBPROBLEMS
#define COLOQUINTE_GP_OPTSUBPROBLEMS
#include "common.hxx"
#include <queue>
#include <vector>
#include <cassert>
#include <numeric>
#include <cmath>
#include <limits>
namespace coloquinte{
typedef std::pair<int_t, capacity_t> t1D_elt;
std::vector<capacity_t> transport_1D(std::vector<t1D_elt> sources, std::vector<t1D_elt> sinks);
std::vector<std::vector<capacity_t> > transport_convex(std::vector<capacity_t> const & capacities, std::vector<capacity_t> const & demands, std::vector<std::vector<float_t> > const & costs);
std::vector<std::vector<capacity_t> > transport_generic(std::vector<capacity_t> const & capacities, std::vector<capacity_t> const & demands, std::vector<std::vector<float_t> > const & costs);
template<typename T>
struct legalizable_task{
T width;
T target_pos;
index_t ind;
legalizable_task(T w, T p, index_t i) : width(w), target_pos(p), ind(i){}
bool operator<(legalizable_task<T> const o) const{ return target_pos < o.target_pos; }
};
// A class to obtain the optimal positions minimizing total weighted displacement along a row
// It is an ordered single row problem/fixed order single machine scheduling problem, solved by the clumping/specialized cascading descent algorithm
// The cost is linear in the distance to the target position, weighted by the width of the cells
template<typename T>
class OSRP_leg{
struct OSRP_bound{
T absolute_pos; // Will be the target absolute position of the cell
T weight; // Will be the width of the cell
bool operator<(OSRP_bound const o) const{ return absolute_pos < o.absolute_pos; }
OSRP_bound(T w, T abs_pos) : absolute_pos(abs_pos), weight(w) {}
};
T begin, end;
std::vector<index_t> cells; // The indexes in the circuit
std::vector<T> constraining_pos; // Where the cells have been pushed and constrain the positions of preceding cells
std::vector<T> prev_width; // Cumulative width of the cells: calculates the absolute position of new cells
std::priority_queue<OSRP_bound> bounds;
// Get the cost of pushing a cell on the row
T get_displacement(legalizable_task<T> const newly_pushed, bool update);
public:
T current_width() const{ return prev_width.back(); }
T remaining_space() const{ return end - begin - current_width(); }
T last_available_pos() const{ return constraining_pos.back() + current_width(); }
T get_cost(legalizable_task<T> const task){ return get_displacement(task, false); }
void push(legalizable_task<T> const task){ get_displacement(task, true); }
// Initialize
OSRP_leg(T b, T e) : begin(b), end(e), prev_width(1, 0) {}
OSRP_leg(){}
typedef std::pair<index_t, T> result_t;
// Get the resulting placement
std::vector<result_t> get_placement() const;
};
struct cell_bound{
index_t c;
int_t pos;
int_t slope;
bool operator<(cell_bound const o) const{ return c < o.c; }
cell_bound(index_t order, int_t p, int_t s) : c(order), pos(p), slope(s) {}
};
bool place_convex_single_row(std::vector<int_t> const & widths, std::vector<std::pair<int_t, int_t> > const & ranges, std::vector<cell_bound> bounds, std::vector<int_t> const & const_slopes, std::vector<int_t> & positions);
bool place_noncvx_single_row(std::vector<int_t> const & widths, std::vector<std::pair<int_t, int_t> > const & ranges, std::vector<int> const & flippables, std::vector<cell_bound> bounds, std::vector<int_t> const & const_slopes, std::vector<int_t> & positions, std::vector<int> & flippings);
template<typename T>
inline T OSRP_leg<T>::get_displacement(legalizable_task<T> const newly_pushed, bool update){
T target_abs_pos = newly_pushed.target_pos - current_width();
T width = newly_pushed.width;
T slope = - width;
T cur_pos = end;
T cur_cost = 0;
std::vector<OSRP_bound> passed_bounds;
while( not bounds.empty() and
((slope < 0 and bounds.top().absolute_pos > target_abs_pos) // Not reached equilibrium
or bounds.top().absolute_pos > end - current_width() - width) // Still not a legal position
){
T old_pos = cur_pos;
cur_pos = bounds.top().absolute_pos;
cur_cost += (old_pos - cur_pos) * (slope + width); // The additional cost for the other cells encountered
slope += bounds.top().weight;
// Remember which bounds we encountered in order to reset the object to its initial state
if(not update)
passed_bounds.push_back(bounds.top());
bounds.pop();
}
T final_abs_pos = std::min(end - current_width() - width, // Always before the end and after the beginning
std::max(begin, slope >= 0 ? cur_pos : target_abs_pos) // but did we stop before reaching the target position?
);
cur_cost += (cur_pos - final_abs_pos) * (slope + width); // The additional cost for the other cells encountered
if(std::numeric_limits<T>::is_integer){
assert(final_abs_pos >= begin);
assert(final_abs_pos <= end - current_width() - width);
}
if(update){
prev_width.push_back(width + current_width());
cells.push_back(newly_pushed.ind);
constraining_pos.push_back(final_abs_pos);
if(slope > 0){ // Remaining capacity of an encountered bound
bounds.push(OSRP_bound(slope, cur_pos));
}
// The new bound, minus what it absorbs of the remaining slope
if(target_abs_pos > begin){
bounds.push(OSRP_bound(2*width + std::min(slope, static_cast<T>(0) ), target_abs_pos));
}
}
else{
for(OSRP_bound b : passed_bounds){
bounds.push(b);
}
}
return cur_cost + width * std::abs((float)(final_abs_pos - target_abs_pos)); // Add the cost of the new cell
}
template<typename T>
inline std::vector<std::pair<index_t, T> > OSRP_leg<T>::get_placement() const{
auto final_abs_pos = constraining_pos;
std::partial_sum(final_abs_pos.rbegin(), final_abs_pos.rend(), final_abs_pos.rbegin(), [](T a, T b)->T{ return std::min(a,b); });
std::vector<result_t> ret(cells.size());
for(index_t i=0; i<cells.size(); ++i){
ret[i] = result_t(cells[i], final_abs_pos[i] + prev_width[i]);
if(std::numeric_limits<T>::is_integer){
assert(final_abs_pos[i] >= begin);
assert(final_abs_pos[i] + prev_width[i+1] <= end);
}
}
return ret;
}
}
#endif

View File

@ -1,29 +0,0 @@
#include "common.hxx"
#include <vector>
namespace coloquinte{
typedef std::pair<int_t, int_t> p_v;
struct piecewise_linear_function{
std::vector<p_v> point_values;
static piecewise_linear_function minimum(piecewise_linear_function const & a, piecewise_linear_function const & b);
piecewise_linear_function previous_min_of_sum(piecewise_linear_function const & o, int_t added_cell_width) const;
piecewise_linear_function previous_min() const;
int_t value_at(int_t pos) const;
int_t last_before(int_t pos) const;
void add_monotone(int_t slope, int_t offset);
void add_bislope(int_t s_l, int_t s_r, int_t pos);
piecewise_linear_function(){}
piecewise_linear_function(int_t min_def, int_t max_def);
};
} // End namespace coloquinte

View File

@ -1,263 +0,0 @@
#ifndef COLOQUINTE_GP_ROUGH_LEGALIZER
#define COLOQUINTE_GP_ROUGH_LEGALIZER
#include "common.hxx"
#include "netlist.hxx"
#include <vector>
#include <cassert>
#include <cmath>
#include <functional>
/*
* A simple class to perform approximate legalization with extreme efficiency
*
* To be called during global placement or before an exact legalization
*
*/
namespace coloquinte{
struct density_limit{
box<int_t> box_;
float_t density_; // from 0.0 for a macro to 1.0 if it does nothing
};
typedef std::vector<density_limit> density_restrictions;
namespace gp{
class region_distribution{
/*
* Coordinates are mostly float but obstacles and areas are integers for correctness
*/
public:
struct movable_cell{
capacity_t demand_; // == area; No FP!!!
point<float_t> pos_; // Target position, determining the cost to allocate it
// int_t x_size, y_size; // May split cells
index_t index_in_placement_;
movable_cell();
movable_cell(capacity_t demand, point<float_t> p, index_t ind);
};
// Specifies a maximum density of movable cells per usable area
// Representing either a macroblock or a routing congestion
private:
struct region;
struct cell_ref{
capacity_t allocated_capacity_;
point<float_t> pos_;
index_t index_in_list_;
cell_ref(){}
cell_ref(capacity_t demand, point<float_t> p, index_t ind) : allocated_capacity_(demand), pos_(p), index_in_list_(ind){}
friend region;
};
struct region{
public:
// Data members
capacity_t capacity_; // ==area; No floating point!!!
point<float_t> pos_;
std::vector<cell_ref> cell_references_;
// Constructors
region(){} // Necessary if we want to resize vectors
region(capacity_t cap, point<float_t> pos, std::vector<cell_ref> cells);
// Helper functions for bipartitioning
private:
static void distribute_new_cells(region & a, region & b, std::vector<cell_ref> cells); // Called by the other two to do the dirty work
public:
void distribute_cells(region & a, region & b) const; // Distribute the cells from one region to two
static void redistribute_cells(region & a, region & b); // Optimizes the distribution between two regions
// Helper functions for multipartitioning
private:
static void distribute_new_cells(std::vector<std::reference_wrapper<region_distribution::region> > regions, std::vector<cell_ref> cells);
public:
void distribute_cells(std::vector<std::reference_wrapper<region_distribution::region> > regions) const;
static void redistribute_cells(std::vector<std::reference_wrapper<region_distribution::region> > regions);
// Helper functions for 1D transportation
public:
static void distribute_new_cells(std::vector<std::reference_wrapper<region_distribution::region> > regions, std::vector<cell_ref> cells, std::function<float_t (point<float_t>)> coord);
static void redistribute_cells(std::vector<std::reference_wrapper<region_distribution::region> > & regions, std::function<float_t (point<float_t>)> coord);
public:
void uniquify_references();
void selfcheck() const;
// Accessors
capacity_t capacity() const;
capacity_t allocated_capacity() const;
capacity_t unused_capacity() const;
index_t cell_cnt() const;
float_t distance(cell_ref const & C) const;
float_t cost() const;
};
private:
// Members
index_t x_regions_cnt_, y_regions_cnt_;
std::vector<movable_cell> cell_list_;
std::vector<region> placement_regions_;
box<int_t> placement_area_;
std::vector<density_limit> density_map_;
const capacity_t full_density_mul; // Multiplicator giving the grain for fractional areas for the surface
capacity_t cell_density_mul; // ANd for the cells
float_t density_scaling_factor_;
private:
// Helper functions
region & get_region(index_t x_coord, index_t y_coord);
region const & get_region(index_t x_coord, index_t y_coord) const;
box<int_t> get_box(index_t x, index_t y, index_t x_cnt, index_t y_cnt) const;
static void sort_uniquify(std::vector<cell_ref> & cell_references);
static void just_uniquify(std::vector<cell_ref> & cell_references);
// Prepare regions with the right positions and capacities; different levels of nesting are compatible
std::vector<region> prepare_regions(index_t x_cnt, index_t y_cnt) const;
public:
inline box<int_t> placement_area() const;
inline point<float_t> region_dimensions() const;
inline index_t x_regions_cnt() const;
inline index_t y_regions_cnt() const;
inline index_t regions_cnt() const;
inline index_t cell_cnt() const;
inline index_t fractional_cell_cnt() const;
/*
* Two types of export
* Region center : upper bound of legalization cost
* 1D quadratic optimization : lower bound of legalization cost
*/
std::vector<movable_cell> export_positions() const;
std::vector<movable_cell> export_spread_positions_quadratic() const;
std::vector<movable_cell> export_spread_positions_linear() const;
// The cost as seen by the partitioning algorithms (but not the export)
float_t cost() const;
/*
* Further partitions
*/
void x_bipartition();
void y_bipartition();
void x_resize(index_t sz);
void y_resize(index_t sz);
void multipartition(index_t x_width, index_t y_width);
void multipartition(index_t width){ multipartition(width, width); }
/*
* Optimization functions
*/
// Bipartitioning: only two regions are considered at a time
void redo_adjacent_bipartitions();
void redo_diagonal_bipartitions();
void redo_bipartitions();
// Line partitioning: optimal on coordinate axis with Manhattan distance (Euclidean distance could use it in any direction)
void redo_line_partitions();
// Multipartitioning: several regions considered, slow runtimes
void redo_diag_partitions(index_t len);
void redo_multipartitions(index_t x_width, index_t y_width);
void redo_multipartitions(index_t width){ redo_multipartitions(width, width); }
// Try to remove duplicate fractional cells
void fractions_minimization();
// Verify
void selfcheck() const;
private:
region_distribution(box<int_t> placement_area, netlist const & circuit, placement_t const & pl, std::vector<density_limit> const & density_map, bool full_density);
public:
/*
* Obtain a region_distribution from a placement
*
* Full density: the object tries to pack the cells as much as possible while still respecting the density limits
* Uniform density: not only are the density limits respected, the allocated capacities are proportional to the allowed densities
*
*/
static region_distribution full_density_distribution(box<int_t> placement_area, netlist const & circuit, placement_t const & pl, std::vector<density_limit> const & density_map = std::vector<density_limit>());
static region_distribution uniform_density_distribution(box<int_t> placement_area, netlist const & circuit, placement_t const & pl, std::vector<density_limit> const & density_map = std::vector<density_limit>());
void update(netlist const & circuit, placement_t const & pl);
};
inline region_distribution::movable_cell::movable_cell(){}
inline region_distribution::movable_cell::movable_cell(capacity_t demand, point<float_t> p, index_t ind) : demand_(demand), pos_(p), index_in_placement_(ind){}
inline box<int_t> region_distribution::placement_area() const { return placement_area_; }
inline point<float_t> region_distribution::region_dimensions() const {
point<int_t> s = static_cast<point<float_t> >(placement_area().dimensions());
return point<float_t>(s.x/x_regions_cnt(), s.y/y_regions_cnt());
}
inline index_t region_distribution::x_regions_cnt() const { return x_regions_cnt_; }
inline index_t region_distribution::y_regions_cnt() const { return y_regions_cnt_; }
inline index_t region_distribution::regions_cnt() const { index_t ret = x_regions_cnt() * y_regions_cnt(); assert(placement_regions_.size() == ret); return ret; }
inline region_distribution::region & region_distribution::get_region(index_t x_coord, index_t y_coord){
return placement_regions_[y_coord * x_regions_cnt() + x_coord];
}
inline region_distribution::region const & region_distribution::get_region(index_t x_coord, index_t y_coord) const{
return placement_regions_[y_coord * x_regions_cnt() + x_coord];
}
inline index_t region_distribution::cell_cnt() const{ return cell_list_.size(); }
inline index_t region_distribution::fractional_cell_cnt() const{
index_t tot_cnt = 0;
for(auto const & R : placement_regions_){
tot_cnt += R.cell_cnt();
}
return tot_cnt;
}
inline capacity_t region_distribution::region::capacity() const{ return capacity_; }
inline capacity_t region_distribution::region::unused_capacity() const{ return capacity() - allocated_capacity(); }
inline capacity_t region_distribution::region::allocated_capacity() const{
capacity_t ret = 0;
for(cell_ref const C : cell_references_){
ret += C.allocated_capacity_;
}
return ret;
}
inline index_t region_distribution::region::cell_cnt() const{ return cell_references_.size(); }
inline float_t region_distribution::region::distance(region_distribution::cell_ref const & C) const{
return std::abs(pos_.x - C.pos_.x) + std::abs(pos_.y - C.pos_.y);
/*
float_t manhattan = std::max(static_cast<float_t>(0.0), std::max(C.pos_.x - surface_.x_max, surface_.x_min - C.pos_.x))
+ std::max(static_cast<float_t>(0.0), std::max(C.pos_.y - surface_.y_max, surface_.y_min - C.pos_.y));
return manhattan * (1.0 + manhattan * 0.0001);
*/
}
} // Namespace gp
} // Namespace coloquinte
#endif

View File

@ -1,88 +0,0 @@
#ifndef COLOQUINE_GP_SOLVERS
#define COLOQUINE_GP_SOLVERS
#include "common.hxx"
#include <vector>
namespace coloquinte{
namespace gp{
struct matrix_doublet{
index_t c_;
float val_;
bool operator<(matrix_doublet const o) const{ return c_ < o.c_; }
matrix_doublet(){}
matrix_doublet(index_t c, float v) : c_(c), val_(v){}
};
struct matrix_triplet{
index_t r_, c_;
float_t val_;
matrix_triplet(index_t ri, index_t ci, float_t v) : r_(ri), c_(ci), val_(v){}
bool operator<(matrix_triplet const o){ return r_ < o.r_ || (r_ == o.r_ && c_ < o.c_); }
};
class linear_system{
std::vector<matrix_triplet> matrix_;
std::vector<float_t> target_;
index_t internal_size_;
public:
void add_triplet(index_t row, index_t col, float_t val){ matrix_.push_back(matrix_triplet(row, col, val)); }
linear_system operator+(linear_system const & o) const;
void add_doublet(index_t row, float_t val){
target_[row] += val;
}
void add_force(
float_t force,
index_t c1, index_t c2,
float_t offs1, float_t offs2
){
add_triplet(c1, c1, force);
add_triplet(c2, c2, force);
add_triplet(c1, c2, -force);
add_triplet(c2, c1, -force);
add_doublet(c1, force * (offs2-offs1));
add_doublet(c2, force * (offs1-offs2));
}
void add_fixed_force(
float_t force,
index_t c,
float_t fixed_pos,
float_t offs
){
add_triplet(c, c, force);
add_doublet(c, force * (fixed_pos-offs));
}
void add_anchor(
float_t scale,
index_t c,
float_t pos
){
add_triplet(c, c, scale);
add_doublet(c, scale*pos);
}
linear_system(index_t s) : target_(s, 0.0), internal_size_(s){}
linear_system(index_t s, index_t i) : target_(s, 0.0), internal_size_(i){}
index_t size() const{ return target_.size(); }
index_t internal_size() const{ return internal_size_; }
void add_variables(index_t cnt){ target_.resize(target_.size() + cnt, 0.0); }
std::vector<float_t> solve_CG(std::vector<float_t> guess, index_t nbr_iter);
};
} // namespace gp
} // namespace coloquinte
#endif

View File

@ -1,35 +0,0 @@
#include "common.hxx"
#include <array>
#ifndef COLOQUINTE_TOPOLOGIES
#define COLOQUINTE_TOPOLOGIES
namespace coloquinte{
namespace steiner_lookup{
template<int pin_cnt>
struct Hconnectivity{
// The edges and the couple of pins connected to the extreme ones are represented by one char each
// The first 4 bits represent the first pin minus one, the next 4 bits the second pin minus one
std::uint8_t connexions[pin_cnt-3];
std::uint8_t extremes;
int_t get_wirelength(std::array<point<int_t>, pin_cnt> const sorted_points) const;
std::array<std::pair<index_t, index_t>, pin_cnt-1> get_x_topology(std::array<point<int_t>, pin_cnt> const sorted_points) const;
};
extern std::array<Hconnectivity<4>, 2> const topologies_4;
extern std::array<Hconnectivity<5>, 6> const topologies_5;
extern std::array<Hconnectivity<6>, 23> const topologies_6;
extern std::array<Hconnectivity<7>, 111> const topologies_7;
extern std::array<Hconnectivity<8>, 642> const topologies_8;
extern std::array<Hconnectivity<9>, 4334> const topologies_9;
extern std::array<Hconnectivity<10>, 33510> const topologies_10;
}
}
#endif

View File

@ -1,47 +0,0 @@
#ifndef COLOQUINTE_UNION_FIND
#define COLOQUINTE_UNION_FIND
#include "common.hxx"
#include <vector>
namespace coloquinte{
class union_find{
std::vector<index_t> connex_representants;
public:
index_t size() const { return connex_representants.size(); }
void merge(index_t a, index_t b){
connex_representants[find(a)] = b;
}
index_t find(index_t ind){
if(connex_representants[ind] != ind){
connex_representants[ind] = find(connex_representants[ind]);
}
return connex_representants[ind];
}
union_find(index_t s) : connex_representants(s){
for(index_t i=0; i<size(); ++i){
connex_representants[i] = i;
}
}
bool is_connex(){
bool connex = true;
for(index_t i=0; i+1<size(); ++i){
connex = connex && (find(i) == find(i+1));
}
return connex;
}
};
} // End namespace coloquinte
#endif

View File

@ -1,261 +0,0 @@
#include "coloquinte/detailed.hxx"
#include "coloquinte/circuit_helper.hxx"
#include <cassert>
namespace coloquinte{
namespace dp{
detailed_placement::detailed_placement(
placement_t pl,
std::vector<index_t> placement_rows,
std::vector<index_t> cell_heights,
std::vector<std::vector<index_t> > rows,
int_t min_x, int_t max_x,
int_t y_origin,
index_t nbr_rows, int_t row_height
)
:
plt_(pl),
cell_rows_(placement_rows),
min_x_(min_x), max_x_(max_x),
y_origin_(y_origin),
row_height_(row_height)
{
assert(row_height > 0);
assert(min_x < max_x);
assert(rows.size() == nbr_rows);
neighbours_limits_.push_back(0);
for(index_t h : cell_heights){
neighbours_limits_.push_back(neighbours_limits_.back() + h);
}
neighbours_ .resize(neighbours_limits_.back(), std::pair<index_t, index_t>(null_ind, null_ind) );
row_first_cells_ .resize(nbr_rows, null_ind);
row_last_cells_ .resize(nbr_rows, null_ind);
std::vector<bool> explored(neighbours_limits_.back(), false);
// Now we extract the dependencies
for(index_t r=0; r<rows.size(); ++r){
if(not rows[r].empty()){
row_first_cells_[r] = rows[r].front();
row_last_cells_[r] = rows[r].back();
}
for(index_t c : rows[r]){
// Has this row of the cell already been visited?
assert(not explored[neighbour_index(c, r)]);
explored[neighbour_index(c, r)] = true;
}
for(index_t i=0; i+1<rows[r].size(); ++i){
index_t c1 = rows[r][i], c2 = rows[r][i+1];
// Save in the internal format
neighbours_[neighbour_index(c1, r)].second = c2;
neighbours_[neighbour_index(c2, r)].first = c1;
// The positions are correct
}
}
// Every level of every cell must have been visited
for(bool o : explored)
assert(o);
// Verify that we haven't made any obvious mistake
selfcheck();
}
void detailed_placement::selfcheck() const{
assert(row_first_cells_.size() == row_last_cells_.size());
for(index_t i=0; i<cell_cnt(); ++i){
for(index_t l=0; l<cell_height(i); ++l){
// not verified now since we don't modify the position for the obstacles
// : assert(c.position.x >= min_x_ and c.position.x + c.width <= max_x_);
index_t n_ind = l + neighbours_limits_[i];
assert(cell_rows_[i] + cell_height(i) <= row_cnt());
if(neighbours_[n_ind].first != null_ind){
index_t oi = neighbours_[n_ind].first;
// Correct neighbour position
assert(neighbours_[neighbour_index(oi, cell_rows_[i]+l)].second == i);
}
else{
// Beginning of a row
assert(row_first_cells_[cell_rows_[i] + l] == i);
}
if(neighbours_[n_ind].second != null_ind){
index_t oi = neighbours_[n_ind].second;
// Correct neighbour position
assert(neighbours_[neighbour_index(oi, cell_rows_[i]+l)].first == i);
}
else{
// End of a row
assert(row_last_cells_[cell_rows_[i] + l] == i);
}
}
}
}
void detailed_placement::swap_standard_cell_topologies(index_t c1, index_t c2){
assert(cell_height(c1) == cell_height(c2));
assert(cell_height(c1) == 1 and cell_height(c2) == 1);
index_t row_c1 = cell_rows_[c1],
row_c2 = cell_rows_[c2];
index_t b_c1 = neighbours_[neighbours_limits_[c1]].first;
index_t b_c2 = neighbours_[neighbours_limits_[c2]].first;
index_t a_c1 = neighbours_[neighbours_limits_[c1]].second;
index_t a_c2 = neighbours_[neighbours_limits_[c2]].second;
// Two cases: they were adjacent or they were not
// Luckily updating in the neighbours first then swapping the recorded neighbours works in both cases for standard cells
// Update the pointers in the cells' neighbours
if(b_c1 != null_ind) neighbours_[neighbour_index(b_c1, row_c1)].second = c2;
else row_first_cells_[row_c1] = c2;
if(b_c2 != null_ind) neighbours_[neighbour_index(b_c2, row_c2)].second = c1;
else row_first_cells_[row_c2] = c1;
if(a_c1 != null_ind) neighbours_[neighbour_index(a_c1, row_c1)].first = c2;
else row_last_cells_[row_c1] = c2;
if(a_c2 != null_ind) neighbours_[neighbour_index(a_c2, row_c2)].first = c1;
else row_last_cells_[row_c2] = c1;
// Swap the properties in both cells
std::swap(neighbours_[neighbours_limits_[c1]], neighbours_[neighbours_limits_[c2]]);
std::swap(cell_rows_[c1], cell_rows_[c2]);
}
std::pair<int_t, int_t> detailed_placement::get_limit_positions(netlist const & circuit, index_t c) const{
auto ret = std::pair<int_t, int_t>(min_x_, max_x_);
for(index_t l=neighbours_limits_[c]; l<neighbours_limits_[c+1]; ++l){
index_t b_i = neighbours_[l].first,
a_i = neighbours_[l].second;
if(b_i != null_ind){
ret.first = std::max(ret.first, plt_.positions_[b_i].x + circuit.get_cell(b_i).size.x);
}
if(a_i != null_ind){
ret.second = std::min(ret.second, plt_.positions_[a_i].x);
}
}
return ret;
}
index_t detailed_placement::get_first_cell_on_row(index_t r){
return row_first_cells_[r];
}
index_t detailed_placement::get_first_standard_cell_on_row(index_t r){
index_t c = get_first_cell_on_row(r);
while(c != null_ind and cell_height(c) != 1){
index_t next_c = get_next_cell_on_row(c, r);
assert(c != next_c);
c = next_c;
}
assert(c == null_ind or cell_rows_[c] == r);
return c;
}
index_t detailed_placement::get_next_cell_on_row(index_t c, index_t r){
return neighbours_[neighbour_index(c, r)].second;
}
index_t detailed_placement::get_prev_cell_on_row(index_t c, index_t r){
return neighbours_[neighbour_index(c, r)].first;
}
index_t detailed_placement::get_next_standard_cell_on_row(index_t c, index_t r){
do{
index_t next_c = get_next_cell_on_row(c, r);
assert(c != next_c);
c = next_c;
}while(c != null_ind and cell_height(c) != 1);
assert(c == null_ind or cell_rows_[c] == r);
return c;
}
void detailed_placement::reorder_cells(std::vector<index_t> const old_order, std::vector<index_t> const new_order, index_t r){
assert(old_order.size() == new_order.size());
assert(not old_order.empty());
index_t before_row = get_prev_cell_on_row(old_order.front(), r);
index_t after_row = get_next_cell_on_row(old_order.back(), r);
for(index_t i=0; i<new_order.size(); ++i){
auto & nghs = neighbours_[neighbour_index(new_order[i], r)];
if(i > 0){
nghs.first = new_order[i-1];
}
else{
nghs.first = before_row;
}
if(i+1 < new_order.size()){
nghs.second = new_order[i+1];
}
else{
nghs.second = after_row;
}
}
if(before_row != null_ind) neighbours_[neighbour_index(before_row, r)].second = new_order.front();
else row_first_cells_[r] = new_order.front();
if(after_row != null_ind) neighbours_[neighbour_index(after_row, r)].first = new_order.back();
else row_last_cells_[r] = new_order.back();
}
void detailed_placement::reorder_standard_cells(std::vector<index_t> const old_order, std::vector<index_t> const new_order){
assert(old_order.size() == new_order.size());
assert(not old_order.empty());
index_t before_row = neighbours_[neighbours_limits_[old_order.front()]].first;
index_t after_row = neighbours_[neighbours_limits_[old_order.back() ]].second;
index_t r = cell_rows_[new_order.front()];
for(index_t i=0; i<new_order.size(); ++i){
assert(cell_height(new_order[i]) == 1);
assert(cell_rows_[new_order[i]] == r);
auto & nghs = neighbours_[neighbours_limits_[new_order[i]]];
if(i > 0){
nghs.first = new_order[i-1];
}
else{
nghs.first = before_row;
}
if(i+1 < new_order.size()){
nghs.second = new_order[i+1];
}
else{
nghs.second = after_row;
}
}
if(before_row != null_ind) neighbours_[neighbour_index(before_row, r)].second = new_order.front();
else row_first_cells_[r] = new_order.front();
if(after_row != null_ind) neighbours_[neighbour_index(after_row, r)].first = new_order.back();
else row_last_cells_[r] = new_order.back();
}
void row_compatible_orientation(netlist const & circuit, detailed_placement & pl, bool first_row_orient){
for(index_t c=0; c<circuit.cell_cnt(); ++c){
if( (circuit.get_cell(c).attributes & YFlippable) != 0 and pl.cell_height(c) == 1){
pl.plt_.orientations_[c].y = (pl.cell_rows_[c] % 2 != 0) ^ first_row_orient;
}
}
}
} // namespace dp
} // namespace coloquinte

View File

@ -1,452 +0,0 @@
#include "coloquinte/legalizer.hxx"
#include "coloquinte/optimization_subproblems.hxx"
#include <iostream>
#include <sstream>
#include <algorithm>
#include <cmath>
#include <queue>
namespace coloquinte{
namespace dp{
void get_result(netlist const & circuit, detailed_placement const & dpl, placement_t & gpl){
for(index_t c=0; c<circuit.cell_cnt(); ++c){
if( (circuit.get_cell(c).attributes & XMovable) != 0)
gpl.positions_[c].x = dpl.plt_.positions_[c].x;
if( (circuit.get_cell(c).attributes & YMovable) != 0)
gpl.positions_[c].y = dpl.plt_.positions_[c].y;
if( (circuit.get_cell(c).attributes & XFlippable) != 0)
gpl.orientations_[c].x = dpl.plt_.orientations_[c].x;
if( (circuit.get_cell(c).attributes & YFlippable) != 0)
gpl.orientations_[c].y = dpl.plt_.orientations_[c].y;
}
}
struct cell_to_leg{
int_t x_pos, y_pos;
index_t original_cell;
int_t width;
index_t nbr_rows;
bool operator<(cell_to_leg const o) const{ return x_pos < o.x_pos; }
cell_to_leg(int_t x, int_t y, index_t ind, int_t w, index_t rows)
: x_pos(x), y_pos(y),
original_cell(ind),
width(w),
nbr_rows(rows)
{}
legalizable_task<int_t> task() const{ return legalizable_task<int_t>(width, x_pos, original_cell); }
};
struct fixed_cell_interval{
int_t min_x, max_x;
index_t cell_ind;
bool operator<(fixed_cell_interval const o) const{ return min_x > o.min_x; }
fixed_cell_interval(int_t mn, int_t mx, index_t ind) : min_x(mn), max_x(mx), cell_ind(ind){}
};
struct cell_leg_properties{
int_t x_pos;
index_t row_pos;
index_t ind;
cell_leg_properties(){}
cell_leg_properties(int_t x, int_t r, index_t i) : x_pos(x), row_pos(r), ind(i){}
};
std::vector<cell_leg_properties> simple_legalize(
std::vector<std::vector<fixed_cell_interval> > obstacles, std::vector<cell_to_leg> cells,
std::vector<std::vector<index_t> > & rows,
int_t x_min, int_t x_max, int_t y_orig,
int_t row_height, index_t nbr_rows
){
std::vector<int_t> first_available_position(nbr_rows, x_min);
rows.resize(nbr_rows);
// Sort the cells by x position
std::sort(cells.begin(), cells.end());
std::vector<cell_leg_properties> ret;
for(cell_to_leg C : cells){
// Dumb, quick and dirty best-fit legalization
bool found_location = false;
// Properties of the current best solution
int_t best_x=0;
int_t best_cost=0;
index_t best_row=0;
// Helper function
auto check_row_cost = [&](index_t r, cell_to_leg const cell, int_t additional_cost){
// Find where to put the cell in these rows
// Simple method: get a range where we can put the cell
assert(r + cell.nbr_rows <= nbr_rows);
assert(additional_cost >= 0);
// First position where we can put it
int_t cur_pos = *std::max_element(first_available_position.begin() + r, first_available_position.begin() + r + cell.nbr_rows);
int_t max_lim = x_max - cell.width;
int_t interval_lim;
do{
interval_lim = max_lim;
// For each row, test if obstacles prevent us from putting a cell here
// Until we find a correct position or are beyond the maximum position
for(index_t i = 0; i<cell.nbr_rows; ++i){
// Find the first obstacle which is after this position
// TODO: use lower/upper bound
auto it=obstacles[r+i].rbegin();
for(; it != obstacles[r+i].rend() && it->max_x <= cur_pos; ++it){
}
if(it != obstacles[r+i].rend()){ // There is an obstacle on the right
assert(it->min_x < it->max_x);
int_t cur_lim = it->min_x - cell.width; // Where the obstacles contrains us
interval_lim = std::min(cur_lim, interval_lim); // Constraint
if(cur_lim < cur_pos){ // If this particular obstacle constrained us so that it is not possible to make it here, we increment the position
cur_pos = std::max(it->max_x, cur_pos);
}
}
}
// Do it again until we find a solution
// TODO: continue until we can't find a better solution (currently sticks before the first obstacle if there is enough whitespace)
}while(interval_lim < cur_pos and interval_lim < max_lim and cur_pos < max_lim); // Not admissible and we encountered an obstacle and there is still hope
if(interval_lim >= cur_pos){ // An admissible solution is found (and if cell.x_pos is between cur_pos and interval_lim it is optimal)
int_t row_best_x = std::min(interval_lim, std::max(cur_pos, cell.x_pos));
int_t row_cost_x = std::abs((float)(row_best_x - cell.x_pos));
if(not found_location or row_cost_x + additional_cost < best_cost){
found_location = true;
best_cost = row_cost_x + additional_cost;
best_x = row_best_x;
best_row = r;
}
}
};
// The row where we would prefer the cell to go
if(C.nbr_rows > nbr_rows) throw std::runtime_error("Impossible to legalize a cell spanning more rows than are available\n");
index_t central_row = std::min( (index_t) std::max( (C.y_pos - y_orig) / row_height, 0), nbr_rows-C.nbr_rows);
// Try every possible row from the best one, until we can't improve the cost
for(index_t row_dist = 0;
(central_row + row_dist < nbr_rows or central_row >= row_dist)
and (not found_location or (int_t) row_dist * row_height * C.width < (int_t) row_height + best_cost);
++row_dist
){
if(central_row + row_dist < nbr_rows - C.nbr_rows){
int_t add_cost = C.width * std::abs((float)static_cast<int_t>(central_row + row_dist) * static_cast<int_t>(row_height) + y_orig - C.y_pos);
check_row_cost(central_row + row_dist, C, add_cost);
}
if(central_row >= row_dist){
int_t add_cost = C.width * std::abs((float)static_cast<int_t>(central_row - row_dist) * static_cast<int_t>(row_height) + y_orig - C.y_pos);
check_row_cost(central_row - row_dist, C, add_cost);
}
}
if(not found_location){ // We didn't find any whitespace to put the cell in
throw std::runtime_error("Didn't manage to pack a cell due to dumb algorithm\n");
}
else{
assert(best_x + C.width <= x_max and best_x >= x_min);
// Update the occupied rows
for(index_t r = best_row; r < best_row + C.nbr_rows; ++r){
// Include the obstacles
while(not obstacles[r].empty()
and obstacles[r].back().max_x <= best_x){
rows[r].push_back(obstacles[r].back().cell_ind);
obstacles[r].pop_back();
}
assert(obstacles[r].empty() or obstacles[r].back().min_x >= best_x + C.width);
rows[r].push_back(C.original_cell);
first_available_position[r] = best_x + C.width;
}
ret.push_back(cell_leg_properties(best_x, best_row, C.original_cell));
}
}
// Finally, push the remaining fixed cells
for(index_t r=0; r<nbr_rows; ++r){
while(not obstacles[r].empty()){
rows[r].push_back(obstacles[r].back().cell_ind);
obstacles[r].pop_back();
}
}
return ret;
}
// A better legalization function which is able to push already legalized cells
std::vector<cell_leg_properties> good_legalize(
std::vector<std::vector<fixed_cell_interval> > obstacles, std::vector<cell_to_leg> cells,
std::vector<std::vector<index_t> > & rows,
int_t x_min, int_t x_max, int_t y_orig,
int_t row_height, index_t nbr_rows
){
// Two possibilities:
// * Single OSRP (group of movable cells) at the current end of the row of standard cells
// * Multiple OSRPs, between each pair of obstacles
// -> allows pushing cells past obstacles
// -> tricky with multiple standard cell heights
// Therefore I chose single OSRP, which gets cleared and pushed to the final state whenever
// * we encounter a multiple-rows cell
// * a new standard cell gets past an obstacle
// The current group of standard cells on the right of the row
std::vector<OSRP_leg<int_t> > single_row_problems(nbr_rows);
for(index_t r=0; r<nbr_rows; ++r){
single_row_problems[r] = OSRP_leg<int_t>(x_min, obstacles[r].empty() ? x_max : obstacles[r].back().min_x);
}
rows.resize(nbr_rows);
// Sort the cells by x position
std::sort(cells.begin(), cells.end());
std::vector<cell_leg_properties> ret;
for(cell_to_leg C : cells){
// Dumb, quick and dirty best-fit legalization
bool found_location = false;
// Properties of the current best solution
int_t best_cost=0;
index_t best_row=0;
index_t obstacles_passed = 0;
// Helper function
auto check_row_cost = [&](index_t r, cell_to_leg const cell, int_t additional_cost){
// Find where to put the cell in these rows
// Check if we can put it in the current ranges and at what cost; if not or if the optimal position is beyond an obstacle, try after this obstacle too
assert(cell.nbr_rows > 0);
assert(r + cell.nbr_rows <= nbr_rows);
assert(additional_cost >= 0);
// Where can we put a standard cell if we allow to move the cells?
if(cell.nbr_rows == 1){
int_t cur_cost = 0;
// Can we simply add it to the single row problem?
bool found_here = single_row_problems[r].remaining_space() >= cell.width;
int_t loc_obstacles_passed = 0;
if(found_here){
// Check the cost of pushing it here with possible displacement
cur_cost = single_row_problems[r].get_cost(cell.task()); // Don't update the row
}
// Other positions where we can put it, without moving other cells this time
if(not found_here or cur_cost > 0){
index_t obstacles_to_throw = 0;
auto it = obstacles[r].rbegin();
while(it != obstacles[r].rend()){
++ obstacles_to_throw;
auto prev_it = it++;
int_t region_end = it != obstacles[r].rend() ? it->min_x : x_max;
if(region_end >= prev_it->max_x + cell.width){
int_t loc_x = std::min(region_end - cell.width, std::max(prev_it->max_x, cell.x_pos));
int_t loc_cost = cell.width * std::abs((float)(cell.x_pos - loc_x));
if(not found_here or cur_cost > loc_cost){
found_here = true;
cur_cost = loc_cost;
loc_obstacles_passed = obstacles_to_throw;
}
}
}
}
if(found_here and (not found_location or cur_cost + additional_cost < best_cost)){
found_location = true;
//std::cout << "Found with displacement cost " << cur_cost << " and total cost " << cur_cost + additional_cost << std::endl;
best_cost = cur_cost + additional_cost;
best_row = r;
obstacles_passed = loc_obstacles_passed;
if(loc_obstacles_passed > 0) assert(not obstacles[r].empty());
}
}
else{
// If it is a fixed cell, we use fixed locations
std::cerr << "cell.nbr_rows:" << cell.nbr_rows << std::endl;
throw std::runtime_error("I don't handle fucking macros (good_legalize)\n");
}
};
// The row where we would prefer the cell to go
if(C.nbr_rows > nbr_rows) throw std::runtime_error("Impossible to legalize a cell spanning more rows than are available\n");
index_t central_row = std::min( (index_t) std::max( (C.y_pos - y_orig) / row_height, 0), nbr_rows-C.nbr_rows);
// Try every possible row from the best one, until we can't improve the cost
for(index_t row_dist = 0;
(central_row + row_dist < nbr_rows or central_row >= row_dist)
and (not found_location or (int_t) row_dist * row_height * C.width < (int_t) row_height + best_cost);
++row_dist
){
if(central_row + row_dist < nbr_rows - C.nbr_rows){
int_t add_cost = C.width * std::abs((float)static_cast<int_t>(central_row + row_dist) * static_cast<int_t>(row_height) + y_orig - C.y_pos);
check_row_cost(central_row + row_dist, C, add_cost);
}
if(central_row >= row_dist){
int_t add_cost = C.width * std::abs((float)static_cast<int_t>(central_row - row_dist) * static_cast<int_t>(row_height) + y_orig - C.y_pos);
check_row_cost(central_row - row_dist, C, add_cost);
}
}
if(not found_location){ // We didn't find any whitespace to put the cell in
throw std::runtime_error("Didn't manage to pack a cell: leave more whitespace and avoid macros near the right side\n");
}
else{
//std::cout << "Cell " << C.original_cell << " of width " << C.width << " targetting row " << central_row << " and position " << C.x_pos << " put at row " << best_row << " with displacement " << best_cost / C.width << " with " << obstacles_passed << " obstacles passed" << std::endl;
// If the cell spans multiple rows, it becomes fixed
// In this case or if the cell goes after an obstacle, push everything before the cell to the fixed state
if(C.nbr_rows == 1){
if(obstacles_passed == 0){ // Ok; just update the old single row problem
single_row_problems[best_row].push(C.task()); // Push it to the row
}
else{
assert(obstacles_passed > 0);
// Empty the single row problem
for(auto p : single_row_problems[best_row].get_placement()){
rows[best_row].push_back(p.first);
ret.push_back(cell_leg_properties(p.second, best_row, p.first));
}
// Find where to put it
int_t region_begin = x_min;
for(index_t i=0; i<obstacles_passed; ++i){
assert(not obstacles[best_row].empty());
region_begin = obstacles[best_row].back().max_x;
rows[best_row].push_back(obstacles[best_row].back().cell_ind);
obstacles[best_row].pop_back();
}
int_t region_end = obstacles[best_row].empty() ? x_max : obstacles[best_row].back().min_x;
single_row_problems[best_row] = OSRP_leg<int_t>(region_begin, region_end);
assert(region_end - region_begin >= C.width);
single_row_problems[best_row].push(C.task()); // Push this only cell to the single row problem
}
}
else{
throw std::runtime_error("I don't handle fucking macros (here)\n");
}
}
}
for(index_t r=0; r<nbr_rows; ++r){
// Finally, push the remaining standard cells in the row
for(auto p : single_row_problems[r].get_placement()){
rows[r].push_back(p.first);
ret.push_back(cell_leg_properties(p.second, r, p.first));
}
// And the fixed cells
while(not obstacles[r].empty()){
rows[r].push_back(obstacles[r].back().cell_ind);
obstacles[r].pop_back();
}
}
rows.resize(nbr_rows);
return ret;
}
detailed_placement legalize(netlist const & circuit, placement_t const & pl, box<int_t> surface, int_t row_height){
if(row_height <= 0) throw std::runtime_error("The rows' height should be positive\n");
index_t nbr_rows = (surface.y_max - surface.y_min) / row_height;
// The position of the ith row is surface.y_min + i * row_height
std::vector<std::vector<fixed_cell_interval> > row_occupation(nbr_rows);
std::vector<cell_to_leg> cells;
placement_t new_placement = pl;
std::vector<index_t> placement_rows(circuit.cell_cnt());
std::vector<index_t> cell_heights(circuit.cell_cnt());
for(index_t i=0; i<circuit.cell_cnt(); ++i){
auto cur = circuit.get_cell(i);
// Assumes fixed if not both XMovable and YMovable
if( (cur.attributes & XMovable) != 0 && (cur.attributes & YMovable) != 0){
// Just truncate the position we target
point<int_t> target_pos = pl.positions_[i];
index_t cur_cell_rows = (cur.size.y + row_height -1) / row_height;
cells.push_back(cell_to_leg(target_pos.x, target_pos.y, i, cur.size.x, cur_cell_rows));
cell_heights[i] = cur_cell_rows;
}
else{
// In each row, we put the index of the fixed cell and the range that is already occupied
int_t low_x_pos = pl.positions_[i].x,
hgh_x_pos = pl.positions_[i].x + cur.size.x,
low_y_pos = pl.positions_[i].y,
hgh_y_pos = pl.positions_[i].y + cur.size.y;
new_placement.positions_[i] = point<int_t>(low_x_pos, low_y_pos);
if(hgh_y_pos <= surface.y_min or low_y_pos >= surface.y_max or hgh_x_pos <= surface.x_min or low_x_pos >= surface.x_max){
placement_rows[i] = null_ind;
cell_heights[i] = 0;
}
else{
assert(low_x_pos < hgh_x_pos and low_y_pos < hgh_y_pos);
int_t rnd_hgh_x_pos = std::min(surface.x_max, hgh_x_pos);
int_t rnd_hgh_y_pos = std::min(surface.y_max, hgh_y_pos);
int_t rnd_low_x_pos = std::max(surface.x_min, low_x_pos);
int_t rnd_low_y_pos = std::max(surface.y_min, low_y_pos);
index_t first_row = (rnd_low_y_pos - surface.y_min) / row_height;
index_t last_row = (index_t) (rnd_hgh_y_pos - surface.y_min + row_height - 1) / row_height; // Exclusive: if the cell spans the next row, i.e. pos % row_height >= 0, include it too
assert(last_row <= nbr_rows);
placement_rows[i] = first_row;
cell_heights[i] = last_row - first_row;
for(index_t r=first_row; r<last_row; ++r){
row_occupation[r].push_back(fixed_cell_interval(rnd_low_x_pos, rnd_hgh_x_pos, i));
}
}
}
}
for(std::vector<fixed_cell_interval> & L : row_occupation){
std::sort(L.begin(), L.end()); // Sorts from last to first, so that we may use pop_back()
// Doesn't collapse them yet, which may make for bigger complexities
for(index_t i=0; i+1<L.size(); ++i){
if(L[i].min_x < L[i+1].max_x) {
std::ostringstream message;
message << "Coloquinte::dp::legalize(): Sorry, I don't handle overlapping fixed cells yet ";
message << " i:" << i << " max_x: " << L[i].max_x << " > min_x:" << L[i+1].min_x << "\n";
throw std::runtime_error(message.str());
}
}
}
std::vector<std::vector<index_t> > cells_by_rows;
auto final_cells = good_legalize(row_occupation, cells, cells_by_rows,
surface.x_min, surface.x_max, surface.y_min,
row_height, nbr_rows
);
for(cell_leg_properties C : final_cells){
new_placement.positions_[C.ind] = point<int_t>(C.x_pos, static_cast<int_t>(C.row_pos) * row_height + surface.y_min);
placement_rows[C.ind] = C.row_pos;
}
return detailed_placement(
new_placement,
placement_rows,
cell_heights,
cells_by_rows,
surface.x_min, surface.x_max,
surface.y_min,
nbr_rows, row_height
);
}
} // namespace dp
} // namespace coloquinte

File diff suppressed because it is too large Load Diff

View File

@ -1,515 +0,0 @@
#include "coloquinte/optimization_subproblems.hxx"
#include <stdexcept>
namespace coloquinte{
std::vector<capacity_t> transport_1D(std::vector<t1D_elt> sources, std::vector<t1D_elt> sinks){
/* Description of the algorithm:
*
* For each cell, put it in its optimal region or the last region where a cell is if there is no space in it
* Push all changes in the derivative of the cost function to a priority queue; those changes occur
* when evicting the preceding cell from a region (most such changes are 0 and not considered, hence the complexity)
* when moving to a non-full region
* While the new cell overlaps with a new region, get the new slope (derivative) at this point
* and push all preceding cell until this region is freed or the slope becomes 0 (in which case the new region is now occupied)
*/
struct bound{
capacity_t pos;
int_t slope_diff;
bool operator<(bound const o) const{ return pos < o.pos; }
};
std::priority_queue<bound> bounds;
std::vector<capacity_t> constraining_pos;
std::vector<capacity_t> prev_cap(1, 0), prev_dem(1, 0);
for(auto const s : sinks){
prev_cap.push_back(s.second + prev_cap.back());
}
for(auto const s : sources){
prev_dem.push_back(s.second + prev_dem.back());
}
// The sinks have enough capacity to hold the whole demand
assert(prev_cap.back() >= prev_dem.back());
const capacity_t min_abs_pos = 0, max_abs_pos = prev_cap.back() - prev_dem.back();
assert(min_abs_pos <= max_abs_pos);
auto push_bound = [&](capacity_t p, int_t s){
assert(s >= 0);
if(p > min_abs_pos){
bound B;
B.pos = p;
B.slope_diff = s;
bounds.push(B);
}
};
// Distance to the right - distance to the left
auto get_slope = [&](index_t src, index_t boundary){
assert(boundary+1 < sinks.size());
assert(src < sources.size());
return std::abs((float)(sources[src].first - sinks[boundary+1].first)) - std::abs((float)(sources[src].first - sinks[boundary].first));
};
capacity_t cur_abs_pos = min_abs_pos;
index_t opt_r=0, next_r=0, first_free_r=0;
for(index_t i=0; i<sources.size(); ++i){
// Update the optimal region
while(opt_r+1 < sinks.size() and (sinks[opt_r].first + sinks[opt_r+1].first)/2 < sources[i].first){
++opt_r;
}
// Update the next region
index_t prev_next_r = next_r;
while(next_r < sinks.size() and sinks[next_r].first <= sources[i].first){
++next_r;
}
index_t dest_reg = std::max(first_free_r, opt_r);
assert(dest_reg < sinks.size());
if(i>0){
// Push bounds due to changing the source crossing the boundary j/j+1
// Linear amortized complexity accross all sources (next_r grows)
// get_slope(i-1, j) - get_slope(i, j) == 0 if j >= next_r
// get_slope(i-1, j) - get_slope(i, j) == 0 if j < prev_next_r-1
for(index_t j=std::max(prev_next_r,1u)-1; j<std::min(first_free_r, next_r+1); ++j){
assert(get_slope(i,j) <= get_slope(i-1,j));
push_bound(prev_cap[j+1] - prev_dem[i], get_slope(i-1, j) - get_slope(i,j));
}
}
// Add the bounds due to crossing the boundaries alone
for(index_t j=first_free_r; j<opt_r; ++j){
assert(get_slope(i,j) <= 0);
push_bound(prev_cap[j+1] - prev_dem[i], -get_slope(i, j));
}
first_free_r = std::max(first_free_r, opt_r);
capacity_t this_abs_pos = std::max(cur_abs_pos, prev_cap[first_free_r] - prev_dem[i]); // Just after the previous cell or at the beginning of the destination region
while(first_free_r+1 < sinks.size() and this_abs_pos > std::max(prev_cap[first_free_r+1] - prev_dem[i+1], min_abs_pos)){ // Absolute position that wouldn't make the cell fit in the region, and we are not in the last region yet
capacity_t end_pos = std::max(prev_cap[first_free_r+1] - prev_dem[i+1], min_abs_pos);
int_t add_slope = get_slope(i, first_free_r);
int_t slope = add_slope;
while(not bounds.empty() and slope >= 0 and bounds.top().pos > end_pos){
this_abs_pos = bounds.top().pos;
slope -= bounds.top().slope_diff;
bounds.pop();
}
if(slope >= 0){ // We still push: the cell completely escapes the region
this_abs_pos = end_pos;
push_bound(end_pos, add_slope-slope);
}
else{ // Ok, absorbed the whole slope: push what remains and we still occupy the next region
push_bound(this_abs_pos, -slope);
++first_free_r;
}
}
cur_abs_pos = this_abs_pos;
constraining_pos.push_back(this_abs_pos);
}
assert(constraining_pos.size() == sources.size());
if(not constraining_pos.empty()){
// Calculate the final constraining_pos
constraining_pos.back() = std::min(max_abs_pos, constraining_pos.back());
}
std::partial_sum(constraining_pos.rbegin(), constraining_pos.rend(), constraining_pos.rbegin(), [](capacity_t a, capacity_t b)->capacity_t{ return std::min(a, b); });
for(index_t i=0; i<constraining_pos.size(); ++i){
constraining_pos[i] += prev_dem[i];
}
return constraining_pos;
}
namespace{ // Anonymous namespace to hide the transportation structures
class current_allocation{
static const index_t null_ind;
// Internal data structures
// Priority queue element to determine the source to be used between regions
struct movable_source{
index_t source;
float_t cost;
bool operator<(movable_source const o) const{
return cost > o.cost // Sorted by cost
|| (cost == o.cost && source < o.source); // And by index to limit the number of fractional elements between two regions
}
movable_source(index_t s, float_t c) : source(s), cost(c) {}
};
// Member data
// The current state
std::vector<std::vector<capacity_t> > sr_allocations; // For each region, for each source, the capacity allocated by the region
std::vector<std::vector<float_t> > sr_costs; // The costs from a region to a source
std::vector<capacity_t> s_demands; // The demands of the sources
std::vector<capacity_t> r_capacities; // The remaining capacities of the regions
// Shortest path data
std::vector<float_t> r_costs; // The costs of allocating to a region
std::vector<index_t> r_parents; // The parents of the regions i.e. the regions where we push sources first (or null_ind)
std::vector<index_t> r_sources; // The source involved in these edges
std::vector<capacity_t> arc_capacities; // The capacities of the edges to the parents, or of the region if no parent
// Best edges data
std::vector<std::vector<std::priority_queue<movable_source> > > best_interregions_costs; // What is the best source to move to go from region k1 to region k2?
index_t dijkstra_cnt;
// Helper functions
// Number of regions
index_t region_cnt() const{
assert(sr_costs.size() == sr_allocations.size());
return sr_costs.size();
}
// Update the edge between two regions
void update_edge(index_t r1, index_t r2);
// Add a source to all heaps of a region; returns if we need to update a path
bool add_source_to_heaps(index_t r, index_t source);
// Initialize the heaps of a region
void create_heaps(index_t reg);
// Run the shortest path algorithm to update the cost of each region
void dijkstra_update();
// Update the edge and returns if we need to rerun Dijkstra
bool push_edge(index_t reg, capacity_t flow);
// Updates a full path when pushing an element; returns if we need to rerun Dijkstra
bool push_path(index_t pushed_reg, capacity_t demanded, capacity_t & flow);
public:
// Add a new source to the transportation problem; should be done in decreasing order of demand to keep low complexity
void add_source(index_t elt_ind);
current_allocation(std::vector<capacity_t> caps, std::vector<capacity_t> demands, std::vector<std::vector<float_t> > costs)
:
sr_allocations(caps.size()),
sr_costs(costs),
s_demands(demands),
r_capacities(caps),
r_costs(caps.size(), 0.0),
r_parents(caps.size(), null_ind),
r_sources(caps.size(), null_ind),
arc_capacities(caps),
best_interregions_costs(caps.size(), std::vector<std::priority_queue<movable_source> >(caps.size())),
dijkstra_cnt(0)
{
assert(caps.size() > 0);
assert(costs.size() == caps.size());
dijkstra_update();
}
std::vector<std::vector<capacity_t> > get_allocations() const{ return sr_allocations; }
index_t get_iterations_cnt() const { return dijkstra_cnt; }
};
const index_t current_allocation::null_ind = std::numeric_limits<index_t>::max();
void current_allocation::update_edge(index_t r1, index_t r2){
while(not best_interregions_costs[r1][r2].empty() and sr_allocations[r1][best_interregions_costs[r1][r2].top().source] == 0){
best_interregions_costs[r1][r2].pop();
}
if(not best_interregions_costs[r1][r2].empty()){
// There is an edge
movable_source cur = best_interregions_costs[r1][r2].top();
float_t new_cost = r_costs[r2] + cur.cost;
if(new_cost < r_costs[r1]){
r_costs[r1] = cur.cost;
r_sources[r1] = cur.source;
r_parents[r1] = r2;
arc_capacities[r1] = sr_allocations[r1][cur.source];
}
}
}
bool current_allocation::add_source_to_heaps(index_t r, index_t source){
bool need_rerun = false;
for(index_t i=0; i<region_cnt(); ++i){
if(i == r) continue;
best_interregions_costs[r][i].push(
movable_source(source,
sr_costs[i][source] - sr_costs[r][source]
)
);
while(sr_allocations[r][best_interregions_costs[r][i].top().source] == 0){
best_interregions_costs[r][i].pop();
}
need_rerun = (best_interregions_costs[r][i].top().source == source) or need_rerun;
}
return need_rerun;
}
void current_allocation::create_heaps(index_t reg){
// Get all relevant elements
std::vector<std::vector<movable_source> > interregion_costs(region_cnt());
for(index_t i=0; i<sr_allocations[reg].size(); ++i){
if(sr_allocations[reg][i] > 0){
for(index_t oreg=0; oreg<region_cnt(); ++oreg){
if(oreg == reg) continue;
interregion_costs[oreg].push_back(
movable_source(
i,
sr_costs[oreg][i] - sr_costs[reg][i]
)
);
}
}
}
// Create the heaps
for(index_t oreg=0; oreg<region_cnt(); ++oreg){
best_interregions_costs[reg][oreg] = std::priority_queue<movable_source>(interregion_costs[oreg].begin(), interregion_costs[oreg].end());
}
}
// Returns if the path has been modified so that we would need to rerun Dijkstra
bool current_allocation::push_edge(index_t reg, capacity_t flow){
index_t cur_source = r_sources[reg];
// Does this edge allocates a new source in the destination region? If yes, update the corresponding heaps
bool already_present = sr_allocations[r_parents[reg]][cur_source] > 0;
// Deallocating from the first region is handled by the get_edge function: just substract the flow
sr_allocations[ reg ][cur_source] -= flow;
sr_allocations[r_parents[reg]][cur_source] += flow;
assert(sr_allocations[reg][cur_source] >= 0); // The source to be pushed was indeed present in the region
assert(r_capacities[reg] == 0); // The region is full, which explains why we need to push
assert(flow <= arc_capacities[reg]); // The flow is not bigger than what can be sent
arc_capacities[reg] = sr_allocations[reg][cur_source]; // Just update the capacity if it turns out that we don't need to run Dijkstra
if(arc_capacities[reg] == 0){
// The source may have been deleted from a region: rerun Dijkstra at the end
return true;
}
else if(not already_present and r_capacities[r_parents[reg]] == 0){
// A new source is allocated to a full region: rerun Dijkstra at the end if it changed the heap's top
return add_source_to_heaps(r_parents[reg], cur_source);
}
else{
// The edge is still present with the same cost and non-zero updated capacity
// The path still exists: no need to rerun Dijkstra yet
return false;
}
}
void current_allocation::dijkstra_update(){
// Simple case of the regions with remaining capacity
std::vector<int> visited(region_cnt(), 0);
index_t visited_cnt = 0;
for(index_t i=0; i<region_cnt(); ++i){
r_sources[i] = null_ind;
r_parents[i] = null_ind;
if(r_capacities[i] > 0){
r_costs[i] = 0.0;
arc_capacities[i] = r_capacities[i];
visited[i] = 1;
++visited_cnt;
}
else{
r_costs[i] = std::numeric_limits<float_t>::infinity();
arc_capacities[i] = 0;
}
}
// if(visited_cnt <= 0) throw std::runtime_error("Capacity problem: no region has been marked as reachable\n");
if(visited_cnt == region_cnt()){ return; }
// Get the costs for every non-visited region
for(index_t i=0; i<region_cnt(); ++i) if(visited[i] == 0){ // For every region that is not visited yet
for(index_t j=0; j<region_cnt(); ++j) if(visited[j] == 1){ // For every already visited region
// Get the best interregion cost
update_edge(i,j);
}
}
while(visited_cnt < region_cnt()){
// Find the region with the lowest cost to visit; mark it visited
index_t best_reg = null_ind;
float_t best_cost = std::numeric_limits<float_t>::infinity();
for(index_t i=0; i<region_cnt(); ++i) if(visited[i] == 0){ // For every region that is not visited yet
if(r_costs[i] < best_cost){
best_cost = r_costs[i];
best_reg = i;
}
}
if(best_reg == null_ind) break; // Some regions are unreachable, typically because they have zero capacity at the beginning
visited[best_reg] = 1;
++visited_cnt;
// Update the cost for every unvisited region
for(index_t i=0; i<region_cnt(); ++i) if(visited[i] == 0){ // For every region that is not visited yet
update_edge(i, best_reg);
}
}
}
bool current_allocation::push_path(index_t pushed_reg, capacity_t demanded, capacity_t & flow){
// Get the final flow sent, which is smaller than the capacities on the path
flow = demanded;
for(index_t reg = pushed_reg; reg != null_ind; reg = r_parents[reg]){
flow = std::min(flow, arc_capacities[reg]);
}
bool rerun_dijkstra = false;
// Update the path between the regions
index_t reg = pushed_reg;
for(; r_parents[reg] != null_ind; reg = r_parents[reg]){
assert(r_capacities[reg] == 0);
rerun_dijkstra = push_edge(reg, flow) or rerun_dijkstra;
}
assert(r_capacities[reg] > 0);
assert(arc_capacities[reg] == r_capacities[reg]);
assert(r_capacities[reg] >= flow);
// Update the capacities at the end
r_capacities[reg] -= flow;
arc_capacities[reg] -= flow;
// The last region on the path is the one that satisfies the demand
if(r_capacities[reg] == 0){ // If we just consumed the available capacity, it becomes useful to move sources off this region: build the heap
create_heaps(reg);
rerun_dijkstra = true;
}
assert(flow > 0);
// If an edge changes cost or a region is full,
// we need to update the costs, parents, sources and arc_capacities using a Dijkstra
// but later
return rerun_dijkstra;
}
void current_allocation::add_source(index_t elt_ind){ //capacity_t demand, std::vector<float_t> const & costs){
for(index_t i=0; i<region_cnt(); ++i){
sr_allocations[i].push_back(0);
}
bool need_rerun = false;
capacity_t demand = s_demands[elt_ind];
while(demand > 0){
// In case we modified the structures earlier
if(need_rerun){
dijkstra_update();
need_rerun = false;
}
++ dijkstra_cnt;
index_t best_reg = null_ind;
float_t best_cost = std::numeric_limits<float_t>::infinity();
for(index_t reg=0; reg<region_cnt(); ++reg){
// Find the region which gets the source
if(r_costs[reg] + sr_costs[reg][elt_ind] < best_cost){
best_reg = reg;
best_cost = r_costs[reg] + sr_costs[reg][elt_ind];
}
}
if(best_reg == null_ind){ throw std::runtime_error("No reachable region found\n"); }
capacity_t flow = 0;
// Tells us whether we need to update the data structures
need_rerun = push_path(best_reg, demand, flow);
demand -= flow;
// Lazily store the change
sr_allocations[best_reg][elt_ind] += flow;
}
// Set the source's demand
for(index_t i=0; i<region_cnt(); ++i){
if(r_capacities[i] == 0 and sr_allocations[i][elt_ind] > 0){
need_rerun = add_source_to_heaps(i, elt_ind) or need_rerun;
}
}
// We leave a clean set with correct paths for the next iteration
if(need_rerun)
dijkstra_update();
}
} // End anonymous namespace
std::vector<std::vector<capacity_t> > transport_generic(std::vector<capacity_t> const & capacities, std::vector<capacity_t> const & demands, std::vector<std::vector<float_t> > const & costs){
current_allocation transporter(capacities, demands, costs);
for(index_t i=0; i<demands.size(); ++i){
transporter.add_source(i);
}
return transporter.get_allocations();
}
bool place_convex_single_row(std::vector<int_t> const & widths, std::vector<std::pair<int_t, int_t> > const & ranges, std::vector<cell_bound> bounds, std::vector<int_t> const & const_slopes, std::vector<int_t> & positions){
std::sort(bounds.begin(), bounds.end());
struct bound{
int_t abs_pos;
int_t slope_diff;
bool operator<(bound const o) const{ return abs_pos < o.abs_pos; }
bound(int_t p, int_t s) : abs_pos(p), slope_diff(s) {}
};
std::priority_queue<bound> prio_queue;
std::vector<int_t> prev_widths(widths.size()+1, 0);
std::partial_sum(widths.begin(), widths.end(), std::next(prev_widths.begin()));
std::vector<int_t> constraining_pos(widths.size());
int_t lower_lim = std::numeric_limits<int_t>::min();
for(index_t i=0, j=0; i<widths.size(); ++i){
int_t old_width = prev_widths[i];
int_t new_width = prev_widths[i+1];
lower_lim = std::max(ranges[i].first - old_width, lower_lim);
int_t upper_lim = ranges[i].second - new_width;
for(; j<bounds.size() and bounds[j].c == i; ++j){
prio_queue.push(bound(bounds[j].pos - old_width, bounds[j].slope));
}
if(upper_lim < lower_lim){ // Infeasible
return false;
}
int_t cur_slope = const_slopes[i];
int_t cur_pos = upper_lim;
while(not prio_queue.empty() and (cur_slope > 0 or prio_queue.top().abs_pos > upper_lim)){
cur_slope -= prio_queue.top().slope_diff;
cur_pos = prio_queue.top().abs_pos;
prio_queue.pop();
}
int_t final_abs_pos = std::max(std::min(cur_pos, upper_lim), lower_lim);
constraining_pos[i] = final_abs_pos;
if(cur_slope < 0){
prio_queue.push(bound(final_abs_pos, -cur_slope));
}
}
positions.resize(constraining_pos.size());
std::partial_sum(constraining_pos.rbegin(), constraining_pos.rend(), positions.rbegin(), [](int_t a, int_t b)->int_t{ return std::min(a,b); });
for(index_t i=0; i<positions.size(); ++i){
positions[i] += prev_widths[i];
}
return true;
}
bool place_noncvx_single_row(std::vector<int_t> const & widths, std::vector<std::pair<int_t, int_t> > const & ranges, std::vector<int> const & flippables, std::vector<cell_bound> bounds, std::vector<int_t> const & const_slopes, std::vector<int_t> & positions, std::vector<int> & flippings){
flippings = std::vector<int>(positions.size(), 0);
return place_convex_single_row(widths, ranges, bounds, const_slopes, positions);
}
} // Namespace coloquinte

View File

@ -1,166 +0,0 @@
#include "coloquinte/circuit_helper.hxx"
#include <stack>
#include <functional>
#include <algorithm>
namespace coloquinte{
namespace gp{
namespace{
//index_t const null_ind = std::numeric_limits<index_t>::max();
inline void opt_orient(netlist const & circuit, placement_t & pl, std::function<int_t (point<int_t>)> i_coor, std::function<bool & (point<bool> &)> b_coor,mask_t FLIPPABLE){
std::stack<index_t> opt_cells;
for(index_t cell_ind = 0; cell_ind < circuit.cell_cnt(); ++cell_ind){
if( (circuit.get_cell(cell_ind).attributes & FLIPPABLE) != 0)
opt_cells.push(cell_ind);
}
while(not opt_cells.empty()){
index_t cell_ind = opt_cells.top(); opt_cells.pop();
assert((circuit.get_cell(cell_ind).attributes & FLIPPABLE) != 0);
// What is the current orientation?
bool old_orientation = b_coor(pl.orientations_[cell_ind]);
int_t pos = i_coor(pl.positions_[cell_ind]);
int_t size = i_coor(circuit.get_cell(cell_ind).size);
// Check both orientations of the cell
std::vector<index_t> involved_nets;
for(netlist::pin_t p : circuit.get_cell(cell_ind)){
involved_nets.push_back(p.net_ind);
}
// Deal with cells with multiple pins in one net (uniquify)
std::sort(involved_nets.begin(), involved_nets.end());
involved_nets.resize(std::distance(involved_nets.begin(), std::unique(involved_nets.begin(), involved_nets.end())));
std::int64_t p_cost = 0, n_cost = 0;
std::vector<index_t> extreme_elements;
for(index_t n : involved_nets){
std::vector<pin_1D> other_pins;
std::vector<int_t> offsets;
for(auto p : circuit.get_net(n)){
if(p.cell_ind != cell_ind){
other_pins.push_back(pin_1D(
p.cell_ind,
i_coor(pl.positions_[p.cell_ind])
+ (b_coor(pl.orientations_[p.cell_ind]) ? i_coor(p.offset) : i_coor(circuit.get_cell(p.cell_ind).size) - i_coor(p.offset)),
0, // Don't care about the offset
(circuit.get_cell(p.cell_ind).attributes & FLIPPABLE) != 0)
);
}
else{
offsets.push_back(i_coor(p.offset));
}
}
assert(offsets.size() > 0);
if(other_pins.size() > 0){ // Else the orientation of the cell doesn't change anything
auto minmaxC = std::minmax_element(other_pins.begin(), other_pins.end());
auto minmaxO = std::minmax_element(offsets.begin(), offsets.end());
p_cost += std::max(pos + *minmaxO.second, minmaxC.second->pos) - std::min(pos + *minmaxO.first, minmaxC.first->pos);
n_cost += std::max(pos + size - *minmaxO.first, minmaxC.second->pos) - std::min(pos + size - *minmaxO.second, minmaxC.first->pos);
int_t min_pin_pos = std::min(pos + *minmaxO.second, pos + size - *minmaxO.first),
max_pin_pos = std::max(pos + *minmaxO.second, pos + size - *minmaxO.first);
// Do the extreme elements change between the two positions?
if(minmaxC.second->movable
and (minmaxC.second->pos < max_pin_pos)
and (minmaxC.second->pos > min_pin_pos) ){
extreme_elements.push_back(minmaxC.second->cell_ind);
}
if(minmaxC.first->movable
and (minmaxC.first->pos < max_pin_pos)
and (minmaxC.first->pos > min_pin_pos) ){
extreme_elements.push_back(minmaxC.first->cell_ind);
}
}
}
if(p_cost < n_cost)
b_coor(pl.orientations_[cell_ind]) = true;
if(p_cost > n_cost)
b_coor(pl.orientations_[cell_ind]) = false;
// If we changed the orientation, check the extreme pins which changed and try their cells again
if(b_coor(pl.orientations_[cell_ind]) != old_orientation){
std::sort(extreme_elements.begin(), extreme_elements.end());
extreme_elements.resize(std::distance(extreme_elements.begin(), std::unique(extreme_elements.begin(), extreme_elements.end())));
for(index_t extreme_cell : extreme_elements){
if( (circuit.get_cell(extreme_cell).attributes & FLIPPABLE) != 0)
opt_cells.push(extreme_cell);
}
}
}
}
/*
inline void spread_orient(netlist const & circuit, placement_t & pl, std::function<float_t & (point<float_t> &)> coor, mask_t FLIPPABLE){
std::vector<float_t> weights(circuit.cell_cnt(), 0.0);
for(index_t n=0; n<circuit.net_cnt(); ++n){
float_t min_pos=INF, max_pos=-INF;
float_t min_offs=INF, max_offs=-INF;
index_t min_ind=null_ind, max_ind=null_ind;
for(netlist::pin_t p : circuit.get_net(n)){
if( (circuit.get_cell(p.cell_ind).attributes & FLIPPABLE) != 0){
float_t pos = coor(pl.positions_[p.cell_ind]);
if(pos < min_pos){
min_pos = pos;
min_ind = p.cell_ind;
min_offs = coor(p.offset);
}
if(pos > max_pos){
max_pos = pos;
max_ind = p.cell_ind;
max_offs = coor(p.offset);
}
}
else{
float_t pos = coor(pl.positions_[p.cell_ind]) + coor(pl.orientations_[p.cell_ind]) * coor(p.offset);
if(pos < min_pos){
min_pos = pos;
min_ind = null_ind;
}
if(pos > max_pos){
max_pos = pos;
max_ind = null_ind;
}
}
}
float_t net_weight = circuit.get_net(n).weight;
if(min_ind != null_ind) weights[min_ind] += net_weight * min_offs;
if(max_ind != null_ind) weights[max_ind] -= net_weight * max_offs;
}
for(index_t c=0; c<circuit.cell_cnt(); ++c){
coor(pl.orientations_[c]) = (weights[c] >= 0.0) ? 1.0 : -1.0;
}
}
*/
} // End anonymous namespace
void optimize_x_orientations(netlist const & circuit, placement_t & pl){
opt_orient(circuit, pl, [](point<int_t> p) -> int_t { return p.x; }, [](point<bool> & p) -> bool & { return p.x; }, XFlippable);
}
void optimize_y_orientations(netlist const & circuit, placement_t & pl){
opt_orient(circuit, pl, [](point<int_t> p) -> int_t { return p.y; }, [](point<bool> & p) -> bool & { return p.y; }, YFlippable);
}
// Iteratively optimize feasible orientations; performs only one pass
void optimize_exact_orientations(netlist const & circuit, placement_t & pl){
optimize_x_orientations(circuit, pl);
optimize_y_orientations(circuit, pl);
}
/*
void spread_orientations(netlist const & circuit, placement_t & pl){
spread_orient(circuit, pl, [](point<float_t> & p) -> float_t & { return p.x; }, XFlippable);
spread_orient(circuit, pl, [](point<float_t> & p) -> float_t & { return p.y; }, YFlippable);
}
*/
} // namespace gp
} // namespace coloquinte

View File

@ -1,260 +0,0 @@
#include "coloquinte/piecewise_linear.hxx"
#include <cassert>
#include <cmath>
namespace coloquinte{
namespace{
struct pl_edge{
p_v f, s;
static void push_intersections(pl_edge a, pl_edge b, piecewise_linear_function & lf){
// Strict, because it makes everything easier
//assert(a.f.first < b.s.first and a.s.first > b.f.first);
//assert(a.f.first < a.s.first and b.f.first < b.s.first);
assert(a.f.first <= b.s.first and a.s.first >= b.f.first);
assert(a.f.first <= a.s.first and b.f.first <= b.s.first);
// ra = (a.s.second - a.f.second) / (a.s.first - a.f.first)
// xintersect = (yb - ya - xb * rb + xa * ra) / (ra - rb)
double ra = static_cast<double>(a.s.second - a.f.second) / (a.s.first - a.f.first);
double rb = static_cast<double>(b.s.second - b.f.second) / (b.s.first - b.f.first);
double xintersect = (b.f.second - a.f.second - rb * b.f.first + ra * a.f.first) / (ra - rb);
if( not xintersect ) return;
int_t pos = xintersect;
if( std::ceil(xintersect) == std::floor(xintersect) ){ // Exact integer intersection
if(pos > std::max(a.f.first, b.f.first) and pos < std::min(a.s.first, b.s.first) ){ // Necessarily smaller than s.first due to the previous condition
lf.point_values.push_back(p_v(pos, a.value_at(pos)));
}
}
else{ // Non exact intersection: create two integers since I don't want to mess with floating point
int_t pos1 = pos;
int_t pos2 = pos + 1;
// Value_at is only an approximation, but it shouldn't be too bad
if(pos1 > std::max(a.f.first, b.f.first) and pos1 < std::min(a.s.first, b.s.first))
lf.point_values.push_back(p_v(pos1, std::min(a.value_at(pos1), b.value_at(pos1))));
if(pos2 > std::max(a.f.first, b.f.first) and pos2 < std::min(a.s.first, b.s.first))
lf.point_values.push_back(p_v(pos2, std::min(a.value_at(pos2), b.value_at(pos2))));
}
}
// Lower-rounded value
int_t value_at(int_t pos) const{
assert(pos >= f.first and pos <= s.first and s.first > f.first);
return (static_cast<std::int64_t>(f.second) * (s.first - pos) + static_cast<std::int64_t>(s.second) * (pos - f.first)) / (s.first - f.first);
}
// Lower-rounded value
int_t pos_at(int_t val) const{
assert(val <= std::max(f.second, s.second) and val >= std::min(f.second, s.second));
assert(f.second != s.second);
return (static_cast<std::int64_t>(f.first) * (s.second - val) + static_cast<std::int64_t>(s.first) * (val - f.second)) / (s.second - f.second);
}
bool above(p_v const o) const{
int_t pos = o.first;
assert(pos > f.first and pos < s.first);
return (static_cast<std::int64_t>(f.second) * (s.first - pos) + static_cast<std::int64_t>(s.second) * (pos - f.first)) > o.second * (s.first - f.first);
}
pl_edge(p_v a, p_v b) : f(a), s(b) {}
};
} // End anonymous namespace
void piecewise_linear_function::add_monotone(int_t slope, int_t offset){
for(auto & V : point_values){
// Offset taken into account here, multiplied with the slope
V.second += slope * (V.first - point_values.front().first - offset);
}
}
void piecewise_linear_function::add_bislope(int_t s_l, int_t s_r, int_t pos){
//assert(pos <= point_values.back().first);
//assert(pos >= point_values.front().first);
/*
if(pos >= point_values.back().first){
add_monotone(s_l, pos - point_values.front().first);
}
else if(pos <= point_values.front().first){
add_monotone(s_r, pos - point_values.front().first);
}
else{
auto it = point_values.begin();
while(it->first < pos){
it->second += s_l * (it->first - pos);
++it;
assert(it != point_values.end());
}
if(it->first != pos){
point_values.insert(it, p_v(pos, pl_edge(*std::prev(it), *it).value_at(pos)));
}
for(auto & V : point_values){
if(V.first > pos)
V.second += s_r * (V.first - pos);
}
}
*/
auto it = std::lower_bound(point_values.begin(), point_values.end(), pos, [](p_v o, int_t v){ return o.first < v; });
if(it != point_values.end() and it->first != pos and it != point_values.begin()){
assert(it->first > pos);
point_values.insert(it, p_v(pos, pl_edge(*std::prev(it), *it).value_at(pos)));
}
for(auto & V : point_values){
if(V.first > pos)
V.second += s_r * (V.first - pos);
if(V.first < pos)
V.second += s_l * (V.first - pos);
}
}
piecewise_linear_function::piecewise_linear_function(int_t min_def, int_t max_def){
point_values.push_back(p_v(min_def, 0));
point_values.push_back(p_v(max_def, 0));
}
piecewise_linear_function piecewise_linear_function::previous_min() const{
piecewise_linear_function ret;
assert(not point_values.empty());
auto it = point_values.begin();
ret.point_values.push_back(*it);
++it;
// Use the previous minimum to detect when we find something smaller
for(; it != point_values.end(); ++it){
int_t cur_min = ret.point_values.back().second;
assert(it->first >= ret.point_values.back().first);
if(it->second < cur_min){
if(std::prev(it)->first != ret.point_values.back().first){ // May be equal, in which case we don't need to push anything new
int_t pos = pl_edge(*std::prev(it), *it).pos_at(cur_min);
if(pos != ret.point_values.back().first and pos != it->first){
ret.point_values.push_back(p_v(pos, cur_min));
}
}
ret.point_values.push_back(*it);
}
}
return ret;
}
piecewise_linear_function piecewise_linear_function::previous_min_of_sum(piecewise_linear_function const & a, int_t shift) const{
piecewise_linear_function ret;
// Go to the correct definition
auto b_begin = point_values.begin(), a_begin = a.point_values.begin();
auto b_it = b_begin, a_it = a_begin;
auto b_end = point_values.end(), a_end = a.point_values.end();
while(a_it != a_end){
if(b_it == b_end or a_it->first < b_it->first+shift){ // Ok, create an edge and calculate the value
if(b_it != b_begin){
int_t value;
if(b_it != b_end){
pl_edge b_edge(*std::prev(b_it), *b_it);
value = b_edge.value_at(a_it->first-shift);
}
else{
value = point_values.back().second;
}
ret.point_values.push_back(p_v(a_it->first, a_it->second + value));
}
++a_it;
}
else if(a_it->first > b_it->first+shift){
if(a_it != a_begin){
pl_edge a_edge(*std::prev(a_it), *a_it);
int_t value = a_edge.value_at(b_it->first+shift);
ret.point_values.push_back(p_v(b_it->first+shift, b_it->second + value));
}
++b_it;
}
else{ // if(a_it->first == b_it->first+shift){
ret.point_values.push_back(p_v(a_it->first, a_it->second + b_it->second));
++a_it;
++b_it;
}
}
return ret.previous_min();
}
int_t piecewise_linear_function::last_before(int_t pos) const{
auto it = point_values.rbegin();
while(it != point_values.rend()){
if(it->first <= pos){
if(it != point_values.rbegin() and std::prev(it)->first > pos){ // On a negative slope
return pos;
}
else{
return it->first; // First point or not mapped to a negative slope in the original function
}
}
++it;
}
assert(false); // We should have found it if the bound was correct
return -1;
}
int_t piecewise_linear_function::value_at(int_t pos) const{
// First position bigger or equal than pos
auto it = std::lower_bound(point_values.begin(), point_values.end(), pos, [](p_v o, int_t v){ return o.first < v; });
if(pos != it->first){
assert(it != point_values.begin());
return pl_edge(*std::prev(it), *it).value_at(pos);
}
else{
return it->second;
}
}
piecewise_linear_function piecewise_linear_function::piecewise_linear_function::minimum(piecewise_linear_function const & a, piecewise_linear_function const & b){
assert(a.point_values.front().first == b.point_values.front().first);
assert(a.point_values.back().first == b.point_values.back().first);
piecewise_linear_function ret;
auto a_it = a.point_values.begin(), b_it = b.point_values.begin();
auto a_end = a.point_values.end(), b_end = b.point_values.end();
ret.point_values.push_back(p_v(a_it->first, std::min(a_it->second, b_it->second)));
assert(std::next(a_it) != a_end and std::next(b_it) != b_end);
while(std::next(a_it) != a_end and std::next(b_it) != b_end){
pl_edge a_edge(*a_it, *std::next(a_it)), b_edge(*b_it, *std::next(b_it));
// Three cases: one of them always below, or both intersect
// Both intersect: we push the values when intersecting
pl_edge::push_intersections(a_edge, b_edge, ret);
// In any case, we push the value of the one below if it finishes, and increment the iterator
if(a_edge.s.first < b_edge.s.first){
++a_it;
if(b_edge.above(a_edge.s)){ // We push a_edge.s
ret.point_values.push_back(a_edge.s);
}
}
else if(a_edge.s.first > b_edge.s.first){
++b_it;
if(a_edge.above(b_edge.s)){ // We push a_edge.s
ret.point_values.push_back(b_edge.s);
}
}
else{
ret.point_values.push_back(p_v(a_edge.s.first, std::min(a_edge.s.second, b_edge.s.second)));
++a_it;
++b_it;
}
}
return ret;
}
} // End namespace coloquinte

File diff suppressed because it is too large Load Diff

View File

@ -1,599 +0,0 @@
#include "coloquinte/detailed.hxx"
#include "coloquinte/circuit_helper.hxx"
#include "coloquinte/optimization_subproblems.hxx"
#include "coloquinte/union_find.hxx"
#include "coloquinte/piecewise_linear.hxx"
#include <cassert>
#include <iostream>
namespace coloquinte{
namespace dp{
namespace{
struct minmax{
int_t min, max;
minmax(){}
minmax(int_t f, int_t s) : min(f), max(s){}
void merge(minmax const o){
min = std::min(min, o.min);
max = std::max(max, o.max);
}
void merge(int_t const o){
merge(minmax(o, o));
}
};
struct order_gettr{
index_t cell_ind, seq_order;
bool operator<(order_gettr const o) const{ return cell_ind < o.cell_ind; }
bool operator<(index_t const o) const{ return cell_ind < o; }
order_gettr(index_t c, index_t i) : cell_ind(c), seq_order(i) {}
};
std::vector<order_gettr> get_sorted_ordered_cells(std::vector<index_t> const & cells){
std::vector<order_gettr> ret;
for(index_t i=0; i<cells.size(); ++i){
ret.push_back(order_gettr(cells[i],i));
}
std::sort(ret.begin(), ret.end());
return ret;
}
std::vector<index_t> get_unique_nets(netlist const & circuit, std::vector<index_t> const & cells){
std::vector<index_t> involved_nets;
for(index_t c : cells){
for(netlist::pin_t p : circuit.get_cell(c)){
involved_nets.push_back(p.net_ind);
}
}
// Uniquify the nets
std::sort(involved_nets.begin(), involved_nets.end());
involved_nets.resize(std::distance(involved_nets.begin(), std::unique(involved_nets.begin(), involved_nets.end())));
return involved_nets;
}
struct Hnet_group{
struct Hpin{
index_t cell_index; // Not indexes in the circuit!!! Rather in the internal algorithm
minmax offset;
bool operator<(Hpin const o) const{ return cell_index < o.cell_index; }
};
struct Hnet{
bool has_ext_pins;
minmax ext_pins;
int_t weight;
Hnet(){
has_ext_pins = false;
ext_pins = minmax(std::numeric_limits<int_t>::max(), 0);
weight = 1;
}
};
std::vector<index_t> net_limits;
std::vector<Hnet> nets;
std::vector<Hpin> pins;
std::vector<int_t> cell_widths;
Hnet_group(){
net_limits.push_back(0);
}
void add_net(std::vector<pin_1D> const added_pins, int_t weight){
Hnet cur_net;
cur_net.weight = weight;
std::vector<Hpin> new_pins;
for(auto const p : added_pins){
if(p.movable){
Hpin new_pin;
new_pin.cell_index = p.cell_ind;
new_pin.offset = minmax(p.offs, p.offs);
new_pins.push_back(new_pin);
}
else{
cur_net.has_ext_pins = true;
cur_net.ext_pins.merge(p.pos);
}
}
std::sort(new_pins.begin(), new_pins.end());
if(not new_pins.empty()){ // Possible when generating from a Steiner topology
// Uniquify just in case there are several pins on the net on a single cell
index_t j=0;
auto prev_pin = new_pins[0];
for(auto it = new_pins.begin()+1; it != new_pins.end(); ++it){
if(it->cell_index == prev_pin.cell_index){
prev_pin.offset.merge(it->offset);
}
else{
new_pins[j] = prev_pin;
++j;
prev_pin = *it;
}
}
new_pins[j]=prev_pin;
new_pins.resize(j+1);
nets.push_back(cur_net);
net_limits.push_back(net_limits.back() + new_pins.size());
pins.insert(pins.end(), new_pins.begin(), new_pins.end());
}
}
std::int64_t get_cost(std::vector<int_t> const & pos) const{
std::int64_t cost=0;
for(index_t n=0; n<nets.size(); ++n){
auto cur_net = nets[n];
minmax mm(std::numeric_limits<int_t>::max(), std::numeric_limits<int_t>::min());
if(cur_net.has_ext_pins){
mm = cur_net.ext_pins;
}
assert(net_limits[n+1] > net_limits[n]);
for(index_t p=net_limits[n]; p<net_limits[n+1]; ++p){
int_t cur_pos = pos[pins[p].cell_index];
mm.merge( minmax(cur_pos + pins[p].offset.min, cur_pos + pins[p].offset.max) );
}
cost += static_cast<std::int64_t>(cur_net.weight) * (mm.max - mm.min);
}
return cost;
}
std::int64_t get_cost(std::vector<int_t> const & pos, std::vector<int> const & flip) const{
std::int64_t cost=0;
for(index_t n=0; n<nets.size(); ++n){
auto cur_net = nets[n];
minmax mm(std::numeric_limits<int_t>::max(), std::numeric_limits<int_t>::min());
if(cur_net.has_ext_pins){
mm = cur_net.ext_pins;
}
assert(net_limits[n+1] > net_limits[n]);
for(index_t p=net_limits[n]; p<net_limits[n+1]; ++p){
int_t cur_pos = pos[pins[p].cell_index];
bool flipped = flip[pins[p].cell_index];
int_t wdth = cell_widths[pins[p].cell_index];
mm.merge( flipped ?
minmax(cur_pos + wdth - pins[p].offset.max, cur_pos + wdth - pins[p].offset.min)
: minmax(cur_pos + pins[p].offset.min, cur_pos + pins[p].offset.max)
);
}
cost += static_cast<std::int64_t>(cur_net.weight) * (mm.max - mm.min);
}
return cost;
}
};
Hnet_group get_B2B_netgroup(netlist const & circuit, detailed_placement const & pl, std::vector<index_t> const & cells){
std::vector<order_gettr> cells_in_row = get_sorted_ordered_cells(cells);
std::vector<index_t> involved_nets = get_unique_nets(circuit, cells);
Hnet_group ret;
for(index_t c : cells)
ret.cell_widths.push_back(circuit.get_cell(c).size.x);
for(index_t n : involved_nets){
std::vector<pin_1D> cur_pins = get_pins_1D(circuit, pl.plt_, n).x;
for(pin_1D & p : cur_pins){
auto it = std::lower_bound(cells_in_row.begin(), cells_in_row.end(), p.cell_ind);
if(it != cells_in_row.end() and it->cell_ind == p.cell_ind){
p.cell_ind = it->seq_order;
}
else{ // Found a pin which remains fixed for this round
p.movable = false;
}
}
ret.add_net(cur_pins, circuit.get_net(n).weight);
}
return ret;
}
Hnet_group get_RSMT_netgroup(netlist const & circuit, detailed_placement const & pl, std::vector<index_t> const & cells){
std::vector<order_gettr> cells_in_row = get_sorted_ordered_cells(cells);
std::vector<index_t> involved_nets = get_unique_nets(circuit, cells);
Hnet_group ret;
for(index_t c : cells)
ret.cell_widths.push_back(circuit.get_cell(c).size.x);
for(index_t n : involved_nets){
auto vpins = get_pins_2D(circuit, pl.plt_, n);
for(auto & p : vpins){
auto it = std::lower_bound(cells_in_row.begin(), cells_in_row.end(), p.cell_ind);
if(it != cells_in_row.end() and it->cell_ind == p.cell_ind){
p.cell_ind = it->seq_order;
}
else{
p.movable = false;
}
}
std::vector<point<int_t> > pin_locations;
for(auto p : vpins)
pin_locations.push_back(p.pos);
auto const Htopo = get_RSMT_topology(pin_locations, 8).x;
// In the horizontal topology, we transform the parts of the tree that are on the row into HPWL subnets
// Two pins sharing an edge are in the same subnet if one of them is on the row: use union-find
union_find UF(vpins.size());
for(auto E : Htopo){
if( vpins[E.first].movable or vpins[E.second].movable){
UF.merge(E.first, E.second);
}
}
std::vector<std::vector<pin_1D> > connex_comps(vpins.size());
for(index_t i=0; i<vpins.size(); ++i){
connex_comps[UF.find(i)].push_back(vpins[i].x());;
}
int_t weight = circuit.get_net(n).weight;
for(index_t i=0; i<vpins.size(); ++i){
if(not connex_comps[i].empty()){
ret.add_net(connex_comps[i], weight);
}
}
}
return ret;
}
// Optimizes an ordered sequence of standard cells on the same row, returns the cost and the corresponding positions
inline std::int64_t optimize_convex_sequence(Hnet_group const & nets, std::vector<index_t> const & permutation, std::vector<int_t> & positions, std::vector<std::pair<int_t, int_t> > const & cell_ranges){
// Get the widths of the cells in row order
std::vector<int_t> loc_widths(permutation.size());
std::vector<std::pair<int_t, int_t> > loc_ranges(permutation.size());
for(index_t i=0; i<permutation.size(); ++i){
loc_widths[permutation[i]] = nets.cell_widths[i];
loc_ranges[permutation[i]] = cell_ranges[i];
}
std::vector<cell_bound> bounds;
std::vector<int_t> right_slopes(permutation.size(), 0);
for(index_t n=0; n<nets.nets.size(); ++n){
index_t fst_c=std::numeric_limits<index_t>::max(), lst_c=0;
int_t fst_pin_offs=0, lst_pin_offs=0;
assert(nets.net_limits[n+1] > nets.net_limits[n]);
auto cur_net = nets.nets[n];
for(index_t p=nets.net_limits[n]; p<nets.net_limits[n+1]; ++p){
// Permutation: index in the Hnet_group to index in the row
index_t cur_cell = permutation[nets.pins[p].cell_index];
if(cur_cell < fst_c){
fst_c = cur_cell;
fst_pin_offs = nets.pins[p].offset.min;
}
if(cur_cell >= lst_c){
lst_c = cur_cell;
lst_pin_offs = nets.pins[p].offset.max;
}
}
if(cur_net.has_ext_pins){
bounds.push_back(cell_bound(fst_c, cur_net.ext_pins.min - fst_pin_offs, cur_net.weight));
bounds.push_back(cell_bound(lst_c, cur_net.ext_pins.max - lst_pin_offs, cur_net.weight));
right_slopes[lst_c] += cur_net.weight;
}
else{
right_slopes[lst_c] += cur_net.weight;
right_slopes[fst_c] -= cur_net.weight;
}
}
bool feasible = place_convex_single_row(loc_widths, loc_ranges, bounds, right_slopes, positions);
auto permuted_positions = positions;
for(index_t i=0; i<permutation.size(); ++i){
permuted_positions[i] = positions[permutation[i]];
}
if(feasible)
return nets.get_cost(permuted_positions);
else
return std::numeric_limits<std::int64_t>::max(); // Infeasible: return a very big cost
}
// TODO: take modified order relative to the obstacles into account
inline std::int64_t optimize_noncvx_sequence(Hnet_group const & nets, std::vector<index_t> const & permutation, std::vector<int_t> & positions, std::vector<int> & flippings, std::vector<int> const & flippability, std::vector<std::pair<int_t, int_t> > const & cell_ranges){
// Get the widths of the cells in row order
std::vector<int_t> loc_widths(permutation.size());
std::vector<int> loc_flipps(permutation.size());
std::vector<std::pair<int_t, int_t> > loc_ranges(permutation.size());
for(index_t i=0; i<permutation.size(); ++i){
loc_widths[permutation[i]] = nets.cell_widths[i];
loc_ranges[permutation[i]] = cell_ranges[i];
loc_flipps[permutation[i]] = flippability[i];
}
int_t min_limit = std::numeric_limits<int_t>::min();
for(index_t i=0; i<loc_ranges.size(); ++i){
min_limit = std::max(loc_ranges[i].first, min_limit);
loc_ranges[i].first = min_limit;
min_limit += loc_widths[i];
}
int_t max_limit = std::numeric_limits<int_t>::max();
for(index_t i=loc_ranges.size(); i>0; --i){
max_limit = std::min(loc_ranges[i-1].second, max_limit);
max_limit -= loc_widths[i-1];
loc_ranges[i-1].second = max_limit;
}
for(index_t i=0; i<loc_ranges.size(); ++i){
if(loc_ranges[i].first > loc_ranges[i].second){
return std::numeric_limits<std::int64_t>::max(); // Infeasible: return a very big cost
}
}
std::vector<piecewise_linear_function> unflipped_cost_functions, flipped_cost_functions;
for(index_t i=0; i<loc_ranges.size(); ++i){
auto cur = piecewise_linear_function(loc_ranges[i].first, loc_ranges[i].second);
unflipped_cost_functions.push_back(cur);
flipped_cost_functions.push_back(cur);
}
for(index_t n=0; n<nets.nets.size(); ++n){
index_t fst_c=std::numeric_limits<index_t>::max(), lst_c=0;
int_t fst_pin_offs_mn=0, lst_pin_offs_mn=0,
fst_pin_offs_mx=0, lst_pin_offs_mx=0;
assert(nets.net_limits[n+1] > nets.net_limits[n]);
auto cur_net = nets.nets[n];
for(index_t p=nets.net_limits[n]; p<nets.net_limits[n+1]; ++p){
// Permutation: index in the Hnet_group to index in the row
index_t cur_cell = permutation[nets.pins[p].cell_index];
if(cur_cell < fst_c){
fst_c = cur_cell;
fst_pin_offs_mn = nets.pins[p].offset.min;
fst_pin_offs_mx = nets.pins[p].offset.max;
}
if(cur_cell >= lst_c){
lst_c = cur_cell;
lst_pin_offs_mn = nets.pins[p].offset.min;
lst_pin_offs_mx = nets.pins[p].offset.max;
}
}
if(cur_net.has_ext_pins){
unflipped_cost_functions[fst_c].add_bislope(-cur_net.weight, 0, cur_net.ext_pins.min - fst_pin_offs_mn);
unflipped_cost_functions[lst_c].add_bislope(0, cur_net.weight, cur_net.ext_pins.max - lst_pin_offs_mx);
flipped_cost_functions[fst_c].add_bislope(-cur_net.weight, 0, cur_net.ext_pins.min - loc_widths[fst_c] + fst_pin_offs_mx);
flipped_cost_functions[lst_c].add_bislope(0, cur_net.weight, cur_net.ext_pins.max - loc_widths[lst_c] + lst_pin_offs_mn);
}
else{
unflipped_cost_functions[fst_c].add_monotone(-cur_net.weight, -fst_pin_offs_mn);
unflipped_cost_functions[lst_c].add_monotone( cur_net.weight, -lst_pin_offs_mx);
flipped_cost_functions[fst_c].add_monotone(-cur_net.weight, fst_pin_offs_mx - loc_widths[fst_c] );
flipped_cost_functions[lst_c].add_monotone( cur_net.weight, lst_pin_offs_mn - loc_widths[lst_c] );
}
}
std::vector<piecewise_linear_function> prev_mins, merged_costs;
for(index_t i=0; i<loc_ranges.size(); ++i){
merged_costs.push_back(loc_flipps[i] ?
piecewise_linear_function::minimum(unflipped_cost_functions[i], flipped_cost_functions[i])
: unflipped_cost_functions[i]
);
if(i>0){
prev_mins.push_back(prev_mins.back().previous_min_of_sum(merged_costs.back(), loc_widths[i-1]));
}
else{
prev_mins.push_back(merged_costs.back().previous_min());
}
}
for(auto const M : prev_mins){
for(index_t i=0; i+1<M.point_values.size(); ++i){
assert(M.point_values[i].second >= M.point_values[i+1].second);
}
}
flippings.resize(cell_ranges.size(), 0); positions.resize(cell_ranges.size(), 0);
int_t pos = std::numeric_limits<int_t>::max();
for(index_t i=loc_ranges.size(); i>0; --i){
// Find the best position and flipping for each cell
pos = prev_mins[i-1].last_before(std::min(pos - loc_widths[i-1], loc_ranges[i-1].second) );
positions[i-1] = pos;
if(loc_flipps[i-1] and flipped_cost_functions[i-1].value_at(pos) < unflipped_cost_functions[i-1].value_at(pos)){
flippings[i-1] = 1;
}
}
for(index_t i=0; i<loc_ranges.size(); ++i){
assert(positions[i] >= loc_ranges[i].first);
assert(positions[i] <= loc_ranges[i].second);
}
for(index_t i=0; i+1<loc_ranges.size(); ++i){
assert(positions[i] + loc_widths[i] <= positions[i+1]);
}
auto permuted_positions = positions;
auto permuted_flippings = flippings;
for(index_t i=0; i<permutation.size(); ++i){
permuted_positions[i] = positions[permutation[i]];
permuted_flippings[i] = flippings[permutation[i]];
}
return nets.get_cost(permuted_positions, permuted_flippings);
}
std::vector<std::pair<int_t, int_t> > get_cell_ranges(netlist const & circuit, detailed_placement const & pl, std::vector<index_t> const & cells){
std::vector<std::pair<int_t, int_t> > lims;
for(index_t i=0; i+1<cells.size(); ++i){
assert(pl.plt_.positions_[cells[i]].x + circuit.get_cell(cells[i]).size.x <= pl.plt_.positions_[cells[i+1]].x);
}
// Extreme limits, except macros are allowed to be beyond the limit of the placement area
int_t lower_lim = pl.get_limit_positions(circuit, cells.front()).first;
int_t upper_lim = pl.get_limit_positions(circuit, cells.back()).second;
for(index_t OSRP_cell : cells){
auto attr = circuit.get_cell(OSRP_cell).attributes;
auto cur_lim = std::pair<int_t, int_t>(lower_lim, upper_lim);
int_t pos = pl.plt_.positions_[OSRP_cell].x;
if( (attr & XMovable) == 0 or pl.cell_height(OSRP_cell) != 1){
cur_lim = std::pair<int_t, int_t>(pos, pos + circuit.get_cell(OSRP_cell).size.x);
}
else{
assert(pos >= lower_lim);
assert(pos + circuit.get_cell(OSRP_cell).size.x <= upper_lim);
}
lims.push_back(cur_lim);
}
return lims;
}
template<bool NON_CONVEX, bool RSMT>
void OSRP_generic(netlist const & circuit, detailed_placement & pl){
for(index_t r=0; r<pl.row_cnt(); ++r){
// Complete optimization on a row, comprising possible obstacles
std::vector<index_t> cells;
std::vector<int> flippability;
// Get the movable cells, if we can flip them, and the obstacles on the row
for(index_t OSRP_cell = pl.get_first_cell_on_row(r); OSRP_cell != null_ind; OSRP_cell = pl.get_next_cell_on_row(OSRP_cell, r)){
auto attr = circuit.get_cell(OSRP_cell).attributes;
cells.push_back(OSRP_cell);
flippability.push_back( (attr & XFlippable) != 0 ? 1 : 0);
}
if(not cells.empty()){
std::vector<std::pair<int_t, int_t> > lims = get_cell_ranges(circuit, pl, cells); // Limit positions for each cell
Hnet_group nets = RSMT ?
get_RSMT_netgroup(circuit, pl, cells)
: get_B2B_netgroup(circuit, pl, cells);
std::vector<index_t> no_permutation(cells.size());
for(index_t i=0; i<cells.size(); ++i) no_permutation[i] = i;
std::vector<int_t> final_positions;
if(NON_CONVEX){
std::vector<int> flipped;
optimize_noncvx_sequence(nets, no_permutation, final_positions, flipped, flippability, lims);
for(index_t i=0; i<cells.size(); ++i){
bool old_orient = pl.plt_.orientations_[cells[i]].x;
pl.plt_.orientations_[cells[i]].x = flipped[i] ? not old_orient : old_orient;
}
}
else{
optimize_convex_sequence(nets, no_permutation, final_positions, lims);
}
// Update the positions and orientations
for(index_t i=0; i<cells.size(); ++i){
pl.plt_.positions_[cells[i]].x = final_positions[i];
}
}
} // Iteration on the rows
pl.selfcheck();
}
template<bool NON_CONVEX, bool RSMT>
void swaps_row_generic(netlist const & circuit, detailed_placement & pl, index_t range){
assert(range >= 2);
for(index_t r=0; r<pl.row_cnt(); ++r){
index_t OSRP_cell = pl.get_first_cell_on_row(r);
while(OSRP_cell != null_ind){
std::vector<index_t> cells;
std::vector<std::pair<int_t, int_t> > lims;
std::vector<int> flippables;
for(index_t nbr_cells=0;
OSRP_cell != null_ind
and nbr_cells < range;
OSRP_cell = pl.get_next_cell_on_row(OSRP_cell, r), ++nbr_cells
){
cells.push_back(OSRP_cell);
flippables.push_back( (circuit.get_cell(OSRP_cell).attributes & XFlippable) != 0);
}
if(not cells.empty()){
std::vector<std::pair<int_t, int_t> > lims = get_cell_ranges(circuit, pl, cells); // Limit positions for each cell
Hnet_group nets = RSMT ?
get_RSMT_netgroup(circuit, pl, cells)
: get_B2B_netgroup(circuit, pl, cells);
std::int64_t best_cost = std::numeric_limits<std::int64_t>::max();
std::vector<int_t> positions(cells.size());
std::vector<int> flippings(cells.size());
std::vector<int_t> best_positions(cells.size());
std::vector<int> best_flippings(cells.size());
std::vector<index_t> permutation(cells.size());
for(index_t i=0; i<cells.size(); ++i) permutation[i] = i;
std::vector<index_t> best_permutation;
// Check every possible permutation of the cells
do{
std::int64_t cur_cost = NON_CONVEX ?
optimize_noncvx_sequence(nets, permutation, positions, flippings, flippables, lims) :
optimize_convex_sequence(nets, permutation, positions, lims);
if(cur_cost <= best_cost){
best_cost = cur_cost;
best_permutation = permutation;
best_flippings = flippings;
best_positions = positions;
}
}while(std::next_permutation(permutation.begin(), permutation.end()));
std::vector<index_t> new_cell_order(cells.size());
// Update the positions and the topology
for(index_t i=0; i<cells.size(); ++i){
index_t r_ind = best_permutation[i]; // In the row from in the Hnet_group
new_cell_order[r_ind] = cells[i];
pl.plt_.positions_[cells[i]].x = best_positions[r_ind];
if(NON_CONVEX){
bool old_orient = pl.plt_.orientations_[cells[i]].x;
pl.plt_.orientations_[cells[i]].x = best_flippings[r_ind] ? not old_orient : old_orient;
}
}
pl.reorder_cells(cells, new_cell_order, r);
cells = new_cell_order;
assert(best_cost < std::numeric_limits<std::int64_t>::max());
}
if(OSRP_cell != null_ind){
assert(cells.size() == range);
OSRP_cell = cells[range/2];
}
} // Iteration on the entire row
} // Iteration on the rows
pl.selfcheck();
}
} // End anonymous namespace
void OSRP_convex_HPWL(netlist const & circuit, detailed_placement & pl){ OSRP_generic< false, false>(circuit, pl); }
void OSRP_convex_RSMT(netlist const & circuit, detailed_placement & pl){ OSRP_generic< false, true >(circuit, pl); }
void OSRP_noncvx_HPWL(netlist const & circuit, detailed_placement & pl){ OSRP_generic< true , false>(circuit, pl); }
void OSRP_noncvx_RSMT(netlist const & circuit, detailed_placement & pl){ OSRP_generic< true , true >(circuit, pl); }
void swaps_row_convex_HPWL(netlist const & circuit, detailed_placement & pl, index_t range){ swaps_row_generic< false, false>(circuit, pl, range); }
void swaps_row_convex_RSMT(netlist const & circuit, detailed_placement & pl, index_t range){ swaps_row_generic< false, true >(circuit, pl, range); }
void swaps_row_noncvx_HPWL(netlist const & circuit, detailed_placement & pl, index_t range){ swaps_row_generic< true , false>(circuit, pl, range); }
void swaps_row_noncvx_RSMT(netlist const & circuit, detailed_placement & pl, index_t range){ swaps_row_generic< true , true >(circuit, pl, range); }
} // namespace dp
} // namespace coloquinte

View File

@ -1,384 +0,0 @@
#include "coloquinte/solvers.hxx"
#include <cassert>
#include <stdexcept>
#include <cmath>
#include <limits>
namespace coloquinte{
namespace gp{
linear_system linear_system::operator+(linear_system const & o) const{
if(o.internal_size() != internal_size()){ throw std::runtime_error("Mismatched system sizes"); }
linear_system ret(target_.size() + o.target_.size() - internal_size(), internal_size());
ret.matrix_ = matrix_;
std::vector<matrix_triplet> omatrix = o.matrix_;
for(matrix_triplet & t : omatrix){
if(t.c_ >= internal_size()){
t.c_ += (target_.size() - internal_size());
}
if(t.r_ >= internal_size()){
t.r_ += (target_.size() - internal_size());
}
}
ret.matrix_.insert(ret.matrix_.end(), omatrix.begin(), omatrix.end());
// ret.target_.resize(target_.size() + o.target_.size() - internal_size);
for(index_t i=0; i<internal_size(); ++i){
ret.target_[i] = target_[i] + o.target_[i];
}
for(index_t i=internal_size(); i<target_.size(); ++i){
ret.target_[i] = target_[i];
}
for(index_t i=internal_size(); i<o.target_.size(); ++i){
ret.target_[i + target_.size() - internal_size()] = o.target_[i];
}
return ret;
}
// The classical compressed sparse row storage
struct csr_matrix{
std::vector<std::uint32_t> row_limits, col_indexes;
std::vector<float> values, diag;
std::vector<float> mul(std::vector<float> const & x) const;
std::vector<float> solve_CG(std::vector<float> const & goal, std::vector<float> guess, std::uint32_t min_iter, std::uint32_t max_iter, float tol) const;
csr_matrix(std::vector<std::uint32_t> const & row_l, std::vector<std::uint32_t> const & col_i, std::vector<float> const & vals, std::vector<float> const D) : row_limits(row_l), col_indexes(col_i), values(vals), diag(D){
assert(values.size() == col_indexes.size());
assert(diag.size()+1 == row_limits.size());
}
};
// A matrix with successive rows padded to the same length and accessed column-major; hopefully a little better
template<std::uint32_t unroll_len>
struct ellpack_matrix{
std::vector<std::uint32_t> row_limits, col_indexes;
std::vector<float> values, diag;
std::vector<float> mul(std::vector<float> const & x) const;
std::vector<float> solve_CG(std::vector<float> goal, std::vector<float> guess, std::uint32_t min_iter, std::uint32_t max_iter, float tol) const;
ellpack_matrix(std::vector<std::uint32_t> const & row_l, std::vector<std::uint32_t> const & col_i, std::vector<float> const & vals, std::vector<float> const D) : row_limits(row_l), col_indexes(col_i), values(vals), diag(D){
assert(values.size() == col_indexes.size());
assert(diag.size() % unroll_len == 0);
assert((row_limits.size()-1) * unroll_len == diag.size() );
assert(row_limits.back() * unroll_len == values.size());
assert(values.size() % unroll_len == 0);
assert(col_indexes.size() % unroll_len == 0);
}
};
// The proxy matrix for compressed sparse storage
class doublet_matrix{
std::vector<std::uint32_t> row_limits;
std::vector<matrix_doublet> doublets;
std::uint32_t size;
void get_compressed(std::vector<std::uint32_t> & limits, std::vector<matrix_doublet> & elements, std::vector<float> & diag) const;
public:
doublet_matrix(std::vector<matrix_triplet> const & triplets, std::uint32_t size);
csr_matrix get_compressed_matrix() const;
template<std::uint32_t unroll_len>
ellpack_matrix<unroll_len> get_ellpack_matrix() const;
};
doublet_matrix::doublet_matrix(std::vector<matrix_triplet> const & triplets, std::uint32_t n) : size(n){
row_limits.resize(size+1, 0);
// First store the row sizes in the array
for(uint32_t i=0; i<triplets.size(); ++i){
++row_limits[triplets[i].r_+1];
}
// The total size of the uncompressed matrix
uint32_t tot_triplets=0;
// Get the beginning position of each row in the csr matrix
for(uint32_t i=1; i<n+1; ++i){
uint32_t new_tot_triplets = tot_triplets + row_limits[i];
row_limits[i] = tot_triplets; // Stores the beginning of the row
tot_triplets = new_tot_triplets;
}
assert(tot_triplets == triplets.size());
// Now we know the size and can allocate storage for the indices and values
doublets.resize(tot_triplets);
// We store the triplets in the new storage and tranform beginning positions into end positions
for(uint32_t i=0; i<triplets.size(); ++i){
doublets[row_limits[triplets[i].r_+1]] = matrix_doublet(triplets[i].c_, triplets[i].val_);
++row_limits[triplets[i].r_+1]; // row_limits will hold the end position of the row
}
}
void doublet_matrix::get_compressed(std::vector<std::uint32_t> & sizes, std::vector<matrix_doublet> & elements, std::vector<float> & diag) const{
assert(size+1 == row_limits.size());
sizes.resize(size);
diag.resize(size, 0.0);
std::vector<matrix_doublet> tmp_doublets = doublets;
for(uint32_t i=0; i<size; ++i){
// Sort the elements in the row
std::sort(tmp_doublets.begin() + row_limits[i], tmp_doublets.begin() + row_limits[i+1]);
// Compress them and extract the diagonal
std::uint32_t l=0;
matrix_doublet cur(tmp_doublets[row_limits[i]]);
for(uint32_t j=row_limits[i]+1; j<row_limits[i+1]; ++j){
if(tmp_doublets[j].c_ == cur.c_){
cur.val_ += tmp_doublets[j].val_;
}
else{
if(i != cur.c_){
elements.push_back(cur);
++l;
}
else{
diag[i] = cur.val_;
}
cur = tmp_doublets[j];
}
}
if(i != cur.c_){
elements.push_back(cur);
++l;
}
else{
diag[i] = cur.val_;
}
sizes[i] = l;
}
}
csr_matrix doublet_matrix::get_compressed_matrix() const{
std::vector<matrix_doublet> tmp_doublets;
std::vector<std::uint32_t> sizes;
std::vector<float> diag;
get_compressed(sizes, tmp_doublets, diag);
// Get the limits of each row
std::vector<std::uint32_t> new_row_limits(row_limits.size());
new_row_limits[0] = 0;
for(std::uint32_t i=0; i<size; ++i){
new_row_limits[i+1] = new_row_limits[i] + sizes[i];
}
// Store the doublets to the sparse storage
std::vector<std::uint32_t> col_indices(tmp_doublets.size());
std::vector<float> values(tmp_doublets.size());
for(std::uint32_t i=0; i<tmp_doublets.size(); ++i){
col_indices[i] = tmp_doublets[i].c_;
values[i] = tmp_doublets[i].val_;
}
return csr_matrix(new_row_limits, col_indices, values, diag);
}
template<std::uint32_t unroll_len>
ellpack_matrix<unroll_len> doublet_matrix::get_ellpack_matrix() const{
std::vector<matrix_doublet> tmp_doublets;
std::vector<std::uint32_t> sizes;
std::vector<float> diag;
get_compressed(sizes, tmp_doublets, diag);
std::uint32_t unrolled_size = (diag.size() % unroll_len == 0)? diag.size()/unroll_len : diag.size() / unroll_len + 1;
sizes.resize(unroll_len * unrolled_size, 0);
diag.resize(unroll_len * unrolled_size, 1.0);
// Store the maximum size of a group of rows
std::vector<std::uint32_t> new_row_limits(unrolled_size+1);
new_row_limits[0] = 0;
for(std::uint32_t i=0; i<unrolled_size; ++i){
std::uint32_t max_sz = sizes[unroll_len*i];
for(int j=1; j<unroll_len; ++j){
max_sz = std::max(max_sz, sizes[unroll_len*i + j]);
}
new_row_limits[i+1] = new_row_limits[i] + max_sz;
}
std::vector<std::uint32_t> col_indices(unroll_len * new_row_limits.back());
std::vector<float> values(unroll_len * new_row_limits.back());
std::uint32_t d = 0;
for(std::uint32_t i=0; i<sizes.size(); ++i){ // For every line
std::uint32_t ui = i/unroll_len;
std::uint32_t k = i%unroll_len;
std::uint32_t max_sz = new_row_limits[ui+1] - new_row_limits[ui];
std::uint32_t row_begin = new_row_limits[ui];
for(std::uint32_t j=0; j<sizes[i]; ++j, ++d){ // For the non-zero values
col_indices[unroll_len * (row_begin+j) + k] = tmp_doublets[d].c_;
values[unroll_len * (row_begin+j) + k] = tmp_doublets[d].val_;
}
for(std::uint32_t j=sizes[i]; j<max_sz; ++j){ // For the padding zeroes
col_indices[unroll_len * (row_begin+j) + k] = 0;
values[unroll_len * (row_begin+j) + k] = 0;
}
}
return ellpack_matrix<unroll_len>(new_row_limits, col_indices, values, diag);
}
std::vector<float> csr_matrix::mul(std::vector<float> const & x) const{
std::vector<float> res(x.size());
assert(x.size() == diag.size());
for(std::uint32_t i=0; i<diag.size(); ++i){
res[i] = diag[i] * x[i];
for(std::uint32_t j=row_limits[i]; j<row_limits[i+1]; ++j){
res[i] += values[j] * x[col_indexes[j]];
}
}
return res;
}
template<std::uint32_t unroll_len>
std::vector<float> ellpack_matrix<unroll_len>::mul(std::vector<float> const & x) const{
std::vector<float> res(x.size());
assert(x.size() % unroll_len == 0);
assert(x.size() == diag.size());
for(std::uint32_t i=0; i+1<row_limits.size(); ++i){
float cur[unroll_len];
for(int k=0; k<unroll_len; ++k){
cur[k] = diag[unroll_len*i+k] * x[unroll_len*i+k];
}
for(std::uint32_t j=row_limits[i]; j<row_limits[i+1]; ++j){
for(int k=0; k<unroll_len; ++k){
cur[k] += values[unroll_len*j+k] * x[col_indexes[unroll_len*j+k]];
}
}
for(int k=0; k<unroll_len; ++k){
res[unroll_len*i+k] = cur[k];
}
}
return res;
}
template<std::uint32_t unroll_len>
float dot_prod(std::vector<float> const & a, std::vector<float> const & b){
assert(a.size() == b.size());
float vals[unroll_len];
for(int j=0; j<unroll_len; ++j) vals[j] = 0.0;
for(std::uint32_t i=0; i<a.size() / unroll_len; ++i){
for(int j=0; j<unroll_len; ++j){
vals[j] += a[unroll_len*i + j] * b[unroll_len*i + j];
}
}
float res = 0.0;
for(int j=0; j<unroll_len; ++j) res += vals[j];
for(int i = unroll_len*(a.size() / unroll_len); i< a.size(); ++i){
res += a[i] * b[i];
}
return res;
}
std::vector<float> csr_matrix::solve_CG(std::vector<float> const & goal, std::vector<float> x, std::uint32_t min_iter, std::uint32_t max_iter, float tol_ratio) const{
std::uint32_t n = diag.size();
assert(goal.size() == n);
assert(x.size() == n);
std::vector<float> r, p(n), z(n), mul_res, preconditioner(n);
r = mul(x);
for(uint32_t i=0; i<n; ++i){
r[i] = goal[i] - r[i];
preconditioner[i] = 1.0/diag[i];
assert(std::isfinite(preconditioner[i]));
z[i] = preconditioner[i] * r[i];
p[i] = z[i];
}
float cross_norm = dot_prod<16>(r, z);
assert(std::isfinite(cross_norm));
float_t const epsilon = std::numeric_limits<float_t>::min();
float start_norm = cross_norm;
for(uint32_t k=0; k < max_iter; ++k){
mul_res = mul(p);
float_t pr_prod = dot_prod<16>(p, mul_res);
float_t alpha = cross_norm / pr_prod;
if(
not std::isfinite(cross_norm) or not std::isfinite(alpha) or not std::isfinite(pr_prod)
or cross_norm <= epsilon or alpha <= epsilon or pr_prod <= epsilon
){
break;
}
// Update the result
for(uint32_t i=0; i<n; ++i){
x[i] = x[i] + alpha * p[i];
r[i] = r[i] - alpha * mul_res[i];
z[i] = preconditioner[i] * r[i];
}
float new_cross_norm = dot_prod<16>(r, z);
// Update the scaled residual and the search direction
if(k >= min_iter && new_cross_norm <= tol_ratio * start_norm){
break;
}
float beta = new_cross_norm / cross_norm;
cross_norm = new_cross_norm;
for(uint32_t i=0; i<n; ++i)
p[i] = z[i] + beta * p[i];
}
return x;
}
template<std::uint32_t unroll_len>
std::vector<float> ellpack_matrix<unroll_len>::solve_CG(std::vector<float> goal, std::vector<float> x, std::uint32_t min_iter, std::uint32_t max_iter, float tol_ratio) const{
std::uint32_t n = diag.size();
std::uint32_t old_n = x.size();
assert(goal.size() == x.size());
x.resize(diag.size(), 0.0);
goal.resize(diag.size(), 0.0);
std::vector<float> r, p(n), z(n), mul_res, preconditioner(n);
r = mul(x);
for(uint32_t i=0; i<n; ++i){
r[i] = goal[i] - r[i];
preconditioner[i] = 1.0/diag[i];
z[i] = preconditioner[i] * r[i];
p[i] = z[i];
}
float cross_norm = dot_prod<unroll_len>(r, z);
float start_norm = cross_norm;
for(uint32_t k=0; k < max_iter; ++k){
mul_res = mul(p);
float alpha = cross_norm / dot_prod<unroll_len>(p, mul_res);
// Update the result
for(uint32_t i=0; i<n; ++i){
x[i] = x[i] + alpha * p[i];
r[i] = r[i] - alpha * mul_res[i];
z[i] = preconditioner[i] * r[i];
}
float new_cross_norm = dot_prod<unroll_len>(r, z);
// Update the scaled residual and the search direction
if(k >= min_iter && new_cross_norm <= tol_ratio * start_norm){
break;
}
float beta = new_cross_norm / cross_norm;
cross_norm = new_cross_norm;
for(uint32_t i=0; i<n; ++i)
p[i] = z[i] + beta * p[i];
}
x.resize(old_n);
return x;
}
std::vector<float_t> linear_system::solve_CG(std::vector<float_t> guess, index_t nbr_iter){
doublet_matrix tmp(matrix_, size());
csr_matrix mat = tmp.get_compressed_matrix();
//ellpack_matrix<16> mat = tmp.get_ellpack_matrix<16>();
guess.resize(target_.size(), 0.0);
auto ret = mat.solve_CG(target_, guess, nbr_iter, nbr_iter, 0.0);
ret.resize(internal_size());
return ret;
}
}
}

View File

@ -1,536 +0,0 @@
#include "coloquinte/topologies.hxx"
#include "coloquinte/circuit_helper.hxx"
#include "coloquinte/union_find.hxx"
#include <algorithm>
#include <cassert>
#include <set>
#include <functional>
#include <cmath>
#include <array>
#include <limits>
namespace coloquinte{
using edge_t = std::pair<index_t, index_t>;
namespace{
struct minmax_t{
int_t min, max;
minmax_t(int_t mn, int_t mx) : min(mn), max(mx) {}
minmax_t() {}
void merge(minmax_t const o){
min = std::min(o.max, min);
max = std::max(o.min, max);
}
void merge(int_t const p){
min = std::min(p, min);
max = std::max(p, max);
}
};
}
namespace steiner_lookup{
template<int pin_cnt>
int_t Hconnectivity<pin_cnt>::get_wirelength(std::array<point<int_t>, pin_cnt> const sorted_points) const{
std::array<minmax_t, pin_cnt-2> minmaxs;
for(index_t i=0; i<pin_cnt-2; ++i){
minmaxs[i] = minmax_t(sorted_points[i+1].y, sorted_points[i+1].y);
}
std::uint8_t b_con = extremes & 15u, e_con = extremes >> 4;
minmaxs[b_con].merge(sorted_points.front() .y);
minmaxs[e_con].merge(sorted_points.back() .y);
for(std::uint8_t const E : connexions){
minmaxs[(E >> 4)].merge(minmaxs[(E & 15u)]);
}
int_t cost = sorted_points.back().x - sorted_points.front().x + sorted_points[b_con+1].x - sorted_points[e_con+1].x;
for(std::uint8_t const E : connexions){
cost += std::abs((float)(sorted_points[(E >> 4) +1].x - sorted_points[(E & 15u) +1].x));
}
for(index_t i=0; i<pin_cnt-2; ++i){
cost += (minmaxs[i].max - minmaxs[i].min);
}
return cost;
}
template<int pin_cnt>
std::array<edge_t, pin_cnt-1> Hconnectivity<pin_cnt>::get_x_topology(std::array<point<int_t>, pin_cnt> const sorted_points) const{
std::array<edge_t, pin_cnt-1> ret;
std::uint8_t b_con = extremes & 15u, e_con = extremes >> 4;
ret[0] = edge_t(0, b_con+1);
ret[1] = edge_t(pin_cnt-1, e_con+1);
for(index_t i=0; i<pin_cnt-3; ++i){
std::uint8_t E = connexions[i];
ret[i+2] = edge_t((E & 15u) +1, (E >> 4) +1);
}
return ret;
}
} // End namespace steiner_lookup
namespace {
template<int n, int array_size>
int_t get_wirelength_from_sorted(std::vector<point<int_t> > const & pins, std::array<steiner_lookup::Hconnectivity<n>, array_size> const & lookups){
std::array<point<int_t>, n> points;
std::copy_n(pins.begin(), n, points.begin());
int_t cost = std::numeric_limits<int_t>::max();
for(auto const L : lookups){
cost = std::min(cost, L.get_wirelength(points));
}
return cost;
}
std::int64_t get_wirelength_from_topo(std::vector<point<int_t> > const & points, std::vector<std::pair<index_t, index_t> > Htopo){
std::vector<minmax_t> minmaxs(points.size());
for(index_t i=0; i<points.size(); ++i){
minmaxs[i] = minmax_t(points[i].y, points[i].y);
}
for(auto const E : Htopo){
minmaxs[E.second].merge(minmaxs[E.first]);
}
std::int64_t cost = 0;
for(edge_t const E : Htopo){
cost += std::abs((float)(points[E.first].x - points[E.second].x));
}
for(index_t i=0; i<points.size(); ++i){
cost += (minmaxs[i].max - minmaxs[i].min);
}
return cost;
}
struct indexed_pt : point<int_t>{
index_t index;
indexed_pt(point<int_t> pt, index_t pos) : point<int_t>(pt), index(pos) {}
indexed_pt(){}
};
template<int n, int array_size>
std::vector<std::pair<index_t, index_t> > get_topology_from_sorted(std::vector<point<int_t> > const & pins, std::array<steiner_lookup::Hconnectivity<n>, array_size> const & lookups){
std::array<point<int_t>, n> points;
std::copy_n(pins.begin(), n, points.begin());
// Find the horizontal topology with the smallest cost
int_t cost = std::numeric_limits<int_t>::max();
index_t ind = std::numeric_limits<index_t>::max();
for(index_t i=0; i<array_size; ++i){
int_t this_cost = lookups[i].get_wirelength(points);
if(this_cost < cost){
cost = this_cost;
ind = i;
}
}
assert(ind != std::numeric_limits<index_t>::max());
auto ret = lookups[ind].get_x_topology(points);
return std::vector<std::pair<index_t, index_t> >(ret.begin(), ret.end());
}
std::vector<edge_t> get_vertical_topology(std::vector<point<int_t> > pins, std::vector<edge_t> const & Htopo){
index_t const null_ind = std::numeric_limits<index_t>::max();
std::vector<indexed_pt> ipoints(pins.size());
for(index_t i=0; i<pins.size(); ++i){
ipoints[i] = indexed_pt(pins[i], i);
}
std::sort(ipoints.begin(), ipoints.end(), [](indexed_pt a , indexed_pt b){return a.y < b.y; });
// First pin with y ordering
std::vector<index_t> min_y_pin(pins.size());
for(index_t i=0; i<ipoints.size(); ++i){
min_y_pin[ipoints[i].index] = i;
}
std::vector<index_t> max_y_pin = min_y_pin;
std::vector<index_t> nxt_y_pin(pins.size(), null_ind);
std::vector<edge_t> ret;
for(auto const E : Htopo){
// Assuming a correctly ordered horizontal topology where the first node of the edge is never visited again
index_t f=E.first, s=E.second;
index_t first_yf=min_y_pin[f], first_ys=min_y_pin[s];
// Push the edges from the first and insert one of its elements in the second's linked structure
if(max_y_pin[f] < min_y_pin[s] or max_y_pin[s] < min_y_pin[f]){
for(index_t yf=first_yf; nxt_y_pin[yf] != null_ind; yf = nxt_y_pin[yf]){
ret.push_back(edge_t(yf, nxt_y_pin[yf]));
}
if(max_y_pin[f] < min_y_pin[s]){
nxt_y_pin[max_y_pin[f]] = min_y_pin[s];
min_y_pin[s] = max_y_pin[f];
}
else if(max_y_pin[s] < min_y_pin[f]){
nxt_y_pin[max_y_pin[s]] = min_y_pin[f];
max_y_pin[s] = min_y_pin[f];
nxt_y_pin[min_y_pin[f]] = null_ind;
}
else{
abort();
}
}
else{ // Need to chose a pin with two connexions because there will be no L route
// One pin from the second is in the middle of the first
if(max_y_pin[f] > max_y_pin[s]){
index_t middle_pin = max_y_pin[s];
index_t yf=first_yf;
// Make the first connexions
for(; nxt_y_pin[yf] < middle_pin; yf = nxt_y_pin[yf]){
ret.push_back(edge_t(yf, nxt_y_pin[yf]));
}
// Make the two connexions with the new pin
ret.push_back(edge_t(yf, middle_pin));
yf = nxt_y_pin[yf];
ret.push_back(edge_t(yf, middle_pin));
// Finish the connexions
for(; nxt_y_pin[yf] != null_ind; yf = nxt_y_pin[yf]){
ret.push_back(edge_t(yf, nxt_y_pin[yf]));
}
}
// One pin from the first is in the middle of the second
else{
for(index_t yf=first_yf; nxt_y_pin[yf] != null_ind; yf = nxt_y_pin[yf]){
ret.push_back(edge_t(yf, nxt_y_pin[yf]));
}
index_t middle_pin = max_y_pin[f];
// Find the place where we can insert this pin
index_t ys=first_ys;
for(; nxt_y_pin[ys] < middle_pin; ys = nxt_y_pin[ys]);
nxt_y_pin[middle_pin] = nxt_y_pin[ys];
nxt_y_pin[ys] = middle_pin;
}
}
}
// The last visited gives the remaining connexions to push
for(index_t yf=min_y_pin[Htopo.back().second]; nxt_y_pin[yf] != null_ind; yf = nxt_y_pin[yf]){
ret.push_back(edge_t(yf, nxt_y_pin[yf]));
}
// Back to the original ordering
for(auto & E : ret){
E.first = ipoints[E.first].index;
E.second = ipoints[E.second].index;
}
return ret;
}
inline void northeast_octant_neighbours(std::vector<point<int_t> > pins, std::vector<std::pair<index_t, index_t> > & edges){
std::vector<indexed_pt> point_list;
for(index_t i=0; i<pins.size(); ++i){
point_list.push_back(indexed_pt(pins[i], i));
}
std::sort(point_list.begin(), point_list.end(),
[](indexed_pt const a, indexed_pt const b){ return a.x + a.y < b.x + b.y; }
);
// Decreasing order of x and y; multiset not necessary because no two elements have same coordinate
std::set<indexed_pt, std::function<bool (indexed_pt const, indexed_pt const)> >
active_upper_octant([](indexed_pt const a, indexed_pt const b)->bool{return a.x > b.x;}),
active_lower_octant([](indexed_pt const a, indexed_pt const b)->bool{return a.y > b.y;});
for(indexed_pt const current : point_list){
{ // North to north-east region
auto first_it = active_upper_octant.lower_bound(current); // Largest x with x <= current.x
auto it = first_it;
for(; it != active_upper_octant.end() && it->x - it->y >= current.x - current.y; ++it){
edges.push_back(std::pair<index_t, index_t>(current.index, it->index));
}
if(first_it != active_upper_octant.end()){ active_upper_octant.erase(first_it, it); }
active_upper_octant.insert(it, current); // Hint to insert the element since it is the correct position
} // End region
{ // North-east to east region
auto first_it = active_lower_octant.lower_bound(current); // Largest y with y <= current.y
auto it = first_it;
for(; it != active_lower_octant.end() && it->y - it->x >= current.y - current.x; ++it){
edges.push_back(std::pair<index_t, index_t>(current.index, it->index));
}
if(first_it != active_lower_octant.end()){ active_lower_octant.erase(first_it, it); }
active_lower_octant.insert(it, current); // Hint to insert the element since it is the correct position
} // End region
}
}
// Gets the nearest octant neighbour for each point in the south-east quadrant
inline void southeast_octant_neighbours(std::vector<point<int_t> > pins, std::vector<std::pair<index_t, index_t> > & edges){
for(auto & pin : pins){
pin.y = - pin.y;
}
northeast_octant_neighbours(pins, edges);
}
std::vector<std::pair<index_t, index_t> > get_small_horizontal_topology_from_sorted(std::vector<point<int_t> > const & pins){
assert(pins.size() <= 10);
switch(pins.size()){
case 2:
return std::vector<edge_t>(1, edge_t(0, 1));
case 3:
return std::vector<edge_t>{{0, 1}, {1, 2}};
case 4:
return get_topology_from_sorted<4, 2>(pins, steiner_lookup::topologies_4);
case 5:
return get_topology_from_sorted<5, 6>(pins, steiner_lookup::topologies_5);
case 6:
return get_topology_from_sorted<6, 23>(pins, steiner_lookup::topologies_6);
case 7:
return get_topology_from_sorted<7, 111>(pins, steiner_lookup::topologies_7);
case 8:
return get_topology_from_sorted<8, 642>(pins, steiner_lookup::topologies_8);
case 9:
return get_topology_from_sorted<9, 4334>(pins, steiner_lookup::topologies_9);
case 10:
return get_topology_from_sorted<10, 33510>(pins, steiner_lookup::topologies_10);
default: // Only 1 and 0 left (11 and more are protected by an assertion)
return std::vector<edge_t>();
}
}
// Get an ordering of the edges that is compatible with the processing functions
std::vector<edge_t> get_tree_topo_sort(std::vector<edge_t> const & topo){
std::vector<edge_t> sorted_topo;
std::vector<std::vector<index_t> > neighbours(topo.size()+1);
for(edge_t const E : topo){
neighbours[E.first].push_back(E.second);
neighbours[E.second].push_back(E.first);
}
std::vector<index_t> to_visit;
std::vector<int_t> nbr_unvisited(topo.size()+1);
for(index_t i=0; i<=topo.size(); ++i){
nbr_unvisited[i] = neighbours[i].size();
assert(topo.size() == 0 or nbr_unvisited[i] >= 1);
if(nbr_unvisited[i] == 1)
to_visit.push_back(i);
}
std::vector<int> visited(topo.size()+1, 0);
while(not to_visit.empty()){
index_t f = to_visit.back();
assert(visited[f] == 0);
visited[f] = 1;
to_visit.pop_back();
for(index_t s : neighbours[f]){
--nbr_unvisited[s];
if(visited[s] == 0){ // It is not a node we already visited
sorted_topo.push_back(edge_t(f, s));
}
if(nbr_unvisited[s] == 1){
to_visit.push_back(s);
}
}
}
assert(sorted_topo.size() == topo.size());
return sorted_topo;
}
std::vector<edge_t> get_big_horizontal_topology_from_sorted(std::vector<point<int_t> > const & pins, index_t exactitude_limit){
auto spanning = get_MST_topology(pins);
// TODO: perform local optimizations on the topology using exact Steiner tree algorithms
// Remove horizontal suboptimalities i.e. when the connexions to the left and right are unbalanced
// Reuse existing code by translation to vertical topology
auto first_Htopo = get_tree_topo_sort(spanning);
auto Vtopo = get_vertical_topology(pins, first_Htopo);
Vtopo = get_tree_topo_sort(Vtopo);
std::vector<point<int_t> > inverted_coords = pins;
for(point<int_t> & pt : inverted_coords){
std::swap(pt.x, pt.y);
}
auto Htopo = get_vertical_topology(inverted_coords, Vtopo);
// Sort the tree so that it is usable when building an RSMT
return get_tree_topo_sort(Htopo);
}
} // End anonymous namespace
std::vector<edge_t> get_RSMT_horizontal_topology(std::vector<point<int_t> > const & pins, index_t exactitude_limit){
if(pins.size() <= 1)
return std::vector<edge_t>();
else if(pins.size() == 2)
return std::vector<edge_t>(1, edge_t(0, 1));
else if(pins.size() == 3){
std::vector<indexed_pt> ipoints(pins.size());
for(index_t i=0; i<pins.size(); ++i){
ipoints[i] = indexed_pt(pins[i], i);
}
auto xpoints=ipoints;
std::sort(xpoints.begin(), xpoints.end(), [](indexed_pt a , indexed_pt b){return a.x < b.x; });
return std::vector<edge_t>{{xpoints[0].index, xpoints[1].index}, {xpoints[1].index, xpoints[2].index}};
}
else{
std::vector<edge_t> horizontal_topology;
// Sort the pins by x coordinate
std::vector<indexed_pt> ipoints(pins.size());
for(index_t i=0; i<pins.size(); ++i){
ipoints[i] = indexed_pt(pins[i], i);
}
std::sort(ipoints.begin(), ipoints.end(), [](indexed_pt a , indexed_pt b){return a.x < b.x; });
std::vector<point<int_t> > sorted_pins(pins.size());
for(index_t i=0; i<pins.size(); ++i){
sorted_pins[i] = ipoints[i];
}
// Get the topology for this ordering
if(pins.size() <= exactitude_limit){
horizontal_topology = get_small_horizontal_topology_from_sorted(sorted_pins);
}
else{
horizontal_topology = get_big_horizontal_topology_from_sorted(sorted_pins, exactitude_limit);
}
// Back to the original ordering
for(auto & E : horizontal_topology){
E.first = ipoints[E.first].index;
E.second = ipoints[E.second].index;
}
return horizontal_topology;
}
}
std::vector<std::pair<index_t, index_t> > get_MST_topology(std::vector<point<int_t> > const & pins){
std::vector<edge_t> edges;
if(pins.size() <= 2){
if(pins.size() == 2){
edges.push_back(edge_t(0, 1));
}
if(pins.size() == 3){
auto D = [](point<int_t> a, point<int_t> b){ return (int_t)(std::abs((float)(a.x - b.x)) + std::abs((float)(a.y - b.y))); };
auto dists = std::array<int_t, 3>({{D(pins[1], pins[2]), D(pins[1], pins[2]), D(pins[0], pins[1])}});
index_t mx = std::max_element(dists.begin(), dists.end()) - dists.begin();
for(index_t i=0; i<3; ++i){
if(i != mx)
edges.push_back(edge_t((i+1) % 3, (i+2) % 3));
}
}
return edges;
}
northeast_octant_neighbours(pins, edges);
southeast_octant_neighbours(pins, edges);
std::vector<edge_t> returned_edges;
auto edge_length = [&](edge_t E){
point<int_t> p1 = pins[E.first],
p2 = pins[E.second];
return std::abs((float)(p1.x - p2.x)) + std::abs((float)(p1.y - p2.y));
};
// Perform Kruskal to get the tree
std::sort(edges.begin(), edges.end(), [&](edge_t a, edge_t b){ return edge_length(a) < edge_length(b); });
union_find merger(pins.size());
for(index_t i=0; i<edges.size() && returned_edges.size()+1 < pins.size(); ++i){
edge_t E = edges[i];
if(merger.find(E.first) != merger.find(E.second)){
merger.merge(E.first, E.second);
assert(merger.find(E.first) == merger.find(E.second));
returned_edges.push_back(E);
}
}
assert(returned_edges.size() + 1 == pins.size());
assert(merger.is_connex());
return returned_edges;
}
std::int64_t MST_length(std::vector<point<int_t> > const & pins){
auto edges = get_MST_topology(pins);
std::int64_t sum = 0;
for(auto E : edges){
sum += std::abs((float)(pins[E.first].x - pins[E.second].x));
sum += std::abs((float)(pins[E.first].y - pins[E.second].y));
}
return sum;
}
std::int64_t RSMT_length(std::vector<point<int_t> > const & pins, index_t exactitude_limit){
assert(exactitude_limit <= 10 and exactitude_limit >= 3);
if(pins.size() <= 3){
if(pins.size() == 2){
return std::abs((float)(pins[0].x - pins[1].x)) + std::abs((float)(pins[0].y - pins[1].y));
}
else if(pins.size() == 3){
auto minmaxX = std::minmax_element(pins.begin(), pins.end(), [](point<int_t> a, point<int_t> b){ return a.x < b.x; }),
minmaxY = std::minmax_element(pins.begin(), pins.end(), [](point<int_t> a, point<int_t> b){ return a.y < b.y; });
return (minmaxX.second->x - minmaxX.first->x) + (minmaxY.second->y - minmaxY.first->y);
}
else{
return 0;
}
}
else{
std::vector<point<int_t> > points = pins;
std::sort(points.begin(), points.end(), [](point<int_t> a , point<int_t> b){return a.x < b.x; });
if(points.size() <= exactitude_limit){
switch(points.size()){
case 4:
return get_wirelength_from_sorted<4, 2>(points, steiner_lookup::topologies_4);
case 5:
return get_wirelength_from_sorted<5, 6>(points, steiner_lookup::topologies_5);
case 6:
return get_wirelength_from_sorted<6, 23>(points, steiner_lookup::topologies_6);
case 7:
return get_wirelength_from_sorted<7, 111>(points, steiner_lookup::topologies_7);
case 8:
return get_wirelength_from_sorted<8, 642>(points, steiner_lookup::topologies_8);
case 9:
return get_wirelength_from_sorted<9, 4334>(points, steiner_lookup::topologies_9);
case 10:
return get_wirelength_from_sorted<10, 33510>(points, steiner_lookup::topologies_10);
default:
abort();
}
}
else{ // Need to create the full topology, then calculate the length back
//return MST_length(points);
auto horizontal_topology = get_big_horizontal_topology_from_sorted(points, exactitude_limit);
return get_wirelength_from_topo(points, horizontal_topology);
}
}
}
point<std::vector<std::pair<index_t, index_t> > > get_RSMT_topology(std::vector<point<int_t> > const & pins, index_t exactitude_limit){
assert(exactitude_limit <= 10 and exactitude_limit >= 3);
// For 3 pin and fewer, the topology is very simple
if(pins.size() <= 2){
if(pins.size() == 2){
auto ret = std::vector<edge_t>(1, edge_t(0, 1));
return point<std::vector<edge_t> >(ret, ret);
}
else{
return point<std::vector<edge_t> >();
}
}
else if(pins.size() == 3){
std::vector<indexed_pt> ipoints(pins.size());
for(index_t i=0; i<pins.size(); ++i){
ipoints[i] = indexed_pt(pins[i], i);
}
auto xpoints=ipoints;
std::sort(xpoints.begin(), xpoints.end(), [](indexed_pt a , indexed_pt b){return a.x < b.x; });
auto ypoints=ipoints;
std::sort(ypoints.begin(), ypoints.end(), [](indexed_pt a , indexed_pt b){return a.y < b.y; });
return point<std::vector<edge_t> >{{{xpoints[0].index, xpoints[1].index}, {xpoints[1].index, xpoints[2].index}}, {{ypoints[0].index, ypoints[1].index}, {ypoints[1].index, ypoints[2].index}}};
}
else{
std::vector<edge_t> horizontal_topology = get_RSMT_horizontal_topology(pins, exactitude_limit);
return point<std::vector<edge_t> >(horizontal_topology, get_vertical_topology(pins, horizontal_topology));
}
}
} // Namespace coloquinte

View File

@ -21,6 +21,7 @@
setup_sysconfdir("${CMAKE_INSTALL_PREFIX}")
setup_boost(program_options)
setup_qt()
setup_python()
cmake_policy(SET CMP0054 NEW)
@ -28,7 +29,6 @@
find_package(Libbfd)
endif()
find_package(BZip2 REQUIRED)
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
find_package(PythonSitePackages REQUIRED)
find_package(BISON REQUIRED)
find_package(FLEX REQUIRED)

View File

@ -19,36 +19,36 @@ import coriolis.Cfg as Cfg
param = Cfg.getParamDouble( 'etesian.aspectRatio' )
param.setDouble( 1.0 )
Cfg.getParamDouble ( 'etesian.spaceMargin' ).setPercentage( 0.05 )
Cfg.getParamBool ( 'etesian.uniformDensity' ).setBool ( False )
Cfg.getParamBool ( 'etesian.routingDriven' ).setBool ( False )
Cfg.getParamString ( 'etesian.feedNames' ).setString ( 'tie_x0,rowend_x0' )
Cfg.getParamString ( 'etesian.cell.zero' ).setString ( 'zero_x0' )
Cfg.getParamString ( 'etesian.cell.one' ).setString ( 'one_x0' )
Cfg.getParamString ( 'etesian.bloat' ).setString ( 'disabled' )
Cfg.getParamDouble ( 'etesian.spaceMargin' ).setPercentage( 0.05 )
Cfg.getParamDouble ( 'etesian.densityVariation' ).setPercentage( 0.05 )
Cfg.getParamBool ( 'etesian.routingDriven' ).setBool ( False )
Cfg.getParamString ( 'etesian.feedNames' ).setString ( 'tie_x0,rowend_x0' )
Cfg.getParamString ( 'etesian.cell.zero' ).setString ( 'zero_x0' )
Cfg.getParamString ( 'etesian.cell.one' ).setString ( 'one_x0' )
Cfg.getParamString ( 'etesian.bloat' ).setString ( 'disabled' )
param = Cfg.getParamEnumerate( 'etesian.effort' )
param.setInt( 2 )
param.addValue( 'Fast' , 1 )
param.addValue( 'Standard', 2 )
param.addValue( 'High' , 3 )
param.addValue( 'Extreme' , 4 )
param.addValue( 'Standard', 3 )
param.addValue( 'High' , 6 )
param.addValue( 'Extreme' , 9 )
param = Cfg.getParamEnumerate( 'etesian.graphics' )
param.setInt( 2 )
param.setInt( 3 )
param.addValue( 'Show every step' , 1 )
param.addValue( 'Show lower bound', 2 )
param.addValue( 'Show result only', 3 )
layout = Cfg.Configuration.get().getLayout()
layout.addTab ( 'Etesian', 'etesian' )
layout.addTitle ( 'Etesian', 'Placement area' )
layout.addParameter( 'Etesian', 'etesian.aspectRatio' , 'Aspect Ratio, X/Y (%)', 0 )
layout.addParameter( 'Etesian', 'etesian.spaceMargin' , 'Space Margin' , 1 )
layout.addRule ( 'Etesian' )
layout.addTitle ( 'Etesian', 'Etesian - Placer')
layout.addParameter( 'Etesian', 'etesian.uniformDensity', 'Uniform density' , 0 )
layout.addParameter( 'Etesian', 'etesian.routingDriven' , 'Routing driven' , 0 )
layout.addParameter( 'Etesian', 'etesian.effort' , 'Placement effort' , 1 )
layout.addParameter( 'Etesian', 'etesian.graphics' , 'Placement view' , 1 )
layout.addRule ( 'Etesian' )
layout.addTab ( 'Placer', 'etesian' )
layout.addTitle ( 'Placer', 'Placement area' )
layout.addParameter( 'Placer', 'etesian.aspectRatio' , 'Aspect Ratio, X/Y' , 0 )
layout.addParameter( 'Placer', 'etesian.spaceMargin' , 'Space Margin' , 1 )
layout.addRule ( 'Placer' )
layout.addTitle ( 'Placer', 'Etesian - Placer')
layout.addParameter( 'Placer', 'etesian.densityVariation' , 'Density variation' , 0 )
layout.addParameter( 'Placer', 'etesian.routingDriven' , 'Routing driven' , 0 )
layout.addParameter( 'Placer', 'etesian.effort' , 'Placement effort' , 1 )
layout.addParameter( 'Placer', 'etesian.graphics' , 'Placement view' , 1 )
layout.addRule ( 'Placer' )

View File

@ -19,22 +19,22 @@ import coriolis.Cfg as Cfg
layout = Cfg.Configuration.get().getLayout()
# Kite Layout.
layout.addTab ( 'Kite', 'kite' )
layout.addTitle ( 'Kite', 'Katabatic - Routing Database' )
layout.addParameter( 'Kite', 'katabatic.saturateRatio' , 'Saturate Ratio (%)' , 0, 1 )
layout.addParameter( 'Kite', 'katabatic.saturateRp' , 'Saturate RoutingPad' , 0, 1 )
layout.addParameter( 'Kite', 'katabatic.globalLengthThreshold', 'Global Length Threshold', 0, 1 )
layout.addParameter( 'Kite', 'katabatic.topRoutingLayer' , 'Top Routing Layer' , 0, 1 )
layout.addParameter( 'Kite', 'anabatic.gcell.displayMode' , 'GCell Display Mode' , 1, 1 )
layout.addRule ( 'Kite' )
layout.addTitle ( 'Kite', 'Kite - Detailed Router' )
layout.addParameter( 'Kite', 'kite.hTracksReservedLocal', 'Vert. Locally Reserved Tracks', 0 )
layout.addParameter( 'Kite', 'kite.vTracksReservedLocal', 'Hor. Locally Reserved Tracks' , 0 )
layout.addParameter( 'Kite', 'kite.eventsLimit' , 'Events Limit' , 0 )
layout.addParameter( 'Kite', 'kite.ripupCost' , 'Ripup Cost' , 1, 1, Cfg.Parameter.Flags.UseSpinBox )
layout.addSection ( 'Kite', 'Ripup Limits', 1 )
layout.addParameter( 'Kite', 'kite.strapRipupLimit' , 'Straps' , 1, 1, Cfg.Parameter.Flags.UseSpinBox )
layout.addParameter( 'Kite', 'kite.localRipupLimit' , 'Locals' , 1, 1, Cfg.Parameter.Flags.UseSpinBox )
layout.addParameter( 'Kite', 'kite.globalRipupLimit' , 'Globals' , 1, 1, Cfg.Parameter.Flags.UseSpinBox )
layout.addParameter( 'Kite', 'kite.longGlobalRipupLimit', 'Long Globals', 1, 1, Cfg.Parameter.Flags.UseSpinBox )
layout.addRule ( 'Kite' )
layout.addTab ( 'Router', 'kite' )
layout.addTitle ( 'Router', 'Katabatic - Routing Database' )
layout.addParameter( 'Router', 'katabatic.saturateRatio' , 'Saturate Ratio (%)' , 0, 1 )
layout.addParameter( 'Router', 'katabatic.saturateRp' , 'Saturate RoutingPad' , 0, 1 )
layout.addParameter( 'Router', 'katabatic.globalLengthThreshold', 'Global Length Threshold', 0, 1 )
layout.addParameter( 'Router', 'katabatic.topRoutingLayer' , 'Top Routing Layer' , 0, 1 )
layout.addParameter( 'Router', 'anabatic.gcell.displayMode' , 'GCell Display Mode' , 1, 1 )
layout.addRule ( 'Router' )
layout.addTitle ( 'Router', 'Kite - Detailed Router' )
layout.addParameter( 'Router', 'kite.hTracksReservedLocal', 'Vert. Locally Reserved Tracks', 0 )
layout.addParameter( 'Router', 'kite.vTracksReservedLocal', 'Hor. Locally Reserved Tracks' , 0 )
layout.addParameter( 'Router', 'kite.eventsLimit' , 'Events Limit' , 0 )
layout.addParameter( 'Router', 'kite.ripupCost' , 'Ripup Cost' , 1, 1, Cfg.Parameter.Flags.UseSpinBox )
layout.addSection ( 'Router', 'Ripup Limits', 1 )
layout.addParameter( 'Router', 'kite.strapRipupLimit' , 'Straps' , 1, 1, Cfg.Parameter.Flags.UseSpinBox )
layout.addParameter( 'Router', 'kite.localRipupLimit' , 'Locals' , 1, 1, Cfg.Parameter.Flags.UseSpinBox )
layout.addParameter( 'Router', 'kite.globalRipupLimit' , 'Globals' , 1, 1, Cfg.Parameter.Flags.UseSpinBox )
layout.addParameter( 'Router', 'kite.longGlobalRipupLimit', 'Long Globals', 1, 1, Cfg.Parameter.Flags.UseSpinBox )
layout.addRule ( 'Router' )

View File

@ -85,19 +85,19 @@ param.addValue( "Custom" , 30 )
param.setInt ( 0 )
layout = Cfg.Configuration.get().getLayout()
layout.addTab ( 'misc', 'Misc.' )
layout.addTitle ( 'misc', 'Miscellaneous' )
layout.addParameter( 'misc', 'misc.catchCore' , 'Catch Core Dumps' , 1 )
layout.addParameter( 'misc', 'misc.verboseLevel1' , 'Verbose' , 0 )
layout.addParameter( 'misc', 'misc.verboseLevel2' , 'Very Verbose' , 0 )
layout.addParameter( 'misc', 'misc.info' , 'Show Info' , 0 )
layout.addParameter( 'misc', 'misc.logMode' , 'Output is a TTY' , 0 )
layout.addParameter( 'misc', 'misc.minTraceLevel' , 'Min. Trace Level' , 1 )
layout.addParameter( 'misc', 'misc.maxTraceLevel' , 'Max. Trace Level' , 1 )
layout.addTitle ( 'misc', 'Print/Snapshot Parameters' )
layout.addParameter( 'misc', 'viewer.printer.mode' , 'Printer/Snapshot Mode', 1 )
layout.addParameter( 'misc', 'viewer.printer.paper' , 'Paper Size' , 0 )
layout.addParameter( 'misc', 'viewer.printer.orientation', 'Orientation' , 0 )
layout.addParameter( 'misc', 'viewer.printer.DPI' , 'DPI' , 0 )
layout.addTab ( 'Misc', 'Misc.' )
layout.addTitle ( 'Misc', 'Miscellaneous' )
layout.addParameter( 'Misc', 'misc.catchCore' , 'Catch Core Dumps' , 1 )
layout.addParameter( 'Misc', 'misc.verboseLevel1' , 'Verbose' , 0 )
layout.addParameter( 'Misc', 'misc.verboseLevel2' , 'Very Verbose' , 0 )
layout.addParameter( 'Misc', 'misc.info' , 'Show Info' , 0 )
layout.addParameter( 'Misc', 'misc.logMode' , 'Output is a TTY' , 0 )
layout.addParameter( 'Misc', 'misc.minTraceLevel' , 'Min. Trace Level' , 1 )
layout.addParameter( 'Misc', 'misc.maxTraceLevel' , 'Max. Trace Level' , 1 )
layout.addTitle ( 'Misc', 'Print/Snapshot Parameters' )
layout.addParameter( 'Misc', 'viewer.printer.mode' , 'Printer/Snapshot Mode', 1 )
layout.addParameter( 'Misc', 'viewer.printer.paper' , 'Paper Size' , 0 )
layout.addParameter( 'Misc', 'viewer.printer.orientation', 'Orientation' , 0 )
layout.addParameter( 'Misc', 'viewer.printer.DPI' , 'DPI' , 0 )

View File

@ -16,8 +16,8 @@
import coriolis.Cfg as Cfg
layout = Cfg.Configuration.get().getLayout()
layout.addTab ( 'stratus1', 'Stratus1' )
layout.addTitle ( 'stratus1', 'Stratus1 - Netlist & Layout Capture' )
layout.addParameter( 'stratus1', 'stratus1.mappingName', 'Virtual Library Translation', 0, 2 )
layout.addParameter( 'stratus1', 'stratus1.format' , 'Netlist Format (vst, vhd)' , 0, 2 )
layout.addParameter( 'stratus1', 'stratus1.simulator' , 'Simulator' , 0, 2 )
layout.addTab ( 'Netlist', 'Stratus1' )
layout.addTitle ( 'Netlist', 'Stratus1 - Netlist & Layout Capture' )
layout.addParameter( 'Netlist', 'stratus1.mappingName', 'Virtual Library Translation', 0, 2 )
layout.addParameter( 'Netlist', 'stratus1.format' , 'Netlist Format (vst, vhd)' , 0, 2 )
layout.addParameter( 'Netlist', 'stratus1.simulator' , 'Simulator' , 0, 2 )

View File

@ -0,0 +1,327 @@
import sys
import os.path
from coriolis import Cfg
from coriolis.Hurricane import Technology, DataBase, DbU, Library, Layer, \
BasicLayer, Cell, Net, Horizontal, Vertical, \
Rectilinear, Box, Point, Instance, Transformation, \
NetExternalComponents, Pad
import coriolis.Viewer
from coriolis.CRL import AllianceFramework, Gds, LefImport, CellGauge, \
RoutingGauge, RoutingLayerGauge
from coriolis.helpers import l, u, n, overlay, io, ndaTopDir
from coriolis.helpers.overlay import CfgCache, UpdateSession
from coriolis.Anabatic import StyleFlags
__all__ = [ "setup" ]
def _routing ():
"""
Define the routing gauge along with the various P&R tool parameters.
"""
af = AllianceFramework.get()
db = DataBase.getDB()
tech = db.getTechnology()
rg = RoutingGauge.create('mcu9t5v0')
rg.setSymbolic( False )
rg.addLayerGauge(
RoutingLayerGauge.create( tech.getLayer( 'Metal1' ) # metal
, RoutingLayerGauge.Horizontal # preferred routing direction
, RoutingLayerGauge.PinOnly # layer usage
, 0 # depth
, 0.0 # density (deprecated)
, u(0.0) # track offset from AB
, u(0.56) # track pitch
, u(0.23) # wire width
, u(0.23) # perpandicular wire width
, u(0.26) # VIA side
, u(0.0 ) )) # obstacle dW
rg.addLayerGauge(
RoutingLayerGauge.create( tech.getLayer( 'Metal2' ) # metal
, RoutingLayerGauge.Vertical # preferred routing direction
, RoutingLayerGauge.Default # layer usage
, 1 # depth
, 0.0 # density (deprecated)
, u(0.0) # track offset from AB
, u(0.56) # track pitch
, u(0.28) # wire width
, u(0.28) # perpandicular wire width
, u(0.26) # VIA side
, u(0.0 ) )) # obstacle dW
rg.addLayerGauge(
RoutingLayerGauge.create( tech.getLayer( 'Metal3' ) # metal
, RoutingLayerGauge.Horizontal # preferred routing direction
, RoutingLayerGauge.Default # layer usage
, 2 # depth
, 0.0 # density (deprecated)
, u(0.0) # track offset from AB
, u(0.56) # track pitch
, u(0.28) # wire width
, u(0.28) # perpandicular wire width
, u(0.26) # VIA side
, u(0.0 ) )) # obstacle dW
rg.addLayerGauge(
RoutingLayerGauge.create( tech.getLayer( 'Metal4' ) # metal
, RoutingLayerGauge.Vertical # preferred routing direction
, RoutingLayerGauge.Default # layer usage
, 3 # depth
, 0.0 # density (deprecated)
, u(0.0) # track offset from AB
, u(0.56) # track pitch
, u(0.28) # wire width
, u(0.28) # perpandicular wire width
, u(0.26) # VIA side
, u(0.0 ) )) # obstacle dW
rg.addLayerGauge(
RoutingLayerGauge.create( tech.getLayer( 'Metal5' ) # metal
, RoutingLayerGauge.Horizontal # preferred routing direction
, RoutingLayerGauge.Default # layer usage
, 4 # depth
, 0.0 # density (deprecated)
, u(0.0) # track offset from AB
, u(0.56) # track pitch
, u(0.28) # wire width
, u(0.28) # perpandicular wire width
, u(0.26) # VIA side
, u(0.0 ) )) # obstacle dW
rg.addLayerGauge(
RoutingLayerGauge.create( tech.getLayer( 'MetalTop' ) # metal
, RoutingLayerGauge.Vertical # preferred routing direction
, RoutingLayerGauge.PowerSupply # layer usage
, 5 # depth
, 0.0 # density (deprecated)
, u(0.0) # track offset from AB
, u(0.9) # track pitch
, u(0.44) # wire width
, u(0.44) # perpandicular wire width
, u(0.26) # VIA side
, u(0.0 ) )) # obstacle dW
af.addRoutingGauge( rg )
af.setRoutingGauge( 'mcu9t5v0' )
cg = CellGauge.create( 'LEF.GF018hv5v_green_sc9'
, 'Metal1' # pin layer name.
, u( 0.56 ) # pitch.
, u( 5.04) # cell slice height.
, u( 0.56) # cell slice step.
)
af.addCellGauge( cg )
af.setCellGauge( 'LEF.GF018hv5v_green_sc9' )
with CfgCache(priority=Cfg.Parameter.Priority.ConfigurationFile) as cfg:
env = af.getEnvironment()
env.setRegister( '.*__dff.*' )
# Place & Route setup
cfg.viewer.minimumSize = 500
cfg.viewer.pixelThreshold = 2
cfg.lefImport.minTerminalWidth = 0.0
cfg.crlcore.groundName = 'vss'
cfg.crlcore.powerName = 'vdd'
cfg.etesian.bloat = 'disabled'
cfg.etesian.aspectRatio = 1.00
cfg.etesian.aspectRatio = [10, 1000]
cfg.etesian.spaceMargin = 0.10
cfg.etesian.uniformDensity = True
cfg.etesian.routingDriven = False
cfg.etesian.latchUpDistance = u(30.0 - 1.0)
#cfg.etesian.diodeName = 'diode'
#cfg.etesian.antennaInsertThreshold = 0.50
#cfg.etesian.antennaMaxWL = u(250.0)
cfg.etesian.feedNames = 'gf180mcu_fd_sc_mcu9t5v0__fill_1,gf180mcu_fd_sc_mcu9t5v0__fill_2,gf180mcu_fd_sc_mcu9t5v0__fill_4,gf180mcu_fd_sc_mcu9t5v0__fill_8'
cfg.etesian.defaultFeed = 'fill_2'
cfg.etesian.cell.zero = 'gf180mcu_fd_sc_mcu9t5v0__tieh'
cfg.etesian.cell.one = 'gf180mcu_fd_sc_mcu9t5v0__tiel'
cfg.etesian.effort = 2
cfg.etesian.effort = (
('Fast', 1),
('Standard', 2),
('High', 3 ),
('Extreme', 4 ),
)
cfg.etesian.graphics = 2
cfg.etesian.graphics = (
('Show every step', 1),
('Show lower bound', 2),
('Show result only', 3),
)
cfg.anabatic.routingGauge = 'mcu9t5v0'
cfg.anabatic.cellGauge = 'LEF.GF018hv5v_green_sc9'
cfg.anabatic.globalLengthThreshold = 1450
cfg.anabatic.saturateRatio = 0.90
cfg.anabatic.saturateRp = 10
#cfg.anabatic.topRoutingLayer = 'mt2'
cfg.anabatic.edgeLength = 192
cfg.anabatic.edgeWidth = 32
cfg.anabatic.edgeCostH = 9.0
cfg.anabatic.edgeCostK = -10.0
cfg.anabatic.edgeHInc = 1.0
cfg.anabatic.edgeHScaling = 1.0
cfg.anabatic.globalIterations = 10
cfg.anabatic.globalIterations = [ 1, 100 ]
cfg.anabatic.gcell.displayMode = 1
cfg.anabatic.gcell.displayMode = (("Boundary", 1), ("Density", 2))
cfg.anabatic.netBuilderStyle = 'VH,3RL+'
cfg.anabatic.routingStyle = StyleFlags.VH
cfg.katana.disableStackedVias = False
cfg.katana.hTracksReservedLocal = 4
cfg.katana.hTracksReservedLocal = [0, 20]
cfg.katana.vTracksReservedLocal = 3
cfg.katana.vTracksReservedLocal = [0, 20]
cfg.katana.termSatReservedLocal = 8
cfg.katana.termSatThreshold = 9
cfg.katana.eventsLimit = 4000002
cfg.katana.ripupCost = 3
cfg.katana.ripupCost = [0, None]
cfg.katana.strapRipupLimit = 16
cfg.katana.strapRipupLimit = [1, None]
cfg.katana.localRipupLimit = 9
cfg.katana.localRipupLimit = [1, None]
cfg.katana.globalRipupLimit = 5
cfg.katana.globalRipupLimit = [1, None]
cfg.katana.longGlobalRipupLimit = 5
cfg.chip.padCoreSide = 'South'
# Plugins setup
cfg.clockTree.minimumSide = u(5.04) * 6
cfg.clockTree.buffer = 'gf180mcu_fd_sc_mcu9t5v0__clkbuf_2'
cfg.clockTree.placerEngine = 'Etesian'
cfg.block.spareSide = 10
cfg.spares.buffer = 'gf180mcu_fd_sc_mcu9t5v0__clkbuf_2'
cfg.spares.maxSinks = 20
def _loadStdLib ( cellsTop ):
"""
Load the muc9t5v0 library from the GDS files.
:param cellsTop: The top directory containing the cells views.
As GDS file is lacking most of the interface informations, apply a
post-process on each cell to educated guess :
* Which nets are external, and in which direction (name matching).
* Blockages: any shape in internals nets in Metal1 or Metal2 layer.
"""
useGds = False
af = AllianceFramework.get()
db = DataBase.getDB()
tech = db.getTechnology()
rootlib = db.getRootLibrary()
cellLib = Library.create(rootlib, 'mcu9t5v')
af.wrapLibrary( cellLib, 0 )
gaugeName = Cfg.getParamString('anabatic.routingGauge').asString()
routingGauge = af.getRoutingGauge( gaugeName )
metal1 = DataBase.getDB().getTechnology().getLayer( 'Metal1' )
metal2 = DataBase.getDB().getTechnology().getLayer( 'Metal2' )
blockage1 = metal1.getBlockageLayer()
blockage2 = metal2.getBlockageLayer()
hpitch = 0
for layerGauge in routingGauge.getLayerGauges():
if layerGauge.getType() == RoutingLayerGauge.PinOnly:
continue
if layerGauge.getDirection() == RoutingLayerGauge.Horizontal:
hpitch = layerGauge.getPitch()
break
if useGds:
io.vprint( 1, ' o Setup GF 180 mcu9t5v library in {} [GDS].'.format( cellLib.getName() ))
io.vprint( 2, ' (__file__="{}")'.format( os.path.abspath( __file__ )))
for cellDir in cellsTop.iterdir():
for gdsFile in sorted(cellDir.glob('*.gds')):
Gds.load( cellLib
, gdsFile.as_posix()
, Gds.NoGdsPrefix|Gds.Layer_0_IsBoundary )
#io.vprint( 1, ' o Skrinking V-AB of {}'.format(DbU.getValueString( hpitch )))
with overlay.UpdateSession():
for cell in cellLib.getCells():
ab = cell.getAbutmentBox()
#ab.inflate( 0, -hpitch )
cell.setAbutmentBox( ab )
cell.setTerminalNetlist( True )
for net in cell.getNets():
if not net.isExternal():
blockages = []
for component in net.getComponents():
if component.getLayer() == metal1 or component.getLayer() == metal1:
blockages.append( component )
if blockages:
io.vprint( 2, ' - Obstacles found in {}'.format( cell ))
for component in blockages:
bb = component.getBoundingBox()
if component.getLayer() == metal1:
v = Vertical.create( net
, blockage1
, bb.getXCenter()
, bb.getWidth()
, bb.getYMin()
, bb.getYMax() )
if component.getLayer() == metal2:
h = Horizontal.create( net
, blockage2
, bb.getYCenter()
, bb.getHeight()
, bb.getXMin()
, bb.getXMax() )
continue
if net.isPower() or net.getName() == 'VDD':
net.setName( 'VDD' )
net.setType( Net.Type.POWER )
net.setGlobal( True )
net.setDirection( Net.Direction.IN )
continue
if net.isGround() or net.getName() == 'VSS':
net.setName( 'VSS' )
net.setType( Net.Type.GROUND )
net.setGlobal( True )
net.setDirection( Net.Direction.IN )
continue
if net.getName() == 'Z' \
or net.getName() == 'ZN' \
or net.getName() == 'Q':
net.setDirection( Net.Direction.OUT )
else:
net.setDirection( Net.Direction.IN )
toDestroy = []
for component in NetExternalComponents.get(net):
if isinstance(component,Pad):
bb = component.getBoundingBox()
pad = Vertical.create( net
, component.getLayer()
, bb.getCenter().getX()
, bb.getWidth()
, bb.getYMin()
, bb.getYMax() )
NetExternalComponents.setExternal( pad )
toDestroy.append( component )
for component in toDestroy:
component.destroy()
else:
io.vprint( 1, ' o Setup GF 180 mcu9t5v library in {} [LEF].'.format( cellLib.getName() ))
io.vprint( 2, ' (__file__="{}")'.format( os.path.abspath( __file__ )))
LefImport.load( (cellsTop / '..' / 'tech' / 'gf180mcu_6LM_1TM_9K_9t_tech.lef').as_posix() )
LefImport.setMergeLibrary( cellLib )
for cellDir in cellsTop.iterdir():
for lefFile in sorted(cellDir.glob('*.lef')):
LefImport.load( lefFile.as_posix() )
af.wrapLibrary( cellLib, 1 )
return cellLib
def _loadIoLib ():
"""
Load the IO library from the GDS files.
"""
af = AllianceFramework.get()
ioLib = af.getLibrary( 1 )
io.vprint( 1, ' o Loading GDS library in "{}".'.format( ioLib.getName() ))
Gds.load( ioLib
, ndaTopDir + '/XXXX.gds'
, Gds.NoGdsPrefix )
def setup ( cellsTop ):
_routing()
_loadStdLib( cellsTop )
#_loadIoLib()

View File

@ -0,0 +1,318 @@
import sys
import os.path
from coriolis import Cfg, Hurricane, Viewer, CRL
from coriolis.Hurricane import Technology, DataBase, DbU, Library, Layer, \
BasicLayer, Cell, Net, Horizontal, Vertical, \
Rectilinear, Box, Point, NetExternalComponents
from coriolis.technos.common.colors import toRGB
from coriolis.technos.common.patterns import toHexa
from coriolis.helpers import l, u, trace, io
from coriolis.helpers.technology import createBL, createVia, setEnclosures
from coriolis.helpers.overlay import CfgCache
__all__ = [ 'setup' ]
def _setup_techno():
io.vprint( 1, ' o Setup GF180MCU technology.' )
io.vprint( 2, ' (__file__="{}")'.format( os.path.abspath( __file__ )))
db = DataBase.create()
CRL.System.get()
tech = Technology.create( db, 'GF180MCU' )
DbU.setPrecision( 2 )
DbU.setPhysicalsPerGrid( 0.005, DbU.UnitPowerMicro )
with CfgCache(priority=Cfg.Parameter.Priority.ConfigurationFile) as cfg:
cfg.gdsDriver.metricDbu = 1e-09
cfg.gdsDriver.dbuPerUu = 0.001
DbU.setGridsPerLambda ( 10 )
DbU.setSymbolicSnapGridStep( DbU.fromGrid( 1.0 ))
DbU.setPolygonStep ( DbU.fromGrid( 1.0 ))
DbU.setStringMode ( DbU.StringModePhysical, DbU.UnitPowerMicro )
Nwell = createBL( tech, 'Nwell' , BasicLayer.Material.nWell , size=u(0.86), spacing=u(0.74), gds2Layer=21 )
LVPwell = createBL( tech, 'LVPwell' , BasicLayer.Material.pWell , size=u(0.74), spacing=u(1.7 ), gds2Layer=204 )
Nplus = createBL( tech, 'Nplus' , BasicLayer.Material.nImplant , size=u(0.4 ), spacing=u(0.4 ), gds2Layer=32 )
Pplus = createBL( tech, 'Pplus' , BasicLayer.Material.pImplant , size=u(0.4 ), spacing=u(0.4 ), gds2Layer=31 )
COMP = createBL( tech, 'COMP' , BasicLayer.Material.active , size=u(0.3 ), spacing=u(0.36), gds2Layer=22 )
Poly2 = createBL( tech, 'Poly2' , BasicLayer.Material.poly , size=u(0.2 ), spacing=u(0.24), gds2Layer=30 )
Cont = createBL( tech, 'Contact' , BasicLayer.Material.cut , size=u(0.22), spacing=u(0.25), gds2Layer=33 )
Metal1 = createBL( tech, 'Metal1' , BasicLayer.Material.metal , size=u(0.23), spacing=u(0.23), gds2Layer=34 )
Via1 = createBL( tech, 'Via1' , BasicLayer.Material.cut , size=u(0.26), spacing=u(0.26), gds2Layer=35 )
Metal2 = createBL( tech, 'Metal2' , BasicLayer.Material.metal , size=u(0.28), spacing=u(0.28), gds2Layer=36 )
Via2 = createBL( tech, 'Via2' , BasicLayer.Material.cut , size=u(0.26), spacing=u(0.26), gds2Layer=38 )
Metal3 = createBL( tech, 'Metal3' , BasicLayer.Material.metal , size=u(0.28), spacing=u(0.28), gds2Layer=42 )
Via3 = createBL( tech, 'Via3' , BasicLayer.Material.cut , size=u(0.26), spacing=u(0.26), gds2Layer=40 )
Metal4 = createBL( tech, 'Metal4' , BasicLayer.Material.metal , size=u(0.28), spacing=u(0.28), gds2Layer=46 )
Via4 = createBL( tech, 'Via4' , BasicLayer.Material.cut , size=u(0.26), spacing=u(0.26), gds2Layer=41 )
Metal5 = createBL( tech, 'Metal5' , BasicLayer.Material.metal , size=u(0.28), spacing=u(0.28), gds2Layer=81 )
Via5 = createBL( tech, 'Via5' , BasicLayer.Material.cut , size=u(0.26), spacing=u(0.26), gds2Layer=82 )
MetalTop = createBL( tech, 'MetalTop', BasicLayer.Material.metal , size=u(0.36), spacing=u(0.38), gds2Layer=53 )
Poly2_Dummy = createBL( tech, 'Poly2_Dummy' , BasicLayer.Material.poly , gds2Layer=30, gds2DataType=4 )
Metal1_Dummy = createBL( tech, 'Metal1_Dummy' , BasicLayer.Material.metal, gds2Layer=34, gds2DataType=4 )
Metal2_Dummy = createBL( tech, 'Metal2_Dummy' , BasicLayer.Material.metal, gds2Layer=36, gds2DataType=4 )
Metal3_Dummy = createBL( tech, 'Metal3_Dummy' , BasicLayer.Material.metal, gds2Layer=42, gds2DataType=4 )
Metal4_Dummy = createBL( tech, 'Metal4_Dummy' , BasicLayer.Material.metal, gds2Layer=46, gds2DataType=4 )
Metal5_Dummy = createBL( tech, 'Metal5_Dummy' , BasicLayer.Material.metal, gds2Layer=81, gds2DataType=4 )
MetalTop_Dummy = createBL( tech, 'MetalTop_Dummy', BasicLayer.Material.metal, gds2Layer=53, gds2DataType=4 )
Poly2_Label = createBL( tech, 'Poly2_Label' , BasicLayer.Material.info, gds2Layer=30, gds2DataType=10 )
Metal1_Label = createBL( tech, 'Metal1_Label' , BasicLayer.Material.info, gds2Layer=34, gds2DataType=10 )
Metal2_Label = createBL( tech, 'Metal2_Label' , BasicLayer.Material.info, gds2Layer=36, gds2DataType=10 )
Metal3_Label = createBL( tech, 'Metal3_Label' , BasicLayer.Material.info, gds2Layer=42, gds2DataType=10 )
Metal4_Label = createBL( tech, 'Metal4_Label' , BasicLayer.Material.info, gds2Layer=46, gds2DataType=10 )
Metal5_Label = createBL( tech, 'Metal5_Label' , BasicLayer.Material.info, gds2Layer=81, gds2DataType=10 )
MetalTop_Label = createBL( tech, 'MetalTop_Label', BasicLayer.Material.info, gds2Layer=53, gds2DataType=10 )
Metal1_BLK = createBL( tech, 'Metal1_BLK' , BasicLayer.Material.blockage, gds2Layer=34, gds2DataType=5 )
Metal2_BLK = createBL( tech, 'Metal2_BLK' , BasicLayer.Material.blockage, gds2Layer=36, gds2DataType=5 )
Metal3_BLK = createBL( tech, 'Metal3_BLK' , BasicLayer.Material.blockage, gds2Layer=42, gds2DataType=5 )
Metal4_BLK = createBL( tech, 'Metal4_BLK' , BasicLayer.Material.blockage, gds2Layer=46, gds2DataType=5 )
Metal5_BLK = createBL( tech, 'Metal5_BLK' , BasicLayer.Material.blockage, gds2Layer=81, gds2DataType=5 )
MetalTop_BLK = createBL( tech, 'MetalTop_BLK', BasicLayer.Material.blockage, gds2Layer=53, gds2DataType=5 )
CONT = createVia( tech, 'CONT_POLY2', 'Poly2', 'Contact', 'Metal1', u(0.22) )
setEnclosures( CONT, Poly2 , u(0.07) )
setEnclosures( CONT, Metal1, u(0.12) )
VIA12 = createVia( tech, 'VIA12', 'Metal1', 'Via1', 'Metal2', u(0.26) )
setEnclosures( VIA12, Metal1, (u(0.06), u(0.00)) )
setEnclosures( VIA12, Metal2, (u(0.06), u(0.01)) )
VIA23 = createVia( tech, 'VIA23', 'Metal2', 'Via2', 'Metal3', u(0.26) )
setEnclosures( VIA23, Metal2, (u(0.06), u(0.01)) )
setEnclosures( VIA23, Metal3, (u(0.01), u(0.06)) )
VIA34 = createVia( tech, 'VIA34', 'Metal3', 'Via3', 'Metal4', u(0.26) )
setEnclosures( VIA34, Metal3, (u(0.01), u(0.06)) )
setEnclosures( VIA34, Metal4, (u(0.06), u(0.01)) )
VIA45 = createVia( tech, 'VIA45', 'Metal4', 'Via4', 'Metal5', u(0.26) )
setEnclosures( VIA45, Metal4, (u(0.06), u(0.01)) )
setEnclosures( VIA45, Metal5, (u(0.01), u(0.06)) )
VIA5T = createVia( tech, 'VIA5T', 'Metal5', 'Via5', 'MetalTop', u(0.26) )
setEnclosures( VIA5T, Metal5 , (u(0.01), u(0.06)) )
setEnclosures( VIA5T, MetalTop, (u(0.06), u(0.01)) )
Border = createBL( tech, 'Border', BasicLayer.Material.other, gds2Layer=63 )
Metal1 .setBlockageLayer( Metal1_BLK )
Metal2 .setBlockageLayer( Metal2_BLK )
Metal3 .setBlockageLayer( Metal3_BLK )
Metal4 .setBlockageLayer( Metal4_BLK )
Metal5 .setBlockageLayer( Metal5_BLK )
MetalTop.setBlockageLayer( MetalTop_BLK )
# Coriolis internal layers
createBL( tech, 'text.cell' , BasicLayer.Material.other )
createBL( tech, 'text.instance', BasicLayer.Material.other )
createBL( tech, 'SPL1' , BasicLayer.Material.other )
createBL( tech, 'AutoLayer' , BasicLayer.Material.other )
createBL( tech, 'gmetalh' , BasicLayer.Material.metal )
createBL( tech, 'gcontact' , BasicLayer.Material.cut )
createBL( tech, 'gmetalv' , BasicLayer.Material.metal )
def _setup_display():
# ----------------------------------------------------------------------
# Style: Coriolis [black]
threshold = 0.2 if Viewer.Graphics.isHighDpi() else 0.1
scale = 1.0
style = Viewer.DisplayStyle( 'Coriolis [black]' )
style.setDescription( 'Coriolis Look - black background' )
style.setDarkening ( Viewer.DisplayStyle.HSVr(1.0, 3.0, 2.5) )
# Viewer.
style.addDrawingStyle( group='Viewer', name='fallback' , color=toRGB('Gray238' ), border=1, pattern='55AA55AA55AA55AA' )
style.addDrawingStyle( group='Viewer', name='background' , color=toRGB('Gray50' ), border=1 )
style.addDrawingStyle( group='Viewer', name='foreground' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='rubber' , color=toRGB('192,0,192' ), border=4, threshold=0.02 )
style.addDrawingStyle( group='Viewer', name='phantom' , color=toRGB('Seashell4' ), border=1 )
style.addDrawingStyle( group='Viewer', name='boundaries' , color=toRGB('wheat1' ), border=2, pattern='0000000000000000', threshold=0 )
style.addDrawingStyle( group='Viewer', name='marker' , color=toRGB('80,250,80' ), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionDraw' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionFill' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='grid' , color=toRGB('White' ), border=1, threshold=2.0 )
style.addDrawingStyle( group='Viewer', name='spot' , color=toRGB('White' ), border=2, threshold=6.0 )
style.addDrawingStyle( group='Viewer', name='ghost' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='text.ruler' , color=toRGB('White' ), border=1, threshold= 0.0 )
style.addDrawingStyle( group='Viewer', name='text.instance' , color=toRGB('White' ), border=1, threshold=400.0 )
style.addDrawingStyle( group='Viewer', name='text.reference', color=toRGB('White' ), border=1, threshold=200.0 )
style.addDrawingStyle( group='Viewer', name='undef' , color=toRGB('Violet' ), border=0, pattern='2244118822441188' )
style.addDrawingStyle( group='Viewer', name='Border' , color=toRGB('wheat1' ), border=1, pattern='0000000000000000', threshold=0 )
# Group: Active Layer.
style.addDrawingStyle( group='Active Layer', name='Nwell' , color=toRGB('Tan' ), pattern='55AA55AA55AA55AA' , threshold=1.5 *scale )
style.addDrawingStyle( group='Active Layer', name='LVPwell' , color=toRGB('LightYellow'), pattern='55AA55AA55AA55AA' , threshold=1.50*scale )
style.addDrawingStyle( group='Active Layer', name='Nplus' , color=toRGB('LawnGreen' ), pattern='55AA55AA55AA55AA' , threshold=1.50*scale )
style.addDrawingStyle( group='Active Layer', name='Pplus' , color=toRGB('Yellow' ), pattern='55AA55AA55AA55AA' , threshold=1.50*scale )
style.addDrawingStyle( group='Active Layer', name='COMP' , color=toRGB('White' ), pattern=toHexa('antihash1.8'), threshold=1.50*scale )
style.addDrawingStyle( group='Active Layer', name='Poly2' , color=toRGB('Red' ), pattern='55AA55AA55AA55AA' , threshold=1.50*scale )
# Group: Routing Layer.
style.addDrawingStyle( group='Routing Layer', name='Metal1' , color=toRGB('Blue' ), pattern=toHexa('poids2.8' ), threshold=0.80*scale )
style.addDrawingStyle( group='Routing Layer', name='Metal2' , color=toRGB('Aqua' ), pattern=toHexa('light_antihash0.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='Metal3' , color=toRGB('LightPink'), pattern=toHexa('light_antihash1.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='Metal4' , color=toRGB('Green' ), pattern=toHexa('light_antihash2.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='Metal5' , color=toRGB('Yellow' ), pattern='1144114411441144' , threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='MetalTop', color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.02*scale )
# Group: Cuts (VIA holes).
style.addDrawingStyle( group='Cuts (VIA holes)', name='Contact', color=toRGB('0,150,150'), threshold=1.50*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='Via1' , color=toRGB('Aqua' ), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='Via2' , color=toRGB('LightPink'), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='Via3' , color=toRGB('Green' ), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='Via4' , color=toRGB('Yellow' ), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='Via5' , color=toRGB('Violet' ), threshold=0.80*scale )
# Group: Fillers.
style.addDrawingStyle( group='Fillers', name='Poly2_Dummy' , color=toRGB('Red' ), pattern='55AA55AA55AA55AA' , border=0, threshold=1.50*scale )
style.addDrawingStyle( group='Fillers', name='Metal1_Dummy' , color=toRGB('Blue' ), pattern=toHexa('poids2.8' ), border=0, threshold=0.80*scale )
style.addDrawingStyle( group='Fillers', name='Metal2_Dummy' , color=toRGB('Aqua' ), pattern=toHexa('light_antihash0.8'), border=0, threshold=0.02*scale )
style.addDrawingStyle( group='Fillers', name='Metal3_Dummy' , color=toRGB('LightPink'), pattern=toHexa('light_antihash1.8'), border=0, threshold=0.02*scale )
style.addDrawingStyle( group='Fillers', name='Metal4_Dummy' , color=toRGB('Green' ), pattern=toHexa('light_antihash2.8'), border=0, threshold=0.02*scale )
style.addDrawingStyle( group='Fillers', name='Metal5_Dummy' , color=toRGB('Yellow' ), pattern='1144114411441144' , border=0, threshold=0.02*scale )
style.addDrawingStyle( group='Fillers', name='MetalTop_Dummy', color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), border=0, threshold=0.02*scale )
# Group: Blockages.
style.addDrawingStyle( group='Blockages', name='Metal1_BLK' , color=toRGB('Blue' ), pattern='006070381c0e0703' , threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='Metal2_BLK' , color=toRGB('Aqua' ), pattern='8103060c183060c0' , threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='Metal3_BLK' , color=toRGB('LightPink'), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='Metal4_BLK' , color=toRGB('Green' ), pattern=toHexa('light_antihash2.8'), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='Metal5_BLK' , color=toRGB('Yellow' ), pattern='1144114411441144' , threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='MetalTop_BLK', color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale, border=2 )
# Group: Text.
style.addDrawingStyle( group='Text', name='Poly2_Label' , color=toRGB('Red' ), pattern='55AA55AA55AA55AA' , threshold=1.50*scale )
style.addDrawingStyle( group='Text', name='Metal1_Label' , color=toRGB('Blue' ), pattern=toHexa('poids2.8' ), threshold=0.80*scale )
style.addDrawingStyle( group='Text', name='Metal2_Label' , color=toRGB('Aqua' ), pattern=toHexa('light_antihash0.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Text', name='Metal3_Label' , color=toRGB('LightPink'), pattern=toHexa('light_antihash1.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Text', name='Metal4_Label' , color=toRGB('Green' ), pattern=toHexa('light_antihash2.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Text', name='Metal5_Label' , color=toRGB('Yellow' ), pattern='1144114411441144' , threshold=0.02*scale )
style.addDrawingStyle( group='Text', name='MetalTop_Label', color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.02*scale )
# Knick & Kite.
style.addDrawingStyle( group='Knik & Kite', name='SPL1' , color=toRGB('Red' ) )
style.addDrawingStyle( group='Knik & Kite', name='AutoLayer' , color=toRGB('Magenta' ) )
style.addDrawingStyle( group='Knik & Kite', name='gmetalh' , color=toRGB('128,255,200'), pattern=toHexa('antislash2.32' ), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gmetalv' , color=toRGB('200,200,255'), pattern=toHexa('light_antihash1.8'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gcontact' , color=toRGB('255,255,190'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::Edge' , color=toRGB('255,255,190'), pattern='0000000000000000' , border=4, threshold=0.02 )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::GCell', color=toRGB('255,255,190'), pattern='0000000000000000' , border=2, threshold=threshold )
Viewer.Graphics.addStyle( style )
# ----------------------------------------------------------------------
# Style: Alliance.Classic [white].
style = Viewer.DisplayStyle( 'Coriolis [white]' )
style.inheritFrom( 'Coriolis [black]' )
style.setDescription ( 'Coriolis Look - white background' )
style.setDarkening ( Viewer.DisplayStyle.HSVr(1.0, 3.0, 2.5) )
style.addDrawingStyle( group='Viewer', name='background', color=toRGB('White'), border=1 )
style.addDrawingStyle( group='Viewer', name='foreground', color=toRGB('Black'), border=1 )
style.addDrawingStyle( group='Viewer', name='boundaries', color=toRGB('Black'), border=1, pattern='0000000000000000' )
Viewer.Graphics.addStyle( style )
# ----------------------------------------------------------------------
# Style: Alliance.Classic [black]
style = Viewer.DisplayStyle( 'Alliance.Classic [black]' )
style.setDescription( 'Alliance Classic Look - black background' )
style.setDarkening ( Viewer.DisplayStyle.HSVr(1.0, 3.0, 2.5) )
# Viewer.
style.addDrawingStyle( group='Viewer', name='fallback' , color=toRGB('Gray238' ), border=1, pattern='55AA55AA55AA55AA' )
style.addDrawingStyle( group='Viewer', name='background' , color=toRGB('Gray50' ), border=1 )
style.addDrawingStyle( group='Viewer', name='foreground' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='rubber' , color=toRGB('192,0,192' ), border=4, threshold=0.02*scale )
style.addDrawingStyle( group='Viewer', name='phantom' , color=toRGB('Seashell4' ), border=1 )
#style.addDrawingStyle( group='Viewer', name='boundaries' , color=toRGB('208,199,192'), border=2, threshold=0 )
style.addDrawingStyle( group='Viewer', name='boundaries' , color=toRGB('wheat1') , border=2, pattern='0000000000000000', threshold=0 )
style.addDrawingStyle( group='Viewer', name='marker' , color=toRGB('80,250,80' ), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionDraw' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionFill' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='grid' , color=toRGB('White' ), border=1, threshold=8.0*scale )
style.addDrawingStyle( group='Viewer', name='spot' , color=toRGB('White' ), border=2, threshold=6.0*scale )
style.addDrawingStyle( group='Viewer', name='ghost' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='text.ruler' , color=toRGB('White' ), border=1, threshold= 0.0*scale )
style.addDrawingStyle( group='Viewer', name='text.instance' , color=toRGB('White' ), border=1, threshold=400.0*scale )
style.addDrawingStyle( group='Viewer', name='text.reference', color=toRGB('White' ), border=1, threshold=200.0*scale )
style.addDrawingStyle( group='Viewer', name='undef' , color=toRGB('Violet' ), border=0, pattern='2244118822441188' )
style.addDrawingStyle( group='Viewer', name='Border' , color=toRGB('wheat1' ), border=1, pattern='0000000000000000', threshold=0 )
# Active Layers.
style.addDrawingStyle( group='Active Layers', name='Nwell' , color=toRGB('Tan' ), pattern=toHexa('urgo.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Active Layers', name='LVPwell' , color=toRGB('LightYellow'), pattern=toHexa('urgo.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Active Layers', name='Nplus' , color=toRGB('LawnGreen' ), pattern=toHexa('antihash0.8'), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Active Layers', name='Pplus' , color=toRGB('Yellow' ), pattern=toHexa('antihash0.8'), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Active Layers', name='COMP' , color=toRGB('White' ), pattern=toHexa('antihash1.8'), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Active Layers', name='Poly2' , color=toRGB('Red' ), pattern=toHexa('poids2.8' ), border=1, threshold=0.00*scale )
# Routing Layers.
style.addDrawingStyle( group='Routing Layers', name='Metal1' , color=toRGB('Blue' ), pattern=toHexa('slash.8' ), border=1, threshold=0.80*scale )
style.addDrawingStyle( group='Routing Layers', name='Metal2' , color=toRGB('Aqua' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='Metal3' , color=toRGB('LightPink' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='Metal4' , color=toRGB('Green' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='Metal5' , color=toRGB('Yellow' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='MetalTop', color=toRGB('Violet' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
# Cuts (VIA holes).
style.addDrawingStyle( group='Cuts (VIA holes)', name='Contact', color=toRGB('0,150,150'), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='Via1' , color=toRGB('Aqua' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='Via2' , color=toRGB('LightPink'), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='Via3' , color=toRGB('Green' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='Via4' , color=toRGB('Yellow' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='Via5' , color=toRGB('Violet' ), threshold=0.0*scale )
# Fillers.
style.addDrawingStyle( group='Fillers', name='Poly2_Dummy' , color=toRGB('Red' ), pattern=toHexa('poids2.8' ), border=0, threshold=0.00*scale )
style.addDrawingStyle( group='Fillers', name='Metal1_Dummy' , color=toRGB('Blue' ), pattern=toHexa('slash.8' ), border=0, threshold=0.80*scale )
style.addDrawingStyle( group='Fillers', name='Metal2_Dummy' , color=toRGB('Aqua' ), pattern=toHexa('poids4.8' ), border=0, threshold=0.00*scale )
style.addDrawingStyle( group='Fillers', name='Metal3_Dummy' , color=toRGB('LightPink'), pattern=toHexa('poids4.8' ), border=0, threshold=0.00*scale )
style.addDrawingStyle( group='Fillers', name='Metal4_Dummy' , color=toRGB('Green' ), pattern=toHexa('poids4.8' ), border=0, threshold=0.00*scale )
style.addDrawingStyle( group='Fillers', name='Metal5_Dummy' , color=toRGB('Yellow' ), pattern=toHexa('poids4.8' ), border=0, threshold=0.00*scale )
style.addDrawingStyle( group='Fillers', name='MetalTop_Dummy', color=toRGB('Violet' ), pattern=toHexa('poids4.8' ), border=0, threshold=0.00*scale )
# Labels.
style.addDrawingStyle( group='Labels', name='Poly2_Label' , color=toRGB('Red' ), pattern=toHexa('poids2.8' ), border=0, threshold=0.00*scale )
style.addDrawingStyle( group='Labels', name='Metal1_Label' , color=toRGB('Blue' ), pattern=toHexa('slash.8' ), border=0, threshold=0.80*scale )
style.addDrawingStyle( group='Labels', name='Metal2_Label' , color=toRGB('Aqua' ), pattern=toHexa('poids4.8' ), border=0, threshold=0.00*scale )
style.addDrawingStyle( group='Labels', name='Metal3_Label' , color=toRGB('LightPink'), pattern=toHexa('poids4.8' ), border=0, threshold=0.00*scale )
style.addDrawingStyle( group='Labels', name='Metal4_Label' , color=toRGB('Green' ), pattern=toHexa('poids4.8' ), border=0, threshold=0.00*scale )
style.addDrawingStyle( group='Labels', name='Metal5_Label' , color=toRGB('Yellow' ), pattern=toHexa('poids4.8' ), border=0, threshold=0.00*scale )
style.addDrawingStyle( group='Labels', name='MetalTop_Label', color=toRGB('Violet' ), pattern=toHexa('poids4.8' ), border=0, threshold=0.00*scale )
# Blockages.
style.addDrawingStyle( group='Blockages', name='Metal1_BLK' , color=toRGB('Blue' ), pattern=toHexa('light_antislash0.8'), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='Metal2_BLK' , color=toRGB('Aqua' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='Metal3_BLK' , color=toRGB('LightPink'), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='Metal4_BLK' , color=toRGB('Green' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='Metal5_BLK' , color=toRGB('Yellow' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='MetalTop_BLK', color=toRGB('Violet' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
# Knick & Kite.
style.addDrawingStyle( group='Knik & Kite', name='SPL1' , color=toRGB('Red' ) )
style.addDrawingStyle( group='Knik & Kite', name='AutoLayer' , color=toRGB('Magenta' ) )
style.addDrawingStyle( group='Knik & Kite', name='gcontact' , color=toRGB('255,255,190'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gmetalh' , color=toRGB('128,255,200'), pattern=toHexa('antislash2.32' ), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gmetalv' , color=toRGB('200,200,255'), pattern=toHexa('light_antihash1.8'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gcut' , color=toRGB('255,255,190'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::Edge' , color=toRGB('255,255,190'), pattern='0000000000000000' , border=4, threshold=0.02*scale )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::GCell', color=toRGB('255,255,190'), pattern='0000000000000000' , border=2, threshold=0.10*scale )
Viewer.Graphics.addStyle( style )
Viewer.Graphics.setStyle( 'Alliance.Classic [black]' )
def setup():
_setup_techno()
_setup_display()
try:
from .techno_fix import fix
except:
pass
else:
fix()

View File

@ -43,6 +43,7 @@ env.setGROUND ( 'vss' )
env.setCLOCK ( '.*ck.*|.*nck.*' )
env.setBLOCKAGE ( 'blockage[Nn]et.*' )
env.setPad ( '.*_px$' )
env.setRegister ( 'sff.*' )
env.setWORKING_LIBRARY( '.' )
env.addSYSTEM_LIBRARY ( library=cellsTop+'/sxlib' , mode=Environment.Append )

View File

@ -43,6 +43,7 @@ env.setGROUND ( 'vss' )
env.setCLOCK ( '.*ck.*|.*nck.*' )
env.setBLOCKAGE ( 'blockage[Nn]et.*' )
env.setPad ( '.*_mpx$' )
env.setRegister ( 'sff.*' )
env.setWORKING_LIBRARY( '.' )
env.addSYSTEM_LIBRARY ( library=cellsTop+'/nsxlib', mode=Environment.Append )

View File

@ -0,0 +1,42 @@
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2019-2023, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./etc/symbolic/lcmos/__init__.py" |
# +-----------------------------------------------------------------+
import coriolis.Cfg as Cfg
from coriolis.helpers import truncPath, tagConfModules
from coriolis.helpers.io import vprint
vprint( 1, ' o Loading "symbolic.lcmos" technology.' )
vprint( 2, ' - "%s".' % truncPath(__file__) )
from coriolis.Hurricane import DataBase
from coriolis.CRL import System
Cfg.Configuration.pushDefaultPriority( Cfg.Parameter.Priority.ConfigurationFile )
if not DataBase.getDB(): DataBase.create()
System.get()
from . import misc
from . import technology
from . import display
from . import analog
from . import alliance
from . import etesian
from . import kite
from . import plugins
from . import stratus1
Cfg.Configuration.popDefaultPriority()
tagConfModules()

View File

@ -0,0 +1,56 @@
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2019-2023, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./etc/symbolic/lcmos/alliance.py" |
# +-----------------------------------------------------------------+
import os
import os.path
from coriolis.helpers import truncPath
from coriolis.helpers.io import vprint
vprint( 2, ' - "{}".'.format(truncPath(__file__)) )
from coriolis.CRL import Environment, AllianceFramework
allianceTop = None
if 'ALLIANCE_TOP' in os.environ:
allianceTop = os.environ['ALLIANCE_TOP']
if not os.path.isdir(allianceTop):
allianceTop = None
if not allianceTop: allianceTop = '/soc/alliance'
cellsTop = allianceTop+'/cells'
af = AllianceFramework.get()
env = af.getEnvironment()
env.setSCALE_X ( 100 )
env.setCATALOG ( 'CATAL' )
env.setIN_LO ( 'vst' )
env.setIN_PH ( 'ap' )
env.setOUT_LO ( 'vst' )
env.setOUT_PH ( 'ap' )
env.setPOWER ( 'vdd' )
env.setGROUND ( 'vss' )
env.setCLOCK ( '.*ck.*|.*nck.*' )
env.setBLOCKAGE ( 'blockage[Nn]et.*' )
env.setPad ( '.*_px$' )
env.setRegister ( 'sff.*' )
env.setWORKING_LIBRARY( '.' )
env.addSYSTEM_LIBRARY ( library=cellsTop+'/sxlib' , mode=Environment.Append )
env.addSYSTEM_LIBRARY ( library=cellsTop+'/dp_sxlib', mode=Environment.Append )
env.addSYSTEM_LIBRARY ( library=cellsTop+'/ramlib' , mode=Environment.Append )
env.addSYSTEM_LIBRARY ( library=cellsTop+'/romlib' , mode=Environment.Append )
env.addSYSTEM_LIBRARY ( library=cellsTop+'/rflib' , mode=Environment.Append )
env.addSYSTEM_LIBRARY ( library=cellsTop+'/rf2lib' , mode=Environment.Append )
env.addSYSTEM_LIBRARY ( library=cellsTop+'/pxlib' , mode=Environment.Append )
env.addSYSTEM_LIBRARY ( library=cellsTop+'/padlib' , mode=Environment.Append )

View File

@ -0,0 +1,20 @@
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2019-2023, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./etc/symbolic/lcmos/analog.py" |
# +-----------------------------------------------------------------+
from coriolis.helpers import truncPath
from coriolis.helpers.io import vprint
vprint( 2, ' - "%s".' % truncPath(__file__) )
from ...common import analog

View File

@ -0,0 +1,474 @@
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2019-2023, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./etc/symbolic/lcmos/display.py" |
# +-----------------------------------------------------------------+
from coriolis.helpers import truncPath
from coriolis.helpers.io import vprint
import coriolis.Cfg as Cfg
import coriolis.Viewer as Viewer
from coriolis.helpers import overlay, l, u, n
from coriolis.technos.common.colors import toRGB
from coriolis.technos.common.patterns import toHexa
vprint( 2, ' - "%s".' % truncPath(__file__) )
def createStyles ( scale=1.0 ):
with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg:
cfg.viewer.minimumSize = 500
cfg.viewer.pixelThreshold = 5
# ----------------------------------------------------------------------
# Style: Alliance.Coriolis [black].
style = Viewer.DisplayStyle( 'Alliance.Coriolis [black]' )
style.setDescription( 'Alliance Coriolis Look - black background' )
style.setDarkening ( Viewer.DisplayStyle.HSVr(1.0, 3.0, 2.5) )
style.addDrawingStyle( group='Viewer', name='fallback' , color=toRGB('Gray238' ), border=1, pattern='55AA55AA55AA55AA' )
style.addDrawingStyle( group='Viewer', name='background' , color=toRGB('Gray50' ), border=1 )
style.addDrawingStyle( group='Viewer', name='foreground' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='rubber' , color=toRGB('192,0,192' ), border=2, threshold=0.02*scale )
style.addDrawingStyle( group='Viewer', name='phantom' , color=toRGB('Seashell4' ), border=1 )
style.addDrawingStyle( group='Viewer', name='boundaries' , color=toRGB('208,199,192'), border=1, pattern='0000000000000000', threshold=0 )
style.addDrawingStyle( group='Viewer', name='marker' , color=toRGB('80,250,80' ), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionDraw' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionFill' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='grid' , color=toRGB('White' ), border=1, threshold=2.0*scale )
style.addDrawingStyle( group='Viewer', name='spot' , color=toRGB('White' ), border=2, threshold=6.0*scale )
style.addDrawingStyle( group='Viewer', name='ghost' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='text.ruler' , color=toRGB('White' ), border=1, threshold=0.0*scale )
style.addDrawingStyle( group='Viewer', name='text.instance' , color=toRGB('Black' ), border=1, threshold=4.0*scale )
style.addDrawingStyle( group='Viewer', name='text.reference' , color=toRGB('White' ), border=1, threshold=20.0*scale )
style.addDrawingStyle( group='Viewer', name='undef' , color=toRGB('Violet' ), border=0, pattern='2244118822441188' )
style.addDrawingStyle( group='Viewer', name='mauka.container', color=toRGB('Magenta4' ), border=4, pattern='0000000000000000', goMatched=False )
# Group: Active Layer.
style.addDrawingStyle( group='Active Layer', name='nWell' , color=toRGB('Tan' ), pattern='55AA55AA55AA55AA' , threshold=1.5 *scale )
style.addDrawingStyle( group='Active Layer', name='pWell' , color=toRGB('LightYellow'), pattern='55AA55AA55AA55AA' , threshold=1.50*scale )
style.addDrawingStyle( group='Active Layer', name='nImplant', color=toRGB('LawnGreen' ), pattern='55AA55AA55AA55AA' , threshold=1.50*scale )
style.addDrawingStyle( group='Active Layer', name='pImplant', color=toRGB('Yellow' ), pattern='55AA55AA55AA55AA' , threshold=1.50*scale )
style.addDrawingStyle( group='Active Layer', name='active' , color=toRGB('White' ), pattern=toHexa('antihash1.8'), threshold=1.50*scale )
style.addDrawingStyle( group='Active Layer', name='poly' , color=toRGB('Red' ), pattern='55AA55AA55AA55AA' , threshold=1.50*scale )
# Group: Routing Layer.
style.addDrawingStyle( group='Routing Layer', name='metal1' , color=toRGB('Blue' ), pattern=toHexa('poids2.8' ), threshold=0.80*scale )
style.addDrawingStyle( group='Routing Layer', name='metal2' , color=toRGB('Aqua' ), pattern=toHexa('light_antihash0.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='metal3' , color=toRGB('LightPink'), pattern=toHexa('light_antihash1.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='metal4' , color=toRGB('Green' ), pattern=toHexa('light_antihash2.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='metal5' , color=toRGB('Yellow' ), pattern='1144114411441144' , threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='metal6' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='metal7' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='metal8' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='metal9' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layer', name='metal10', color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.02*scale )
# Group: Cuts (VIA holes).
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut0', color=toRGB('0,150,150'), threshold=1.50*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut1', color=toRGB('Aqua' ), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut2', color=toRGB('LightPink'), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut3', color=toRGB('Green' ), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut4', color=toRGB('Yellow' ), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut5', color=toRGB('Violet' ), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut6', color=toRGB('Violet' ), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut7', color=toRGB('Violet' ), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut8', color=toRGB('Violet' ), threshold=0.80*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut9', color=toRGB('Violet' ), threshold=0.80*scale )
# Group: MIM6.
style.addDrawingStyle( group='MIM6', name='metbot_r', color=toRGB('Aqua' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale )
style.addDrawingStyle( group='MIM6', name='cut6' , color=toRGB('LightPink'), pattern=toHexa('light_antihash1.8'), threshold=0.80*scale )
style.addDrawingStyle( group='MIM6', name='metal7' , color=toRGB('Green' ), pattern=toHexa('light_antihash2.8'), threshold=0.80*scale )
# Group: Blockages.
style.addDrawingStyle( group='Blockages', name='blockage1' , color=toRGB('Blue' ), pattern='006070381c0e0703' , threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage2' , color=toRGB('Aqua' ), pattern='8103060c183060c0' , threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage3' , color=toRGB('LightPink'), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage4' , color=toRGB('Green' ), pattern=toHexa('light_antihash2.8'), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage5' , color=toRGB('Yellow' ), pattern='1144114411441144' , threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage6' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage7' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage8' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage9' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage10', color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale, border=2 )
# Group: Knik & Kite.
style.addDrawingStyle( group='Knik & Kite', name='SPL1' , color=toRGB('Red' ) )
style.addDrawingStyle( group='Knik & Kite', name='AutoLayer' , color=toRGB('Magenta' ) )
style.addDrawingStyle( group='Knik & Kite', name='gmetalh' , color=toRGB('128,255,200'), pattern=toHexa('light_antihash0.8'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gmetalv' , color=toRGB('200,200,255'), pattern=toHexa('light_antihash1.8'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gcut' , color=toRGB('255,255,190'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::Edge' , color=toRGB('255,255,190'), pattern='0000000000000000', threshold=0.02*scale, border=4 )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::GCell', color=toRGB('255,0,0' ), pattern='0000000000000000', threshold=0.02*scale, border=4 )
Viewer.Graphics.addStyle( style )
# ----------------------------------------------------------------------
# Style: Alliance.Coriolis [white].
style = Viewer.DisplayStyle( 'Alliance.Coriolis [white]' )
style.inheritFrom( 'Alliance.Coriolis [black]' )
style.setDescription( 'Alliance Coriolis Look - white background' )
style.setDarkening ( Viewer.DisplayStyle.HSVr(1.0, 3.0, 2.5) )
style.addDrawingStyle( group='Viewer', name='fallback' , color=toRGB('Gray238' ), border=1, pattern='55AA55AA55AA55AA' )
style.addDrawingStyle( group='Viewer', name='background' , color=toRGB('Gray50' ), border=1 )
style.addDrawingStyle( group='Viewer', name='foreground' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='rubber' , color=toRGB('192,0,192' ), border=4, threshold=0.02*scale )
style.addDrawingStyle( group='Viewer', name='phantom' , color=toRGB('Seashell4' ), border=1 )
style.addDrawingStyle( group='Viewer', name='boundaries' , color=toRGB('208,199,192'), border=1, pattern='0000000000000000', threshold=0 )
style.addDrawingStyle( group='Viewer', name='marker' , color=toRGB('80,250,80' ), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionDraw' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionFill' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='grid' , color=toRGB('White' ), border=1, threshold=2.0*scale )
style.addDrawingStyle( group='Viewer', name='spot' , color=toRGB('White' ), border=2, threshold=6.0*scale )
style.addDrawingStyle( group='Viewer', name='ghost' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='text.ruler' , color=toRGB('White' ), border=1, threshold=0.0 *scale )
style.addDrawingStyle( group='Viewer', name='text.instance' , color=toRGB('White' ), border=1, threshold=400.0 *scale )
style.addDrawingStyle( group='Viewer', name='text.reference', color=toRGB('White' ), border=1, threshold=200.0*scale )
style.addDrawingStyle( group='Viewer', name='undef' , color=toRGB('Violet' ), border=0, pattern='2244118822441188' )
# Active Layers.
style.addDrawingStyle( group='Active Layer', name='nWell' , color=toRGB('Tan' ), pattern=toHexa('urgo.8' ), border=1, threshold=0*scale )
style.addDrawingStyle( group='Active Layer', name='pWell' , color=toRGB('LightYellow'), pattern=toHexa('urgo.8' ), border=1, threshold=0*scale )
style.addDrawingStyle( group='Active Layer', name='nImplant', color=toRGB('LawnGreen' ), pattern=toHexa('antihash0.8'), border=1, threshold=0*scale )
style.addDrawingStyle( group='Active Layer', name='pImplant', color=toRGB('Yellow' ), pattern=toHexa('antihash0.8'), border=1, threshold=0*scale )
style.addDrawingStyle( group='Active Layer', name='active' , color=toRGB('White' ), pattern=toHexa('antihash1.8'), border=1, threshold=0*scale )
style.addDrawingStyle( group='Active Layer', name='poly' , color=toRGB('Red' ), pattern=toHexa('poids2.8' ), border=1, threshold=0*scale )
style.addDrawingStyle( group='Active Layer', name='poly2' , color=toRGB('Orange' ), pattern=toHexa('poids2.8' ), border=1, threshold=0*scale )
# Routing Layers.
style.addDrawingStyle( group='Routing Layer', name='metal1' , color=toRGB('Blue' ), pattern=toHexa('slash.8' ), border=1, threshold=0.0*scale )
style.addDrawingStyle( group='Routing Layer', name='metal2' , color=toRGB('Aqua' ), pattern=toHexa('poids4.8'), border=1, threshold=0.0*scale )
style.addDrawingStyle( group='Routing Layer', name='metcap' , color=toRGB('DarkTurquoise'), pattern=toHexa('poids2.8'), border=2, threshold=0.0*scale )
style.addDrawingStyle( group='Routing Layer', name='metal3' , color=toRGB('LightPink' ), pattern=toHexa('poids4.8'), border=1, threshold=0.0*scale )
style.addDrawingStyle( group='Routing Layer', name='metal4' , color=toRGB('Green' ), pattern=toHexa('poids4.8'), border=1, threshold=0.0*scale )
style.addDrawingStyle( group='Routing Layer', name='metal5' , color=toRGB('Yellow' ), pattern=toHexa('poids4.8'), border=1, threshold=0.0*scale )
style.addDrawingStyle( group='Routing Layer', name='metal6' , color=toRGB('Violet' ), pattern=toHexa('poids4.8'), border=1, threshold=0.0*scale )
style.addDrawingStyle( group='Routing Layer', name='metal7' , color=toRGB('Red' ), pattern=toHexa('poids4.8'), border=1, threshold=0.0*scale )
style.addDrawingStyle( group='Routing Layer', name='metal8' , color=toRGB('Blue' ), pattern=toHexa('poids4.8'), border=1, threshold=0.0*scale )
style.addDrawingStyle( group='Routing Layer', name='metal9' , color=toRGB('Blue' ), pattern=toHexa('poids4.8'), border=1, threshold=0.0*scale )
style.addDrawingStyle( group='Routing Layer', name='metal10', color=toRGB('Blue' ), pattern=toHexa('poids4.8'), border=1, threshold=0.0*scale )
# Cuts (VIA holes).
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut0', color=toRGB('0,150,150'), threshold=0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut1', color=toRGB('Aqua' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut2', color=toRGB('LightPink'), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut3', color=toRGB('Green' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut4', color=toRGB('Yellow' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut5', color=toRGB('Violet' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut6', color=toRGB('Red' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut7', color=toRGB('Blue' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut8', color=toRGB('Blue' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut9', color=toRGB('Blue' ), threshold=0.0*scale )
# MIM6.
style.addDrawingStyle( group='MIM6', name='metbot_r', color=toRGB('Aqua' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale )
style.addDrawingStyle( group='MIM6', name='metal7' , color=toRGB('Green'), pattern=toHexa('light_antihash2.8'), threshold=0.80*scale )
# Blockages.
style.addDrawingStyle( group='Blockages', name='blockage1' , color=toRGB('Blue' ), pattern=toHexa('light_antislash0.8'), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage2' , color=toRGB('Aqua' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage3' , color=toRGB('LightPink'), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage4' , color=toRGB('Green' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage5' , color=toRGB('Yellow' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage6' , color=toRGB('Violet' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage7' , color=toRGB('Red' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage8' , color=toRGB('Blue' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage9' , color=toRGB('Blue' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage10', color=toRGB('Blue' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
# Knick & Kite.
style.addDrawingStyle( group='Knik & Kite', name='SPL1' , color=toRGB('Red' ) )
style.addDrawingStyle( group='Knik & Kite', name='AutoLayer' , color=toRGB('Magenta' ) )
style.addDrawingStyle( group='Knik & Kite', name='gmetalh' , color=toRGB('128,255,200'), pattern=toHexa('antislash2.32' ), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gmetalv' , color=toRGB('200,200,255'), pattern=toHexa('light_antihash1.8'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gcut' , color=toRGB('255,255,190'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::Edge' , color=toRGB('255,255,190'), pattern='0000000000000000', border=4, threshold=0.02*scale )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::GCell', color=toRGB('255,255,190'), pattern='0000000000000000', border=2, threshold=0.10*scale )
Viewer.Graphics.addStyle( style )
# ----------------------------------------------------------------------
# Style: Alliance.Classic [black]
style = Viewer.DisplayStyle( 'Alliance.Classic [black]' )
style.setDescription( 'Alliance Classic Look - black background' )
style.setDarkening ( Viewer.DisplayStyle.HSVr(1.0, 3.0, 2.5) )
# Viewer.
style.addDrawingStyle( group='Viewer', name='fallback' , color=toRGB('Gray238' ), border=1, pattern='55AA55AA55AA55AA' )
style.addDrawingStyle( group='Viewer', name='background' , color=toRGB('Gray50' ), border=1 )
style.addDrawingStyle( group='Viewer', name='foreground' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='rubber' , color=toRGB('192,0,192' ), border=4, threshold=0.02*scale )
style.addDrawingStyle( group='Viewer', name='phantom' , color=toRGB('Seashell4' ), border=1 )
#style.addDrawingStyle( group='Viewer', name='boundaries' , color=toRGB('208,199,192'), border=2, threshold=0 )
style.addDrawingStyle( group='Viewer', name='boundaries' , color=toRGB('wheat1') , border=2, pattern='0000000000000000', threshold=0 )
style.addDrawingStyle( group='Viewer', name='marker' , color=toRGB('80,250,80' ), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionDraw' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionFill' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='grid' , color=toRGB('White' ), border=1, threshold=8.0*scale )
style.addDrawingStyle( group='Viewer', name='spot' , color=toRGB('White' ), border=2, threshold=6.0*scale )
style.addDrawingStyle( group='Viewer', name='ghost' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='text.ruler' , color=toRGB('White' ), border=1, threshold= 0.0*scale )
style.addDrawingStyle( group='Viewer', name='text.instance' , color=toRGB('White' ), border=1, threshold=400.0*scale )
style.addDrawingStyle( group='Viewer', name='text.reference', color=toRGB('White' ), border=1, threshold=200.0*scale )
style.addDrawingStyle( group='Viewer', name='undef' , color=toRGB('Violet' ), border=0, pattern='2244118822441188' )
# Active Layers.
style.addDrawingStyle( group='Active Layers', name='nWell' , color=toRGB('Tan' ), pattern=toHexa('urgo.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Active Layers', name='pWell' , color=toRGB('LightYellow'), pattern=toHexa('urgo.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Active Layers', name='nImplant', color=toRGB('LawnGreen' ), pattern=toHexa('antihash0.8'), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Active Layers', name='pImplant', color=toRGB('Yellow' ), pattern=toHexa('antihash0.8'), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Active Layers', name='active' , color=toRGB('White' ), pattern='0000000000000000' , border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Active Layers', name='poly' , color=toRGB('Red' ), pattern=toHexa('poids2.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Active Layers', name='poly2' , color=toRGB('Orange' ), pattern=toHexa('poids2.8' ), border=1, threshold=0.00*scale )
# Routing Layers.
style.addDrawingStyle( group='Routing Layers', name='metal1' , color=toRGB('Blue' ), pattern=toHexa('slash.8' ), border=1, threshold=0.80*scale )
style.addDrawingStyle( group='Routing Layers', name='metal2' , color=toRGB('Aqua' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='metcap' , color=toRGB('DarkTurquoise'), pattern=toHexa('poids2.8' ), border=2, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='metal3' , color=toRGB('LightPink' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='metal4' , color=toRGB('Green' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='metal5' , color=toRGB('Yellow' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='metal6' , color=toRGB('Violet' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='metal7' , color=toRGB('Red' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='metal8' , color=toRGB('Blue' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='metal9' , color=toRGB('Blue' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
style.addDrawingStyle( group='Routing Layers', name='metal10', color=toRGB('Blue' ), pattern=toHexa('poids4.8' ), border=1, threshold=0.00*scale )
# Cuts (VIA holes).
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut0', color=toRGB('0,150,150'), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut1', color=toRGB('Aqua' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut2', color=toRGB('LightPink'), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut3', color=toRGB('Green' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut4', color=toRGB('Yellow' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut5', color=toRGB('Violet' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut6', color=toRGB('Red' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut7', color=toRGB('Blue' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut8', color=toRGB('Blue' ), threshold=0.0*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut9', color=toRGB('Blue' ), threshold=0.0*scale )
# MIM6.
style.addDrawingStyle( group='MIMI6', name='metbot_r', color=toRGB('Aqua' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale )
style.addDrawingStyle( group='MIMI6', name='metal7' , color=toRGB('Green'), pattern=toHexa('light_antihash2.8'), threshold=0.80*scale )
# Blockages.
style.addDrawingStyle( group='Blockages', name='blockage1' , color=toRGB('Blue' ), pattern=toHexa('light_antislash0.8'), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage2' , color=toRGB('Aqua' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage3' , color=toRGB('LightPink'), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage4' , color=toRGB('Green' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage5' , color=toRGB('Yellow' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage6' , color=toRGB('Violet' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage7' , color=toRGB('Red' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage8' , color=toRGB('Blue' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage9' , color=toRGB('Blue' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
style.addDrawingStyle( group='Blockages', name='blockage10', color=toRGB('Blue' ), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=4 )
# Knick & Kite.
style.addDrawingStyle( group='Knik & Kite', name='SPL1' , color=toRGB('Red' ) )
style.addDrawingStyle( group='Knik & Kite', name='AutoLayer' , color=toRGB('Magenta' ) )
style.addDrawingStyle( group='Knik & Kite', name='gmetalh' , color=toRGB('128,255,200'), pattern=toHexa('antislash2.32' ), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gmetalv' , color=toRGB('200,200,255'), pattern=toHexa('light_antihash1.8'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gcut' , color=toRGB('255,255,190'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::Edge' , color=toRGB('255,255,190'), pattern='0000000000000000' , border=4, threshold=0.02*scale )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::GCell', color=toRGB('255,255,190'), pattern='0000000000000000' , border=2, threshold=0.10*scale )
Viewer.Graphics.addStyle( style )
# ----------------------------------------------------------------------
# Style: Alliance.Classic [white].
style = Viewer.DisplayStyle( 'Alliance.Classic [white]' )
style.inheritFrom( 'Alliance.Classic [black]' )
style.setDescription( 'Alliance Classic Look - white background' )
style.setDarkening ( Viewer.DisplayStyle.HSVr(1.0, 3.0, 2.5) )
# Group: Viewer.
style.addDrawingStyle( group='Viewer', name='fallback' , color=toRGB('Black'), border=1, pattern='55AA55AA55AA55AA' )
style.addDrawingStyle( group='Viewer', name='background' , color=toRGB('White'), border=1 )
style.addDrawingStyle( group='Viewer', name='foreground' , color=toRGB('Black'), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionDraw' , color=toRGB('Black'), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionFill' , color=toRGB('Black'), border=1 )
style.addDrawingStyle( group='Viewer', name='grid' , color=toRGB('Black'), border=1, threshold=6.0*scale )
style.addDrawingStyle( group='Viewer', name='spot' , color=toRGB('Black'), border=1, threshold=6.0*scale )
style.addDrawingStyle( group='Viewer', name='ghost' , color=toRGB('Black'), border=1 )
style.addDrawingStyle( group='Viewer', name='text.ruler' , color=toRGB('Black'), border=1, threshold=0.0 *scale )
style.addDrawingStyle( group='Viewer', name='text.instance' , color=toRGB('Black'), border=1, threshold=4.0 *scale )
style.addDrawingStyle( group='Viewer', name='text.reference', color=toRGB('Black'), border=1, threshold=20.0*scale )
style.addDrawingStyle( group='Viewer', name='undef' , color=toRGB('Black'), border=0, pattern='2244118822441188' )
Viewer.Graphics.addStyle( style )
# ----------------------------------------------------------------------
# Style: Layout Design [black]
style = Viewer.DisplayStyle( 'Layout Design [black]' )
style.inheritFrom( 'Alliance.Classic [black]' )
style.setDescription( 'Alliance Classic Look - white background' )
style.setDarkening ( Viewer.DisplayStyle.HSVr(1.0, 3.0, 2.5) )
# Active Layers.
style.addDrawingStyle( group='Active Layers', name='nWell' , color=toRGB('Tan' ), pattern='0000000000000000', threshold=1.50*scale, border=2 )
style.addDrawingStyle( group='Active Layers', name='pWell' , color=toRGB('LightYellow'), pattern='0000000000000000', threshold=1.50*scale, border=2 )
style.addDrawingStyle( group='Active Layers', name='nImplant', color=toRGB('LawnGreen' ), pattern='0000000000000000', threshold=1.50*scale, border=2 )
style.addDrawingStyle( group='Active Layers', name='pImplant', color=toRGB('Yellow' ), pattern='0000000000000000', threshold=1.50*scale, border=2 )
style.addDrawingStyle( group='Active Layers', name='active' , color=toRGB('White' ), pattern='0000000000000000', threshold=1.50*scale, border=2 )
style.addDrawingStyle( group='Active Layers', name='poly' , color=toRGB('Red' ), pattern='0000000000000000', threshold=1.50*scale, border=2 )
# Routing Layers.
style.addDrawingStyle( group='Routing Layers', name='metal1' , color=toRGB('Blue' ), pattern='0000000000000000', threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Routing Layers', name='metal2' , color=toRGB('Aqua' ), pattern='0000000000000000', threshold=0.40*scale, border=2 )
style.addDrawingStyle( group='Routing Layers', name='metal3' , color=toRGB('LightPink'), pattern='0000000000000000', threshold=0.02*scale, border=2 )
style.addDrawingStyle( group='Routing Layers', name='metal4' , color=toRGB('Green' ), pattern='0000000000000000', threshold=0.02*scale, border=2 )
style.addDrawingStyle( group='Routing Layers', name='metal5' , color=toRGB('Yellow' ), pattern='0000000000000000', threshold=0.02*scale, border=2 )
style.addDrawingStyle( group='Routing Layers', name='metal6' , color=toRGB('Violet' ), pattern='0000000000000000', threshold=0.02*scale, border=2 )
style.addDrawingStyle( group='Routing Layers', name='metal7' , color=toRGB('Violet' ), pattern='0000000000000000', threshold=0.02*scale, border=2 )
style.addDrawingStyle( group='Routing Layers', name='metal8' , color=toRGB('Violet' ), pattern='0000000000000000', threshold=0.02*scale, border=2 )
style.addDrawingStyle( group='Routing Layers', name='metal9' , color=toRGB('Violet' ), pattern='0000000000000000', threshold=0.02*scale, border=2 )
style.addDrawingStyle( group='Routing Layers', name='metal10', color=toRGB('Violet' ), pattern='0000000000000000', threshold=0.02*scale, border=2 )
# Cuts (VIA holes).
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut0', color=toRGB('0,150,150'), pattern=toHexa('poids4.8'), threshold=1.50*scale, border=1 )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut1', color=toRGB('Aqua' ), pattern='0000000000000000', threshold=0.80*scale, border=1 )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut2', color=toRGB('LightPink'), pattern='0000000000000000', threshold=0.80*scale, border=1 )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut3', color=toRGB('Green' ), pattern='0000000000000000', threshold=0.80*scale, border=1 )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut4', color=toRGB('Yellow' ), pattern='0000000000000000', threshold=0.80*scale, border=1 )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut5', color=toRGB('Violet' ), pattern='0000000000000000', threshold=0.80*scale, border=1 )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut6', color=toRGB('Violet' ), pattern='0000000000000000', threshold=0.80*scale, border=1 )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut7', color=toRGB('Violet' ), pattern='0000000000000000', threshold=0.80*scale, border=1 )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut8', color=toRGB('Violet' ), pattern='0000000000000000', threshold=0.80*scale, border=1 )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut9', color=toRGB('Violet' ), pattern='0000000000000000', threshold=0.80*scale, border=1 )
Viewer.Graphics.addStyle( style )
# ----------------------------------------------------------------------
# Style: Layout Design [white]
style = Viewer.DisplayStyle( 'Layout Design [white]' )
style.inheritFrom( 'Layout Design [black]' )
style.setDescription( 'Layout Design Look - white background' )
style.setDarkening ( Viewer.DisplayStyle.HSVr(1.0, 3.0, 2.5) )
# Group: Viewer.
style.addDrawingStyle( group='Viewer', name='background' , color=toRGB('White'), border=1 )
style.addDrawingStyle( group='Viewer', name='grid' , color=toRGB('Black'), border=1, threshold=2.0 *scale )
style.addDrawingStyle( group='Viewer', name='spot' , color=toRGB('Black'), border=1, threshold=2.0 *scale )
style.addDrawingStyle( group='Viewer', name='text.ruler' , color=toRGB('Black'), border=1, threshold=0.0 *scale )
style.addDrawingStyle( group='Viewer', name='text.reference', color=toRGB('Black'), border=1, threshold=20.0*scale )
# Group: Active Layers.
style.addDrawingStyle( group='Active Layers', name='active', color=toRGB('175,175,175'), pattern='0000000000000000', threshold=1.50*scale, border=2 )
Viewer.Graphics.addStyle( style )
# ----------------------------------------------------------------------
# Style: For Printers [white]
style = Viewer.DisplayStyle( 'For Printers' )
style.setDescription( 'For Printers' )
style.setDarkening ( Viewer.DisplayStyle.HSVr(1.0, 3.0, 2.5) )
# Group: Viewer.
style.addDrawingStyle( group='Viewer', name='fallback' , color=toRGB('Gray238' ), border=1, pattern='55AA55AA55AA55AA' )
style.addDrawingStyle( group='Viewer', name='background' , color=toRGB('White' ), border=1 )
style.addDrawingStyle( group='Viewer', name='foreground' , color=toRGB('Black' ), border=1 )
style.addDrawingStyle( group='Viewer', name='rubber' , color=toRGB('192,0,192'), border=4, threshold=0.02*scale )
style.addDrawingStyle( group='Viewer', name='phantom' , color=toRGB('Seashell4'), border=1 )
style.addDrawingStyle( group='Viewer', name='boundaries' , color=toRGB('Black' ), border=1, pattern='0000000000000000', threshold=0 )
style.addDrawingStyle( group='Viewer', name='marker' , color=toRGB('80,250,80'), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionDraw' , color=toRGB('Black' ), border=1 )
style.addDrawingStyle( group='Viewer', name='selectionFill' , color=toRGB('Black' ), border=1 )
style.addDrawingStyle( group='Viewer', name='grid' , color=toRGB('Black' ), border=1, threshold=2.0*scale )
style.addDrawingStyle( group='Viewer', name='spot' , color=toRGB('Black' ), border=2, threshold=6.0*scale )
style.addDrawingStyle( group='Viewer', name='ghost' , color=toRGB('Black' ), border=1 )
style.addDrawingStyle( group='Viewer', name='text.ruler' , color=toRGB('Black' ), border=1, threshold=0.0 *scale )
style.addDrawingStyle( group='Viewer', name='text.instance' , color=toRGB('Black' ), border=1, threshold=4.0 *scale )
style.addDrawingStyle( group='Viewer', name='text.reference' , color=toRGB('Black' ), border=1, threshold=20.0*scale )
style.addDrawingStyle( group='Viewer', name='undef' , color=toRGB('Violet' ), border=0, pattern='2244118822441188' )
style.addDrawingStyle( group='Viewer', name='mauka.container', color=toRGB('Magenta4' ), border=4, pattern='0000000000000000', goMatched=False )
# Group: Active Layers.
style.addDrawingStyle( group='Active Layers', name='nWell' , color=toRGB('Tan' ), pattern=toHexa('urgo.32' ), border=1, threshold=0.02*scale )
style.addDrawingStyle( group='Active Layers', name='pWell' , color=toRGB('LightYellow'), pattern=toHexa('antipoids2.32'), border=1, threshold=0.02*scale )
style.addDrawingStyle( group='Active Layers', name='nImplant', color=toRGB('LawnGreen' ), pattern=toHexa('diffusion.32' ), border=0, threshold=0.02*scale )
style.addDrawingStyle( group='Active Layers', name='pImplant', color=toRGB('Yellow' ), pattern=toHexa('diffusion.32' ), border=0, threshold=0.02*scale )
style.addDrawingStyle( group='Active Layers', name='active' , color=toRGB('White' ), pattern=toHexa('active.32' ), border=0, threshold=0.02*scale )
style.addDrawingStyle( group='Active Layers', name='poly' , color=toRGB('Red' ), pattern=toHexa('antipoids2.32'), border=1, threshold=0.02*scale )
style.addDrawingStyle( group='Active Layers', name='poly2' , color=toRGB('Orange' ), pattern=toHexa('antipoids2.32'), border=1, threshold=0.02*scale )
# Group: Routing Layers.
style.addDrawingStyle( group='Routing Layers', name='metal1' , color=toRGB('Blue' ), pattern=toHexa('slash.32' ), border=4, threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layers', name='metal2' , color=toRGB('Aqua' ), pattern=toHexa('antislash2.32'), border=1, threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layers', name='metcap' , color=toRGB('DarkTurquoise'), pattern=toHexa('poids2.32' ), border=2, threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layers', name='metal3' , color=toRGB('LightPink' ), pattern=toHexa('antislash3.32'), border=1, threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layers', name='metal4' , color=toRGB('Green' ), pattern=toHexa('antislash4.32'), border=1, threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layers', name='metal5' , color=toRGB('Yellow' ), pattern=toHexa('antislash5.32'), border=1, threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layers', name='metal6' , color=toRGB('Violet' ), pattern=toHexa('antislash2.32'), border=1, threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layers', name='metal7' , color=toRGB('Violet' ), pattern=toHexa('antislash2.32'), border=1, threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layers', name='metal8' , color=toRGB('Violet' ), pattern=toHexa('antislash2.32'), border=1, threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layers', name='metal9' , color=toRGB('Violet' ), pattern=toHexa('antislash2.32'), border=1, threshold=0.02*scale )
style.addDrawingStyle( group='Routing Layers', name='metal10', color=toRGB('Violet' ), pattern=toHexa('antislash2.32'), border=1, threshold=0.02*scale )
# Group: Cuts (VIA holes)
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut0', color=toRGB('Blue' ), pattern=toHexa('poids2.8' ), border=2, threshold=0.02*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut1', color=toRGB('Aqua' ), pattern=toHexa('antipoids2.8'), border=2, threshold=0.02*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut2', color=toRGB('LightPink'), pattern=toHexa('poids2.8' ), border=2, threshold=0.02*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut3', color=toRGB('Green' ), pattern=toHexa('antipoids2.8'), border=2, threshold=0.02*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut4', color=toRGB('Yellow' ), pattern=toHexa('poids2.8' ), border=2, threshold=0.02*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut5', color=toRGB('Violet' ), pattern=toHexa('antipoids2.8'), border=2, threshold=0.02*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut6', color=toRGB('Violet' ), pattern=toHexa('antipoids2.8'), border=2, threshold=0.02*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut7', color=toRGB('Violet' ), pattern=toHexa('antipoids2.8'), border=2, threshold=0.02*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut8', color=toRGB('Violet' ), pattern=toHexa('antipoids2.8'), border=2, threshold=0.02*scale )
style.addDrawingStyle( group='Cuts (VIA holes)', name='cut9', color=toRGB('Violet' ), pattern=toHexa('antipoids2.8'), border=2, threshold=0.02*scale )
# Group: MIM6.
style.addDrawingStyle( group='MIM6', name='metbot_r', color=toRGB('Aqua' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale )
style.addDrawingStyle( group='MIM6', name='cut6' , color=toRGB('LightPink'), pattern=toHexa('light_antihash1.8'), threshold=0.80*scale )
style.addDrawingStyle( group='MIM6', name='metal7' , color=toRGB('Green' ), pattern=toHexa('light_antihash2.8'), threshold=0.80*scale )
# Group: Blockages.
style.addDrawingStyle( group='Blockages', name='blockage1' , color=toRGB('Blue' ), pattern='006070381c0e0703' , threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage2' , color=toRGB('Aqua' ), pattern='8103060c183060c0' , threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage3' , color=toRGB('LightPink'), pattern=toHexa('poids4.8' ), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage4' , color=toRGB('Green' ), pattern=toHexa('light_antihash2.8'), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage5' , color=toRGB('Yellow' ), pattern='1144114411441144' , threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage6' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage7' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage8' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage9' , color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale, border=2 )
style.addDrawingStyle( group='Blockages', name='blockage10', color=toRGB('Violet' ), pattern=toHexa('light_antihash0.8'), threshold=0.80*scale, border=2 )
# Group: Knik & Kite.
style.addDrawingStyle( group='Knik & Kite', name='SPL1' , color=toRGB('Red' ) )
style.addDrawingStyle( group='Knik & Kite', name='AutoLayer' , color=toRGB('Magenta' ) )
style.addDrawingStyle( group='Knik & Kite', name='gmetalh' , color=toRGB('128,255,200'), pattern=toHexa('light_antihash0.8') , border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gmetalv' , color=toRGB('200,200,255'), pattern=toHexa('light_antihash1.8') , border=1 )
style.addDrawingStyle( group='Knik & Kite', name='gcut' , color=toRGB('255,255,190'), border=1 )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::Edge' , color=toRGB('255,255,190'), pattern='0000000000000000', border=2 )
style.addDrawingStyle( group='Knik & Kite', name='Anabatic::GCell', color=toRGB('Black' ), pattern='0000000000000000', border=2, threshold=0.80*scale )
Viewer.Graphics.addStyle( style )
Viewer.Graphics.setStyle( 'Alliance.Classic [black]' )
createStyles( scale=1.0 )

View File

@ -0,0 +1,20 @@
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2019-2023, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./etc/symbolic/lcmos/etesian.py" |
# +-----------------------------------------------------------------+
from coriolis.helpers import truncPath
from coriolis.helpers.io import vprint
vprint( 2, ' - "%s".' % truncPath(__file__) )
from ...common import etesian

View File

@ -0,0 +1,194 @@
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2019-2023, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./etc/symbolic/lcmos/kite.py" |
# +-----------------------------------------------------------------+
import coriolis.Cfg as Cfg
from coriolis.Hurricane import DataBase
from coriolis.CRL import AllianceFramework, RoutingGauge, \
RoutingLayerGauge, CellGauge
from coriolis.helpers import truncPath, l, u, n
from coriolis.helpers.io import vprint
vprint( 2, ' - "%s".' % truncPath(__file__) )
from ...common import kite
p = Cfg.getParamDouble ( 'lefImport.minTerminalWidth' ).setDouble ( 0.0 )
p = Cfg.getParamString ( 'katabatic.routingGauge' ).setString ( 'sxlib' )
p = Cfg.getParamInt ( "katabatic.globalLengthThreshold" ).setInt ( 1450 )
p = Cfg.getParamPercentage( "katabatic.saturateRatio" ).setPercentage( 80 )
p = Cfg.getParamInt ( "katabatic.saturateRp" ).setInt ( 8 )
p = Cfg.getParamString ( 'katabatic.topRoutingLayer' ).setString ( 'METAL5' )
# Kite parameters.
p = Cfg.getParamInt( "kite.hTracksReservedLocal" ); p.setInt( 3 ); p.setMin( 0 ); p.setMax( 20 )
p = Cfg.getParamInt( "kite.vTracksReservedLocal" ); p.setInt( 3 ); p.setMin( 0 ); p.setMax( 20 )
p = Cfg.getParamInt( "kite.eventsLimit" ); p.setInt( 4000002 )
p = Cfg.getParamInt( "kite.ripupCost" ); p.setInt( 3 ); p.setMin( 0 )
p = Cfg.getParamInt( "kite.strapRipupLimit" ); p.setInt( 16 ); p.setMin( 1 )
p = Cfg.getParamInt( "kite.localRipupLimit" ); p.setInt( 9 ); p.setMin( 1 )
p = Cfg.getParamInt( "kite.globalRipupLimit" ); p.setInt( 5 ); p.setMin( 1 )
p = Cfg.getParamInt( "kite.longGlobalRipupLimit" ); p.setInt( 5 ); p.setMin( 1 )
# Anabatic & Katana parameters are temporarily hosted here.
p = Cfg.getParamString ( 'anabatic.routingGauge' ); p.setString ( 'sxlib' )
p = Cfg.getParamInt ( "anabatic.globalLengthThreshold" ); p.setInt ( 1450 )
p = Cfg.getParamPercentage( "anabatic.saturateRatio" ); p.setPercentage( 80 )
p = Cfg.getParamInt ( "anabatic.saturateRp" ); p.setInt ( 8 )
p = Cfg.getParamString ( 'anabatic.topRoutingLayer' ); p.setString ( 'METAL5' )
p = Cfg.getParamInt ( "anabatic.edgeLength" ); p.setInt ( 24 )
p = Cfg.getParamInt ( "anabatic.edgeWidth" ); p.setInt ( 4 )
p = Cfg.getParamDouble ( "anabatic.edgeCostH" ); p.setDouble ( 19.0 )
p = Cfg.getParamDouble ( "anabatic.edgeCostK" ); p.setDouble ( -60.0 )
p = Cfg.getParamDouble ( "anabatic.edgeHScaling" ); p.setDouble ( 1.0 )
p = Cfg.getParamInt ( "anabatic.globalIterations" ); p.setInt ( 10 ); p.setMin(1); p.setMax(100)
p = Cfg.getParamEnumerate ( "anabatic.gcell.displayMode" ); p.setInt ( 1 )
p.addValue( "Boundary", 1 )
p.addValue( "Density" , 2 )
p = Cfg.getParamBool ( "katana.useGlobalEstimate" ); p.setBool ( False );
p = Cfg.getParamInt ( "katana.hTracksReservedLocal" ); p.setInt ( 3 ); p.setMin(0); p.setMax(20)
p = Cfg.getParamInt ( "katana.vTracksReservedLocal" ); p.setInt ( 3 ); p.setMin(0); p.setMax(20)
p = Cfg.getParamInt ( "katana.hTracksReservedMin" ); p.setInt ( 1 ); p.setMin(0); p.setMax(20)
p = Cfg.getParamInt ( "katana.vTracksReservedMin" ); p.setInt ( 1 ); p.setMin(0); p.setMax(20)
p = Cfg.getParamInt ( "katana.termSatReservedLocal" ); p.setInt ( 8 )
p = Cfg.getParamInt ( "katana.termSatThreshold" ); p.setInt ( 9 )
p = Cfg.getParamInt ( "katana.eventsLimit" ); p.setInt ( 4000002 )
p = Cfg.getParamInt ( "katana.ripupCost" ); p.setInt ( 3 ); p.setMin(0)
p = Cfg.getParamInt ( "katana.strapRipupLimit" ); p.setInt ( 16 ); p.setMin(1)
p = Cfg.getParamInt ( "katana.localRipupLimit" ); p.setInt ( 9 ); p.setMin(1)
p = Cfg.getParamInt ( "katana.globalRipupLimit" ); p.setInt ( 5 ); p.setMin(1)
p = Cfg.getParamInt ( "katana.longGlobalRipupLimit" ); p.setInt ( 5 ); p.setMin(1)
p = Cfg.getParamString( 'chip.padCoreSide' ); p.setString( 'South' )
tech = DataBase.getDB().getTechnology()
af = AllianceFramework.get()
rg = RoutingGauge.create( 'sxlib' )
rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL1') # metal.
, RoutingLayerGauge.Vertical # preferred routing direction.
, RoutingLayerGauge.PinOnly # layer usage.
, 0 # depth.
, 0.0 # density (deprecated).
, l(0) # track offset from AB.
, l(5) # track pitch.
, l(2) # wire width.
, 0 # perpandicular wire width.
, l(1) # VIA side (that is VIA12).
, l(4) # obstacle dW.
) )
rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL2') # metal.
, RoutingLayerGauge.Horizontal # preferred routing direction.
, RoutingLayerGauge.Default # layer usage.
, 1 # depth.
, 0.0 # density (deprecated).
, l(0) # track offset from AB.
, l(5) # track pitch.
, l(2) # wire width.
, 0 # perpandicular wire width.
, l(1) # VIA side (that is VIA23).
, l(4) # obstacle dW.
) )
rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL3') # metal.
, RoutingLayerGauge.Vertical # preferred routing direction.
, RoutingLayerGauge.Default # layer usage.
, 2 # depth.
, 0.0 # density (deprecated).
, l(0) # track offset from AB.
, l(5) # track pitch.
, l(2) # wire width.
, 0 # perpandicular wire width.
, l(1) # VIA side (that is VIA34).
, l(4) # obstacle dW.
) )
rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL4') # metal.
, RoutingLayerGauge.Horizontal # preferred routing direction.
, RoutingLayerGauge.Default # layer usage.
, 3 # depth.
, 0.0 # density (deprecated).
, l(0) # track offset from AB.
, l(5) # track pitch.
, l(2) # wire width.
, 0 # perpandicular wire width.
, l(1) # VIA side (that is VIA23).
, l(4) # obstacle dW.
) )
rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL5') # metal.
, RoutingLayerGauge.Vertical # preferred routing direction.
, RoutingLayerGauge.Default # layer usage.
, 4 # depth.
, 0.0 # density (deprecated).
, l(0) # track offset from AB.
, l(5) # track pitch.
, l(2) # wire width.
, 0 # perpandicular wire width.
, l(1) # VIA side (that is VIA23).
, l(4) # obstacle dW.
) )
af.addRoutingGauge( rg )
rg = RoutingGauge.create( 'sxlib-2M' )
rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL1') # metal.
, RoutingLayerGauge.Vertical # preferred routing direction.
, RoutingLayerGauge.PinOnly # layer usage.
, 0 # depth.
, 0.0 # density (deprecated).
, l(0) # track offset from AB.
, l(5) # track pitch.
, l(2) # wire width.
, 0 # perpandicular wire width.
, l(1) # VIA side (that is VIA12).
, l(4) # obstacle dW.
) )
rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL2') # metal.
, RoutingLayerGauge.Horizontal # preferred routing direction.
, RoutingLayerGauge.Default # layer usage.
, 1 # depth.
, 0.0 # density (deprecated).
, l(0) # track offset from AB.
, l(5) # track pitch.
, l(2) # wire width.
, 0 # perpandicular wire width.
, l(1) # VIA side (that is VIA23).
, l(4) # obstacle dW.
) )
af.addRoutingGauge( rg )
af.setRoutingGauge( 'sxlib' )
# Gauge for standard cells.
cg = CellGauge.create( 'sxlib'
, 'metal2' # pin layer name.
, l( 5.0) # pitch.
, l( 50.0) # cell slice height.
, l( 5.0) # cell slice step.
)
af.addCellGauge( cg )
# Gauge for Alliance symbolic I/O pads.
cg = CellGauge.create( 'pxlib'
, 'metal2' # pin layer name.
, l( 5.0) # pitch.
, l(400.0) # cell slice height.
, l(200.0) # cell slice step.
)
af.addCellGauge( cg )

View File

@ -0,0 +1,20 @@
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2019-2023, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./etc/symbolic/lcmos/misc.py" |
# +-----------------------------------------------------------------+
from coriolis.helpers import truncPath
from coriolis.helpers.io import vprint
vprint( 2, ' - "%s".' % truncPath(__file__) )
from ...common import misc

View File

@ -0,0 +1,20 @@
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2019-2023, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./etc/symbolic/lcmos/patterns.py" |
# +-----------------------------------------------------------------+
from coriolis.helpers import truncPath
from coriolis.helpers.io import vprint
vprint( 2, ' - "%s".' % truncPath(__file__) )
from ...common import patterns

View File

@ -0,0 +1,32 @@
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2019-2023, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./etc/symbolic/lcmos/plugins.py" |
# +-----------------------------------------------------------------+
import coriolis.Cfg as Cfg
from coriolis.helpers import truncPath, l, u, n
from coriolis.helpers.io import vprint
vprint( 2, ' - "%s".' % truncPath(__file__) )
Cfg.getParamInt ( "chip.block.rails.count" ).setInt ( 5 )
Cfg.getParamInt ( "chip.block.rails.hWidth" ).setInt ( l( 12) )
Cfg.getParamInt ( "chip.block.rails.vWidth" ).setInt ( l( 12) )
Cfg.getParamInt ( "chip.block.rails.hSpacing" ).setInt ( l( 3) )
Cfg.getParamInt ( "chip.block.rails.vSpacing" ).setInt ( l( 3) )
Cfg.getParamBool ( "chip.useAbstractPads" ).setBool ( True )
Cfg.getParamInt ( 'clockTree.minimumSide' ).setInt ( l(600) )
Cfg.getParamString( 'clockTree.buffer' ).setString( 'buf_x2')
Cfg.getParamString( 'clockTree.placerEngine' ).setString( 'Etesian')
Cfg.getParamInt ( 'block.spareSide' ).setInt ( 10 )
Cfg.getParamString( 'spares.buffer' ).setString( 'buf_x8')
Cfg.getParamInt ( 'spares.maxSinks' ).setInt ( 31 )

View File

@ -0,0 +1,26 @@
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2019-2023, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./etc/symbolic/lcmos/stratus1.py" |
# +-----------------------------------------------------------------+
import os.path
import coriolis.Cfg as Cfg
from coriolis.helpers import sysConfDir, truncPath
from coriolis.helpers.io import vprint
vprint( 2, ' - "%s".' % truncPath(__file__) )
from ...common import stratus1
Cfg.getParamString( "stratus1.format" ).setString( "vst" )
Cfg.getParamString( "stratus1.simulator" ).setString( "asimut" )
Cfg.getParamString( "stratus1.mappingName" ).setString( os.path.join(sysConfDir,'symbolic/cmos/stratus2sxlib.xml') )

View File

@ -0,0 +1,401 @@
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2019-2023, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./etc/symbolic/lcmos/technology.py" |
# +-----------------------------------------------------------------+
from coriolis.helpers import l, u, n, truncPath
from coriolis.helpers.io import WarningMessage, vprint
vprint( 2, ' - "{}".'.format(truncPath(__file__)) )
from coriolis.Hurricane import DbU, DataBase, Technology, Layer, BasicLayer, \
DiffusionLayer, TransistorLayer, \
RegularLayer, ContactLayer, ViaLayer
def createBL ( layerName, material ):
global tech
return BasicLayer.create( tech, layerName, BasicLayer.Material(material) )
tech = DataBase.getDB().getTechnology()
if tech:
print( WarningMessage( 'lcmos.technology: Technology already exists, "{}"'.format(tech.getName()) ))
else:
tech = Technology.create( DataBase.getDB(), 'lcmos' )
DbU.setPrecision ( 2 )
DbU.setPhysicalsPerGrid ( 0.5, DbU.UnitPowerMicro )
DbU.setGridsPerLambda ( 2 )
DbU.setSymbolicSnapGridStep( DbU.fromLambda(1.0) )
DbU.setPolygonStep ( DbU.fromGrid (2.0) )
from ...common import loadGdsLayers
nWell = createBL( 'nWell' , BasicLayer.Material.nWell ) # Non-Routing Layers.
pWell = createBL( 'pWell' , BasicLayer.Material.pWell )
nImplant = createBL( 'nImplant' , BasicLayer.Material.nImplant )
pImplant = createBL( 'pImplant' , BasicLayer.Material.pImplant )
active = createBL( 'active' , BasicLayer.Material.active )
poly = createBL( 'poly' , BasicLayer.Material.poly )
poly2 = createBL( 'poly2' , BasicLayer.Material.poly )
cut0 = createBL( 'cut0' , BasicLayer.Material.cut ) # Routing Layers & VIA Cuts.
metal1 = createBL( 'metal1' , BasicLayer.Material.metal ) # WARNING: order *is* meaningful.
cut1 = createBL( 'cut1' , BasicLayer.Material.cut )
metal2 = createBL( 'metal2' , BasicLayer.Material.metal )
metcap = createBL( 'metcap' , BasicLayer.Material.other )
cut2 = createBL( 'cut2' , BasicLayer.Material.cut )
metal3 = createBL( 'metal3' , BasicLayer.Material.metal )
cut3 = createBL( 'cut3' , BasicLayer.Material.cut )
metal4 = createBL( 'metal4' , BasicLayer.Material.metal )
cut4 = createBL( 'cut4' , BasicLayer.Material.cut )
metal5 = createBL( 'metal5' , BasicLayer.Material.metal )
cut5 = createBL( 'cut5' , BasicLayer.Material.cut )
metal6 = createBL( 'metal6' , BasicLayer.Material.metal )
cut6 = createBL( 'cut6' , BasicLayer.Material.cut )
metal7 = createBL( 'metal7' , BasicLayer.Material.metal )
cut7 = createBL( 'cut7' , BasicLayer.Material.cut )
metal8 = createBL( 'metal8' , BasicLayer.Material.metal )
cut8 = createBL( 'cut8' , BasicLayer.Material.cut )
metal9 = createBL( 'metal9' , BasicLayer.Material.metal )
cut9 = createBL( 'cut9' , BasicLayer.Material.cut )
metal10 = createBL( 'metal10' , BasicLayer.Material.metal )
blockage1 = createBL( 'blockage1' , BasicLayer.Material.blockage )
blockage2 = createBL( 'blockage2' , BasicLayer.Material.blockage )
blockage3 = createBL( 'blockage3' , BasicLayer.Material.blockage )
blockage4 = createBL( 'blockage4' , BasicLayer.Material.blockage )
blockage5 = createBL( 'blockage5' , BasicLayer.Material.blockage )
blockage6 = createBL( 'blockage6' , BasicLayer.Material.blockage )
blockage7 = createBL( 'blockage7' , BasicLayer.Material.blockage )
blockage8 = createBL( 'blockage8' , BasicLayer.Material.blockage )
blockage9 = createBL( 'blockage9' , BasicLayer.Material.blockage )
blockage10 = createBL( 'blockage10', BasicLayer.Material.blockage )
metal1 .setBlockageLayer( blockage1 )
metal2 .setBlockageLayer( blockage2 )
metal3 .setBlockageLayer( blockage3 )
metal4 .setBlockageLayer( blockage4 )
metal5 .setBlockageLayer( blockage5 )
metal6 .setBlockageLayer( blockage6 )
metal7 .setBlockageLayer( blockage7 )
metal8 .setBlockageLayer( blockage8 )
metal9 .setBlockageLayer( blockage9 )
metal10.setBlockageLayer( blockage10 )
textCell = createBL( 'text.cell' , BasicLayer.Material.other ) # Misc. non-physical layers.
textInst = createBL( 'text.instance', BasicLayer.Material.other ) # Used by the software for visualization
SPL1 = createBL( 'SPL1' , BasicLayer.Material.other ) # purposes only.
AutoLayer = createBL( 'AutoLayer' , BasicLayer.Material.other )
gmetalh = createBL( 'gmetalh' , BasicLayer.Material.metal ) # Special BasicLayers for Knik & Kite Routers.
gcut = createBL( 'gcut' , BasicLayer.Material.cut ) # *Must be after all others*
gmetalv = createBL( 'gmetalv' , BasicLayer.Material.metal )
# VIAs for real technologies.
via12 = ViaLayer.create( tech, 'via12' , metal1, cut1, metal2 )
via23 = ViaLayer.create( tech, 'via23' , metal2, cut2, metal3 )
via34 = ViaLayer.create( tech, 'via34' , metal3, cut3, metal4 )
via45 = ViaLayer.create( tech, 'via45' , metal4, cut4, metal5 )
via56 = ViaLayer.create( tech, 'via56' , metal5, cut5, metal6 )
via67 = ViaLayer.create( tech, 'via67' , metal6, cut6, metal7 )
via78 = ViaLayer.create( tech, 'via78' , metal7, cut7, metal8 )
via89 = ViaLayer.create( tech, 'via89' , metal8, cut8, metal9 )
via910 = ViaLayer.create( tech, 'via910', metal9, cut9, metal10 )
# Composite/Symbolic layers.
NWELL = RegularLayer .create( tech, 'NWELL' , nWell )
PWELL = RegularLayer .create( tech, 'PWELL' , pWell )
NTIE = DiffusionLayer .create( tech, 'NTIE' , nImplant , active, nWell)
PTIE = DiffusionLayer .create( tech, 'PTIE' , pImplant , active, pWell)
NDIF = DiffusionLayer .create( tech, 'NDIF' , nImplant , active, None )
PDIF = DiffusionLayer .create( tech, 'PDIF' , pImplant , active, None )
GATE = DiffusionLayer .create( tech, 'GATE' , poly , active, None )
NTRANS = TransistorLayer.create( tech, 'NTRANS' , nImplant , active, poly, None )
PTRANS = TransistorLayer.create( tech, 'PTRANS' , pImplant , active, poly, None )
POLY = RegularLayer .create( tech, 'POLY' , poly )
POLY2 = RegularLayer .create( tech, 'POLY2' , poly2 )
METAL1 = RegularLayer .create( tech, 'METAL1' , metal1 )
METAL2 = RegularLayer .create( tech, 'METAL2' , metal2 )
metcapdum = RegularLayer .create( tech, 'metcapdum' , metcap )
metbot = RegularLayer .create( tech, 'metbot' , metal2 )
METAL3 = RegularLayer .create( tech, 'METAL3' , metal3 )
METAL4 = RegularLayer .create( tech, 'METAL4' , metal4 )
METAL5 = RegularLayer .create( tech, 'METAL5' , metal5 )
METAL6 = RegularLayer .create( tech, 'METAL6' , metal6 )
METAL7 = RegularLayer .create( tech, 'METAL7' , metal7 )
METAL8 = RegularLayer .create( tech, 'METAL8' , metal8 )
METAL9 = RegularLayer .create( tech, 'METAL9' , metal9 )
METAL10 = RegularLayer .create( tech, 'METAL10' , metal10 )
CONT_BODY_N = ContactLayer .create( tech, 'CONT_BODY_N', nImplant , cut0, active, metal1, None )
CONT_BODY_P = ContactLayer .create( tech, 'CONT_BODY_P', pImplant , cut0, active, metal1, None )
CONT_DIF_N = ContactLayer .create( tech, 'CONT_DIF_N' , nImplant , cut0, active, metal1, None )
CONT_DIF_P = ContactLayer .create( tech, 'CONT_DIF_P' , pImplant , cut0, active, metal1, None )
CONT_POLY = ViaLayer .create( tech, 'CONT_POLY' , poly , cut0, metal1 )
# VIAs for symbolic technologies.
VIA12 = ViaLayer .create( tech, 'VIA12' , metal1, cut1, metal2 )
VIA23 = ViaLayer .create( tech, 'VIA23' , metal2, cut2, metal3 )
VIA23cap = ViaLayer .create( tech, 'VIA23cap' , metcap, cut2, metal3 )
VIA34 = ViaLayer .create( tech, 'VIA34' , metal3, cut3, metal4 )
VIA45 = ViaLayer .create( tech, 'VIA45' , metal4, cut4, metal5 )
VIA56 = ViaLayer .create( tech, 'VIA56' , metal5, cut5, metal6 )
VIA67 = ViaLayer .create( tech, 'VIA67' , metal6, cut6, metal7 )
VIA78 = ViaLayer .create( tech, 'VIA78' , metal7, cut7, metal8 )
VIA89 = ViaLayer .create( tech, 'VIA89' , metal8, cut8, metal9 )
VIA910 = ViaLayer .create( tech, 'VIA910' , metal9, cut9, metal10 )
BLOCKAGE1 = RegularLayer.create( tech, 'BLOCKAGE1' , blockage1 )
BLOCKAGE2 = RegularLayer.create( tech, 'BLOCKAGE2' , blockage2 )
BLOCKAGE3 = RegularLayer.create( tech, 'BLOCKAGE3' , blockage3 )
BLOCKAGE4 = RegularLayer.create( tech, 'BLOCKAGE4' , blockage4 )
BLOCKAGE5 = RegularLayer.create( tech, 'BLOCKAGE5' , blockage5 )
BLOCKAGE6 = RegularLayer.create( tech, 'BLOCKAGE6' , blockage6 )
BLOCKAGE7 = RegularLayer.create( tech, 'BLOCKAGE7' , blockage7 )
BLOCKAGE8 = RegularLayer.create( tech, 'BLOCKAGE8' , blockage8 )
BLOCKAGE9 = RegularLayer.create( tech, 'BLOCKAGE9' , blockage9 )
BLOCKAGE10 = RegularLayer.create( tech, 'BLOCKAGE10', blockage10 )
gcontact = ViaLayer .create( tech, 'gcontact' , gmetalh , gcut, gmetalv )
tech.setSymbolicLayer( CONT_BODY_N.getName() )
tech.setSymbolicLayer( CONT_BODY_P.getName() )
tech.setSymbolicLayer( CONT_DIF_N .getName() )
tech.setSymbolicLayer( CONT_DIF_P .getName() )
tech.setSymbolicLayer( CONT_POLY .getName() )
tech.setSymbolicLayer( POLY .getName() )
tech.setSymbolicLayer( POLY2 .getName() )
tech.setSymbolicLayer( METAL1 .getName() )
tech.setSymbolicLayer( METAL2 .getName() )
tech.setSymbolicLayer( METAL3 .getName() )
tech.setSymbolicLayer( METAL4 .getName() )
tech.setSymbolicLayer( METAL5 .getName() )
tech.setSymbolicLayer( METAL6 .getName() )
tech.setSymbolicLayer( METAL7 .getName() )
tech.setSymbolicLayer( METAL8 .getName() )
tech.setSymbolicLayer( METAL9 .getName() )
tech.setSymbolicLayer( METAL10 .getName() )
tech.setSymbolicLayer( BLOCKAGE1 .getName() )
tech.setSymbolicLayer( BLOCKAGE2 .getName() )
tech.setSymbolicLayer( BLOCKAGE3 .getName() )
tech.setSymbolicLayer( BLOCKAGE4 .getName() )
tech.setSymbolicLayer( BLOCKAGE5 .getName() )
tech.setSymbolicLayer( BLOCKAGE6 .getName() )
tech.setSymbolicLayer( BLOCKAGE7 .getName() )
tech.setSymbolicLayer( BLOCKAGE8 .getName() )
tech.setSymbolicLayer( BLOCKAGE9 .getName() )
tech.setSymbolicLayer( BLOCKAGE10 .getName() )
tech.setSymbolicLayer( VIA12 .getName() )
tech.setSymbolicLayer( VIA23 .getName() )
tech.setSymbolicLayer( VIA34 .getName() )
tech.setSymbolicLayer( VIA45 .getName() )
tech.setSymbolicLayer( VIA56 .getName() )
tech.setSymbolicLayer( VIA67 .getName() )
tech.setSymbolicLayer( VIA78 .getName() )
tech.setSymbolicLayer( VIA89 .getName() )
tech.setSymbolicLayer( VIA910 .getName() )
tech.setSymbolicLayer( gcut .getName() )
tech.setSymbolicLayer( gmetalh .getName() )
tech.setSymbolicLayer( gmetalv .getName() )
tech.setSymbolicLayer( gcontact .getName() )
NWELL.setExtentionCap ( nWell, l(2.0) )
NWELL.setExtentionWidth( nWell, l(0.0) )
PWELL.setExtentionCap ( pWell, l(2.0) )
PWELL.setExtentionWidth( nWell, l(0.0) )
NTIE.setMinimalSize ( l(3.0) )
NTIE.setExtentionCap ( nWell , l(2.0) )
NTIE.setExtentionWidth( nWell , l(2.5) )
NTIE.setExtentionCap ( nImplant, l(1.5) )
NTIE.setExtentionWidth( nImplant, l(0.0) )
NTIE.setExtentionCap ( active , l(0.0) )
NTIE.setExtentionWidth( active , l(0.0) )
PTIE.setMinimalSize ( l(3.0) )
PTIE.setExtentionCap ( pWell , l(2.0) )
PTIE.setExtentionWidth( pWell , l(2.5) )
PTIE.setExtentionCap ( pImplant, l(1.5) )
PTIE.setExtentionWidth( pImplant, l(0.0) )
PTIE.setExtentionCap ( active , l(0.0) )
PTIE.setExtentionWidth( active , l(0.0) )
NDIF.setMinimalSize ( l(3.0) )
NDIF.setExtentionCap ( nImplant, l(0.5) )
NDIF.setExtentionWidth( nImplant, l(0.0) )
NDIF.setExtentionCap ( active , l(0.5) )
NDIF.setExtentionWidth( active , l(0.0) )
PDIF.setMinimalSize ( l(3.0) )
PDIF.setExtentionCap ( pImplant, l(0.5) )
PDIF.setExtentionWidth( pImplant, l(0.0) )
PDIF.setExtentionCap ( active , l(0.5) )
PDIF.setExtentionWidth( active , l(0.0) )
GATE.setMinimalSize ( l(1.0) )
GATE.setExtentionCap ( poly , l(1.5) )
NTRANS.setMinimalSize ( l( 1.0) )
NTRANS.setExtentionCap ( nImplant, l(-1.5) )
NTRANS.setExtentionWidth( nImplant, l( 3.0) )
NTRANS.setExtentionCap ( active , l(-1.5) )
NTRANS.setExtentionWidth( active , l( 2.0) )
PTRANS.setMinimalSize ( l( 1.0) )
PTRANS.setExtentionCap ( nWell , l(-1.5) )
PTRANS.setExtentionWidth( nWell , l( 2.5) )
PTRANS.setExtentionCap ( pImplant, l(-1.5) )
PTRANS.setExtentionWidth( pImplant, l( 2.5) )
PTRANS.setExtentionCap ( active , l(-1.5) )
PTRANS.setExtentionWidth( active , l( 2.5) )
POLY .setMinimalSize ( l(1.0) )
POLY .setExtentionCap ( poly , l(0.5) )
POLY2.setMinimalSize ( l(1.0) )
POLY2.setExtentionCap ( poly , l(0.5) )
METAL1 .setMinimalSize ( l(1.0) )
METAL1 .setExtentionCap ( metal1 , l(1.0) )
METAL2 .setMinimalSize ( l(1.0) )
METAL2 .setExtentionCap ( metal2 , l(1.0) )
METAL3 .setMinimalSize ( l(1.0) )
METAL3 .setExtentionCap ( metal3 , l(1.0) )
METAL4 .setMinimalSize ( l(1.0) )
METAL4 .setExtentionCap ( metal4 , l(1.0) )
METAL4 .setMinimalSpacing( l(3.0) )
METAL5 .setMinimalSize ( l(2.0) )
METAL5 .setExtentionCap ( metal5 , l(1.0) )
METAL6 .setMinimalSize ( l(2.0) )
METAL6 .setExtentionCap ( metal6 , l(1.0) )
METAL7 .setMinimalSize ( l(2.0) )
METAL7 .setExtentionCap ( metal7 , l(1.0) )
METAL8 .setMinimalSize ( l(2.0) )
METAL8 .setExtentionCap ( metal8 , l(1.0) )
METAL9 .setMinimalSize ( l(2.0) )
METAL9 .setExtentionCap ( metal9 , l(1.0) )
METAL10.setMinimalSize ( l(2.0) )
METAL10.setExtentionCap ( metal10 , l(1.0) )
# Contacts (i.e. Active <--> Metal) (symbolic).
CONT_BODY_N.setMinimalSize( l( 1.0) )
#CONT_BODY_N.setEnclosure ( nWell , l( 1.5), Layer.EnclosureH|Layer.EnclosureV )
CONT_BODY_N.setEnclosure ( nImplant, l( 1.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_BODY_N.setEnclosure ( cut0 , l( 0.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_BODY_N.setEnclosure ( active , l( 1.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_BODY_N.setEnclosure ( metal1 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
CONT_BODY_P.setMinimalSize( l( 1.0) )
#CONT_BODY_P.setEnclosure ( pWell , l( 1.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_BODY_P.setEnclosure ( pImplant, l( 1.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_BODY_P.setEnclosure ( cut0 , l( 0.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_BODY_P.setEnclosure ( active , l( 1.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_BODY_P.setEnclosure ( metal1 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
CONT_DIF_N.setMinimalSize( l( 1.0) )
CONT_DIF_N.setEnclosure ( nImplant, l( 1.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_DIF_N.setEnclosure ( cut0 , l( 0.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_DIF_N.setEnclosure ( active , l( 1.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_DIF_N.setEnclosure ( metal1 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
CONT_DIF_P.setMinimalSize( l( 1.0) )
CONT_DIF_P.setEnclosure ( pImplant, l( 1.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_DIF_P.setEnclosure ( cut0 , l( 0.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_DIF_P.setEnclosure ( active , l( 1.0), Layer.EnclosureH|Layer.EnclosureV )
CONT_DIF_P.setEnclosure ( metal1 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
CONT_POLY.setMinimalSize( l( 1.0) )
CONT_POLY.setEnclosure ( poly , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
CONT_POLY.setEnclosure ( metal1 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
# VIAs (i.e. Metal <--> Metal) (symbolic).
VIA12 .setMinimalSize ( l( 1.0) )
VIA12 .setEnclosure ( metal1 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA12 .setEnclosure ( metal2 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA12 .setMinimalSpacing( l( 4.0) )
VIA23 .setMinimalSize ( l( 1.0) )
VIA23 .setEnclosure ( metal2 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA23 .setEnclosure ( metal3 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA23 .setMinimalSpacing( l( 4.0) )
VIA34 .setMinimalSize ( l( 1.0) )
VIA34 .setEnclosure ( metal3 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA34 .setEnclosure ( metal4 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA34 .setMinimalSpacing( l( 4.0) )
VIA45 .setMinimalSize ( l( 1.0) )
VIA45 .setEnclosure ( metal4 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA45 .setEnclosure ( metal5 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA45 .setMinimalSpacing( l( 4.0) )
VIA56 .setMinimalSize ( l( 1.0) )
VIA56 .setEnclosure ( metal5 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA56 .setEnclosure ( metal6 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA56 .setMinimalSpacing( l( 4.0) )
VIA67 .setMinimalSize ( l( 1.0) )
VIA67 .setEnclosure ( metal6 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA67 .setEnclosure ( metal7 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA67 .setMinimalSpacing( l( 4.0) )
VIA78 .setMinimalSpacing( l( 4.0) )
VIA78 .setMinimalSize ( l( 1.0) )
VIA78 .setEnclosure ( metal7 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA78 .setEnclosure ( metal8 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA78 .setMinimalSpacing( l( 4.0) )
VIA89 .setMinimalSize ( l( 1.0) )
VIA89 .setEnclosure ( metal8 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA89 .setEnclosure ( metal9 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA89 .setMinimalSpacing( l( 4.0) )
VIA910.setMinimalSize ( l( 1.0) )
VIA910.setEnclosure ( metal9 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA910.setEnclosure ( metal10 , l( 0.5), Layer.EnclosureH|Layer.EnclosureV )
VIA910.setMinimalSpacing( l( 4.0) )
# Blockages (symbolic).
BLOCKAGE1 .setMinimalSize ( l( 1.0) )
BLOCKAGE1 .setExtentionCap( blockage1 , l( 0.5) )
BLOCKAGE2 .setMinimalSize ( l( 2.0) )
BLOCKAGE2 .setExtentionCap( blockage2 , l( 0.5) )
BLOCKAGE3 .setMinimalSize ( l( 2.0) )
BLOCKAGE3 .setExtentionCap( blockage3 , l( 0.5) )
BLOCKAGE4 .setMinimalSize ( l( 2.0) )
BLOCKAGE4 .setExtentionCap( blockage4 , l( 0.5) )
BLOCKAGE5 .setMinimalSize ( l( 2.0) )
BLOCKAGE5 .setExtentionCap( blockage5 , l( 1.0) )
BLOCKAGE6 .setMinimalSize ( l( 2.0) )
BLOCKAGE6 .setExtentionCap( blockage6 , l( 1.0) )
BLOCKAGE7 .setMinimalSize ( l( 2.0) )
BLOCKAGE7 .setExtentionCap( blockage7 , l( 1.0) )
BLOCKAGE8 .setMinimalSize ( l( 2.0) )
BLOCKAGE8 .setExtentionCap( blockage8 , l( 1.0) )
BLOCKAGE9 .setMinimalSize ( l( 2.0) )
BLOCKAGE9 .setExtentionCap( blockage9 , l( 1.0) )
BLOCKAGE10.setMinimalSize ( l( 2.0) )
BLOCKAGE10.setExtentionCap( blockage10, l( 1.0) )
gdsLayersTable = \
[ ("nWell" , "LNWELL" , 1, 0)
, ("nImplant", "LNIF" , 3, 0)
, ("pImplant", "LPDIF" , 4, 0)
, ("active" , "LACTIVE" , 2, 0)
, ("poly" , "LPOLY" , 7, 0)
, ("cut0" , "LCONT" , 10, 0)
, ("metal1" , "LALU1" , 11, 0)
, ("cut1" , "LVIA" , 14, 0)
, ("metal2" , "LALU2" , 16, 0)
, ("cut2" , "LVIA2" , 18, 0)
, ("metal3" , "LALU3" , 19, 0)
, ("cut3" , "LVIA3" , 21, 0)
, ("metal4" , "LALU4" , 22, 0)
, ("cut4" , "LVIA4" , 25, 0)
, ("metal5" , "LALU5" , 26, 0)
, ("cut5" , "LVIA5" , 28, 0)
, ("metal6" , "LALU6" , 29, 0)
]
loadGdsLayers( gdsLayersTable )

View File

@ -29,8 +29,9 @@ namespace CRL {
class LefImport {
public:
static void reset ();
static Hurricane::Library* load ( std::string fileName );
static void reset ();
static Hurricane::Library* load ( std::string fileName );
static void setMergeLibrary ( Hurricane::Library* );
};

View File

@ -33,6 +33,7 @@
#include "hurricane/Contact.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Rectilinear.h"
#include "hurricane/Cell.h"
#include "hurricane/Library.h"
#include "hurricane/UpdateSession.h"
@ -71,6 +72,7 @@ namespace {
class LefParser {
public:
static void setMergeLibrary ( Library* );
static DbU::Unit fromLefUnits ( int );
static Layer* getLayer ( string );
static void addLayer ( string, Layer* );
@ -108,8 +110,8 @@ namespace {
inline int getNthRouting () const;
inline void incNthRouting ();
inline RoutingGauge* getRoutingGauge () const;
inline void addPinSegment ( string name, Segment* );
inline void clearPinSegments ();
inline void addPinComponent ( string name, Component* );
inline void clearPinComponents ();
private:
static int _unitsCbk ( lefrCallbackType_e, lefiUnits* , lefiUserData );
static int _layerCbk ( lefrCallbackType_e, lefiLayer* , lefiUserData );
@ -121,6 +123,7 @@ namespace {
void _pinStdPostProcess ();
void _pinPadPostProcess ();
private:
static Library* _mergeLibrary;
string _file;
string _libraryName;
Library* _library;
@ -128,7 +131,7 @@ namespace {
Net* _net;
string _busBits;
double _unitsMicrons;
map< string, vector<Segment*> > _pinSegments;
map< string, vector<Component*> > _pinComponents;
static map<string,Layer*> _layerLut;
vector<string> _unmatchedLayers;
vector<string> _errors;
@ -170,15 +173,20 @@ namespace {
inline const vector<string>& LefParser::getErrors () const { return _errors; }
inline void LefParser::pushError ( const string& error ) { _errors.push_back(error); }
inline void LefParser::clearErrors () { return _errors.clear(); }
inline void LefParser::addPinSegment ( string name, Segment* s ) { _pinSegments[name].push_back(s); }
inline void LefParser::clearPinSegments () { _pinSegments.clear(); }
inline void LefParser::addPinComponent ( string name, Component* comp ) { _pinComponents[name].push_back(comp); }
inline void LefParser::clearPinComponents () { _pinComponents.clear(); }
Library* LefParser::_mergeLibrary = nullptr;
map<string,Layer*> LefParser::_layerLut;
DbU::Unit LefParser::_coreSiteX = 0;
DbU::Unit LefParser::_coreSiteY = 0;
void LefParser::setMergeLibrary ( Library* library )
{ _mergeLibrary = library; }
void LefParser::reset ()
{
_layerLut.clear();
@ -272,6 +280,11 @@ namespace {
Library* LefParser::createLibrary ()
{
if (_mergeLibrary) {
_library = _mergeLibrary;
return _library;
}
DataBase* db = DataBase::getDB();
Library* rootLibrary = db->getRootLibrary();
if (not rootLibrary) rootLibrary = Library::create( db, "RootLibrary" );
@ -499,6 +512,19 @@ namespace {
}
cdebug_log(100,0) << "| " << segment << endl;
}
if (geoms->itemType(igeom) == lefiGeomPolygonE) {
lefiGeomPolygon* polygon = geoms->getPolygon(igeom);
vector<Point> points;
for ( int ipoint=0 ; ipoint<polygon->numPoints ; ++ipoint ) {
points.push_back( Point( parser->fromUnitsMicrons(polygon->x[ipoint])
, parser->fromUnitsMicrons(polygon->y[ipoint]) ));
}
points.push_back( Point( parser->fromUnitsMicrons(polygon->x[0])
, parser->fromUnitsMicrons(polygon->y[0]) ));
Rectilinear::create( blockageNet, blockageLayer, points );
continue;
}
}
return 0;
@ -553,7 +579,7 @@ namespace {
if (not isPad) parser->_pinStdPostProcess();
else parser->_pinPadPostProcess();
parser->clearPinSegments();
parser->clearPinComponents();
cerr << " - " << cellName
<< " " << DbU::getValueString(width) << " " << DbU::getValueString(height)
@ -643,10 +669,23 @@ namespace {
, parser->fromUnitsMicrons( r->yh )
);
}
if (segment) parser->addPinSegment( pin->name(), segment );
if (segment) parser->addPinComponent( pin->name(), segment );
//cerr << " | " << segment << endl;
continue;
}
if (geoms->itemType(igeom) == lefiGeomPolygonE) {
lefiGeomPolygon* polygon = geoms->getPolygon(igeom);
vector<Point> points;
for ( int ipoint=0 ; ipoint<polygon->numPoints ; ++ipoint ) {
points.push_back( Point( parser->fromUnitsMicrons(polygon->x[ipoint])
, parser->fromUnitsMicrons(polygon->y[ipoint]) ));
}
points.push_back( Point( parser->fromUnitsMicrons(polygon->x[0])
, parser->fromUnitsMicrons(polygon->y[0]) ));
Rectilinear* rectilinear = Rectilinear::create( net, layer, points );
if (rectilinear) parser->addPinComponent( pin->name(), rectilinear );
continue;
}
if (geoms->itemType(igeom) == lefiGeomClassE) {
// Ignore CLASS <site>. Deduced from segments positions.
continue;
@ -688,20 +727,27 @@ namespace {
const RoutingLayerGauge* gaugeMetal2 = _routingGauge->getLayerGauge( 1 );
Box ab = _cell->getAbutmentBox();
//cerr << " @ _pinStdPostProcess" << endl;
cerr << " @ _pinStdPostProcess" << endl;
for ( auto element : _pinSegments ) {
string pinName = element.first;
vector<Segment*>& segments = element.second;
vector<Segment*> ongrids;
for ( auto element : _pinComponents ) {
string pinName = element.first;
vector<Component*>& components = element.second;
vector<Segment*> ongrids;
for ( Segment* segment : segments ) {
bool isWide = (segment->getWidth() >= getMinTerminalWidth());
for ( Component* component : components ) {
Segment* segment = dynamic_cast<Segment*>( component );
if (segment) {
if (component->getNet()->isSupply()) continue;
bool isWide = (segment->getWidth() >= getMinTerminalWidth());
//cerr << " > " << segment << endl;
cerr << " > " << segment << endl;
if (not isVH())
cerr << "NOT isVH()" << endl;
else
cerr << "isVH()" << endl;
if (not segment->getNet()->isSupply()) {
if (isVH() and (segment->getLayer()->getMask() == metal1->getMask())) {
cerr << "isVH()" << endl;
Vertical* v = dynamic_cast<Vertical*>( segment );
if (v) {
DbU::Unit nearestX = gaugeMetal2->getTrackPosition( ab.getXMin()
@ -712,7 +758,7 @@ namespace {
if (nearestX == v->getX()) {
} else {
DbU::Unit neighbor = nearestX
+ ((nearestX > v->getX()) ? 1 : -1) * gaugeMetal2->getPitch();
+ ((nearestX > v->getX()) ? 1 : -1) * gaugeMetal2->getPitch();
//cerr << " | X:" << DbU::getValueString(v->getX())
// << " nearestX:" << DbU::getValueString(nearestX)
@ -738,16 +784,67 @@ namespace {
}
}
}
}
if (isWide) ongrids.push_back( segment );
if (isWide) ongrids.push_back( segment );
}
Rectilinear* rectilinear = dynamic_cast<Rectilinear*>( component );
if (not (rectilinear->getLayer()->getMask() == metal1->getMask()))
continue;
if (rectilinear) {
cerr << " > " << rectilinear << endl;
vector<Box> boxes;
rectilinear->getAsRectangles( boxes );
if (component->getNet()->isSupply()) {
ongrids.push_back( Horizontal::create( rectilinear->getNet()
, rectilinear->getLayer()
, boxes.front().getYCenter()
, boxes.front().getHeight()
, _cell->getAbutmentBox().getXMin()
, _cell->getAbutmentBox().getXMax()
)
);
} else {
for ( const Box& box : boxes ) {
DbU::Unit nearestX = gaugeMetal2->getTrackPosition( ab.getXMin()
, ab.getXMax()
, box.getXCenter()
, Constant::Nearest );
DbU::Unit xmin = std::min( box.getXMin(), nearestX - gaugeMetal2->getViaWidth()/2 );
DbU::Unit xmax = std::max( box.getXMax(), nearestX + gaugeMetal2->getViaWidth()/2 );
ongrids.push_back( Vertical::create( rectilinear->getNet()
, rectilinear->getLayer()
, (xmax+xmin)/2
, xmax-xmin
, box.getYMin()
, box.getYMax()
)
);
// DbU::Unit neighbor = nearestY
// + ((nearestY > box.getYCenter()) ? 1 : -1) * gaugeMetal2->getPitch();
// if ( (box.getYMin() > neighbor)
// or (box.getYMax() < neighbor) ) {
// ongrids.push_back( Vertical::create( rectilinear->getNet()
// , rectilinear->getLayer()
// , box.getXCenter()
// , box.getWidth()
// , box.getYMin()
// , box.getYMax()
// )
// );
// }
}
}
}
}
if (ongrids.empty()) {
cerr << Warning( "LefParser::_pinStdPostProcess(): Pin \"%s\" has no terminal ongrid."
, pinName.c_str() ) << endl;
for ( Segment* segment : segments ) {
NetExternalComponents::setExternal( segment );
for ( Component* component : components ) {
NetExternalComponents::setExternal( component );
}
} else {
for ( Segment* segment : ongrids ) {
@ -763,10 +860,10 @@ namespace {
Box ab = getCell()->getAbutmentBox();
bool isCornerPad = (_cellGauge) and (_cellGauge->getSliceHeight() == _cellGauge->getSliceStep());
for ( auto element : _pinSegments ) {
string pinName = element.first;
vector<Segment*>& segments = element.second;
vector<Segment*> ongrids;
for ( auto element : _pinComponents ) {
string pinName = element.first;
vector<Component*>& segments = element.second;
vector<Segment*> ongrids;
if (segments.empty()) continue;
@ -963,4 +1060,12 @@ namespace CRL {
}
void LefImport::setMergeLibrary ( Library* library )
{
#if defined(HAVE_LEFDEF)
LefParser::setMergeLibrary( library );
#endif
}
} // End of CRL namespace.

View File

@ -1,6 +1,5 @@
# -*- explicit-buffer-name: "CMakeLists.txt<crlcore/src/ccore/cyclop>" -*-
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
include_directories ( ${CRLCORE_SOURCE_DIR}/src/ccore
${HURRICANE_INCLUDE_DIR}
${UTILITIES_INCLUDE_DIR}

View File

@ -32,8 +32,6 @@
-lutil
)
find_package (Python3 COMPONENTS Interpreter Development)
add_definitions( -DCORIOLIS_TOP="${CORIOLIS_TOP}"
-DSYS_CONF_DIR="${SYS_CONF_DIR}"
-DPYTHON_SITE_PACKAGES="${PYTHON_SITE_PACKAGES}"

View File

@ -43,6 +43,8 @@ namespace CRL {
using Isobar::ParseTwoArg;
using Isobar::__cs;
using Isobar::PyLibrary_Link;
using Isobar::PyTypeLibrary;
using Isobar::PyLibrary;
extern "C" {
@ -86,14 +88,37 @@ extern "C" {
}
static PyObject* PyLefImport_setMergeLibrary ( PyObject*, PyObject* args )
{
cdebug_log(30,0) << "PyLefImport_setMergeLibrary()" << endl;
HTRY
PyObject* pyLibrary = NULL;
if (PyArg_ParseTuple( args, "O:LefImport.setMergeLibrary", &pyLibrary )) {
if (IsPyLibrary(pyLibrary)) {
LefImport::setMergeLibrary( PYLIBRARY_O(pyLibrary) );
} else {
PyErr_SetString( ConstructorError, "LefImport.setMergeLibrary(): Bad parameter type (not a Library)." );
return NULL;
}
} else {
PyErr_SetString( ConstructorError, "LefImport.setMergeLibrary(): Bad number of parameters." );
return NULL;
}
HCATCH
Py_RETURN_NONE;
}
// Standart Destroy (Attribute).
PyMethodDef PyLefImport_Methods[] =
{ { "load" , (PyCFunction)PyLefImport_load , METH_VARARGS|METH_STATIC
{ { "load" , (PyCFunction)PyLefImport_load , METH_VARARGS|METH_STATIC
, "Load a complete Cadence LEF library." }
, { "reset" , (PyCFunction)PyLefImport_reset , METH_NOARGS|METH_STATIC
, { "reset" , (PyCFunction)PyLefImport_reset , METH_NOARGS|METH_STATIC
, "Reset the Cadence LEF parser (clear technology)." }
, { "setMergeLibrary" , (PyCFunction)PyLefImport_setMergeLibrary, METH_VARARGS|METH_STATIC
, "Merge into this library instead of creating a new one." }
//, { "destroy" , (PyCFunction)PyLefImport_destroy , METH_VARARGS
// , "Destroy the associated hurricane object. The python object remains." }
, {NULL, NULL, 0, NULL} /* sentinel */

View File

@ -1,7 +1,6 @@
# -*- explicit-buffer-name: "CMakeLists.txt<crlcore/src/x2y> -*-
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
include_directories ( ${CRLCORE_SOURCE_DIR}/src/ccore
${HURRICANE_INCLUDE_DIR}
${UTILITIES_INCLUDE_DIR}

View File

@ -69,7 +69,13 @@ class ShellEnv ( object ):
self.shellEnv[ 'MBK_CATAL_NAME' ] = env.getCATALOG()
self.shellEnv[ 'RDS_IN' ] = 'gds'
self.shellEnv[ 'RDS_OUT' ] = 'gds'
self.shellEnv[ 'ALLIANCE_TOP' ] = ShellEnv.ALLIANCE_TOP
if ShellEnv.ALLIANCE_TOP:
self.shellEnv[ 'ALLIANCE_TOP' ] = ShellEnv.ALLIANCE_TOP
libPath = ShellEnv.ALLIANCE_TOP + '/lib'
LD_LIBRARY_PATH = os.environ[ 'LD_LIBRARY_PATH' ]
if LD_LIBRARY_PATH != '':
libPath += ':' + LD_LIBRARY_PATH
self.shellEnv[ 'LD_LIBRARY_PATH' ] = libPath
def export ( self ):
"""

View File

@ -42,7 +42,10 @@ class Where ( object ):
return '<Where coriolisTop="{}">'.format( Where.coriolisTop.as_posix() )
def setupCMOS ():
def setupCMOS ( checkToolkit=None ):
Where( checkToolkit )
ShellEnv().export()
from .. import Cfg
from .. import Viewer
from .. import CRL
@ -50,8 +53,6 @@ def setupCMOS ():
from .yosys import Yosys
import coriolis.technos.symbolic.cmos
Where()
with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg:
cfg.misc.catchCore = False
cfg.misc.info = False
@ -81,6 +82,46 @@ def setupCMOS ():
break
def setupLCMOS ( checkToolkit=None ):
Where( checkToolkit )
ShellEnv().export()
from .. import Cfg
from .. import Viewer
from .. import CRL
from ..helpers import overlay, l, u, n
from .yosys import Yosys
import coriolis.technos.symbolic.lcmos
with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg:
cfg.misc.catchCore = False
cfg.misc.info = False
cfg.misc.paranoid = False
cfg.misc.bug = False
cfg.misc.logMode = True
cfg.misc.verboseLevel1 = True
cfg.misc.verboseLevel2 = True
cfg.misc.minTraceLevel = 1900
cfg.misc.maxTraceLevel = 3000
cfg.katana.eventsLimit = 1000000
cfg.katana.termSatReservedLocal = 6
cfg.katana.termSatThreshold = 9
Viewer.Graphics.setStyle( 'Alliance.Classic [black]' )
af = CRL.AllianceFramework.get()
env = af.getEnvironment()
env.setCLOCK( '^ck$|m_clock|^clk$' )
Yosys.setLiberty( Where.checkToolkit / 'cells' / 'lsxlib' / 'lsxlib.lib' )
ShellEnv.RDS_TECHNO_NAME = (Where.allianceTop / 'etc' / 'cmos.rds').as_posix()
path = None
for pathVar in [ 'PATH', 'path' ]:
if pathVar in os.environ:
path = os.environ[ pathVar ]
os.environ[ pathVar ] = path + ':' + (Where.allianceTop / 'bin').as_posix()
break
def setupCMOS45 ( useNsxlib=False, checkToolkit=None, cellsTop=None ):
from .. import Cfg
from .. import Viewer
@ -295,7 +336,7 @@ def setupTSMC_c180_c4m ( checkToolkit=None, ndaTop=None ):
cfg.misc.verboseLevel1 = True
cfg.misc.verboseLevel2 = True
cfg.etesian.graphics = 3
cfg.etesian.uniformDensity = True
cfg.etesian.densityVariation = 0.04
cfg.etesian.spaceMargin = 0.04
cfg.katana.eventsLimit = 4000000
af = CRL.AllianceFramework.get()
@ -304,3 +345,52 @@ def setupTSMC_c180_c4m ( checkToolkit=None, ndaTop=None ):
Yosys.setLiberty( liberty )
ShellEnv.CHECK_TOOLKIT = Where.checkToolkit.as_posix()
def setupGF180MCU_GF ( checkToolkit=None, pdkTop=None ):
from .. import Cfg
from .. import Viewer
from .. import CRL
from ..helpers import setNdaTopDir, overlay, l, u, n
from .yosys import Yosys
if isinstance(pdkTop,str):
pdkTop = Path( pdkTop )
if not pdkTop:
print( '[ERROR] technos.setupGF180MCU_GF(): pdkTop directory has *not* been set.' )
if not pdkTop.is_dir():
print( '[ERROR] technos.setupSky130_c4m(): pdkTop directory do *not* exists:' )
print( ' "{}"'.format(pdkTop.as_posix()) )
Where( checkToolkit )
cellsTop = pdkTop / 'libraries' / 'gf180mcu_fd_sc_mcu9t5v0' / 'latest' / 'cells'
#liberty = pdkTop / 'libraries' / 'gf180mcu_fd_sc_mcu9t5v0' / 'latest' / 'liberty' / 'gf180mcu_fd_sc_mcu9t5v0__tt_025C_5v00.lib'
liberty = pdkTop / 'FULL.lib'
from coriolis.technos.node180.gf180mcu import techno
from coriolis.technos.node180.gf180mcu import mcu9t5v0
techno.setup()
mcu9t5v0.setup( cellsTop )
with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg:
cfg.misc.catchCore = False
cfg.misc.minTraceLevel = 12300
cfg.misc.maxTraceLevel = 12400
cfg.misc.info = False
cfg.misc.paranoid = False
cfg.misc.bug = False
cfg.misc.logMode = True
cfg.misc.verboseLevel1 = False
cfg.misc.verboseLevel2 = False
cfg.etesian.graphics = 2
cfg.anabatic.topRoutingLayer = 'm4'
cfg.katana.eventsLimit = 4000000
af = CRL.AllianceFramework.get()
#lg5 = af.getRoutingGauge( 'mcu9t' ).getLayerGauge( 5 )
#lg5.setType( CRL.RoutingLayerGauge.PowerSupply )
env = af.getEnvironment()
env.setCLOCK( '^sys_clk$|^ck|^jtag_tck$' )
Yosys.setLiberty( liberty )
ShellEnv.CHECK_TOOLKIT = Where.checkToolkit.as_posix()

View File

@ -21,13 +21,13 @@ The ``sram`` module provide base classes for SRAM assemby.
import sys
import re
import traceback
from ..helpers.io import ErrorMessage, WarningMessage
from ..helpers.overlay import UpdateSession
from ..helpers import trace, l, u, n
from ..Hurricane import DataBase, Breakpoint, DbU, Box, Net, Cell, \
Instance, Transformation, PythonAttributes
from .. import CRL
from .chip.configuration import GaugeConf
from ...helpers.io import ErrorMessage, WarningMessage
from ...helpers.overlay import UpdateSession
from ...helpers import trace, l, u, n
from ...Hurricane import DataBase, Breakpoint, DbU, Box, Net, Cell, \
Instance, Transformation, PythonAttributes
from ... import CRL
from ..block.configuration import GaugeConf
af = CRL.AllianceFramework.get()

View File

@ -176,15 +176,15 @@ Conclusion for the nand2+nor2 implementation:
import sys
import re
import traceback
from ...helpers.io import ErrorMessage, WarningMessage
from ...helpers.overlay import UpdateSession
from ...helpers import trace, l, u, n
from ...Hurricane import Breakpoint, DbU, Box, Net, Cell, Instance, \
Transformation, PythonAttributes
from ... import CRL
from ..chip.configuration import GaugeConf
from .sram import Bus, Column, ColBlock, ColGroup, \
HeaderRow, BaseSRAM
from ...helpers.io import ErrorMessage, WarningMessage
from ...helpers.overlay import UpdateSession
from ...helpers import trace, l, u, n
from ...Hurricane import Breakpoint, DbU, Box, Net, Cell, Instance, \
Transformation, PythonAttributes
from ... import CRL
from ..block.configuration import GaugeConf
from .sram import Bus, Column, ColBlock, ColGroup, \
HeaderRow, BaseSRAM
"""

View File

@ -36,15 +36,15 @@ You can configure the placer in two ways:
.. code-block:: Python
with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg:
cfg.etesian.effort = 2
cfg.etesian.uniformDensity = True
cfg.etesian.spaceMargin = 0.8
cfg.etesian.aspectRatio = 1.0
cfg.etesian.effort = 2
cfg.etesian.spaceMargin = 0.8
cfg.etesian.densityVariation = 0.1
cfg.etesian.aspectRatio = 1.0
With this setup, the cells will be spread uniformally over the
area (``etesian.uniformDensity``), with ``80%`` of free space
added and an aspect ratio of ``100%`` (square shape).
With this setup, the placement will have ``80%`` of free space added and
an aspect ratio of ``100%`` (square shape). Some variations in density
is allowed, with at most ``10%`` unused space.
8.1 Router -- Katana

View File

@ -176,11 +176,10 @@ Etesian Configuration Parameters
| | The extra white space added to the total area |
| | of the standard cells |
+-----------------------------------+------------------+----------------------------+
|``etesian.uniformDensity`` | TypeBool | :cb:`False` |
|``etesian.densityVariation`` | TypePercentage | :cb:`5` |
| +------------------+----------------------------+
| | Whether the cells will be spread envenly |
| | across the area or allowed to form denser |
| | clusters |
| | Control deviation from uniform density in the |
| | placement, as a percentage of area. |
+-----------------------------------+------------------+----------------------------+
|``etesian.effort`` | TypeInt | :cb:`2` |
| +------------------+----------------------------+

View File

@ -24,8 +24,8 @@ with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg:
cfg.misc.minTraceLevel = 1900
cfg.misc.maxTraceLevel = 3000
cfg.etesian.effort = 2
cfg.etesian.uniformDensity = True
cfg.etesian.spaceMargin = 0.8
cfg.etesian.densityVariation = 0.1
cfg.etesian.aspectRatio = 1.0
cfg.katana.eventsLimit = 1000000
cfg.katana.termSatReservedLocal = 6

View File

@ -176,11 +176,10 @@ Etesian Configuration Parameters
| | The extra white space added to the total area |
| | of the standard cells |
+-----------------------------------+------------------+----------------------------+
|``etesian.uniformDensity`` | TypeBool | :cb:`False` |
|``etesian.densityVariation`` | TypePercentage | :cb:`5` |
| +------------------+----------------------------+
| | Whether the cells will be spread envenly |
| | across the area or allowed to form denser |
| | clusters |
| | Control deviation from uniform density in the |
| | placement, as a percentage of area. |
+-----------------------------------+------------------+----------------------------+
|``etesian.effort`` | TypeInt | :cb:`2` |
| +------------------+----------------------------+

View File

@ -17,8 +17,8 @@
set_cmake_policies()
setup_boost(program_options)
setup_python()
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
find_package(PythonSitePackages REQUIRED)
find_package(HURRICANE REQUIRED)
#find_package(KATABATIC REQUIRED)

View File

@ -10,7 +10,6 @@
${Boost_INCLUDE_DIRS}
${Python_INCLUDE_DIRS}
)
find_package (Python3 COMPONENTS Interpreter Development)
set( includes etesian/Configuration.h
etesian/Placement.h
etesian/FeedCells.h

View File

@ -56,13 +56,11 @@ namespace Etesian {
, _placeEffort ( static_cast<Effort>
(Cfg::getParamEnumerate ("etesian.effort" , Standard )->asInt()) )
, _updateConf ( static_cast<GraphicUpdate>
(Cfg::getParamEnumerate ("etesian.graphics" , LowerBound )->asInt()) )
, _spreadingConf ( Cfg::getParamBool ("etesian.uniformDensity" , false )->asBool()? ForceUniform : MaxDensity )
(Cfg::getParamEnumerate ("etesian.graphics" , FinalOnly )->asInt()) )
, _routingDriven ( Cfg::getParamBool ("etesian.routingDriven" , false )->asBool())
, _spaceMargin ( Cfg::getParamPercentage("etesian.spaceMargin" , 5.0)->asDouble() )
, _densityVariation ( Cfg::getParamPercentage("etesian.densityVariation", 5.0)->asDouble() )
, _aspectRatio ( Cfg::getParamPercentage("etesian.aspectRatio" ,100.0)->asDouble() )
, _antennaInsertThreshold
( Cfg::getParamDouble ("etesian.antennaInsertThreshold", 50.0)->asDouble() )
, _tieName ( Cfg::getParamString ("etesian.tieName" ,"tie_x0" )->asString() )
, _feedNames ( Cfg::getParamString ("etesian.feedNames" ,"tie_x0,rowend_x0")->asString() )
, _diodeName ( Cfg::getParamString ("etesian.diodeName" ,"dio_x0" )->asString() )
@ -107,18 +105,17 @@ namespace Etesian {
, _cg (NULL)
, _placeEffort ( other._placeEffort )
, _updateConf ( other._updateConf )
, _spreadingConf ( other._spreadingConf )
, _spaceMargin ( other._spaceMargin )
, _densityVariation ( other._densityVariation)
, _aspectRatio ( other._aspectRatio )
, _antennaInsertThreshold( other._antennaInsertThreshold )
, _tieName ( other._tieName )
, _feedNames ( other._feedNames )
, _diodeName ( other._diodeName )
, _spareBufferName ( other._spareBufferName )
, _bloat ( other._bloat )
, _latchUpDistance ( other._latchUpDistance )
, _antennaGateMaxWL ( other._antennaGateMaxWL )
, _antennaDiodeMaxWL( other._antennaDiodeMaxWL )
, _antennaGateMaxWL ( other._antennaGateMaxWL )
, _antennaDiodeMaxWL( other._antennaDiodeMaxWL)
{
if (other._rg) _rg = other._rg->getClone();
if (other._cg) _cg = other._cg->getClone();
@ -141,12 +138,11 @@ namespace Etesian {
cmess1 << Dots::asIdentifier(" - Cell Gauge" ,getString(_cg->getName())) << endl;
cmess1 << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl;
cmess1 << Dots::asInt (" - Update Conf" ,_updateConf ) << endl;
cmess1 << Dots::asInt (" - Spreading Conf" ,_spreadingConf ) << endl;
cmess1 << Dots::asBool (" - Routing driven" ,_routingDriven ) << endl;
cmess1 << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl;
cmess1 << Dots::asPercentage(" - Spread Margin" ,_densityVariation ) << endl;
cmess1 << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl;
cmess1 << Dots::asString (" - Bloat model" ,_bloat ) << endl;
cmess1 << Dots::asPercentage(" - Antenna Insert" ,_antennaInsertThreshold ) << endl;
cmess1 << Dots::asString (" - Antenna gate Max. WL" ,DbU::getValueString(_antennaGateMaxWL )) << endl;
cmess1 << Dots::asString (" - Antenna diode Max. WL",DbU::getValueString(_antennaDiodeMaxWL)) << endl;
cmess1 << Dots::asString (" - Latch up Distance",DbU::getValueString(_latchUpDistance)) << endl;
@ -174,11 +170,10 @@ namespace Etesian {
record->add ( getSlot( "_cg" , _cg ) );
record->add ( getSlot( "_placeEffort" , (int)_placeEffort ) );
record->add ( getSlot( "_updateConf" , (int)_updateConf ) );
record->add ( getSlot( "_spreadingConf" , (int)_spreadingConf ) );
record->add ( getSlot( "_spaceMargin" , _spaceMargin ) );
record->add ( getSlot( "_densityVariation" , _densityVariation ) );
record->add ( getSlot( "_aspectRatio" , _aspectRatio ) );
record->add ( getSlot( "_antennaInsertThreshold", _antennaInsertThreshold ) );
record->add ( getSlot( "_tieName" , _tieName ) );
record->add ( getSlot( "_tieName" , _tieName ) );
record->add ( getSlot( "_feedNames" , _feedNames ) );
record->add ( getSlot( "_diodeName" , _diodeName ) );
record->add ( getSlot( "_spareBufferName" , _spareBufferName ) );

File diff suppressed because it is too large Load Diff

View File

@ -81,6 +81,7 @@ extern "C" {
DirectSetLongAttribute (PyEtesianEngine_setFixedAbHeight,setFixedAbHeight,PyEtesianEngine,EtesianEngine)
DirectSetLongAttribute (PyEtesianEngine_setFixedAbWidth ,setFixedAbWidth ,PyEtesianEngine,EtesianEngine)
DirectSetDoubleAttribute (PyEtesianEngine_setSpaceMargin ,setSpaceMargin ,PyEtesianEngine,EtesianEngine)
DirectSetDoubleAttribute (PyEtesianEngine_setDensityVariation,setDensityVariation ,PyEtesianEngine,EtesianEngine)
DirectSetDoubleAttribute (PyEtesianEngine_setAspectRatio ,setAspectRatio ,PyEtesianEngine,EtesianEngine)
DirectGetLongAttribute (PyEtesianEngine_getFixedAbHeight,getFixedAbHeight,PyEtesianEngine,EtesianEngine)
DirectGetLongAttribute (PyEtesianEngine_getFixedAbWidth ,getFixedAbWidth ,PyEtesianEngine,EtesianEngine)
@ -273,6 +274,8 @@ extern "C" {
, "Use this width when computing the size of the default abutment box (disable aspect ratio)." }
, { "setSpaceMargin" , (PyCFunction)PyEtesianEngine_setSpaceMargin , METH_VARARGS
, "Override the configuration space margin parameter value." }
, { "setDensityVariation" , (PyCFunction)PyEtesianEngine_setDensityVariation, METH_VARARGS
, "Override the configuration density variation parameter value." }
, { "setAspectRatio" , (PyCFunction)PyEtesianEngine_setAspectRatio , METH_VARARGS
, "Override the configuration aspect ratio parameter value." }
, { "resetPlacement" , (PyCFunction)PyEtesianEngine_resetPlacement , METH_NOARGS

View File

@ -40,17 +40,14 @@ namespace Etesian {
// Class : "Etesian::Configuration".
enum Effort { Fast =1
, Standard=2
, High =3
, Extreme =4
, Standard=3
, High =6
, Extreme =9
};
enum GraphicUpdate { UpdateAll =1
, LowerBound=2
, FinalOnly =3
};
enum Density { ForceUniform=1
, MaxDensity =2
};
class Configuration {
public:
@ -63,11 +60,10 @@ namespace Etesian {
inline CellGauge* getCellGauge () const;
inline Effort getPlaceEffort () const;
inline GraphicUpdate getUpdateConf () const;
inline Density getSpreadingConf () const;
inline bool getRoutingDriven () const;
inline double getSpaceMargin () const;
inline double getDensityVariation () const;
inline double getAspectRatio () const;
inline double getAntennaInsertThreshold () const;
inline string getTieName () const;
inline string getFeedNames () const;
inline string getDiodeName () const;
@ -77,6 +73,7 @@ namespace Etesian {
inline DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getAntennaDiodeMaxWL () const;
inline void setSpaceMargin ( double );
inline void setDensityVariation ( double );
inline void setAspectRatio ( double );
void print ( Cell* ) const;
Record* _getRecord () const;
@ -88,11 +85,10 @@ namespace Etesian {
CellGauge* _cg;
Effort _placeEffort;
GraphicUpdate _updateConf;
Density _spreadingConf;
bool _routingDriven;
double _spaceMargin;
double _densityVariation;
double _aspectRatio;
double _antennaInsertThreshold;
string _tieName;
string _feedNames;
string _diodeName;
@ -111,11 +107,10 @@ namespace Etesian {
inline CellGauge* Configuration::getCellGauge () const { return _cg; }
inline Effort Configuration::getPlaceEffort () const { return _placeEffort; }
inline GraphicUpdate Configuration::getUpdateConf () const { return _updateConf; }
inline Density Configuration::getSpreadingConf () const { return _spreadingConf; }
inline bool Configuration::getRoutingDriven () const { return _routingDriven; }
inline double Configuration::getSpaceMargin () const { return _spaceMargin; }
inline double Configuration::getDensityVariation () const { return _densityVariation; }
inline double Configuration::getAspectRatio () const { return _aspectRatio; }
inline double Configuration::getAntennaInsertThreshold () const { return _antennaInsertThreshold; }
inline string Configuration::getTieName () const { return _tieName; }
inline string Configuration::getFeedNames () const { return _feedNames; }
inline string Configuration::getDiodeName () const { return _diodeName; }
@ -125,6 +120,7 @@ namespace Etesian {
inline DbU::Unit Configuration::getAntennaGateMaxWL () const { return _antennaGateMaxWL; }
inline DbU::Unit Configuration::getAntennaDiodeMaxWL () const { return _antennaDiodeMaxWL; }
inline void Configuration::setSpaceMargin ( double margin ) { _spaceMargin = margin; }
inline void Configuration::setDensityVariation ( double margin ) { _densityVariation = margin; }
inline void Configuration::setAspectRatio ( double ratio ) { _aspectRatio = ratio; }

View File

@ -18,7 +18,7 @@
#include <tuple>
#include <iostream>
#include <unordered_map>
#include "coloquinte/circuit.hxx"
#include "coloquinte/coloquinte.hpp"
#include "hurricane/Timer.h"
#include "hurricane/Name.h"
@ -70,7 +70,6 @@ namespace Etesian {
typedef std::tuple<Net*,int32_t,uint32_t> NetInfos;
typedef std::tuple<Instance*, std::vector<RoutingPad*> > InstanceInfos;
typedef std::map<Instance*,size_t,DBo::CompareById> InstancesToIds;
typedef std::map<Net*,size_t,DBo::CompareById> NetsToIds;
typedef std::set<std::string> NetNameSet;
public:
static const Name& staticGetName ();
@ -91,10 +90,9 @@ namespace Etesian {
inline DbU::Unit getFixedAbWidth () const;
inline Effort getPlaceEffort () const;
inline GraphicUpdate getUpdateConf () const;
inline Density getSpreadingConf () const;
inline double getSpaceMargin () const;
inline double getDensityVariation () const;
inline double getAspectRatio () const;
inline double getAntennaInsertThreshold () const;
inline DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getAntennaDiodeMaxWL () const;
inline DbU::Unit getLatchUpDistance () const;
@ -114,6 +112,7 @@ namespace Etesian {
inline void setFixedAbHeight ( DbU::Unit );
inline void setFixedAbWidth ( DbU::Unit );
inline void setSpaceMargin ( double );
inline void setDensityVariation ( double );
inline void setAspectRatio ( double );
void setDefaultAb ();
void adjustSliceHeight ();
@ -131,11 +130,8 @@ namespace Etesian {
inline Transformation toBlock ( const Transformation& ) const;
void setPlaceArea ( const Box& );
size_t toColoquinte ();
void preplace ();
void roughLegalize ( float minDisruption, unsigned options );
void globalPlace ( float initPenalty, float minDisruption, float targetImprovement, float minInc, float maxInc, unsigned options=0 );
void detailedPlace ( int iterations, int effort, unsigned options=0 );
void antennaProtect ();
void globalPlace ();
void detailedPlace ();
void place ();
uint32_t doHFNS ();
inline void useFeed ( Cell* );
@ -160,15 +156,12 @@ namespace Etesian {
bool _flatDesign;
Box _placeArea;
std::vector<Box> _trackAvoids;
coloquinte::box<coloquinte::int_t>* _surface;
coloquinte::netlist* _circuit;
coloquinte::placement_t* _placementLB;
coloquinte::placement_t* _placementUB;
coloquinte::density_restrictions* _densityLimits;
NetsToIds _netsToIds;
coloquinte::Rectangle* _surface;
coloquinte::Circuit* _circuit;
coloquinte::PlacementSolution* _placementLB;
coloquinte::PlacementSolution* _placementUB;
InstancesToIds _instsToIds;
std::vector<InstanceInfos> _idsToInsts;
std::vector<NetInfos> _idsToNets;
Hurricane::CellViewer* _viewer;
Cell* _diodeCell;
FeedCells _feedCells;
@ -195,9 +188,9 @@ namespace Etesian {
private:
inline uint32_t _getNewDiodeId ();
Instance* _createDiode ( Cell* );
void _updatePlacement ( const coloquinte::placement_t*, uint32_t flags=0 );
void _progressReport1 ( string label ) const;
void _progressReport2 ( string label ) const;
void _updatePlacement ( const coloquinte::PlacementSolution* );
void _coloquinteCallback(coloquinte::PlacementStep step);
void _checkNotAFeed ( Occurrence occurrence ) const;
};
@ -214,10 +207,9 @@ namespace Etesian {
inline DbU::Unit EtesianEngine::getFixedAbWidth () const { return _fixedAbWidth; }
inline Effort EtesianEngine::getPlaceEffort () const { return getConfiguration()->getPlaceEffort(); }
inline GraphicUpdate EtesianEngine::getUpdateConf () const { return getConfiguration()->getUpdateConf(); }
inline Density EtesianEngine::getSpreadingConf () const { return getConfiguration()->getSpreadingConf(); }
inline double EtesianEngine::getSpaceMargin () const { return getConfiguration()->getSpaceMargin(); }
inline double EtesianEngine::getDensityVariation () const { return getConfiguration()->getDensityVariation(); }
inline double EtesianEngine::getAspectRatio () const { return getConfiguration()->getAspectRatio(); }
inline double EtesianEngine::getAntennaInsertThreshold () const { return getConfiguration()->getAntennaInsertThreshold(); }
inline DbU::Unit EtesianEngine::getAntennaGateMaxWL () const { return getConfiguration()->getAntennaGateMaxWL(); }
inline DbU::Unit EtesianEngine::getAntennaDiodeMaxWL () const { return getConfiguration()->getAntennaDiodeMaxWL(); }
inline DbU::Unit EtesianEngine::getLatchUpDistance () const { return getConfiguration()->getLatchUpDistance(); }
@ -232,6 +224,7 @@ namespace Etesian {
inline void EtesianEngine::setFixedAbHeight ( DbU::Unit abHeight ) { _fixedAbHeight = abHeight; }
inline void EtesianEngine::setFixedAbWidth ( DbU::Unit abWidth ) { _fixedAbWidth = abWidth; }
inline void EtesianEngine::setSpaceMargin ( double margin ) { getConfiguration()->setSpaceMargin(margin); }
inline void EtesianEngine::setDensityVariation ( double margin ) { getConfiguration()->setDensityVariation(margin); }
inline void EtesianEngine::setAspectRatio ( double ratio ) { getConfiguration()->setAspectRatio(ratio); }
inline DbU::Unit EtesianEngine::toDbU ( int64_t v ) const { return v*getSliceStep(); }
inline uint32_t EtesianEngine::_getNewDiodeId () { return _diodeCount++; }

View File

@ -16,8 +16,8 @@
set_cmake_policies()
check_distribution()
setup_sysconfdir( "${CMAKE_INSTALL_PREFIX}" )
setup_python()
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
find_package(PythonSitePackages REQUIRED)
find_package(HURRICANE REQUIRED)
find_package(CORIOLIS REQUIRED)

View File

@ -6,7 +6,6 @@
${CONFIGURATION_INCLUDE_DIR}
${Python_INCLUDE_DIRS}
)
find_package (Python3 COMPONENTS Interpreter Development)
set( includes flute.h
dl.h

View File

@ -18,9 +18,9 @@
set_cmake_policies()
setup_boost(program_options)
setup_qt()
setup_python()
find_package(Libexecinfo REQUIRED)
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
find_package(PythonSitePackages REQUIRED)
find_package(LEFDEF REQUIRED)
find_package(FLUTE REQUIRED)

View File

@ -20,11 +20,11 @@
cmake_policy(SET CMP0054 NEW)
setup_boost(program_options)
setup_qt()
setup_python()
find_package(BZip2 REQUIRED)
find_package(BISON REQUIRED)
find_package(FLEX REQUIRED)
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development )
find_package(PythonSitePackages REQUIRED)
find_package(Libexecinfo REQUIRED)
if (USE_LIBBFD)

View File

@ -20,6 +20,7 @@
FloatParameter.cpp
MatrixParameter.cpp
MCheckBoxParameter.cpp
SpinBoxParameter.cpp
StepParameter.cpp
StringParameter.cpp
BJT.cpp

View File

@ -107,4 +107,17 @@ namespace Analog {
}
string Cascode::_getTypeName () const
{ return "Cascode"; }
Record* Cascode::_getRecord () const
{
Record* record = Super::_getRecord();
record->add( getSlot("_cBulkConnectedName" , _cBulkConnectedName ) );
record->add( getSlot("_cBulkUnconnectedName", _cBulkUnconnectedName ) );
return record;
}
} // Analog namespace.

View File

@ -109,4 +109,17 @@ namespace Analog {
}
string CommonDrain::_getTypeName () const
{ return "CommonDrain"; }
Record* CommonDrain::_getRecord () const
{
Record* record = Super::_getRecord();
record->add( getSlot("_cdBulkConnectedName" , _cdBulkConnectedName ) );
record->add( getSlot("_cdBulkUnconnectedName", _cdBulkUnconnectedName ) );
return record;
}
} // Analog namespace.

View File

@ -103,4 +103,16 @@ namespace Analog {
{ return (isBulkConnected()) ? _cgBulkConnectedName : _cgBulkUnconnectedName; }
string CommonGatePair::_getTypeName () const
{ return "CommonGatePair"; }
Record* CommonGatePair::_getRecord () const
{
Record* record = Super::_getRecord();
record->add( getSlot("_cgBulkConnectedName" , _cgBulkConnectedName ) );
record->add( getSlot("_cgBulkUnconnectedName", _cgBulkUnconnectedName ) );
return record;
}
} // Analog namespace.

View File

@ -244,4 +244,17 @@ namespace Analog {
}
string CommonSourcePair::_getTypeName () const
{ return "CommonSourcePair"; }
Record* CommonSourcePair::_getRecord () const
{
Record* record = Super::_getRecord();
record->add( getSlot("_cspBulkConnectedName" , _cspBulkConnectedName ) );
record->add( getSlot("_cspBulkUnconnectedName", _cspBulkUnconnectedName ) );
return record;
}
} // Analog namespace.

View File

@ -98,4 +98,17 @@ namespace Analog {
{ return (isBulkConnected()) ? _ccpBulkConnectedName : _ccpBulkUnconnectedName; }
string CrossCoupledPair::_getTypeName () const
{ return "CrossCoupledPair"; }
Record* CrossCoupledPair::_getRecord () const
{
Record* record = Super::_getRecord();
record->add( getSlot("_ccpBulkConnectedName" , _ccpBulkConnectedName ) );
record->add( getSlot("_ccpBulkUnconnectedName", _ccpBulkUnconnectedName ) );
return record;
}
} // Analog namespace.

View File

@ -264,4 +264,17 @@ namespace Analog {
}
string DifferentialPair::_getTypeName () const
{ return "DifferentialPair"; }
Record* DifferentialPair::_getRecord () const
{
Record* record = Super::_getRecord();
record->add( getSlot("_dpBulkConnectedName" , _dpBulkConnectedName ) );
record->add( getSlot("_dpBulkUnconnectedName", _dpBulkUnconnectedName ) );
return record;
}
} // Analog namespace.

Some files were not shown because too many files have changed in this diff Show More