Compare commits

...

134 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
Jean-Paul Chaput 9b87b92eec Groudwork for short localization in Tramontana.
In order to accurately find the rectangles (Components) causing a short
circuit, we need to aggregate the equipotentials as soon as we starts
to merge the tiles. Because tiles being a union set, the tree compression
forbid to know which tile overlap which one afterwards. So the equipotentials
are created early on the fly. We also add an accounting of all the net's
components (Plug excluded) to know if it is fully included in the
equipotential. If not, we have an open.

This is an impacting change from the previous version in which we build
the equipotentials *after* aggregating the tiles only. The added cost
comes from the number of equipotential merging that we have to perform
when we merge tiles. Almost two times slower. May need to have a deep
look on how to optimize it later (efficient merge or keeping the order
tiles where merged).
2023-06-16 13:34:36 +02:00
Jean-Paul Chaput 5233d860f4 Slight change in Occurrence::getCompactString() formatting.
* Change: In Occurrence::getCompactString(), when the path is void,
    still display a double colon (::) instead of just one so we know
    for sure that the it is void.
2023-06-16 13:33:50 +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
Jean-Paul Chaput 46c685a7f8 Install Alliance in Release.Shared, not Debug.Shared. 2023-05-25 23:10:49 +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 56883db08e Display a window title when the viewer starts empty. 2023-05-07 12:16:18 +02:00
Jean-Paul Chaput abee13d669 Small improvement to the NetlistWidget (more fields). 2023-05-07 11:54:04 +02:00
Jean-Paul Chaput 96e6c9dd06 Fix a sync problem between the EquiWidget and the SelectionWidget. 2023-05-06 18:13:39 +02:00
Jean-Paul Chaput c53fc01cb2 Add Rectilinear & "cut" support to the extractor.
Note about the managment of VIA & cuts: Components using a layer which
  is a ViaLayer, that is one containing more than one BasicLayer,
  multiple tiles are created in QueryTiles::goCallback().
    Components that have a single BasicLayer of "cut" material will
  also have their multiples tiles created in QueryTiles::goCallback().
    Rectilinear components will have their multiples tiles created
  in Tile::create(). Tile::create() return not all the tiles but the
  one used as root (for the union find).

* New: In SweepLine::_buildCutConnexMap(), when using a "cut" layer
    in a standalone way, and not as part of a ViaLayer, we do not
    automatically know to which layer above & below they are connected.
      We build a table for each cut layer, based on the ViaLayer,
    to know all tops & belows layers they connect (this is cumulative,
    in the case of "cut" towards the substrate).
      Then in Tile::create(), we not only create the tile for the "cut"
    but also in thoses connected layers (and link them in the union
    find).
* New: In Tile::create(), when we encounter a Rectilinear, break it
    into rectangles and make as many tiles. All tiles linked to the
    same root in the union find.
* Bug: In Hurricane::Rectilinear, ambiguous specification of the set
    of points defining the shape. I did suppose that the start and and
    point where not the same the last edge being between them.
      But if FlexLib, it uses the GDSII inspired convention where the
    first and last point must be the same, to indicate a closed contour.
      This difference was not causing any difference with the drawing,
    but it was a problem for getAsRectangle(). This was creating a
    "false" extra vertical edge leading to a bigger rectangle.
    And this, in turn, was making "false" intersections in the
    tiling/sweepline of the extractor.
      Add a more thorough checking of the points vector.
2023-05-05 16:22:51 +02:00
Jean-Paul Chaput 52fd1c1c40 Add vertical rectangles partionning to Rectilinear.
* New: Rectilinear::asRectangles(), decompose the Rectilinear into a
    set of non-overlapping rectangles sliced vertically.
      This not a mathematical minimum set. But should be speedier.
      Done using a sweepline processing the vertical edges.
      Specially suited for use in the extractor which basically
    manage only rectangles.
      Simple algorithm described in pp. 9-11 of Extractor notebook.
      Tests done with unitests/python/test_rectilinear.py, the
    Rectilinear here should cover all the sweepline cases.
2023-05-03 17:08:57 +02:00
Jean-Paul Chaput 4c7cf227be Add ability to "filter out" buried net in TabEquipotentials.
Definition: A buried net is a net that has no components at the top
Cell level. Typically example is a wire internal to a standard cell.
Those nets, while part of the complete design (flat) are not part
of the top netlist, and we may want not to see it.
  A buried net is slighly different from a deep net. While a deepnet
is also not reaching the top level cell, we created it at top level
to be processed by the router (virtual flatten).
2023-04-14 01:07:40 +02:00
Jean-Paul Chaput d928a3c7a5 Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into tramontana 2023-04-13 14:05:48 +02:00
Jean-Paul Chaput c3bed61257 Full transhierarchical implementation done.
* New: Equipotential elements includes now:
    1. Components at the top level (the cell owning the Equi).
    2. Nets at the top level. If an equi include all the components
       of a Net, own the Net, not all it's individual components.
    3. Other equipotentials from the Instances immediatey below.
       Thoses equis should be equivalents to the Plug of the Net.
       They are stored in the form of Occurrences <Instance,Equi>,
       the relation is stored on that Occurrence.
* New: Equipotential::getFlatComponents(), a collection to recursively
    get all the *component* occurrences of the equi. Transhierarchically.
    Go through components, nets components, and recursively through
    the child equis.
* New: EquipotentialRelation, the master of this relation is the
    Equipotential and the slaves, all its elements.
* Change: In Tile, in case the tile is build on a deep component,
    we trace up the Equipotential it belongs to in the Instance
    level immediately belonging to the Cell under extraction.
    They must exists as we extract from bottom to top all the
    master cells. So we have, for that tile an Occurrence
    <Instance,Equi> that we can store in the current Equi level.
* Change/Bug: In Tile, add an Id to be reliably sort the tiles
    in the IntervalTree. As we replaced the tile component occurrence
    by a <Instance,Equi> we were having multiple tiles with the same
    equi. This was causing havoc again in the IntervalTree.
      Should add a check in the RbTree for elements with the
    exact same key, but that would imply passing a new template
    parameter for the "equal" function.
2023-04-13 14:00:50 +02:00
Jean-Paul Chaput 57bab117b4 Add typedef NetSet, for set of Net* sorted by Ids. 2023-04-13 00:18:10 +02:00
Jean-Paul Chaput 31b0c4daf1 Add selection/unselection by Occurrence collection in CellWidget. 2023-04-13 00:15:38 +02:00
Jean-Paul Chaput b9862ecd5e Fix scaling in CellImage::toImage(), compute size from *screen widget*. 2023-04-13 00:14:12 +02:00
Jean-Paul Chaput 518a376c01 Transhierarchical/flat extraction work, no netlist rebuild yet.
* Bug: In Interval::intersect(), bad condition check in strict mode.
* Change: In Occurrence::operator<(), change the sorting criterions
    so that the ones with no paths are "lower", then the one with
    no entities, then compare entities Id then Path hashes.
* Change: In Occurrence::getCompactString(), to be more readable,
    suppress leading and ending "<>".
* Change: In IntervalTree, now use an IntervalDataCompare to control
    the ordering of the nodes inside the tree. This may be needed
    when IntervalData is build upon a pointer, we don't want to
    sort on pointer values (non deterministic) .
* Bug: In IntervalTree::postRemove(), there was an incorrect computation
    of the updated childsVMax.
* Bug: In IntervalTree::beginOverlaps(), miscalculated leftmost
    interval overlapping.
* Bug: In RbTree::remove(), when exchanging the removed node for a
    leaf, fully swap the nodes contents, was incompletly copied before.
* New: In CellWidget, add new slots selectSet(OccurrenceSet&) and
    unselectSet(OccurrenceSet&), to be able to select/unselected sets
    of Occurrence (for use by TabEquipotentials).
* Change: In EtesianEngine, no more need to remove leading/ending "<>".
* New: In Tramontana, use a Query to find all the Occurrence under
    an area. Previously we were using Cell::getOccurrencesUnder()
    which *do not* return the components in instances, so we would
    have been unable to find trans-hierarchical shorts circuits.
* New: In tramontana, now use a Relation to tag all the components
    belonging to an Equipotential.
* Change: In Equipotential, store everything under the form of
    Occurrence, instead of Components. Due to the way the Occurrences
    are sorted, the one holding Components should be firts.
2023-04-02 23:02:46 +02:00
Jean-Paul Chaput 6361ad4ca0 Move the Tramontana menu from P&R to Tools. 2023-03-28 16:09:00 +02:00
Jean-Paul Chaput e968a5088f Added recursive extraction of all instances models in Tramontana. 2023-03-28 16:08:11 +02:00
Jean-Paul Chaput 5afb4cabe9 Add a verbose option to ToolEngine, don't always display infos. 2023-03-28 16:06:49 +02:00
Jean-Paul Chaput 23c0c24c0f Non-hierarchical, metal only, rectangle only, extractor is now working.
* New: In Tramontana,
  * Multi-layer support for the swap line. Split VIAs into their
    various metal plates and link the two relevant tiles, ensuring
    connexity between layers.
  * Improved Equipotential information rebuild. Try to rebuild more
    closely the Net characteristics. Improved tab widgets.
2023-03-28 15:13:02 +02:00
Jean-Paul Chaput 2568a1a496 Added deletion tests for RbTree & IntervalTree in unittests. 2023-03-28 15:12:31 +02:00
Jean-Paul Chaput e22e7f7476 IntervalTree is now support multiple intervals with same lower bound.
* New: Interval::CompareByMinMax, lexicographical comparison of
    Intervals, first compare the lower bound (VMin) then the
    upper bound (VMax). Needed for IntervalTree.
* Change: In IntervalTree, the key comparison was only based on
    the lower bound (VMin). That means that the tree would accept
    only one interval for a given VMin. You couldn't store both
    [1:4] and [1:5]. Now use CompareByMinMax that allows it.
2023-03-28 14:52:23 +02:00
Jean-Paul Chaput a0911be50a Add complete support for Equipotential selection in the Controller. 2023-03-26 21:15:15 +02:00
Jean-Paul Chaput e5d9c8808b Reduce the default pixel threshold to 5. 2023-03-26 21:12:49 +02:00
Jean-Paul Chaput 7ed41613de Add ControllerWidget::insertAfterTab() to put a new tab where we want. 2023-03-26 21:12:14 +02:00
Jean-Paul Chaput 50a9036d28 Add support for selection by ComponentSet in CellWidget.
* New: In Component, typedef ComponentSet (set sorted on Ids).
* New: CellWidget::selectSet() & CellWidget::unselectSet() select/unselect
    a whole set of component.
2023-03-26 21:08:58 +02:00
Jean-Paul Chaput 8f387620cb One Layer, one Cell extraction implementation in Tramontana.
* New: Tramontana::Equipotential, implemented.
* Change: Tramontana::Tile, add UnionFind capabilities and Equipotential
    attribute.
* New: Tramontana::SweepLine, build upon Hurricane::IntervalTree,
    can now perform a "one layer only" extraction (checked with "metal1").
2023-03-18 18:17:23 +01:00
Jean-Paul Chaput 5879a5b581 Removing Solstice & Equinox from Unicorn (forgotten bits). 2023-03-18 18:12:24 +01:00
Jean-Paul Chaput 1f4b9450e5 Fix, IntervalTree::overlap_iterator was progressing one step too far. 2023-03-18 18:11:03 +01:00
Jean-Paul Chaput 090c13663e Create stub for Tramontana, reimplementation of the extractor/LVX. 2023-03-16 15:06:11 +01:00
174 changed files with 8370 additions and 46005 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() set_cmake_policies()
setup_boost(program_options) setup_boost(program_options)
setup_qt() setup_qt()
setup_python()
find_package(Libexecinfo REQUIRED) find_package(Libexecinfo REQUIRED)
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
find_package(PythonSitePackages REQUIRED) find_package(PythonSitePackages REQUIRED)
find_package(LEFDEF REQUIRED) find_package(LEFDEF REQUIRED)
find_package(FLUTE REQUIRED) find_package(FLUTE REQUIRED)

View File

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

View File

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

View File

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

View File

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

View File

@ -278,6 +278,8 @@ namespace Anabatic {
if (flags & (VSmall|UseNonPref)) { if (flags & (VSmall|UseNonPref)) {
cdebug_log(145,0) << "case: UseNonPref" << endl; 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) ); AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getBuildContactLayer(rpDepth+1) );
AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical|useNonPref ); AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical|useNonPref );
rpSourceContact = subContact1; rpSourceContact = subContact1;
@ -1155,8 +1157,8 @@ namespace Anabatic {
} }
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) { for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess ); AutoContact* leftContact = doRp_Access( getGCell(), rpsM1[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess ); AutoContact* rightContact = doRp_Access( getGCell(), rpsM1[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal ); 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 SegNonPref = (1L<<37);
static const uint64_t SegAtMinArea = (1L<<38); static const uint64_t SegAtMinArea = (1L<<38);
static const uint64_t SegNoMoveUp = (1L<<39); static const uint64_t SegNoMoveUp = (1L<<39);
static const uint64_t SegOnVSmall = (1L<<40);
// Masks. // Masks.
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2; static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned; static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
@ -202,6 +203,7 @@ namespace Anabatic {
inline bool isTerminal () const; inline bool isTerminal () const;
inline bool isUnbreakable () const; inline bool isUnbreakable () const;
inline bool isNonPref () const; inline bool isNonPref () const;
inline bool isNonPrefOnVSmall () const;
inline bool isDrag () const; inline bool isDrag () const;
inline bool isAtMinArea () const; inline bool isAtMinArea () const;
inline bool isNotSourceAligned () const; inline bool isNotSourceAligned () const;
@ -536,6 +538,7 @@ namespace Anabatic {
inline bool AutoSegment::isLocal () const { return not (_flags & SegGlobal); } inline bool AutoSegment::isLocal () const { return not (_flags & SegGlobal); }
inline bool AutoSegment::isUnbreakable () const { return _flags & SegUnbreakable; } inline bool AutoSegment::isUnbreakable () const { return _flags & SegUnbreakable; }
inline bool AutoSegment::isNonPref () const { return _flags & SegNonPref; } 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::isBipoint () const { return _flags & SegBipoint; }
inline bool AutoSegment::isWeakTerminal () const { return (_rpDistance < 2); } inline bool AutoSegment::isWeakTerminal () const { return (_rpDistance < 2); }
inline bool AutoSegment::isWeakTerminal1 () const { return (_rpDistance == 1); } inline bool AutoSegment::isWeakTerminal1 () const { return (_rpDistance == 1); }

View File

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

View File

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

View File

@ -20,6 +20,7 @@
srcDir=${HOME}${nightly}/coriolis-2.x/src/alliance/alliance/src srcDir=${HOME}${nightly}/coriolis-2.x/src/alliance/alliance/src
commonRoot=${HOME}${nightly}/coriolis-2.x/${arch}/Release.Shared commonRoot=${HOME}${nightly}/coriolis-2.x/${arch}/Release.Shared
#commonRoot=${HOME}${nightly}/coriolis-2.x/${arch}/Debug.Shared
buildDir=${commonRoot}/build buildDir=${commonRoot}/build
installDir=${commonRoot}/install installDir=${commonRoot}/install

View File

@ -24,8 +24,9 @@ projects = [
#, "knik" #, "knik"
#, "katabatic" #, "katabatic"
#, "kite" #, "kite"
, "equinox" #, "equinox"
, "solstice" #, "solstice"
, "tramontana"
, "oroshi" , "oroshi"
, "bora" , "bora"
, "karakaze" , "karakaze"

View File

@ -35,6 +35,7 @@ class Builder:
self._noCache = False self._noCache = False
self._ninja = False self._ninja = False
self._clang = False self._clang = False
self._manylinux = False
self._noSystemBoost = False self._noSystemBoost = False
self._macports = False self._macports = False
self._devtoolset = 0 self._devtoolset = 0
@ -62,6 +63,7 @@ class Builder:
elif attribute == "noCache": self._noCache = value elif attribute == "noCache": self._noCache = value
elif attribute == "ninja": self._ninja = value elif attribute == "ninja": self._ninja = value
elif attribute == "clang": self._clang = value elif attribute == "clang": self._clang = value
elif attribute == "manylinux": self._manylinux = value
elif attribute == "macports": elif attribute == "macports":
self._macports = value self._macports = value
if value: self._noSystemBoost = True if value: self._noSystemBoost = True
@ -177,6 +179,7 @@ class Builder:
if self._bfd: command += [ "-D", "USE_LIBBFD:STRING=%s" % self._bfd ] if self._bfd: command += [ "-D", "USE_LIBBFD:STRING=%s" % self._bfd ]
if self._qt4: command += [ "-D", "WITH_QT4:STRING=TRUE" ] if self._qt4: command += [ "-D", "WITH_QT4:STRING=TRUE" ]
if self._openmp: command += [ "-D", "WITH_OPENMP: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 command += [ "-D", "CMAKE_BUILD_TYPE:STRING=%s" % self.buildMode
#, "-D", "BUILD_SHARED_LIBS:STRING=%s" % self.enableShared #, "-D", "BUILD_SHARED_LIBS:STRING=%s" % self.enableShared
, "-D", "CMAKE_INSTALL_PREFIX:STRING=%s" % self.installDir , "-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 ( "--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 ( "--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 ( "--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 ( "--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 ( "--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)." ) 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.llvmtoolset: builder.llvmtoolset = options.llvmtoolset
if options.bfd: builder.bfd = "ON" if options.bfd: builder.bfd = "ON"
if options.qt4: builder.qt4 = True if options.qt4: builder.qt4 = True
if options.manylinux: builder.manylinux = True
if options.openmp: builder.openmp = True if options.openmp: builder.openmp = True
if options.makeArguments: builder.makeArguments = options.makeArguments if options.makeArguments: builder.makeArguments = options.makeArguments
#if options.svnMethod: builder.svnMethod = options.svnMethod #if options.svnMethod: builder.svnMethod = options.svnMethod

View File

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

View File

@ -84,10 +84,10 @@
set(DEBUG_FLAGS "-g") set(DEBUG_FLAGS "-g")
if(CYGWIN) if(CYGWIN)
set(ADDITIONAL_FLAGS "-D_GLIBCXX_USE_C99") set(ADDITIONAL_FLAGS "-D_GLIBCXX_USE_C99")
set(CXX_STANDARD "gnu++11") set(CXX_STANDARD "gnu++17")
else() else()
set(ADDITIONAL_FLAGS "-Wl,--no-undefined") set(ADDITIONAL_FLAGS "-Wl,--no-undefined")
set(CXX_STANDARD "c++11") set(CXX_STANDARD "c++17")
endif() 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 -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) 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) 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. # 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. # 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. # Look in other places.
${CORIOLIS_DIR_SEARCH} ${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES include/coriolis2 PATH_SUFFIXES include/coriolis2
# Help the user find it if we cannot. # Help the user find it if we cannot.
DOC "The ${COLOQUINTE_INCLUDE_PATH_DESCRIPTION}" DOC "The ${COLOQUINTE_INCLUDE_PATH_DESCRIPTION}"
) )
MESSAGE( "COL ${COLOQUINTE_INCLUDE_PATH}" )
FIND_LIBRARY(COLOQUINTE_LIBRARY_PATH FIND_LIBRARY(COLOQUINTE_LIBRARY_PATH
NAMES coloquinte NAMES coloquinte

View File

@ -180,7 +180,7 @@ Development files for the Coriolis 2 package.
%{coriolisTop}/include/vlsisapd/configuration/*.h %{coriolisTop}/include/vlsisapd/configuration/*.h
%{coriolisTop}/include/vlsisapd/dtr/*.h %{coriolisTop}/include/vlsisapd/dtr/*.h
%{coriolisTop}/include/vlsisapd/openChams/*.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/*.h
%{coriolisTop}/include/coriolis2/hurricane/viewer/*.h %{coriolisTop}/include/coriolis2/hurricane/viewer/*.h
%{coriolisTop}/include/coriolis2/hurricane/isobar/*.h %{coriolisTop}/include/coriolis2/hurricane/isobar/*.h

View File

@ -284,6 +284,16 @@ class GitRepository ( object ):
Command( [ 'git', 'checkout', branch ], self.fdLog ).execute() Command( [ 'git', 'checkout', branch ], self.fdLog ).execute()
return 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 ): class Configuration ( object ):
@ -303,7 +313,7 @@ class Configuration ( object ):
def __init__ ( self ): def __init__ ( self ):
self._sender = 'Jean-Paul.Chaput@soc.lip6.fr' self._sender = 'Jean-Paul.Chaput@soc.lip6.fr'
self._receivers = [ 'Jean-Paul.Chaput@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._allianceRepo = 'https://gitlab.lip6.fr/jpc/alliance.git'
self._coriolisRepo = 'https://gitlab.lip6.fr/jpc/coriolis.git' self._coriolisRepo = 'https://gitlab.lip6.fr/jpc/coriolis.git'
self._benchsRepo = 'https://gitlab.lip6.fr/jpc/alliance-check-toolkit.git' self._benchsRepo = 'https://gitlab.lip6.fr/jpc/alliance-check-toolkit.git'
@ -601,6 +611,8 @@ try:
if conf.rmSource: gitCoriolis.removeLocalRepo() if conf.rmSource: gitCoriolis.removeLocalRepo()
gitCoriolis.clone () gitCoriolis.clone ()
gitCoriolis.checkout( 'devel' ) gitCoriolis.checkout( 'devel' )
gitCoriolis.submoduleInit()
gitCoriolis.submoduleUpdate()
if conf.rmSource: gitBenchs.removeLocalRepo() if conf.rmSource: gitBenchs.removeLocalRepo()
gitBenchs.clone() gitBenchs.clone()

View File

@ -18,9 +18,9 @@
setup_boost(program_options) setup_boost(program_options)
setup_qt() setup_qt()
setup_qwt() setup_qwt()
setup_python()
find_package(Libexecinfo REQUIRED) find_package(Libexecinfo REQUIRED)
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
find_package(PythonSitePackages REQUIRED) find_package(PythonSitePackages REQUIRED)
find_package(LEFDEF REQUIRED) find_package(LEFDEF REQUIRED)
find_package(FLUTE 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_sysconfdir("${CMAKE_INSTALL_PREFIX}")
setup_boost(program_options) setup_boost(program_options)
setup_qt() setup_qt()
setup_python()
cmake_policy(SET CMP0054 NEW) cmake_policy(SET CMP0054 NEW)
@ -28,7 +29,6 @@
find_package(Libbfd) find_package(Libbfd)
endif() endif()
find_package(BZip2 REQUIRED) find_package(BZip2 REQUIRED)
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
find_package(PythonSitePackages REQUIRED) find_package(PythonSitePackages REQUIRED)
find_package(BISON REQUIRED) find_package(BISON REQUIRED)
find_package(FLEX REQUIRED) find_package(FLEX REQUIRED)

View File

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

View File

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

View File

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

View File

@ -16,8 +16,8 @@
import coriolis.Cfg as Cfg import coriolis.Cfg as Cfg
layout = Cfg.Configuration.get().getLayout() layout = Cfg.Configuration.get().getLayout()
layout.addTab ( 'stratus1', 'Stratus1' ) layout.addTab ( 'Netlist', 'Stratus1' )
layout.addTitle ( 'stratus1', 'Stratus1 - Netlist & Layout Capture' ) layout.addTitle ( 'Netlist', 'Stratus1 - Netlist & Layout Capture' )
layout.addParameter( 'stratus1', 'stratus1.mappingName', 'Virtual Library Translation', 0, 2 ) layout.addParameter( 'Netlist', 'stratus1.mappingName', 'Virtual Library Translation', 0, 2 )
layout.addParameter( 'stratus1', 'stratus1.format' , 'Netlist Format (vst, vhd)' , 0, 2 ) layout.addParameter( 'Netlist', 'stratus1.format' , 'Netlist Format (vst, vhd)' , 0, 2 )
layout.addParameter( 'stratus1', 'stratus1.simulator' , 'Simulator' , 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.setCLOCK ( '.*ck.*|.*nck.*' )
env.setBLOCKAGE ( 'blockage[Nn]et.*' ) env.setBLOCKAGE ( 'blockage[Nn]et.*' )
env.setPad ( '.*_px$' ) env.setPad ( '.*_px$' )
env.setRegister ( 'sff.*' )
env.setWORKING_LIBRARY( '.' ) env.setWORKING_LIBRARY( '.' )
env.addSYSTEM_LIBRARY ( library=cellsTop+'/sxlib' , mode=Environment.Append ) env.addSYSTEM_LIBRARY ( library=cellsTop+'/sxlib' , mode=Environment.Append )

View File

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

@ -191,8 +191,9 @@ namespace CRL {
bool ToolEngine::_inDestroyAll = false; bool ToolEngine::_inDestroyAll = false;
ToolEngine::ToolEngine ( Cell* cell ) ToolEngine::ToolEngine ( Cell* cell, bool verbose )
: Super() : Super()
, _verbose (verbose)
, _cell (cell) , _cell (cell)
, _placementModificationFlag(0) , _placementModificationFlag(0)
, _routingModificationFlag (0) , _routingModificationFlag (0)
@ -219,11 +220,13 @@ namespace CRL {
put( enginesRelation ); put( enginesRelation );
cmess1 << " o Creating ToolEngine<" << getName() << "> for Cell <" if (_verbose) {
<< _cell->getName() << ">" << endl; cmess1 << " o Creating ToolEngine<" << getName() << "> for Cell <"
<< _cell->getName() << ">" << endl;
cmess1 << Dots::asString( " - Initial memory" cmess1 << Dots::asString( " - Initial memory"
, Timer::getStringMemory(Timer::getMemorySize()) ) << endl; , Timer::getStringMemory(Timer::getMemorySize()) ) << endl;
}
} }

View File

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

View File

@ -81,13 +81,14 @@ namespace CRL {
protected: protected:
Cell* _cell; Cell* _cell;
private: private:
bool _verbose;
unsigned int _placementModificationFlag; unsigned int _placementModificationFlag;
unsigned int _routingModificationFlag; unsigned int _routingModificationFlag;
bool _inRelationDestroy; bool _inRelationDestroy;
Timer _timer; Timer _timer;
uint32_t _passNumber; uint32_t _passNumber;
protected: protected:
ToolEngine ( Cell* cell ); ToolEngine ( Cell* cell, bool verbose=true );
virtual void _postCreate (); virtual void _postCreate ();
virtual void _preDestroy (); virtual void _preDestroy ();
protected: protected:

View File

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

View File

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

View File

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

View File

@ -43,6 +43,8 @@ namespace CRL {
using Isobar::ParseTwoArg; using Isobar::ParseTwoArg;
using Isobar::__cs; using Isobar::__cs;
using Isobar::PyLibrary_Link; using Isobar::PyLibrary_Link;
using Isobar::PyTypeLibrary;
using Isobar::PyLibrary;
extern "C" { 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). // Standart Destroy (Attribute).
PyMethodDef PyLefImport_Methods[] = 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." } , "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)." } , "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" , (PyCFunction)PyLefImport_destroy , METH_VARARGS
// , "Destroy the associated hurricane object. The python object remains." } // , "Destroy the associated hurricane object. The python object remains." }
, {NULL, NULL, 0, NULL} /* sentinel */ , {NULL, NULL, 0, NULL} /* sentinel */

View File

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

View File

@ -64,7 +64,7 @@ class PnR ( FlowTask ):
else: else:
print( 'PnR.doTask() run in interactive CGT mode.' ) print( 'PnR.doTask() run in interactive CGT mode.' )
PnR.textMode = False PnR.textMode = False
from .. import Etesian, Anabatic, Katana, Bora, Tutorial, Viewer, Unicorn from .. import Etesian, Anabatic, Katana, Bora, Tramontana, Tutorial, Viewer, Unicorn
ShellEnv().export() ShellEnv().export()
if self.script and not callable(self.script): if self.script and not callable(self.script):
@ -80,8 +80,8 @@ class PnR ( FlowTask ):
unicorn = Unicorn.UnicornGui.create() unicorn = Unicorn.UnicornGui.create()
unicorn.setApplicationName ( 'cgt') unicorn.setApplicationName ( 'cgt')
unicorn.registerTool ( Etesian.GraphicEtesianEngine.grab() ) unicorn.registerTool ( Etesian.GraphicEtesianEngine.grab() )
#unicorn.registerTool ( Kite.GraphicKiteEngine.grab() )
unicorn.registerTool ( Katana.GraphicKatanaEngine.grab() ) unicorn.registerTool ( Katana.GraphicKatanaEngine.grab() )
unicorn.registerTool ( Tramontana.GraphicTramontanaEngine.grab() )
unicorn.registerTool ( Bora.GraphicBoraEngine.grab() ) unicorn.registerTool ( Bora.GraphicBoraEngine.grab() )
unicorn.registerTool ( Tutorial.GraphicTutorialEngine.grab() ) unicorn.registerTool ( Tutorial.GraphicTutorialEngine.grab() )
#unicorn.setAnonNetSelectable(False) #unicorn.setAnonNetSelectable(False)

View File

@ -69,7 +69,13 @@ class ShellEnv ( object ):
self.shellEnv[ 'MBK_CATAL_NAME' ] = env.getCATALOG() self.shellEnv[ 'MBK_CATAL_NAME' ] = env.getCATALOG()
self.shellEnv[ 'RDS_IN' ] = 'gds' self.shellEnv[ 'RDS_IN' ] = 'gds'
self.shellEnv[ 'RDS_OUT' ] = '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 ): def export ( self ):
""" """

View File

@ -42,7 +42,10 @@ class Where ( object ):
return '<Where coriolisTop="{}">'.format( Where.coriolisTop.as_posix() ) return '<Where coriolisTop="{}">'.format( Where.coriolisTop.as_posix() )
def setupCMOS (): def setupCMOS ( checkToolkit=None ):
Where( checkToolkit )
ShellEnv().export()
from .. import Cfg from .. import Cfg
from .. import Viewer from .. import Viewer
from .. import CRL from .. import CRL
@ -50,8 +53,6 @@ def setupCMOS ():
from .yosys import Yosys from .yosys import Yosys
import coriolis.technos.symbolic.cmos import coriolis.technos.symbolic.cmos
Where()
with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg: with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg:
cfg.misc.catchCore = False cfg.misc.catchCore = False
cfg.misc.info = False cfg.misc.info = False
@ -81,6 +82,46 @@ def setupCMOS ():
break 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 ): def setupCMOS45 ( useNsxlib=False, checkToolkit=None, cellsTop=None ):
from .. import Cfg from .. import Cfg
from .. import Viewer from .. import Viewer
@ -189,6 +230,7 @@ def setupSky130_c4m ( checkToolkit=None, pdkMasterTop=None ):
cfg.misc.logMode = True cfg.misc.logMode = True
cfg.misc.verboseLevel1 = False cfg.misc.verboseLevel1 = False
cfg.misc.verboseLevel2 = False cfg.misc.verboseLevel2 = False
cfg.viewer.pixelThreshold = 5
cfg.etesian.graphics = 2 cfg.etesian.graphics = 2
cfg.anabatic.topRoutingLayer = 'm4' cfg.anabatic.topRoutingLayer = 'm4'
cfg.katana.eventsLimit = 4000000 cfg.katana.eventsLimit = 4000000
@ -294,7 +336,7 @@ def setupTSMC_c180_c4m ( checkToolkit=None, ndaTop=None ):
cfg.misc.verboseLevel1 = True cfg.misc.verboseLevel1 = True
cfg.misc.verboseLevel2 = True cfg.misc.verboseLevel2 = True
cfg.etesian.graphics = 3 cfg.etesian.graphics = 3
cfg.etesian.uniformDensity = True cfg.etesian.densityVariation = 0.04
cfg.etesian.spaceMargin = 0.04 cfg.etesian.spaceMargin = 0.04
cfg.katana.eventsLimit = 4000000 cfg.katana.eventsLimit = 4000000
af = CRL.AllianceFramework.get() af = CRL.AllianceFramework.get()
@ -303,3 +345,52 @@ def setupTSMC_c180_c4m ( checkToolkit=None, ndaTop=None ):
Yosys.setLiberty( liberty ) Yosys.setLiberty( liberty )
ShellEnv.CHECK_TOOLKIT = Where.checkToolkit.as_posix() 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

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

View File

@ -176,11 +176,10 @@ Etesian Configuration Parameters
| | The extra white space added to the total area | | | The extra white space added to the total area |
| | of the standard cells | | | of the standard cells |
+-----------------------------------+------------------+----------------------------+ +-----------------------------------+------------------+----------------------------+
|``etesian.uniformDensity`` | TypeBool | :cb:`False` | |``etesian.densityVariation`` | TypePercentage | :cb:`5` |
| +------------------+----------------------------+ | +------------------+----------------------------+
| | Whether the cells will be spread envenly | | | Control deviation from uniform density in the |
| | across the area or allowed to form denser | | | placement, as a percentage of area. |
| | clusters |
+-----------------------------------+------------------+----------------------------+ +-----------------------------------+------------------+----------------------------+
|``etesian.effort`` | TypeInt | :cb:`2` | |``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.minTraceLevel = 1900
cfg.misc.maxTraceLevel = 3000 cfg.misc.maxTraceLevel = 3000
cfg.etesian.effort = 2 cfg.etesian.effort = 2
cfg.etesian.uniformDensity = True
cfg.etesian.spaceMargin = 0.8 cfg.etesian.spaceMargin = 0.8
cfg.etesian.densityVariation = 0.1
cfg.etesian.aspectRatio = 1.0 cfg.etesian.aspectRatio = 1.0
cfg.katana.eventsLimit = 1000000 cfg.katana.eventsLimit = 1000000
cfg.katana.termSatReservedLocal = 6 cfg.katana.termSatReservedLocal = 6

View File

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

View File

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

View File

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

View File

@ -56,13 +56,11 @@ namespace Etesian {
, _placeEffort ( static_cast<Effort> , _placeEffort ( static_cast<Effort>
(Cfg::getParamEnumerate ("etesian.effort" , Standard )->asInt()) ) (Cfg::getParamEnumerate ("etesian.effort" , Standard )->asInt()) )
, _updateConf ( static_cast<GraphicUpdate> , _updateConf ( static_cast<GraphicUpdate>
(Cfg::getParamEnumerate ("etesian.graphics" , LowerBound )->asInt()) ) (Cfg::getParamEnumerate ("etesian.graphics" , FinalOnly )->asInt()) )
, _spreadingConf ( Cfg::getParamBool ("etesian.uniformDensity" , false )->asBool()? ForceUniform : MaxDensity )
, _routingDriven ( Cfg::getParamBool ("etesian.routingDriven" , false )->asBool()) , _routingDriven ( Cfg::getParamBool ("etesian.routingDriven" , false )->asBool())
, _spaceMargin ( Cfg::getParamPercentage("etesian.spaceMargin" , 5.0)->asDouble() ) , _spaceMargin ( Cfg::getParamPercentage("etesian.spaceMargin" , 5.0)->asDouble() )
, _densityVariation ( Cfg::getParamPercentage("etesian.densityVariation", 5.0)->asDouble() )
, _aspectRatio ( Cfg::getParamPercentage("etesian.aspectRatio" ,100.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() ) , _tieName ( Cfg::getParamString ("etesian.tieName" ,"tie_x0" )->asString() )
, _feedNames ( Cfg::getParamString ("etesian.feedNames" ,"tie_x0,rowend_x0")->asString() ) , _feedNames ( Cfg::getParamString ("etesian.feedNames" ,"tie_x0,rowend_x0")->asString() )
, _diodeName ( Cfg::getParamString ("etesian.diodeName" ,"dio_x0" )->asString() ) , _diodeName ( Cfg::getParamString ("etesian.diodeName" ,"dio_x0" )->asString() )
@ -107,18 +105,17 @@ namespace Etesian {
, _cg (NULL) , _cg (NULL)
, _placeEffort ( other._placeEffort ) , _placeEffort ( other._placeEffort )
, _updateConf ( other._updateConf ) , _updateConf ( other._updateConf )
, _spreadingConf ( other._spreadingConf )
, _spaceMargin ( other._spaceMargin ) , _spaceMargin ( other._spaceMargin )
, _densityVariation ( other._densityVariation)
, _aspectRatio ( other._aspectRatio ) , _aspectRatio ( other._aspectRatio )
, _antennaInsertThreshold( other._antennaInsertThreshold )
, _tieName ( other._tieName ) , _tieName ( other._tieName )
, _feedNames ( other._feedNames ) , _feedNames ( other._feedNames )
, _diodeName ( other._diodeName ) , _diodeName ( other._diodeName )
, _spareBufferName ( other._spareBufferName ) , _spareBufferName ( other._spareBufferName )
, _bloat ( other._bloat ) , _bloat ( other._bloat )
, _latchUpDistance ( other._latchUpDistance ) , _latchUpDistance ( other._latchUpDistance )
, _antennaGateMaxWL ( other._antennaGateMaxWL ) , _antennaGateMaxWL ( other._antennaGateMaxWL )
, _antennaDiodeMaxWL( other._antennaDiodeMaxWL ) , _antennaDiodeMaxWL( other._antennaDiodeMaxWL)
{ {
if (other._rg) _rg = other._rg->getClone(); if (other._rg) _rg = other._rg->getClone();
if (other._cg) _cg = other._cg->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::asIdentifier(" - Cell Gauge" ,getString(_cg->getName())) << endl;
cmess1 << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl; cmess1 << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl;
cmess1 << Dots::asInt (" - Update Conf" ,_updateConf ) << endl; cmess1 << Dots::asInt (" - Update Conf" ,_updateConf ) << endl;
cmess1 << Dots::asInt (" - Spreading Conf" ,_spreadingConf ) << endl;
cmess1 << Dots::asBool (" - Routing driven" ,_routingDriven ) << endl; cmess1 << Dots::asBool (" - Routing driven" ,_routingDriven ) << endl;
cmess1 << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl; cmess1 << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl;
cmess1 << Dots::asPercentage(" - Spread Margin" ,_densityVariation ) << endl;
cmess1 << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl; cmess1 << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl;
cmess1 << Dots::asString (" - Bloat model" ,_bloat ) << 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 gate Max. WL" ,DbU::getValueString(_antennaGateMaxWL )) << endl;
cmess1 << Dots::asString (" - Antenna diode Max. WL",DbU::getValueString(_antennaDiodeMaxWL)) << endl; cmess1 << Dots::asString (" - Antenna diode Max. WL",DbU::getValueString(_antennaDiodeMaxWL)) << endl;
cmess1 << Dots::asString (" - Latch up Distance",DbU::getValueString(_latchUpDistance)) << 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( "_cg" , _cg ) );
record->add ( getSlot( "_placeEffort" , (int)_placeEffort ) ); record->add ( getSlot( "_placeEffort" , (int)_placeEffort ) );
record->add ( getSlot( "_updateConf" , (int)_updateConf ) ); record->add ( getSlot( "_updateConf" , (int)_updateConf ) );
record->add ( getSlot( "_spreadingConf" , (int)_spreadingConf ) );
record->add ( getSlot( "_spaceMargin" , _spaceMargin ) ); record->add ( getSlot( "_spaceMargin" , _spaceMargin ) );
record->add ( getSlot( "_densityVariation" , _densityVariation ) );
record->add ( getSlot( "_aspectRatio" , _aspectRatio ) ); 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( "_feedNames" , _feedNames ) );
record->add ( getSlot( "_diodeName" , _diodeName ) ); record->add ( getSlot( "_diodeName" , _diodeName ) );
record->add ( getSlot( "_spareBufferName" , _spareBufferName ) ); 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_setFixedAbHeight,setFixedAbHeight,PyEtesianEngine,EtesianEngine)
DirectSetLongAttribute (PyEtesianEngine_setFixedAbWidth ,setFixedAbWidth ,PyEtesianEngine,EtesianEngine) DirectSetLongAttribute (PyEtesianEngine_setFixedAbWidth ,setFixedAbWidth ,PyEtesianEngine,EtesianEngine)
DirectSetDoubleAttribute (PyEtesianEngine_setSpaceMargin ,setSpaceMargin ,PyEtesianEngine,EtesianEngine) DirectSetDoubleAttribute (PyEtesianEngine_setSpaceMargin ,setSpaceMargin ,PyEtesianEngine,EtesianEngine)
DirectSetDoubleAttribute (PyEtesianEngine_setDensityVariation,setDensityVariation ,PyEtesianEngine,EtesianEngine)
DirectSetDoubleAttribute (PyEtesianEngine_setAspectRatio ,setAspectRatio ,PyEtesianEngine,EtesianEngine) DirectSetDoubleAttribute (PyEtesianEngine_setAspectRatio ,setAspectRatio ,PyEtesianEngine,EtesianEngine)
DirectGetLongAttribute (PyEtesianEngine_getFixedAbHeight,getFixedAbHeight,PyEtesianEngine,EtesianEngine) DirectGetLongAttribute (PyEtesianEngine_getFixedAbHeight,getFixedAbHeight,PyEtesianEngine,EtesianEngine)
DirectGetLongAttribute (PyEtesianEngine_getFixedAbWidth ,getFixedAbWidth ,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)." } , "Use this width when computing the size of the default abutment box (disable aspect ratio)." }
, { "setSpaceMargin" , (PyCFunction)PyEtesianEngine_setSpaceMargin , METH_VARARGS , { "setSpaceMargin" , (PyCFunction)PyEtesianEngine_setSpaceMargin , METH_VARARGS
, "Override the configuration space margin parameter value." } , "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 , { "setAspectRatio" , (PyCFunction)PyEtesianEngine_setAspectRatio , METH_VARARGS
, "Override the configuration aspect ratio parameter value." } , "Override the configuration aspect ratio parameter value." }
, { "resetPlacement" , (PyCFunction)PyEtesianEngine_resetPlacement , METH_NOARGS , { "resetPlacement" , (PyCFunction)PyEtesianEngine_resetPlacement , METH_NOARGS

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -49,13 +49,25 @@ string demangle ( const char* symbol )
#else #else
string demangle ( const char* symbol ) string demangle ( const char* symbol )
{ { return symbol; }
return symbol;
}
#endif #endif
string& split ( string& s )
{
size_t i = s.find( "<" );
while ( i != string::npos ) {
if (i+3 > s.size()) break;
//if (s[i+2] != '>') {
s.insert( i, "\\n" );
//}
i = s.find( "<", i+3 );
}
return s;
}
} // End of Hurricane namespace. } // End of Hurricane namespace.

View File

@ -118,6 +118,9 @@ Contact::Contact(Net* net, const Layer* layer, DbU::Unit x, DbU::Unit y, DbU::Un
{ {
if (not _layer) if (not _layer)
throw Error("Contact::Contact(): Can't create " + _TName("Contact") + ", NULL layer."); throw Error("Contact::Contact(): Can't create " + _TName("Contact") + ", NULL layer.");
if ( _width < _layer->getMinimalSize() ) _width = _layer->getMinimalSize();
if ( _height < _layer->getMinimalSize() ) _height = _layer->getMinimalSize();
} }
Contact::Contact(Net* net, Component* anchor, const Layer* layer, DbU::Unit dx, DbU::Unit dy, DbU::Unit width, DbU::Unit height) Contact::Contact(Net* net, Component* anchor, const Layer* layer, DbU::Unit dx, DbU::Unit dy, DbU::Unit width, DbU::Unit height)

View File

@ -111,21 +111,21 @@ bool Interval::intersect(const Interval& interval, bool strict) const
if (isEmpty() or interval.isEmpty()) return false; if (isEmpty() or interval.isEmpty()) return false;
if ( (_vMax < interval._vMin) or (interval._vMax < _vMin) ) return false; if ( (_vMax < interval._vMin) or (interval._vMax < _vMin) ) return false;
return not strict or ( (_vMax != interval._vMin) and (interval._vMax != _vMin) ); return not strict or ( (_vMax > interval._vMin) or (interval._vMax > _vMin) );
} }
bool Interval::inferior(const Interval& interval, bool strict) const bool Interval::inferior(const Interval& interval, bool strict) const
// ***************************************************************** // *****************************************************************
{ {
if (_vMax < interval._vMin) return true; if (_vMax == interval._vMin) return not strict;
return not strict and (_vMax == interval._vMin); return (_vMax < interval._vMin);
} }
bool Interval::superior(const Interval& interval, bool strict) const bool Interval::superior(const Interval& interval, bool strict) const
// ***************************************************************** // *****************************************************************
{ {
if (_vMin > interval._vMax) return true; if (_vMin > interval._vMax) return true;
return !strict && (_vMin == interval._vMax); return not (strict or (_vMin != interval._vMax));
} }
bool Interval::isConstrainedBy(const Interval& interval) const bool Interval::isConstrainedBy(const Interval& interval) const

View File

@ -772,15 +772,23 @@ void Net::_preDestroy()
cdebug_tabw(18,-1); cdebug_tabw(18,-1);
} }
string Net::_getFlagsAsString() const
// **********************************
{
string ds;
ds += ((isDeepNet() ) ? "d" : "-");
ds += ((_isExternal ) ? "e" : "-");
ds += ((_isGlobal ) ? "g" : "-");
ds += ((_isAutomatic) ? "a" : "-");
return ds;
}
string Net::_getString() const string Net::_getString() const
// *************************** // ***************************
{ {
string bs = Inherit::_getString(); string bs = Inherit::_getString();
string ds = "\"" + getString(_name) + "\" "; string ds = "\"" + getString(_name) + "\" ";
ds += ((isDeepNet() ) ? "d" : "-"); ds += _getFlagsAsString();
ds += ((_isExternal ) ? "e" : "-");
ds += ((_isGlobal ) ? "g" : "-");
ds += ((_isAutomatic) ? "a" : "-");
ds += " "; ds += " ";
ds += getString(_type ) + " "; ds += getString(_type ) + " ";
ds += getString(_direction); ds += getString(_direction);

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