Compare commits

..

1233 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 d41e328253 Added easier access to devices parameters in AnalogDesign. 2023-05-08 20:00:47 +02:00
Jean-Paul Chaput 7cfd056da2 Completed inspector support on analog transitors. 2023-05-08 20:00:29 +02:00
Jean-Paul Chaput 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 ae5f6ad3de Added some more debug info in capacitors. 2023-04-26 19:34:22 +02:00
Jean-Paul Chaput a31cf3d334 Fix SRAM import hierarchy for new coriolis namespace. 2023-04-26 11:46:53 +02:00
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
Gabriel Gouvine 4b15396444 Remove old steps from the installation 2023-04-04 16:20:29 +02:00
Gabriel Gouvine 8bd0a3b0c8 Do not show shell guess ofr directory queries 2023-04-04 16:17:13 +02:00
Jean-Paul Chaput e04f6b1cbc Make it work under the bootstrap dir for directories queries. 2023-04-04 16:13:59 +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
Jean-Paul Chaput b7f6af8588 Add a specific "ps" command under Cygwin in coriolisEnv.py. 2023-03-15 12:06:44 +01:00
Jean-Paul Chaput 91e7685921 Try a more portable call of "ps" in coriolisEnv.py. 2023-03-14 18:29:37 +01:00
Jean-Paul Chaput 9cfa104836 Build against Qt5 by default. Uses --qt4 to force uses of Qt4.
* Change: In bootstrap, FindBootstrap.cmake, ccb (builder) & socInstaller,
    suppress the "--qt5" argument as it the default now. Create a "--qt4"
    to force building against the old one.
2023-03-13 17:37:19 +01:00
Jean-Paul Chaput 8a23a89f5d Rewrite backward compatibility for Qwt 5 (Qt4) for SlicingPlotWidget. 2023-03-13 16:51:16 +01:00
Jean-Paul Chaput 8353df1ee6 Use smaller font for code block in documentation (nest.css). 2023-03-13 16:45:42 +01:00
Jean-Paul Chaput 03c424f1a1 Add bop detection on allianceInstaller.sh. 2023-03-10 22:20:09 +01:00
Jean-Paul Chaput b4fe1a3686 Add a fallback when the "ps" command fail in coriolisEnv.py. 2023-03-09 19:07:22 +01:00
Jean-Paul Chaput 87fd1fa7b6 Fix missing Python link libraries, more of them. 2023-03-09 18:39:48 +01:00
Jean-Paul Chaput 7a644c65fb Add support for the Python benchs (doit) in socInstaller.py. 2023-03-09 15:35:44 +01:00
Jean-Paul Chaput 1f16642c82 Restore alternate support for Qt 4. 2023-03-09 15:30:23 +01:00
Jean-Paul Chaput 79d8461c8f Fix missing libraries in Flute Python wrapper (linking). 2023-03-09 15:25:26 +01:00
Jean-Paul Chaput 881e97bbd3 Fix missing libraries problems (seen on Cygwin).
* Change: In bootstrap/cmake_modules/FindBootstrap.cmake, add a
    "-Wl,--no-undefined" to the C++/ld flags to force checking of
    undefined symbol at link time.
2023-03-07 17:29:40 +01:00
Jean-Paul Chaput aafec8c64c Fix a conflict with predefined macro "_B" in Hurricane::Diagonal. 2023-03-07 17:21:08 +01:00
Jean-Paul Chaput 1e8c304ac5 Fix: designflow/klayout.py rule forgot to add targets. 2023-03-07 11:52:52 +01:00
Jean-Paul Chaput 842c2dfffc Late import of pyosys to not block if N/A in designflow/yosys.py. 2023-03-06 14:58:39 +01:00
Jean-Paul Chaput 461b81bb75 Reverse commit #c7608998 (LD_LIBRARY_PATH), was not the problem. 2023-03-06 14:49:30 +01:00
Jean-Paul Chaput d7c9316920 Forgot to update default techno loading with coriolis namespace. 2023-03-03 16:03:54 +01:00
Jean-Paul Chaput 3fdef7aa8d Remove deprecated Kite reference in designflow/pnr.py. 2023-03-03 15:40:42 +01:00
Jean-Paul Chaput c7608998ce Comprehensive LD_LIBRARY_PATH init in coriolisEnv.py.
* In bootstrap/coriolisEnv.py, under WSL it seems that setting up the
    LD_LIBRARY_PATH makes the linker to ignore /etc/ld.so.conf.
    To avoid that, use ldconfig to import all the known paths into
    LD_LIBRARY_PATH.
2023-03-03 15:39:38 +01:00
Jean-Paul Chaput 57b5cca27f Downgrade CMake requirements to 3.16. Detects correctly Python 3.
Fix courtesy of N. Shimizu.
2023-03-03 15:36:40 +01:00
Jean-Paul Chaput 50937d69c7 Add basic yosys (nopy), klayout scripts and command support to designflow.
* New: In cumulus.designflow: add yosysnp to manage Yosys without
    Python support enabled.
      Add klayout support for running scripts in batch mode.
      Add generic system command support.
* Change: In cumulus.designflow.task.TaskFlow, systematically
    convert pathes (str) into pathlib.Path in targets and depends.
* New: In cumulus.designflow.clean.Clean, add cleaning by glob.
2023-03-01 23:57:55 +01:00
Jean-Paul Chaput 5546c2d89f Fix nightly build path finding in crlenv.py. 2023-03-01 11:42:50 +01:00
Jean-Paul Chaput 94323f28e0 Merge branch 'poetry-cleanup' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2023-02-28 13:49:20 +01:00
Jean-Paul Chaput c68932c813 Policy change for NDA/third party modules loading ("addons.coriolis").
* Change: In cumulus/plugins/__init__.py, new behavior for loading
    plugins supplied as third party. In order to avoid messing up
    with the "site-packages/coriolis/" main package tree (with
    modules named "coriolis.<MODULE>", they have to be under
    "site-packages/addons/coriolis/" (so modules will be named
    "addons.coriolis.<MODULE>"). This should prevent *overwritting*
    standard modules by third party ones.
      Now uses pathlib for module loading.
      Had a conflict between Hurricane.Path and pathlib.Path, now do
    not import the Hurricane one into the module globals...
2023-02-28 13:32:11 +01:00
Jean-Paul Chaput 800305abc3 Removed long obsoleted XML techno config files. 2023-02-27 23:08:03 +01:00
Jean-Paul Chaput f404bcc8c0 Fix small regression in initHook.py of bora & katana. 2023-02-27 22:34:44 +01:00
Jean-Paul Chaput 1557d613ae Comprehensive reorganisation of the Python part of Coriolis.
* Move all Python stuff under a common Python namespace "coriolis".
* Instead of having a series subtrees for each tool, integrate
  everything in one common tree. So now, all components can be
  located either with an absolute path from "coriolis" or, inside
  cross-reference themselves through relatives imports.
* As a consequence, we only need to add ".../site-packages/coriolis/"
  to the PYTHONPATH, and not a whole bunch of subdirectories.
  And nothing, if installed in-system.
* The tree of free technologies configuration files is also moved
  below "coriolis/technos" instead of "/etc".
* Supressed "cumulus" level for the plugins.
* All python modules are rewritten using relative imports except
  for the configuration files that uses absolute import as they
  can be cloned outside of the tree to serve as templates.

* Change: In boostrap/FindPythonSitePackages, include "/coriolis" in
    Python_CORIOLISARCH and Python_CORIOLISLIB.
      Provide a Python_SITELIB *without* "/coriolis" appended.
* Change: In cumulus/plugins/__init__.loadPlugins(), must prefix modules
    read in the plugins directory by "coriolis.plugins.". No longer need
    to add their path to sys.path.
* Change: In crlcore/python/technos/nodeX/*/devices.py, the scripts of
    the layouts generators must be prefixed by "coriolis.oroshi.".
* Change: In CRL::System CTOR, no longer add the pathes of the various
    plugins to sys.path. Only "site-packages/coriolis/".
* New: In Utilities::Path::toPyModePath(), new method to convert a
    filesystem path into a python module path.
      Examples:
        "coriolis/plugins/block"    --> "coriolis.plugins.block".
        "coriolis/plugins/rsave.py" --> "coriolis.plugins.rsave".
* Change: In katanaEngine::_runKatanaEngine(), rename the hook script
    initHook.py. No longer need to modify sys.path.
* Change: In BoraEngine::_runBoraEngine(), rename the hook script
    initHook.py. No longer need to modify sys.path.
* Change: In UnicornGui::_runUnicornInit(), rename the hook script
    initHook.py. No longer need to modify sys.path.
* Change: In cumulus.plugins.chip.constants, put the constants
    outside __init__.py to avoid a loop at initialization.
2023-02-27 22:14:32 +01:00
Jean-Paul Chaput c37e6ff953 Regenerated documentation, just to check. 2023-02-22 15:02:39 +01:00
Jean-Paul Chaput b6961a10c9 Deprecation of Mauka & hMetis (old simulated annealing placer). 2023-02-21 17:06:16 +01:00
Jean-Paul Chaput 3d9e86303e Final deprecation of Katabatic, Knick & Kite. 2023-02-21 17:04:38 +01:00
Robert Taylor fabcabe31d Add pattern back in for git tag versioning 2023-02-21 16:10:55 +01:00
Robert Taylor 6b455b66d5 Use metadata in version number 2023-02-21 16:10:55 +01:00
Robert Taylor d49c76791a Don't package docs in the wheel 2023-02-21 16:10:55 +01:00
Robert Taylor 4aa7b680a7 Use git tags to version releases 2023-02-21 16:10:55 +01:00
Robert Taylor a1bd7cae8a Add readme to pyproject.toml 2023-02-21 16:10:55 +01:00
Robert Taylor 3d25c6881d Upload wheels in CI 2023-02-21 16:10:55 +01:00
Robert Taylor 3196196642 enable epfl repo 2023-02-21 16:10:55 +01:00
Robert Taylor 42de4409c5 CI: fix architectures 2023-02-21 16:10:55 +01:00
Robert Taylor d8e67e5e7d Reduce debug output 2023-02-21 16:10:55 +01:00
Robert Taylor f0cd6e602a Use ninja for build 2023-02-21 16:10:55 +01:00
Robert Taylor d10b7524ce remove cylop and cx2y from scripts 2023-02-21 16:10:55 +01:00
Robert Taylor fa1f8e78e0 CI: only build cpython >= 3.8 2023-02-21 16:10:55 +01:00
Robert Taylor 32a6aaf61f Ignore missing symbols harder when linking python 2023-02-21 16:10:55 +01:00
Robert Taylor 7a8a3d3434 Always pass build type 2023-02-21 16:10:55 +01:00
Robert Taylor 8f8671c8fb Only build cycop and x2y when in debug build 2023-02-21 16:10:55 +01:00
Robert Taylor a02c88a893 Don't link libpython, it isn't there in manylinux 2023-02-21 16:10:55 +01:00
Robert Taylor eb26bb1f87 fix to build on manylinux 2023-02-21 16:10:55 +01:00
Robert Taylor 6088ab7b69 Split out python versions in CI 2023-02-21 16:10:55 +01:00
Robert Taylor c22dfe3216 Pass in python library path to cmake 2023-02-21 16:10:55 +01:00
Robert Taylor 095e260e3b Use target_link_libraries correctly everywhere to avoid runtime link issues 2023-02-21 16:10:55 +01:00
Robert Taylor 974473aff7 fix rpaths - really didn't need quoting 2023-02-21 16:10:55 +01:00
Robert Taylor 78f4107f36 Update poetry lock 2023-02-21 16:10:55 +01:00
Robert Taylor 0868283e43 Fix runtime linking error 2023-02-21 16:10:55 +01:00
Robert Taylor 4e879b4506 RPATH for libraries to find other coriolis libs 2023-02-21 16:10:55 +01:00
Robert Taylor 412f9bb22d Fixes for cibuildwheel building 2023-02-21 16:10:55 +01:00
Robert Taylor e1736fcdba Support older qwt 2023-02-21 16:10:55 +01:00
Robert Taylor 7789c6db80 update poetry lock 2023-02-21 16:10:55 +01:00
Robert Taylor 52f64bc9d3 Use the running python for cmake 2023-02-21 16:10:55 +01:00
Robert Taylor 2b88f8188c try dropping python dependancy and see what breaks 2023-02-21 16:10:55 +01:00
Robert Taylor e7fcfd1a44 Add gitlab CI using cibuildwheel 2023-02-21 16:10:55 +01:00
Robert Taylor 29add5e898 Fix tutorial for python 3 2023-02-21 16:10:55 +01:00
Robert Taylor 05c0f955c5 Fix up rpath of binaries 2023-02-21 16:10:55 +01:00
Robert Taylor c6795754a1 Move into Corilois namespace 2023-02-21 16:10:55 +01:00
Robert Taylor a3abb567b5 Add version and author to pyproject.toml 2023-02-21 16:10:55 +01:00
Robert Taylor 424c61d6a4 Fix errors when building clean 2023-02-21 16:10:55 +01:00
Robert Taylor ebabf1e988 install helpers at top level 2023-02-21 16:10:55 +01:00
Robert Taylor df78c3ab48 Add bin files as scripts 2023-02-21 16:10:55 +01:00
Robert Taylor 5a669c4641 Fix Python linking issues 2023-02-21 16:10:55 +01:00
Robert Taylor b07bf75283 Give same import semantics for now, fix rpath issue 2023-02-21 16:10:55 +01:00
Robert Taylor ee2e18f801 Add Coriolis dir that poetry needs, along with base __init__.py 2023-02-21 16:10:55 +01:00
Robert Taylor d614e490e7 Poetry package build working for most of coriolis 2023-02-21 16:10:55 +01:00
Robert Taylor f8afd5bded Move to packaging requiring no changes to CMake 2023-02-21 16:10:54 +01:00
Robert Taylor 806018b740 Initial Poetry infrastructure 2023-02-21 16:10:54 +01:00
Robert Taylor 858a783ddd Move decprecated components out of the way, to avoice confusion 2023-02-21 16:10:54 +01:00
Jean-Paul Chaput db56681025 More tweaking in the H-Tree Y offset, to avoid stacked VIAs. 2023-02-15 15:17:28 +01:00
Jean-Paul Chaput 07f269196b Manage new cases of stacked VIAs potential creation.
When placing a vertical M1 (and setting it's axis), the perpandiculars
M2 extremities changes, and they have a VIA. If they are already placed
too, they may silently create a stacked VIAs because the track markers
of the perpendiculars are not taken into account. Now, force to rip them
up so the markers will be re-read. If no stacked VIAs has been created,
the segment will be re-put at it's previous place, otherwise it will be
placed on another track.

* New: Track::hasViaMarker(), check if a marker of a Net is under a
    given interval (so we can know we are about to create a VIA stack).
* New: Manipulator::avoidStackedVias(), ripup perpandiculars to the
    current segment that *may* create stacked VIAs. That is perpandicular
    in the *up* layer which begin or end on the moved vertical.
* New: In SegmentFsm::insertInTrack(), bindTotrack() & moveToTrack(),
    call Manipulator::avoidStackedVias(), if activated.
* Change: In NegociateWidow/loadRoutingPads(), no longer exclude clock
    nets. So the TrackMarkers are created for the root net.
2023-02-14 22:35:56 +01:00
Jean-Paul Chaput 77afb7cba4 Quick for H-Tree driver Y offset (account for root & symmetry). 2023-01-23 14:46:30 +01:00
Robert Taylor cf92ee9588 Add pattern back in for git tag versioning 2023-01-20 16:13:36 +00:00
Robert Taylor 53af6a2a87 Use metadata in version number 2023-01-19 16:04:18 +00:00
Robert Taylor 0860dffb61 Don't package docs in the wheel 2023-01-19 16:04:18 +00:00
Robert Taylor 8d74ed8110 Use git tags to version releases 2023-01-19 16:04:18 +00:00
Robert Taylor b8d2a0e598 Add readme to pyproject.toml 2023-01-19 16:04:18 +00:00
Robert Taylor 4cab713fc9 Upload wheels in CI 2023-01-19 16:04:18 +00:00
Robert Taylor 651cf57a13 enable epfl repo 2023-01-19 16:04:18 +00:00
Robert Taylor 4281370f2e CI: fix architectures 2023-01-19 16:04:18 +00:00
Robert Taylor d7f6917047 Reduce debug output 2023-01-19 16:04:18 +00:00
Robert Taylor 64b0fda925 Use ninja for build 2023-01-19 16:04:18 +00:00
Robert Taylor aac5b8554b remove cylop and cx2y from scripts 2023-01-19 16:04:18 +00:00
Robert Taylor b5a669291e CI: only build cpython >= 3.8 2023-01-19 16:04:18 +00:00
Robert Taylor 69bdbd9cd8 Ignore missing symbols harder when linking python 2023-01-19 16:04:18 +00:00
Robert Taylor e8f31aa852 Always pass build type 2023-01-19 16:04:18 +00:00
Robert Taylor 56e31c79b7 Only build cycop and x2y when in debug build 2023-01-19 16:04:18 +00:00
Robert Taylor 1b9a91cb1c Don't link libpython, it isn't there in manylinux 2023-01-19 16:04:18 +00:00
Robert Taylor 05fbfbe7fe fix to build on manylinux 2023-01-19 16:04:18 +00:00
Robert Taylor 4da93f3394 Split out python versions in CI 2023-01-19 16:04:18 +00:00
Robert Taylor b2bbaead53 Pass in python library path to cmake 2023-01-19 16:04:18 +00:00
Robert Taylor 56aa1b189c Use target_link_libraries correctly everywhere to avoid runtime link issues 2023-01-19 16:04:17 +00:00
Robert Taylor deaff0842f fix rpaths - really didn't need quoting 2023-01-19 16:04:17 +00:00
Robert Taylor 90c478e8c4 Update poetry lock 2023-01-19 16:04:17 +00:00
Robert Taylor 4b7973ac84 Fix runtime linking error 2023-01-19 16:04:17 +00:00
Robert Taylor 8ccd9618dd RPATH for libraries to find other coriolis libs 2023-01-19 16:04:17 +00:00
Robert Taylor c1fdf4963b Fixes for cibuildwheel building 2023-01-19 16:04:17 +00:00
Robert Taylor 842602cdcb Support older qwt 2023-01-19 16:04:17 +00:00
Robert Taylor e72c2b7af1 update poetry lock 2023-01-19 16:04:17 +00:00
Robert Taylor b638f235a7 Use the running python for cmake 2023-01-19 16:04:17 +00:00
Robert Taylor f3186d7ed1 try dropping python dependancy and see what breaks 2023-01-19 16:04:17 +00:00
Robert Taylor 06dfdfb52f Add gitlab CI using cibuildwheel 2023-01-19 16:04:17 +00:00
Robert Taylor 198d5ce035 Fix tutorial for python 3 2023-01-19 16:04:17 +00:00
Robert Taylor 449ee2e81e Fix up rpath of binaries 2023-01-19 16:04:17 +00:00
Robert Taylor f604351fa2 Move into Corilois namespace 2023-01-19 16:04:17 +00:00
Robert Taylor 546dfa2f20 Add version and author to pyproject.toml 2023-01-19 16:04:17 +00:00
Robert Taylor c0054eb267 Fix errors when building clean 2023-01-19 16:04:17 +00:00
Robert Taylor 46acf17e47 install helpers at top level 2023-01-19 16:04:17 +00:00
Robert Taylor a0b307b3b4 Add bin files as scripts 2023-01-19 16:04:17 +00:00
Robert Taylor cd4f8560ca Fix Python linking issues 2023-01-19 16:04:17 +00:00
Robert Taylor 8dfd522b71 Give same import semantics for now, fix rpath issue 2023-01-19 16:04:17 +00:00
Robert Taylor d31c489e33 Add Coriolis dir that poetry needs, along with base __init__.py 2023-01-19 16:04:17 +00:00
Robert Taylor 80e83d42ed Poetry package build working for most of coriolis 2023-01-19 16:04:17 +00:00
Robert Taylor 57ac01b54a Move to packaging requiring no changes to CMake 2023-01-19 16:04:17 +00:00
Robert Taylor c277d9f121 Initial Poetry infrastructure 2023-01-19 16:04:17 +00:00
Robert Taylor c41b92e45f Move decprecated components out of the way, to avoice confusion 2023-01-19 16:04:17 +00:00
Jean-Paul Chaput f7b2a4f5bb The previous fix for low metal tech, must apply only for them in htree. 2023-01-19 14:54:00 +01:00
Jean-Paul Chaput 38cc00005d Fix missing VIA & bad offset in htree for low metal techs. 2023-01-19 13:57:35 +01:00
Jean-Paul Chaput 96fe367cc0 Fix overlap of non-used RoutinPads in VH,2RL styles.
* New: In KatanaEngine::digitalInit(), when using a "VH,2RL" style,
    protect all RoutingPads of each net, because unlike "2RL+" style,
    the standard cell RoutingPads are not in a "below" layer only
    used inside the cell, but on the V layer. So the area of the RP,
    even if not fully used to connect, must be protected.
* Change: In NegociateOverlapCost(), when computing cost from a fixed
    or blockage, do not set the infinite flag if it's the *same* net.
* New: In KatanaEngine::protectRoutingPads(), add a new "flags" argument
    to pass on whether we want to protect the the RP candidates or just
    the non-used ones.
* Change: In protectRoutingpad(), change the formula (again) to compute
    the berth to give to a fixed segment... Should really try to
    summarize all the case.
* Change: In TrackFixedSegment::getNet(), no longer return the blockage
    net if the real net is tagged as clock.
2023-01-18 23:42:38 +01:00
Jean-Paul Chaput 047bf14921 Wrong computation of the up/down dogleg layer for 2 layers gauges.
* Bug: In Anabatic::AutoHorizontal::_makeDogleg(), the up/down flag
    was incorrectly computed when the RoutingGauge RL where not the
    lower one. This was leading to making doglegs in non-routable
    layers (but present in the gauge for other purposes).
2023-01-18 23:42:17 +01:00
Jean-Paul Chaput 2116e181de Add a breakpoint *before* global routing loading in cumulus/block.py. 2023-01-18 23:20:28 +01:00
Jean-Paul Chaput c7330041fb Remove unmatched DebugSession::close() in RawGCellsUnder. 2023-01-18 15:49:51 +01:00
Jean-Paul Chaput 7598485a4f Allow the BigVia to stack the cuts in some cases. 2023-01-14 22:38:36 +01:00
Jean-Paul Chaput 9df5fc838c Support for non-stacked VIAs in Katana.
* New: In Katana::Configuration, added option:
    "cfg.katana.disableStackedVias" (default to false), so the router
    do not stack VIAs on top of each other.
* Bug: In NegociateWindow::loadRoutingPads(), create TrackMarkers using
    the right depth when the gauge starts with non-routable ones.
* New: In Track::addOverlapCost(), when disableStackedVias is active,
    uses the markers from the below terminals to tag the cost as
    "infinite", so the track *cannot* be used by the marker's net
    owner. Can be refined by checking that we are not at a segment's
    end but will do for now.
2023-01-14 22:35:57 +01:00
Jean-Paul Chaput 7d88b14334 Keep Sphinx variant documentation sources, just in case... 2023-01-14 12:45:08 +01:00
Jean-Paul Chaput 0a69e7d62d Correct broken links in Python Tutorial documentation. 2023-01-14 12:41:06 +01:00
Jean-Paul Chaput 181b2e1080 Re-enable and check the building of I/O ring with pad spacers.
* New: In cumulus/block.bigvia, add a getBoundingBox() method.

* New: In cumulus/block.configuration.GaugeConf.rpAccess(),
    add a vertical strap segment in case the RP is not high enough to
    accomodate the potential offset of the contact.
      In case of gauge with only two routing layers, if the RP
    is vertically accessed, do not put a VIA12 but just a METAL2
    contact (there will be *no* turn).

* Change: In cumulus/chip.CoreWire.drawWire(), the wire at *chip level*
    going to the pad was shrunk of 3 pitch when *not* in the preferred
    routing direction. Removing it as it creates gaps in some cases.
      This was likely needed for a specific kind of I/O pad so should
    be re-enabled on targeted cases in the future.

* Change: In cumulus/chip.corona.VerticalRail, manage in a smarter way
    the conflicts when a rail is accessed from both sides overlapping
    on an Y position. That is, from the supply I/O pads *and* from the
    *core* supply lines.
      Formerly, we just didn't connect the core power line, which was
    a mistake potentially leaving power rails unconnected (it it did
    occur on both sides).
      Also checks if the conflict really arise, that is, the power lines
    are both on top or bottom.

* Change: In cumulus/chip.pads.Side._placePad(), manage I/O pads with
    a bottom left corner of abutment box *not* at (0,0). Argh!

* Bug: In cumulus/chip.pads, create the filler pad instances in the
    chip, not in the corona.
2023-01-14 12:39:22 +01:00
Jean-Paul Chaput 0e17b91692 Add at least one pitch to each cell in BloatChannel profile.
* Change: In Etesian::BloatChannel, when two DFFs are side by side, if
    they are not separated by at least one pitch, the track avoid
    mechanism will not be able to work. Hence the minimal one pitch.
2023-01-14 12:09:43 +01:00
Jean-Paul Chaput 83ff59817a Export CellViewer::setPixelThreshold() to the Python interface. 2023-01-14 12:06:15 +01:00
Jean-Paul Chaput c86d074f06 Export Contact::setLayer() to the Python interface. 2023-01-14 12:05:51 +01:00
Jean-Paul Chaput 3e921ff07a More debug information in chip pad & corona generation.
* Change: In cumulus/plugins.chip.configuration, do not add an extra
    slice height to the minHCorona & minVCorona. Now seems a bit overkill
    on small chips.
2023-01-09 09:26:44 +01:00
Jean-Paul Chaput bdb0091043 Just a little indentation for my autistic self. 2023-01-09 09:21:56 +01:00
Jean-Paul Chaput e38e3f46f2 Route ring pad wires, even if there is no pad on that side. 2023-01-07 13:08:10 +01:00
Jean-Paul Chaput 0bc7b3203a Add DesignFlow to the doc generation. New snapshot of the doc. 2023-01-07 13:01:23 +01:00
Jean-Paul Chaput 30afe6036b Add management of unused layers in cumulus/plugins.block.configuration. 2023-01-07 12:57:23 +01:00
Jean-Paul Chaput d9ebeb4b96 Search path reordering in crlenv.py so the debug version can be found. 2023-01-07 12:53:11 +01:00
Jean-Paul Chaput d2b40d568b Extend routing gauge to support non-routing layers at the bottom.
* New: In CRL::RoutingLayerGauge, two new types of gauge are supported:
    - Unusable : just do nothing with it, but the layer is stacked.
    - BottomPowersupply : can be used for supply routing only, and
      is *below* the normal routing layers (instead of on top as
      usual).
    Both new types must be *below* the real routing layers.
* New: In CRL::RoutingGauge, add a new attribute "firstRoutingLayer"
    to give the index (depth) of the first layer usable for routing.
    (not Unusable and not BottomPowerSupply)
* New: In Anabatic::Session & Anabatic::NetBuilder, in order to build
    the initial wiring, provides (Session) and use (NetBuilder) the
    new functions:
      - getBuildRoutingLayer(depth)
      - getBuildContactLayer(depth)
      Thoses functions takes into account (offset) the unusable layers
    so depth 0 is the first usable routing layer, and so on.
2023-01-07 12:51:38 +01:00
Jean-Paul Chaput 2501688dd1 Add support for layers alias names. Bug in _addPhysicalrule().
* New: In Technology, in order to support symbolic technology on top
    of a real technology using non-generic layer names, it comes in
    handy to be able to define layer alias names. Generic *real*
    layer names could be defined as alias over the technology
    specific ones. Then, we can build the symbolic layers upon
    the generic names (so *that* part of the init code can be
    shared between techs).
       Adds Technology::addLayerAlias()
       The semantic of Technology::getLayer() changes a little, it
     return the techno layer associtated to the name *or* the
     aliased name.
* Bug: In Technology::_addPhysicalRule(), in case of a rule redefinition,
    we were using it's name *after* the deletion of the rule object.
    Nasty crash.
      Improve the error message by giving the name of the conflicting
    rule.
* In CRL/helpers.analogtechno, add an addDevice() function to load
    analogic devices descriptors (copied from the old init system).
* In CRL/ApParser, if an exception is catched, tells in which file and
    line it did occur.
* In Oroshi/dtr.Rules, add a translation step to get the rule names
    from the technology. From generic names to actual technology
    layer names.
       Add some documentation.
* In Oroshi/stack.Stack, get the layers names through dtr.Rules to get
    the layers names translated.
2023-01-05 16:58:49 +01:00
Jean-Paul Chaput da56189d2e allianceInstaller.sh also must support nightly builds. 2023-01-02 12:24:19 +01:00
Jean-Paul Chaput db54e685f7 Correct again for nightly build. 2023-01-02 12:06:03 +01:00
Jean-Paul Chaput 100342e640 Support for nightly build in booststrap/crlenv.py. 2023-01-02 11:47:45 +01:00
Jean-Paul Chaput e590400ebb Add DoIt base design flow support. In full replacement of Makefiles. 2022-12-31 15:01:37 +01:00
Jean-Paul Chaput ae01be3c53 Set the initial verbose levels to off. Smarter loadUserSettings(). 2022-12-31 14:50:46 +01:00
Jean-Paul Chaput 36eb9f9121 Export the Alliance library list in AllianceFramework (as a list). 2022-12-31 14:48:25 +01:00
Jean-Paul Chaput b8cd4264bd Bug in topology management switch in NetBuilder::construct().
* Bug: In NetBuilder::construct(), the xG_xM1 topologies where wrongly
    redirected towards xG_1M1, so only one M1 was connected, all others
    left floating.
      Now direct them towards xG_xM1_xM3.
* Bug: In NetBuilderHybridVH, activate topology management for 2G_1M1.
2022-12-16 20:02:11 +01:00
Jean-Paul Chaput b65e6f83ff More clean approach to the verbosity levels in overlay and io. 2022-12-16 17:17:30 +01:00
Jean-Paul Chaput c85ad530c4 Take into account blockages and right shift bug in track avoidance.
* Change: In Etesian::SubSlice::getUsedVTracks(), now take blockages
    into account for used vertical tracks.
* Bug: In Etesian::SubSlice::avoidTrack(), right free interval for
    shifting was wrongly computed, effectively allowing *any* shift.
    This was creating cells overlap!
* New: In Hurricane::BasicLayer & Layer, establish a two way link
    between the blockage layer and routing layer. Now we can access
    the routing layer from the blockage.
2022-12-16 17:17:05 +01:00
Jean-Paul Chaput ca41dbd5ef Support for avoidance of vertical tracks in low metal techs.
* New: In NetBuilderHybridVH::_do_1G_xM1_1PinM1(), added configuration
    to manage pins on the north/south sides for VH,2RL.
* Bug: In NetBuilderHybridVH::doRp_xG_xM1_xM3(), correct misplaced
    vertical creation (buildind invalid topologies).
* New: EtesianEngine::toColoquinte(), display histograms of the cells
    widths (in pitch) before and after bloating to get a better feeling
    of the behavior.
* New: In EtesianEngine, add support for track avoidance. Portions of
    tracks to avoid are specified by a Box, which should flat and on
    the axis of the request track. This feature is used by the H-Tree
    to clear the vertical tracks under the tree from any terminal.
* New: In Etesian::Area, Slice and SubSlice, add support for track
    avoidance. Exported to the Python wrapper.
* New: SubSlice::getUsedVTracks() to get a set of tracks blocked by
    the cell.
* New: SubSlice::trackAvoid(), shift left/rigth the cell under the
    requested vertical track. Try only to move the cell under the
    track and not it's neighbor, so it assume that there is sufficient
    space left or right of the cell.
* Bug: In cumulus/plugins.block.configuration.BlockConf, the Cfg
    parameters may be read too early from the Cfg space into the
    various sub-conf objects (like FeedsConf). Delay the reading
    of the parameters in a _postInit() functions.
      Modify Block and CoreToChip to call _postInit().
* New: In cumulus/plugins.block.configuration.BlockConf._loadRoutingGauge,
    allow the cell gauge name to differ from the routing gauge name.
* New: In cumulus/plugins.block.configuration.FeedsConf, allow to
    select the default feed to be used with 'etesian.defaultFeed'
    parameter.
* New: In cumulus/plugins.block.spares.BufferPool, allow to control
    whether or not we want tie to either side of the pool.
    (for latch up).
* New: In cumulus/plugins.block.HTree._connectLeaf(), add support
    for track avoidance.
* Bug: In cumulus/plugins.block.HTree._connectLeaf(), the TL2 contact,
   the one on the *top* auxiliary buffer seemed to have been badly
   positioned until now (too low, not using tl2Y).
     This is strange because it should have caused disconnections,
   but I didn't see it in the wiring and the regressions tests didn't
   flag anything wrong. Still a bit weird and worrying.
2022-12-13 16:02:23 +01:00
Jean-Paul Chaput 49bcdb3195 One more remains of the previous routing configuration. 2022-11-26 15:05:56 +01:00
Jean-Paul Chaput c131e7a948 Clean parameters for routing topologies. Improved 2RL- support.
Previously, the relevant NetBuilder and routing strategies where
directly guessed from the RoutingGauge traits. This is no longer
doable as the combinations increases. Now to configure both the
global and detailed router we need three "parameters" :

1. The routing gauge itself (tells which layers are in which
   directions) and how to make the VIAs.
2. The NetBuilder to use, they are identified by strings.
   Currently we support:
   * "HV,3RL+", for all SxLib derived standard cells.
   * "VH,2RL", for hybrid routing (over the cell, but terminals
     are also in the first RL).
   * "2RL-", for strict channel routing.
   * "VH,3RL+", an attempt for FreePDK 45, not optimized enough
     to be considered as usable.
3. The routing style, mostly affect the way the GCell grid will be
   built.
   * VH      : first RL is V.
   * HV      : first RL is H.
   * OTH     : Run in full over-the-cell mode (needs at least 3RL).
   * Channel : Run in *strict* channel routing mode (no routing over
               the standard cells).
   * Hybrid  : Create channels, but can use H tracks over the
               standard cells.

Thoses three parameters are partly overlapping and must be sets in
a consistent manner, otherwise strange results may occurs.

* New: CRL::RoutingGauge::getFirstRoutingGauge(), to get the lowest
    layer available for routing (not a PinOnly, not a PowerSupply).
* Change: In CRL::RoutingGauge::isHV() and isVH(), were previously
    always returning false when the gauge was 2RL only. Now, check
    on the first usable RL.
* Bug: In cumulus/plugins.block.configuration._loadRoutingGauge(),
    there was a bad computation of the deep RLs when the top layer
    was not defined. Occured for 2RL gauges only.
* Bug: In Anabatic::RpsInRow::slacken() (LayerAssign), forgotten curly braces
    in the test to skip METAL2 terminals.
* Change: In Etestian::BloatChannel::getDx(), adjust the bloating
    policy to converge on Arlet6502. Always ensure that there is
    a 50% ratio between terminal used V-tracks and free ones.
      If there is more than 80% of terminals, add one more track.
* Bug: In AnabaticEngine & KatanaEngine, KatanaEngine is a derived
    class of AnabaticEngine.  They uses Anabatic::Configuration
    and Katana::Configuration that also derives from each other.
    I though I had made one configuration attribute in the base
    class that was using the right Configuration. But no. I did
    have two configurations attributes, one in AnabaticEngine and
    one in KatanaEngine, the later "shadowing" the former. As a
    results, parameters modified in AnabaticEngine, *after* the
    initial creation of the tool *where never seen* at Katana
    level (due to it's own duplicate). What a mess.
      Now there is only one attribute in the *base* class Anabatic,
    which is created through a new virtual function _createConfiguration()
    called in _postCreate() which allocate the right Configuration
    according to the dynamic type of the tool (KatanaEngine).
      In KatanaEngine, access the configuration through the
    attribute (_configuration) and not the accessor (getConfiguration()).
* Bug: In KatanaEngine, no longer directly use the _configuration attribute
    (which is not accessible anyway) but the getConfiguration() accessor.
    The accessor perform a static_cast from the Super::getConfiguration()
    into Katana::Configuration.
      Complete cleanup of the various configuration accessors.
* New: AnabaticEngine::setupNetBuilder(), perform an early check
    of the requested NetBuilderStyle. The NetBuilderStyle is just a
    string that will be matched against the (hard-coded) supported
    NetBuilders. Then check the topological characteristics against
    the capabilities of the gauge (HV, VH and so on).
      Still a bit too hard-coded for now.
      This function has been split from AnabaticEngine::_loadGrByNet().
* Change: AnabaticEngine::isChannelStyle() renamed from isChannelMode().
* New: In Anabatic::Configuration, two new attributes to select the
    topology and routing style:
      - _netBuilderStyle to explicitely select the NetBuilder to use.
        It's a string, which is provided by each NetBuilder.
      - _routingStyle to define how the overall routing will work.
        It's a set of flags (StyleFlags):
	* VH      : first RL is V.
	* HV      : first RL is H.
	* OTH     : Run in full over-the-cell mode (needs at least 3RL).
	* Channel : Run in *strict* channel routing mode (no routing over
	            the standard cells).
	* Hybrid  : Create channels, but can use H tracks over the
	            standard cells.
* New: In anabatic/Constants, add StyleFlags to define how the router
    should operate (see above).
* Bug: In Anabatic::GCell, in CTOR, no reason to set up the HChannelGCell flag.
* Bug: In Anabatic::GCell::updateDensity(), when computing layers non contiguous
    saturation, do not systematically skip RL 0, but only if it's PinOnly.
* Change: In Anabatic::NetBuilder, rename isTwoMetal by isStrictChannel.
* Change: In Anabatic::NetBuilderHV, rename doRp_AccessNorthPin() in
    doRp_AccessNorthSouthPin(). More accurate.
* Bug: In NetBuilderHV::_do_1G_xM1_1PinM2(), the wires to connect the M1
    terminals where created *twice*. Uterly stupid, there where placed in
    overlap by the router!
* New: In AnabaticEngine, new accessors to the NetBuilderStyle and
    RoutingStyle, proxies towards Configuration.
* Bug: In Manipulator::relax(), if there are two doglegs to be done, but
    they are in the same GCell, only do one (the conflicting interval)
    is short.
* Change: In Katana::Session, rename isChannelMode() into isChannelStyle().
* Change: In TrackSegment::isUnbreakable() and isStrap(), return false
    when the base segment is a *weak global* (aligned with a global one).
* Change: In Katana::Row::createChannel(), correctly distinguish between
    *strict channel* style and *hybrid* style. Tag the GCells as std cells
    row or channels only in the former case.
2022-11-26 13:07:12 +01:00
Jean-Paul Chaput e262c7bd1a Merge branch 'fix-duplicate-case-filenames' into 'devel'
Remove old generated files that clash on case-insensitive file systems

See merge request vlsi-eda/coriolis!15
2022-11-15 23:06:13 +00:00
Robert Taylor 68a3695780 Remove old generated files that clash on case-insensitive file systems 2022-11-15 11:51:43 +00:00
Jean-Paul Chaput 2b870fc609 Remove obsolete dependency towards LibXml2 in CMakeLists.txt. 2022-11-07 17:36:49 +01:00
Jean-Paul Chaput ecda00e154 Adjustments in AutoSegment::canReduce() and TrackSegment::canRealign().
* Change: In AutoSegment::canReduce(), allow reduction, when in channel
    mode, for bottom connected jumpers at depth 1. Forbidden otherwise
    as it may cause problems with the terminals (in OTC).
* Change: In TrackSegment::canRealign(), allow realignement of reduced
    segments. What really needs to be checked is that it do not have
    perpandiculars in reduced state.
2022-11-03 10:36:44 +01:00
Jean-Paul Chaput 15412317ec Add a second repair stage after the realing stage of the router.
* New: In Katana::NegotiateWindow::_negociate(), if the realign stage is
    enabled, perform a second stage of repair after it. To do this we
    need to reverse the state of events marked as FailedRepair to Repair.
      We isolate the repair stage in a new dedicated function,
    NegociateWindow::_negociateRepair(). Maybe should do the same for
    each other negociate stage.
2022-11-03 00:21:51 +01:00
Jean-Paul Chaput 8c182672dd Cleanly get rid of PyQt dependency.
* New: Hurricane::ErrorWidget, new widget exported to Python to replace
    helpers.io.ErrorWidget.
* New: Hurricane::AboutWindow, new window exported to Python to replace
    cumulus/plugins.aboutwindow.AboutWidget.
2022-11-02 00:21:00 +01:00
Jean-Paul Chaput 13795bec48 Add Environement attribute (pattern) to match the FF names. 2022-10-31 16:31:30 +01:00
Jean-Paul Chaput a0880da706 Issue a warning when the blockage net (for OBS) do not exists. 2022-10-31 16:29:07 +01:00
Jean-Paul Chaput 1253eeeef4 Allow the user to choose the name of the SRAM. Placement fix.
* Change: In cumulus/plugins.sram.sram_256x32, add a new parameter to
    __init__() so the user can choose the model name of the generated
    SRAM.
* Change: In cumulus/plugins.sram.sram.BaseSRAM.placeInstance(),
    placement status must be FIXED instead of PLACED so the placer do
    not "unplace" them.
      The Cell.updatePlacedFlag() method must also be called once
    the model if fully built.
2022-10-30 10:36:52 +01:00
Jean-Paul Chaput 11bae679f1 Export the Cell::updatePlacedFlag() to the Python interface. 2022-10-30 10:10:23 +01:00
Jean-Paul Chaput 3613ce0b5d Typo in LefImport, the conf variable name is "lefImport.unmatchedlayers". 2022-10-30 10:08:43 +01:00
Jean-Paul Chaput 47b26476b7 Fixed bad perpand interval computation in AutoSegment::getTopologicalinfos(). 2022-10-27 19:47:44 +02:00
Jean-Paul Chaput dbfcfae1e8 Update of the DefExport (work in progress).
* New: In CRL::DefExport, checkStatus() has a second argument to display
    a more comprehensive error message.
      Applied throughout all the DEF callbacks.
* Bug: In CRL::DefExport, the UNIT statement and associated toDefUnits()
    functions where wrong. Now always use a UNITS of 1000 in microns.
    Then toDefUnits() converts DbU into microns and multiply by 1000.
* Change: In CRL::defExport::_netCbk(), enable the net name renaming
    only when the ProtectNetNames flag is set.
* New: In CRL::PyDefExport, also export the flag values to Python.
2022-10-27 19:47:17 +02:00
Jean-Paul Chaput 775b6bf1fc Better management of discrepencies bewteen LEF & techno layers.
* Change: In CRL::LefImport::LefParser, layers defined in the LEF file
    are matched *in order* to the ones from the technology *in order*
    (not by name matching). But if there is a mismatch, that is more
    layers in the techno than in LEF, we got a shift. Now we can tell
    the parser to ignore a set of layers by setting up the configuration
    variable:
       LefImport.unmatchedLayers = 'DIFFP,POLY2,SMURF'
2022-10-27 19:46:29 +02:00
Jean-Paul Chaput 81920c622e Stricter layer management in the GDS parser.
* In CRL::GdsStream::_staticInit(), all the layers where added to the
    translation table, whether or not they where configured for the
    GDS stream. So the non GDS configured layers got a GDS layer
    id of 0 and were using this case. Either overwriting the legit
    layer or creating a new one while it should have been invalid.
      Now we check for the hasGds() predicate of the layers.
* In CRL::GdsStream, add a new option to tell that, layer id 0,
    if undefined, may be used as the definition of the boudary of
    the cell (abutment box).
* In CRL::PyGds, now also export the flags to the Python interface.
2022-10-27 19:45:20 +02:00
Jean-Paul Chaput 5a07033172 In BasicLayer, change GDS number types from "unsigned int" to "uint32_t". 2022-10-27 19:43:19 +02:00
Jean-Paul Chaput 7c85835c8f Added partial support for Pad (component) in RoutinPad.
* New: In Hurricane::RoutingPad, added support if the supporting component
    is a Pad. The source/target positions are computed according to the
    most likely direction.
      Change the _getEntityAsComponent() function into an inline template
    _getEntityAs<T>().
      Change the flags from an enum to static const uint32_t.
* Change: In Anabatic::Configuration, use _getEntityAs<T>.
* Change: In Anabatic::Dijkstra, use _getEntityAs<T>.
* Change: In Anabatic::NetBuilder, use _getEntityAs<T>.
* Change: In Katabatic::LoadGrByNet, use _getEntityAs<T>.
* Change: In Katana::ProtectRoutingPads, use _getEntityAs<T>.
* Change: In Bora::AnalogDistance, use _getEntityAs<T>.
* Change: In Etesian::EtesianEngine, use _getEntityAs<T>.
2022-10-27 19:42:13 +02:00
Jean-Paul Chaput 118b28b5a7 Prevent the absence of PyQt5 to stop lauching cgt.
* Change: In CRL/helpers.io, the ErrorWidget requires PyQt5 to execute but
    is not mandatory to run Coriolis/cgt. In order to be more portable,
    if it is not availble just evert to text display on the console.
      This widget will be directly supplied by Coriolis in the future
    completely removing the need for PyQt.
*Change: In cumulus/plugins/aboutwindow, same as above.
2022-10-26 16:37:16 +02:00
Jean-Paul Chaput 60c8bfe75e Remove reference to Foehn in SRAM generator (unpublished tool yet). 2022-10-26 16:32:00 +02:00
Jean-Paul Chaput 288d1c70b9 New bloat profile for channel routing (named "channel"). 2022-10-23 17:44:45 +02:00
Jean-Paul Chaput bba364eecc Fix: some AutoSegments where wrongly flagged as reduced.
* Bug: In Anabatic::AutoSegment::canReduce(), when looking at a fixed
    segment we were unconditionally flagging it as reduced if it was
    a "jumper", regardless of it's length.
      It was wrong, now also check for a length below the P-Pitch.
      This was introduced when implementing the channel routing.
2022-10-23 15:23:22 +02:00
Jean-Paul Chaput a6f61c1044 Update the channel routing feature to integrate with the OTC P&R.
* Update: In CRL/node600/phenitec/kite.py, update the routing gauge to
    the new format. So now we can use again SxLib-2M (channel routing
    SxLib for two metal technologies).
* Change: In CRL::BlifParser, if a master cell is not found in the
    AllianceFramework, then try in the Blif supplied libraries.
    This is used to load the zero, one and tie cells.
      Add a Blif::getCell() static function to look into the Blif
    supplied libraries.
* Change: In CRL::LefImport, sometimes there can be discrepencies between
    the LEF ROUTING layers and the Coriolis routing gauge. Now ignore
    routing layers that are *not* presents in the Coriolis gauge.

* Change: In AnabaticEngine, moved routingMode attribute from KatanaEngine,
    as some setup operations needs it.
* Change: In AutoSegment::canReduce(), allow fixed segments to be reduced
    if they are "jumpers" (turn+turn and top+top or bot+bot).
      This case arise on the edge of routing channels for fixed wires
    to connect terminals.
* Change: In AutoSegment::getTopologicalinfos(), compute differently the
    (leftBound,rightBound) interval when in channel mode.
       In over-the-cell mode, this interval is the one of the whole
    GCells under the wire. In channel mode, for fixed wires (that is,
    verticals connecteds to cells) this interval is reduced to half
    the GCell height, on the connected side of said channel.
      This allows Manipulator::_insertToTrack() to issue disantangling
    requests (push left/push right) for fixed segments that are face
    to face in the channel.
* Change: In Anabatic::Configuration CTOR, allow the cellGauge to have a
    different name from the routingGauge. Now if the cell gauge that
    should match the routing gauge is not found, fallback to the
    name set in "anabatic.cellGauge" parameter.
      Case occur when we try to match with CORE sites from LEF files.
* Change: In Etesian::Configuration CTOR, same change as in the
    Anabatic configuration.
* Change: In Anabatic::GCell::updateDensity(), never set the GoStraight
    flag in channel mode. This flag makes sense when there is at least
    4 routing layers (so we have 2 contiguous free of blockages).
* Bug: In Anabatic::Session::_getNearestGridpoint(), sometimes the nearest on
    grid point is outside the constraint box. Now force the point
    to remains inside constraints even if offgrid.

* Change: In Katana::DataNegociate::update(), perpandiculars that are
    either reduced or in non-preferred routing direction should not
    trigger a bug message.
* Change: In KatanaEngine::_check(), do not check for fixed, horizontal
    non-prefs AutoSegments in channel mode (avoid false bug display).
* Bug: In Manipulator::_forceToTrack(), slighty shrink (-1) the interval
    to free. The intersection function of intervals returns true when
    the two intervals *exactly* touches (1.vMax == 2.vMin). But in
    this specific case, they are not *overlapping* and no action
    should be taken...
* Bug: In Manipulator::_insertInTrack(), do not reject the track when
    we are overlapping a fixed vertical segment in channel mode.
    (Hmm, maybe already corrected by the previous one).
* Change: In Katana::NegociateOverlapCost(), in channel mode, do
    not put two overlaping vertical fixed segments into infinite cost.
    This happens when two cell connected verticals are face to face in
    a channel. We want them negociated the track (by shrinking their
    length) instead of excluding it right away.
* Change: In NegociateWindow::createTrackSegment(), in channel mode,
    do not attempt to create a track segment over a fixed and reduced
    AutoSegment.
      Do not attempt to put a non-preferred AutoSegment on a Track
    either.
* Bug: In RoutingEvent::revalidate(), the number of availables tracks
    was badly computed when in the pure constraint case, when there
    was only one it was reporting zero.
* Change: In TrackElements::TrackElements_Perpandicular::Locator,
    do not issue a bug when an non-pref or reduced AutoSegment do not
    have an associated TrackElement.
* Change: In TrackSegmentCost::update(), do not issue a bug when a
    perpandicular is reduded or non-pref and do not have a TrackElement.
2022-10-22 16:39:22 +02:00
Jean-Paul Chaput 9594476ab6 Improved SRAM output multiplexer, using NAND/NOR.
* New: In cumulus/plugins/sram_256x32.py, build the output mux using a
    NAND2/NOR2 binary tree instead of mux2/mux3. Use more, but much
    smaller cells. The reduction of wirelength (from Yosys) goes
    from 4% to 15% for the non-folded variant.
      Uses a specially placed tree to minimize wire length.
* New: In cumulus/plugins/sram.py, extend StdCellConf to convert names
    accross library flavors (FlexLib_TSMC_C180, FlexLib_Sky130 and
    generic SxLib).
2022-10-17 17:18:49 +02:00
Jean-Paul Chaput d294a770c4 Added Standard Cells based SRAM generator (Python).
The generator as been build in two parts:
1. A genereric sram.BaseSRAM class to provides support for all kind of
   SRAM (grouping column tree, headers, folding).
2. The specific SRAM_256x32 (256 words of 32 bits) suited for the
   ethmac.
The sram has been simulated with genpat+asimut and gives identical
results to the Yosys one (at gate level). No timing though.
2022-10-14 10:12:03 +02:00
Jean-Paul Chaput df1ba66c09 Fix a crash in PowerRails when a terminal is not connected.
* Bug: In Katana::GlobalNetTable::getRootNet(), when tracking up the
    net through the plug (to look if it's connected to a top level
    clock), we may encounter an *unconnected* plug.
      We where not checking that case, and went crashing. Now issue
    a warning and return NULL.
      This indicates that, up until now, we didn't encounter any
    unconnected Plug in our netlists. This did show up due to a
    building error in the SRAM Standard Cell generator.
2022-10-14 10:10:43 +02:00
Jean-Paul Chaput 82cd53b107 Display the length units in KatanaEngine::printCompletion() (unambiguous). 2022-10-13 10:54:50 +02:00
Jean-Paul Chaput 757284896c Remove extra debug messages in PythonAttributes. 2022-10-13 10:54:11 +02:00
Jean-Paul Chaput 7d31d6c457 Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2022-09-22 10:35:21 +02:00
Jean-Paul Chaput 35f73ecec3 Added plugin for placing Yosys generated SRAM (failed experiment). 2022-09-21 17:48:26 +02:00
Jean-Paul Chaput 8980a01dae Added new tool "foehn" to create/manipulate DAG.
Build DAG then create an ordered list of gates from it. DAG starting
points could be Net or Instances (we take the output of the Instance).
Multiple DAG can be created, but once an Instance is part of a DAG,
it connot be part of another and is conidered as "reached" by all
subsequent DAG run. The ordered list build from a DAG contains both
Net and Instances.
   A new property has DagProperty, accessible through DagExtension
has been created to store relevant information of the DAG on each
Instance or Net (work in progress).
2022-09-21 17:46:48 +02:00
Jean-Paul Chaput 3f1148b105 Added support to map vectors of Entity into Python lists of PyEntity. 2022-09-21 17:30:30 +02:00
HoangAnhP 5b88929d23 Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2022-08-23 14:36:25 +02:00
HoangAnhP 93fbc74f8d Seabreeze : nothing new, just some typos fixed 2022-08-23 14:35:55 +02:00
Jean-Paul Chaput 16428ffaa9 Updated documentation Python/Tutorial to catch up with API improvements. 2022-08-15 13:49:35 +02:00
Jean-Paul Chaput 440547a1c5 PyAttributesHolder, again (2). 2022-08-14 18:35:21 +02:00
Jean-Paul Chaput d0d0e3aa3d Fixing the PyAttributesHolder type definition, again. 2022-08-14 18:28:34 +02:00
Jean-Paul Chaput bdd78ce44a Right preprocess condition in PythonAttribues for old GCC 2022-08-14 18:14:35 +02:00
Jean-Paul Chaput c0b4a73f9e Alternate PyTypeObject inititalization in PythonAttributes for old GCC. 2022-08-14 13:05:35 +02:00
Jean-Paul Chaput 56aa978a9b Added management of Python attributes on DBo.
* New: Isobar::PyAttributesHolder, a PyObject with only a dictionary
    to hold the attributes associated to a DBo.
* New: Isobar::PyHolderProperty, the Property that encapsulate
    PyAttributesholder.
* New: Isobar::PythonAttributes, the extension to simplify the
    management of the PyAttributesholder.
* Change: In PyEntity, now use a dedicated tp_getattro and tp_setattro
    to delegate the Python attribute access towars the PyAttributesholder.
* New: In hurricane/doc & documentation, update docs regarding Python
    attributes managment.
2022-08-13 17:46:47 +02:00
Jean-Paul Chaput fefa47b2dc Remove submodule error that was painful under emacs. 2022-08-05 15:36:10 +02:00
HoangAnhP 5667797ae6 Seabreeze : More than 1 Contact in 1 RoutingPad 2022-08-01 10:58:59 +02:00
HoangAnhP af20ef092c Seabreeze : new case to be considered 2022-07-22 19:13:14 +02:00
HoangAnhP 2d181a592f Seabreeze : Finally fixed conflict 2022-07-22 13:25:17 +02:00
HoangAnhP 1e978d5149 Revert "Seabreeze : fixing conflict"
This reverts commit 0e9556676a.
2022-07-22 13:12:57 +02:00
HoangAnhP c8a15a3129 Revert "Revert "Seabreeze : fixing conflict""
This reverts commit 1016ae54a6.
2022-07-22 13:12:55 +02:00
HoangAnhP 1016ae54a6 Revert "Seabreeze : fixing conflict"
This reverts commit 0e9556676a.
2022-07-22 13:11:04 +02:00
HoangAnhP 0e9556676a Seabreeze : fixing conflict 2022-07-22 13:04:14 +02:00
HoangAnhP d16ec20966 Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel
Conflicts:
	Seabreeze/src/Delay.cpp
2022-07-22 12:50:41 +02:00
HoangAnhP dedad34585 Complete fonctions of class Delay 2022-07-22 12:39:08 +02:00
Jean-Paul Chaput 149b4997fd Code reorganisation of Seabreeze consolidating objects. 2022-07-22 01:01:21 +02:00
Jean-Paul Chaput c647a670b1 Add full inspector support (getString/getRecord) to Seabreeze. 2022-07-21 19:24:42 +02:00
HoangAnhP bf181787cb Seabreeze : new class Delay for the result 2022-07-21 12:03:52 +02:00
HoangAnhP 555f6ea6a4 Seabreeze : new class for results 2022-07-21 11:45:18 +02:00
HoangAnhP b65821282c Seabreeze : optimise with new attribute of Node + fix wrong formula of Elmore's delay 2022-07-21 11:44:44 +02:00
HoangAnhP a6bfbdf825 Seabreeze : some changes 2022-07-20 17:49:43 +02:00
Jean-Paul Chaput 336b0ad015 First step in normalizing/rewriting Seabreeze. 2022-07-20 15:14:38 +02:00
Jean-Paul Chaput be1dd12c1a Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2022-07-14 15:20:40 +02:00
Jean-Paul Chaput 34a3ae327c Revert horizontalAdvance() to width() so it build on old Qt5 versions. 2022-07-14 15:19:24 +02:00
HoangAnhP 78401f5129 Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2022-07-13 12:30:33 +02:00
HoangAnhP 0cd9cd7ddb Seabreeze : Elmore's delay calculation checked, it should be good (?) 2022-07-13 12:30:10 +02:00
Jean-Paul Chaput db0ecb878d Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2022-07-13 11:48:48 +02:00
Jean-Paul Chaput c737d5bd0c Port to Python3 capacitors & resistors generators.
Main list of ports:

* Replace deprecated operator '<>' by '!='.
* To check if a list is empty, do not compare to [], but check it's
  length instead.
* Do not make a class inherit indirectly twice from the same base class.
* Hurricane physical object constructors uses DbU::Unit as arguments,
  seen as int in Python, so they will not match float. Unfortunately
  the calculation often gives float. So explicitely cast them into
  int. This is due to a change of behavior in Python. Now, 3/2
  gives 1.5 (float). To get the previous one use: 3/2 -> 1 (int).
* dict.keys()[0] no longer work, instead use list(dict.keys())[0].
2022-07-13 11:20:55 +02:00
Jean-Paul Chaput f453dbc6f9 Correct the selection bug in Net mode in CellWidget.
In SelectorCriterion & SelectorCriterions, when selecting a Net occurrence,
we where storing the Net only. This was fine if the Net was belonging to
the Cell's top level. But when it was an occurrence of a non-top level
net, this was creating the elusive incoherent Occurrence problem.
Now we truly store the occurrence of the Net, to be accurate, the root
of the HyperNet.

* Change: In SelectorCriterions::add(), the Net* argument is replaced
    by a Occurrence of Net. Must be an HyperNet root occurrence.
      Same goes for SelectorCriterions::remove().
* Change: In CellWidget::select(), when called with a Net occurrence,
    select the whole HyperNet components.
* Change: In NetSelectorCriterion, now use a Net occurrence instead
    of directly a Net. Must be an HyperNet root net occurrence.
2022-07-13 11:20:24 +02:00
HoangAnhP 7267951683 Seabreeze : debugged, RC calculated for each node. Testing delay_Elmore 2022-07-12 15:03:33 +02:00
HoangAnhP d1c0e4882a Seabreeze : update on calculating RC; adding explication (brief) of fonctions 2022-07-12 12:39:37 +02:00
HoangAnhP 157532af48 Seabreeze : fixed wrong formula of C. Still not using data, parameters are defined 2022-07-07 09:30:24 +02:00
HoangAnhP 871622f482 Seabreeze : phase 2, add Configuration 2022-07-06 18:20:35 +02:00
HoangAnhP d9db42447d Seabreeze : Step 1 - Building Tree is done. Going to step 2 - Compute RC 2022-06-17 12:05:57 +02:00
HoangAnhP 9b59c50efc Seabreeze : new version of function build_branch(). No more recursivity 2022-06-16 18:14:47 +02:00
HoangAnhP 2c89e5b41a Seabreeze : error while returning the contact from build_branch() 2022-06-15 12:01:32 +02:00
HoangAnhP e2c27cc039 Seabreeze : add fonction build_from_Node(Node*, Segment*) 2022-06-14 12:34:44 +02:00
HoangAnhP e9147299b0 Seabreeze : add fonction build_branch(Contact* ct) to help build a branch and pass all the 'unecessary' contacts 2022-06-13 17:14:58 +02:00
HoangAnhP d593683394 Seabreeze : problem solved, tree created with all the contacts. To improve to a better form of tree. 2022-06-13 14:53:36 +02:00
HoangAnhP 3bd38f4363 Work for Nets with 2 or less RoutingPads. Further analysis for bigger nets 2022-06-09 17:15:06 +02:00
HoangAnhP 0864db6c2f Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2022-06-09 12:04:10 +02:00
HoangAnhP 801e31f716 Seabreeze : Segmentation fault when acceding vector nodes of tree 2022-06-09 09:54:42 +02:00
Jean-Paul Chaput 9d818df5b1 Computation of the relative area used by the registers in Etesian.
* Change: In EtesianEngine::toColoquinte(), not only compute the ratio
    of DFF versus the total number of gates, but also the ratio in
    term of area. As the DFF are usually very big cells compare to
    combinatorial one, the direct gate ratio could be misleading as
    to the "weight" of those cell in the design.
2022-06-05 20:36:41 +02:00
Jean-Paul Chaput 33a5cd3b0b Nicer looking of the dots in Bora::SlicingPlotWidget (IMHO). 2022-06-05 20:36:01 +02:00
Jean-Paul Chaput bbea20b4f6 Correct, again, the problem of PyLayoutGenerator in Python 3.
* Bug: In PyLayoutGenerator, in the method definition of setVerboselevel(),
    the error was not METH_STATIC but the lack of METH_VARARGS flag.
2022-06-05 20:35:39 +02:00
HoangAnhP 77ecf5523d Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2022-06-03 17:03:24 +02:00
HoangAnhP aed63ccdf5 Seabreeze, first commit 2022-06-03 16:48:17 +02:00
Jean-Paul Chaput 33e148440c Correct a compliance problem with Python > 3.8 of METH_STATIC.
* Change: In PyLayoutGenerator, in the method definition of the class,
    replace the METH_STATIC flag by METH_CLASS for setVerboseLevel().
      There may be more of it elsewere, but as they didn't seem to
    have been triggered, we will see as it happens.
2022-05-27 18:09:12 +02:00
Jean-Paul Chaput 19504ad64f Correct misaligned contact in heavy load H-Tree.
* Bug: In cumulus/plugins.block.htree.HTree._connectLeaf(), the stacked
    contact to connect the top left buffer amplifier was not forcibly
    aligned on the vertical METAL5. In some configuaration it was
    leading to gaps at METAL5 level.
2022-05-26 23:40:30 +02:00
Jean-Paul Chaput 5b469e458f Bug in AutoSegment::getEndAxis() computation.
* Bug: In AutoSegment::getEndAxes(), as the NonAligned flag may be
    wrong, always loop over the aligneds (if any). Then, the
    target axis computation was wrong, using a min() instead of
    a max().
      This was, in turn, wrongly activating isNearMinArea() and
    causing non-minimal length segment to have their extremeties
    extented. And, in the end, Track overlap.
2022-05-26 17:51:25 +02:00
Jean-Paul Chaput 2efae3507e Remove unconnected part of the nets after HFNS.
This was the reason why we, sometimes got "UNCONNECTED" errors in the
VHDL PORT MAP statements. This was the remnants of the originally
connected driver.

* Bug: In Etesian::BufferTree, as the root driver is disconnected from
    all the sinks, but the top tree buffer, we may end up with
    unconnected signal on instances that were using it.
      So now, call BufferTree::rcleaupNet() to remove the Net in
    the Cell that where used to "transmit" the original driver.
* Bug: In Etesian::BufferTree, no longer use a _isDeepNet attribute
    guessed from the occurrences pathes of the RoutingPad, but
    trust the Net::isDeepNet() method.
2022-05-25 17:09:00 +02:00
Jean-Paul Chaput 86d539fe5d Add a breakoint after perfoming HFNS in cumulus.plugins.block. 2022-05-25 17:08:34 +02:00
Jean-Paul Chaput c17c4c3f6e Add management for very rare segment cross blocking (ripup loop).
* New: In Katana::DataNegociate, add a "sameRipup" counter to keep
    the *consecutive* number of time a segment is put in the same
    track.
* New: In TrackSegment::setAxis(), update/reset the "sameRipup"
    counter of the DataNegociate.
* New: In TrackCost, add new flag "Blacklisted" to mark Tracks that
    have been riped up too much in a consecutive row.
      TrackCost::Compare::operator() will then sort the blacklisted
    track after the non-blacklisted ones.
* New: In SegmentFsm CTOR, raise the Blacklist flag on the TrackCost
    if the "sameRipup" is above 10. This to get away from a state
    well in the ripup.
2022-05-23 17:58:17 +02:00
Jean-Paul Chaput c877d7e980 Forgot to merge the router failure status in chip.chip.doPnR(). 2022-05-21 18:49:55 +02:00
Jean-Paul Chaput a94a290c9b Be a bit more lax for out of bound requests in Track::getBeginIndex(). 2022-05-21 13:19:51 +02:00
Jean-Paul Chaput ba23a362fb Bad protection layer used in NetBuilderHV::doRp_AutoContact().
Bug: In NetBuilderHV::doRp_AutoContact(), when encountering a
  punctual RoutingPad in METAL1, create the protection in the
  METAL2 layer instead of METAL1 (current layer).
2022-05-21 13:19:28 +02:00
Jean-Paul Chaput 53db943d14 Discriminate between I/O pin and block pin in NetBuilder.
* Bug: In NetBuilder::setStartHook(), trigger the "move up" of
    global routing only when encountering RoutingPad of a macro
    block and *not* an I/O pin of the whole block (at the edge).
    Boils down to look if the RoutingPad is anchored on a Pin
    or a Segment (macro block).
2022-05-21 13:03:38 +02:00
Jean-Paul Chaput 1babec2e91 Save VHDL model only once in the rsave Cumulus plugin.
* Bug: In cumulus/plugins/rsave.py, the Cells where saveds each time
    one instance of was encountered. Resulting in multiple saves.
    It was, of course, ineficient, but it also triggers a bug
    that seems to happen after multiple save : the VHDL additional
    property was deleted *before* the full hierarchical dump was
    finished.
      Now, we save each Cell only once so it does not occur, but
    should make a deeper investigation later.
2022-05-21 13:02:58 +02:00
Jean-Paul Chaput 42bf5d29d4 General review & redesign of the "minimum area checking" for segments.
* Change: In AutoHorizontal::setDuSource() & ::setDuTarget() (& AutoVertical),
    check that the requested "du" is less than a pitch (this is not an
    upper bound). Issue a warning if not true.
* Change: In AutoSegment::revalidate(), when passing the previous span
    interval to expandToMinLength(), if we are in creation stage, make
    it empty because it has no sense yet and can lead to a lock in a
    too narrow span.
      Change the coupled behavior of expandToMinLength() vs.
    unexpandToMinLength(), the call to "unexpand" will be done on
    AutoSegments that are flagged with SegAtMinArea, instead of
    using the return value of "expand". This way we control across
    multiple revalidate() if a segment can be "unexpanded".
* Bug: In AutoSegment::expandToMinLength(), not only try to shift left
    if we are beyoond the max bound but also to the right if we are
    below the min bound.
      the span on the target and source were miscalculated, we must
    add the half-minimal distance to get the span inside the Track.
* Change: In AutoSegment::isMiddleStack(), rename into isNearMinArea()
    as we check for any *small length* set of AutoSegments and not
    only the one part of a middle stack. In some rare instances,
    two aligned segments can nevertheless be too short.
* Bug: In AutoSegment::reduceDoglegLayer(), when finding a reduced
    segment also reset it's duSource & duTarget because it will
    no longer be an isolated strip of metal.
* Change: In AutoHorizontal::updateOrient(), when there is a
    source/target swap, no need to exchange the dxSource and
    dxTarget extentions.
* Change: In AutoHorizontal::setDuSource() & ::setDuTarget(), check
    for du bigger than the pitch, which should never occur and
    display a warning.
      Same modification in AutoVertical.
* Change: In Track::repair(), now invalidate the shifted segments
    to ensure cache coherency with the TrackElement.
      Do not take AutoSegment in non-preferred direction into
    account, and especially do not try to resize them.
      Now, invalidate the corrected segments (see below).
* Change: In KatanaEngine::finalizeLayout(), move the track repair
    stage from here into NegociateWidow::run(). This way we avoid
    the false warning about segment overlap in the data-base final
    check. The false warning was because the AutoSegment where
    shifted but not invalidated/revalidated leading to a cache
    incoherency in the TrackElement. Now they *are* invalidated
    and updated.
* Bug: In Track::checkMinArea(), do not check for minimal area when
    a segment is overlapping a same net neighbor. To avoid false
    minimum area violation warnings.
2022-05-18 14:54:14 +02:00
Jean-Paul Chaput ab13a02eed Do not make dogleg on segments in non-preferred routing direction.
* Bug: In AutoContactTurn::updateTopology(), in some case we were making
    doglegs on segments in non-preferred routing direction (mostly M2).
    This must be never be done. As, by construction, at least one segment
    of the turn must be in the preferred routing direction, always use
    this one to make the dogleg.
      This bug is likely to explain the remaining "bad spin" in the
    final self-check of the routing data-structure.
2022-05-12 17:54:05 +02:00
Jean-Paul Chaput d3b7251eac NetRoutingExtension::get() failsafe when net is NULL. 2022-05-12 17:53:21 +02:00
Jean-Paul Chaput 5ff81b59ec Separate count from the list of indexes in configuration.IoPin. 2022-05-12 17:52:55 +02:00
Jean-Paul Chaput 59c0ab067b Mangle the "'" in Verilog to VHDL translator. 2022-05-12 17:52:22 +02:00
Jean-Paul Chaput 0a64f3b83d Create and connect dummy signals for unconnected *outputs* in BLIF parser. 2022-05-12 17:51:56 +02:00
Jean-Paul Chaput 921c519bd3 More detailed error message in case of VHDL PORT MAP discrepency. 2022-05-12 17:51:30 +02:00
Jean-Paul Chaput cd60032d9c Added direct management of macro blocks I/O pins in METAL2 & METAL3.
The decoupling of the cell gauge and the routing gauge implies that
the METAL2 & METAL3 terminals of macro blocks cannot be aligned on
the routing tracks anymore. That is, an horizontal METAL2 terminal
will not be on a track axis, but offgrid, so we no longer can use
a METAL2 horizontal segment to connect to it. Making an adjustement
between the offgrid terminal and the on-grid segment has proven
too complex and generating difficult configuration for the router.
Moreover, METLA2 terminal could be fully inside a METAL2 blockage.
So now, when the gauges are decoupled, we connect the METAL2 and
METAL3 the same way we do for METAL1: *from above* in the perpandicular
direction and using a *sliding* VIA. We assume that those kind of
terminals in upper metals are quite long.

* New: In Hurricane::Rectilinear, export the isNonRectangle() method
    to the Python interface.
* New: In CRL::RoutingGauge, add function isSuperPitched() with the
    associated boolean attribute. Set to true when each pitch of
    each layer is independant (not low fractional multiples).
* New: In AnabaticEngine, add the ability to temporarily disable the
    canonize() operation (mainly used in dogleg creation).
* New: In AutoSegment::canonize(), do nothing if the operation is
    disabled by AnabaticEngine.
* Bug: In Session::_revalidateTopology(), disable the canonization
    during the topology updating of a net. Too early canonization
    was occuring in makeDogleg() leading to incoherencies when
    performing the later canonization stage over the complete net.
    Mostly occured in the initial build stage of the net.
* New: In GCell, add function postGlobalAnnotate(), if a layer
    is fully blocked (above 0.9), typically, under a blockage,
    add a further capacity decrease of 2 on the edges. So we may
    handle a modicum of doglegs.
* Bug; In GCell::addBlockage(), removeContact(), removeHSegment()
    and removeVSegment(), forgot to set the Invalidated flag.
    This may have lead to innacurate densities.
* Change: In GCell::updateDensity(), more complex setting of the
    GoStraight flag. This flag is now set if we don't have two
    *contiguous* below 60% of density. We need free contiguous
    layers to make doglegs.
* New: In NetBuilder, now manage a current state flag along
    with the state flag of the *source* GCell. This flag is used
    to tell if the GCell needs it's *global* routing to be done
    using the upper layers (METAL4 & METAL5) instead of the
    lower ones.
* New: In NetBuilder::setStartHook(), set the state flag of the
    GCell to ToUpperRouting when processing a global routing
    articulation and one of the base layer is obstructed
    above 0.9.
      In GCell with terminals, also set ToUpperRouting when there
    are some in METAL2 / METAL3 and the gauge is not super-pitched.
* New: In NetBuilder, function isInsideBlockage(), to check if a
    terminal is completely or partially enclosed in a blockage.
* Change: In NetBuilderHV::doRp_AutoContact(), remove support for
    trying to put on grid misaligned METAL2/METAL3.
      Instead systematically access them from above.
      Do not cover with fixed protection terminals that are already
    enclosed in blockages.
* Bug: In NetBuilderHV::doRp_AutoContact(), always add the terminal
    contact in the requested GCell and not the target/source one,
    in case the terminal span several GCells.
* Change: In NetBuilderHV::doRp_Access(), create the local wiring
    according to the RoutingPad layer.
* Change: In NetBuilderHV::_do_xG(), _do_2G(),
    create the global wiring in upper layers, according to the
    ToUpperRouting flag.
* Change: In NetBuilderHV::_do_xG_xM3(), now delegate to
    _do_xG_xM3_baseRouting() and _do_xG_xM3_upperRouting() if the
    density at terminal level is above 0.5.
* New: NetBuilderHV::_do_xG_xM3_baseRouting() and
    _do_xG_xM3_upperRouting() separated function to manage the
    local routing.
* Change: In NetBuilder::_do_globalSegment(), if the currently
    processed GCell or it's source is in ToUpperRouting mode,
    move up the global segment. Do *not* use the moveUp() function
    which would create doglegs unwanted at this stage.
* New: In KatanaEngine::annotateGlobalGraph(), call postGlobalAnnotate()
    on the GCell after the blockages have been taken into accound to
    add the penalty.
* Bug: In Track::getPrevious(), correctly manage the 0 value for the
    index argument. Strange it didn't show earlier.
      Same goes for Track::expandFreeInterval().
2022-04-27 21:56:41 +02:00
Jean-Paul Chaput 908231c4c4 Missing BigVia import and some typos. 2022-04-03 13:19:49 +02:00
Jean-Paul Chaput 4ffd91822f Added support for SPICE terminal ordering from .spi files.
After a Cell has been created in memory (by parsers or Python scripts)
we can annotate it with the Spice parser so it will know the right
order with which to create the subcircuit call ('x').

* New: In CRL::Spice::load(), add support to read the ".subckt" card
    and guess the right ordering for generating the 'x' (subcircuit
    card call).
* Bug: In Spice::SpiceBit & Spice::BitExtension, when a Net bit property
    is removed, if it's the currently cached property in BitExtension
    it may lead to a crash. So when a property is destroyed, we must
    also clear the cache (see remove(), clearCache() & onReleasedby()).
      I'm wary that this could also happen on other kind of cached
    extensions...
* New: In CRL::NamingScheme, new method vhdlToVlog() to translate back
    VHDL net name into Verilog. Currently only changes "()" into "[]".
    Used to generate the commented SPICE interface for Alliance compliance.
* Change: In Spice::Entity, previously all the ordering where removed
    between each run of the SPICE parser, but the orders read from
    SPICE file (mostly standard cells) must be kept. So add a flag
    ReferenceCell to prevent the removal by ::destroyAll().
2022-04-03 13:18:42 +02:00
Jean-Paul Chaput fd624f03b6 Forgot emiting "layoutAbouttobechanged" in NetlistModel::setCell().
* Bug: In NetlistModel::setCell() template, forgot to send the
    "layoutAboutToBeChanged" signal before disconnecting the
    netlist datas. This seemed to go unnoticed until ported
    under Qt5. Was generating strange random core dump when
    running the engines with a net kept selected. Disgraceful
    crash during demos...
2022-01-26 19:41:39 +01:00
Jean-Paul Chaput 7f936367f8 Fix deletion bug in Selector::_preDestroy().
* Bug: In Selector::_preDestroy(), *do not* iterate over the _cellWidgets
    map as we destroy it's elements! We end up in destroyed ones...
    Instead destroy the first one until the map is empty.
2022-01-26 19:34:31 +01:00
Jean-Paul Chaput a5d92ecc29 Beautification, display "boundaries" below everything else.
* Change: In CellWidget::_redraw(), the boundaries, that is, instances
    abutment boxes where drawn *after* everything else, so they where
    hiding more interesting informations (especially at low zoom level)
    like routing wires.
      Now draw them *first* so they are *below*.
2022-01-26 19:31:01 +01:00
Jean-Paul Chaput 6210d312fe Correct the image snaphot generation (CellImage).
* Change: In CellImage::setScreenCellWidget, fully copy the display
    settings from the reference widget (not just part of them).
* Bug: In CellImage::toImage(), if the abutment box of the displayed
    cell is not *fully* includer in the viewer area, do *not* try to
    reframe it. The reframe() method seems to be buggy, works OK
    just without calling it.
2022-01-26 19:25:50 +01:00
Jean-Paul Chaput 08b951047c Update to support BFD 2.35.2 to generate file/line in stack traces. 2022-01-26 19:19:01 +01:00
Jean-Paul Chaput b54380e05d Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2022-01-15 17:28:44 +01:00
Jean-Paul Chaput b6192e78c1 Minor documentation patchs to work with RHEL9. 2022-01-15 17:28:21 +01:00
Jean-Paul Chaput 1d839711ad Merge branch 'lefdef-out' into 'devel'
Bind DEF/LEF export to Python and make it useful for real processes

See merge request vlsi-eda/coriolis!14
2022-01-14 13:42:39 +00:00
Jean-Paul Chaput c805f4d6e4 Fix stupid mistake of "trace" import in core2chip.cmos.py. 2022-01-13 11:16:07 +01:00
Jean-Paul Chaput 22dd3ddc73 Remove bison generated yy.tab.h. Included by mistake. 2022-01-12 16:31:46 +01:00
Jean-Paul Chaput c41bd36279 Small code presentation improvements. 2022-01-12 16:27:47 +01:00
Jean-Paul Chaput 762e25adde More Python 3 corrections.
* Change: In unicorn/python/unicornInit.py, when iterating over all the
    loaded modules, now we have "namespace" that have a __file__
    attribute which is set to None. Skip them.
* Change: In stratus1/st_net.py, "is" must be replaced by "==" when
    doing string comparison.
* Change: In stratus1/st_parser.py, open file in "rb" mode instead
    of "r" (so we get a bytestream as now required by Python).
2022-01-12 16:25:01 +01:00
gatecat 6c66208e0c def: Write route segments
Signed-off-by: gatecat <gatecat@ds0.me>
2022-01-12 14:14:15 +00:00
gatecat 9635cc3311 lef: Fix MANUFACTURINGGRID order
Signed-off-by: gatecat <gatecat@ds0.me>
2022-01-12 13:42:03 +00:00
gatecat c4ef465c41 def: Fix order of instance transforms
Signed-off-by: gatecat <gatecat@ds0.me>
2022-01-10 19:45:24 +00:00
gatecat 4250c5bec7 def: Fix export of pins
Signed-off-by: gatecat <gatecat@ds0.me>
2022-01-10 18:47:13 +00:00
gatecat a8dd84838b def: Fix export units for non-lambda processes
Signed-off-by: gatecat <gatecat@ds0.me>
2022-01-10 16:54:04 +00:00
gatecat ddb684bfe1 defexport: Make it useful for real processes
Signed-off-by: gatecat <gatecat@ds0.me>
2022-01-10 16:54:04 +00:00
gatecat 4884a5d6dc crlcore: Add Python bindings for DEF export
Signed-off-by: gatecat <gatecat@ds0.me>
2022-01-10 16:54:04 +00:00
gatecat 2f1caca812 lefexport: Make it useful for real processes
Signed-off-by: gatecat <gatecat@ds0.me>
2022-01-10 16:54:04 +00:00
gatecat e1c5366fef crlcore: Add Python bindings for LEF export
Signed-off-by: gatecat <gatecat@ds0.me>
2022-01-10 16:54:04 +00:00
Jean-Paul Chaput 0d7deafe81 Remove mistakenly commited backup file. 2022-01-01 17:15:41 +01:00
Jean-Paul Chaput 581f557aef Fix: The SelectionPopup widget was deleted after first use.
* Bug: In Viewer::SelectionPopup(), the window attribute
   Qt::WA_DeleteOnClose was *not* cleared. So the window was deleted
   after first use while it was though staying allocated.
     Again, generating weird crashes.
     Took the occasion to slightly redesign the behavior to select
   and highlight individual components.
2022-01-01 16:47:09 +01:00
Jean-Paul Chaput 0c54d109cc Fix: Do not return transient string in PyTypeManager.
* Bug: In Isobar3::PyTypeManager, the accessors _getCppTypeName() and
    _getPyTypeName() where returning string *by value*, hence, short
    lived copies.
      But, in _setupPyType() and _addToModule(), as we interface with
    the Python/C API, we extract the c_str(). Which where removed as
    we used temporary objects. Leading to memory corruption and weird
    crashes.
      Now returns "const string&" so the c_str() stays allocated.
2022-01-01 16:46:41 +01:00
Jean-Paul Chaput 9aaaf33e6e Manage more interrupt signals in CRL::System::_trapSig(). Display value. 2022-01-01 16:46:15 +01:00
Jean-Paul Chaput 550b087f05 Takes even further appart the HTree buffer input/output. 2021-12-31 16:48:45 +01:00
Jean-Paul Chaput 084eee3b39 Added support for RHEL9. 2021-12-31 16:35:38 +01:00
Jean-Paul Chaput 5f8a0a944c Display bug for non-rectangular components in DrawinQuery::drawGo().
* Bug: In CellWidget::DrawingQuery::drawGo(), the display condition was
    wrong, it was requiring *both* width & height to be above the display
    threshold. Either one is sufficient to activate the display.
      Was causing the selective diseapearance of gates at low zoom level
    and printed version.
* Change: In CellPrinter, force the display threshold to one pixel in it's
    internal CellWidget used for printing.
2021-12-25 15:23:49 +01:00
Jean-Paul Chaput fdce75fdad Fix bad computation of perpandicular free space in DataNegociate, again.
* Bug: In Katana::DataNegociate::update(), when computing the length of
    source & target extension on a perpandicular segment, must use the
    extensions of the *directly* connected AutoSegment (the baseSegment)
    and not the canonical one that may be different, so with unrelated
    extensions.
2021-12-25 15:23:23 +01:00
Jean-Paul Chaput 104c043416 In the H-Tree, shift vertical H wire one pitch to the left.
* Bug: In cumulus/plugins.block.HTree._rrouteHTree(), the RoutingPads
    for the input and output of the buffer where sometimes put too
    close from each others, giving the pitch of the vertical tracks.
    Now shift one pitch left the vertical branchs of the H-Tree.
* Bug: In cumulus/plugins.block.HTree._rrouteHTree(), also shift down
    one pitch the horizontal branch, due to track rounding they *may*
    end up on the same track, generating a short.
2021-12-25 15:22:58 +01:00
Jean-Paul Chaput 64056d25ee Layer assignment step was ignoring the number of RoutingPad threshold.
* Bug: In Anabatic::layerAssign(), during the step of desaturation of
    GCells that contains too much terminals (i.e. lot of *local*
    congestion), the desaturation threshold was har-coded to 8.
    Wich is fine for symbolic cmos but way too low for Flexlib.
      End result was that most straight wires where moved towards
    the upper layers, creating congestion (imbalance of layer
    densities).
      Now the parameter:
        * "anabatic.saturateRp" (default value:8) is correctly taken
	  into account.
2021-12-22 15:52:22 +01:00
Jean-Paul Chaput a4ad671739 Fix too naive obstacle detection on non-prefered metal2 wires.
* Fix: In Manipulator::avoidBlockage(), the dedicated function to check if
    there is an obstacle in the way of a non-prefered routing wire (done
    for metal2 connecting to terminals only) was too naive.
      We were checking the tracks for obstacles crossing exactly the axis
    of the segment. And for near-miss this is not enough. Now check on
    the whole x-span to be used by the segment.
      Code borrowed and simplified from Track::addOverlapcost().
* Change: In Manipulator::moveUp(), the default value for the extra
    reservation allowing a long wire to move up need to be customized
    for Flexlib/StdCellLib (allow successful routing of ChipFlow/MPW4).
      Add two new configuration parameters to katana:
        * "katana.longWireUpThresold1" : the length, expressed in number
	  of *slice height* above which a global wire is considered a
	  *long* wire (not close interconnect).
        * "katana.longWireUpReserve1" : the extra number of free tracks
	  that must remains free in the up layer after the move up,
	  in each GCell traversed by the wire. Expressed in number of
	  tracks, but can be non-integer (float, for instance: 1.5).
2021-12-21 16:13:31 +01:00
Jean-Paul Chaput 92e5f3fa4d Update ad-hoc patch for obstacles for Flexlib & StdCellLib.
* Bug: In Katana::PowerRailsPlane::Rail::doLayout(), to avaid tracks too
    close to an offgrid obstacle in the preferred routing direction, we
    expand the width/height of the segment by one pitch. BUT it seems to
    still be too close for Flexlib and StdCellLib, so there is an ad-hoc
    patch based on the *name* of the cell library. Update it to take
    "StdCellLib" into account.
2021-12-21 16:13:07 +01:00
Jean-Paul Chaput 3fa8d516bc Fix bad computation of perpandicular free space in DataNegociate.
NOTE: This is likely to explain why we still got overlap in the
      track coherency check in very rare occasions.

* Bug: In Katana::DataNegociate::update(), when computing the allowed
    free interval for the segment axis deduced from the perpandicularly
    connex segments, we account for the extension of the connecting
    VIA. Those extension varies according to the kind of VIA and are
    given by getExtensionCap().
      We were accounting for the source & target extension VIA on the
    parallel segments, assuming that source/target would not swap when
    the perpandicular is moved. Which is *not* true.
      Now account for the extension of the *connecting* VIA on all ends.
* Change: In AutoSegment::getTopologicalInfos(), enrich the list of
    perpandicularly connected segment with wether they are connex by
    their *source* or *target* contact. Mainly to be used by
    DataNegociate::update().
2021-12-18 17:45:17 +01:00
Jean-Paul Chaput ae1f08f039 Change SkyWater130 Caravel harness connecting strategy.
* Change: In cumulus/plugins/core2chip, instead of the user providing
    an explicit mapping towards the harness I/O pins, we expect that
    the core block must have I/O pins with names matching thoses of
    the harness. That way, connections are automatically made.
* Change: In cumulus/plugins/block/htree, if the root signal of the
    H-Tree is a bit from a vector (like "io_in(0)"), then remove the
    vector index notation on all the stem name of all the sub-nets.
    Done by the unbitify() function: "io_in(0)" => "io_in_bit0".
2021-12-17 15:58:57 +01:00
Jean-Paul Chaput 76d468f6d5 Change in feed & tie managements to fill the empty row spaces.
* Change: In EtesianEngine::_postCreate(), issue a warning if the list of
    feeds is empy (configuration: "cfg.etesian.feedNames").
* New: Add a FeedCeels::getFeedByWidth() method to get feeds by their
    width in DbU::Unit and not only pitches.
* Change: In Placement::Slice::fillHole(), invert the tie filling and
    feeds filling stage. Now we first try to fill the row hole with
    feeds, using the widest first, and if they are not configured or
    too wide, use the tie.
      As the tie *should* also be integrated in the feed list, we may
    suppress altogether the fallback tie filling step. Keep it for now.
* Change: In Placement::slice::createDiodeUnder(), the inserted diode
    *may* be smaller than the feed it replace. So, in this case, add
    a complementary feed to fill the gap.
    NOTE 1: Out of lazyness, we add only *one* complementary filler
            cell. So there *must* be one of a width wich correspond
	    exactly to the difference between the original feed and
	    the diode. Otherwise, gap will remains.
    NOTE 2: With wider feed cells, they may cross the GCell border.
            But we must insert the diode under the GCell, otherwise
	    the global routing will be defective. So, for now, reject
	    feeds that cross the boundary. Must be done more smartly
	    by inserting the diode over the left or right side of
	    the feed.
2021-12-17 15:58:13 +01:00
Jean-Paul Chaput 4ab6888b94 Fix Pin managment on north & east side of the cell abutment box.
* Change: In AnabaticEngine::setupPrerouteds(), take into account the
    number of Pins. Now consider a net containing multiple Pins and, at most,
    one segment as *non-routed".
      This case may specifically happens for nets with pins on the north
    and east side, which are slightly *inside* the abutment box (to be
    seen by the router) and draw with them their *outside* direct
    connection wire.
* Bug: In cumulus/plugins.chip.CoreWire, no longer put the north or
    east side external Pin *exacyly* on the abutment box but *one pitch*
    inside so they are correctly seens by the P&R (must be *inside*
    the area of a GCell).
2021-12-17 15:56:15 +01:00
Jean-Paul Chaput 67ca0997c3 Merge branch 'fix-blif-zero-one' into 'devel'
blif: Improve detection of zero/one net by requiring it to be external

See merge request vlsi-eda/coriolis!12
2021-12-11 21:07:18 +00:00
Jean-Paul Chaput 73296503ad Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2021-12-11 22:00:10 +01:00
Jean-Paul Chaput fe32916d14 Add support for the SkyWater130 Caravel harness to "core2chip".
It is now possible to automatically nest a core block inside a harness
frame, like we do for an ordinary chip whith I/O pads. The DEF harness
file "user_project_wrapper.def" must be made available though the block
configuration variable:
   conf.cfg.harness.path = './user_project_wrapper.def'
A first small example is given in:
   alliance-check-toolkit/benchs/counter/sky130_c4m
The harness layout is stripped from it's native power grid (but keep
the power ring). I/O pad information in block/configuration is
slightly "bent* to manage pins instead of complete I/O pads.

* Bug: In cumulus/plugins.block.Block.setupAb(), the routingBb was not
    set up when working in chip mode. Now set (to the corona AB).
* Change: In cumulus/plugins.chip.__init__, move there the CoreWire
    class (from chip/pads.py) so it can be shared with the harness
    version of pads.py.
* Change: In cumulus/plugins.chip.powerplane, compute the intersection
    between the vertical supply stripes and the deep horizontal power
    lines in a smarter fashion, so two (or more) vertically contiguous
    BigVias are merged into one (two BigVia side by side where causing
    mimimal spacing distance violation on the cut in Sky130).
2021-12-11 19:52:31 +01:00
Jean-Paul Chaput 2ca9e162ef Allow the detailed routing to be build from non-bottom P&R layers.
* New: In Anabatic::AutoSegment::create(), allow the created segment to
    be in any supported routing layer, and not only the bottom H & V.
    Modifications impact the *two* overload of the function.
* Change: In Anabatic::NetBuilderHV::doRp_AutoContacts(), for punctual
    METAL1, the protection has to be in METAL2. Bump the layer depth
    to correctly use the updated verstion of AutoSegment::create().
* Change: In AnabaticEngine::checkPlacement(), for the Pin, check that
    it's layer is in the routing gauge before anything else.
* New: In Katana::NegociateWindow::createTrackSegment(), if the track
    nearest the segment axis (refTrack) do not exists, call a
    breakpoint just before crashing.
2021-12-11 19:51:24 +01:00
Jean-Paul Chaput ba2a74e35d Tweaked DEF support to load the Caravel harness.
* Bug: In CRL::BlifParser::Model CTOR, forgot to set the direction
    on auto-generated power supply global nets. So they were put
    in "linkage" in the VST files.
* New: In CRL::DefImport, add specific support for the Sky130/Caravel
    harness "user_project_wrapper".Mainly:
    - Do not fuse together "io_in" and "io_out" as a single net as
      they should (according to the DEF). So we can connect separately
      on each of them. We only allow one port for each net, as in VHDL.
2021-12-11 19:48:57 +01:00
Jean-Paul Chaput 2f0bf5456d Added Etesian to the measurment system.
* Bug: In CRL::MeasureSet::toStringHeaders(), check and issue a warning
    if a measure label ends with a "." (dot).
* Change: In CRL::ToolEngine::getMeasure(), return the data measure
    by pointer instead of by reference (easier to manipulate afterwards).
* New: In EtesianEngine::place(), add the placement runtime (under label
    "placeT") to the measure set.
* New: In KatanaEngine::dumpMeasures(), add the Etesian runtime to the
    set of measures.
2021-12-11 19:47:24 +01:00
Jean-Paul Chaput be598c9b96 Update the Python wrapping of Hurricane::Entity.
* New: In Hurricane::PyEntity, export the getBoundingBox() method.
2021-12-11 19:44:20 +01:00
gatecat 3f08b3789f blif: Improve detection of zero/one net by requiring it to be external
Signed-off-by: gatecat <gatecat@ds0.me>
2021-12-10 19:17:03 +00:00
Jean-Paul Chaput f14ef8adc2 Updated PDFs, December 10, 2021 (15:07). 2021-12-10 15:07:58 +01:00
Gabriel Gouvine b4a7d1a6fd Add SUPPORT.rst file 2021-12-09 22:32:02 +01:00
Gabriel Gouvine 4e23dff0dc Update URL in the README 2021-12-09 22:31:58 +01:00
Jean-Paul Chaput f954f69574 Suppress error message when NDA plugins directory does not exists. 2021-11-28 19:40:59 +01:00
Jean-Paul Chaput b1b67d18e6 Add support of vertical power rails made of powmid cells in Block.
* New: In cumulus/plugins.block.congiguration: New PowersConf config
    sub-object to store characteristics of the "powmid_x0" cell.
    The name of the Cell with which to build the vertical power
    rails is given though the cfg parameter:
      "cfg.etesian.cell.power"
* New: In cumulus/plugins.block.spares, add support for creating
    vertical power lines along with the buffers pools of the H-Trees.
    At most, one vertical power rail will be put exactly at the right
    edge of the buffer pool of each leaf QuadTree. We can reduce that
    number, using the parameter:
      "cfg.block.vRailsPeriod = N"
      Which give the ratio to use (one over N QuadTree leaf).
   WARNING: This may not work if the QuadTree is "dented" not in a
            corner but in the *middle* of the side. Needs to be
	    improved and/or checked.
2021-11-28 19:12:59 +01:00
Jean-Paul Chaput df972b7250 Add Diode/Feed flags in Cell. Correct computation of Instance count.
WARNING: We are partially duplicating the informations pertaining
         to the Alliance catalog (stored in the Catalog property)
	 directly into the Cell. This is needed for Flexlib which
	 is not using the Alliance loading mechanim. Ideally the
	 Catalog information should be moved into the Cell.

* New: In Cell, add new state flags Diode, PowerFeed (in addition to
    Pad & Feed).
      Export flags setter/getter to Python. For Flexlib usage.
* Change: In AllianceFramework::getInstancesCount(), correctly skip
    Diode & Feeds based on Cell flags. Those flags must correctly
    be set in the various Flexlib_fix.py scripts.
2021-11-28 19:03:02 +01:00
Jean-Paul Chaput 01224e6a06 Forgot to disable debug in Track::repair() ... 2021-11-26 23:33:05 +01:00
Jean-Paul Chaput d8218d0698 Fix bad computation of gap in Tracks in some special cases.
* Bug: In Track::repair(), when closing a same net gap, the amount the
    "right" segment duSource must be shifted left was incorrectly
    computed in some instances.
      The previous calculation was assuming that the right edge of the
    gap was at the exact same position than the source extension.
    But when there is a non-preferred direction connected to it, this
    is wrong. Now compute the delta accounting for a difference
    between the right edge of the gap and the source extension.
2021-11-26 18:59:46 +01:00
Jean-Paul Chaput 6a3c9d1d54 Set the a default pixel threshold in CRL/etc/commons.display.
NOTE: Due to Python pathes, the NDA.common is *not* seen, even by NDA
      protected configuration. They are using the non-NDA one. No harm
      in that, just need to be known...
2021-11-26 11:32:33 +01:00
Jean-Paul Chaput 7c0f1fcf58 Fairly compute the flat numbers of instances in a design.
* New: In AllianceFramework::getInstancesCount(), add a flag TerminalNetlist
    to stop recursion on "terminal for netlist" instance level. This is to
    avoid counting physical only or non-routed instances inside hard macros,
    like SRAM blocks. This was leading to an overstimation of the "size"
    in number of gates of the routing problem.
* Change: In KatanaEngine CTOR, call for the terminal for netlist number of
    gates...
2021-11-26 11:29:23 +01:00
Jean-Paul Chaput 966a25181f Optimize Cell::getDeeNet() to fix the slow-down in PowerRails.
* New: In DeepNet, add an DeepNet::Uplink property on the HyperNet
    root net Occurrence so we have a direct two-way link between
    the top (flattened net) and the root of the HyperNet.
      Down link is ensured by the Occurrence, up link by the Uplink
    property.
* Change: In Cell::getDeepNet(), now use the DeepNet Uplink property
    instead of looping over *all* top nets. This was the cause of the
    terrific slow down in PowerRails, especially on flatteneds designs.
2021-11-25 10:49:45 +01:00
Jean-Paul Chaput ca499e024c Restore the measurements taking in Anabatic/Katana.
* New: In AnabaticEngine::printMeasures(), re-enable runtime & memory
    footprint in measurements.
* Bug: In Anabatic::AutoSegment CTOR, correct computation of the initial
    number of global segments. We were relying on the "global" flag,
    which is *not* set at this stage. Now compare source and target
    GCells.
* New: In KatanaEngine::runGlobalRouter(), store H-ovE & V-ovE in
    measurements.
* New: In KatanaEngine CTOR, add the number of gates (flattened) to
    the measurments.
* New: In KatanaEngine::runNegociate(), add the number of GCells to
    the measurements.
* Change: In KatanaEngine::printCompletion(), compute the wirelengths
    in either lambdas (symbolic) or *nanometers* (real).
* New: In cumulus/plugins.block.Block, add a setting to request the
    Katana measurements dumping: "cfg.katana.dumpMeasures"
2021-11-24 15:52:56 +01:00
Jean-Paul Chaput 10bd5510da Fix library linking problem for gcc 9 and above (Ubuntu 20/Debian 11).
* Bug: In all CMakeLists.txt, it seems I was doing a worng use of
    target_link_library(). No longer add dependencies to the C++ base
    library but instead either to the Python associated module or
    to the final binaries. This was inderectly causing the linking
    problem related to Python (which was a misdirection).
* Bug: Typo in FindLibexecinfo.cmake, do not use FindLib[E]xecinfo.
* Change: In CRL/ccore/CMakeLists.txt, activate SKIP_AUTOMOC on
    bison/flex generated files.
* Bug: In viewer/PyHApplication, do not delete the C++ object in
    the Python destroy method.
2021-11-22 00:05:48 +01:00
Jean-Paul Chaput 302accfbb1 Update documentation (by mistake, nothing new). 2021-11-21 23:40:40 +01:00
Jean-Paul Chaput c67e326205 Updated PDFs, November 21, 2021 (22:10). 2021-11-21 22:10:34 +01:00
Jean-Paul Chaput 3b971ddf3e Updated PDFs, November 21, 2021 (19:41). 2021-11-21 19:41:13 +01:00
Jean-Paul Chaput 972ed1be20 In Stratus.st_model, make Model derive from object. 2021-11-21 19:37:32 +01:00
Jean-Paul Chaput 5bf80a95d0 In Katana::Configuration::print(), display the _{h,v}TrackReservedMin. 2021-11-21 19:37:06 +01:00
Jean-Paul Chaput 66e7fd648d In ccb.py, update the organization name to "Sorbonne Université". 2021-11-21 19:36:35 +01:00
Jean-Paul Chaput c595a8e73e No longer straight route the root of a H-Tree.
* Change: In cumulus/plugins.block.HTree._rrouteHTree(), make the
    non-routing of the root net the default policy. Straight routing
    can still be activated with the use of Spares.ROUTE_ROOT_NET.
2021-11-16 17:11:00 +01:00
Jean-Paul Chaput 0f636912e0 Support more configuration 1G_xM1_1PinM2.
* Change: In Anabatic::NetBuilder::construct(), add support for up to 5 M1
    terminals in calling _do_1G_xM1_1PinM2(). When inserting diodes on
    long wires, when there is not enough space underneath, they may end
    up gouped at an end.
2021-11-16 00:28:43 +01:00
Jean-Paul Chaput d72ccca88e Fix wrongly exported internal pin to the north side in H-Tree.
* Bug: In cumulus/plugins.block.HTree._rrouteHTree(), on the top level
    H-Tree, draw a wire to the north side of the abutment box *only*
    if the root (usually clock) signal is *external*. It may be that
    it is *internal*, so must be routed as a normal one to the root of
    the tree.
2021-11-14 23:20:33 +01:00
Jean-Paul Chaput 68ae46ef20 Shift the wire connecting to the root of the H-Tree to avoid shorts. 2021-11-13 22:13:16 +01:00
Jean-Paul Chaput fcf6ec97c3 More fixes for the selection & inspector mechanisms.
* Bug: In Common.h, makes the INSPECTOR_PV_SUPPORT to generate a getRecord()
    by *value* instead of *by reference*. Seems the overload resolution
    system has changed and discriminate between them using now the exact
    match.
      This was causing InspectorWidget::setRootoccurrence() to fail, the
    getRecord(Occurrence) not corectly resolved always returning NULL.
* Change: In Occurrence, now use INSPECTOR_PV_SUPPORT (instead of PR).
* Change: In SelectionPopup, added a _cellWidget attribute to be able
    to call setShowSelection() in ::mouseReleaseEvent(), same as for
    SelectCommand.
* Bug: In SelectionWidget::changeSelectionMode(), reset the _updateState
    to ExternalEmit in *all cases* at the end of the function call.
    Failing to do that was another cause for the selection check box
    to desinchronize.
2021-11-09 10:53:56 +01:00
Jean-Paul Chaput f5bfeb3eae Fix auto-scaling of the grid over the displayed area.
* Bug: In CellWidget::drawGrid(), the scaling of grid was never recomputed
    according to the zoom level. So in low zoom, it was too fine and
    hidding everything underneath...
      Now always display between 1 and 10 lines. Lines are put on the
    grid step.
      Makes the grid draw in dotted lines, seems to looks nicer.
2021-11-06 13:41:15 +01:00
Jean-Paul Chaput 95dd4ab8ff Add minimal DEF support to parse the Caravel harness for Sky130.
* New: In CRL::DefImport, the previous version of the parser was designed
    only to read pure netlists, no physical components. Now add features
    for:
    * VIA generate statements. Generated VIAs are created as Cell and
      then instaciated wherever they are needed. Alternative would be
      to duplicate it's contents so the original netlist is not changed.
      But would create lot more objects.
    * PIN, added support for basic physical shapes.
    * SPECIALNETS and their associated wiring (path callback).
    Note: (to myself) As the Path is created *before* the NET or SPECIALNET
          callback is called, we must create a temporary net to store
          the path components. This is the "__prebuild__" net which
          will be merged later with the actual net.
2021-11-06 11:51:39 +01:00
Jean-Paul Chaput 92484ccbb2 Fix bug in the Cadence/DEF parser, occuring on the PathCbk.
* Bug: In def/def_keywords.cpp, in defrData::pathIsDone(), the attribute
    defrData.PathObj was *forcibly* deleted directly inside the defrData
    class (with defrData remaining allocated). Either there is something
    I enterily miss or this is a big blunder.
      This was causing DefImport parser to crash, when activating the
    Path callback.
2021-11-06 11:40:48 +01:00
Jean-Paul Chaput 846ac49ab8 Finally solve the selection desynchronisation problem.
* Bug: In CellViewer::setShowSelection(bool), this slot is connected
    to the hidden 's' menu key. It was toggling state according to
    the state of the *menu key* (Qt) which was *not* kept in synch
    with the state of the CellWidget. So it was causing desinchronized
    selection visibility toggle. Now, ignore the state of the menu
    and toggle the CellWidget state directly.
* Bug: In Selector::attachTo(), when adding the new CellWidget to the
    map<>, the initial flag must be Selector::Selected instead of 0,
    so we see it.
* Change: In CellWidget & ControllerWidget, adjust the default size of
    the widgets (to better suit my display...).
2021-11-03 14:27:21 +01:00
Jean-Paul Chaput 247ddb3a5c Suppress wrong error message in Katana::Session::_addMoveEvent().
* Bug: In Katana::Session::_addMoveEvent(), an error message is issued if
   the segment is not *already* in a Track. But, it is not the case for
   non-preferred Segment or reduced segment and it is valid. So suppress
   the message in those cases.
2021-11-03 14:26:53 +01:00
Jean-Paul Chaput dcc26f23c7 Fix offset track and extension problem in the H-Tree.
* Bug: In cumulus/plugins.block.htree._connectLeaf(), when HEAVY_LEAF_LOAD
    was used, the additionnal horizontal segment added to connect the
    extra buffer may have been:
    1. Misaligned, causing the blockage to be wrongly taken into account
       and leading to potential short circuits.
    2. In some RoutingGauge configurations, the extra length added to
       the segment left extention was too short, leading to DRC violations.
    So created new GaugeConf methods to manage thoses problems:
    * GaugeConf.getStackX() & GaugeConf.getStackY() to get back the
      contact coordinates of the *deep* part (typically the METAL2).
      So be able to align on them.
    * GaugeConf.createHorizontal(), added a parameter to explicitely
      state the additional length of the *left* extension. This is lazy,
      will soon add both.
2021-11-02 10:30:33 +01:00
Jean-Paul Chaput 53f019d165 Merge branch 'const-fix' into 'devel'
Fix 'static assertion failed: comparison object must be invocable as const'

See merge request vlsi-eda/coriolis!9
2021-10-31 11:20:20 +00:00
Myrtle Shah 5b5922096a Fix 'static assertion failed: comparison object must be invocable as const'
Signed-off-by: Myrtle Shah <gatecat@chipflow.io>
2021-10-30 13:50:44 +01:00
Jean-Paul Chaput 1bb5a0ae15 Merge branch 'pr' into 'devel'
Add Nix code

See merge request vlsi-eda/coriolis!8
2021-10-29 15:30:05 +00:00
Jean-Paul Chaput f41875ccdf Try to blindly correct the linking problem of cx2y. 2021-10-29 17:05:44 +02:00
Jean-Paul Chaput 1592e46a3f At last setup a COPYRIGHT.rst and LICENSE.rst files. 2021-10-29 15:03:03 +02:00
Las Safin abfc63558e
nix: Remove unnecessary `ln` from libresoc test 2021-10-26 23:00:13 +00:00
Las Safin 0f66968a9c
nix: add compatibility files 2021-10-26 22:30:34 +00:00
Las Safin 3072c548cd
Ignore /result (from nix-build) 2021-10-26 22:30:33 +00:00
Las Safin fda334e527
nix: Disable tests temporarily 2021-10-26 22:30:29 +00:00
Las Safin b02c387ed5
nix: Remove dependencies on vlsisapd 2021-10-26 21:47:24 +00:00
Las Safin af95f9f671 nix: Use Python 3 2021-10-26 21:10:13 +00:00
Las Safin 2467580396 nix: Fix missing imports 2021-10-26 20:38:19 +00:00
Las Safin 83b266cb81 nix: Update dependencies 2021-10-26 20:17:17 +00:00
Las Safin 6e5c03434a Adapt Nix code to Python 3 switch.
This commit also reduces the diff by not removing
some (unnecessary) error handling.
2021-10-26 20:10:59 +00:00
Jean-Paul Chaput d0405d8152 Speed up the database by caching the Occurrence hash.
* Change: In Hurricane::SharedPath, the hash for the shared pathes, which
    serves for Map<> storing, were computed "on the fly" at each
    ::getHash() call, and were involving recursive calls of all the
    hashes along the components of the shared path. This is terribly
    slow especially in a design with a deep hierarchy (typical case
    LS180).
      Now, at the cost of one supplemenental unsigned long in each
    SharedPath, it is only computed once in the constructor, and is
    no longer recursive (only access the *first* tail, if any).
      As a consequence, the re-display computation delay becomes
    bearable. But also speed up any transhierarchical walkthough.
2021-10-19 14:48:33 +02:00
Jean-Paul Chaput 180aa52c74 Link is not enough, copy & duplicate tab files for LEF & DEF. 2021-10-18 18:58:35 +02:00
Jean-Paul Chaput c8fd3c0bec Make a link instead of a move in LEF/DEF parsers CMakeLists. 2021-10-18 18:35:29 +02:00
Jean-Paul Chaput 5343f9c98b Disable tie cell insertion in EtesianEngine::toHurricane().
* Change: In Etesianengine::toHurricane(), no longer call interTies().
    This *should* no longer be needed as almost all standard cells
    (SxLib & FlexLib) already contains polarisation contacts.
      So do not need to disturb the placement.
      Secondly, in presence of a H-Tree, when there is not enough
    space to insert a sufficient number of tie cell, the lefmost one
    in the sub-row is shifted to left, overlaping the H-Tree buffer
    cells. This is a bug (even signaled by a warning). But as this
    part is disabled, I won't correct it soon...
2021-10-16 13:45:14 +02:00
Jean-Paul Chaput e80df4538d Build square external pins instead of "flattened" ones.
* Change: In Cumulus/plugins.block.Block, for standalone block,
    the external Pin where created non-square, the "perpandicular"
    side made a half wire width. But in case the wire width was an
    odd number of physical grid, it was leading to offgrid screaming
    in the GDS driver.
      Now, just make them square...
2021-10-16 13:44:51 +02:00
Jean-Paul Chaput 4b9c095ae9 The .tp_print field must be present for Python < 3.8 in PyTypeManager. 2021-10-15 19:35:03 +02:00
Jean-Paul Chaput 7cb8e20644 Merge branch 'build-fix' into 'devel'
Fix Coriolis build on Arch Linux

See merge request vlsi-eda/coriolis!7
2021-10-15 16:51:20 +00:00
Jean-Paul Chaput d6b01a557a Fix out-of-bound with short layers names in GdsDriver::GdsStream.
* Bug: In CRL::GdsDriver::GdsStream::operator<<(Cell*), when looking for
    layer names ending with ".pin", must also check that the string is
    at least 4 characters long.
2021-10-15 18:39:07 +02:00
Myrtle Shah 1dfa6aff67 Add missing "#include"s
Signed-off-by: Myrtle Shah <gatecat@chipflow.io>
2021-10-15 13:40:29 +01:00
Myrtle Shah 8d0faee896 cmake: Set policy needed for latest FindPython to work
Signed-off-by: Myrtle Shah <gatecat@chipflow.io>
2021-10-15 13:40:25 +01:00
Myrtle Shah 2d24efdb6c Bump minimum CMake version
The CMake version set was so old that obsolete policies were being
enabled and breaking FindPython. 2.8 should still be old enough not to
cause problems for any current users.

Signed-off-by: Myrtle Shah <gatecat@chipflow.io>
2021-10-15 13:38:38 +01:00
Myrtle Shah 03f0e51dfd hurricane: Remove '.tp_print' field
This field has been deprecated in Python 3 and no longer exists at all
in Python 3.9, causing a build error.

Signed-off-by: Myrtle Shah <gatecat@chipflow.io>
2021-10-15 12:51:10 +01:00
Myrtle Shah 9f9ad61ee7 lefdef: Don't move generated tab.hpp files
Signed-off-by: gatecat <gatecat@ds0.me>
2021-10-15 12:44:39 +01:00
Jean-Paul Chaput f58212eb96 Fix incorrect application of xTracksReservedMin in Katana.
* Bug: In KatanaEngine::annotateGlobalGraph(), the minimum track reservation
    was not applied correctly. Instead of adding the *difference* between
    the minimum and the current reservation, the minimum was simply added.
    Leading to too high reservation. And loss of control about what we
    were doing on the edges capacities...
      Really stupid.
2021-10-14 23:50:14 +02:00
Jean-Paul Chaput fd2c92f442 * Change: In cumulus/plugins.chip.powerplane, when the vertical rail is
large enough instead of creating one big via along the horizontal
    cell power lines, we create one big VIA at each end. To avoid to
    create too massive obstructions.
      But the thresold was too high for cmos45, leading to short with
    the clock tree trunk.
2021-10-09 22:51:48 +02:00
Jean-Paul Chaput 5ba4c35d63 Change back the pixel display threshold to 5 (downgrade my HiDPI display). 2021-10-09 22:43:11 +02:00
Jean-Paul Chaput b9a1395b4b Improve Coriolis root directory search in coriolisEnv.py.
* Change: In bootstrap/coriolisEnv.py, when all tries to locate the
    installation root in predefined locations, try the directory the
    script is installed in.
      This allows for a user to use an installation made in another
    user's account.
2021-10-09 22:39:06 +02:00
Jean-Paul Chaput 4a256f36b5 Refit the design after entering placement in cumulus/plugins.block.doPnR(). 2021-10-07 00:55:03 +02:00
Jean-Paul Chaput 069c654a24 Make "msxlib_uniform" the default gauge in cmos45. 2021-10-07 00:52:57 +02:00
Jean-Paul Chaput b2e265f73e Increase bloating in Etesian "nsxlib" profile, for ls180+cmos45. 2021-10-07 00:51:15 +02:00
Jean-Paul Chaput 66361fcf3d Correct catastrophic memory bloat in Anabatic::layerAssign() step.
* Bug: In Anabatic::_desaturate(), the set of invalidated GCells was never
    cleared between iterations of desaturated GCells. This was not a
    memory leak per se because, in the end, the set was freed. But it did
    induce a gigantic bloating in memory. This finally explain the strange
    slow down in that stage.
      Detected in ls180+cmos45.
* Change: In Anabatic::GCell, add a flag for each depth to avoid
    desaturating twice the same GCell (maybe not needed now that the
    bug is corrected, but it ensure a no-looping).
2021-10-07 00:48:47 +02:00
Jean-Paul Chaput 2cfd9a0c51 Increase the display threshold of GCell edges (visible at lower zoom). 2021-10-07 00:41:12 +02:00
Jean-Paul Chaput b1bc22f8e7 Bad computation of minimal area of stacked VIAs in Cumulus.
* Bug: In cumulus/plugins.block.configuration.GaugeConf.expandMinArea(),
    The minimal length of the segment intermediate wires where computed
    for the minimal area using an integer division ( // ), which is
    stupid for less than 1.0 values. They are real quantities at this
    point...
      This was making the DRC of ls180 failing.
2021-10-07 00:39:24 +02:00
Jean-Paul Chaput f77741db3f In GraphicKatanaEngine, restore normal display of edges occupancy. 2021-10-07 00:32:14 +02:00
Las Safin e69da9aeb7
Fix licenses 2021-10-06 16:07:46 +00:00
Jean-Paul Chaput b1befe5626 Added "--shell=<SHELL>" option to coriolisEnv.py. 2021-10-02 14:02:03 +02:00
Jean-Paul Chaput 36ce36f582 In block.iospecs.py, no more need to translate into UTF-8 in Python3. 2021-10-02 00:59:17 +02:00
Jean-Paul Chaput d288ca4d09 Forgotten debug message in SubNetNames::match(). 2021-10-02 00:25:52 +02:00
Jean-Paul Chaput 0e63168802 Regenerated whole doc (by mistake)... 2021-10-01 21:36:45 +02:00
Jean-Paul Chaput 61ab4b0da6 Cleanup of CMake, again. 2021-10-01 19:29:29 +02:00
Jean-Paul Chaput 2b9ca8abcc Updated PDFs, October 01, 2021 (19:23). 2021-10-01 19:23:27 +02:00
Jean-Paul Chaput c9bef61c3d Updated PDFs, October 01, 2021 (19:21). 2021-10-01 19:21:36 +02:00
Jean-Paul Chaput da84e5934a Updated PDFs, October 01, 2021 (19:19). 2021-10-01 19:19:23 +02:00
Jean-Paul Chaput 6c39d607d3 Updated PDFs, October 01, 2021 (19:17). 2021-10-01 19:17:52 +02:00
Jean-Paul Chaput f9d309a51e Updated PDFs, October 01, 2021 (19:14). 2021-10-01 19:14:41 +02:00
Jean-Paul Chaput fbc9551a3f Updated PDFs, October 01, 2021 (18:54). 2021-10-01 18:54:05 +02:00
Jean-Paul Chaput 0c0b426894 Follow up of PyModule_GetFilenameObject() modification. 2021-10-01 18:33:47 +02:00
Jean-Paul Chaput 7e9153f6f9 Update CMakeLists.txt to newer policies. 2021-10-01 18:31:53 +02:00
Jean-Paul Chaput e11bd98f52 Correct for various warnings appearing under gcc 8.3.0 (Debian 10).
Note: We don't suppress warnings due to unused variables or functions,
      as we may need them later or in debug mode...

* Change: In Hurricane::DBo::~DBo, add a noexcept(false) because
    constructed by default destructor of derived classes seems to
    loosen it. The right solution whould be to explicitely define
    all virtual destructors (too lazy for now).
* Change: In Viewer::Script, replace the deprecated
    PyModule_GetFilename() by PyModule_GetFilenameObject(), Unicode
    support again...
2021-10-01 16:12:28 +02:00
Jean-Paul Chaput c28fe3402b Take account of more Python site-packages.
* Change: In bootstrap/coriolisEnv.py, the script was looking to
    pythonX.Y (like "python2.7" or "python3.6") only. Now added
    "major" only directories like "python2" or "python3".
2021-10-01 00:30:10 +02:00
Jean-Paul Chaput a617cea0a5 Remove deprecated C++11 throw() specifications. 2021-10-01 00:26:58 +02:00
Jean-Paul Chaput 9852c76c2c Revert from std::regex to C POXIX regex.
* Bug: In Hurricane::Backtrace(), the std::regex supplied by gcc 4.8.5
    seems to be buggy. So, for now, to compile on my reference system,
    revert to C POSIX.
2021-09-30 20:06:48 +02:00
Jean-Paul Chaput 35c44f8b81 Typo in error message. 2021-09-30 20:00:24 +02:00
Jean-Paul Chaput 0d473e18c0 Fix crash in Anabatic::AntennaProtect.
* Bug: In Anabatic::AntennaProtect, if the diode cell exists *but* the
    maximum wire length for a diode is *not* defined (so zero) cancel
    the diode protection instead of making a divide by zero.
2021-09-30 19:59:28 +02:00
Jean-Paul Chaput 9c71ce8a03 Updated doc of the new Python/C++ template wrapper.
* Change: In Isobar3::PyWrapper, C++ exceptions where not catcheds,
    forgot to call exceptionWrapper().
* Change: In Isobar3, remove unused pyToC<>() flavor where T is a
    simple pointer and the argument is also a simple pointer, does
    not make sense.
2021-09-26 17:27:57 +02:00
Jean-Paul Chaput a53281cdb3 Updated PDFs, September 26, 2021 (17:17). 2021-09-26 17:17:03 +02:00
Jean-Paul Chaput ee06ba2932 Updated PDFs, September 26, 2021 (17:07). 2021-09-26 17:07:53 +02:00
Jean-Paul Chaput a7083f6063 Updated PDFs, September 26, 2021 (17:03). 2021-09-26 17:03:05 +02:00
Jean-Paul Chaput 43743940fa Updated PDFs, September 26, 2021 (16:55). 2021-09-26 16:55:18 +02:00
Jean-Paul Chaput 844db44ebf Rename pyTypePostModuleInit<> to pyTypePostInit<> (clearer). 2021-09-25 19:20:57 +02:00
Jean-Paul Chaput 16d1da053a Migration towards Python 3, stage 2: C++ template wrapper ready.
* New: In hurricane/configuration, the Python/C template wrapper has
    now all the needed features to mass-migrate Hurricane and the
    ToolEngines.
      The new Hurricane module is named Hurricane3 so it does not
    collides with the old one which is still used. Will do the
    same for all ToolEngines Python wrappers until migration is
    complete.
* New: In unittests/python/, create very basic unit tests for the
    Configuration & Hurricane new template wrapper.
    Note: It is almost impossible to use valgrind on them because
          it doesn't recognize correctly Python allocation mechanism.
	  To make it work, both valgrind & Python needs to be
	  recompiled with special options...
2021-09-25 17:03:14 +02:00
Jean-Paul Chaput 3bd0dbfd24 Forgot to encode bytes read from file into string. 2021-09-19 23:35:51 +02:00
Jean-Paul Chaput 02777e127e Migration towards Python3, first stage: still based on C-Macros.
* New: Python/C++ API level:
  * Write a new C++/template wrapper to get rid of boost::python
  * The int & long Python type are now merged. So a C/C++ level,
    it became "PyLong_X" (remove "PyInt_X") and at Python code
    level, it became "int" (remove "long").
* Change: VLSISAPD finally defunct.
  * Configuration is now integrated as a Hurricane component,
    makes use of the new C++/template wrapper.
  * vlsisapd is now defunct. Keep it in the source for now as
    some remaining non essential code may have to be ported in
    the future.
* Note: Python code (copy of the migration howto):
  * New print function syntax print().
  * Changed "dict.has_key(k)" for "k" in dict.
  * Changed "except Exception, e" for "except Exception as e".
  * The division "/" is now the floating point division, even if
    both operand are integers. So 3/2 now gives 1.5 and no longer 1.
    The integer division is now "//" : 1 = 3//2. So have to carefully
    review the code to update. Most of the time we want to use "//".
    We must never change to float for long that, in fact, represents
    DbU (exposed as Python int type).
  * execfile() must be replaced by exec(open("file").read()).
  * iter().__next__() becomes iter(x).__next__().
  * __getslice__() has been removed, integrated to __getitem__().
  * The formating used for str(type(o)) has changed, so In Stratus,
    have to update them ("<class 'MyClass'>" instead of "MyClass").
  * the "types" module no longer supply values for default types
    like str (types.StringType) or list (types.StringType).
    Must use "isinstance()" where they were occuring.
  * Remove the 'L' to indicate "long integer" (like "12L"), now
    all Python integer are long.
* Change in bootstrap:
  * Ported Coriolis builder (ccb) to Python3.
  * Ported Coriolis socInstaller.py to Python3.
  * Note: In PyQt4+Python3, QVariant no longer exists. Use None or
    directly convert using the python syntax: bool(x), int(x), ...
    By default, it is a string (str).
* Note: PyQt4 bindings & Python3 under SL7.
  * In order to compile user's must upgrade to my own rebuild of
    PyQt 4 & 5 bindings 4.19.21-1.el7.soc.
* Bug: In cumulus/plugins.block.htree.HTree.splitNet(), set the root
    buffer of the H-Tree to the original signal (mainly: top clock).
      Strangely, it was only done when working in full chip mode.
2021-09-19 19:41:24 +02:00
Las Safin fca22782a0
Remove unneeded input 2021-09-16 20:10:05 +00:00
Las Safin 8c21c6a35b
libresoc: Use recon experiment instead 2021-09-06 20:57:27 +00:00
Las Safin c3d10b21aa
Use older version of yosys for Libre-SoC 2021-09-05 18:48:19 +00:00
Las Safin 41274d6ab5
Make Libre-SoC almost work 2021-09-05 17:47:17 +00:00
Las Safin 4f6f668b74
Try to get libresoc working 2021-09-05 16:06:44 +00:00
Las Safin 6ae448ee39
LibreSoC experiment work 2021-09-05 14:49:09 +00:00
Las Safin 8e8844588c
Fix unittests 2021-09-05 14:22:18 +00:00
Las Safin c7bf1a75d2
Fix comment 2021-09-05 14:17:19 +00:00
Las Safin 0e8367d63c
Add nix/libresoc-experiments9.nix 2021-09-05 14:16:11 +00:00
Las Safin b1570850bd
Make unittests a check 2021-09-05 14:03:28 +00:00
Las Safin 7a3f337935
Make alliance-check-toolkit a check 2021-09-05 13:57:31 +00:00
Las Safin d5f3c6c3d0
Add comment about CORIOLIS_TOP 2021-09-05 12:20:50 +00:00
Las Safin 33a847c117
Make all checks work 2021-09-03 15:17:56 +00:00
Las Safin 7f805cb48f
Run all tests (some fail) 2021-09-03 14:00:08 +00:00
Las Safin df7d4667a9
Don't try to catch import error in cgt 2021-09-03 13:54:37 +00:00
Las Safin c62f95af7c
Get adder/cmos test working! 2021-09-03 13:49:43 +00:00
Las Safin e354b3ac4b
Fix stratus1 2021-09-03 13:48:01 +00:00
Las Safin c6624909de
Keep backward compatibility for cumulus users 2021-09-03 13:46:33 +00:00
Las Safin fd55e99a7c
fix karakaze 2021-09-03 13:33:48 +00:00
Las Safin 1fddafc814
Add combined 2021-09-03 13:31:29 +00:00
Las Safin 84640f3bc1
Some checks pass! 2021-09-03 13:10:08 +00:00
Las Safin a3a738c0ff
Fix cumulus 2021-09-03 12:50:39 +00:00
Las Safin 658db5ab58
Get further in alliance tests 2021-09-03 12:29:44 +00:00
Las Safin 5c7b2fdc28
Fix devShell 2021-09-03 10:12:38 +00:00
Las Safin 4f266c04eb
Get alliance check toolkit to fail 2021-09-02 22:39:29 +00:00
Las Safin 78db672549
Use Nixpkgs with Alliance 2021-09-02 22:00:29 +00:00
Las Safin 979f97df2f
Include yosys 2021-09-02 09:54:51 +00:00
Las Safin d28ec8b7c4
Add initial code for running alliance checks 2021-09-01 22:30:59 +00:00
Las Safin 55f32e510e
Run unit tests 2021-09-01 18:46:28 +00:00
Las Safin 521863e195
Use OpenMP 2021-09-01 17:39:00 +00:00
Las Safin 953a98b769
Make cgt work a bit more 2021-09-01 17:18:05 +00:00
Las Safin f20ffa02e9
Get oroshi working 2021-09-01 11:13:49 +00:00
Las Safin 227a8f1721
Set CORIOLIS_TOP for crlcore check 2021-09-01 10:03:41 +00:00
Las Safin d4818a6b81
Fix missing import in crlcore 2021-09-01 09:40:23 +00:00
Las Safin 3584ea3ee9
Use pyqt4 4.12.1 2021-09-01 09:31:22 +00:00
Las Safin 2f11506dbf
Try to get Qt support to work 2021-08-31 19:06:30 +00:00
Las Safin c5fdafbf53
Add license for Nix code 2021-08-31 15:50:50 +00:00
Las Safin 36203e5d51
Fix licenses 2021-08-31 15:47:12 +00:00
Las Safin 6beed7504c
crlcore 2021-08-31 15:32:38 +00:00
Las Safin e2475c8332
Add devShells 2021-08-31 14:10:13 +00:00
Las Safin b5b4f0a633
unicorn, tutorial, kite, katabatic, bora 2021-08-29 19:58:17 +00:00
Las Safin eeba236c36
katana 2021-08-29 19:24:14 +00:00
Las Safin 5bbc5b3b2e
etesian, anabatic 2021-08-29 19:21:28 +00:00
Las Safin 7bab1feec5
flute 2021-08-29 19:16:28 +00:00
Las Safin 7661abe6e1
Try to get crlcore working 2021-08-29 18:25:21 +00:00
Las Safin c7df1e6ac9
hurricane 2021-08-29 17:46:28 +00:00
Las Safin 41665edfed
Add generic helper 2021-08-29 17:37:07 +00:00
Las Safin 7105a5aea4
Make vlsisapd accessible through Python! 2021-08-29 15:33:53 +00:00
Las Safin e1975b45ea
Fix linking with boost python 2021-08-29 15:31:41 +00:00
Las Safin 18c4ebdb86
Set version and default package 2021-08-27 20:18:09 +00:00
Las Safin ceffebde2e
-DBUILD_DOC=ON 2021-08-27 20:08:48 +00:00
Las Safin 7ecd0ce2fe
unittests 2021-08-27 20:00:36 +00:00
Las Safin 9e21326d03
documentation 2021-08-27 19:56:12 +00:00
Las Safin 11311072a2
unicorn 2021-08-27 19:48:19 +00:00
Las Safin ed96a0b2e4
Build documentation 2021-08-27 17:20:51 +00:00
Las Safin c47e89ce26
tutorial 2021-08-27 17:18:34 +00:00
Las Safin 8ead337bd8
stratus1 2021-08-27 17:15:30 +00:00
Las Safin 644805db36
solstice 2021-08-27 17:07:48 +00:00
Las Safin ffdff0b77a
oroshi 2021-08-27 16:44:57 +00:00
Las Safin 2c4f143e15
metis, mauka 2021-08-27 16:43:24 +00:00
Las Safin d7fe45acd8
nimbus 2021-08-27 16:40:10 +00:00
Las Safin b6336a0249
kite 2021-08-27 16:36:55 +00:00
Las Safin d6837972aa
karakaze 2021-08-27 16:29:24 +00:00
Las Safin 024b4b232f
ispd 2021-08-27 16:23:35 +00:00
Las Safin dcc0e6aebf
include/coriolis -> include/coriolis2 2021-08-27 16:15:28 +00:00
Las Safin 99cf78f580
ispd work 2021-08-27 15:27:53 +00:00
Las Safin 552e54731a
katabatic 2021-08-27 15:16:06 +00:00
Las Safin 867df820f5
knik 2021-08-27 15:10:28 +00:00
Las Safin 9110d58ef2
equinox 2021-08-27 15:07:38 +00:00
Las Safin c253ef4ed7
bora 2021-08-27 14:49:00 +00:00
Las Safin 72b46d7802
katana 2021-08-27 14:36:23 +00:00
Las Safin 4dff6fd6c3
etesian and anabatic 2021-08-27 14:26:33 +00:00
Las Safin a5187f34b9
flute 2021-08-26 16:44:45 +00:00
Las Safin 83eb8b4a6b
cumulus 2021-08-26 16:23:26 +00:00
Las Safin 9aa450e8af
crlcore 2021-08-26 16:14:25 +00:00
Las Safin 68400d9437
crlcore work 2021-08-23 08:44:29 +00:00
Las Safin a7ecaeaa36
Cleanup 2021-08-23 08:44:07 +00:00
Las Safin 985ae3edde
coloquinte and lefdef 2021-08-22 11:40:56 +00:00
Las Safin 8c9353f791
hurricane builds 2021-08-22 11:17:47 +00:00
Las Safin 7c5679408f
Get vlsisapd and bootstrap building! 2021-08-22 10:54:22 +00:00
Las Safin be6260ab64
temporary commit 2021-08-22 05:47:36 +00:00
Las Safin 3bef114e97
Use CMake 2.8 2021-08-21 22:09:39 +00:00
Las Safin 5a536b93b4
Got it working? 2021-08-16 19:50:39 +00:00
Las Safin 435168931e
bad hack 2021-08-16 19:06:13 +00:00
Las Safin 82b6604e2b
wip 2021-08-16 17:41:57 +00:00
Jean-Paul Chaput f1668cec5f Disable BFD support by default.
* Change: In <tool>/CMakeLists.txt, add an USE_LIBBFD option to
    enable the link against the BFD library. Latest versions seems
    to have changed their API.
* Change: In bootstrap/ccp.by & builder/Builder.py, add an option
    "--bfd" (and self._bfd) to enable BFD support.
2021-07-17 13:01:19 +02:00
Jean-Paul Chaput 3687ca80e9 Add management for highly loaded leafs of H-Trees.
In the LS180, probably due to the implementation of a small RAM
with DFFs, some leaf of the clock tree (H-Tree) got heavily
loaded (around 80 DFFs sinks). Implement an option that allow
the leaf of the QuadTree to use three buffers instead of one.
The sinks are partitionned using their angle from the center
of the leaf (trigonometric direction). CChoose the bigger angle
gaps to perform the split.

* Change: In Cumulus/plugins.block.configuration.GaugeConf, in
     getNearestHorizontalTrack() and getNearestVerticalTrack() add an
     offset argument to shift the position of the requested track
     by a certain amount.
* Change: In Cumulus/plugins.block.configuration.GaugeConf, in
    createHorizontal(), add a flag to make the source end of the
    segment to "stick out". Useful when connecting to a stacked
    VIA top, but using a lower layer that can be shifted.
* New: In Cumulus/plugins.block.spares.Spares, BufferPool & QuadTree,
    add support for selection and management of multiple buffers at
    the same time. Basically returns a list of selected buffer
    instances instead of just one instance.
      Added HEAVY_LEAF_LOAD flag to Spares. To be used by all tools
    classes that makes use of it.
      Added QuadTree.runselect(), be sure to call it between different
    H-Tree operations, otherwise results will be strange.
* New: In Cumulus/plugins.block.htree.HTree, in case of heavy leaf
    load, in the leaf of the tree, allocate three buffers instead
    of one. Select them to form a triangle around the main one.
    That is, use (i,j), (i+1,j) and (i,j+1).
      Added a HTree._connectLeaf() to share the handling of the child
    buffer connexions. Whether they are leaf of not and heavy or not.
* Change: Cumulus/plugins.block.Block, expand HTree support to
    manage the HEAVY_LEAF_LOAD flag.
2021-07-01 14:01:44 +02:00
Jean-Paul Chaput c6f703b1cc New parameter "katana.trackFill" to control the dummy fill ratio. 2021-06-27 20:16:42 +02:00
Jean-Paul Chaput 106bc89cb5 Fix offgrid core power rings in symbolic/cmos configuration.
* Bug: In CRL/etc/symbolic/plugins.py, power lines around the core where
    badly spaced, allowing the filler to insert a fill wire that was
    causing both DRC error and short circuit.
2021-06-26 14:38:13 +02:00
Jean-Paul Chaput 3f42981fb2 Fix too narrow blockages areas for the SRAM/macro wrapper.
* In Cumulus/plugins/block/macro.py, the METAL3 blokage was too narrow
    on the left side, allowing use of METAL3 track too close from
    internal components.
      The METAL5 blockages around jumpers where also too narrow.
      Thoses problems where seen with the density filler which put
    wires everywhere.
2021-06-26 14:37:37 +02:00
Jean-Paul Chaput 5a43c1465e Fix badly filled tracks containing blockages.
* Bug: In Track::repair(), consider the blockage net as any other, so
    the metal filling works correctly (correct management of transitions
    between blockage and non-blockage).
2021-06-26 14:36:59 +02:00
Jean-Paul Chaput 46c4cc98df Fill every two tracks in Track::repair() to balance metal density. 2021-06-25 15:55:59 +02:00
Jean-Paul Chaput 6fc7ece575 Use fill_x0 instead of tie_x0 in Etesian::Slice::fillHole()
* Change: In Etesian::Slice::fillHole(), instead of cramming the home
    with tix_x0 only, put one tie at both ends and fill the rest
    with fill_x0. This should help the vendor density filler to
    equalze.
* New: In Etesian::Configuration, add the parameter:
    "etesian.tieName" (for tix_x0) as it now separate from the simple
    filler cells.
2021-06-24 11:18:22 +02:00
Jean-Paul Chaput fdf66cbf64 In Etesian bloat profile for FlexLib, expand mx2_x2 of one more pitch.
* In Etesian::BloatFlexLib::getDx(), expand the "mx2_x2" of one more
    pitch (2 instead of 1). The P&R was unable to allocate a critical
    diode under a slice that was littered with those cells in LS180.
2021-06-24 11:17:52 +02:00
Jean-Paul Chaput 2705226cd0 Manage .include in SPICE driver so they occurs only once.
SPICE simulators don't like to have the same model defined twice.
As we have a "one file per model policy", then we must include the
model file only once. This is particularly critical for standard
cells. So now, the driver include all the models in the top level,
both terminals ans intermediate. And the sub-models include nothing.
We stop at the "TerminalNetlist" level.
  Add an option flag througout all the Spice driver hierarchy to
convey that information.
2021-06-24 11:17:21 +02:00
Jean-Paul Chaput f49426f2bb The "d" and "s" terminals where inverted in the LibreSOC IOPadInOut.
* Bug: In cumulus/plugins.chip.libresocio, the ioPadInfos where inverting
   "d" and "s" terminals on IOPadInOut. This was indirectly detected by
   the DRC complaining about floating gates on the "d" connected nets!
2021-06-23 00:07:51 +02:00
Jean-Paul Chaput 98e95587cf Remove Spice extension after use. Checks for non-driven nets.
* New: cumulus/plugins.checks, plugin providing a oneDriver() function
    to check that each net has one and only one driver. This is for
    Cell that are not P&R (in which it is also checked). So, typically
    the chip level.
* New: In cumulus/plugins.chip.core2chip, add a call to oneDriver().
* Bug: In cumulus/plugins.chip.core2chip, clear Spice extensions after
    save. Otherwise we may use an outdated Spice extension after the
    P&R. This is were Net missing Spice::Bit may occur.
2021-06-23 00:07:25 +02:00
Jean-Paul Chaput 0d7e0fa88b Correct the SPICE driver in case a Net is missing Spice::BitExtension.
* Change: In Spice::Entity::toEntity(), add an error message if the
    Spice::Bit extension is missing.
2021-06-23 00:06:51 +02:00
Jean-Paul Chaput 51ca8ab4af Added basic SPICE driver support.
The structure of the driver is copied from the Vhdl one. It is not
integrated as a an AllianceFramework one but as a standalone like
GDS. For now use numerical indexes for electrical nodes but also
support strings. The nets are ordereds in reverse alphabetical
order, but a custom order can be defined, if we read the model
from an external SPICE subckt (to be done).
  SPICE saving has also been added to the cumulus/rsave plugin
and the block/chip P&R one.
2021-06-21 01:30:28 +02:00
Jean-Paul Chaput eeda81f746 Move deprectated version of Spice parser/driver out of the way. 2021-06-20 11:35:26 +02:00
Jean-Paul Chaput 68d957fe3a Prevent wires part of a diode cluster to be moved up.
Protections diodes may not be able to play their role if they are
separated from their cluster by upper level layers (METAL4/METAL5).
This seems not to diminish the total number of diodes.

* New: In Anabatic::NetData, add a set of non move up segments in
    the object. To tag global wires that are part of a cluster.
* New: In Anabatic::AutoSegment, add support for a SegNoMoveUp
    flag. This flag is propagated through _makeDogleg()	.
      Used in ::canMoveUp() and ::canPivotUp().
* New: In Anabatic::NetBuilder, add NetData to the attributes so
    we can extract the NoMoveUp infomation given by the antenna
    protect stage.
* New: In NetBuilderHV::_do_globalSegment(), lookup NoMoveUp
    information from NetData to put it in AutoSegment.
* New: In AntennaProtect(Net*), flags the RoutingPad clusters wires
    as non movable up.
* New: In AnabaticEngine::breatAt(GCell*), propagate the SegNoMoveUp
    flags. Based on NetData.
2021-06-18 19:17:24 +02:00
Jean-Paul Chaput 72b5de88c4 Fix bugs in AutoSegment::isMiddleStack() and canReduce().
* Bug: In AutoSegment::canReduce(), in the repair stage, segments are
    allowed to go beyond their GCell bondaries, so global segments can
    end up in zero length. So now allow globals less than one P-Pitch
    to be flagged as reduced.
* Bug: In AutoSegment::isMiddleStack(), systematically reject non-canonical
    segment. If it is non-canonical, then is aligned with a canonical one.
    Then we will perform the check on it.
      There seems to be another porblem of update of the length of the
    associated TrackElement, the increase of size of the non-canonical is
    not taken into account. This is enough to prevent the problem to
    arise but we should invsetigate further.
* Hack: In AutoSegment::canMoveUp(), prevent segment id:6378409 to be
    moved up so the last antenna effect is avoided. This is not a clean
    way to do it.
2021-06-17 23:49:54 +02:00
Jean-Paul Chaput ddc7aef13b At last make use of cdebug_log() in Track::repair(). 2021-06-17 23:36:35 +02:00
Jean-Paul Chaput f873e616cb Use of tset() manipulator instead of setw() when printing in cdebug_log. 2021-06-17 23:36:22 +02:00
Jean-Paul Chaput d43fa49778 Add basic support for logo insertion in cumulus/plugins.chip. 2021-06-16 16:26:33 +02:00
Jean-Paul Chaput 15e7abf667 Use the DATATYPE for LAYER record in GdsStream.
* Change: In GdsStream::_gdsLayerTable, use a map<> instead of a vector<>,
    use a combined value of the layer index and the datatype as index.
        (index = (layer<<16) + datatype.
    This allow for layers that are represented by a pair of (layer,datatype)
    with same layer and different datatypes.
* Change: In GdsStream::gdsToLayer(), now have two parameters, the layer
    and the datatype.
2021-06-16 16:24:01 +02:00
Jean-Paul Chaput 6c68055199 In core2chip, use the "padres" input of the analog pad. 2021-06-15 01:18:41 +02:00
Jean-Paul Chaput c83fff72ac Suppress cell fitting during P&R. 2021-06-15 01:17:01 +02:00
Jean-Paul Chaput 2e015ea780 Prune ordinary wires in Katana::PowerRails.
* Change: In Katana::PowerRails, in TerminalNetlist cells instances,
    the ordinary nets components where generating obstacles, leading
    to stupid cross blockages between the obstacle generated by the
    component supporting the routing pad and the RP itself.
      Now only take into account supplies and clocks (any layers)
    and blockage layers.
      Fix symbolic benches.
2021-06-13 12:03:57 +02:00
Jean-Paul Chaput 63d2f69459 Increate the reluctance to go up in Manipulator::moveUp().
* Change: In Katana::Manipulator::moveUp(), the "reserve" value was
    of 0.5 for pivot up and locals, now set it to 1.0, like in all
    other cases ("reserve" is the number of free tracks that is
    needed to allow the move up, in addition the the length being
    moved up).
      Fix routing convergence on the MIPS pipeline bench.
2021-06-13 12:03:35 +02:00
Jean-Paul Chaput 1569e2807e In CRL::GdsParser, GDS layers indexes up to 1024, just in case. 2021-06-12 17:52:29 +02:00
Jean-Paul Chaput f3ccf31e48 Fix incomplete GDS layer table in GdsParser.
* Bug: In CRL::GdsParser(), the table of GDS layer was limited to 64,
   which is the maximum, according to the reference. But it is no
   longer true. Extend to 256.
     This was leading to GDS files missing some layers.
2021-06-12 16:29:08 +02:00
Jean-Paul Chaput 3bd1d56582 Fix last DRC incorrect case in TrackSegment::isMiddleStack().
* Bug: In TrackSegment::isMiddleStack(), formerly, all global segments
    where discarted. But in the routing repair stage, segments can go
    *outside* their GCell boundaries, allowing globals to became of
    null length.
       Hence, for global, we now also check the wirelength.
2021-06-12 16:21:10 +02:00
Jean-Paul Chaput f9e4daace9 Comment out debug information in Track::repair(). 2021-06-12 16:17:03 +02:00
Jean-Paul Chaput ffd6f571b5 No longer connect the root of HTrees with straigh lines, use the router.
* Change: In cumulus/plugins.chip.chip.doConnectCore(), do not use the
    feature of the HTree to connect the root buffer straight to the
    corona pin. It prevents the router to insert a diode when those
    wires are too long. So let the standard router manage them.
      Should add diode insertions in HTree.connectHTrees() later.
2021-06-12 11:49:07 +02:00
Jean-Paul Chaput 1733b5142a Fix bad index in Track::repair().
* Bug: In Track::repair(), when a same net gap has been found and closed,
    we display a warning. We display the two segments fused, but when it's
    the two first, we must not use index "i-1" (with i=0) ...
2021-06-12 11:42:53 +02:00
Jean-Paul Chaput ebe8ea64c6 Freeze version of RapidJSON to build under SL7.
* Change: In bootstrap/socInstaller.py, freeze the version of RapidJSON
    to commmit #b1a4d91 as later ones have problems building their doc
    under SL7.
2021-06-11 11:47:35 +02:00
Jean-Paul Chaput 4e7dbee831 Fix HTree to corona's edge wiring in horizontal direction.
* Bug: In cumulus/plugins.chip.powerplane.Builder._connectHTree(),
    when building the stacked VIAs over the corona Pin and the
    root buffer RoutingPad, pass the GaugeConf.HAccess flag so the
    stack stops at METAL4 (top horizontal layer).
      Before we where also adding a VIA up to METAL5 which was unused
    and caused a minimal area violation.
2021-06-11 11:47:02 +02:00
Jean-Paul Chaput 68812fa0ca Fix same net gap between the two last elements of a Track.
* Bug: In Track::repair(), the same net gaps between the last and before
    last track elements where overlooked. Leading to very rare DRC
    violations.
2021-06-11 11:46:37 +02:00
Jean-Paul Chaput 7c8d47a2d1 More generic criterion for finding under minimum area segments.
* Change: In AutoSegment::isMiddleStack(), after checking for obvious
    non-candidates, relies on axis-to-axis wirelength instead of topological
    criterions. We will not be able to account all the topologies that
    may cause problem. So consider every segment whose length is below
    one perpandicular pitch.
2021-06-11 11:46:13 +02:00
Jean-Paul Chaput 9c153699be Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2021-06-10 15:29:31 +02:00
Jean-Paul Chaput 79858840fc In NetBuilderHV::_do_xG_1M1(), less rigid topology for straight vertical. 2021-06-10 15:29:00 +02:00
Luke Kenneth Casson Leighton 19b9f9e2e7 put in a temporary absolutely terrible hack for now to skip adding analog pins 2021-06-10 11:50:55 +00:00
Luke Kenneth Casson Leighton ed3bdbe455 un-messed-up IoSpecs.loadFromPinmux, add new function for
making a pad Analog
2021-06-10 11:46:30 +00:00
Luke Kenneth Casson Leighton ac3e78c55c allow ioSpecs loadFromPinmux to undersand IoPin.ANALOG format 2021-06-10 11:13:27 +00:00
Jean-Paul Chaput 7961aab0e1 Adjust blockage area over SRAM.
* Change: In cumulus/plugins.block.macro, the METAL2 blockage was
    allowing horizontal tracks to be used but the METAL3 blockage
    was conflicting with the end of the perpandiculars.
      The router was not able to manage that, so we slightly expand
    the METAL2 blockage to encompass the unreachable track.
      For the same reason, add a METAL4 blockage over METAL2.
2021-06-09 15:11:43 +02:00
Jean-Paul Chaput 92a3e32aaf Add jumpers (antenna protection) on I/O pads and SRAM macro-block.
* New: In cumulus/plugins.chip.pads, add METAL5 jumpers on all wires
    going to/from the I/O pads on the East & West side. This is a
    quick hack as:
      1. We should put it also on North/South, but no violation
         happens here.
      2. We should put it on *ouput* wire only (for only those are
         connected to transistors gates).
* New: In cumulus/plugins.chip.macro, put jumpers on the East side
    connectors for the SRAM block. Also a quick hack, not robust for
    anything else than the SRAM.
2021-06-08 12:20:05 +02:00
Jean-Paul Chaput dd49a185af Compensate diodes between RP clusters & wire clusters.
In Anabatic::AntennaProtect, when we cannot insert enough diodes
under a wire cluster. Which makes it likely very long and over an
area where diodes cannot be inserted (chip border close to I/O pads
or over a macro-block). Request extra diode insertion on it's
connecting RoutingPad clusters.

* New: In Anabatic::DiodeCluster, add a "forced diode" counter for
    extra diodes inertions. Only used in the DiodeRps derived class.
* New: In Anabatic::DiodeCluster, add support for a cluster to know
    it's neighbors. Stored as indexes of the table being built in
    Anabatic::antennaProtect(Net*).
* New: In Anabatic::antennaProtect(Net*), when builing the WireCluster,
    also find it's neigbors. Store the index of the cluster a segment
    belongs to in clusterSegments.
2021-06-08 12:19:40 +02:00
Jean-Paul Chaput 5f60767486 In AutoSegment::expandToMinLength(), ensure that we stay on foundry grid 2021-06-08 12:19:08 +02:00
Jean-Paul Chaput 352ca94483 Change the way QuadTree.getLeafUnder() locate the leaf.
* Change: In cumulus/plugins.Block.getLeafUnder(): formerly, we where
    using the cut-lines (x/y) to locate which leaf a point is under.
    But in case of incomplete tree, it is difficult to manage.
      Now we chosse the leaf according to the distance to the center
    of the leaf area. Choose the shorter, of course.
      This solve the H-Tree DFF bad assignment around the PLL (top
    right corner) in LS180.
2021-06-06 10:55:24 +02:00
Jean-Paul Chaput a2daf26fca Fix Block.getFlattenedNet() for "one instance path" cases. 2021-06-06 10:50:13 +02:00
Jean-Paul Chaput fc445a2285 More comprehensive error message in VST parser (connector discrepencies). 2021-06-06 10:46:39 +02:00
Jean-Paul Chaput 9b8ea64545 Add VHDL "ref" keyword to CRL::NamingScheme. Cleanup BlifParser debug. 2021-06-04 11:28:12 +02:00
Jean-Paul Chaput 1d7a415e9f Fix memory corruption after placement occurring on LibreSOC/ls180.
* Bug: In Cumulus/plugins.block.Block, re-order Etesian tool creation
    and virtual net flattening. Must investigate later why it is so
    sensitive to at least warn/stop cleanly.
2021-06-03 01:20:24 +02:00
Jean-Paul Chaput d2a621629a Build blockages for all fixed nets in Katana.
* Bug: In Katana::GlobalNetTable::getRootNet(), look for all fixed nets,
    not only supplies and clocks. There may be some as now H-Trees are
    not limited to clocks.
      Should solve ao68000 short circuit cases.
2021-06-02 14:53:45 +02:00
Jean-Paul Chaput d2e1ab3796 Add rgetInstanceMatching to utilities, as reminder and for later use. 2021-06-02 14:16:45 +02:00
Jean-Paul Chaput 1afc48fb4c Forgot to update pointers to merged nets in BlifParser. 2021-06-02 14:14:32 +02:00
Jean-Paul Chaput db26e14358 Add -fsanitize=address to the DEBUG flags. 2021-06-02 14:14:11 +02:00
Jean-Paul Chaput fed586385c Do not connect HTree to I/O pad if the net is internal.
* Bug: In Cumulus/plugins.chip.powerplane.Builder._connectHTree(), is was
    previously assumed that a net manged by a H-Tree was always coming from
    the outside (i.e. a clock or a reset signal).
      It is no longer the case, for example with the PLL internally generated
    clock.
      So prune internal signals in this method.
2021-06-02 14:13:53 +02:00
Jean-Paul Chaput ef004a955b Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2021-05-31 00:07:15 +02:00
Jean-Paul Chaput 205a6877db More generic H-Tree support to accomodate the LS180 PLL internal clock.
The H-Tree support is now allowed for any net, not only the clocks and
not only top-level nets. This allow to better management of the LS180
internal clock signal.

* New: In Cell::flattenNets(Instance*,set<string>,uint64_t) new overload
    of the function to allow the user to select nets that will *not*
    be flattened. This makes the NoClockFlatten flag effectively obsolete,
    we keep it for backward compatibility.
      The net names can be of non top level ones. In that case, they must
    use the name an HyperNet will get (the Occurrence name). For example:
         "instance1.instance2.deep_net_name".
* New: In PyCell, update the wrapper for the new parameter of flattenNets(),
    new utility function pyListToStringSet() to translate a Python list into
    a C++ set of names.
* New: In EtesianEngine, add support for a list of nets to be excluded
    from the flattening procedure. Those excluded nets will also be
    excludeds from the Coloquinte nets *and* HFNS synthesis, as they
    are likely to be manageds by a H-Tree.
* Change: In AnabaticEngine::_loadGrByNet(), now also skip nets that are
    flagged as manually detailed route.
* New: In AnabaticEngine::antennaProtect(), do not try to insert diodes
    on nets that are already fixed or detaled route. This replace the
    clock exclusion.
* New: In cumulus/plugins.{block,htree,chip}, replace the concept
    of clock-tree by the more generic H-Tree. That is, we can ask the P&R
    to create H-Tree on any net of the design, not only the ones matcheds
    as clock. The net does not even need to be top-level.
      This is to manage the PLL internal clock generated by the PLL in
    the LS180 chip.
      Start to change all reference to "clock" into "H-Tree".
* Bug: In cumulus/plugins.chip.powerplanes.Builder._connectHTree(),
    there was an inversion of the H & V routing gauges to compute the
    track into which put the H-Tree center to corona edge wiring.
      This was causing tracks to be used twice, seen in the ao68000 test
    bench.
2021-05-31 00:02:23 +02:00
Luke Kenneth Casson Leighton 93ac03af07 repeat debug information when net direction changes
some debug info is printed out if an OUTPUT net direction is reversed
repeated the same code for an INPUT net
2021-05-27 13:57:08 +00:00
Jean-Paul Chaput 5b6bc7c91b Add & fix GDS parser for PATH of type 4 (seen in the PLL).
* New: In CRL::GdsStream::xyToPath(), now manage BGNEXTN & ENDEXTN for
    PATHTYPE 4.
      The begin/end Contact are created to use exactly the area of the
    extension. Otherwise there were overspill when the size of the
    extension is greater than the width of the path. Also need to do
    a sligth shift if the extension is an odd number of foundry grid.
      This fix the offgrid problems.
2021-05-25 15:08:57 +02:00
Jean-Paul Chaput 39231d5191 Allow to enable/disable minimal size checking in Contact CTOR. 2021-05-25 14:56:07 +02:00
Jean-Paul Chaput 1bff74a56e Use simple pattern matching in Block._rgetInstance() (LKCL). 2021-05-22 22:10:26 +02:00
Jean-Paul Chaput 3858461beb Added support for analog pad in Core2Chip & libresocio. 2021-05-22 15:22:40 +02:00
Jean-Paul Chaput fd67ca6cda Correct handling of block orientation in block.py & macro.py.
* Bug: In cumulus/plugins.macro.Macro.__init__(), stick out the rigth number
    of pitches on North & East sides (never tested before).
* New: In cumulus/plugins.macro.Macro.__init__(), manage layer change
    if the terminal is not in the preferred routing direction. Use BigVia
    and put at least two cuts.
2021-05-22 15:21:26 +02:00
Jean-Paul Chaput d4c3cf7dbb More accurate antenna management in Anabatic.
* New: In Anabatic::DiodeWire, use "antennaDiodeMaxWL" to compute the number
    of diodes to insert in a wire only cluster. Use boxes instead of segments
    to define the area as segments can be splitted by the diodes inserteds
    at the DiodeRps stage.
* New: In DiodeWire::createDiodes(), specific diode insertion method.
    Try to instert first in long horizontal wires.
2021-05-22 15:14:32 +02:00
Jean-Paul Chaput dbdef9901f Separate the antenna max. WL into two distinct settings.
Split "antennaMaxWL" into :
* "etesian.antennaGateMaxWL"  : max length *without* any diode.
* "etesian.antennaDiodeMaxWL" : max length that *one* diode can support.
2021-05-22 15:04:13 +02:00
Jean-Paul Chaput 4b2c120478 More comprehensive warning for offgrid shapes in GdsStream::xyToComponent(). 2021-05-22 14:57:25 +02:00
Jean-Paul Chaput 90300eb651 Small typo in Cell::getComponentsUnder() Python wrapper. 2021-05-22 14:54:36 +02:00
Jean-Paul Chaput 8ce16add53 Add a "forced halo" to diode clusters.
When a long *horizontal* wire connect to a cluster, an antenna effect
may be created *before* the METAL3 is deposited, if the cluster's diode
is not *directly* connected to the gate through *only* METAL2. So, we
add a "forced halo" where the long horizontal connecting wires will be
broken by a diode *near* the gate. This problem do not occur for long
connecting METAL3, as the diode will be connected by then. Note that
we are hard-coding the gauge routing direction in the algorithm.
  With that modification, only one antenna effect remains in LibreSOC
LS180. May be corrected by post-treatement.

* New: In Anabatic::DiodeCluster::mergeForcedhalo() add specific secondary
    areas where diode must be insterted in addition to the one of the
    RroutingPad cluster. To "isolate" the cluster from long horizontal
    wires.
2021-05-13 12:20:28 +02:00
Jean-Paul Chaput 7ffe75110b Fix, again, the save procedure in cumulus/plugins.chip & block.
* Bug: In cumulus/plugins.chip.Chip.save(), now completely delegate the
    saving procedure to the base class (i.e. Block.save() which is
    BlockConf.save()).
* Bug/Change: In cumulus/plugins.block.configuration.BlockConf.save(),
    Now manage all the configutation, whether it is a simple block or
    a whole chip.
      In the case of a whole chip we must force the saving on both
    chip and corona as the later, being P&R will be seen as a terminal
    block and not recursively saved.
2021-05-12 12:12:52 +02:00
Jean-Paul Chaput c80e99c0a1 Create clusters for wire only chunks and add diodes if they are too long.
Protecting clusters of sinks is not enough. There can be very long
wires that far exceed the protection capacity of one diode. Instead
of putting a bunch of diodes near the sinks, we choose to put them
regularly along the interconncting wires.
  With this approach we are down to 7 antenna violations on LibreSOC
LS180 test chip.
  This will get less good results on arlet6502 & ao6800 because of the
core being a long way from the I/O pads. Should create jumpers on thoses,
but it is for later.
2021-05-11 14:30:38 +02:00
Jean-Paul Chaput 7ad26f1a37 Ignore short overlaping same-net segments in realign stage.
* Change: In Track::addOverlapCost(), in some configuration, we can
    have two overlapping short segments that can *both* be realigned.
    But they prevent that because we account their shared length on
    the track.
      So now, in realign mode only, do not account same-net shared
    length if the segment length is less than *two perpandicular pitches*.
      This helps the antenna protection by making the diode connected
    directly to METAL2 long stripes, and not keeping them isolated.
2021-05-11 14:30:10 +02:00
Jean-Paul Chaput ef8133b1c6 Correct renaming/save ordering in cumulus/plugins.chip.Chip.save() (again). 2021-05-11 14:13:00 +02:00
Jean-Paul Chaput 28c8af27be Fix memory corruption due to the deletion of unused spare buffers.
* In cumulus/plugins.block.Block.{place,doPnr}(), reorder the
    feed insertion and spare buffer deletion call. Formerly, we
    were :
      1. Creating spare buffersa (Python).
      2. Placing (C++)
      3. Adding feeds (EtesianEngine::toHurricane() call) (C++).
      4. Removing unused spare buffers (Python).
   So, step 4 was *not* informing the C++ placement data-structure
   created at step 3 of the change. Resulting in occurrences using
   deleted Entities (Instance).
     Now we swap step 3. and 4. so toHurricane() is called *after*
   any Python managed change is done.
     Ideally, what we should implement is a way for Python to inform
   the C++ data-structure. No real problem here, but time...
2021-05-11 14:11:43 +02:00
Jean-Paul Chaput 972787c81e Fix memory corruption in Etesian::Area, separate it's creation.
* In Etesian::Slice::createDiodeUnder(), delete the Instance *after*
    removing the tile referring it. This was working, unless we
    active the debug mode which tries to print the Tile's instance.
* In EtesianEngine::place(), no longer call toHurricane() at the
    end of the placement. Must now be done as a separate step.
    Exported to Python interface.
      This fix is related to the spare buffer removal memory
    corruption
2021-05-11 14:00:04 +02:00
Jean-Paul Chaput 079f4c2009 Fix unitialized stat structure in Vlsisapd, Path::mode() (valgrind). 2021-05-11 13:46:53 +02:00
Jean-Paul Chaput c137c1ac5b Do not account self-segment in track cost calculation.
* Change: In Katana::Track::addOverlapCost(), if an overlaping segment
    is owned by the net *and* is the one we want to insert, do not take
    it into account in the shared length.
      This case never occured before we introduced the "realign" stage,
    as a to be inserted segment, was, by definition, not already
    inserted in a track. But in the realign stage, it is. So we should
    not account it when computing the insertion cost in the track it
    is already in. This was preventing short segments (less than a
    pitch) to be correctly re-aligned.
      And, as a side effect, preventing the antenna/diodes to work as
    intended (diode connected at METAL3 layer while the antenna occur
    at METAL2 layer).
2021-05-09 11:03:09 +02:00
Jean-Paul Chaput e50426a5bc Fix saving order in cumulus/chip.py to get right core instance name. 2021-05-09 11:02:39 +02:00
Jean-Paul Chaput 1fb433d9ac Stop saving AP files when working in real mode.
* Change: In cumulus/plugins.block.configuration.Configuration.save()
    and cumulus/plugins.chip.Chip.save(), according to the kind of
    routing gauge we are using (symbolic or real), either recursively
    save all the layouts (AP symbolic files) or only the top-level
    GDSII (which embed all the hierarchy) one.
2021-05-04 19:31:34 +02:00
Jean-Paul Chaput bb5c99247a Complete rewrite of the diode insertion algorithm.
First part of the antenna effect protection : diode insertions.
Anabatic::antennaProtect(Net*) and it's supporting infrastructure
has been rewritten & simplificated. Must be used in conjuction
with the "Flexlib" bloat model of Etesian. A cursory description
of the algorithm has been added in the source file.

* New: GCell::hasNet() to tell if net is going through a GCell,
    either as a straigth wire or has a local GContact (turn,
    branch, terminal).
* New: Etesian::BloatFlexib class (tagged "Flexlib") suited for
    flexlib uses. It is derived from "nsxlib".
      To have enough space to insert all the wanted diodes, we
    enlarge "mx2_x2" & "mx3_x2" of resp. 1 and 2 pitches.
      This is an empiric finding, Yosys seems very fond of thoses
    gates and we often see them underneath area where no space
    was available to put a diode... May need some more fine grained
    analysis.
2021-05-04 19:31:12 +02:00
Jean-Paul Chaput 44f716c4a2 Perform only one connexion to the power supplies and the corona ring.
* Bug: In cumulus/plugins.chip.pads, we were connecting the ground and
    power supplies to all the horizontal wires in the corona ring.
    But, when there are more than one and especially at the outer
    border of the pad, the vertical connecting wire will create
    various shorts over the pad.
      Now we connect only to the innermost horizontal wire only.
    Had to chech if the core side of the pad is north or south.
2021-04-28 23:38:32 +02:00
Jean-Paul Chaput e2d0188543 Fix net creation/lookup ordering in cumulus/core2chip (fuse vss & iovss). 2021-04-28 14:24:47 +02:00
Jean-Paul Chaput 89a45180c1 In cumulus/core2chip, suppress "iovss", everything is connected to "vss". 2021-04-28 13:35:48 +02:00
Jean-Paul Chaput dcfba9ef18 Export Catalog::State creation support to Python.
* New: In CRL::PyCatalog, add the second parameter "add" to getState()
    so we can request the creation of the state if needed.
* New: In CRL::PyCatalogState, export setCell() and setInMemory() methods.
* Bug: In CRL::Subckt::createModel(), when a cell has a State entry in
    the catalog, also check that it really has a Cell loaded in memory.
    If not, throw an exception (and do not crash).
2021-04-28 12:58:47 +02:00
Jean-Paul Chaput 39d8aa479e In cumulus/plugins.macro, check for the SRAM name in both upper/lower cases. 2021-04-24 12:59:13 +02:00
Jean-Paul Chaput 440b71f727 In cumulus/plugins.block.Block.placeMacro(), move messages into trace mode. 2021-04-24 12:58:51 +02:00
Jean-Paul Chaput 5cba995549 In cumulus/plugins.chip.powerplane, check for too-narrow power contacts. 2021-04-24 12:58:22 +02:00
Jean-Paul Chaput 8d54a9cc29 In Etesian::Placement, reduce the number of warnings in case of misaligned block. 2021-04-24 12:56:32 +02:00
Jean-Paul Chaput 496cc00304 In Katana, Adjust the moveUp cases in SegmentFsm/Manipulator.
* Change: In SegmentFsm::_slackenLocal(), in the Minimize state, when
    the segment is fully blocked *and* has *lot* of candidate tracks,
    that means that it is up against a *massive* blockage (i.e. a macro
    block). In that case, try to move up (to go *over* it).
      Previous behavior was to go straight to Inimplemented state.
* Change: In SegmentFsm::_slackenGlobal(), manage fully blocked
    global segments. But finally, this configuration didn't arise.
* Change: In Manipulator::moveUp(), restore the management of the
    AllowLocalMoveUp flag, to be able to move up local segments
    (needed by SegmentFsm::_slackenLocal()).
2021-04-24 12:56:16 +02:00
Jean-Paul Chaput 79f5b3db08 In AutoSegment::canMoveUp(), increase to 2 the added penalty under FlexLib. 2021-04-24 12:55:47 +02:00
Jean-Paul Chaput decc4745d2 Add a RoutingLayerGauge.setType() and export to Python (finally unused). 2021-04-24 12:55:17 +02:00
Jean-Paul Chaput 0640586cbc In CRL::VstDriver, name-mangle file names too with option UniquifyUpperCase.
* Bug: In CRL::vstDriver(), when upper case names are uniquified, including
    components, the associated model filename must also be mangled.
2021-04-22 15:14:06 +02:00
Jean-Paul Chaput 03a52977d3 Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel 2021-04-21 17:01:55 +02:00
Jean-Paul Chaput 37f311ac7d Don't remembers what thoses do, but don't want to loose them either. 2021-04-21 17:00:48 +02:00
Luke Kenneth Casson Leighton 7ba68a0718 whoops, sorry... 2021-04-21 14:30:58 +00:00
Luke Kenneth Casson Leighton 8932bcf7bc add BigVia.AllowAllExpand to all corona pads.
this is already done elsewhere BigVia is used.
no reason not to also use it in corona
2021-04-21 14:07:29 +00:00
Jean-Paul Chaput d10961b585 Put the clock tree connecting wires farther apart from the corona border.
* Bug: In cumulus/plugins.chip.powerplane, while building the connexion
    from the corona border to the root of the HTree, the horizontal
    wire at the top was too close from the border causing a minimal
    spacing error in the DRC. Now put two tracks of distance.
2021-04-21 14:16:53 +02:00
Jean-Paul Chaput f2f5f687d0 Shrink macro block external pins.
* Bug: In cumulus/plugins.macro.Macro, external west/east segments where
    slightly too long and conflicted with the METAL2 blockage.
2021-04-21 14:16:26 +02:00
Jean-Paul Chaput f4514cecf3 Use Track::repair() to solve overlaps.
* New: In Track::repair(), the gapset was used to *close* same-net gaps
   is now alos used to restore minimal spacing between different nets.
   Seems to be not fully working yet.
2021-04-21 13:51:33 +02:00
Jean-Paul Chaput a05bd81bab Complete reorganization of where the routing stage is stored in Katana.
* In KatanaEngine:
    - Former situation:
        Each RoutingEvent did store the routing stage it was in. And it
        was misnamed "mode".
    - New organization:
        The routing stage is stored in KatanaEngine itself. It can be
	accessed through a proxy in Session.
* Change: In DataNegociate::update(), when in Realign stage and computing
    non-preferred perpnadicular routing *do not* expand of one pitch
    outside the RoutingPad range.
2021-04-21 13:51:08 +02:00
Jean-Paul Chaput 493ed1ea11 In AutoSegment::canMoveUp(), adjust balance for FlexLib M2/M4.
* Change: In AutoSegment::canMoveUp(), hard code for FlexLib a track
    reserve of one when trying to move up.
      In FlexLib, the router promotes too easily METAL2 towards METAL4,
    clogging the higher level. So we end up with the METAL2 level
    under-saturated and the METAL4 over saturated, leading to routing
    failures.
      Now we assume that there is "one track less available" in METAL4.
      As for now, solves the problem for LibreSOC.
2021-04-21 13:49:41 +02:00
Jean-Paul Chaput ab908b8c44 Issue an early warning for offgrid coordinates in GdsParser. 2021-04-19 14:29:23 +02:00
Jean-Paul Chaput cd4f797831 Export terminal of I/O pads at chip level. 2021-04-19 14:26:29 +02:00
Jean-Paul Chaput 3b6b588a74 Manage pads for external components in CRL::GdsParser.
* New: In CRM::GdsSteam::makeExternals(), now take into accounts Pad
    for Net external components. Also delete the original components
    after creating the copy in the right Net.
      So now the PLL terminals are correctly seen.
2021-04-18 20:37:19 +02:00
Jean-Paul Chaput 7d1e1f8c44 Adjust again the interface of the SRAM block (METAL2 stick out more). 2021-04-18 20:36:57 +02:00
Jean-Paul Chaput 2084a3bde2 Bad computation of the track axis for fixed in NetBuilderHV::_do_xG_1PinM2().
* Bug: In NetBuilderHV::_do_xG_1PinM2(), for METAL2 pins on the EAST
    side, we were computing the track from the XMax position of the
    GCell. Now, with complete discoupling of the routing pitches and
    GCell size, this is most of the time false.
      Replace with a true computation of the last track of routing
    area.
2021-04-18 20:36:44 +02:00
Jean-Paul Chaput 2019fa25d7 Fix crash when getting the free interval around a TrackSegment.
* Bug: In TrackSegment::getFreeInterval(), if, for whatever reason,
    a discrepency happens between the TrackSegment and the Track,
    that is the _track fields point to a *wrong* Track. Then the
    index lookup will fail (Track::npos), so return an all-span
    interval instead of trying to expand it and crash (out of
    bound).
2021-04-18 20:36:20 +02:00
Jean-Paul Chaput 444cc777e5 Fix topological bug in NetBuilderHV::_do_xG_1PinM2().
* Bug: In NetBuilderHV::_do_xG_1PinM2(), when the M2 pin is on the *east*
    side and there are three globals, we must swap htee1 & htee2.
      Otherwise, we the SW/NE contacts do not have the right numbers
    of free segments attach.
* New: In AnabaticEngine::cleanupGlobal(), check that no global component
    is left behind, sure sign that the global to detailed building went
    wrong.
2021-04-17 13:03:15 +02:00
Jean-Paul Chaput 445f5161da Increase again blockages area over SRAMs blocks. 2021-04-17 12:56:40 +02:00
Jean-Paul Chaput b0cfe8fc82 Fix bad spacing of the rightmost power lines (just a sign error). 2021-04-17 12:54:49 +02:00
Luke Kenneth Casson Leighton aeb9d7d4e5 blif2vst.py naming of components needs to be munged
https://gitlab.lip6.fr/vlsi-eda/coriolis/-/issues/36

Signed-off-by: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
2021-04-16 12:41:39 +00:00
Luke Kenneth Casson Leighton 628ff1ae06 correct direction of core-to-corona gpio pad connections for Net.Direction.IN
cumulus/src/plugins/alpha/core2chip/core2chip.py

Signed-off-by: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
2021-04-16 12:19:41 +00:00
Jean-Paul Chaput cc2137ec4f Check that the core is wide enough to accomodate at least one middle power line. 2021-04-16 11:43:22 +02:00
Jean-Paul Chaput 9800c0ad3d Correct my botched patch on Etesian::HFNS buffer vs. net naming. 2021-04-16 10:31:49 +02:00
Jean-Paul Chaput 8279e76070 In Etesian, set correct direction for buffereds HFNS nets.
* Bug: In Etesian::HFNS::Cluster, all the created nets were systematically
    created in the IN direction, which is obviously wrong for the driver.
      Now Slice::raddTransPlug() accept a third argument stating if we are
    creating a driver or a sink. Direction of the net is now combining
    and can be IN, OUT or sometimes INOUT.
      The VHDL files where reflecting that problem and made GHDL choke.
* Change: In Etesian::HFNS::Cluster, prefix the instance name by "cmpt_"
    so it doesn't clash with the signal name in VHDL.
2021-04-16 00:05:04 +02:00
Jean-Paul Chaput 813d0860fd In Etesian::Placement, ensure that the tie in holes are pitcheds.
* Bug: In Etesian::Placement::Slice::fillHole(), do not use the xmin
    previous bound, but pitch it (by excess). Insert ties *only* if
    they completely fit in the free space.
      This bug was showing *between* two SRAMs side-by-side, a column
    of tie was inserted...
2021-04-15 23:55:29 +02:00
Jean-Paul Chaput 7f41cd73c7 In EtesianEngine::toColoquinte(), increase the buf_x8 size to solve DRC/LUP. 2021-04-15 23:50:54 +02:00
Jean-Paul Chaput 20efd75a32 More accurate detection of zero-length segments.in AutoSegment::canReduce(). 2021-04-15 23:47:21 +02:00
Jean-Paul Chaput 95713ac66b Align power lines on QuadTree leaf area centers (X).
* Bug: In cumulus/plugins.block.block.py, always import Python modules
    using the exact same path. Otherwise the module may get imported
    twice and static variables are duplicated, generating a big mess.
      This was causing problem for the LUT in macro.py, and got SRAMs
    blocks encapsulated twice.
* New: In cumulus/plugins.block.block.Block.addPlaceHolder(), create
    a "place holder" instance over a given area to prevent the placer
    from using it. Allow to make space reservation.
* New: In cumulus/plugins.block.configuration.BlockConf, copy the
    toXPitch() and toYSlice() methods from spare in order to share
    them between modules. Still have to remove some other local copies.
* New: In cumulus/plugins.block.spare.QuadTree, keep a list of all
    the X centers of the partitionned areas. For yse by the power lines.
* New: In cumulus/plugins.chip.chip, move doPowerLayout() call from
    doChipFloorplan() to doConnectCore(), this is to delay the call
    until *after* the spare QuadTree has been created and we can
    align the power lines to the centers of the QuadTree.
* New: In cumulus/plugins.chip.pads.Corona.doPowerLayout(), if a
    spare QuadTree has been created, align the power lines on the
    X center of the leaf areas. This is a cheap way to avoid DRC
    errors between the power BigVias and the wires from the various
    clock trees (on METAL5).
* New: In cumulus/plugins.block.macro, add an ad-hoc patch for Staf's
    SRAMs. The blockage areas are slightly too narrow. We enlarge
    them by one pitch.
2021-04-15 23:44:19 +02:00
Jean-Paul Chaput dd28bbba7a Comment out debug messages in GdsDriver & GdsParser. 2021-04-15 23:22:07 +02:00
Jean-Paul Chaput 2002282483 Add a zero-length segment compaction stage in Anabatic DTOR.
* New: In AnabaticEngine::_gutAnabatic(), perform progessive compaction
    of segment of null length.
      CAUTION: Reduced segments *may* not be null length segments.
               They are "less or equal" than one perpandicular pitch and
	       can have their layer put into the perpandicular one.
                 They non-null one *must* be excluded for the compaction.
      Null segments are compacted starting from the one connecteds to
   non-null length segments. This is to avoid the compaction starting
   in the middle of a whole set of zero-segments that will block further
   compaction.
     This behavior was causing "zero-length" segment on orphaned layers
   that were causing minumal area DRC errors.
* Change: AutoSegment::canReduce() is modified so it now takes a flag
    argument to tell it to look for collapisble zero-length segments.
* New: AutoSegment::getNonReduceds(): returns the number of non-zero
    length segments connecteds to the current one.
* Change: In AutoSegment::reduceDoglegLayer(), use the perpandicular
    width of the routing layer instead of the regular (parallel) one.
      This was causing DRC errors.
2021-04-12 23:50:25 +02:00
Jean-Paul Chaput 2f24c05a72 Fix bug in Track::repair(), select the right segment to extend. 2021-04-12 23:34:55 +02:00
Jean-Paul Chaput a66da90446 Never reduce METAL2 short wires to METAL1.
* Change: In AutoSegment::canReduce(), no longer allow short METAL2
    connected only to VIA12 to be reduced in METAL1, as we do not
    control the METAL1 level of layers. This problem started to
    show when connecting to diodes (antenna).
      Should get rid of METAL1 DRC violations.
2021-04-10 19:51:50 +02:00
Jean-Paul Chaput 81fffb9d0a Add a new Track finishing stage: close short gaps of same nets wires.
* New: In Track::repair(), short gaps between segments of the same
    nets where occuring and being not detected. This was causing
    DRC minimal distance violations. Now, fuse the segments when
    they are too close. Done by extenting the duSource of the
    rightmost one to the leftlost one.
       Create ancillary class GapSet to manage the gaps of the
    various segment of the same net.
2021-04-10 19:51:19 +02:00
Jean-Paul Chaput d3ee38b01e Forgot to update root clocktree wiring for block-only routing. 2021-04-10 19:41:30 +02:00
Jean-Paul Chaput 3276950ec4 Prefix all Cell from a GDS file with "gds_" to avoid cell overload.
* Bug: In CRL::GdsParser, the PLL was using copies of the standard cell
    with the same name. And unfortunately, they where found *before*
    the FlexLib one when using DataBase::getCell(). As their I/O where
    wrong it was leading to a massive netlist connexion corruption in
    blif2vst.
      To avoid that, any Cell created by the GDS parser is now prefixed
    by "gds_".
* Change: In CRL::GdsStream CTOR, report when the file cannot be opened
    instead of saying that the GDS file is corrupted (misleading).
2021-04-09 13:55:08 +02:00
Jean-Paul Chaput 3eb3f52bc8 Refining check in AutoSegment::isMiddleStack().
* Change: In AutoSegment::isMiddleStack(), reject configurations where
    we have a Tee in the same direction as the segment. That is, (HTee + H)
    or (VTee + V). It is unlikely that the two segments of the tee will
    be of null size.
2021-04-09 13:54:46 +02:00
Jean-Paul Chaput 2a1f014491 Added a new post-routing stage "realign" in Katana.
When a segment is placed only once (which is to say it is nerver ripped
up) it can sometimes end-up in a non-optimal place. We now add a stage
in Katana where each segment is "re-placed" in order to maximise
alignment on it's neighbor. This is a new stage added to both
RoutingEvent and NegociateWidow. Segments are replaced *only* in free
space, they will not ripup *other* segments, except for their own
perpandiculars. We exclude from re-placement globals (unlikely to move)
and segment that have reduced perpandiculars which *must* not be elongated
and potentially raised.
  Add a new katana setting to enable/disable the realign stage (enabled
by default:
    - "katana.runRealignStage" ( = True )
2021-04-08 15:10:14 +02:00
Jean-Paul Chaput 4b6da7bde9 Suppress uneeded debug output in Cumulus/plugins.chip.pads. 2021-04-08 15:09:41 +02:00
Jean-Paul Chaput 31d6a45702 In Cumulus/plugins.block.iospecs, add IoPin.START and END to auto-load specs.
Contributed by LKCL.
2021-04-08 11:22:12 +02:00
Jean-Paul Chaput 556c38e4b9 Bug in spares.py, "rtag", the root was repeated in each level. 2021-04-07 14:51:32 +02:00
Jean-Paul Chaput df4201e1fe Manage a minimum spacing between I/O pads at chip level.
* Change: In Cumulus/plupins.chip.pads.Side, in some case (LibreSOCIOPads),
    when not put side by side, the I/O pads must be separated by a
    minimal distance.
      Introduce the new configuration parameter:
        cfg.chip.minPadSpacing
      Disabled if zero or non-defined.
      Fix NWELL DRC errors for TSMC.
2021-04-07 14:51:16 +02:00
Jean-Paul Chaput a2525f2260 More accurate detection of small metal srips for minimum area.
* Change: In AutoSegment::isMiddlestack(), we where previously only
    detecting (turn+turn) or (turn+terminal) topologies. This was
    too restrictive. Added (terminal+XTee) when the tee is perpandicular
    to the segment, for example horizontal + VTee.
      Fix minimal area DRC error in METAL2 for TSMC.
2021-04-07 14:50:42 +02:00
Jean-Paul Chaput e6f18a95d3 Fix vector mapping in VHDL portmap. one/zero names in BlifParser.
* Bug: In Vhdl::VhdlPortmap::toVhdlPortMap(), when the mapped names
    are part of a vector, but *not* in the "downto" direction,
    unvectorize anyway. In the component declarations, vectors are
    always in "downto" order, so they must also be mapped in that
    order.
* Bug: In CRL::BlifParser::newOne() & newZero(), we have to create
    signal names different from instance names for VHDL compliance.
    This is complementary to what is done in blif2vst.
      No completely satisfied with that. Should find a more generic
    way to do it in the future.
2021-04-06 18:19:16 +02:00
Jean-Paul Chaput ec3c22547a Bug fixes in the VST/VHDL driver coupled with BlifParser.
* Change: In Hurricane::NetAlias, store additional data in NetAliasName,
    the external status of the former Net. When a Net::merge() is
    performed, we must keep track of whether the merged (destroyed)
    one was external and keep that information.
      Add NetAliasHook::isExternal() & NetAliasHook::setExternal()
    virtual methods.
* Change: In Net::getNet() add a new optional argument to allow the
    search of the net name in *internal* aliases. Otherwise only the
    aliases tagged as *external* will be searched.
      It was a bug that, when looking for a Plug master net by name
    we got an homonymous internal net. In that case we must only
    look for net that are (or where) part of the interface.
* New: In Vhdl::VectorSignal, when a vector contains only one bit,
    unvectorize it, like when it is non-contiguous (we use the
    isCountiguous() method to carry that information).
* New: In Vhdl::VhdlEntity, Catalog::State and NamingScheme, added
    a flag UniquifyUpperCase to uniquify the names in uppercases.
    In case of a clash with the same name in lowercase.
      Prepend 'u' before all previously uppercased letter. For
    example 'VexRiscV' becomes 'uvexuriscuv' (urgh!).
      The Catalog flags is exported to Python for use by the blif2vst
    script.
* Change: In BlifParser, Model::newOne() and Model::newZero(), return
    a new gate each time it is called instead of making just one for
    each Model. This way, if two outside nets are connected to one
    or zero they do not get merged (should work, but will be less
    clear).
* Bug: In BlifParser, Model::connectSubckts(), when looking for the
    master net in the instances models (by name), limit the search
    to the *external* aliases names.
* Change: In NamingScheme::vlogTovhdl(), reactivate the removal of
    two consecutive '_'.
* Change: In cumulus/bin/blif2vst.py, prefix the master cells
    (i.e. components) with 'cmpt_' to avoid clash names with signals
    in VHDL.
2021-04-05 23:53:44 +02:00
Jean-Paul Chaput 08d1db5dd6 Rewrite support for minimum area metal wires (stacked VIAs).
We use the segments extensions (dxTarget & dyTarget) to enlarge if
needed the segments. This new implementation is completely at
Anabatic level and should not be seen (i.e. managed) at Katana level.

* Change: In AutoHorizontal & AutoVertical, change the semantic of
    getSourceU() and getTargetU(). formerly they where the end
    position of the segment (with extension included), now they
    gives the position of the anchor contacts, that is the axis
    of the perpandiculars.
* New: AutoSegment::getLength() is still a proxy toward the
     Segment::getLength() which returns the length of segment with
     dxSource & dxTarget. We introduce a getAnchoredlength()
     which returns the length between the centers of the S/T
     anchors. That is axis to axis.
       This is this length which is now used througout Anabatic.
* New: In AutoSegment::_extentionCaps, add a fourth item to hold
    the segment minimal length (to respect minimal area given
    the wire width).
* New: In AutoSegment::getExtensionCap(), if the segment has
    a non-zero S/T extension, returns it instead of the S/T
    contact extension *if it is greated*. The check of the
    extension can be disabled by the Flag::NoSegExt flag.
* Change: In AutoSegment::isMiddleStack(), security check on
    the presence of source and targets. More accurate detection
    of perpandicular in "same layer" with a non-zero length,
    So the area is OK, even with a short segment.
* New: AutoSegment::expandToMinLength(), check if a segment is
    under the minimal length and expand it if need be by playing
    with the dxTarget & dxSource. Tag minimal segments with the
    AutoSegment::SegAtMinArea flag. Also try to keep the segment
    *inside* it's former (supposedly wider) interval.
* New: AutoSegment::unexpandToMinLength(), to be called on a
    formerly minimal sized segment which as grown up. Reset
    it's S/T extensions to zero and unset the flag SegAtMinArea.
* Change: In AutoHorizontal::updateOrient(), when the extension
    are non-zero, also swap them if needed, to keep the exact
    footprint of the segment.
* New: In AutoSegment::revalidate(), check that the segment
    respect the minimal length (area), and expand it if needed.
      Conversely, if the segment has grown up from a minimal
    length state, reset it's extensions to zero.
* Change: In Anabatic::Session::revalidate(), invalidateds
    segments are now sorted in such a way that the "middle stack"
    ones are revalidateds last. Not recall 100% why...
* New: In Katana::TrackCost, add a computation of the free interval
    length we are into (if any). Not used yet, keep it for future
    use.
* Change: In KatanaEngine::finalizeLayout(), remove the call to
    segments minimum area protection. It is now obsoleted by the
    new implementation in Anabatic.
* Change: In Track::check(), call the minimum size/area checker
    Track::checkMinArea().
2021-04-05 00:01:54 +02:00
Jean-Paul Chaput 0326d513bd Use the extention cap in Anabatic to ensure the METAL minimum area.
* New: In AutoSegment::getExtensionCap(), when a routing layer has a
    minimal area defined, compute the minimal wire length (given it's
    width). Then, for segments identified as "MiddleStack" (local
    with turns at each end towards opposite layers), if their length
    is below minimal, return a longer extention cap.
      This may be optimized because with this, the segment extension
    is symmetric on both side while it could be made assymetric.
2021-04-01 08:46:02 +02:00
Jean-Paul Chaput 5311050438 Fix various bugs in the RoutingPad stack creation/positionning.
* Bug: In Cumulus/plugins.block.configuration.GaugeConf.rpAcces(), start
    building the stack of contacts + short segments straps from the
    layer of the RoutingPad and *not* from the first layer of the
    RoutinhGauge.
* Bug: In Cumulus/plugins.block.configuration.GaugeConf.setStackPosition(),
    Only align in the RoutingLayer gauge direction of the top layer of
    the stack. For example, METAL2(H) will be y aligned or METAL3(V)
    will be x aligned.
* Bug: In Cumulus/plugins.chip.powerplane.Builder._connectClock(),
    forgot to call expandMinArea() on the pinRp contact stack.
2021-03-31 01:58:23 +02:00
Jean-Paul Chaput b9c6b5dd80 Duplicate external compoenents in CRL::GdsDriver to please "Vendor" StreamIn.
* Change: In CRL::GdsStream::operator<<(Cell*),  external components needs
    to be exported twice. First as "METALx.pin" to signal an external
    component (and give it's name). And second as a "normal" component
    in "METALx". If the METALx part is forgotten, the "Vendor" StreamIn
    will not see the METALx.pin as something physical so f***g gaps appears
    in the wiring. And furthermore, if the TEXT label is above it, the
    name of the net goes away...
2021-03-31 01:46:21 +02:00
Jean-Paul Chaput a81f6b27f5 Temporarily remove chip size checking in chip.configuration. 2021-03-30 11:37:32 +02:00
Jean-Paul Chaput 946cba8209 Add a register count in Etesian initialization, just for stats. 2021-03-30 11:36:25 +02:00
Jean-Paul Chaput 2140737e10 In Anabatic::antennaProtect(), error in computing the diode GCell location. 2021-03-29 19:03:26 +02:00
Jean-Paul Chaput 109b2e4dee Opaque blocks area was not taken into account in EtesianEngine::toHurricane().
* Bug: In EtesianEngine::toHurricane(), when looping over the AB of all the
    FIXED instances occurrences, we where excluding contained AB instead of
    merging them...
2021-03-29 16:55:54 +02:00
Jean-Paul Chaput 9dc0040703 Support for non complete clock-tree to fill every nook and cranny.
* Change: In Cumulus/plugins.block.spares, allow the QuadTree to have
    only *some* of it's four childs (BL, TL, TR, BR).
      Modify QuandTree.getLeafUnder() so when there is no leaf under
    the point, due to an incomplete tree, we get the closer leaf.
      Leaf are suppressed when their center points (where the buffers
    are to be put) are under a FIXED Instance (that is, an opaque block).
      Those opaque blocks (or macro blocks) must be put *on the periphery*
    of the design, because the closer they got to the center, the larger
    the chunks of QuadTree that are removeds.
* Change: In Cumulus/plugins.block.clocktree, based on the spare
    QuadTree changes, can now build a clock-tree with some of the
    leaf missing. Should find a way to compensate for the missing
    leaf wires & buffer (dummies).
2021-03-29 16:49:00 +02:00
Jean-Paul Chaput f4891a0aee Added a "Matrix Placer" in Cumulus.
* New: In Cumulus/plugins.block.matrix.RegisterMatrix, based on pattern
    matching the output of DFF, allow to rebuild and place a matrix of
    DFF constituting a RAM.
      It finally proven not useful because it is a too naive approach.
    Intermediate gates (buf_x2) must be found too. Most of the control
    signals have more than 20 sinks so gets splitted by HFNS and lastly,
    we would want the decoder to be integrated too, but they are not
    regulars.
      The right way to do it is to create a generator that build it
    then expose it in a way nMigen can understand (not the other way
    around, nMigen -> Yosys).
2021-03-29 16:36:16 +02:00
Jean-Paul Chaput fa4084f3d9 Added computation and display of the effective space margin in Etesian. 2021-03-24 23:22:03 +01:00
Jean-Paul Chaput f89e4ed467 In cumulus/plugins.block.Block, make use of the C++ backport of hfns4. 2021-03-23 17:22:07 +01:00
Jean-Paul Chaput d9b14d680a In Katana::protectRoutingPad(), check that the RP is not still on the Plug. 2021-03-23 17:19:38 +01:00
Jean-Paul Chaput a2665b6e3a In Anabatic, Do not take into account diodes when making nets size histogram. 2021-03-23 17:17:32 +01:00
Jean-Paul Chaput 1a918c69b1 Backport cumulus/hfns4 into C++ in EtesianEngine::doHFNS(). 2021-03-23 17:14:39 +01:00
Jean-Paul Chaput ec96161f0f New CRL::SubNetNames class to parse/generate VHDL vectorised subnames.
* New: CRL::SubNetNames (in ToolBox), takes a VHDL signal name, vectorized
   or not and allow to generated sub-net names from it, with respect to
   the original vector name.
     Examples:
       * machin     -> machin_hfns_0, machin_hfns_1, ...
       * bidule(3)  -> bidule_bit3_hfns_0, bidule_bit3_hfns_1, ...
     Makes use of the POSIX regex library to avoid Boost dependencies.
2021-03-23 17:11:56 +01:00
Jean-Paul Chaput 9230d52b64 Big bug in HyperNet_ComponentOccurrences::Locator::progress().
* Bug: In HyperNet_ComponentOccurrences::Locator::progress(), (Collection
    locator), the _netOccurrenceLocator (which progess along the various
    Net occurrences of the HyperNet) was not in synch with the
    _componentOccurrence locator of the current net. It was pointing
    to the *next* net occurrence.
      The result was the generation of a path for the net commponents
    that was incorrect (it was the path of the *next* net occurrence),
    and making Occurrence constructor throw an exception.
* Change: In Cell::flattenNets(), DeepNet::_createRoutingPads(),
    Occurrence::Occurrence() and UpdateSession, added even more trace
    informations.
2021-03-23 17:06:02 +01:00
Jean-Paul Chaput cfcd4b7115 Do not for materialization in RoutingPad::setExternalComponent().
* Bug: In RoutingPad::setExternalComponent(), we where always forcing
    the materialization of the RoutingPad (QuadTree insertion). Now
    respect the Go::enableAutoMaterialization() state.
      Forcing the materialization is equivalent to having an
    UpdateSession. So when creating large amount of RoutingPads it did
    result in huge slow down, like in HFNS algorithms.
      With this modification we go down from 6h+ to 4m for the ls180.
2021-03-23 17:05:18 +01:00
Jean-Paul Chaput 1b5327313a Added Net direction checker/setter in CRL Core.
* New: CRL::restoreNetsdirection() (in ToolBox) that checks the coherency
    of all Nets direction through a complete hierarchy of cells.
      Stops at Cells flagged "TerminalNetlist".
      Directions are rebuilt for all the Cells part of the hierarchy
    in a bottom up fashion. It is also checked that Nets have only one
    driver (we assume there is no three-state busses).
      To sort cells in hierarchical order (bottom up according to their
    depth), copy the DepthOrder class from the GDSII driver. Will unify
    them later.
      exported to the Python interface.
* New: In cumulus/tools/blif2vst.py, add a call to restoreNetsdirection()
    before saving.
2021-03-15 23:57:15 +01:00
Jean-Paul Chaput 11390867f1 A more compact string representation for Hurricane::Path. 2021-03-15 23:45:33 +01:00
Jean-Paul Chaput dbb16b618f Correct managment of macro block regarding to P&R.
* Change: In NetBuilder::getPositions(), ordering of source/target points
    is now integrated to this function instead of left to the caller.
    In case of real (non-symbolic) routing gauge, skrink the ends of
    half the wire width.
* Change: In NetBuilderHV::doRp_AutoContacts(), in case of non-METAL1
    RoutingPad, put the axis of the segment on the nearest track.
    Issue a warning if we have to shift, as it may be a potential
    source of routing problems.
* New: Anabatic::Session::getNearestTrackaAxis(), proxy to compute
    track positions, knowing the design abutment box.
* Bug: In Katana::PreProcess::propagateCagedConstraints(), when
    looking at all the slave components anchoreds on a RoutingPad,
    if they do not have an AutoSegment lookup, skip them instead
    of crashing.
* New: In cumulus/plugins.block.Block.placeMacro(), new method to
    place a macro cell, partly delegating to the Macro block wrapper.
      Must be called *after* both core and corona abutment boxes have
    been set.
      Adjust the macro block position so the METAL2 & METAL3 pins
    are exactly on pitch regarding the full routing grid. The reference
    being the corona.
      A shift, less than one pitch may be applied, leading in some
    cases of overlapping abutment boxes. But this shouldn't be a
    problem.
      The macro to place is designated through a path of instances
    names, rooted at the *core* (not the corona). Meaning that the
    head instance must be one of the core.
* Change: In cumulus/plugins.chip.Chip, the complete chip I/O pads
    plus corona and core placement is moved out from doPnR() and
    put into doChipFloorplan(). It is now mandatory to call this
    method *before* doPnR().
      Those methods are now cleanly separated so we can perform macro
    block placement or any inner core floorplaning operations between
    them.
* Change:  In cumulus/plugins.macro.Macro, instead of creating large
    pads for the I/O pins so whatever the block position, they will
    be under a grid point, create a simple dogleg to put them on
    grid.
      To ensure that they are "on grid", the block pins must be
    in METAL2 (horizontal E/W) or METAL3 (vertical N/S) and the block
    is assumed to be placed so the bottom left corner of it's
    abutment box is exactly on one grid point for M2/M3.
      This should be done by Block.placeMacro().
2021-03-14 16:16:54 +01:00
Jean-Paul Chaput 7e6250d460 Use wide pads (1 P-Pitch) for METAL3 in the cumulus/Macro block wrapper 2021-03-09 10:58:49 +01:00
Jean-Paul Chaput 1205505cf2 Set all segments of external net as external components.
* New: In KatanaEngine::exportExternalnets(), for commercial tools to
    correctly regenerate the external pins from GDSII files it seems
    necessary that all segments needs to have TEXT label. So make them
    external components.
2021-03-05 00:44:15 +01:00
Jean-Paul Chaput aece850a6c Fix bugs in power supply obstacle management.
* Bug: In PowerRailsPlanes::Rail::doLayout(), in case of non-blockage but
    fixed segments (that is, power lines), expand the segment box of one
    picth to put blockage on too close neigboring tracks.
* Change: In Manipulator::avoidBlockage(), more accurate computation of
    the blocked area for pushing aside the terminal & turn of the non-pref
    segment.
2021-03-05 00:43:24 +01:00
Jean-Paul Chaput 7aa0e1321e Bug: Forgot to export Pins in GdsDriver. 2021-03-02 12:47:20 +01:00
Jean-Paul Chaput f4204c52d7 Support for dedicated power plane in Cumulus (vertical stripes).
* New: In cumulus/plugins.chip.powerplane, build the overall power
    grid when there is a dedicated supply layer. Makes vertical
    supply stripes and connect them the *horizontal* power rails
    inside the blocks (could be in *any* layer).
      Stripes positions are determined by the pins createds by
    the pads module.
* New: In cumulus/plugins.chip.chip, use the powerplane builder
    if the RoutingGauge provides a PowerSupply kind.
* New: In cumulus/plugins.block.configuration, add support for
    PowerSupply gauges.
* New: In cumulus/plugins.block.pads, if the gauge provides a
    PowerSupply, create north/south border pins for power & ground
    to direct the corona to make vertical power strips.
      This assume that we are using LibreSOC like I/O pads that
    can be connected straight from everywhere in the corona.
      First and last 2 stripes are "cap end" and narrower.
      Positions and width of the sripes are set through the
    configuration parameters:
    * "chip.supplyRailWidth"
    * "chip.supplyRailPitch"
* Change: In cumulus/plugins.block.spares, now take into account
    the "placeArea" parameter.
* Change: In cumulus/plugins.block.bigvia, now have a per metal layer
    area that *may* be expanded if it is too narrow to put at least
    one cut. Add flags to allow controlled expansion of the metal
    plates.
      As a security, now raise an exception if no cut can be created.
2021-03-02 12:19:18 +01:00
Jean-Paul Chaput 3a68cdf549 Support for "AbstractedSupply" in Katana power rails builder.
* New: In KatanaEngine::PowerRails, now stop the query on
    "AbstractedSupply" master cells. Modification coupled with
    EtesianEngine::flattenPower().
2021-03-02 12:18:45 +01:00
Jean-Paul Chaput ff89f2667d New method EtesianEngine::flattenPower() to build power abstract.
* New: In EtesianEngine::flattenPower(), this is a duplication of the
    KatanaEngine::PowerRails. The new paradigm is that when a Cell
    is placed by etesian it's AbstractedSupply flag is set and the
    creation of the abstract is taken care of at this point.
      Should provide some speedup when Katana process it.
      Note that we still need to keep PowerRails at Katana stage for
    design that are loaded already placed (no Etesian run).
* New: In EtesianEngine::setPlaceArea(), as the slice spin is imposed
    on us by Coloquinte, the bottom slice of the place area *must*
    be on a ID oriented slice, that is an even one, relative to the
    fully placed area.
* Bug: In EtesianEngine, remove the slice spin detection. The spin
    is imposed on us by Coloquinte which always place the bottom
    row in ID orientation.
      Code should be completly removed in the future, along with
    the obsolete AddFeeds (replaced by Placement).
2021-03-02 12:18:11 +01:00
Jean-Paul Chaput 63a03bf11b Add a new RoutingLayerGauge type "PowerSupply".
* New: In CRL::RoutingLayerGauge, add a new kind of gauge "PowerSupply"
    to flag a layer which is dedicated to routing power supplies.
* New: In AllianceFramework, add management of PowerSupply gauge kind.
    Exported in the Python interface.
2021-03-02 12:17:40 +01:00
Jean-Paul Chaput a6492f6edc Allow Hurricane::Query to stop on master cells with designated flags.
* New: In Query & QueryStack, add a new stop criterion "stopCellFlags"
    based on the flags of the instances master cell. The instance will
    still be processed, but not it's childs. Typically used to stop
    exploring on "AbstractedSupply" cells.
      Exported in the Python interface.
* New: In Cell::Flags, new value "AbstractedSupply" to mark Cells from
    which an abstract has been built for supplies & blockages. But *not*
    for common nets. Helps reduce the recursion through the hierarchy
    when building supply line in FlattenPower.
      Export setter/getter in the Python interface.
* New: In Instance, add a "PruneMaster" filter to stop hierarchical
    exploration on instances which master cells have at least one of
    the given flags set.
* Change: In NetExternalcomponents::isInternal(), use "const Component*"
    instead of "Component*".
* Bug: In Cell::Flags, the NoFlags must be *zero*, not *one*! And we
    can reclaim that bit for future use.
* Cleanup: In Hurricane::Cell, remove changeQuadTree() related methods.
    Fusing various Cell's QuadTree is not a viable idea.
* Cleanup: In Hurricane::Instance, remove no longer used "_flags"
    attributes.
2021-03-02 12:17:13 +01:00
Jean-Paul Chaput d00a51029e External block wrapper support added in cumulus/plugins.macro.
* New: In cumulus/plugins.macro.macro.Macro() to encapsulate foreign blocks.
    Round their size to an exact number of GCells and a guard of one GCell.
    External terminal must be on the periphery and will be made to stick out
    in the guard ring. This is sub-optimal for now but provide a workaround
    some Katana bad assumptions.
      A "perpandicular padding" is also added to terminals to limit the
    offgrid related problems. Have to optimize that in conjuction with
    Katana.
2021-02-18 00:07:03 +01:00
Jean-Paul Chaput 7bae6d8bad Partial management of offgrid fixed segments in Katana.
NOTE: To myself, one more bug uncovered in the Track segments management.
      This is really too complex, must find time to re-think and simplify
      the whole thing.

* New: In Katana::NegociateWidow::createTrackSegment(), detect offgrid
    fixed segments and insert them into tracks directly (as *wide* segment
    of two tracks).
* New: In Katana::TrackSegment::create() factory method, check for offgrid
    fixed segment and use a TrackSegmentWide (of 2 tracks) for them.
* New: In Katana::TrackSegmentWide CTOR, check if they are used in the
    context of an offgrid segment and in that case set the track span
    to two. We *do not* manage yet the case for both *wide* and *offgrid*
    segments.
* Change: In Katana::PowerRails::Rails::doLayout(), do not expand blockage
    rectangles over their real size. Add the guard only for real layers
    segments.
* Bug: In Katana::PreProcess::propagateCagedConstraints(), when looking
    for the first track index, check for out of bound value (npos).
* Bug: In Katana::Track::addOverlapCost(), before using the overlap
    segment indexes, check if we are not in a free hole (get the free
    interval from center).
* Bug: In Katana::Track::expandFreeInterval(), the interval was badly
    computed if it was included inside segments of another (same) net.
2021-02-17 23:57:45 +01:00
Jean-Paul Chaput db0ad6bf07 Partial support for offgrid METAL3 RoutingPad in Anabatic::NetBuilderHV.
* New: In Anabatic::NetBuilder::_do_1G_1M3(), RoutingPad in METAL3 from
    blocks are most likely to be offgrid in real mode, we must account
    for that case. When an offgrid METAL3 is found, a strap of METAL2
    is added, as it may be less than one pitch, it will be reduced into
    METAL3 often.
* New: In Anabatic::NetBuilder::doRp_Access(), Support for offgrid METAL2
    is added but not enabled yet. Seems to need more polishing.
2021-02-17 23:34:17 +01:00
Jean-Paul Chaput d942f3cb59 Add support for Rectilinear & Polygon in PyEntity_NEW(). 2021-02-17 23:22:31 +01:00
Jean-Paul Chaput 07b51b10c7 Allow to demote Net external component to "internal", export to Python. 2021-02-17 23:20:24 +01:00
Jean-Paul Chaput 21c269a855 Improved support for foreign block support in Cumulus.
* Change: In cumulus/plugins.block.Block.__init__(), assume that a block
    is already built only if *all* it's instances are placed. Not some
    of them.
* New: In cumulus/plugins/block/configuration, added support for a
    placeArea parameter to restrict the placement area further than the
    abutment box (see Etesian for the new feature).
* Change: In cumulus/plugins/CoreToChip, no longer adds I/O pads for
    core signals that lacks one. Only issue an error message and
    continue. More useful for debugging block support.
2021-02-01 17:01:32 +01:00
Jean-Paul Chaput 14ff6ce78a * Bug: In KatanaEngine::TrackFixedSegment CTOR, for finding the GCells
under the fixed segment, we were using the axis *of the segment*,
    but if it is very wide, this is completly off.
      Now use the axis of the *track* to get the right GCells impacteds.
2021-02-01 16:52:03 +01:00
Jean-Paul Chaput 35d54c3e74 Take account of Rectilinears in KatanaEngine::setupPowerRails()
* New: In QueryPowerRails::addToPowerRail(), now manage Rectilinears,
    *if* they are, in fact, rectangles. For LibreSOCMem block support.
2021-02-01 16:48:36 +01:00
Jean-Paul Chaput e0bae89a81 Bug in KatanaEngine::annotateGlobalGraph(), bad edge capacity computation.
* Bug: In KatanaEngine::annotateGlobalGraph(), overlapping blockages or
    fixed segments where taken into account as separate ones. This was
    making the edge capacity reservation too high. Creating false
    zero-capacity edges at some points.
      Didn't show up until now because we did not have overlaps.
2021-02-01 16:43:42 +01:00
Jean-Paul Chaput 7a7a3b9f1b GoStraight & GCell density sorting bugs.
* Bug: In Anabatic::GCell::updateDensity(), the GoStraight flag is now
    set in this function when the density of blockage is above 40%.
    (should be parametrized in the future). This is linked with the
    Katabatic TrackFixedsegment bug.
* Bug: In Anabatic::GCell::Key::Compare, the densities of the GCell
   where sorted in the *wrong* order, that is *less denser first*.
   This was making the layer assignment working on it's head.
     WTF, how did it ever work.
     Also sort on global saturation.
2021-02-01 16:36:26 +01:00
Jean-Paul Chaput 9df5f5f1b7 Allow to do the placement in a sub-area in Etesian.
* New: In EtesianEngine, add a "placedArea" attribute to restrict the
    placement area to a part only of the whole abutement box. This a
    way to exclude some area containing *big* hard block.
      The placer terribly slow down when tring to "push aside" cells
    from the area taken by the block.
      This will be also used to restrict the clock tree covered area.
      It is far from optimal but will do for now.
    NOTE: The placeArea must be expressed in the coordinate system of
          the sub-block to be placed, if one has been defined.
2021-02-01 16:24:44 +01:00
Jean-Paul Chaput 2ba7bb4fca Better Verilog/VHDL name mixing in the Blif parser.
* Change: In Model::connectSubckts(), when trying to lookup the
    Hurricane Net from it's Blif name, try first as a VHDL one then
    after a Verilog to VHDL translation. Especially useful for bits
    of vectorized names ("signal[X]" --> "signal(X)").
2021-02-01 16:18:25 +01:00
Jean-Paul Chaput 48357c37a9 Added DbU::toCeil() & DbU::toFloor() for rounding on a dedicated step. 2021-02-01 16:13:16 +01:00
Jean-Paul Chaput 95d3ca5344 In CRL::GdsDriver, filter out "CORIOLBLK*" layers (gross hack). 2021-01-27 12:14:29 +01:00
Jean-Paul Chaput a5fbe94705 In cumulus/plugins.block.Block, set the right cell in the editor. 2021-01-27 11:38:27 +01:00
Jean-Paul Chaput 5649a3b984 Second version of the antenna effect protection.
* Change: In EtesianEngine::globalPlace(), disable the call to
    antennaProtect(). First reason is that, after all, Coloquinte
    do not handle so well the resizing of the cells "on the fly",
    it overspill the boundaries sometimes. Second reason is that
    as we cannot know the routing tree at this stage, we will not
    be able to choose the correct points for diode insertions.
    We only have a Steiner tree wich may not be the same as a
    density driven Dijkstra.
* Change: In Etesian::Area, the Occurrence to the Instances where
    not stored in a uniform way. Some where starting from the
    placed sub-block, some where starting from the top level
    (corona), making their processing (and remembering it) tricky.
    Now, they are all expressed from the top cell (corona).
    The coordinate system is now systematically the one of the
    top block (*not* the block).
      Create various overloaded functions EtesianEngine::toCell()
    and EtesianEngine::toBlock() to ease Occurrence & coordinate
    translations.
* New: In Etesian::Slice::createDiodeUnder(), add a X position hint.
    Search is done by going through the whole slice range and
    minimizing the distance to the hint. If it starts to be too
    slow, we may optimize.
* Bug: In EtesianEngine::toColoquinte(), the placement of the top
    level external pins was not taken into account (this at last
    explain their weird positioning).
* New: AnabaticEngine::antennaProtect(), new algorithm to avoid
    antenna effect. This step must be done *after* global routing
    and *before* detailed routing. This way we have access to the
    real routing and can mend it (along with the netlist) to
    insert diodes at the rigth points.
      From the global routing we build clusters (DiodeCluster) of
    RoutingPads connected through a set of wire whose total length
    is below the antenna effect threshold. Long wires connecting the
    clusters are also tagged because we need to put a diode between
    them and the first RoutingPad of the cluster. This is to avoid
    a long METAL2 wire connecting to the RoutingPad before the diode is
    connected through METAL3 (in case of misalignment).
      This protection is not even enough. For *very long* wires, we
    needs to put *more* than one diode (this is to be implemented).
2021-01-27 11:38:00 +01:00
Jean-Paul Chaput b926e02d92 Fix typo in FindETESIAN.cmake in include path searching. 2021-01-27 10:59:58 +01:00
Jean-Paul Chaput 5f6302de44 Added HasAntenna flag to NetRoutingProperty. 2021-01-27 10:58:03 +01:00
Jean-Paul Chaput 88081fae12 Added Path::contains(Instance*) method. 2021-01-27 10:57:35 +01:00
Jean-Paul Chaput 087ef239c2 Add support for Antenna/Diode insertion in Etesian.
* New: In Etesian::Configuration add new parameters for antenna
    effect management:
    * "etesian.diodeName"    : the name of the diode cell.
    * "etesian.antennaMaxwl" : maximum length above which antenna
         effect can occur. Must be the maximum for all the normal
	 routing layers.
    * "etesian.antennaInsertThreshold" : during the placement steps,
         threshold for linear disruption at which we will look for
	 the RSMT and insert diodes.
* New: In EtesianEngine::antennaProtect(), at a designated point
    in the placement iteratives step, when the spreading starts to
    be significant enough estimate the RSMT length and add a diode
    if need be. The diode will be put side by side with the driver
    cell. This is done by enlarging the driver cell of the diode
    width.
* New: In EtesianEngine::_updatePlacement(), in the final stage,
    modify the netlist to connect the diode. The diode will be
    put on the side of the cell closest to the driver. This may
    alow to make the connexion directly in METAL1 in the future.
* Change: In etesian/Placement.cpp, make the whole placement
    structure a persistent attribute of the EtesianEngine so
    it can be used afterwards.
      Add a post-placement diode insertion feature. Finally
    unused as they are added on the fly during placement.
      In the Area, add data about the diode tie in the TieLut.
* Change: Add EtesianEnginea::clearColoquinte(), to keep the
    post-placement structure while purging the Coloquinte one.
* Change: In cumulus/plugins.block.block, keep the Etesian engine
    until the whole P&R is done, so we potentially can exploit
    the post-placement datas.
* Bug: In cumulus/plugins.chip.power.GoCb(), for the METAL1 power
    and ground wires coming from the standard cell, it was assumed
    they where made of Horizontal segments, this is not the case
    in FlexLib... So force to consider the plane as Horizontal when
    we are processing that plane.
      Better solution should be to use Horizontals...
2021-01-13 19:36:20 +01:00
Jean-Paul Chaput 78cbb662e6 Add updators to modify cell sizes on the fly in Coloquinte. 2021-01-13 19:10:31 +01:00
Jean-Paul Chaput 79e47d1ef2 Add net driver detection in Dijkstra (just a check for now). 2021-01-13 19:08:00 +01:00
Jean-Paul Chaput 2b0a2c88b7 More informative error message in Occurrence constructor. 2021-01-13 19:05:20 +01:00
Jean-Paul Chaput 250ef29674 Fix the smart truncate display in DbU::getValueString(). 2021-01-13 19:04:13 +01:00
Jean-Paul Chaput 3b5a0f5bd2 Again, bug fix in the Inspector support, on getSlot<> template.
The policy about how to create slots was not completly clear.
Now, only add *pointers* or *references* to class attributes,
never do a "copy by value". Reflect that change in SlotTemplate<>
various partial specializations.
  Hammer in your head that in C++ functions templates do not allow
for partial specialization. So write only *one* template for
::getSlot<>() (refdefinition simply got ignoreds, at least with gcc).

* Bug: In Slot, only one template for getSlot<> (see above).
    Adjust SlotTemplates<> to provides partial specialization only for:
    * "const Data&".
    * "Data*".
    * "const Data*".
    * "Data* const"
    * "Record*".
* Bug: In Instance::_getRecord(), suppress slot based on transient
    values "XCenter" & "YCenter".
* Bug: In CRL::ToolEngine::_getRecord(), suppress slot "Name" based
    on a transient value.
* Change: In ::getRecord(std::list<Elementt>*) (and variant), pass
    all elements to ::getSlot() as (const Element*).
2021-01-08 12:43:47 +01:00
Jean-Paul Chaput 678631d44f GdsDriver now export correctly I/O pin (for FlexLib).
* In CRL::GdsStream::operator<<(Cell*), when encountering an *external*
    component, try to find a ".pin" layer associated (if not already
    in it). Then drive the BOUNDARY & TEXT in it. This way, Cadence/
    Calibre seems to be able to recognize them as Pin.
2020-12-27 13:49:05 +01:00
Jean-Paul Chaput 405ca8d11b Improved support for LibreSOCIO (real), use IOPadIn & IoPadOut. 2020-12-27 12:46:04 +01:00
Jean-Paul Chaput 57432bbb50 * Bug: In cumulus/plugins.chip.configuration, check that the core
height is a multiple of sliceHeight. Otherwise, in some situations,
    fixed cell may peek out of the placement area, triggering
    Coloquinte assert (which says that the top of the cell is *above*
    the top row).
2020-12-27 12:43:26 +01:00
Jean-Paul Chaput e3803d28d7 Simple HFNS (#4), break the net, regardless of placement.
* New: In cumulus/plugins.block.hfns4.py, perform simple HFNS by breaking
    the net into sub-nets of at most 10 sinks (hard-coded for now).
      As this method is called *after* the netlist as been virtually
    flattened, we have to create the RoutingPad at the top level
    ourselves. Sub-nets are created at the Cell top-level (same
    approach as for clock synthesis, because there is no smart way
    to guess where they should be).
* New: In cumulus/plugins.block.block.py, perform HFNS (#4) *before*
    doing placement. To see the real sink count on each net, we must
    perform the virtual net flattening first (Cell::flattenNets()).
* Change: In cumulus/plugins.block.configuration, allow the creation
    of spare buffer in any cell (instead of only "self.cellPnR").
* Change: In cumulus/plugins.block.spares.Spares.raddTransNet(),
    Check if intermediate masterNet exists in Cells before trying
    to blindly re-create it.
2020-12-27 12:38:01 +01:00
Jean-Paul Chaput b0ae6be652 Export Cell::flattenNets() & revlevant Cell flags. 2020-12-27 12:21:14 +01:00
Jean-Paul Chaput 49ffe1e1ba Added management of tie *inside* cells.
* New: In Etesian/Placement::Area, added support to take into account
    bulk inside cells. Currently only hard-wired configuration for
    FlexLib is available. Should add a front-end to analyse the
    cells of the library to lookup for bulk ties in the future.
2020-12-23 11:22:12 +01:00
Jean-Paul Chaput 70d32528cd Added new utility conversions DbU::toMicrons() & DbU::fromMicrons(). 2020-12-23 11:16:38 +01:00
Jean-Paul Chaput ead11f8b93 Added support for external connectors in GDS parser/driver.
* New: In CRL::GdsDriver, create TEXT record under each external
    Net component. Seems to be the aknoweledged way to signal
    external pins.
* New: In CRL::GdsParser, read TEXT record and create Net and
    external components that are in the same layer and at the
    same position.
2020-12-19 23:04:50 +01:00
Jean-Paul Chaput 8fdaf47f3d Second attempt at tie insertion. Works, but disturb placement.
* New: In Etesian::Configuration, added "etesian.lacthUpDistance" to
    control tie cells insertion (for polarization contacts).
* New: Etesian/Placement as a complete replacement for FeedCells.
    Rebuild the complete slicing structure of the placement to
    serve as a building block for post-placement changes under
    Coriolis. Currently used to regularly insert body ties.
      This is not optimal as we displace cells in each slice in
    a non-coordinated manner.
* New: In cumulus/plugins/block.configuration.FeedsConf, register
    the "etesian.latchUpDistance" parameter. Provides the tie width.
* New: In cumulus/plugins.block.spares, add ties around the buffer
    pool block and "cap ties" at both end of each slice.
2020-12-17 10:22:43 +01:00
Jean-Paul Chaput 2e50ff4724 Compute and display feed insertion statistic per row. 2020-12-09 00:15:54 +01:00
Jean-Paul Chaput 172bdd9240 First attempt at inserting bulks, fail.
* New: In cumulus/plugins.block.spares, added creation of vertical
    stacks of feed cells, for their N/P tie contacts, to ensure
    correct bulk polarization. Fail, because the placer cannot
    cope with such massive obstacles, the vertical columns are
    too close to manage.
* New: In cumulus/plugins.block.configuration, add support to
    FeedsConf so lone instances can be created (for the first
    bulk trial).
2020-12-09 00:15:30 +01:00
Jean-Paul Chaput 945b9a24fa Fix I/O Pad ring 45 degree corners where off the foundry grid.
* New: In CRL/hepers, new function onFGrid() to ensure a DbU is on the
    foundry grid. Rounding is always done to the inferior integer.
* New: In CRL/GdsDriver, added a set of isOnGrid() functions to check
    that all coordinates of various objects are on the foundry grid.
      Use isOnGrid() in most objects processed in
    GdsStream::operator<<(Cell*).
* Bug: In cumulus/plugins.chip.pads.Corner, correctly round the
    coordinates of the 45 degree segments so they are still on the
    foundry grid.
2020-12-09 00:05:52 +01:00
Jean-Paul Chaput 973cc0f3c3 In LibreSOCIO, allow to choose between complete/abstract layout.
* New: In cumulus/plugins.core2chip.libresocio.CoreToChip, use new
    configuration variable "chip.useAbstractpads" to select between the
    abstract version (GPIO, VDD, ...) and the full version (IOPadInOut,
    IOPadVdd, ...) layout.
2020-12-07 16:41:09 +01:00
Jean-Paul Chaput 564714d73e Set a maximum wire with for LibreSOCIO I/O pads to corona wires.
* New: In cumulus/plugins.chip.pads.Corona._createCorewire(), add an
    hard-coded limitation for LibreSOCIO I/O pad to corona wires to
    always be below the maximal threshold.
2020-12-07 16:39:36 +01:00
Jean-Paul Chaput 51028980c9 Modify the chain of "save()" calls in chip/block to pass on flags.
* Change: In cumulus/plugins.block.configuration.BlockConf.save(),
             cumulus/plugins.block.Block.save(),
             cumulus/plugins.chip.Chip.save(),
             cumulus/plugins.core2chip.core2chip.CoreToChip.buildChip(),
    Add a "flags" parameter to control the way logical views (aka "vst")
    are saved. Mainly allowing to pass on the VstUseConcat option in
    order for Alliance tools to be able to read them back (lvx, asimut).
* Change: In cumulus/plugins.core2chip.core2chip.CoreToChip.buildChip(),
    don't stop at the first I/O pad signal missing on the core, but
    display all the missing ones (LKCL proposal).
2020-12-05 11:59:48 +01:00
Jean-Paul Chaput 1411739c0b Make block/chip plugin use the common rsave plugin.
* In cumulus/block.configuration, the rsave method was buggy. It did stop
    it did not save "terminal" master cells (i.e. a cell without instance)
    instead of "netlistTerminal" (explicitely flagged for standard cells).
      The result was that some "empty netlist" in the complete "ls180"
    from LibreSOC went missing. Causing cougar to complain.
2020-12-04 12:20:57 +01:00
Jean-Paul Chaput be5483a0ad Do not skip thin (elongated) QuadTree leaves. 2020-12-04 12:14:08 +01:00
Jean-Paul Chaput 84d25da1b8 More thorough verification of outputs of tie low/tie high in Blif parser.
* Change: In CRL::Model::staticInit(), when trying to guess the ouput
    of the tie low & tie high cells check if the net name is not a
    power or ground. A bad input was choosen with FlexLib as the
    vdd/vss nets where not typed as POWER/GROUND.
2020-12-03 16:34:22 +01:00
Jean-Paul Chaput c76453112e More explicit message for Pad unconnected pins. 2020-12-02 20:06:22 +01:00
Jean-Paul Chaput 4e2dfceb37 Tag contacts layers as symbolic in CRL/etc/common/technology.py 2020-12-02 20:04:27 +01:00
Jean-Paul Chaput 642579b444 More fix for the slow display in CellViewer.
* Change: In Hurricane::QuadTree_GosUnder::Locator::progress(), directly
    prune the elements which sizes are under the threshold. This allows
    the too small Instances to be directly skipped. This was the key
    point slowing the walktrough. We were systematically going through
    all the instances (that is consistent with the perf traces).
* Change: In Hurricane::Cell_OccurrencesUnder, add a threshold parameter
    to pass on the QuadTree (through getInstancesUnder()).
      Needed for the CellWidget selection to have the same problem as
    the display itself (select only what is displayed).
* New: In Hurricane::CellView, add two new parameters:
    1. "viewer.minimumSize" set the original size of the window, in pixels.
       (doubled for HiDPI).
    2. "viewer.pixelThreshold", the size, in pixels, under which
       components/instances will not be displayeds.
* New: In CRL/etc/cmos.misc.py, added parameters "viewer.minimumSize"
    and "viewer.pixelsThreshold".
2020-12-02 20:02:55 +01:00
Jean-Paul Chaput 7feb39d056 Separate size check for Hurricane::Contact & Hurricane::Pin.
* Change: In Hurricane::Contact, as it is the base class of Pin, a
    width *or* height can rightfully be null (according to the
    Pin orientation).
      Put the check in a Contact::_postCheck() function.
* Change: In Hurricane::Contact, replace all the "const DbU::Unit&"
    parameters by simply "DbU::Unit".
* Change: In Hurricane::Pin, add a dedicated _postCheck() function.
2020-12-02 19:12:27 +01:00
Jean-Paul Chaput 6e0593e526 Merge branch 'createBL_area' into 'devel'
CreateBL area parameter

See merge request vlsi-eda/coriolis!5
2020-11-27 18:51:18 +01:00
Jean-Paul Chaput 78823b17c1 Transfer of blif2vst.py & yosys.py from alliance-check-toolkit. 2020-11-27 18:47:19 +01:00
Jean-Paul Chaput 85d943a3e4 Added support for JSON pinmux reading from LibreSOC.
* New: In cumulus/plugins.blocks.iospecs.IoSpecs, new class to manage
    I/O pads placement. Support for reading the JSON pinmux format
    (courtesy of LKCL & StackOverflow).
2020-11-27 18:46:58 +01:00
Staf Verhaegen 775a169e82 Add area parameter to createBL() helper function.
This parameter allows to specify the minimum area for a layer.
2020-11-26 17:25:52 +01:00
Jean-Paul Chaput 13726d648b Better/nicer management of the BigVia in cumulus.
* Change: In cumulus/plugins.block.bigvia.BigVia, center the VIA cut
    matrix. Issue a BIG warning when no one cut could be drawn
    (temporarily disabled until I fix the corona).
2020-11-25 21:52:48 +01:00
Jean-Paul Chaput 867e6cc966 Completely discouple the RoutingGauge from the CellGauge in Etesian.
* Change: In EtesianEngine, V-Pitch and H-Pitch are now initialized
    from the Cell gauge "slice step". It may still be best if the
    METAL2 routing grid is still a fractional ratio of the cell height.
2020-11-25 21:52:26 +01:00
Jean-Paul Chaput 2a900c4abb New CRL/helpers.technology.createVia() helpers method. 2020-11-25 21:52:05 +01:00
Jean-Paul Chaput e08bc9a407 Check contacts for minimal size in real mode.
* Change: In Hurricane::Contact::Contact(), check width & hieight of
    the contact against the minimal size, if below, bellow a warning
    and increase the dimension.
      May too paranoid when used on turn in same metal (no cut).
2020-11-25 21:51:43 +01:00
Jean-Paul Chaput 29b57e86e5 DRC correct on Arlet6505 / TSMC C180.
Integrate new features and bug fixes so the Arlet 6502 benchs successfully
passes real DRC with reference industrial tools. Short summary:
* Manage minimum area for VIAs in Katana::Tracks.
* Allow different wire width for wires perpandicular to the prefered
  routing direction.
* StackedVIAs used in the clock tree no longer assume an uniform
  routing grid (same offset & pitch all the way up).
* Some hard-coded patches in PowerRails for FlexLib.

* New: In CRL/symbolic/cmos/kite.py & cmos45/kite.py, update the
    RoutingLayerGauges by adding the new PWireWidth parameter.
    Always zero in case of symbolic layout (too fine tuning).
* New: In CRL::RoutingGauge, add accessor to PWireWidth parameter.
    Modify the clone method.
* New: In CRL::RoutingLayerGauge, add new parameter "PWireWidth"
    to give the width of a wire when it not drawn in the prefered
    routing direction. If it is set to zero, the normal width is
    used.
* New: In CRL::PyRoutingGauge, export the updated constructor
    interface. It is *not* backward compatible, one must add the
    PWireWidth parameter in the various kite.py configuration
    files (in etc/).
* Change: In AnabaticEngine::_gutAnabatic(), disable the minimum
    area detection mechanism, replaced by a more complete one in
    Katana::Track. Left commented out for now, but will be removed
    in the future.
* Change: In Anabatic::AutoContact::updateLayer(), now systematically
    calls setLayerAndWidth() to potentially resize the VIAs. This is
    needed in real mode as VIAs are *not* macro-generated but have
    their real final size.
* Change: In Anabatic::AutoContact::setLayerAndWidth(), select the
    width and height of the contact using the gauge wire width *and*
    perpandicular *wire width*.
* Change: In Anabatic::AutoSegment::_initialize(), the "VIA to same cap"
    to PWireWidth/2, this will be the size of the VIA in the
    non-preferred direction at the end cap (non-square in real mode).
* Change: In Anabatic::AutoSegment::getExtensionCap(), makes different
    cases for symbolic and real. Use raw length in real, add half the
    wire width in symbolic.
      Add a flag to get the extension cap *only*, not increased of
    half the minimal spacing.
* Change: In Anabatic::AutoSegment::bloatStackedStrap(), enhanced,
    but finally unused...
* New: In Anabatic::AutoSegment::create(), use the PWireWidth when
    the segment is not in the preferred routing direction (and of
    minimal width).
* New: In Anabatic::Configuration, add new getPWirewidth(),
     DPHorizontalWidth() and DPVerticalWidth() accessors.
* Change: In AnabaticEngine::setupPreRouteds(), skip components in
    in "cut" material. We are only interested in objects containing
    some metal (happens in real mode when VIAs cuts are really there).
* New: In Katana::PowerRailsPlanes::Rail::doLayout(), add an hard-coded
    patch that artificially enlarge the *wide wire* so the spacing for
    wide wire is enforced. For now, two pitches on each side for
    "FlexLib" gauge.
* New: In Katana::Track, add support to find and correct small wire
    chunks so they respect the minimum area rules.
      Two helper functions:
      * ::hasSameLayerTurn(), to find if a a TrackElement as non-zero length
        perpandicular is same layer connected to it.
      * ::toFoundryGrid(), to ensure that all coordinates will be on the
        foundry grid (may move in a more shared location).
      * ::expandToMinArea(), try to expand, *in the routing direction*
        the too small wire so it respect the minimal area. Check for the
	free space in the track.
    Track::minExpandArea() go through all the TrackElements in the track
    to look for too small ones and correct them.
* Change: In Katana::RoutingPlane, add an accessor to get the tracks.
* New: In KatanaEngine::finalizeLayout(), add a post-treatment to find
    for minimal area violations.
* Change: In cumulus/plugins.block.configuration.GaugeConf, add a
    routingBb attribute that will serve as a common reference to all
    the functions calculation track positions. We must not have two
    different reference for the core and the corona. The reference
    is always the corona when we working on a complete chip.
* New: In cumulus/plugins.block.configuration.GaugeConf.getTrack(),
    Simplified and more reliable way of getting tracks positions.
    Use the routingBb.
* New: In cumulus/plugins.block.configuration.GaugeConf.rpAccess(),
    Make use of getTrack() to get every metal strap on the right
    X/Y position.
* New: In cumulus/plugins.block.configuration.GaugeConf.expandMinArea(),
    As those wires are left alone by the router, it is our responsability
    to abide by the minimal area rule here. Hence the code duplication
    from the router (bad).
      Mainly wires made for the clock tree, I mean.
* Bug: In cumulus/plugins.chip.configuration.ChipConf.setupICore(),
    the core instance must be placed on the GCell grid, defined by the
    slice height (X *and* Y).
* Bug: In cumulus/plugins.chip.corona.Builder(), forgot to use bigvia
    for the corners of the inner ring.
* Bug: In cumulus/plugins.chip.pads.corona._createCoreWire(), hard-coded
    patch for LibreSOCIO, the power/ground connectors toward the core
    are too wide and can create DRC errors when put side by side.
    Shrink them by the minimal distance.
2020-11-23 23:07:15 +01:00
Jean-Paul Chaput ba43b02e87 Fix segment AutoSegment::reduce() multiple-call (must run once).
* Bug: In Anabatic::AutoSegment::reduce(), no longer reduce *again*
    an already reduced segment.
      This bug was seen through a side effect, it was causing the
    "reduced perpandicular" counter to be incremented too much and
    so it cannot get back to zero, blocking the layer reduction
    (AutoSegment::reduceDoglegLayer()) and some bad VIAs where left
    over.
      More debug information in reduce & raise functions.
* Change: In Katana::Session::_revalidate(), process to be raised
    segments *before* segments that can be reduceds.
2020-11-17 15:02:50 +01:00
Jean-Paul Chaput 0d372365e1 Fix left open DebugSession in Katana::NegociateWindow::createTrackSegment(). 2020-11-17 15:02:24 +01:00
Jean-Paul Chaput 2fab191cef Merge branch 'typo_createlib' into 'devel'
Typo in python af.createLibrary() signature.

See merge request vlsi-eda/coriolis!4
2020-11-16 11:37:08 +01:00
Jean-Paul Chaput 73b019a156 Fix a slight shift between pad instances and their ring wires. 2020-11-16 00:58:40 +01:00
Jean-Paul Chaput f5ee37d2e6 Manage minimum area for VIAs in the P&R.
* New: In Hurricane::Layer, add support for a minimal area (given in
    microns). Exported in the Python interface.
* New: In Anabatic::AutoSegment::bloatStackedStrap(), method to
    enlarge too small vertically stacked VIAs. For now just create
    a square ensuring the minimal area. Potentially cause DRC error in
    some cases so needs to be refined.
* New: In Anabatic::_gutAnabatic(), check for too little stacked VIAs
    and display a report.
2020-11-16 00:55:49 +01:00
Staf Verhaegen b054045c0e Typo in python af.createLibrary() signature.
Small typo.
2020-11-15 11:10:11 +01:00
Jean-Paul Chaput b91fbbbda2 Added utlity script bootstrap/resetDoc.sh to revert the generated doc. 2020-11-14 18:54:23 +01:00
Jean-Paul Chaput b974795a44 Generate cut via matrixes instead of monolithic symbolic ones.
* New: In cumulus/plugins/chip.corona.HorizontalRail & VerticalRail,
    use the new BigVia instead of StackVia to generate a matrix of
    cut when in real mode. Stick to the one massive VIA when in
    symbolic.
* New: In cumulus/plugins/block.bigvia.BigVia to generate matrixes
    of cut VIA.
2020-11-14 18:53:51 +01:00
Jean-Paul Chaput a4eb811bcb Exported Layer::getTopEnclosure() in Python interface. 2020-11-14 18:51:41 +01:00
Jean-Paul Chaput e4d821e5b6 Added warnings for off foundry grids in Rectilinear::create(). 2020-11-14 18:50:42 +01:00
Jean-Paul Chaput 3a3c4fe3c5 DbU::getValueString() was truncating lambda value one decimal too short. 2020-11-14 18:49:23 +01:00
Jean-Paul Chaput bf0d1ef350 More accurate layout detection in CRL::GdsDriver.
* Bug: In CRL::GdsDriver::hasLayout(), a Cell was saved in the GDSII
    stream only if it has a layout, but the check was not accurate
    enough. In the Arlet6502, the whole core was missing.
      Now check for the abscence of Plugs (not unfinished Nets) and
    PLACED/FIXED instances.
2020-11-14 18:48:49 +01:00
Jean-Paul Chaput 4344023221 Updated PDFs, November 13, 2020 (15:02). 2020-11-13 15:02:56 +01:00
Jean-Paul Chaput c6e5583233 Documentation cleanup & rebuild.
* Change: In documentation/build.py, more PEP8 & Python 3 future compliance.
    Correct copy of the tools HTML docs on my laptop, to have a full
    offline copy of the doc.
* New: In documentation/contents/pages/check-toolkit, duplicate the doc
    from alliance-check-toolkit README. Seems it has been inadvertently
    removed at some point (?). Have to be careful to maintain in synch
    with the toolkit.
* Change: <tool>/doc/*/SoC.css, use Roboto fonts when availables.
* Update: Commit the whole pre-generated docs (Doxygen, Pelican).
2020-11-12 14:22:31 +01:00
Jean-Paul Chaput 8c52755558 Updated PDFs, November 12, 2020 (14:00). 2020-11-12 14:00:16 +01:00
Jean-Paul Chaput 574fc9f9be Updated PDFs, November 12, 2020 (13:02). 2020-11-12 13:02:16 +01:00
Jean-Paul Chaput f0735beba2 Updated PDFs, November 12, 2020 (13:01). 2020-11-12 13:01:04 +01:00
Jean-Paul Chaput 8f2d311cfd Updated PDFs, November 12, 2020 (13:00). 2020-11-12 13:00:24 +01:00
Jean-Paul Chaput c5f2faa96c Updated PDFs, November 12, 2020 (12:58). 2020-11-12 12:58:25 +01:00
Jean-Paul Chaput f583a85f8a Updated PDFs, November 12, 2020 (12:40). 2020-11-12 12:40:02 +01:00
Jean-Paul Chaput d05539378c Fix rounding error in GDSII driver.
* Bug: In CRL/GdsStream::toGdsDbu(), when converting a physical number,
    in double to a number of GDSII dbu in int32_t, we must not use the
    direct cast int32_t(v) because v can be 2.9999999999 which got
    simply truncated into 2 while we want 3. So now use the rounding
    function std::lrint() and configure it round to the *nearest*
    integer.
       Note that we don't check that the long returned can correctly
    fit into int32_t.
2020-11-12 01:18:47 +01:00
Jean-Paul Chaput acc9405ba3 Added support for real LibreSOCIO pads.
* New: In cumulus/plugins.block.configuration, added class ConstantsConf
    to store information and create instances of "zero" and "one" cells.
    Added attribute in BlockConf class.
* Change: In cumulus/plugins.block.configuration, moved the cell cloning
    and saving from block.spares.Spares to configuration.BlockConf as
    it is a service that can be used by other modules than just spares.
    Other modules may modificate the netlists also, like in XXXX.
* Change: In cumulus/plugins.chip.configuration, in various methods,
    manage both cases when the layer is symbolic or real (difference
    in accessing the underlying BasicLayers).
* Change: In cumulus/plugins.chip.configuration, less clutered display
    of lambda length in trace mode (and use of 'L' as 'l' was too close
    to '1').
* Bug: In cumulus/plugins.chip.corona.VerticalSide.addBlockages(),
    as the clock are now on the *inner* rail(s), blockage must be on
    the *outer* rails (power lines).
* New: In cumulus/plugins.chip.pads.Corner, add support for 45 degree
    corners (cfg setting "chip.use45corners").
* New: In cumulus/plugins.chip.pads.Side.check(), correct computation
    of the side's length. Was using the ioPadStep instead of the pad
    cell width!
* Change: In cumulus/plugins.chip.pads.Corona._padAnalysis(), LibreSOCIO
    pads uses Verticals for their ring wires (common sense would want
    them *Horizontal*). So they must be included in the physical pin
    detection, but in turn this cause havoc in pxlib... So create a
    filtering according to the library name. This is *not* robust
    but will do for now.
* New: In cumulus/plugins.chip.pad.core2chip.CoreToChip, rename
    self.state into self.conf for clarity.
      New method newEnableForNet(), to create "enable" nets on the
    fly for emulated In/Out pads.
      As it can edit the netlist (new "enable" nets) call the
    BlockConf.rsave() method instead of direct saving through
    AllianceFramework.
      Raise NotImplementederror instead of ErrorMessage.
* New: In cumulus/plugins.chip.pad.core2chip.IoPad.createPad(),
    on emulated In/Out I/O pad like for LibreSOC, generate on the fly
    the right enable signal.
      If an enable signal is given, it will be used (backward
    compatible with the previous behavior).
* New: In cumulus/plugins.chip.pad.core2chip, support for real
    LibreSOCIO pads in libresocio.py module.
2020-11-11 14:29:56 +01:00
Jean-Paul Chaput 1b6d5bd09d Remove check over RegularLayer in TrackFixedsegment CTOR (for real mode). 2020-11-11 13:46:47 +01:00
Jean-Paul Chaput 03bfc091c3 Warn for zero values in Layer.setMinimalSize() & setMinimalSpacing(). 2020-11-11 13:45:15 +01:00
Jean-Paul Chaput 61b9817421 .
Implement BasicLayer.getTop() & getBottom(), need them in real mode.
2020-11-11 13:43:26 +01:00
Jean-Paul Chaput 266409acc4 In DbU.getValueString(), use 'L' for lambdas ('l' too close of '1'). 2020-11-11 13:40:58 +01:00
Jean-Paul Chaput d37970d184 In Stratus.Model.CellHurCreation(), remove call to setTerminal(). 2020-11-11 13:36:56 +01:00
Jean-Paul Chaput 541b23216c Support of FlexLib I/O in Core2Chip & chip plugins (alpha).
* New: In cumulus/plugins/core2chip/, support for the FlexLib I/O cells
    symbolic abstracts ("niolib"). More flexible way of specifying the
    number and positions of the various power pads, both I/O power and
    core power.
      For niolib (FlexLib I/O abstract), support for multiple clocks,
    that is, clock become ordinary pad (with signals typed as CLOCK).
* New: In cumulus/plugins/chip/, added support for niolib and final
    integration of multiple clocks (only for niolib).
2020-11-02 17:42:32 +01:00
Jean-Paul Chaput f8a9dd9f71 Update cmos45 for use with FlexLib I/O symbolic abstracts. 2020-11-02 17:18:40 +01:00
Jean-Paul Chaput afa5fcd4c7 More informative error message in Hurricane::Net constructor. 2020-11-02 17:16:02 +01:00
Jean-Paul Chaput f9cd0e2565 .
Cleanup & error messages in cumulus/plugins/alpha/.
2020-10-25 12:08:48 +01:00
Jean-Paul Chaput 04e9b56102 Try some new colors for the abutment box drawing (again). 2020-10-25 12:06:41 +01:00
Jean-Paul Chaput 3993f948b7 Change the way the grid is drawn in CellWidget.
* Change: In CellWidget::drawGrid(), for the "super-grid", now use
    lines instead of small crosses. The super-grid is set to 10 point
    of the snap grid in all cases (symbolic, real, foundry grid).
* New: Export CellWidget::setDbuMode() to CellViewer, and into it's
    Python wrapper.
* Bug: In CellWidget::setCell(), keep the dbuMode when loading a new
    cell instead of reverting to default.
2020-10-25 12:05:54 +01:00
Jean-Paul Chaput aadd7744ee Small typo in GDS driver Python wrapper error message. 2020-10-25 11:43:41 +01:00
Jean-Paul Chaput 81522e73a2 New technology helpers createBL & setEnclosures. 2020-10-25 11:42:25 +01:00
Jean-Paul Chaput 25cbb6b3c9 Try some new colors for the abutment box drawing. 2020-10-25 11:39:44 +01:00
Jean-Paul Chaput b9f2a5bf28 Remove unused buffers in Block & Core2Chip.
Note: The previous strategy was not fully coherent in chip mode.
      Everything added, net and components must be added at
      corona level and not separated between corona and core.

* New: In cumulus/plugins/block.configuration, new FeedsConf object
    to handle the feeds and provide a filling area helper.
* New: In cumulus/plugins/block.spares.removeUnusedbuffers() to
    remove unused buffers in the pools and replace them by feedthrough.
* Change: In cumulus/plugins.block.spares, unify coordinate/slice
    computation. If we are in chip mode, the coordinates are
    expressed in the corona *but* aligned on the slices of the
    *core* model.
* Change: In cumulus/plugins.block.Block.rsave(), add the '_r' suffix
    to the routed cells.
* Change: In cumulus/plugins.clocktree.ClockTree, when in chip mode
    create everything at corona level. Also forgot to set type of
    clock subnet as clock.
2020-10-23 22:28:42 +02:00
Jean-Paul Chaput e6e667c6c7 Etesian manage top level obstacles when placing a sub-block.
Note: To implement this in a more flexible way we should introduce a
      concept of Instance/Cell "placeholder" to reserve space
      transhierarchically.

* Change: In EtesianEngine::toColoquinte(), when placing only one block
    in a cell, the cell itself can contains other fixed instances
    that are over the placement area. Create dummy fixed instances
    to reserve the taken space.
       In EtesianEngine::AddFeeds(), do not put feed cells over the
    cell area occuped by the sibling instances cells.
* Cleanup: In KatanaEngine::setupPowerRails(): small cleanup.
2020-10-23 22:28:04 +02:00
Jean-Paul Chaput 0217ca1f26 Force VST driver to clear all Vhdl properties after running.
* Change: In CRL::vstDriver(), remove all Vhdl properties after running.
    The properties are not updated if the cell (Entity) change, so the
    next time it is called, an incomplete or incoherent state was saved
    (for example, incomplete "port map"). Removing all properties is
    less efficient but works.
* Cleanup: In CRL/helpers/overlay, remove forgotten debug message.
2020-10-23 22:26:50 +02:00
Jean-Paul Chaput f7ba17213d In cumulus/Chip plugin Check that the spare side is not too small.
* Change: In Cumulus/plugins/block/spares, check that "block.spareSide"
    is not below 7*sliceHeight and issue a warning instead of a later
    divide by zero...
2020-10-18 23:17:16 +02:00
Jean-Paul Chaput 6bc8751879 Change the type of parameters for Etesian from Percentage to Double.
* Change: In CRL/etc/common/etesian.py, use double parameters
    instead of percentages to simplify. For space margin and form
    factor. This need the rewrite of coriolis2/settings.py in
    alliance-check-toolkit.
2020-10-18 23:17:00 +02:00
Jean-Paul Chaput 04098a4655 Bug in overlay.CfgCache, values were never set!
* Bug: In CRL/helpers/overlay.CachedParameter.cacheRead(), values where
    not read *from* the Configuration DB, due to a forgotten "self.".
      In CRL/helpers/overlay.CfgCache.__setattr__(), value was simply
    never set! Only interval and set of values were manageds!
      In CRL/helpers/overlay.CfgCache.__getattr__(), must distinguish
    between two access cases, when were are truly accessing a
    CachedParameter, return it's *value*. Otherwise, it is a
    recursive CfgCache, then return the object.
2020-10-18 23:16:22 +02:00
Jean-Paul Chaput ccc376f132 In cumulus/block/timings.py, filter non-available cells. 2020-10-16 11:26:58 +02:00
Jean-Paul Chaput 158d8c717d Add ability to add non-symbolic library in AllianceFramework.
* New: In CRL::AllianceFramework::wrapLibrary(), can now add in the set
    of AllianceLibrary one which is wrapped around another one. All the
    cells must be already present and do attempt to save them with
    AllianceFramework (AP parser will drive nonsensical datas).
2020-10-16 11:25:57 +02:00
Jean-Paul Chaput 23f9ea052c Improved CRL/helpers.overlay.CfgCache, setting of secondary values.
* New: In CRL/helpers.overlay.CfgCache, create a class to fully handle
    all the Configuration parameters settings. That is, range and
    enumerated values. This way we can fully create them from
    the CfgCache instead of merely changing the value of an
    existing one.
      Examples:
        cfg.anabatic.gcell.displayMode  = 1
        cfg.anabatic.gcell.displayMode  = ( ("Boundary", 1), ("Density", 2) )
        cfg.katana.hTracksReservedLocal = 4
        cfg.katana.hTracksReservedLocal = [ 0, 20 ]
2020-10-16 11:20:38 +02:00
Jean-Paul Chaput c9f73d1f3d Slightly more explicit error message in the Blif parser.
* Change: In CRL::Blif, when a Blif connector do not exists in the
    Hurricane instance (Plug / External master net), issue a more
    informative message.
2020-10-16 11:11:37 +02:00
Jean-Paul Chaput 3d33c4e66a Port of the chip P&R plugins into Alpha.
Note: The port is not complete. Integration of LKCL patches will
      follow shortly.

* Change: In cumulus/plugins/alpha/block, more simple inheritance
    scheme. Use classic inheritance instead of @classdecorator.
    BlockConf (renamed from BlockState) now inherit from GaugeConf,
    Double inheritance tree, for Block/Chip and BlockConf/ChipConf.
    Allow an uniform syntax for configuration parameters.
* New: In cumulus/plugins/alpha/chip, port of the chip plugin and
    integrate with the block plugin. It is now a derived class of
    Block. ChipConf is also a derived from BlockConf.
      Obsolete "./coriolis2/ioring.py", all informations are given
    though the ChipConf state class.
* New: In cumulus/plugins/alpha/core2chip, only Alliance/pxlib is
    ported yet.
2020-10-14 15:26:46 +02:00
Jean-Paul Chaput 0a5fbd9ff0 More explicit error message in EtesianEngine.setBlock() Python wrapper. 2020-10-14 15:08:26 +02:00
Jean-Paul Chaput 51c6b90160 Added property managment in @classdecorator. Unused :-( ... 2020-10-14 15:06:42 +02:00
Jean-Paul Chaput 79f3350eba More explicit error message in Cell.getNet() Python wrapper. 2020-10-14 14:58:32 +02:00
Jean-Paul Chaput 513bc72541 Port & integration of core2chip into alpha/block.
* New: In CRL/helpers/utils.py, create a Python "class decorator".
    Works like a decorator but without the need of implementing
    the Concrete/Abstract classes structure Design Pattern.
      Create proxies in the derived class for the base class
    attributes & methods.
* Change: In cumulus/plugins/alpha/block/configuration.py, enrich
    the BlockState object to support core2chip parameters. Make it
    even more autonomous from the Block class.
* New: In cumulus/plugins/alpha/core2chip, port of the core2chip plugin
    and integration with the alphs/block plugin. At "constant features"
    as a first. Only ported "cmos", phlib will be later.
2020-10-07 15:07:16 +02:00
Jean-Paul Chaput 9d56066c2d Allow consecutives '_' in VST identifiers. Replace '/' by '_'. 2020-09-30 17:15:14 +02:00
Jean-Paul Chaput 3495536268 Third variant for HFNS, trunks mades with Steiner tree (FLUTE).
Note: Keep the various hfnsX.py as toolboxes for future experiments.
* New: cumulus/plugins/block/hfns3.py, build the trunk of the
    net as a RMST. First with the "Iterative One Steiner Point"
    (terribly slow above 100 points) then with FLUTE.
      For the global routing trunk, must be very cautious to
    check that the cluster "graph point" is the one of the
    it's buffer RoutingPad so both end up in the same GCell.
* New: cumulus/plugins/block/timing.py, stub for basic
    timing computation and conversion between sink and
    capacitance. Currently based on the fake 350nm given as
    example in SxLib ("man sxlib"...).
2020-09-30 11:59:51 +02:00
Jean-Paul Chaput 8f0a8e5a3a Added support for loading user defined global routing in Anabatic.
* New: In Hurricane::NetRoutingProperty, add and change the meaning
    of the following flags:
      - ManualGlobalRoute : now means that a global routing *trunk*
        is present, made of "gmetalh", "gmetalv" & "gcontact".
      - Manualdetailroute : added, get the former meaning of
        ManualGlobalRoute, that is, the detailed routing is
	already present for this net, but can be changed by the
	detailed router. Implies that it respect the Terminal,
	HTee & VTee structuration.
* New: Add Anabatic::Diskstra::loadFixedGlobal(), to account
    a manually global net into the edges capacities.
* New: In Anabatic::Edges::ripup(), exclude manually global routed
    segments from the ripup. Change the segment sorting function
    so that thoses segments are put in head of list (considered
    as "smaller").
* Change: In AnabaticEngine::setupPreRouteds(), now detect manual
    global routed and manual detail routed signals, and tag them
    accordingly.
* New: In AnabaticEngine::Configuration & Session, add proxies
    for the global routing layers ("gmetalh", "gmetalv", "gcontact").
* New: In Anabatic::Constants, add flags for global fixed and
    detail routed nets.
* Change: In KatanaEngine::updateEstimateDensity(), now use int64_t
    for flute coordinates.
* New: Add CRL::RoutingGauge::hasLayer(), to know if a layer is
    managed by the gauge (comparison by mask).
2020-09-30 11:55:39 +02:00
Jean-Paul Chaput 18405599e8 Added Python for FLUTE (for fast RSMT in HFNS).
* New: In flute, added a Python binding. Contains two methods: "readLUT()",
    to load the POWV9.dat and POST9.dat and "flute()" to build a RSMT.
    "flute()" takes a tuple of positions (themselves 2-uple) like:
        ( (x0,y0), (x1,y1,), ... (xN,yM) )
    and returns a tuple of 3-uple of branches:
        ( (n0,x0,y0), (n1,x1,y1), ... )
    In "flute.h", set the distance type (DTYPE) to int64_t to always
    accomodate DbU::Unit.
      As it now uses the Hurricane Python interface and the path utilities
    from CRL Core, move it's compilation *after* them (see build.conf in
    bootstrap).
2020-09-30 11:52:22 +02:00
Jean-Paul Chaput ea94175eb4 In Entity, add Python bindings for "isBound()" and "getId()". 2020-09-30 11:50:09 +02:00
Jean-Paul Chaput 0c1a6def56 Basic implementation of High Fanout Net Synthesis.
To perform HFNS, recursively makes clusters of closest sinks, less than
30 sinks and with a control of the half-perimeter at all the clusters
levels. Clearly needs lots of improvements but the backbone of the
feature works. Make use of the pool buffers as do the clock tree.
Clustering is done with a degenerated Kruskal algorithm.

This is rougly based on the article:
    Buffered Steiner Trees for Difficult Instances
    Charles J. Alpert, Member, IEEE
    IEEE TCAD, Vol. 21, No. 1, January 2002
    0278–0070/02$17.00 (c) 2002 IEEE
2020-09-14 15:14:23 +02:00
Jean-Paul Chaput 42d11792a1 Bugs in NetBuilderHV for topologies containing metal3 pins.
* In NetBuilder::_do_xG_1PinM3(), in the three global case, an
    incorrect connexion was made.
* In NetBuilder::_do_2G_xM1_1PinM2(), in the global E+W case,
    segment between vtee1 <-> turn1 must be vertical.
2020-09-14 15:12:37 +02:00
Jean-Paul Chaput f249fe1efe Forgotten default parameter value for "katana.useGlobalEstimate". 2020-09-14 15:01:58 +02:00
Jean-Paul Chaput e53113ebb1 Just some manic code beatification. 2020-09-14 11:15:15 +02:00
Jean-Paul Chaput f00b8cd667 Allow RoutingPad::getPlugOccurrence() to build upon a Pin.
* Change: In Hurricane::RoutingPad::getPlugOccurrence(), it was
    forbidden to rebuild the Occurrence over anything other than
    Plug. But as we now also uses Pins, it becomes useful to
    rebuild the Occurrence on a Pin. The name of the function
    stays, even if its less meaningful now.
2020-09-11 12:56:35 +02:00
Jean-Paul Chaput 3e6d5622e8 Improvement on Python interface of Occurrence, Point & CellViewer.
* Bug: In Isobar::PyOccurrence, use "compare by value" instead of
    "compare by pointer" for the Python comparison function. So we
    really can compare identical Occurrences.
* New: In Isobar::PyPoint, export the "manhattanDistance()" function.
* New: In Isobal::PyCellViewer, add the following funtions to the
    exported interface:
    - "select()"
    - "unselect()"
    - "unselectAll()"
    - "reframe()"
    - "setShowSelection()"
    So now we can easily highlight components from Python (to ease
    debug).
* New: In Hurricane::CellViewer, create a proxy for the CellWidget
    "reframe()" function.
2020-09-11 12:55:51 +02:00
Jean-Paul Chaput 0b5ce309eb Implement QuadTree pruning to speedup the display of huge designs.
When displaying big designs, the drawing was very slow because all
the graphical objects were browsed *before* deciding if they were
big enough for display. So we introduce a new mode of working of
the QuadTree to that the ones with areas *below* a certain thresold
just get skipped. Of course, the previous behavior must be preserved
(when the threhsold is zero or negative) as most of the time, we
*want* *all* the objects under an area, not only the biggest ones.
For now, in CellWidget, the visibility threshold is set to 20 pixels.
With this, we can display the Libre-SOC "test_issuer" of 100Kgates
in between 20 to 30s.

* New: In Hurricane::QuadTree_GosUnder collection & locator, add a
    "threshold" argument so that QuadTree which both area sides are
    below that lenght will be ignored (no walkthrough at all).
      Zero (or negative) threshold means  that no QuadTree will be
    pruned, we get back to the previous behavior.
* New: In Hurricane::Slice::getComponentsUnder(), add the threshold
    argument (with a default to 0).
* New: In Hurricane::Cell::getInstancesUnder(), add the threshold
    argument (with a default to 0).
* New: In Hurricane::Query, added support for the threshold parameter.
    In doQuery(), instances that have *both* side under the threshold
    are pruned (slightly different from QuadTree areas).
* New: In Hurricane::CellWidget::_redraw(), set the visibility
    threshold to 20 pixels (arbitrary, must be parametrized).
* New: In Hurricane::Cell, added destroyPhysical() method.
    Remove *all* physical components and the DeepNets (so make
    a virtual *unflatten*) in the correct dependency order.
    In particular, RoutingPads, that relies on Occurrence over
    physical components must be destroyeds *before* the entity
    they are based on is destroyed.
2020-08-27 19:14:44 +02:00
Jean-Paul Chaput 083e58d953 Add CRL::Catalog and Net::getRoutingPads() to the Python interface.
* New: In CRL::PyAllianceFramework, export getCatalog(), in PyCatalog,
    export the getState(name) method and add a PyCatalog_Link().
    In PyCatalogState, add PyCatalogState_Link(), cannot use the
    macro because of the C++ name resolution operator (Catalog::State).
* New: In Isobar, export the RoutingPads collection to the Python interface.
* New: In Hurricane::Net, export the getRoutingPads() method to the
    Python interface (hence the need of the previous export).
2020-08-21 16:00:50 +02:00
Jean-Paul Chaput 1c6a9b64b0 Fix missing update session in block/spares.
* Bug: In cumulus/plugins/alpha/block/clocktree.ClockTree.splitClock(),
    forgot to wrap inside an UpdateSession.
* Bug: In cumulus/plugins/alpha/block/clocktree.spares.raddTransNet(),
    forgot to set the masterNet for recursive call when the plug already
    exists.
2020-08-12 22:55:29 +02:00
Jean-Paul Chaput 51e3639687 Added multiple clock support in cumulus/plugins/alpha/block.
* New: Added multiple clock support in H-Tree generation in alpha/block.
* New: In CRL/etc/<NODE>/<TECH>/plugins.py, added three new parameters
    for block plugin config:
      "block.spareSide" : The size of the minimum side of a buffered area.
                          (quad-tree leaf).
      "spare.buffer"    : The model of the cell buffer to be used.
      "spare.maxSinks"  : max number of sinks on a buffer before issuing
                          a warning (non-blocking).
* Bug: In Etesian::BloatCell::getAb(), never apply the bloat profile to
    fixed cells. In case of buffers from the spare maxtrix it was leading
    Coloquinte to detect an overlap of fixed cells, which it do not
    support (rightly so).
2020-08-11 14:49:07 +02:00
Jean-Paul Chaput 38375fd9ae Export isCLOCK() in AllianceFramework Python interface. 2020-08-11 14:47:44 +02:00
Jean-Paul Chaput fa062daa99 Tweaks in CRL/helpers Trace & CfgCache.
* Change: In CRL/helpers.Trace, flush stderr before issuing the trace
    message to avoid mixing up stdout & stderr (sometimes misleading).
* Change: In CRL/helpers.overlay.CfgCache, no longer display all the
    applied setting after a call to apply(). Too verbose.
2020-08-11 14:47:03 +02:00
Jean-Paul Chaput fa15331793 Simpler allocation of regex in CRL::Environment.
* Change: In CRL::Environment, regex_t are now pointers instead of values,
    this way the "in initialization" flag can be removed (maybe still too
    complicated).
2020-08-11 14:46:31 +02:00
Jean-Paul Chaput 0c6db7e8b9 More explicit throw messages in Coloquinte/legalizer.cxx. 2020-08-11 14:45:57 +02:00
Jean-Paul Chaput a91b92acfa Bug, forgotten self in block.Side (thanks LKCL). 2020-08-07 13:35:53 +02:00
Jean-Paul Chaput 77a41674bc Shift dogleg created from EAST pins (M2) from one P-Pitch left.
* Bug: In Anabatic::AutoHorizontal::_slacken(), when creating the target
    dogleg, if the target was a fixed pin (M2) on the east side, the
    vertical was put righ on the side, which is *not* an allowed track.
    The exact east side is not covered by a vertical track (this comes
    from a policy adpopted for the GCell, to avoid overlapping tracks
    on the border). So we got an error message when katana tries to
    bind it to a track. Now shift one perpandicular pitch to the *left*
    for the EAST pins.
2020-08-07 12:37:26 +02:00
Jean-Paul Chaput 5e85757dea Bad asserts in Coloquinte rough_legalizer.
* Bug: In Coloquinte::rough_legalizer, when running in debug mode,
    some assert where popping up. But, in normal mode the placer
    just went fine. So we assume they where too broad in their
    scope. Commented out.
2020-08-07 12:36:45 +02:00
Jean-Paul Chaput f9ea7509df Bug fix, correctly transmit the editor when processing sub-block. 2020-08-06 15:05:25 +02:00
Jean-Paul Chaput 7777d03f3a Correct too rigid topology in NetBuilderHV::_do_1G_xM1_1PinM2 (E/W).
* Change: In Anabatic::NetBuilderHV::_do_1G_xM1_1PinM2(), the M2 pin
    (horizonal) was directly aligned with the outgoing global through
    a H-Tee. This was too rigid. Now it can be misaligned.
2020-08-06 15:04:45 +02:00
Jean-Paul Chaput 140d6f20dc Increase the "reserve" length when moving up long wires (ARM run-17).
* New: In Katana::Manipulator::moveUp(), if the length of the wire is
    greater than 60 pitchs, increase the reserve from 0.5 track to
    1.0 track. This is to left more free tracks when lots of very
    long segments are moved up. Make the run 17 of the ARM test bench
    pass.
2020-08-06 15:04:18 +02:00
Jean-Paul Chaput 748289ad7e Correct context for error message in EtesianEngine::setDefaultAb(). 2020-08-05 01:29:37 +02:00
Jean-Paul Chaput 85d7714910 Solve algorithmic execution time of Anabatic layer assignement.
* Change: In AnabaticEngine::_desaturate(), now use a STL priority
    queue built upon a vector with duplicates of the GCell keys.
      Much much more faster than the previous set with a custom
    sorting key over the GCell. Insertion & removal where getting
    a lot of time. Now it's down to less than a minutes, even for
    big designs.
* Change; In Anabatic::GCells, add the ability to clone the GCell
    key, to use it independently in GCells sorting containers.
      This way the cloned value do not change when the GCell is
    updated. Keep track of the latest (most up to date) cloned
    key.
2020-08-05 01:27:26 +02:00
Jean-Paul Chaput 78b7e683e5 Add a context manager to helpers.overlay.CfgCache.
* New: In CRL/helpers.overlay.CfgCache, add support for context manager,
    so we can progressively remove the use of Configuration. One class
    to use in all contexts (immedaite setting or storing a set of
    Cfg parameters).
2020-08-05 01:26:16 +02:00
Jean-Paul Chaput 5027d5d5ef Bug in error message in AutoContact::getLentgh(). 2020-08-05 01:25:12 +02:00
Jean-Paul Chaput e3515ab900 Don't skip fixed instances in Etesian, stupid!
* Bug: In Etesian::toColoquinte(), inadvertently stopped taking into
    account fixed instances... Compute correctly the number of
    instances to place (all instances minus fixed ones..).
2020-08-03 21:58:38 +02:00
Jean-Paul Chaput 79c5f4db58 Already placed blocks must be flagged as FIXED instead of PLACED.
* Bug: In cumulus/plugins/block/block.py, when a block is found to have
    a layout, that is, is already placed & routed, it's instances must
    be flagged as FIXED instead or PLACED so Etesian will really sees
    them as unmovable and don't account them to be placed.
2020-08-03 19:43:03 +02:00
Jean-Paul Chaput 63854d80c1 Just skip placement when there is no instances to place.
* New: In EtesianEngine::toColoquinte(), fixed blocks must not be
    accounted as instances to be placed.
      When, there is no instances to place, just issue an error message
    and return.
2020-08-03 19:39:09 +02:00
Jean-Paul Chaput ea38329de1 * Bug: In CellCollection::Cell_HyperNetRootNetOccurrences::progress(),
skip Nets that are inside Terminal Netlist master cells. Was done
    ine the locator constructor but forgotten in the progress().
2020-08-03 19:35:21 +02:00
Jean-Paul Chaput 86b184dd1e Bug fix: Bad topology in NetBuilderHV::_do_2G_xM1_1PinM2() again.
* Bug: In Anabatic::NetBuilderHV::_do_2G_xM1_1PinM2(), in the case of a
    bend of global wires, the topology was faulty. Too rigid topology,
    the global wire was forcibly aligned on the external Pin.
2020-08-03 19:28:16 +02:00
Jean-Paul Chaput c63827681a Remove forgotten debug message in KatanaEngine::annotateGlobalGraph(). 2020-08-02 23:02:08 +02:00
Jean-Paul Chaput 6210a08e99 Forgotten some pages of the generated documentation. 2020-08-02 18:22:28 +02:00
Jean-Paul Chaput 3b700baec0 Be more Python3 compliant and replace "beta" menu by "alpha". 2020-08-02 18:20:27 +02:00
Jean-Paul Chaput 835e7264fe New: Cumulus Stats plugin, for trans-hierarchical statistics. 2020-08-02 18:19:05 +02:00
Jean-Paul Chaput 4d1acc35ab New: Reimplementation of the Cumulus Block plugin (in alpha). 2020-08-02 18:18:40 +02:00
Jean-Paul Chaput f211cae69a New: Parameters hTrackReservedMin in Katana.
* New: In Katana::Configuration, two new parameters hTrackReservedMin
   and same for V. Forced decrease of all edges capacities, to use
   when the global router is too optimistic...
2020-08-02 18:16:21 +02:00
Jean-Paul Chaput d6b90a70ab Enable Etesian to compute AB of fixed width.
* New: In EtesianEngine::setDefaultAb(), add computation of AB when
    using fixed width (fixed height) was already available.
      Add attribute management for the fixed width along with a
    Python export.
2020-08-02 18:15:15 +02:00
Jean-Paul Chaput 5498ad9ecb Bug fix: Never slacken a segment from a Pin.
* New: In Anabatic::AutoContactTerminal, new method "isOnPin()" to
    know if the terminal contact is on a Pin. Introduced in base
    class.
* Bug: In Anabatic::AutoHorizontal::_canSlacken() & AutoVertical,
    forbid slackening from a Pin. As Pin are all on the side of the
    cell (aligneds) and the perpandicular segment will be locked on
    the Pin, it generates intractable overlaps for the router.
2020-08-02 18:13:47 +02:00
Jean-Paul Chaput be2f9f8a45 Bug fix: Always select the Pin as best RoutingPad component.
* Bug: In Anabatic::Configuration::selectRpComponent(), always select
    the Pin as the best component. It is mandatory for a block that
    we pick up the terminal at the periphery and not one deep inside
    the block.
* Bug: In Hurricane::RoutingPad::setOnBestcomponent(), same rule as
    in Anabatic, if there is any, the Pin must always be the best
    RoutingPad component.
2020-08-02 18:12:52 +02:00
Jean-Paul Chaput a971f6f91b Bug fix: Bad topology in NetBuilderHV::_do_2G_xM1_1PinM2().
* Bug: In Anabatic::NetBuilderHV::_do_2G_xM1_1PinM2(), in the case of a
    bend of global wires, the topology was faulty. Badly connected HTees.
2020-08-02 18:11:39 +02:00
Jean-Paul Chaput de6308d8d4 Bug fix: ApDriver was not saving "blockageX" layers.
* Bug: In CRL/ApDriver/toMbkLayer(), add translation entries for
    converting "real" blockage layers. So they don't get ignoreds...
2020-08-02 18:09:46 +02:00
Jean-Paul Chaput 1e3788d93e New Python class helpers.overlay.CfgCache.
* New: In CRL/helpers/overlay.py, CfgCache class to hold a set of
    configuration parameters and apply it on demand. It has a
    different behavior than Configuration.
2020-08-02 18:09:02 +02:00
Jean-Paul Chaput 3996a8e15d Change: In Hurricane::CellViewer, rename "beta" menu to "alpha". 2020-08-02 18:08:14 +02:00
Jean-Paul Chaput 0745498505 Export the Pin name and direction to the Python interface.
* New: In Hurricane::PyPin, export ::getName() and ::getPlacementStatus().
2020-08-02 18:07:27 +02:00
Jean-Paul Chaput 134044ee99 Bad indentation in oroshi/dtr.py (from latest merge). 2020-07-22 17:26:28 +02:00
Marie-Minerve Louërat 7ae37a2ac3 Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel
Conflicts:
	oroshi/python/dtr.py
2020-07-22 15:05:00 +02:00
Marie-Minerve Louërat be0255c27b Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel
Conflicts:
	oroshi/python/dtr.py
2020-07-22 15:00:19 +02:00
Jean-Paul Chaput 17ecfd823b Enhanced techno rule support. Inspector support bug fix.
* Bug: In Hurricane/Commons.h, modify the getRecord<>() templates so
    that for both vector<Element> and vector<Element*>, the individual
    record created for each element are donne with pointers. That is,
    for the vector<Element> case, we take a pointer.
      As a general policy, except for the POD types, always use pointers
    or references to data in the records/inspector. Never uses values
    that can call the copy constructor.
      Suppress INSPECTOR_PV_SUPPORT() macro, keep only
    INSPECTOR_PR_SUPPORT().
      Provide value support only for getString<>() template.
      This value & copy constructor problem was causing a crash when
    trying to inspect Hurricane::AnalogCellExtension.
* New: In Hurricane::Technology, change the API of the PhysicalRule,
    now we can only create/get PhysicalRule, but setting the value of
    the rule itself must be done on the rule.
      Enhance PhysicalRule to provide for stepped rules, non isotropic
    and ratio rules.
      Merge TwoLayersPhysicalrule in PhysicalRule, much simpler to
    suppress the management of derived classes. That means that we
    loose a little memory as some fields are mutually exclusive.
    Not a problem considering that there will not be so many of thoses
    objects.
* New: In CRL/helpers.analogtechno.py, enhanced DTR support for rules
    like:
      ('minSpacing'  , 'metal1', ((0.4,20.0), (0.8,1000.0)), Length, 'REF.1')
      ('minEnclosure', 'metal1', 'cut1', (0.2,0.3)         , Length, 'REF.2')
      ('minDensity'  , 'metal1', 0.30                      , Unit  , 'REF.3')
      The DTR parser has been updated, but not the oroshi.dtr Rule
    cache for analog components. Given a rule name, the value used
    will be the horizontal one of the first step.
* Change: In hurricane/doc/hurricane, re-generate the documentation
    with updated support for Technology & PhysicalRule.
2020-07-21 11:22:04 +02:00
Jean-Paul Chaput 34c1795630 Support for long in CRL/overlay.Configuration.__setattr__(). 2020-07-14 19:55:20 +02:00
Jean-Paul Chaput 960e0cda18 In CRL::NamingScheme::vlogTovhdl(), remove '%' invalid VHDL character. 2020-07-14 19:53:34 +02:00
Jean-Paul Chaput 8ce2a7e318 In Etesian, do not reset the placement if we are using a sub-block.
* Bug: In EtesianEngine::place(), reset the placement *only* if we are
    *not* placing a sub-block *and* the top cell abutment box is empty.
* Bug: In EtesianEngine::place(), set the instance placement status of
    all intermediate instances to PLACED, so the AP driver will save
    them (we were having partially saved layout when using hierarchical
    designs).
* Bug: In EtesianEngine::resetPlacement(), reset the PLACED flag and
    the abutment box on the top cell or sub-block to be placed.
2020-07-14 19:51:01 +02:00
Jean-Paul Chaput e4041d5e26 Improved Hurricane/Python database reset.
* Change: In CRL/helpers/__init__.py, to ensure a complete restart of
    the database the __init__.py must be called again, but it's not the
    case with reload() (see Python doc). So helpers.resetCoriolis()
    must explicitly removes the Coriolis related Python modules from
    sys.modules (calling "del sys.modules[moduleName]").
      That list of Coriolis Python modules is built by calling
    helpers.tagConfModules(), it will tag all modules added to
    sys.modules since startup. It will remove (much) more than
    Coriolis modules, but that should be ok.
* Change: In CRL/etc/{node*,symbolic}/TECH/__init__.py, add a call to
    helpers.tagConfModules() for the techno modules to be erased on
    reset.
2020-07-14 19:49:54 +02:00
Marie-Minerve Louërat e7bf8022f7 Ajout de règles 2020-07-09 17:05:57 +02:00
Jean-Paul Chaput 010fc79f4f Added rule minWidth_nWell to oroshi rule loader. 2020-06-30 14:54:42 +02:00
Jean-Paul Chaput 441cb71475 * New: In Anabatic::NetBuilder, to tackle once and for all the GCell
configurations for Libre-SOC manage up to 9 METAL1 terminals in
    1G to 4G configurations.
2020-06-30 10:00:29 +02:00
Jean-Paul Chaput 424b66e671 Added new GCell configurations to handle Libre-SOC test_issuer.
* New: In Anabatic::NetBuilder, some GCells configurations of Libre-SOC
    "test_issuer" (soclayout/experiments9) did have more METAL1 terminals
    than was though possible. Just added more entries in the connexity
    table for bigger numbers of METAL1. No new configuration was added,
    used the already existing ones.
2020-06-29 13:02:27 +02:00
Jean-Paul Chaput f3dd4bcd31 Fixes cumulus recursive save plugin.
* Bug: In cumulus/plugins/rsave.py, use "Cell.isTerminalNetlist()"
    instead of "Cell.isTerminal()" to find the hierarchical stop
    points.
      If the root cell to be saved is itself a *terminal netlist*
    one, save it anyway. The top level *must* be saved regardless to
    it's status.
2020-06-26 17:13:52 +02:00
Jean-Paul Chaput b48f9b40b8 Fixes bad VHDL port map assignment for vectors in VST driver.
* Bug: In CRL/Vhdl::VectorPortMap::toVhdlPortMap(), two problems:
    1. Bad condition for the use of VstUseConcat. Must be used *only*
       when there is more than *one* mapped name.
    2. Missing case, when there is exactly *one* mapped name, that
       means that we have one full width vector to vector assignement.
       There may be another weakness here, for the portmap we assumes
       that both vector are mapped in the *same* direction (which is
       "downto" by our convention).
    3. In the "bit by bit mapping case" (every bits of the vector are
       differents bits), use the "signal + bit index" name instead of
       juste the signal name (i.e. full width).
    Solves the Libre-SOC/soclayout/experiment6/fpmul64 problem, now
    we can avoid the YOSYS_FLATTEN.
2020-06-26 17:13:18 +02:00
Jean-Paul Chaput b23f620c5d The VST driver may suppress linkage type.
* Change: In Vhdl:::Signal::toVhdlPort(), in Alliance VST signal with
    undefined directions are typed "linkage". This may not be compatible
    with vasy, so allow to replace them by "in".
* New: In CRL::Catalog::State, add a new flag VstNoLinkage to tell if
   the VST driver should not use the "linkage" type.
* Change: In Vhdl::Entity, add a VstNoLinkage flag to disable the use
    of the "linkage" type.
2020-06-24 23:27:21 +02:00
Jean-Paul Chaput 1ccb9c340f Add setters for space margin and aspect ratio in Etesian.
* Change: In EtesianEngine, add setters for space margin and aspect ratio.
    Export them in Python.
2020-06-16 21:39:10 +02:00
Jean-Paul Chaput b0a3bb33af Add early error detection for misaligned Pins.
* Change: In AnabaticEngine::checkPlacement(), add a check on all the
    external pins for preferred layer direction and routing grid
    alignement.
2020-06-16 21:38:21 +02:00
Jean-Paul Chaput 235a9eecea Adjustements to the ExceptionWidget behavior.
* Change: In Hurricane::ExceptionWidget,
    - Use a QTextLabel instead of a QLabel, make it "look like" a QLabel.
    - Always display using text mode. Not HTML (to preserve indentation).
    - Make the text of the error message selectable.
    - Make it resizable.
2020-06-16 21:37:18 +02:00
Jean-Paul Chaput 9c082230b5 Add forgotten asDouble() method to the Parameter interface.
* New: In vlsisapd/PyConfiguration, add asDouble() to the Parameter
    Python wrapper.
* New: In CRLCore/helpers/overlay, add support for float parameters
    in configuratuon.
2020-06-16 21:33:33 +02:00
Jean-Paul Chaput 09192ba084 Bug fix, check for unconnected signals in CRL::VectorPortMap::toVhdlportMap().
* Bug: In CRL::VectorPortmap::toVhdlPortMap(), unconnected bits where
    correctly checkeds for multi-bits vectors (both ordered and holed),
    but not for mono-bits connections (ONE bit of a vector).
2020-06-09 14:08:08 +02:00
Jean-Paul Chaput 5d891b2cd8 The VST driver is now allowed to preserve the case of identifiers.
* New: In CRL::NamingScheme, add a flag VstNoLowerCase, and its
    management it in the Verilog to VHDL converter.
* Change: In CRL::BlifParser::Model::toVhdlModels(), disable the
    lowercasing of identifiers. We shouldn't apply Alliance VHDL
    subset constraits when reading blif files. So we will see
    uppercase identifiers in Coriolis.
* Change: In CRL::VstParser, no longer lowercase identifiers that
    are *not* VHDL keywords. Uppercases are legals in VHDL...
* New: In CRL::Catalog::State, add a new flag VstNoLowerCase to
    tell if the VST driver should keep the uppercases.
* Change: In CRL::VhdlEntity, add a VstNolowerCase flag to disable
    the lowercasing.
* Change: In CRL::vstDriver, lower case the file name if needed.
    remove the previously opened filename if it differs from the
    lowercased one.
* Change: In UnicornGui CTOR, disable VHDL enforcement for the
    Blif parser.
2020-06-08 13:34:25 +02:00
Jean-Paul Chaput f91fc4f927 Add experimental matrix placer into cumulus.
* In cumulus.plugins.matrixplacer.py, BETA plugins for getting back
    matrix-like netlists placement. This plugin is configured *ONLY*
    for Libre-SOC FU-FU matrix 30x30.
2020-06-06 12:16:51 +02:00
Jean-Paul Chaput f2a60768ca Export Entity::getId() to the Python interface. 2020-06-06 12:13:57 +02:00
Jean-Paul Chaput 7b1dab7742 Generate only one/zero cell in Blif parser.
* Change: In CRL::BlifParser, formerly, a zero/one cell was added for
    each vss/vdd direct connection, generating a huge flock of cells.
    Now only generate one per netlist.
      It can be discussed whether to old behavior is more desirable,
    it is a compromise between wire and area.
2020-06-06 12:13:29 +02:00
Jean-Paul Chaput ac04466090 Automatically try to load the layout of Terminal Cells.
* Change: In CRL::AllianceFramework::getCell(), if the Cell is marked
    as TerminalNetlist, then it may be a standard cell. So it's layout
    must be loaded. So now, systematically try to load the layout of
    netlist terminal cells.
2020-06-06 12:13:05 +02:00
Jean-Paul Chaput c6287c8d95 Correct Cell object detection while reading Oceane parameters.
* Bug: In karakaze/AnalogDesign.readParameters(), when asserting the
    type of dspec[0], it can either be a type (for analog devices) or
    a Cell object (*not* a type). So the issubclass may fails.
      Now check first if dspec[0] is an *instance* of Cell.
      This is an anisotropy in the type of the first element of
    the devicesSpecs table, but suppress one superfluous parameter.
2020-05-27 16:11:53 +02:00
Jean-Paul Chaput 4483766f34 Enabled support for track positionning in analog Transistor devices.
* New: In Analog, new Parameter derived class "StringParameter",
    to support strings. Also added to the Python interface.
* New: In Analog::Transistor, added StringParameters for specifying
    track positions. They are named "G.t", "S.t", "D.t" and "B.t".
* New: In Oroshi/wip_transistor.py, now read the track positionning
    devices parameters.
* New: In Karakaze/AnalogDesign.doDevice(), read an optional 14th
    parameter holding the track positions (example in ADC-SAR).
2020-05-11 15:59:45 +02:00
Jean-Paul Chaput 7dcd8e136a Suppress wrong errors/warnings in AnabaticEngine & AutoSegment.
* Bug: In Anabatic::AutoHorizontal & AutoVertical, in getGCells()
    method, do not display the "NULL GCell under" error message if the
    segment has just been created. It could on a "wrong" axis position
    so the line probing method may fail.
* Bug: In AnabaticEngine CTOR, if the "blockagenet" is created there,
    do not forget to set it's type to BLOCKAGE (to avoid later warnings).
* Bug: In Anabatic::NetBuilder::_load(), do not display a warning if the
    blockage net has no RoutingPads (it *must* not have one).
2020-05-10 17:09:33 +02:00
Jean-Paul Chaput faef4b182f Manage all devices in karakaze/AnalogDesign.readParameters().
* Change: In Karakaze/analogdesign/AnalogDesign.readParameters(),
    only Transistor and Capacitors where manageds. So when a devices in
    the dspec was from another type, it did issue an error.
      Now cleanly skip unsupported (yet) devices.
2020-05-10 11:47:30 +02:00
Jean-Paul Chaput b553aae8ad Correct icon sizing for normal definition display in BreakPointWidget. 2020-05-10 11:46:54 +02:00
Jean-Paul Chaput dc25159cd6 Bug fix, reset Cell flags after unrouting an analog design.
* Bug: In Bora::SlicingNode::clearGlobalRouting(), as we are unrouting the
    cell, the flags set up by Katana must be reset. The Cell is no longer
    "Terminal" and it's nets are "Un-flattened".
2020-04-30 00:38:32 +02:00
Jean-Paul Chaput bd4ace7cc8 Full update of the generated documentation. 2020-04-27 14:14:03 +02:00
Jean-Paul Chaput 2b4ee3abea Update docker config for Debian-10 / LibreSOC. 2020-04-27 14:11:44 +02:00
Jean-Paul Chaput 477c37643c Bug, In Session::_revalidateTopology(), iterate over an invalid vector!
* Bug: In Anabatic::Session::_revalidateTopology(), when iterating over
    _segmentInvalidateds, the vector can be modified. If it leads to a
    reallocation we end up on invalid iterators (using freed memory so
    sometimes with overwritten contents). Now, iterate with an index
    which warranty that we get a valid item at each iteration of the
    loop. And, of course, the vector is ensured to not shrink...
* Change: In Anabatic::Session::Session(), reserve (pre-allocate) at least
    1024 elements for all vectors. Mostly prevent the above bug and
    avoid constant reallocation.
2020-04-27 11:22:05 +02:00
Jean-Paul Chaput 3dbaea6aca Bug fix, restore the FreePDK 45 (real) support.
* Change: In CRL::LefParser::_macroCbk(), create a Catalog entry for the
    newly read MACRO (that is Cell) and sets the Logical, Physical,
    InMemory and TerminalNetlist flags.
* Bug: In CRL::LefParser::_siteCbk(), check for NULL cell gauge.
* New: In CRL::AllianceFramework, add setCellGauge(), to set the default
    cell gauge. Exported to Python.
* Change: In CRL/etc/common/technology.py, create variables for VIA
    layers, so we can modify their properties afterwards.
* New: In CRL/etc/node45/freepdk45, port the configuration files to the
    new Python "importable" format.
      Note: in kite.py, all the gauges (Routing & Cells) must be named
    "LEF.CoreSite" to please my LEF parser, so it can match the gauge
    name with the SITE name for standard cells.
* Bug: In Anabatic::NetBuilderVH::_do_2G(), forgotten to be reimplemented
    from the base class. Simply redirect to _do_xG().
* Change: In Katana::PowerRailsPlanes::PowerRailsplanes(), create plane
    from the layers in the RoutingGauge and their associated blockages
    instead of sweeping through all the basic layers.
      Allow to distinguish bewteen "METAL" (symbolic) and "metal" (real).
2020-04-27 10:34:19 +02:00
Jean-Paul Chaput e7bc4dc167 Bug fix, In Katana, do not remove AutoSegment conflicting with blockages.
* Bug: In Katana::NegociateWindow::createTrackSegment(), *fixed* AutoSegment
    in conflict with blockage where removeds. This was creating "holes"
    in the Anabatic articulated segment structure. Now just *don't*
    create the TrackSegment. Pass the regression tests, but not sure
    it is not generating problems elsewhere.
* New: AnabaticEngine::checkPlacement() to issue more clear errors about
    a defective placement.
2020-04-21 15:40:59 +02:00
Jean-Paul Chaput a4acb22e3c Bug fix, make the AP parser reentrant (NO static variables).
* Bug: In CRL::ApParser::_parseInstance(), the instance coordinates where
    stored in *static* variables (boo). Making the parser *not* reentrant.
    But in _parseInstance(), it can be recursively called through
    getCell() when an sub-instance layout was missing.
      Also make non-static all other variables in the various parser
    function.
2020-04-21 15:39:35 +02:00
Jean-Paul Chaput 0a664fed36 Support for multiple M1 connectors in GCells with M3 pins.
* Change: In Anabatic::NetBuilderHV(), in 2-3 globals plus one M3 pins,
    support up to 3 M1 connectors.
2020-04-20 20:53:49 +02:00
Jean-Paul Chaput 8978074fe7 Added new configuration in NetBuilderHV (for M3 Pins).
* New: In Anabatic::NetBuilderHV(), added configurations to manage
    one Pin M3 + one M1 terminal plus 2 & 3 globals:
      * _do_2G_1M1_1PinM3()
      * _do_3G_1M1_1PinM3()
    They were occuring for the first time in soclayout/experiment7
    in the "flat" approach.
* New: In Katana::runNegociate(), mark the newly routed netlist as
    "NetlistTerminal" so it is not placed and routed *again* when
    reused as an instance (mostly interract with Etesian).
2020-04-20 12:53:07 +02:00
Jean-Paul Chaput 010d9a3782 Clean policy of netlist (vst) and layout (ap) views recursive loading.
* Bug: In CRL::VstParserGrammar & VstParserScanner, when loading the
    instances models, we where loading both logical & physical views.
    This was causing cases of reentrency of the parser, with reset
    of the lexer static dictionary, leading to memory corruption.
      Now the identifiers are stored in the YaccState of each
    parsed cell and we only recursively call for the logical view.
* Change: In CRL::ApParser::_parseInstance(), recursively load the
    physical views as they are no longer loaded by the Vst parser.
* Change: In CRL::AllianceFramework::getCell(), sets the
    TerminalNetlist flag from the state (mode 'C' in CATAL) onto
    the cell.
* Change: In EtesianEngine::loadLeafcelllayouts(), new functions to
    load the layouts of the leaf cells if only the netlist has been
    loaded.
2020-04-17 11:28:47 +02:00
Jean-Paul Chaput 5a4d23f8fd Fix bad direction for segments in ApDriver.
* Bug: In CRL::ApDriver::DumpSegments(), reset the direction field to
    NULL between iterations so it is recomputed for each component and
    not keeping the first one ever guessed.
2020-04-15 10:42:38 +02:00
Jean-Paul Chaput 05c0907d5c Fix for Coriolis issue #6 (Katana core dump on ALU16).
* Bug: In Katana::AutoSegment::_preDestroy(), remove the segment from
    the source & target AutoContact cache.
      In LibreSOC/experiment7, weird placement caused fixed AutoSegment
    overlaping blockage to be deleteds. It seems to have never occured
    before (or at least, no ended up in core dump).
2020-04-15 10:41:46 +02:00
Jean-Paul Chaput 7e7e7170ba Improve symmetry management for analog designs.
* Bug: In Hurricane::NetRoutingState::getSymValue(), outrageously bad
    computation of the symmetric coordinate when the value was superior
    to the axis... (shame on me).
* Change: In Anabatic::Disjkstra::load(), for symmetrically paired nets,
    check that the axis of symmetry is *outside* the searchArea.
      Otherwise, the two mirrored areas overlaps and the two nets will
    unescapably be on top of each other. Issue a warning but still
    continue.
* Change: In Anabatic::Vertex::isRestricted(), allow perpandicular
    wire to go through struts or thin (less than one routing pitch)
    node. May have to recheck in the future and restrict to struts
    only.
* Bug: In Bora::HVSlicingNode::updateSymNetAxis(), rescursive call in
    child node was not systematically done (bad curly brace position).
      Also checks that symmetries are not empty before accessing the
    front element (one less core dump).
2020-04-10 12:15:23 +02:00
Jean-Paul Chaput 74e4544a55 Correct computation of H/W ratio in Bora (Igor Zivanovic).
* Bug: In Bora/SlicingDataModel, the division was done with integers,
    leading so there was a rounding *before* we casted to double.
      Now, use the BoxSet::getRatio() method and cast to double *before*
    dividing.
2020-04-08 15:09:20 +02:00
Jean-Paul Chaput a50b6ce317 More PEP8 compliant Python code. Start rewrite Python/C++ wrappers.
* Change: In CRL/helpers, cumulus/plugins, oroshi & karakaze,
    Move towards more Python PEP8 compliance:
      * All indentations sets to 4 spaces (in progress).
      * In plugins, remove messages about software collections
        and RHEL (too many case could wrongly lead to that).
	Instead systematically uses "helpers.io.catch()".
      * Put in lowercases all modules names. Note that C++ exported
        modules *keep* their Capitalized names (to preserve the
	identity with the C++ namespace).
      * When making import, use full path.
      * Rename the run function from "ScriptMain()" to "scriptMain()".
* Cleanup: In CRL/etc, remove obsoleted configuration files,
    the one ending in ".conf". Keep those who have not been ported
    to the new style yet.
* New: In Hurricane/src/configuration, first trial at replacing the
    C preprocessor macros by C++ templates. Applied first to configuration
    from VLSISAPD.
      This is unfinished business, just a limited demonstrator for now.
      It is installed as a separate Python library "Cfg2" which do not
    interact with the rest of Coriiolis.
      The end goal is to fully remove boost and merge VLSISAPD useful
    components directly inside Hurricane.
2020-04-08 11:24:42 +02:00
Jean-Paul Chaput e9ce33a857 Resistor integration.
* New: In Isobar::PyResistor, manage type RPOLYH and RPOLY2PH.
* Change: In Hurricane::Resistor, rename plate nets from "PIN1" and
    "PIN2" into "t1" and "t2" (try to respect uniform naming scheme).
* New: In Karakaze/AnalogDesign.py, support for reading Resistor
    parameters.
* New: In Orosshi, ResistorSnake.py imported from Mariam Tlili's work
    and associated Resistor.py to make parameter conversion.
      Currently we only uses vertical layout for resistors.
      Added METAL2 horizontal terminals for resistors.
2020-03-30 12:40:29 +02:00
Jean-Paul Chaput 2fa8016eaa Make Pin terminals really punctuals (bug shown in nmigen/ALU16). 2020-03-20 18:55:38 +01:00
Jean-Paul Chaput 654ae5b8a4 Added compile script for Yosys in docker (for Debian 10). 2020-03-20 15:07:41 +01:00
Jean-Paul Chaput 2af531991e Correct drive of the Pin in AP driver.
* Bug: In CRL::ApDriver::DumpSegments(), when saving RoutingPads build
    on Pin *not* at the top level (that is, Pin from an instance),
    use the pin's orientation to choose the segment type.
      * NORTH/SOUTH becomes a Vertical.
      * EAST/WEST becomes an Horizontal.
      Formerly, the segment direction was guessed only for the bounding
    box, leading to segments in incorrect directions leading to DRC
    errors (in nmigen/ALU16, net "b(10)").
* Bug: In CRL/symbolic/cmos/technology.py, forgotten import for
    WarningMessage.
2020-03-20 12:05:12 +01:00
Jean-Paul Chaput 837de500aa Compliance with Debian 10 Buster.
* Change: In all tools, FindTOOL.cmake, no longer use LIB_SUFFIX to
    search for tool libraries but try "lib64/" then "lib/".
* Change: In bootstrap/socInstaller.py, take Debian 10 into account.
* Change: In bootstrap/docker, move from Debian 9 to Debian 10.
2020-03-19 18:18:35 +01:00
Jean-Paul Chaput b07a472250 Dynamic detection of Coriolis2 library directory.
* Change: In bootstrap/coriolisEnv.py, no longer rely on the uname to
    choose the library directory (lib64 or lib), but instead look for
    those locations (lib64 gets precedence).
2020-03-15 23:58:31 +01:00
Jean-Paul Chaput a12d88040a Capacitor support, at last.
* Change: In Hurricane::DbU::setGridPerLambdas(), allow the grid per
    lambda to be even. Needed when using nsxlib libraries that are
    drawn using a "half lambda" (two lambdas to get an Alliance lambda).
* New: In Oroshi/python, integrated capacitors. Modifications and
    correction from Mariam's code:
    * No need to redefine __setattr__() on CapacitorUnit.
    * Pitch horizontally & vertically (symbolic routing tracks) the
      devices.
    * Put the horizontal access tracks on the routing pitch.
    * Sets the horitontal metal2 wires as external components and
      NOT the capacitor plates themselves.
    * Makes the size (plates) of the unit capacitor a multiple of
      the foundry grid, not a floating number...
    * Correct the net ownership of horizontal tracks in
      drawHRoutingTracks().
    * Simplification & put error management directly inside of
      __isCapacitorUnitOK__().
* New: In Karakaze/python/AnalogDesign, capacitor spec now include
    the dummy parameter.
2020-03-15 17:56:09 +01:00
Jean-Paul Chaput 2152811005 Correctly setup the breakpoint initial stop level to 1. 2020-03-10 12:22:03 +01:00
Jean-Paul Chaput dfe4d80b60 Clarify semantic of flatten Collections (walkthrough).
In the Cell/Instance hierarchy, the "terminal" and "leaf cell" concepts
where not clearly defined and partially overlapping. Now, "Terminal" is
the refer to the physical hierarchy (layout) and "TerminalNetlist" to
the logical hierarchy (netlist). The logical hierarchy can be less deep
than the physical one thanks to a Cell dedicated cell flags. Collections
related to the physical hierarchy keep their old names, the one related
to the logical hierarchy are renamed from "Leaf" to "TerminalNetlist".
The name "Leaf" was too ambiguous (leaf for *what* hierarchy).

* Change: In Hurricane::Device, set the "TerminalNetlist" flag once and
    for all. No need set it in all the derived classes again.
* New: In Hurricane::MultiCapacitor, added new parameter "dummy" to
    create dummies around the capacity matrix.
* Change: In Hurricane::Cell, remove "Leaf" related methods, replace
    them by "TerminalNetlist" one, especially Collections. Now we have
    two clear sets of Collections to walkthough the layout or the
    netlist.
      Change the "Terminal" flag into "TerminalNetlist".
* Change: In Hurricane::CellCollections, rename "Leaf" into
    "TerminalNetlist" collections and apply the new semantic to the
    locators.
* Change: In Hurricane::DataBase, Leaf to TerminalInstance renaming.
* Change: In Hurricane::DeepNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::HyperNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Instance, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Viewer::HierarchyInformations, Leaf to
    TerminalInstance renaming.
* Change: In CRL::AllianceFramework, Leaf to TerminalInstance renaming.
* Change: In CRL::Catalog, Leaf to TerminalInstance renaming.
* Change: In CRL::ApParser, Leaf to TerminalInstance renaming.
* Change: In EtesianEngine::AddFeeds, Leaf to TerminalInstance renaming.
* Bug: In EtesianEngine::resetPlacement, move there the loop over
    non terminal netlist instances to flag fully placed sub-blocks
    as terminal for the netlist. Only then remove the feed cells
    from unplaced instances. Previously, the feed cells where stripped
    even from already placed instances.
* Change: In Katana, Leaf to TerminalInstance renaming.
* Bug: In Bora::PyDSlicingNode, allow the range parameter to be the
    Python None object when we do not want to pass one but need to
    have it as positional parameter.
* Change: In Cumulus/clocktree/ClockTree.py, Leaf to TerminalInstance
    renaming.
2020-03-10 12:10:53 +01:00
Mariam Tlili e2d6929fbe Merge branch 'devel' of gitlab.lip6.fr:vlsi-eda/coriolis into devel
Conflicts:
	oroshi/python/CapacitorRoutedSingle.py
        Hidden tabulations remaining
2020-03-06 17:53:01 +01:00
Mariam Tlili 7281129850 Latest Capacitor corrections by Mariam. 2020-03-06 17:48:42 +01:00
Jean-Paul Chaput f3d5712afd Merge branch 'remove_env' into 'devel'
Allow to remove the Coriolis environment.

See merge request vlsi-eda/coriolis!1
2020-03-05 10:18:14 +01:00
Jean-Paul Chaput 59ee8358ca First working recursive place & route (Libre-SOC ALU16 benchmark).
* New: In Hurricane::Cell::isLeaf(), a leaf cell was defined as one
    without instances. Now it can be software defined with the
    "FlattenLeaf" state. If it is flagged "flatten leaf" is will be
    considered as a leaf by the trans-hierarchical walkthrough.
      This flag is also set for Cells in the Alliance CATAL.
* New: In Hurricane::Cell_LeafInstanceOccurrences::progress(), add a
    test to prune leaf cells.
* Bug: In Hurricane::getComponentOccurrences(), when calling the
    locator constructor, the "withLeafCells" argument was forgotten
    and was getting the value of "doExtraction" (wich, fortunately,
    was the same).
* Change: In Hurricane::HypreNet_LeafPlugOccurrences::progress(),
    prune the leaf cells instead of the terminal ones.
* Change: In Hurricane::HypreNet_ComponentOccurrences::progress(),
    prune the leaf cells instead of the terminal ones.
* New: In Hurricane::Cell, add a "useFlattenLeaf" mode to take into
    account or ignore the "FlattenLeaf" flag when doing trans-
    hierarchical walkthrough.
      Not sure if it shouldn't be systematic.
* New: In Etesian::toColoquinte() and other, activate the "FlattenLeaf"
    mode for all walkthough. So we can stop at already placed sub-blocks.
* Bug: In Etesian::toColoquinte(), when placed sub-block where present,
    the number of instances was under estimated, so the instance array
    was oversized and the end went unitialized. So we were getting all
    kind of strange behavior from Coloquinte...
      Now throw an exception if the number of instances differs from
    the computed size.
* Bug: In Etesian::toColoquinte(), as for the instance array, now
    correctly compute the size with the ecluded nets (supplies, clocks).
* Bug: In Etesian::resetPlacement(), event if the Cell is unplaced,
    go through the instance list to remove the potential feed cells.
      The netlist is written back after placement *with* the feed
    cells added. So, when loading again, they where cluttering the
    netlist and giving feed redefintions warning. They also generated
    erratic behaviors.
* New: In Anabatic::NetBuilderHV, added configurations for:
    * 1G_1M1_1PinM3
    * 1G_xM1_1PinM2
    * 2G_xM1_1PinM2
    * doRp_AccessNorthPin
* New: In Anabatic::NetBuilderHV, added Pin management in SingleGCell.
* Bug: In Anabatic::NetBuilderHV::_do_xG_1PinM3(), the North/South
    global routing configuration was forgotten (only East/West).
* Bug: In Katana::TrackFixedSegment, the blockage net was a static
    variable initialized at the first run. So we were getting stuck
    with the blockage net of the first cell to be routed. Of course,
    it did show only when Katana was run multiple times in the same
    process.
2020-03-04 00:50:18 +01:00
Jean-Paul Chaput 757b95343b Support for full Database clear & restart.
* New: In CRL/etc/node600/phenitec, ported configuration of Phenitec 0.6um
    Compliant with DataBase reset.
* New: In CRL/python/helpers, added function "unloadUserSettings()" to
    unload Python modules prior to a full reset.
      Added "resetCoriolis()" to perform full DataBase reset.
* Change: In CRL::AllianceFramework, make it a derived class of DBo so
    the destroy() is now provided.
* Bug: In CRL::AllianceFramework::getCell(), do not attempt any load if
    the library list is empty. Should never occur except in case of a
    botched databse reset.
* New: In CRL::AllianceFramework, new method "saveCATAL()" to write back
    the catalog of a library and "saveCells()" to write back the cells.
      Note: only cells actually loaded in memory will be write back.
* New: In CRL::Catalog, add method "saveToFile()" to write back the CATAL
    of a library.
* Change: In CRL::ParserDriver, replace "const string&" by "string"
    (improved string support of the GNU STL).
* Change: In CRL::ParserSlot, use string instead of Name.
* Change: In CRL::ApParser, make _layerInformation an ordinary attribute
    instead of a static one. This allow for it's correct resetting
    across databas resets.
* Change: In CRL::VstParserGrammar, reinitialize Vst::framework at each
    parser call. Needed to support database reset.

* New: In Hurricane::DBo, add an object counter to be sure that when
    we perform a reset, no remaining DBo is allocated. This is different
    of the object id which is ever increasing.
      Note that, at reset, we check against "1" remaining element as at
    this point only Database is still allocated.
      Add a new "resetId()" method. MUST NEVER BE CALLED except by
    DataBase::_preDestroy().
* New: In Hurricane::Database, new clear() method to remove the Cells
    of all the libraries in reverse hierarchical depth order.
    Make use of the new CellsSort class.
* Change: In Hurricane::DataBase::_preDestroy(), call "clear()" and
    DBo::resetId().
* Change: In Hurricane::Breakpoint, change the default callback to be
    a static function. So we can restore it later.
* Bug: In Hurricane::Instance::_preDestroy(), there was yet another
    loop of deletion over a collection for the shared pathes.
      Replace it by the repetitive deletion of the first element.
* Bug: In Hurricane::Net::_preDestroy(), RoutingPads must be destroyed
    prior to any other component.
* New: In Hurricane::ColorScale, add a "qtFree()" method for freeing
    the Qt Brush, Pen & Color.
* New: In Hurricane::DrawingStyle, add a "qtFree()" method for freeing
    the Qt Brush, Pen & Color.
* New: In Hurricane::Graphics, add a "disable()" method to call the
    various "qtFree()" of the sub-objects.
2020-02-29 16:55:14 +01:00
Jean-Paul Chaput eab4a4aa7f In BlifParser, correct management of alias to $true/$false for terminals.
* Bug: In CRL/BlifParser::Model::mergeAlias(), when a signal is aliased
    toward $true or $false in a Blif file (through a ".name" statement),
    it was directly merged to "vdd" (resp. "vss"), and if it is an
    external signal, this leads to its removal, potentially making "hole"
    in its interface.
      Now, create a gate zero or one for each tied up/low signal. This
    way the interface is fully kept. At the cost of some supplemental
    gates.
2020-02-24 18:58:48 +01:00
Staf Verhaegen 19ed35784c Allow to remove the Coriolis environment.
coriolisEnv.py now has a --remove option to allow to remove Coriolis settings from the shell environment.
2020-02-24 13:37:28 +01:00
Jean-Paul Chaput 5d968b0997 Add nMigen to docker & chroot images.
* New: In bootsrap/docker:
    * install python3/nMigen tool in all environment.
    * Add a new image on top of the coriolis one to have a shell
      (with X11 connexion to the host system).
    * Upgrade Yosys to 0.9.
    * Correct integration of allianceInstaller.sh in socInstaller.py.
    * Add a chroot mode to socInstaler.py (for Debian 9 chrooted).
    * Allow benchs to be run separately.
2020-02-20 00:45:52 +01:00
Jean-Paul Chaput 1d05f1278e Added 3G + 5M1 configuration in NetBuilder. Never occured before. 2020-02-19 23:24:52 +01:00
Jean-Paul Chaput 2d91df1d47 Update doc link for the new Pelican generated one. 2020-02-10 13:38:06 +01:00
Jean-Paul Chaput 068740601c Created docker images to check rebuild on various distributions.
* New: In bootstrap/docker, paraphernalia to rebuild and check Coriolis
    for Debian 9, Ubuntu 18 & SL 7 on pristine systems. Added scripts
    to rebuild Alliance as well and perform the alliance-check-toolkit
    regression tests.
* Change: Updated installation documentation. Added a section for docker.
2020-02-09 18:18:42 +01:00
Jean-Paul Chaput 6ea7a6f1f3 Forgotten socInstaller.py file in previous commit, stupid! 2020-02-09 11:45:04 +01:00
Jean-Paul Chaput 2f81f454e6 Updating socInstaller.py for docker cases.
* New: In bootstrap/socInstaller.py, partial redesign of group of commands
    to better handles all the cases. Added support for docker context,
    and added Alliance compilation "alongside" Coriolis (merged install
    tree).
* Change: In bootstrap/coriolisEnv.py, when run in a docker container we
    no longer can trust the kernel name to guess the OS, as the kernel is
    the one of the host and not the docker guest. This was causing problem
    for determining the Python site-package directory. Now just check all
    possible locations and stop at the first directory found.
2020-02-09 00:47:11 +01:00
Jean-Paul Chaput 0dc98dfce3 Migrating doc from Sphinx towards Pelican.
* Change: In documentation, now generate the overall documentation using
    Pelican instead of Sphinx. This allows to have an unified approach
    between the coriolis.lip6.fr website and the local documentation.
      So we keep using "only" two doc generators: doxygen & Pelican.
2020-02-03 17:44:15 +01:00
Jean-Paul Chaput 803c5f8ada Updated PDFs, February 03, 2020 (15:12). 2020-02-03 15:12:04 +01:00
Jean-Paul Chaput 057501a8df Capacitor & resistor integration in the Slicing Tree.
* New: In Karakaze/Oceane.py, now also read capacitor & resistors parameters.
    In AnalogDesign.readParameters(), get the capacitor parameters from
    Oceane into the "device spec" (dspec). Translate form OSI unit to
    Coriolis units (F -> pF).
* Bug: In Bora::NodeSets::create(), Capacitor matrix parameters where never
    read due to a misplaced curly brace (at the matrixRange dynamic_cast<>
    test).
* Change: In Bora/PyDSlicingNode, now check that the parameter is either
    a StepParameterRange or a MatrixParameterRange.
      Also add a check that the Instance name exists...
* Bug: In Bora::SlicingPlotWidget::updateSelectedPoint(), as we display
    only the transistor parameters in dynamic labels, do not forget to
    skip resistor and capacitor. Otherwise we end up in out of bound
    access in the vector of labels.
2020-01-23 14:07:19 +01:00
Jean-Paul Chaput eea67a9111 Added static bloat profile in Katana.
* Change: In bootstrap/FindBoostrap.cmake, remove the -fsanitize=address
    as it requires the "san" librarie which may be difficult to install.
* Change: In CRL/symbolic/cmos45/kite.py, decrease the METAL3 pitch from
    10l to 8l. This is for testing with 4 routing metal only technology
    like AMS c35b4 symbolic.
* Change: In Katana/BloatProfile, add static bloat option, that is, only
    cell bloated in the first pass will be bloated again in subsequent
    ones.
      Add a "katana.bloatOverloadAdd" parameter to more easily control the
    amount added to the computed overload.
* Change: In Oroshi, start integration of multi capacitors as generator.
    Translate generator parameter into CapacitorStack ones. Add code for
    routing unit capacitor.
2020-01-23 14:03:59 +01:00
Jean-Paul Chaput 26610ba80c Fixe bad Python exception catch for C-launched scripts.
* In Hurricane::Viewer::Script::runFunction() & callFunction(), when the
    script returns NULL, do not immediately return but first check if an
    exception has been set. If so, print it *then* clear it.
      Due to not clearing the exception we where seeing one later with
    no relation to the true problem.
* In Oroshi/python/Rules.py, a bad test structure was discarting all the
    "no layer rule with physical length" in the loading process. It was
    blocked by the physical unit rule special cases.
2019-12-19 01:18:11 +01:00
Jean-Paul Chaput 41a49809d2 Merge branch 'devel' of ssh://bop-t/users/largo2/git/coriolis into devel 2019-12-15 20:16:58 +01:00
Jean-Paul Chaput e711ce8dd2 More configuration parameters for P&R Conductor, for experimenting.
* Change: In Hurricane::Viewer::ExceptionWidget & CRL/python/helpers/io.py,
    downscale icons for non-HiDPI screen.
* Change: In CRL/etc/common/display.py, change the display threshold of
    METAL1 layer so it do not appear at high scaling.
* New: In Etesian, activate the "setFixedAbHeight()" feature and export it
    to Python. Allows to increase the space margin at constant height.
      To be used by the P&R conductor.
* Change: In Unicorn/cgt.py, when running a script, insert the current
    working directory at head of the sys.path, not at the end. So installed
    modules do not shadow local one.
* New: In Anabatic::Edge, new accessor "getRawcapacity()" to know the full
    capacity of the edge, that is, the real maximum number of tracks that
    can go through the associated side.
* Change: In Katana/BloatProfile/Slice::tagsOverloaded(), bloating policy
    change, now bloat all the instances under the GCell, not only the first
    one.
* Change: In KatanaEngine::runGlobalRouter(), restore the search halo growth
    policy to expanding of 3 GCells every 3 iterations.
      New metrics displayed, the edge wire length length overload.
* Change: In cumulus/plugins/ConductorPlugin.py, now accepts the following
    configuration parameters:
      - "anabatic.globalIterationsEstimate", maximum number of global
        iterations during the bloating computation passes.
      - "conductor.useFixedAbHeight", tells wether the additionnal blank
        space must be added so the aspect ratio is kept or the height is
	kept (and the block become wider).
    Disable the display of "rubber" to unclutter a little the view.
2019-12-15 19:28:54 +01:00
Mariam Tlili f269c6b523 Merge branch 'devel' of https://www-soc.lip6.fr/git/coriolis into devel 2019-12-12 14:30:52 +01:00
Mariam Tlili f77801b3fb Added nun-unit capacitor & single routed capacitor. 2019-12-12 14:29:57 +01:00
Mariam Tlili e1389f501a First integration of Resistors (straight & snake). 2019-12-12 14:23:35 +01:00
Jean-Paul Chaput 9812f2fc3a Corrections to build under MacOS X. 2019-12-11 22:13:47 +01:00
Jean-Paul Chaput 09eccacfee Various fixes for Katana::BloatProfile.
* Bug: In Katana::BloatProfile::FlatInstance for X & Y calculation of
    flattened instances reserse the order of transformation. We must apply
    the occurrence path transformation to the instance transformation,
    and not the other way around.
      Was causing the bug in SNX example.
* Bug: In Katana::BloatProfile::Slice::tagOverloadeds(), the underlying
    Gcell was not kept in synch with the instance. This was causing a right
    shift of the bloated area.
* New: In Katana::BloatProfile, add the selection of overloaded edges and
    failed nets.
      Add a flag to KatanaEngine::runGlobalrouter() to choose what failed/
    overloaded components to display (selectors).
2019-12-11 11:17:32 +01:00
Jean-Paul Chaput 8cc2d9f06e Allow 45/135 degrees edges in Hurricane::Rectilinear. 2019-12-09 13:44:19 +01:00
Jean-Paul Chaput f04d07cd22 Commented the wron line in cumulus plugins install commands... 2019-12-09 13:04:22 +01:00
Jean-Paul Chaput 68e45bc5ab Groudwork for routing density driven placement. Compliance with clang 5.0.1.
This commit contains two set of features that should have been commited
separately.
  1. Compliance with clang 5.0.1, tested with the RedHat collection
     llvm-toolset-7. This allow Coriolis to be compiled under Darwin (MacOS)
     with Xcode & macports. The bootstrap install system has been modificated
     accordingly.
  2. The basic support for routing density driven placement. Related
     features are:
     * Bloat property. Each Occurrence of an Instance can be individually
       bloated. This property not attached to any tool to allow the placer and
       router to share it as wanted. Nevertheless, it is defined in Etesian.
     * BloatProfile in Katana, add individual Bloat properties to Instances
       occurrences based on the East & North overflowed edges of each GCell.
     * Support in ToolEngine for a "pass number" of a tool. This pass number
       is mainly used to make "per pass" measurements. The MeasureSet system
       is improved accordingly to support multiple values of a same measure.
     * Embryo of "P&R Conductor" to perform the place & route loop until the
       design is successfully placed. May be the first brick of a Silicon
       Compiler.

* Change: In boostrap/FindBoostrap.cmake, in setup_boost(), added tag to
    the python component for macport (ex: python27).
* Change: In boostrap/build.conf, put etesian before anabatic for
    instance occurrence BloatProperty dependency.
      Added option support for the "llvm-toolset-7" collection to build
    against clang 5.0.1.
* Bug: In Hurricane::getRecord( const pair<T,U>& ), the getSlot<> templates
    for first & second arguments must be called with <const T> and <const U>
    as the pair itself is const (and not simply <T> & <U>).
* Change: In Hurricane::getSlot() temlate, only use "string" arguments and
    not const string&, simpler for template argument deduction.
* Bug: In Hurricane::AnalogCellExtension, the StandardPrivateProperty<>
    template has a static member "_name". Clang did show that the template
    for this static number has to be put inside the namespace where the
    template *is defined* (i.e. Hurricane) instead of the namespace where
    it is instanciated (i.e. Analog).
* Bug: In Isobar, Matrix_FromListOfList(), PyInt_AsPlacementStatus() must
    be put outside the C linkage back in the Isobar C++ namespace (clang).
* Bug: In Hurricane::DBo::~DBo, and derived add a throw() specification
    (clang).
* Bug: In Hurricane::RegularLayer::getEnclosure() & setEnclosure(), change
    signature so it matches the one of the base class (clang).
* Bug: In Hurricane::CellPrinter, use double brackets for initializer list
    (clang).
* Change: In Hurricane::Breakpoint, reverse the meaning of the error level.
    Only error level *lesser or equal* than the stop level will be enabled.
* Bug: In CRL/python/helpers/__init__.loadUserSettings(), must put the
    current working directory in the sys.path as in certain configuration
    it may not be included.
* Bug: In CRL::ApDriver, DumpSegments(), no longer generate segments when
    encountering a RoutingPad on a top-level Pin Occurrence. The segment
    was generated in the wrong direction, creating DRC violations on the
    "mips_core_flat" example.
* Change: In CRL::Measures, partial re-design of the measurements management.
    Now, each kind of measure can accept multiple values put in a vector.
    The index is intented to match a tool run number.
* Change: In CRL::Histogram, add support for multiple sets of datas,
    indexeds with tool run number.
* Change: In CRL::ToolEngine, add support for multiple pass number, add
    addMeasure<> templates for the various data-types.
* Change: In CRL::gdsDriver & CRL::gdsParser(), comment out unused GDS record
    name constants.
* New: Etesian::BloatProperty, property to attach to Instance occurrences
    that contains the extra number of pitch to add to the cell width.
* Bug: In AutoSegment::CompareByDepthLength, the segment length comparison
    was wrong, it was always returning true, which broke the "strick weak
    ordering" of the comparison.
      This was producing a core-dump in GCell::updateDensity() when sorting
    a vector<>. The end() iterator was being dereferenced, leading to the
    problem.
* Bug: In Katana::DataSymmetric::checkPairing(), the test for segments
    whose axis is perpandicular to the symmetry axis was wrong
    ("!=" instead of "-").
* New: In Katana/GlobalRoute, new ::selectSegments(), selectOverloadedgcells()
    and selectBloatedInstances() to automatically select segments from
    overloaded edges, overloaded GCells and bloated cells.
* Change: In KatanaEngine, return a more detailed success state, distinguish
    between global and detailed.
      Add support for multiple routing iterations.
* New: In cumulus/python/plugins/ConductorPlugin.py, embryo of routing
    driven placement.
2019-12-09 01:57:44 +01:00
Jean-Paul Chaput a3b006a809 Add templates for derived Key in DBo::CompareById::oprator() [gcc 8].
* Change: In Hurricane::DBo::CompareById, starting from gcc 8, the compare
    function is checked inside the STL map<>/set<> so the lhs & rhs arguments
    are of the exact type of the Key, even excluding a base class.
      So now, in complement of the normal function, we provide a templated
    comparison functor in CompareById.
2019-12-01 13:31:33 +01:00
Jean-Paul Chaput 5ee4487d95 Bug fixes in SlicingTree, bad refcount incrementation of BoxSet.
* Bug: In Bora::BoxSet::destroy(), perform the actual destroy only when
    the reference count reaches zero.
      In Bora::HVBoxSet CTOR, when duplicating the vector<BoxSet*> arguments,
    we must increase the refcount of the all the BoxSet.
      The refcounting mecanism of the BoxSet & NodeSet is badly implemented
    and should need a full reviewing and redesigning.
2019-11-22 18:29:09 +01:00
Jean-Paul Chaput 5f53487036 Added RPOLYH & RPOLY2PH types to ResistorFamily. 2019-11-22 11:32:48 +01:00
Jean-Paul Chaput f38945d200 Various bug fixes (Selection, Measures/Histogram, helpers).
* Bug: In CRL/python/helpers/__init__.py, in textPythonTrace(), when an
    ErrorMessage was catched, the trace parameter was not correctly
    extracted leading to an "exception in exception".
* New: In Isobar/PyCell, exported Cell::getNonLeafInstanceOccurrences()
    collection.
* New: In Isobar/PyTransformation, type is now built so the tp_compare
    is linked to the C++ operator==().
* Change: In Hurricane::SelectionModel, Hurricane::SelectionWidget and
    CellWidget, no longer use Occurrences but directly the Selector property.
      We also use the Selector to know if an Occurrence is selected by
    looking at that property on it's Quark. This avoid a very lengthy
    search in vector when there is many elements (say > 10000).
      NOTE: This is a bad implementation as there is a confusion between
    beeing selected (that is, having a Selector property attached to
    an Occurrence Quark) and being actually displayed as selected.
    This lead to awkward implatation of the various "toggle" methods.
    Have to rethink that more clearly later.
* Bug: In CRL::Histogram, the non-inline template full specialisation
    of Measure<Histogram> must not be put in the header but in the module
    to avoid multiple definition and link failure. They are actually
    real, classic functions.
2019-11-22 00:24:47 +01:00
Jean-Paul Chaput 39cd831a57 Added message when loading the technology/configuration files.
* New: In CRL/python/helpers.io, vprint() wrapper around print to display
    messages according to the verbose level.
      In etc/*, add messages in every configuration files so we may know
    under which we are running.
2019-11-15 14:40:59 +01:00
Jean-Paul Chaput ef2635b9f3 Etesian should use the CellGauge slice step when adding the feed cells.
* Bug: In EtesianEngine, it was using the vertical track pitch from the
    routing gauge, but it may differ from the cell pitch. For example in
    "cmos350" the cell step is 10 lambdas while the vertical routing
    pitch may be only 8 lambdas.
      This bug shows because now we try to use the non-PinOnly routing
    gauge for the reference routing gauge.
2019-11-15 12:26:14 +01:00
Jean-Paul Chaput 92edd9ba31 New implementation for the Python hash and compare methods.
* Change: In Hurricane::Isobar/PyHurricane.h, make the hash function use
    the DBo id whenever possible instead of the object pointer, fall back
    to it for standalone objects (Box like one). The DirectHashMethod()
    macro generate a C style function (linkage) which call a template
    function "getPyHash<>()" that uses a SFINAE mechanism to select
    the right variant.
      Create two comparison macros DirectCmpByPtrMethod() and
    DirectCmpByValueMethod() to customize the comparison for objects that
    have C++ operator==(). So now two boxes with the same contents will
    be seen equal by Python. For DBo objects we keep the previous
    comparison by C++ pointer.
2019-11-14 23:56:01 +01:00
Jean-Paul Chaput 85540c9a58 Added capacitor documentation in Oroshi, and generated. 2019-11-13 23:43:04 +01:00
Jean-Paul Chaput f130417232 Various bug fixes for Analog P&R. OK for GM/Chamla & OTA/Miller.
* Change: In CRL::RoutingLayerGauge::getHorizontalGauge(), when selecting
    the default gauge, try, if possible to avoid the PinOnly one.
      Same goes for the vertical one.
* Bug: In Katana::TrackCost CTOR, symmetric track axis position was wrong,
    was using the reference instead of the symmetric.
* Bug: In BoraEngine::updatePlacement(), set up the Dijkstra search halo
    to one pitch so it can use immediately neighboring channels.
* New: In BoraEngine, added python startup hook like in Katana. Mainly
    to setup debug nets.
2019-11-13 23:31:51 +01:00
Jean-Paul Chaput 1e4b8b4647 Added support for extra resistor rules in Hurricane::Technology.
* New: In BasicLayer::Material, added "info" kind of material for layers
    that are only informationals (i.e. not real GDS one). Created to
    store geometric combination of layers, this is a temporary solution.
      Have to define a clearer semantic for that.
* New: In CRL/helpers/AnalogTechno.py, new "Count" type for count numbers
    that must not go through DbU::Unit converter. They are plain integers,
    but stored in DbU::Unit (keeping track of that semantic is left to
    the user).
2019-11-13 16:09:38 +01:00
Jean-Paul Chaput 88235dc3a4 Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
    setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
    Change in addDevice(), the span which was only meaningful for
    transistor devices is replaced by a parameter argument.
      The parameter argument has to be consistent with the device type.
2019-11-12 02:21:03 +01:00
Jean-Paul Chaput 9d86282b8f In Cyclop CMakeLists, cleanup the switch Qt4/Qt5. 2019-11-10 12:28:50 +01:00
Jean-Paul Chaput a8a904180d In AllianceFramework::createCell(), handle non-existent library. 2019-11-08 00:18:23 +01:00
Jean-Paul Chaput 8035b31f27 First stage in analog capacitor integration
* Bug: In Technology::getPhysicalRule(), if the named layerdo not exists,
    throw an exception instead of silently putting a NULL pointer inside
    a rule.
* New: In Hurricane/Analog, new parameters classes for capacitor devices:
    - Analog::Matrix, a matrix of null or positives integers to encode
      capacitor matrix matching.
    - Analog::Capacities, a list of float values for all component of a
      multi-capacitor.
* New: In Hurricane::Script, add a "getFileName()" method to get the full
    path name of the Python module.
* Change: In Analog::LayoutGenerator, completly remove the logger utility
    as it is no longer used. Simply print error messages instead.
* Change: In Analog::MetaCapacitor, rename top & bottom plate 'T' & 'B'.
    Accessors renamed in "getTopPlate()" & "getBottomPlate()".
* New: In Analog::MultiCapacitor, complete rewrite. Makes use of the
    new parameters "capacities" and "matrix". Dynamically generates it's
    terminals as we do not know beforehand how many capacitors could be
    put in it.
* Bug: In isobar/PyHurricane.h, in Type object definition, do not prepend
    a "Py" to class name (so the keep the C++ name).
* Change: In CRL/etc/scn6m_deep_09/devices.py, add entry for the new
    capacitor generator.
* New: In oroshi/python/ParamsMatrix, add a "family" entry in the [0,0]
    element to distinguish between transistor, capacitor and resistor.
    (this is the matrix of values returned to the LayoutGenerator after
     device generation).
      Now have one "setGlobalParams()" function per family.
* New: In oroshi/python/Rules.py, added DTR rules needed by capacitors.
    Catch exceptions if something wrong append when we extract the rules
    from the technology.
* New: In Bora, the devices are no longer *only* transistors, so the
    possibles configurations are no longer defined only by a number of
    fingers. We must be able to support any kind of range of configuration.
      So the explicit range of number of fingers is replaced by a base
    class ParameterRange, and it's derived classes:
      - Bora::StepParameterRange, to encode the possible number of fingers
        of a transistor (the former only possibility).
      - Bora::MatrixParameterRange, to encode all the possible matching
        scheme for a capacitor. As there is no way to compress it, this
	is a vector of Matrix (from Analog).
* Change: In Bora::DSlicingNode::_place(), the ParameterRange has to be set
    on the right configuration (through the index) before being called.
      The generation parameters are taken from the active item in the
    ParameterRange.
* Change: In Bora::NodeSets::create(), iterate over the ParameterRange
    to build all the configuration. Adjustement to the routing gauge
    pitchs are moved into the DBoxSet CTOR to save a lot of code.
      Semantic change: the index in the NodeSets is now the index in
    the associated ParameterRange and no longer the number of fingers
    of a transistor.
      Check that the ParameterRange dynamic class is consitent with the
    device family.
* Change: In Bora::DBoxSet, same semantic change as for NodeSets, the
    number of finger become an index in ParameterRange.
      In DBoxSet::create(), now also perform the abutment box adjustement
    to the RoutingGauge, if possible.
* New: In Karakaze/python/AnalogDesign.py, add support for Capacitor
    devices.
2019-11-07 17:05:49 +01:00
Jean-Paul Chaput ef0f6f771a In Python scripts, if PyQt 4 fails to load, try PyQt 5.
* In CRL::Cyclop/CMakeLists.txt, add *again* the MOC files to the list
    of .cpp . Don't know what is happening here with MOC under Qt 5.
* In CRL/python/helpers.io, cleanly fails if neither PyQt 4 nor PyQt 5 is
    found. And tell it directly because this the module tasked to handle
    the exceptions/errors...
* In Cumulus/plugins/AboutWindow.py, try PyQt 4 then PyQt 5.
* In documentation/UsersGuide, now tells explicitely that Qt 4 must be
    used under RedHat 7 and Qt 5 under Debian.
2019-10-30 16:58:43 +01:00
Jean-Paul Chaput 2c73cfe76c Migrating the initialisation system to be completely Python-like.
* New: In bootstrap/coriolisEnv.py, add the "etc" directory to the
    PYTHONPATH as initialization are now Python modules.
* New: In Hurricane/analogic, first groundwork for the integration of
    PIP/MIM/MOM multi-capacitors. Add C++ and Python interface for the
    allocation matrix and the list of capacities values.
* Change: In Hurricane::RegularLayer, add a layer parameter to the
    constructor so the association between the RegularLayer and it's
    BasicLayer can readily be done.
* Change: In Hurricane::Layer, add a new getCut() accessor to get the
    cut layer in ViaLayer.
* Change: In Hurricane::DataBase::get(), the Python wrapper should no
    longer consider an error if the data-base has not been created yet.
    Just return None.
* Bug: In Isobar::PyLayer::getEnclosure() wrapper, if the overall
    enclosure is requested, pass the right parameter to the C++ function.
* Change: In AllianceFramework, make public _bindLibraries() and export
    it to the Python interface.
* Change: In AllianceFramework::create(), do not longer call bindLibraries().
    This now must be done explicitely and afterwards.
* Change: In AllianceFramework::createLibrary() and
    Environement::addSYSTEM_LIBRARY(), minor bug corrections that I don't
    recall.
* Change: In SearchPath::prepend(), set the selected index to zero and
    return it.
* Change: In CRL::System CTOR, add "etc" to the PYTHONPATH as the
    configuration files are now organized as Python modules.
* New: In PyCRL, export the CRL::System singleton, it's creation is no
    longer triggered by the one of AllianceFramework.
* New: In CRL/etc/, convert most of the configuration files into the
    Python module format. For now, keep the old ".conf", but that are no
    longer used.
      For the real technologies, we cannot keep the directory name as
    "180" or "45" as it not allowed by Python syntax, so we create "node180"
    or "node45" instead.
      Most of the helpers and coriolisInit.py are no longer used now.
    To be removed in future commits after being sure that everything
    works...
* Bug: In AutoSegment::makeDogleg(AutoContact*), the layer of the contacts
    where badly computed when one end of the original segment was attached
    to a non-preferred direction segment (mostly on terminal contacts).
      Now use the new AutoContact::updateLayer() method.
* Bug: In Dijkstra::load(), limit symetric search area only if the net
    is a symmetric one !
* Change: In Katana/python/katanaInit.py, comply with the new initialisation
    scheme.
* Change: In Unicorn/cgt.py, comply to the new inititalization scheme.
* Change: In cumulus various Python scripts remove the call to
    helpers.staticInitialization() as they are not needed now (we run in
    only *one* interpreter, so we correctly share all init).
      In plugins/__init__.py, read the new NDA directory variable.
* Bug: In cumulus/plugins/Chip.doCoronafloorplan(), self.railsNb was not
    correctly managed when there was no clock.
* Change: In cumulus/plugins/Configuration.coronaContactArray(), compute
    the viaPitch from the technology instead of the hard-coded 4.0 lambdas.
      In Configuration.loadConfiguration(), read the "ioring.py" from
    the new user's settings module.
* Bug: In stratus.dpgen_ADSB2F, gives coordinates translated into DbU to
    the XY functions.
      In st_model.Save(), use the VstUseConcat flag to get correct VST files.
      In st_net.hur_net(), when a net is POWER/GROUND or CLOCK also make it
    global.
* Change: In Oroshi/python/WIP_Transistor.py, encapsulate the generator
    inside a try/except block to get prettier error (and stop at the first).
2019-10-28 18:09:14 +01:00
Jean-Paul Chaput 2d8e26a467 Quick fix for Stratus1, missing cell mapping file. 2019-10-25 11:20:15 +02:00
Jean-Paul Chaput 1da71ae740 Bug when the METAL3 pitch is not multiple of METAL1.
* Bug: In Katana::SegmentFsm CTOR, when computing costs for METAL2 in
    non-preferred direction attached to METAL1 terminals, do not try to
    align on a METAL3 track, as there may be not. Especially when the
    METAL3 pitch is not multiple of the METAL1 one.
      Compute at least one cost (with the same axis as the vertical METAL1
    terminal).
* Change: In Etesian::BloatCells, adjust the "90%" bloat profile for a
    METAL3 pitch of 8 lambdas (sligh decrease).
* Bug: In cumulus/plugins/ChipPLace.py, import chip.Chip, not only chip.
2019-10-16 21:47:32 +02:00
Jean-Paul Chaput 43ea63d98d New Etesian bloat profile "90%".
* New: In Etesian::BloatCells, new profile for hihgly saturated designs named
    "90%", as it add, on average, 90% of free space. This has been made for
    the "ao68000" of Staf Verhaegen and may needs some refinement as it is a
    bit brutal.
2019-10-13 17:52:03 +02:00
Jean-Paul Chaput 5bbeb0b062 Support for separated NDA tree. Big cleanup of the Python init system.
* Change: In Hurricane::Script, when running a script, no longer do it
    inside a Python sun-interpreter, use the current one. This way we
    no longer have our modules initialized twice or more, which was
    starting to be unmanageable (with the NDA support).
      The settings were re-read multiple time to the same value, so it
    was working, but still...
      I hope I didn't left some dangling Python objects now.
* Bug: In Hurricane::LayoutGenerator::drawLayout(), get the device abutment
    box though a Pyhon object *before* finalizing which removes that objet.
* New: In cumulus/plugins/__init__.py, add a "loadPlugins()" and static
    initialisation to preload plugins modules.
      We use that pre-loading step to append to the module __path__ attribute
    the alternate directory where a NDA covered may be found. This assume that
    the directory tree under the NDA root is identical to the one under the
    public root.
* New: In cumulus/plugins/chip/__init__.py, small utility function
    importContants() to import the constants inside another module namespace,
    to have more consise notations.
* Change: In cumulus/plugins/, in the various plugins sub-modules import
    use the full path from plugins, that is, for example:
      from plugins.core2chip.CoreToChip import IoPad
* Change: In Unicorn/python/unicornInit.py, no longer directly load the
    plugins modules, this is now done by cumulus/plugins/__init__.py.
      Instead, iterate through sys.modules for the ones starting by "plugins/"
    and try to execute a Unicorn hook, if present.
* Change: In Karakaze/python/AnalogDesign.py, update for the new Instance.create()
    prototype (added placement parameter).
2019-10-11 17:36:54 +02:00
Gabriel Gouvine ae98b117ba Handle fixed pins on a net 2019-10-06 12:58:49 +02:00
Gabriel Gouvine a90b5ed890 Partial support of newer Bookshelf formats 2019-10-06 12:58:42 +02:00
Gabriel Gouvine f1644fc229 Workaround to get the ISPD benchmarks working 2019-10-06 12:58:33 +02:00
Jean-Paul Chaput 5914e16f26 Added management for "phlib" I/O pad external connectors (for cougar/lvx).
* New: In CRL::ApDriver::DumpSegments(), drive as top-level segments the
    RoutingPads using a Pin, and not only using a segment. They are not
    exported as top level Pin but only as Segment as they do belong to
    a deeper level.
* New: In Cumulus/plugins/PadsCorona.Side._placePads(), now manage both
    "pxlib" and "phlib*". Pad library management is still hardcoded, this
    should be made a configuration option someday.
2019-10-05 16:04:12 +02:00
Jean-Paul Chaput 02b30b6681 More terse failure message from the global router.
* Bug: In CRL::cstDriver(), re-activate the management of the VstUseConcat
    flag. Why was he removed in the first place?
* Change: In KatanaEngine::runGlobalRouter(), no longer give the details of
    each overflowed edge and the complete list of impacted nets.
    Only a count.
2019-09-29 18:35:16 +02:00
Jean-Paul Chaput 6faf83309e Force pitching on dragged AutoContacts.
* Change: In Anabatic::AutoContactTerminal::updateGeometry(), when a
    draggable AutoContact is moved, pitch it on the routing grid instead
    of putting it in lowest/highest position.
2019-09-26 01:16:01 +02:00
Jean-Paul Chaput 2bd18313d1 More tuning for ARMv2a (95% success, 38/40). Bugs in core2chip.
* Change: In Anabatic::GCell::updateDensity(), all non-passthrough wires
    now have a cost of 0.5 instead of 0.33 for locals.
* Change: In Manipulator::canMoveUp(), increase the "reserve" amount to
    1.0 for "far from terminal" wires (rpDistance > 2).
* Change: In NegociateWindow::NegociateOverlapCost(), always sets "AtRipupLimit"
    when the overlapping segment is nearing it's maximum ripup limit.
    (different detection for non-preferred and regular)
* Change: In SegmentFsm::_slackenStrap(), call avoidBlockage() if it is
    overlapping a blockage *or* a segment at it's ripup limit. I hope I
    didn't create an infinite loop here.
* Bug: In cumulus/plugins/PadsCorona.py, CoreWire._computeCoreLayers(),
    the big contact between symbolic and real was badly computed for
    east/west (was using width instead of height, bummer!).
      In Corona._createCoreWire(), completly screwed computation of the
    side gap, was using a badly initialized value of the "bb" variable.
* Bug: In cumulus/plugins/Chip.py, the computation of the minimal size
    for the corona was wrong, do *not* add the size of the pads and
    multiply by two as it is done by "inflate". This was forcing the user
    to create way to large chips for a given core size.
2019-09-25 18:35:03 +02:00
Jean-Paul Chaput d7931391c0 Adjusted routing pitch for METAL4 to METAL7 for FreePDK45 symbolic. 2019-09-19 23:52:03 +02:00
Jean-Paul Chaput 24dedce09c Added core2chip support for Phenitec80.
This commit degrades the run success rate of ARMv2a to 87% (40 iters).
* New: In CRLcore/etc/.../kite.conf, add configuration parameters:
      katana.termSatReservedlocal
      katana.termSatthreshold
    for the new edge capacity computation system.
* New: In CRLcore/etc/symbolic/phenitec06/, add support for N. Shimizu
    small I/O pads (supplied in phlib80). Tune various parameters of
    Anabatic/Katana to increase routing success.
* Change: In CRLcore/alliance/ap/ApParser, make Pin external components,
    so RoutingPad will be build upon in global routing.
      Do not complain when a I/O pad has a physical instance that did
    not exists in the netlist. Just create it (appeared in phlib80).
      When no netlist instance exists in a pad, the pad Cell is still
    considered as terminal.
* New: In Etesian::BloatCells, new profile named "3metals" better suited
    for two routing metals technologies (i.e. Phenitec).
* New: In Anabatic::RawGCellsUnder, new CTOR which take only source &
    target points instead of a segment. Needed to manage wide segment for
    which the axis to consider is not that of the segment (one axis for
    each track it intersect).
* New: In Anabatic::GCell, add a RoutingPad count attribute, for Edge
    reservation computation.
* New: In AnabaticEngine::computeEdgeCapacities(), instead of decreasing
    all edges of a fixed amount (hTrackReservedLocal), guess the GCell
    cluttering from the number of RoutingPads that it contains.
      For non-saturated GCells, the four edges are decreased by the number
    of RoutingPads. We use the maximum from the two neigboring GCells.
    The hTrackReservedLocal parameter is now used only as a *maximum*
    that the edge reservation can reach.
      If a GCell is saturated (more than 8 RoutingPads, the saturation is
    propagated horizontally to 2 neigboring GCells).
* Change: In AutoContactTerminal::getNativeConstraintBox(), use a more
    flexible gauge name matching for terminal vertical extensions correction.
    Namely, match all "msxlib*" kind of gauges.
* Change: In AutoSegment::setAxis(), add the ability to force the axis
    position, even if it is a non-canonical segment. Maybe needed in the
    initialisation steo, before the first canonisation is performed.
* New: In NetBuilder, added new methods _do_1G_1PinM1() and _do_2G_1PinM1(),
    to manage coronas for Phenitec designs.
      To avoid various side effects from segments being too close from
    the north / east side of the routing area, make those segments fixeds.
* Change: In KatanaEngine::annotateGlobalGraph(), the management of wide
    wires was wrong. The axis to use to find the underlying GCells is the
    one of the track, not of the segment. This was creating bad edge
    capacity computation under the power ring of a block and subsequently
    routing failures.
* New: In Kanata::Manipulator, added method reprocessParallels(), not used
    though, but keep it anyway, might be of use later...
* New: In Kanata::Manipulator, added method avoidBlockage() for terminal
    METAL2 in non-preferred direction, restrict the terminal and turn
    constraint box at the current position of the perpandicular, so it
    doesn't create a deadlock in METAL2.
* Change: In SegmentFsm::conflictSolveByPlaceds(), if we cannot break
    using the whole overlap, try the first atomic overlap.
* New: In SegmentFsm::_slackenStrap(), manage conflict between a non-prefered
    segment and a blockage, this when to call avoidBlockage()...
* New: In Katana::Configuration, management of the new edge computation
    parameters:
      katana.termSatReservedlocal
      katana.termSatthreshold
* New: In Cumulus/plugins/Core2Chip, support for Phenitec I/O pads.
2019-09-17 17:05:54 +02:00
Jean-Paul Chaput c6ea1bccdd Improvements in routing quality for ARMv2a, reached 100% success.
Now reliably work for 20 successive runs (doRun.sh) with pseudo-random
variations.
* Change: In AnabaticEngine::computeNetConstraints(), fully recompute
    the "distance to RoutingPads" for all AutoSegments.
      Previously we tried to do it incrementally, but as it's computed
    as a minimum, it stayed stuck at the lowest value, event after a
    net's change of topology that could made it increase (a new dogleg
    did appear between the segment and the RoutingPad).
2019-08-23 23:48:09 +02:00
Jean-Paul Chaput 02eb5c56ad Improvements in routing quality for ARMv2a
* Change: In Katana::SegmentFsm::_slackenStrap(), make unbreakable segments
    pass through the LocalVsGlobal state so when other try to ripup them
    they are prioritary. Otherwise some could go through Unimplemented
    directly, without allowing other to attempt to make a detour.
* Change: In Katana::NegociateWindow::NegociateOverlapCost(), when a
    global, which is about to be slackened wants to use a track where there
    is a segment directly connected to a terminal with a significant
    ripup count, mark it as "AtRipupLimit" so it tries to avoid it.
      The idea is that globals with high ripup count must avoid terminal
    segments because it is likely they will be riped up again so they
    better find another track. This was leading to unsolvable configuration
    when two segments always want the same track. In this cas, the global
    would loose.
* Bug: In Katana::TrackSegment::canSlacken(), never slacken a segments in
    non-preferred direction.
* Change: In Anabatic::AutoHorizontal::_slacken(), allow slackening of
    segments which perpandiculars are in non-preferred direction, and
    not only directly attached to terminals.
* Change: In Anabatic::AutoSegment::canMoveUp(), re-allow segments which
    perpandiculars are in non-preferred direction to be moved up.
* Bug: In Katana::Manipulator::moveUp(), when moving up, do not forget
    to ripup and reschedule said segment.
2019-08-23 15:43:13 +02:00
Jean-Paul Chaput 1124e92ac2 Correcting non-deterministic behavior in Anabatic/Katana (again).
This non-deterministic behavior was showing only in the ARMv2a benchmark
around event 180k...
* Bug: In Anabatic::Session::_netInvalidateds & _netRevalidateds, the
    set<> was still sorted on pointers. As contacts & segments can be
    created to maintain connexity after a layer change, we got a
    discrepency in objects Ids that may generate a change in ordering
    later.
* Bug: In Katana::Session::_doRemovalEvents(), the set of Tracks that
    got elements deleted was still using pointers. Now we use a TrackSet
    sorted on (direction,depth,axis). This should not have created
    a change in the results, as destructions do not change Ids, but it
    genereate extra differences in traces.
2019-08-20 16:30:03 +02:00
Jean-Paul Chaput 014dbe1bcc Bug in segment layer reduction causing METAL2 to go in METAL1 (RISC-V).
* Bug: In Anabatic::AutoSegment::reduceDoglegLayer(), we did not check
    that not only source and target depth span was zero, but also both
    on the same one. This was seen in the RISC-V where a METAL2 small
    segment was demoted into METAL1 causing a gap in the routing (and
    a short in the underlying standart cell).
2019-08-18 13:20:50 +02:00
Jean-Paul Chaput 91f973c00f Improve the management of the I/O pad near the chip corner.
* Bug: In cumulus/plugins/PadsCorona.py, when a pad is at the beginning
    or at the end of the side, the pad corona terminal may be outside
    the corona range (not directly facing it). In that case, create a
    bend to reach it.
      Worse, in some case more than one (but likely no more), could be
    in that case, so not only do we create a bend but also make a
    shift in the bended segment so two consecutive ones are not on the
    same axis, causing shorts.
      If both end pads of a corner are in that case, we cannot prevent
    a short, so at least, issue a warning.
* Bug: In CRL::Vhdl, the Entity::VstUseConcat was not passed correctly
    along, so we did get a strange mix of conat and direct assignment.
* New: In Unicorn/cgt.py : added --vst-use-concat options to control
    the VST driver behavior.
2019-08-16 00:40:49 +02:00
Jean-Paul Chaput f92b48174b Correct management of "fused_net" in Alliance parser/drivers.
* Bug: In CRL::ApDriver & CRL::ApParser, when saving a fused net, do not
    use it's name but put a star (*) character to set it anonymous.
      Having all component named was creating problems in cougar and
    subsquently in yagle (bad name for master latch).
      Conversely, in the parser, if the name of the net is "fused_net",
    make it a real fused_net and not an ordinary one.
2019-08-15 01:59:38 +02:00
Jean-Paul Chaput 5877691cde The VST driver can now be setup to use or not concat ('&') in PORT MAP.
* New: In CRL::AllianceFramework::saveCell(), through the view flag we
    can pass an option 'CRL::Catalog::State::VstUseConcat' to tell the
    driver tu use or not the concat '&' in PORT MAP statements.
      It is not completely clean that the flag for controlling the VST
    driver behavior is put in the Catalog states, but it's easier for
    now...
      And, of course, exported at Python level.
2019-08-13 14:46:23 +02:00
Jean-Paul Chaput d670de4125 Added support for 3 metal layers symbolic Phenitec 0.6um.
* New: In CRL/etc/symbolic/phenitec06, configuration for symbolic
    layout targeted for Phenitec 0.6um (do not contains any NDA
    covered informations). Could be used for any 3 metal layers
    techno.
* Bug: In Cumulus/plugins/chip/Configuaration.py, _setStackposition()
    disable stack error when there is no slave component on the stack
    (happens when the stack consists only of one contact).
2019-08-12 15:41:17 +02:00
Jean-Paul Chaput 4b9a6ec4a9 Ensure that there is at least one free GCell on each side of the corona.
* Change: In Cumulus/plugins/chip/PadsCorona, if the external pins of
    the corona are in GCells that are also under the core block ring
    power lines, they are flagged as "go straight" and this produce
    impossible configurations for the router to solve. Now we ensure
    that there is one free GCell all around the corona border.
* Bug: In Cumulus/plugins/chip/Configuration.py & PadsCorona.py,
    at the begin/end of a side of pad, connectors can be outside the
    corona range (i.e. not directly face to face). Now make a dogleg
    if needed. This is a work in progress as if there are two of them,
    they will short on the perpandicular part. We must compute a
    shift.
2019-08-12 01:11:58 +02:00
Jean-Paul Chaput 1b2c90424a Do not slacken segments which source/target in a "go straight" GCell.
* Change: In Anabatic::AutoHorizontal::_canSlacken(), if the source or
    target contact is in a GCell flagged "go straight", do not slacken,
    which would create a dogleg. This case is usually meet under big
    power rails that render a dogleg impossible to place as all tracks
    are used.
       Same modification for AutoVertical.
2019-08-12 01:01:29 +02:00
Jean-Paul Chaput 70a3960ba5 ioNet used as "enable" should not get the name of the pad.
* Bug: In Cumulus/plugins/core2chip/CoreToChip.py, when creating the ioNet
    objects, when a signal is an enable we must not set the external chip
    net (the name for the PAD terminal) as it may be set later if it is
    also used as an individual pad.
2019-08-09 18:45:19 +02:00
Jean-Paul Chaput 15cd9187de Allow enable signal of bidir pads to be exported in Core2Chip.
* Change: In Cumulus/plugins/core2chip/CoreToChip.py, in IoNet select
    the external I/O net (pad connected) signal to be generated in the
    context of the I/O pad instanciation. This should allow an enable
    signal in one pad to be also used in a direct output pad.
2019-08-09 12:56:54 +02:00
Jean-Paul Chaput e80fcd8648 Remove VHDL driver extension/property after use.
* In CRL::vstDriver(), remove the Vhdl::EntityExtension right after driving
    the file. This avoid keeping in memory a mostly usnused structure and
    solve the "second write after modification" problem.
2019-08-08 14:12:22 +02:00
Jean-Paul Chaput 86c4e9cb17 Added support for Tristate and bidir pads in CoreToChip.
* New: In Cumulus/plugins/CoreToChip, added support for Tristate ouput
    pads and bidirectional pads.
      Added capability to name the I/O pad instance and their external
    terminals so we can override the default naming scheme.
      Mandatory anyway for bidirectional and tristate I/O pad as we
    cannot guess the core net grouping (in/out/enable).
      Support is available for symbolic CMOS and AMS c35b4 (but not
    published due to NDA).
* Change: In Cumulus/plugins/chip/Configuration.py, the configuration
    file is now named simply "ioring.py" instead of being prefixed by
    the design name. As a consequence we can have only one chip per
    directory. But now all the tools, for any design in that directory
    can peek datas into it.
2019-08-08 00:57:19 +02:00
Jean-Paul Chaput acc3a38f60 Support for placing *one* block of a Cell in Etesian.
* Change: In Hurricane::Cell_LeafInstanceOccurrences, add the ability to
    walkthrough the leaf of one specific top-level instance.
* Change: In Hurricane::Cell_NonLeafInstanceOccurrences, add the ability to
    walkthrough the leaf of one specific top-level instance.
* Change: In Hurricane::Cell:
    getLeafInstanceOccurrences() and getNonLeafInstanceOccurrences(), now
    have a parameter Instance* to select the leafs we want to walk through.
    If set NULL (default value) browse through all the instances,
    as before.
* Change: In Hurricane::DeepNet, add forgotten Inspector support.
* New: In EtesianEngine, add a "block" (and Instance) attribute to allow
    the placement of one specific bloc. If we want to place the core of
    a chip and take into account the external terminals (if they are not
    already fixed as Pins at the edge of *said* block). We must place
    the core *in the context* of it's instanciation in the corona.
      Note for G. Gouvine : Pin & external RP should be taken into account
    starting at line 629 of EtesianEngine.cpp...
* New: In cumulus/plugins/chip/Chip.py, make use of the new block
    placement feature of ETesian.
* Bug: In KatanaEngine::create(), perform a pre-check to prevent trying to
    route whole chip, which is forbidden an leads to annoying core-dumps.
    Routing must take place "at most" at Corona level.
* Bug: In KatanaEngine::PowerRails, create a plane for METAL1 blockage.
    Not completely sure this was a bug...
2019-08-04 17:33:03 +02:00
Jean-Paul Chaput 1b444d8f49 In cumulus/Core2Chip.py forgot a parameter to an error message call. 2019-07-31 19:16:40 +02:00
Jean-Paul Chaput 1359fe4ba6 Change Net name merge policy in the Blif parser.
* Change: In CRL/BlifParser::Model::mergeAlias(), do not always merge the
    net2 with net1 (RHS with LHS of the ".name" instruction). This may
    result in a name change in the design interface (external net).
      Instead, merge any internal net with the external, so keep the
    external net name. If both are external, keep the one with the lower
    id (which should have been created first).
2019-07-31 18:29:22 +02:00
Jean-Paul Chaput 85e969bca9 Disable the use of concat '&' in VST port map. 2019-07-31 17:38:35 +02:00
Jean-Paul Chaput d69327d9a9 Various typos correction (courtesy of G. Gouvine). 2019-07-30 13:13:57 +02:00
Jean-Paul Chaput f528cdea4c Upgrade of Katana detailed router to support Arlet 6502.
* Change: In Hurricane::SharedName, replace the incremental Id by a hash key.
    This is to ensure better deterministic properties. Between use cases,
    additional strings may have to be allocated, shitfing the ids. Even if
    hash can be duplicated, we should be able to ensure that the absolute
    order in map table should be preserved. Supplemental strings are inserted
    in a way that keep the previous order.
* Change: In CRL/etc/symbolic/cmos/kite.conf, add "katabatic.routingGauge"
    default parameter value ("sxlib").
* Change: In CRL/etc/common/technology.conf, define minimal spacing for
    symbolic layers too (added for METAL4 only for now).
* Change: In CRL::Histogram, extend support to dynamically sized histograms.
    Add a text pretty print with table and pseudo-curve.
* Change: In Cumulus/plugins/ClockTreePlugin, create blockage under the
    block corona corners so the global router do not draw wire under them.
    This was creating deadlock for the detailed router.
      When the abutment has to be computed, directly use Etesian to do it
    instead of duplicating the computation in the Python plugin.
* New: In Etesian, as Coloquinte seems reluctant to evenly spread the
    standard cells, we trick it by making them bigger during the placement
    stage. Furthermore, we do not not uniformely increase the size of the
    cells but create a "bloating profile" based on cell size, cell name
    or it's density of terminals. Currently only two profiles are defined,
    "disabled" which does nothing and "nsxlib" targeted on 4 metal layer
    technologies (aka AMS 350nm, c35b4).
* Bug: In Knik::MatrixVertex, load the default routing gauge using the
    configuration parameter "katabatic.routingGauge" as the default one
    may not be the first registered one.
* New: In AnabaticEngine::setupNetDatas(), build a dynamic historgram of
    the nets terminal numbers.
* Bug: In Anabatic::AutoContact::Invalidate(), always invalidate the
    contact cache when topology is invalidated. In case of multiple
    invalidations, if the first did not invalidate the cache, later one
    that may need it where not allowed to do so. The end result was correct
    nonetheless, but it did generate annoying error messages.
* Bug: In Anabatic::AutoContactTurn::updateTopology(), bad computation
    of the contact's depth when delta == 2.
* Bug: In Anabatic::Gcell::getCapacity(), was always returning the west
    edge capacity, even for the westermost GCell, should be the east
    edge in that case.
* New: In Anabatic::AutoSegment, introduce a new measure "distance to
    terminal". This is the minimal number of segments separating the
    current one from the nearest RoutingPad. This replace the previous
    "strong terminal" and "weak terminal" flags.
      This distance is used by Katana to sort the events, we route the
    segments *from* the RoutingPads *outward*. The idea being that if we
    cannot event connect to the RoutingPad, there is no points continuing
    as thoses segments are the more constraineds. This gives an order close
    to the simple ascending metals but with better results.
* New: In Anabatic::AutoSegment, introduce a new flag "Unbreakable", disable
    dogleg making on those segments. mainly intended for local segments
    directly connecteds to RoutingPads (distance == 0).
* New: In Anabatic::AutoSegment, more aggressive reducing of segments.
    Now the only case where a segment cannot be reduced is when it is
    one horizontal branch in a HTee or a vertical on a VTee. Check if,
    when not accounted the source & target VIAs are still connex, if so,
    allow reducing.
* New: In Anabatic::AutoContact, new state flags CntVDogleg & CntHDogleg
    mainly to prevent making doglegs twice on a turn contact. This is to
    limit over-fragmentation. If one dogleg doesn't solve the problem,
    making a second one will make things worse only...
* Bug: In Anabatic::Configuration::selectRpcomponent(), we were choosing
    the component with the *smallest* span instead of the *bigger* one.
* New: In Anabatic::GCell, introduce a new flag "GoStraight" to tell that
    no turn go be made inside those GCells. Mainly used underneath a block
    corona.
* New: In AnabaticEngine::layerAssign(), new GCellRps & RpsInRow to manage
    GCells with too many terminals. Slacken at least one RoutingPad access
    when there is more than 8 RoutingPad in the GCell (slacken or change
    a vertical METAL2 (non-preferred) into a METAL3).
* Change: In Anabatic::NetBuilderHV, allow the use of terminal connection
    in non-preferred direction. That is, vertical METAL2 directly connected
    to the RoutingPad (then a horizontal METAL2). This alllows for short
    dogleg without clutering the METAL3 layer (critical for AMS c35b4).
      Done in NetBuilderHV::doRp_Access(), with a new UseNonPref flag.
      Perform some other tweaking on METAL1 access topologies, to also
    minimize METAL3 use.
* New: In AnabaticEngine::computeNetConstraints(), also compute the
    distance to RoutingPad for segments. Set the Unbreakable flag, based
    on the distance and segment length (local, short global or long global).
      New local function "propagateDistanceFromRp()".
* Change: In AnabaticEngine.h, the sorting class for NetData, SparsityOrder,
    is modificated so net with a degree superior to 10 are sorted first,
    whatever their sparsity. This is to work in tandem with GlobalRouting.
* New: In Katana::TrackSegmentNonPref, introduce a class to manage segment
    in non-preferred routing direction. Mostly intended for small METAL2
    vertical directly connected to RoutingPad. Modifications to manage
    this new variant all through Katana.
* Change: In Katana::GlobalRoute, DigitalDistance honor the GoStraight flag
    of the GCell. Do not make bend inside thoses GCells.
* Change: In KatanaEngine::runGlobalRouter(), high degree nets (>= 10) are
    routed first and whitout the global routing estimation. There should be
    few of them so they wont create saturations and we want them as straight
    as possible. Detour are for long be-points.
      Set the saerch halo to one GCell in the initial routing stage (before
    ripup).
* Bug: In KatanaEngine & NegociateWindow, call _computeCagedconstraints()
    inside NegociateWindow::run(), as segments are inserted into tracks
    only at that point so we cannot make the computation earlier.
* Change: In Katana::Manipulator::repackPerpandiculars(), add a flag to
    select whether to replace the perpandiculars *after* or *before* the
    current segment.
* Change: In Katana::NegociateWindow::NegociateOverlapCost(), when the
    segment is fully enclosed inside a global, the longest overlap cost
    is set to the shortest global hoverhang (before or after).
      When the cost is for a global, set an infinite cost if the overlapping
    segment has a RP distance less or equal to 1 (this is an access segment).
* Bug: In Katana::PowerRailsPlane::Rail::doLayout(), correct computation of
    the segments extension cap.
* New: In Katana::QueryPowerRails::addToPowerRail(), add support for Pad.
* Change: In Katana/PreProcess::protectCagedTerminals(), apply the contraints
    to any turn connected to the first segment of the RoutingPad so the
    perpandicular constraints got propagated to the perpandicular segment...
* Change: In RoutingEvent, cache the "distance to RP" value.
* Change: In RoutingEvent::Key::compare(), sort *first* on distance to
    RoutingPad, then layer depth. If both distance to RoutingPad is null,
    then sort on segment length.
* Change: In RoutingEvent::_processRepair(), try a repack perpandicular with
    perpandiculars first (then with perpandicular last, then give up).
* Change: In SegmentFsm::bindToTrack() and moveToTrack(), set an axis hint
    when creating the insertion event.
* Change: In SegmentFsm::_slackenStrap(), add a step through slacken between
    minimize and maximum slack (wihch directly end up in unimplemented).
* Change: In Session::_addInsertEvent(), add an axis parameter needed when
    the axis of the segment is not the one of the track (case of wide
    segments or non-preferred direction).
* Bug: In Track::_preDestroy(), bad management of the TrackElement reference
    count. Destroy the segment only when reaching zero...
* Bug: In Track::expandFreeIneterval(), forgotten to manage case when there
    is a set of overlaping segments at the "end" of the track, the
    EndIsTrackMax was not set.
* Change: In TrackCost::Compare, increase the cost when an overlaping
    segment is at it's ripup limit. We should try *not* to rip it up if
    we can. Add a dedicated flag "AtRipupLimit".
* Change: In TrackElement, add proxies for isUnbreakable(), new function
    updateTrackSpan().
* New: In TrackFixedSegment CTOR, when a supply wire of METAL2 or above is
    found, make the underlying GCells "GoStraight".
* New: In TrackElement::canDogleg(GCell*), check for already done perpandicular
    dogleg on source/target (reject if so).
2019-07-28 23:20:00 +02:00
Jean-Paul Chaput bc88fe0075 Merge branch 'devel' of ssh://bop-t/users/largo2/git/coriolis into devel 2019-06-04 14:52:21 +02:00
Marie-Minerve Louërat ab517fbfac Typos corrigees dans Hurricane et Python Tutorial 2019-06-04 14:34:20 +02:00
Marie-Minerve Louërat 2bc2fd1583 Typos corrigees dans Users Guide.
Fin de devel_anabatic
2019-06-04 14:32:23 +02:00
Jean-Paul Chaput 8ad910301d In CRLcore, new gauge "msxlib4" for compliance with AMS 350nm (symbolic).
* New: In CRL/etc/symbolic/cmos45/kite.conf, new gauge "msxlib4" for both
    routing and cells. Have only 4 metal layers but with all the same pitches
    and width. Differs from the 45nm compliant where pitches double starting
    from METAL4.
* New: In CRL/etc/symbolic/cmos45/plugins.conf, adjust default parameters for
    the clock tree plugin so they are identical to the one of "cmos" (scaling).
* Change: In CRL/python/helpers/io.py, in catch(), do not set up the script
    path here as it is non-informative.
2019-05-29 13:16:01 +02:00
Jean-Paul Chaput 0df4821806 Full update of the generated documentation for version 2.3 2019-05-27 18:49:51 +02:00
Jean-Paul Chaput 9db39a7b5e Merge branch 'devel_anabatic' of ssh://bop-t/users/largo2/git/coriolis into devel_anabatic
Conflicts:
	documentation/UsersGuide/Installation.rst
2019-05-26 15:52:18 +02:00
Jean-Paul Chaput e00b19d454 In documentation, Update installation instructions. 2019-05-26 15:46:44 +02:00
Jean-Paul Chaput 911095284f Adapt socInstaller to the new SL7 & benchmarks. 2019-05-26 15:41:24 +02:00
Jean-Paul Chaput 4cd0bcb009 Various bug corrections to pass the alliance-check-toolkit reference benchs.
* New: In Isobar::PyCell, export the isRouted() and setRouted() to the
    Python interface.
* Bug: In CRL::Entity::parseEntity(), check that the closing parenthesis
    is the last character of the net name. Issue a more relevant error
    message.
* In Anabatic::NetBuilder::_do_xG() and all other unimplemented methods,
    throw an error if called from a derived classes instead of just
    issuing a message in the debug stream. Avoid later core dumps...
* In Anabatic::NetBuilderHV, implement the builders for GCells with
    one pin. Needed to support chip/corona routing.
* Bug: In Cumulus/plugins/Chip.py, check that coronaCk exists before
    using it.
* New: In Cumulus/plugins/PadsCorona/Side._placePad(), when routing
    a design with symbolic pads, export the chip external "pad"
    connectors to be able to perform a lvx (otherwise cougar do not
    create external nets).
      In Corona._createCoreWire(), set the minimal gap between the pads
    and the corona to 6 pitches. Empirical value to avoid DRC errors
    with symbolic pads (pxlib).
      When successufully done, mark the Corona cell as routed.
* Bug: In Cumulus/plugins/Core2Chip.IoNet, the regex for vectorizet net
    was wrong, it was allowing only one digit in the index.
* Bug: In Cumulus/plugins/Core2Chip.cmos, correct management of
    pad & corona clock nets. Correct connexion between vdde/vddi.
* Bug: In Unicorn/cgt.py, forgot to execute scripts when in text mode.
2019-05-24 23:57:22 +02:00
Marie-Minerve Louërat d641607ac3 Typos corrigees dans Python Tutorial for Hurricane database 2019-05-24 13:55:23 +02:00
Marie-Minerve Louërat 973dedc4a5 Typos corrigees dans les fichiers du User Guide 2019-05-24 13:24:11 +02:00
Marie-Minerve Louërat 10f0f9b55d Ajout Roselyne dans les contributeurs 2019-05-23 17:30:42 +02:00
Marie-Minerve Louërat b78a524e5f Introduction d'une page de garde pour la documentation Coriolis et Python 2019-05-23 15:51:06 +02:00
Jean-Paul Chaput 3fb746fbef Support for mixing real pads & symbolic core. Wrapper around s2r.
* Change: In Hurricane::Error constructors disable the backtrace generation.
    (*very* slow).
* Change: In Hurricane::Library::getHierarchicalname(), more compact
    naming. Remove the name of the root library.
* New: In Hurricane::Net, new type "FUSED", for component with no net.
    More efficient than having one net for each.
* Change: In CellViewer, BreakpointWidget, use Angry Birds icons.
* Change: In CellWidget::State, use the hierarchical name (cached) as key
    to the state. This allow to load two cells with the same name but from
    different libraries in the widget history.
* Change: In PyGraphics, export "isEnabled()" and "isHighDpi()" functions.
* Change: In CRL/etc/symbolic/cmos/plugin.conf, and
    CRL/etc/common/plugin.conf use the physical dimensions converters.
* Change: In CRL/etc/symbolic/cmos/technology.conf, make the GDS layer
    table coherent with the default Alliance cmos.rds.
* New: CRL/python/helpers/io.py, put ErrorMessage new implementation here,
    along with a new ErrorWidget written in PyQt4. It seems finally that
    PyQt4 can be used alongside Coriolis Qt widgets.
      New ErrorMessage.catch() static function to manage all exceptions
    in except clauses.
* Change: In CRL/python/helpers/, no longer use ErrorMessage.wrapPrint(),
    directly print it.
      Rewrite the utilities to display Python stack traces "textStacktrace()"
    and "showStacktrace()".
* Change: In CRL::AllianceFramework, shorten the names of the libraries.
* Change: In CRL::ApParser & CRL::ApDriver, more accurate translation between
    Alliance connectors (C record) and Hurricane::Pin objects. Pin are no
    longer made square but thin and oriented in the connecting direction.
      Use the new fused net for unnamed components.
* New: In CRL::GdsParser, implementation of SREF parsing, i.e. instances.
    Due to the unordered nature of the GDS stream, instances creation are
    delayed until the whole stream has been parsed and only then are they
    created.
      For the sake of reading back Alliance s2r GDS, we assume that any
    TEXT following a boundary is the Net name the boundary (component)
    belongs to.
      Create abutment box for Cells, computed from the bounding box, so
    the Hurricane QuadTree could work properly.
      Make use of the fused net for unnamed components.
* New: In Cumulus/plugins/chip, complete rewrite of the I/O pad management.
    Now we can mix real (foundry) pads and a symbolic core.
      To cleanly support the de-coupling between the real part and the
    symbolic one we introduce a new intermediary hierarchical level, the
    corona. We have now:
      Chip --> Pads + Corona --> Core.
      At chip level (and if we are using real pads) the layout is fully
    real (excepting the corona).
      The Corona contains everything that is symbolic. It has symbolic
    wires extending outward the abutment box to make contact with the
    real wires coming from the pads.
      In the pad ring we can use corners instances (or not), pad spacers
    or directly draw wires between connectors ring pads.
      Provide two flavors: placement only or full place & route.
    WARNING: If routing in a second step, *do not route* the *Chip* but
    the *Corona*.
* Change: In Cumulus/plugins/clocktree, give the modified Cell an
    additional extension of "_cts" (Clock Tree Synthesis) instead of
    "_clocked", to follow the common convention.
* New: In cumulus/plugins/S2R.py, encapsulate call to Alliance S2R and
    reload the translated Cell in the editor.
* New: In cumulus/plugins/core2chip, provide an utility to automatically
    create a chip from a core. To work this plugins must have a basic
    understanding of the pad functionalities which may differs from
    foundry to foundry. So a base class CoreToChip is created, then for
    each supported pad foundry a derived class is added. Currently we
    support AMS c35b4 and Alliance symbolic cmos.
* Bug: In Anabatic::Configuration, read the right configuration parameter
    "anabatic.topRoutinglayer" (Katana), and not the one for Katabatic...
* Change: In Unicorn/cgt.py, process the plugins in alphabetical order
    to ensure a reproductible ordering of the menus...
2019-05-22 14:34:32 +02:00
Jean-Paul Chaput 9bcc81eb7d Tweak FindBoostrap.cmake to detect Qwt under Linux Mint. 2019-05-10 12:12:30 +02:00
Jean-Paul Chaput 1360479eed Switch place in menus between Katana & Kite (Katana becomes the default).
* Change: In Hurricane::CellViewer, reorganisation of the to level menus.
    Add "Misc." and it's two sub-menus "Beta" and "Obsolete".
* Change: In GraphicKiteEngine::addToMenu(), set Kite in the obsolete menu.
* Change: In GraphicKatanaEngine::addToMenu(), set Katana as the standart
    router.
2019-05-10 11:59:21 +02:00
Jean-Paul Chaput 82dc58bf8e Redesign of I/O pads and Corona support to mix real and symbolic.
* Bug: In CRL/etc/symbolic/cmos/plugins.conf, rails dimensions are no
    longer expressed directly in lambda. Must be created using helper.l().
* Change: In CRL::ApParser, slightly more smart management of Pin width.
    Must normalize Pin behavior between Alliance & Hurricane as in
    Alliance they have only one dimension.
* Change: In CRL::LefImport, if a net name end with "!", assume it's a
    global one. Have to check this naming convention.
* Change: In Anabatic::NetBuilderHV::_do_1G_1PinM3() & _do_1G_1PinM2()
    now implemented. Needed for the corona routing support.
* Change: In AnabaticEngine::setupPreRouted(), exclude segments outside
    the abutment box.
* Change: In KatanaEngine::PowerRails, remove the I/O pad support as now
    we route only inside the Corona. So only one vdd/vss/ck are supported.
* New: In cumulus/plugins/ChipPlugin.py, complete rewrite of the chip
    support:
    * Uncouple pad I/O ring whith real cells (foundry) from a symbolic
      core. A new intermediate level "corona" is introduced to handle
      the real/symbolic transition.
    * Ability to explicitly setup position of the pads on the chip side
      in case of uneven distribution.
    * Enable clock tree to be build with 3 metal only (M2 to M4) instead
      of (M2 to M5).
2019-05-10 11:58:05 +02:00
Jean-Paul Chaput ce60ed5a30 In Etesian & Anabatic, use the "anabatic.routingGauge" conf. parameter.
* Change: In Etesian::Configuration CTOR, use the gauge from the
    configuration parameter "anabatic.routinGauge" instead of the default
    one.
* Change: In Anabatic::Configuration CTOR, use the gauge from the
    configuration parameter "anabatic.routinGauge" instead of the default
    one.
2019-05-10 11:54:32 +02:00
Jean-Paul Chaput 43629a6c1c Tweaking Layer & RoutingGauge management. Allow negative track indexes.
* Bug: In Hurricane python module, forgot to add the Segment type.
* Change: In Isobar/layer.getEnclosure() wrapper check and cast the Layer
    argument into BasicLayer.
* Change: In CRL::RoutingGauge::getLayerGauge(Layer*), getLayerType() and
    getLayerDirection() no longer check layer identity based on layer
    mask instead of just Layer* pointer. To allow a unified call wether
    the layer is real or symbolic.
* Change: In CRL::RoutingLayerGauge::getTrackIndex() and getTrackPositon(),
    no longer consider negative indexes as invalid and reset them to
    zero. The check for out of bound index is now left to Anabatic &
    Katana.
* Change: In CRL/RoutingGauge.getRoutingLayer() and getContactLayer(),
    more detailed error message.
* Change: In CRL/RoutingLayerGauge.getTrackIndex() and getTrackPosition(),
    indexes are now signed long instead of unsigned.
2019-05-10 11:52:42 +02:00
Jean-Paul Chaput 2beee8a25c Bug: Compopent creation inside a Collection loop In Cell::flattenNets().
* Bug: In Hurricane::Cell::flattenNets(): Same error again, do not create
    components while iterating over the components Collection.
      Now RoutingPad of top nets are create outside the loop as they must.
2019-05-10 11:48:33 +02:00
Marie-Minerve Louërat 16bd5270f7 Merge branch 'devel_anabatic' of ssh://bop/users/largo2/git/coriolis into devel_anabatic 2019-05-03 16:14:26 +02:00
Jean-Paul Chaput f6c840fd59 ISPD05 loading speed issues. IO PAD support for LEF importation.
* New: In Hurricane::IntrusiveMap, introduce IntrusiveMapConst which allow
    to search with a "const Key&" instead of a "Key", sparing the copy
    construction of the Key.
* Change: In Hurricane::Cell::NetMap, use the new kind of map with
    "const Name&" key access. This speeds up the Cell::getNet() method
    by suppressing one copy construction of a Name, which are costly
    after all...
      Should review the whole code to use "const Name&" everywhere it
    is possible.
* Change: In Hurricane::Entity & Hurricane::DBo, displace the unique
    identifier from Entity to DBo (move up to the base class).This
    to allow us to build deterministic map of DBo requireds in
    UpdateSession (which is built upon a SharedProperty).
      WARNING: This break the JSON database exportation support, do not
    use it until fixed/rewritten.
* Change: In Hurricane::Layer, add an attribute to know if a layer is
    associated to a blockage. Modificate accordingly PyLayer and
    BasicLayer.
* Change: In Hurricane::SharedProperty, the set of owners (DBo*) is now
    stored in a std::set sorted on the objects Ids, instead of a simple
    vector. The linera search time through the std::vector was starting
    to show (ISPD05 bigblue1).
* Bug: In Isobar::PyInstance, make full contructor signature (5 arguments)
    conform to the C++ one. It was only accepting the four first and
    forcing the placement status to be FIXED.
* Bug: In CRL/etc/symbolic/ispd05/kite.conf, update for the new configuration
    requirements where all distance must be converted into DbU in the
    file itself (use "helpers.l()", "helpers.m()"). Apply to the cell &
    routing gauges.
* Bug: In CRL/etc/symbolic/ispd05/technology.conf, update for the new
    configuration. "helpers.initTechno()" *must* by called first thing
    in this file in order for the Technology to be created.
* New: In CRL::AllianceFramework, add matchCellGauge() &
    matchCellgaugeByHeight()
* New: In CRL::CellGauge, add a flag to distinguish gauges meant for
    IO Pads and an "isPad()" predicate.
* Change: In CRL::Ispd05Bookshelf, flush the UpdateSession stack every
    1000 elements additions. Maybe not necessary now the the UpdateSession
    property relies on a std::set instead of a std::vector.
* New: In CRL::LefImport, support for SITE and match/create the appropriate
    CellGauge on the fly. Specific support for MACROS that are flagged PAD.
      Add a dedicated post-treatment for PAD connectors, extend them toward
    the boundary of the nearest abutment box side. Tested only on AMS 350nm
    c35b4 for now.
      This part is most likely to be tweaked for every kind of real foundry
    pad that we may encounter...
* Change: In EtesianEngine::findYSpin(), use the C++ "for" construct to loop
    over Collections.
* Change: In Unicorn/cgt.py, register the Python/C++ tutorial support by
    default.
2019-04-22 12:16:16 +02:00
Jean-Paul Chaput bbcf14eb5a First step in supporting ISPD18 detailed routing benchmarks.
* Change: In CRL::DefImport, added callback to read the DEF UNITS statement
    and perform a correct length conversion. Previously set to read pseudo
    lambdas in hundredth of microns.
      Added DefParser::getLefCell() to lookup master cells in the LEF
    libraries before looking in the Alliance ones (rooted under "LEF"
    library).
* Change: In CRL::LefParser::_pinPostProcess(), when no segment suitable
    for terminal connexion is found, add all of them. This is a quick hack
    and an a correct policy that match all techno must be implemeneted.
* New: In CRL::pyCRL, add a Python wrapper for DefImport.
* New: In CRL/etc/45/ispd18/ added configuration files for the "real"
    technology used by the ISPD18 45nm design benchmarks.
2019-03-29 11:07:55 +01:00
Jean-Paul Chaput 3e4430c089 Fix huge memory link in Collection iterator.
* Bug: In Hurricane::Collection::iterator, the iterator use a locator from
    a getLocator() not wrapped inside an auto_pointer like GenericLocator.
    So the destructor of the iterator must take care of the deletion.
      This was showing more and more as we converted forEach() into the
    C++ 11 for syntax.
      Seems to decrease the memory use by almost a factor 2...
* Bug: In Dijkstra::_cleanup(), as a double security, cleanup the queue.
2019-03-23 15:43:00 +01:00
Jean-Paul Chaput 3a2916b5e6 Improved clock-tree support for variable pitch routing gauges.
* New: In Hurricane::Isobar::PySegment, added wrapper for getOppositeAnchor().
* Bug: CRL::PyRoutingLayerGauge, Python wrapper of getTrackPosition() was
    in fact returning getTrackNumer().
* Bug: In Katana::PowerRailsPlanes::Rail::doLayout(), add the half minimum
    distance to the blockage segments extensions. Was causing too near
    VIAs is cmos45.
* Change: In cumulus/plugins/ClockTree, correctly manage routing gauge when
    the lower pitches (M2/M3) is different from the upper one (M4/M5).
    But we still can only do sxlib compliant gauges because we do not
    handle a switch in preferred routing directions.
2019-03-23 11:05:51 +01:00
Jean-Paul Chaput 5dd235b3cd Adding moc cpps to the link of Cyclop under Qt 5.
* Bug: In CRL::cyclop, on former versions of Qt 5 there was a double
    link of the moc generated modules. This appears to be solved under
    Ubuntu 10.04 LTS, so now we have to add them again explicitly.
2019-03-21 13:27:43 +01:00
Jean-Paul Chaput 435b647ddf Compatiblilty with boost 1.57 on RedHat 6. 2019-03-11 16:01:11 +01:00
Jean-Paul Chaput 94044992ef Pin management implemented for NetBuilderHV.
* Bug: In Katana::Track::expandFreeInterval(), the OutsideElement case was
    not handled correctly, the end index must be increased in that case.
    As a result, this function was returning too short an interval.
      This was affecting the computation of perpandicular free interval
    in DataNegociate::update() for perpandicular fixed but not in a track.
* New: In Anabatic::NetBuilder and NetBuilderVH, now manage GCells with
    one Pin, and up to three globals. Used to put terminals at the
    edge of a block.
* New: In EtesianEngine, now manage placed Pins.
    (done through extractInstanceName())
* Change: In CRL::RoutingGauge::getHorizontalGauge() no longer skip PinOnly
    gauges to find the reference one (same goes for vertical).
2019-03-10 13:25:43 +01:00
Jean-Paul Chaput 0b605000ed Bug fixes in Blif parser (no VHDL enforcement) & GDS driver.
* Bug: In Hurricane::DrawingQuery::drawGo(), forgot to apply translation
    on Polygon and Rectilinear.
* Bug: In Hurricane::Rectilinear, forgot implementation of getContour().
    Add a new accessor getPoints().
* Bug: In CRL::Blif::load(), do not always enforce translation towards
    VHDL names. When loading LEF+gds it may change the Cell names between
    the two stages so the gds layout do not get added to the LEF Cell
    phantom.
      Now add a boolean enforceVhdl argument (may be a flag in the future).
* Bug: In ::GdsStream::operator<<(Cell*), forgot to drive the Rectilinear.
2019-03-07 20:14:08 +01:00
Jean-Paul Chaput 9a872b10af Add boost157 for building under RHEL 6 with Software Collections. 2019-03-07 20:02:44 +01:00
Jean-Paul Chaput f107a68938 Reorganisation of menus in a more clear way. 2019-03-05 23:23:14 +01:00
Jean-Paul Chaput 89c730ec61 Bug in coriolisEnv.py. Avoid looping in Katana repair stage.
* In Katana::RoutingEvent::_processRepair(), do no reschedule perpandiculars
    that are already in repair mode, they may loop with repackperpandiculars().
2019-03-04 23:25:25 +01:00
Jean-Paul Chaput cc899710ea Update generated documenation (change for devtoolset). 2019-03-04 14:35:16 +01:00
Jean-Paul Chaput 05a7af886c Enabling the user to choose the devtoolset it needs.
* Change: In boostrap/ccb.py, change the devtoolset argument from a fixed
    behavior "--devtoolset-2" to a selecting one "--devtoolset=X" where X
    is the requested version of the devtoolset.
      Modify coriolisEnv.py to dynamically detect with which devtoolset
    we have been compiled. Idem for Makefile.package and
    FindBootstrap.cmake.
2019-03-04 14:20:13 +01:00
Jean-Paul Chaput fac01b10aa Compare function key adjustement for Rule in Technology.h
* Bug: In hurricane/Technology.h we define a set of UnitRule with a
    custom sorting function. STL starting with gcc 8, introduce a type
    checking of the compare function. And as everithon is template, we
    must use the exact key type and no longer a base type... So we create
    an overload for each derived type :-(
2019-03-04 12:45:02 +01:00
Jean-Paul Chaput 915eaf2157 Patch flute to be compatible with boost 1.65.
* Bug: In flute, a 'D' macro is defined which collides with another one
    from Boost 1.65. Rename it into 'DPARAM'.
2019-03-04 12:34:43 +01:00
Jean-Paul Chaput 0f4c8ec181 Added FLUTE library as a top level standalone tool in Coriolis. 2019-02-26 20:13:47 +01:00
Jean-Paul Chaput 57d52023e1 Command line support for Katana in cgt.
* New: In Unicorn/cgt.py, add "-K" option to use Katana for global and
    detailed routed (in place of Knik/Kite).
      Comment the preroute stage to ensure determinism (I often forgot
    to run this stage while in graphic mode).
2019-02-26 20:09:26 +01:00
Jean-Paul Chaput 9e6463c217 Support for density estimation for the global router.
* Bug: In Anabatic::Edge::getDistance(), remove the additionnal 0.1
    added to horizontal edges. This was for testing before the hScaling
    parameter was added (to the distance computation in GlobalRoute).
* New: Anabatic::Path_Edges, collectio to walkthrough all the edges
    between two node. More complex than in Knik as we are no longer
    using a regular grid. We may request the north bound path or south
    bound path.
      Collection returned by AnabaticEngine::getEdgesUnderPath().
* New: In Anabatic::NetData, add a new flag GlobalEstimated to tell if
    the net RMST has been computed (using FLUTE).
* New: In Anabatic::PriorityQueue, used to sort Vertexes by increasing
    distances, add a new criterion to be used in case of distance
    equality. The attractor which should be the center of the search
    area. In case of equality, we choose the Vertex which is closest
    to the attractor. Give a small improvement, and more "dendritic"
    trees.
      For a more simple implementation of the comparison function it is
    made as a static member (so no two Dijkstra objects at the same
    time...).
* Change: In Anabatic::Edge, make the estimate occupance a floating
    point number instead of an integer.
* New: In Katana::GlobalRoute, finally implement the estimated congestion
    driven router. Net RMST estimated using FLUTE.
      Use the historic cost from Knik implementation and not the one
    given in Damien's thesis, which seems not be the same and a bit
    strange.
* New: In KatanaEngine, add the ability to exclude nets from routing,
    and export it to Python.
2019-02-26 20:03:53 +01:00
Jean-Paul Chaput 6ae3a902ee Correct H/K parameters for global routing. New cmos45 symbolic.
* Change: In CRL/etc/cmos/kite.conf, setup correct H/K parameters for
    the Katana global router. Value copied from Knik. They give a
    faster solution.
* New: In CRL/etc/cmos45/, new symbolic settings adapted to FreePDK 45nm.
    Courtesy of N. Shimizu. To be used with NSXLIB.
* New In CRL::System, add "coriolis_top" to the set of pathes available
    to the user.
2019-02-26 20:00:28 +01:00
Jean-Paul Chaput e704306cad More robust deterministic netmap. Use classic string hash.
* Change: In Hurricane::Cell::NetMap, the hash function is now based on
    the string itself and not on the id of the SharedName. We now may
    remove the id attribute of the SharedName.
      This to ensure a more robust deterministic behavior. The sort
    order do not depend on whether we did use names before or not.
2019-02-26 19:56:29 +01:00
Jean-Paul Chaput 9f69230837 Correct CellWidget & CellPrinter to be really WYSIWYG.
* Change: In Hurricane::CellWidget, new "isPrinter" attribute to know if
    the CellWidget is used as a device for printing.
      New function copyExtensionsGos() to duplicate the ExtensionGo drawing
    callbacks. This is a temporary hack until the ExtensionGo are made static
    to be shared by all CellWidgets.
      In _redraw(), the DrawingQuery flags were not correctly reset between
    different stage of the drawing. This was resulting of uneeded walkthough
    of the slicing tree, along with incorrect display of some of the layers
    (i.e. rubbers where diplayeds when ExtensionGos where active).
* Change: In GraphicKatanaEngine, fine tune the display of GCells for printing
    CellWidget.
* Change: In Hurricane::CellPrinter, copy all the settings from the palette
    of the reference (graphic) CellWidget into the printer CellWidget.
    Also copy the ExtensionGos callbacks so we can print them. Use the
    new CellWidget attribute "isPrinter" for the callbacks to be able
    to adapt to Printer settings.
* Change: In Hurricane::Time::getStringTime(), only print two decimals
    for time durations.
2019-02-20 18:24:43 +01:00
Jean-Paul Chaput 6fd383ad51 Make FLUTE an independant tool in the Coriolis git repository.
* Change: To allow multiple tools, and not only Knik, to link and use
    FLUTE, remove it from Knik and put it at top level.
      Bootsrap must compile this new tool and the library must be
    included in all CMakeLists.txt depending on Knik (and soon
    Anabatic).
2019-02-12 12:48:52 +01:00
Jean-Paul Chaput ea4fdfd230 In Anabatic, correctly set the wire width according to the routing gauge.
* New: Anabatic::AutoContact::setLayerAndWidth() to set both layer and
    VIA width/side according to the RoutingGauge. If the delta in zero,
    use the metal gauge, and the VIA gauge otherwise.
* Bug: In Anabatic::AutoContactTerminal, Anabatic::AutoContactTurn,
    Anabatic::AutoContactHTee & Anabatic::AutoContactVTee, in the
    updateTopology() method, set both the layer and the VIA with when
    there is a change of layer. Note that this default size may be
    overriden later by updateSeize() in the case of non-default width
    segments.
* New: In Anabatic::AutoSegment, new overload setLayer(size_t) to set
    both layer and segment with according to the routing gauge.
* Bug: In Anabatic::AutoHorizontal and Anabatic::AutoVertical, in method
    _makeDogleg(), make use of the new setLayer() to correctly set up
    the wire width.
      Idem for Anabatic::AutoSegment::changeDepth() and ::makeDogleg(),
    and in Anabatic::LayerAssign.
2019-02-12 12:43:09 +01:00
Marie-Minerve Louërat aa7cb7d4d8 Merge branch 'devel_anabatic' of ssh://bop/users/largo1/git/coriolis into devel_anabatic 2019-02-04 14:56:45 +01:00
Marie-Minerve Louërat b05ad820a4 Remove tedius lef.tab.h 2019-02-04 14:55:29 +01:00
Jean-Paul Chaput 2f9a7076cb Forgoten hurricane analog generated documentation. 2018-11-29 12:03:26 +01:00
Jean-Paul Chaput 2b302495ef Correct dependency problems in lefdef. 2018-11-27 13:43:59 +01:00
Jean-Paul Chaput c76fa034ba Implementation of a red-black tree and an interval tree.
* New: In Hurricane::RbTree, template for red-black tree. Standard
    implementation but well integrated in the Hurricane database and
    ready to be derived (both iterator and Collection support).
* New: In Hurricane::IntervalTree, template for interval tree, derived
    from RbTree.
* New: unittests tool to perform unit tests.
* Change: In Bora::ChannelRouting, now implemented with IntervalTree.
    There is something suspicious here : the "thick" version of
    addWireoccupation() seems never to be called. Have to check the
    wide wire support implementation.
2018-11-07 23:48:43 +01:00
Jean-Paul Chaput ac51ac3910 Analog intergration part III. Removing obsoleted vlsisapd/openChams. 2018-10-18 18:26:15 +02:00
Jean-Paul Chaput fcd6d69a2f Analog integration part II. Analog place & route (slicing tree).
* Change: In Hurricane::CellWidget, set the minimal size to 350 pixels
    to fit my normal DPI secondary screen...
* Change: In Hurricane::Error(), reactivate the backtrace generation by
    default. Seriously slow down the program each time an Error is to
    be constructed.
* Bug: In Analog::Device::preCreate(), check for NULL Technology before
    attempting to use it.
* Change: In Hurricane/Analog, remove all '*Arguments*' classes and their
    Python interface. It was an obsoleted way of passing devices parameters
    to the Python layout generators (located in Oroshi). Now we just get
    them straight from the Device with the getParamter() method.
* Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze.
* Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove
    all uses of the "Arguments". Directly access the parameters through
    the device itself. Make the checkCoherency() with identical arguments
    as of layout().
* New: Bora tool that performs analog place & route. Based on a slicing
    tree representation. It is the thesis work of Eric Lao.
      Code beautyfication and some programming cleanup.
* New: Karakaze tool, provide the Python base class AnalogDesign used
    to build an analog design. Create/configure devices and assemble
    them in a slicing tree.
* Change: In Unicorn/cgt.py, display the stack trace in case of an
    ImportError exception as well as for other exceptions.
      Add Bora to the set for included tool engines.
2018-10-18 18:10:01 +02:00
Jean-Paul Chaput 3f73b9d033 Anlog integration part I. Atomic devices support (transistors).
* Change: In boostrap, remove support for Chams.
* New: In Hurricane::Technology, added support for DTR rules, UnitRule,
    PhysicalRule and TwoLayersPhysicalrule. Added devices descriptors and
    models descriptors (for Spice). Spice description is not used yet
    but kept anyway in case of future use.
* New: Hurricane::Analog whole library and it's Python interface. This
    provides support for transistors, capacitors and resistors. Only
    transistor support is fully implemented as of now.
* New: In CRL/python/coriolisInit.py, read configuration files for the
    Analog extension (analog.conf & devices.conf). Thoses are optionals
    and a simple warning is issued if not found.
      Added helpers/AnalogTechno.py DTR loading helper.
      Add analog configuration files for 180/scn6m_deep_09.
* New: Oroshi tool that provides actual layout drawing for transistors.
2018-10-01 16:52:17 +02:00
Jean-Paul Chaput dc01b60d5c Force the locale LC_ALL to be POSIX (in Hurricane::DataBase).
* Problem: In LEF/DEF, the parsers makes use of the libc "strtod()" which
    is now localized. So, if your environment is set up for French, the
    decimal separator is not '.' (dot) but ',' (comma). So floating
    numbers in LEF/DEF file are not longer recognized as such, causing
    the parsers to fail with a LEFPARS-1 error.
      To avoid that, we force the LC_ALL environment variable to POSIX
    in Hurricane::DataBase::create(). So first things that happens when
    Hurricane starts, is the environment to be reset.
      Strangely, when I try to setup only LC_NUMERIC with setlocale()
    it doesn't work. There is something I'm missing there...
2018-09-28 12:12:18 +02:00
Jean-Paul Chaput 3c849787e2 Removed generated bison file for the LEF parser. 2018-09-27 15:18:21 +02:00
Jean-Paul Chaput b53511ea83 Minor adjustements for analog device checker (test of AMS c35b4).
* Change: In CRL::GdsStream, no longer export empty Cells as structures,
    to avoid empty cells in Cadence. To prevent meta-transistors to be
    exported as real physical objects.
      Also put a hard-coded test to prevent exporting "control_r" model
    which is made of AMS standard cells for "amsOTA".
* Change: In CRL/PyRoutingGauge, export the isHV() and isVH() methods so
    the Stack can access it.
* Change: In Hurricane/PyCellViewer, export the removeHistory() method.
    When a Cell is deleted, it must be also removed from the editor
    history. This should be take care of automatically, but for now
    we make it manually through scripts.
* Bug: In Anabatic::NetBuilder::doRp_accessAnalog(), the gauge offset
    was not taken into account when creating initial Contact on
    RoutingPad. The program self corrected afterwards, but with the
    display of a disgraceful message.
* Change: In Anabatic::Configuration and Session, export the gauge offsets.
2018-09-20 18:24:30 +02:00
Jean-Paul Chaput 152276ddbb Corrected coordinates policy in stratus1.
* Bug: In stratus1, all coordinates given to the functions are now
    assumed to be in DbU instead of lambda. Designer must convert
    himself his coordinates from the unit of his choice into DbU.
      See helpers.l(), or helpers.m().
2018-09-11 19:21:11 +02:00
Jean-Paul Chaput 399a2e3c48 Merge branch 'devel_stratus' of ssh://bop-t/users/largo2/git/coriolis into devel_anabatic
Conflicts:
	documentation/CMakeLists.txt
	documentation/_templates/indexcontent.html
	documentation/index.rst
	katana/src/katana/RoutingEvent.h
	stratus1/CMakeLists.txt
2018-08-19 13:27:09 +02:00
Jean-Paul Chaput 116d927d1e Correct comutation of metricsBdu in GDS driver (courtesy of M. Koefferlein). 2018-07-17 13:36:17 +02:00
Jean-Paul Chaput d99d797a40 Debugged the GDSII driver. Now working with Cadence.
* Bug: In CRL::GdsDriver::GdsStream two bugs :
    1. The tm fields are int but must be casted into uint16_t in BGNLIB
       and BGNSTR.
    2. The mandatory LIBNAME record was missing.
    3. We also force, for now the dbu to be 1000 and the UU to be 1um.
2018-07-16 19:43:44 +02:00
Jean-Paul Chaput 55a29488c9 Correct handling of lambdas & microns in configuration files.
* Bug: In CRL/etc/NODE/VENDOR/Technology.conf, the database must be configured
    as early has possible so the functions ensuring length conversions can
    work correctly (l(v), u(v)). So we can no longer rely on a table to be
    read after the execution of the file. We perform a direct call to the
    helpers.Technology.initTechno() function. And it must be made first
    thing.
      In all tables taking dimensions, we must use one of the converter
    function helpers.l(v), helpers.u(v) or helpers.n(v) so the the value v
    get converted in lambda, microns or nanometer (resp.). Make the
    modifications in all technology.conf and kite.conf files.
* Change: In CRL/coriolisInit.py, remove the technoConfig variable that has
    been replaced by a direct call to helpers.Technology.initTechno().
* Change: In CRL/helpers.Alliance.loadRoutingGaugesTable(), no longer try to
    convert coordinates, they must already be in DbU.
* Change: In CRL/helpers.__init__.py, remove lambdaMode() and micronsMode()
    they could not be made to work as expected. Create l(), u(), n() as
    replacement.
2018-07-16 11:32:40 +02:00
Jean-Paul Chaput 094cb8a132 Improved handling of short nets (fully included in one GCell).
The short net mode degrade the routing in some cases. This will be
fixed in a next batch of commits.

* New: In Hurricane::NetRoutingProperty, added "ShortNet" flag for Nets
    that are completly inside *one* GCell.
* Bug: In CRL::BlifParser::Model::staticInit(), when looking for the
    output of zero and one cell, also skip the blockage net (as well as
    automatic and supplies).
* New: In Anabatic::AutoSegment, added "ShortNet" flag to know if the
    segment is part of a short net (fully included in *one* GCell).
      Also add accessor/mutators for the _analogMode flag (was it ever
    used before?).
* New: In Anabatic::NetBuilder::singleGCell(), if a RoutingPad is
    vertically small, add a vertical segment to give it some slack.
* New: In Anabatic::Dijkstra::_materialize(), detect "short net" as
    they have only one GCell in their source list...
* Bug: In AnabaticEngine::_loadGrbyNet(), reset the AutoSegment
    "short net" and "analog mode" creation flags between two different
    nets.
* New: In Katana::Configuration, added dedicated ripup for short net
    segmnts.
* New: In Katana: partially implemented support for "short dogleg", that
    is dogleg that are always kept in same metal because they connect
    neighboring perpandicular tracks. Not finished neither activated
    yet.
* New: In Katana::TreckElement and derived, export the the *short net*
    support from AutoSegment.
* Bug: In Katana::RoutingEvent::_processRepair(), when a segment is
    successfully inserted, re-process any perpandicular that is in
    repair state, as it may have a new chance to be placed.
* New: In Katana::SegmentFsm::slackenTopology(), always reject short nets.
* Bug: In Katana::Track::check(), correctly handle wide segments instead
    of issuing false check messages.
2018-07-16 11:16:51 +02:00
Jean-Paul Chaput b88c3336cd No longer build doc in top Makefile as it is already build. 2018-07-12 10:02:02 +02:00
Jean-Paul Chaput 6b29ad0078 In AllianceFramework, no longer try to load ".vhdl" files in ".vst".
* Change: In CRL::ParserMap, no longer recognize the file extensions
    ".vhdl" and ".vhd" which are true VHDL and cannot be parsed by the
    "vst" (Alliance structural subset VHDL) parser.
       This should solve annoying problems for the Makefiles when there
    is both the full VHDL file ".vhdl" and the synthesized one ".vst"
    (note that this problem do not arise when using Yosys/Blif).
2018-06-11 16:49:40 +02:00
Jean-Paul Chaput e88b2050c2 Tuning of Anabatic & Katana for AMS 350nm (c35b4).
* New: In Anabatic::LayerAssign, a new mode "LayerAssignNoGlobalM2V" has
    been added to manage the 3 routing metal technologies like AMS 350nm.
    The standard cells have all their connectors punctual and aligned on
    an horizontal line in the middle of the Cell. This is a design
    inherited from the channel routing times that makes global routing
    in metal2 *through* a standard cell almost impossible (except for
    directly neighboring cells). Thus, the layer assignment must move
    up all the metal2 that span more than two GCells.
* Change: In Katana::Manipulator::ripupPerpandiculars(), when a perpandicular
    has a fixed axis and it's (sole) underlying track is taken, ripup
    the other segment to ensure the perpandicular interval will be free.
      We need to do that, because in DataNegociate::update(), if the
    perpandicular is taken, the perpandicular interval will always been
    empty preventing the segment to have a valid track span (so directly
    failing).
* Change: In Katana::SegmentFsm::conflictSolveByPlaceds() the fixed axis
    segments must also been taken into account as conflicts.
       Also correct a small bug, the first conflicting segment in the
    interval was not taken into account correctly.
2018-06-11 16:44:26 +02:00
Jean-Paul Chaput 2077a19bec In AutoSegment::_changeDepth(), correct invalidation of GCells.
* Bug: In Anabatic::AutoSegment::_changeDepth(), GCells under the segment
    must be invalidated in order for the density to be recomputed.
    But we were using GCell::invalidate() which is meant for the quad-tree
    and graphic system, so the density almost never updated in case of
    a layer change, leading to over-congested GCells in the top layers
    (110% !).
       Now we directly set the Invalidated flag.
2018-06-08 12:20:37 +02:00
Jean-Paul Chaput ea9a1f3710 CRL::Blif parser now able to load both non-Alliance & Alliance design.
* Change: In CRL::Blif, we now can add a list of Hurricane library for
    the parser to look for standart cells. If the library list is *empty*
    we look use the Alliance mechanism, if not, we look *only* in this
    library list. This behavior is implemented in Subckt::createModel(). I
      To add a library, use CRL::Blif::add(Library*).
      This allow to manage symbolic or real mode loading, it may need
    some rework to clarify the interface.
2018-06-08 12:02:49 +02:00
Jean-Paul Chaput c5034a9156 Typo in CMakeLists.txt : AND instead of "and". 2018-06-06 23:22:18 +02:00
Jean-Paul Chaput 767407736d Add a fully generated documentation in the git repository.
* Change: In all tools supplying documentation, as we use some specific
    software to create the doc, they may not be available, or worse, be
    and incompatible version. So, by default, we install the files shipped
    with the git repository. To force a full doc rebuild, use the "--doc"
    flag of ccb.py.
2018-06-06 18:42:26 +02:00
Jean-Paul Chaput 40b82212e3 Detect double routing attempt in Katana.
* Change: In Anabatic::setupPreRouteds(), routed DeepNets can have
    components both at Occurrence root net devel and at top level.
    If no nets remains to route, set the tool state to EngineDriving,
    which prevent any further work (except for finalize).
2018-06-03 18:28:27 +02:00
Jean-Paul Chaput 1887f45135 Exported Polygon::getSubPolygons() to Python.
* New: In Hurricane::Isobar::PyPolygon, export the getSubPolygons()
    method. Makes a list of list (maybe tuple should have been better
    to prevent user's rewrite).
* Change: In documentation/examples/scripts/, update polygons.py to
    serve as a very basic test-bench for Polygon, manhattanhization
    and sub-polygons display.
2018-06-03 12:55:28 +02:00
Jean-Paul Chaput 4f089ffdea Polygon internal normalization. Sub-polygons for GDSII driver.
* Change: In Hurricane::Polygon, store the points so they are always
    ordered in the counter-clockwise (trigonometric) direction. This
    simplicificate internal computations.
* New: In Hurricane::Polygon, added getSubPolygons() methods, that
    split horizontally the polygon in sub-polygons of about 1000
    vertexes. This is mainly to be used by the GDSII driver to abide
    to the XY 4000 points limitation.
* New: In Hurricane::Isobar, export support for Point collections so
    the various contour Polygon methods can be created in the Python
    interface.
* New: In CRL::GdsDriver, split the Polygons into set of sub-polygons
    of less than 1000 vertexes. Use the getSubPolygons() method.
* Change: In stratus1.dpgen_RF2, makes more explicit error messages
    about placement by displaying the faulty vs. expected coordinates.
2018-06-03 11:47:31 +02:00
Jean-Paul Chaput ea16b5a556 Added GDSII parser. Component/Polygon reorganisation.
* New: In CRL, implement a GDSII parser. The complete syntax is supported,
    but only a few subset is really taken into account. It is intended to
    load the layout of standard cells only. The interface of the cell is
    provided through a LEF file and it complete layout through the GDSII.
      The loader work in a Library way. It takes a Hurricane library as
    argument and search in the GDSII library structures with a name
    matching the Cell of the library and complete them.
* Change: In Hurricane::Component, put the Contour methods at Component
    level so we can use them in a generic way in the CellWidget drawing
    primitives.
* New: Hurricane::Rectilinear polygon, for small rectlinear polygons.
    Should be less than 100 vertexes. For bigger ones, use Polygon
    which allows slanted egdes.
* Bug: In CRL, freepdk_45/technology.conf, there seems to be an incoherency
    bettween the GDSII layer numbers as defined in the Cadence FreeePDK45.tf
    file and the one used in the supplied layout of the GDSII cells.
      For now, we align on the GDSII cells to get nice layouts, but it
    has to checked.
2018-05-20 15:47:34 +02:00
Jean-Paul Chaput 4a65a8d4e7 Added GDSII driver. Bug in Blif parser.
* New: In CRL, implement a true GDSII driver. The driver is directly under
    CRL and do not use an intermediate structure in vlsisapd. The ASCII
    GDSII is removed.
      Huge polygons are not supported yet. Have to be split up in
    sub-polygons of less than 4000 vertexes.
      Symbolic layout can be exported to give a rough idea of the layout
    but RDS expension is not applied. Symbolic composite layers are
    expansed into their basic layers so the design *looks* normal.
* Deprecated: In CRL, remove all traces of the old XML configuration
    parsers. No one needs them now, including Chams.
* Bug: In CRL::BlifParser, before blindly loading the model of a subckt
    from disk with AllianceFramework, checks if it is in the Catalog
    first. Load with AllianceFramework only cells that are in the
    Catalog.
      This prevent a file of the same name than a model to be loaded
    shadowing the later defintion of the model in the Blif file.
      All this is due to the fact that Blif could be non-ordered for
    the models...
* Change: In Hurricane::BasicLayer, the "extract number" is replaced
    by a GdsLayer and GdsDatatype to generate accurate GDS files.
    Even if datatype is 0 most of the time.
      Update all the "technology.conf" files in CRL to provide those
    two numbers.
2018-05-15 13:12:00 +02:00
Jean-Paul Chaput 41c9959e30 Added support for diagonal wires (45° and 135°)
* New: In Hurricane::Diagonal, new object to represent 45° and 135°
    segments (X routing). Althought they have source & target, they
    are not articulated like Horizontal & Vertical, due to the
    combined displacement of X and Y (diagonal).
      Maybe we should create a common class for all the polygons
    to make "::getContour()" a method.
      Now we could represent self capacitances and high frequency
    wires.
2018-05-07 13:46:44 +02:00
Jean-Paul Chaput 6ed8de5837 Added latest doc compilation to avoid rebuild. 2018-05-05 00:23:44 +02:00
Jean-Paul Chaput 0902b21f23 Added support for huge approximated polygons (for photonics).
* New: Hurricane::Triange as been renamed into Hurricane::Polygon.
    Add support for convex polygons. Polygon are approximateds by
    excess by a manhattan rectilinear polygon (with potentially
    thousands of vertexes). To reduce the memory footprint,
    compaction techniques reducing by at least a factor 4 has been
    implemented. We could go further by only storing the non-repetitive
    part of the edge (defined by the integral fraction dY/dY).
    We will see, if the program slows too much.
      The manhattan approximate is always computed but displayed
    only if the polygon grid step is greated than 4 pixels.
      The level of approximation of the polygons can be controlled
    through the "DbU::_polygonStep" parameter.
* Change: In CRL/coriolisInit.py and CRL/helpers/Technology.py, regroup
    all DbU related parameters into "technoConfig" (i.e. suppress
    "viewerConfig"). Update all the relevant technology.conf configuration
    files.
      Change the loader behavior so that "technoConfig" is read first
    and is now responsible for creating the Technology of the DataBase.
* New: In Hurricane::CellWidget, added support for displaying mahanttanized
    polygons.
* Change: In documenation/scripts/expample/polygons.py, perform (I hope)
    a comprehensive test of the polygons (check all slopes, clockwise and
    conter-clockwise).
* New: In Hurricane::DbU, added template to manage vector<> of DbU.
    Support for the "polygonStep" parameter.
2018-05-04 17:06:41 +02:00
Jean-Paul Chaput 1a338f620c Corrections in the Dijkstra global routing (ripup) mechanism.
* Bug: In Anabatic::Dijkstra, the degree of a vertex (the number of neighbors
    belonging to the same net) was miscalculated. This was leading, in the
    materialize step to some feed-through vertexes not being broken.
    Leading in turn to incomplete transformation of the detailed routing.
      Also in _trackback(), the degree of the first vertex we were backtracking
    from was not incremented.
* Bug: In Anabatic::Dijkstra::materialize(), systematically use
    GCell::breakGoThrough() on both source and target. This is needed when
    we are in the ripup phase as both source and target can be go-through.
      This was also leading to incomplete detailed routing transformation.
* Change: In Anabatic::Edge::ripup(), ripup one third of the segments instead
    of thoses exeeding the global length threshold. This way we are sure to
    desaturate an edge. Needs to be further calibrated.
* Change: In Aanabatic::GCell::breakGoThrough(), no longer return NULL.
    Return existing gcontact if any. Break if it is a go-through and create
    a new gcontact in last resort. Maybe rename this function.
* New: In Anabatic::Configuration, new parameters:
    - anabatic.edgeHScaling, to adjust the length of the horizontal edges
        relative to the vertical ones (this is a ratio).
    - anabatic.globalIterations, set the maximum number of ripup passes
        of the global router.
* New: In CRL/etc/*/kite.conf, added new parameters anabatic.edgeHScaling
    and anabatic.globalIterations.
* New: In Katana::GlobalRoute::DigitalDistance, take into account the new
    edgeHScaling factor. Must be used when the capacity of V-edges differs
    greatly for H-edges (case of AMS 350nm c35b4 for instance).
* Bug: In Katana::GlobalRoute::DigitalDistance, the historic cost is
    computed for an edge length of "1". Must be multiplicated by the
    current edge length to have any measurable effect.
      This bug is finally explaining why the ripup was producing the
    same solutions over and over, the historical cost was negligible!
2018-04-16 12:10:48 +02:00
Jean-Paul Chaput 80dcd264bb Allow nearest Track selection in Katana::RoutingPlane::getTrackByPosition().
* Change: In Katana::RoutingPlane::getTrackByPosition(), when requesting a
    track less than *one pitch* beyond the last one, return the last one
    instead of NULL. Only if the mode allows it (i.e. Nearest or Inferior).
2018-04-13 15:06:15 +02:00
Jean-Paul Chaput 580ca0892c Correct rounding of GCell horizontal size in GCell::doGrid().
* Change: In Anabatic::GCell::doGrid(), the GCell where square using the
    slice height as side. This was leading to vertical edges with slightly
    different capacities when the vertical picth was not a multiple of
    the horizontal one. This was not a bug per se as the global router
    is able to manage any interval.
      Now the horizontal side is rounded on the slice step.
2018-04-13 15:00:13 +02:00
Jean-Paul Chaput cabbab5140 Correct interval capacity computation around zero in RoutingLayerGauge.
* Bug: In CRL::RoutingLayerGauge::divide() & getTrackNumber(), the number
    of traks crossing an edge was wrongly computed for GCells around the
    zero coordinate, this was due to the change in rouding direction
    around zero. It was starting to show for routing gauges with an offset.
      Note: to simplificate the computation of the capacity of an interval,
    all the track over a Cell are computed from (0,0). The Cell abutment
    box has to be choosen relative to that. The tracks positions are fixed
    all over the Cell (or chip if it is one).
2018-04-13 14:59:40 +02:00
Jean-Paul Chaput 6b4baad8b9 More non-deterministics behavior corrections.
* Bug: In Hurricane::Cell_SubCells collection, order the set<> of Cell
    with Entity::CompareById instead of pointer values.
* Bug: In Hurricane::Component_ConnexComponents::Locator, sort the
    set<> of Components with Entity::CompareById instead of pointers.
* Bug: In Hurricane::Occurrence::operator<(), uses Ids to compare
    both _entity and _sharedPath. Check for NULL pointers.
* Change: In Hurricane::IntrusiveMap, add a debug output in _resize()
    like for IntrusiveSet.
      Note to myself : despite their names, InstrusiveMap are hash
    tables and not map<> in the STL sense.
* Bug: In CRL Core, Vst parser, sort the CellVectorMap on Ids.
* Bug: In CRL::NamingScheme::toVhdl(), sort the set<Cell*> models on Ids.
* Bug: In CRL::toVhdlName(), sort the set<Cell*> models on Ids.
* Bug: In CRL::getInstancesCount(), sort the map<Cell*,size_t>
    gatesByMaster on Ids.
2018-04-08 16:58:55 +02:00
Jean-Paul Chaput 2465d12c87 Merge branch 'devel_anabatic' of ssh://bop-t/users/largo2/git/coriolis into devel_anabatic 2018-03-27 23:56:09 +02:00
EricLaoGitHub 457b4f0acb Minor modification for Analog wire occupation estimation
In Dijkstra.h:
   - Add: accessor to get _sources
2018-03-27 18:29:51 +02:00
Jean-Paul Chaput 5a02d1ad3b Do not take into account segment when the overlap is zero...
* Bug: In Katana::Track::addOverlapCost(), check that the overlap is
    not *exactly* zero (exact interval fitting), and do not consider
    them as obstacle (they where raising the infinite flag when they
    where *fixed*).
2018-03-27 18:04:43 +02:00
Jean-Paul Chaput 45f941719d Topology update was not correctly done after layer change.
* Bug: In Anabatic::AutoSegment, Anabatic::AutoContact and derived
    classes, the recursive invalidation mechanism did have cross-call
    troubles.
      - The various AutoContact::_invalidate() now take the flag into
        account instead of resetting it. This is for Flags::Topology
	to be passed along from segments to contacts.
      - In AutoSegment::invalidate(), do not invalidate S/T contacts
        already invalidateds. In the same way, do not invalidate
	aligned segments already invalidateds (save some recursion).
      - In AutoSegment::_changeDepth(), call invalidate with
        Flags::Topology (to force contact update) and Flags::NoCheckLayer
        to avoid disgraceful warnings.
* New: Anabatic::NetBuilder::_do_xG_1M1() with (x >= 2) new set of
    optimized topologies when there is multiple globals but only one
    terminal. The default one was making two connections to the same
    RoutingPad, which was making clutter.
2018-03-27 18:03:51 +02:00
Jean-Paul Chaput 0fa6f8be9b Determinism correction of Hurricane, CRL core & Katana.
* Bug: In Hurricane::Cell::uniquify(), a set<Cell*> sorted on pointers
    was remaining. Now sorted on Entity::Id.
* Bug: In CRL::VhdlEntity, in the driver, the components where driven
    in pointer order (set<> again). Now use ids.
* Bug: In CRL/etc/scn6m_deep_09/technology.conf, the symbolic extentions
    for VIAs and layers were wrong. Have to be multiplied by two.
* Change: In AnabaticEngine, AutoContact and AutoSegment LUTs are now
    sorted on Entity::Id. Should not have had any impact, but better
    safe than sorry.
* Change: In KatanaEngine, Symmetric contraint map<> is now sorted on
    Entity::id. Idem for TrackSegmentLut.
2018-03-25 00:58:22 +01:00
Jean-Paul Chaput 23cb020ed3 Fix in 180/scn6m_deep_09, forgot to setup metal layers mininal spacing.
* Bug: In CRL Core, etc/180/scn6m_deep_09/technology.conf the minimal
    spacing for the metal layers layout were not set, allowing the
    router to place VIAs too close to each others. This was generating
    either DRC errors or short-circuits.
2018-03-21 17:32:05 +01:00
Jean-Paul Chaput e5892ab855 Bug: In singleGCell(), make dogleg for misaligned metal1 pins.
* Bug: In Anabatic::NetBuilder::singleGCell(), in HV mode, check if the
    two adjacent metal1 pins at least share a vertical span. If not,
    create a dogleg.
2018-03-21 16:06:55 +01:00
Jean-Paul Chaput add2136562 Forgotten isobar header for Triangle. 2018-03-20 11:56:15 +01:00
Jean-Paul Chaput 14fd994f69 Added first suppport for Polygons (Triangles). 2018-03-20 11:49:04 +01:00
Jean-Paul Chaput d9ac21e594 Forgotten HTML files in PythonTutorial. 2018-03-19 18:14:38 +01:00
Jean-Paul Chaput d4913dfb22 In documentation/examples, doChip now can be run through cgt. 2018-03-19 17:09:30 +01:00
Jean-Paul Chaput 8434b01457 Add missing 'anabatic.routingGauge' parameter for scn6m_deep. 2018-03-19 14:16:05 +01:00
Jean-Paul Chaput 3a6760f52a Bad guessing of the output of zero_x0 & one_x0 in BlifParser.
* Bug: In CRL::BlifParser::Model::staticInit(), when looking for the
    output of the Cell, discard power supplies *and* automatic Nets.
2018-03-19 12:55:22 +01:00
Jean-Paul Chaput 2a36a72e34 Improve error messages about parameters in PyOccurrence constructor. 2018-03-18 23:29:57 +01:00
Jean-Paul Chaput 1c2c858ce8 Added netlist & tool engines to Hurricane+Python tutorial. 2018-03-18 23:28:49 +01:00
Jean-Paul Chaput dd4a01fe70 Validating channel routing mode (two metals) on SNX.
* New: In Hurricane::Entity, add an id counter limit and a memory size
    limit. The two limits are checked only when a new Entity object is
    created. This should help avoiding massive memory links.
* New: In CRL Core, add a "crlcore.groundName" and a "crlcore.powerName"
    parameter to specify the name of the ground/power signals to be
    created if they are missing in a Cell. For Alliance libraries it
    would be "vss" & "vdd" (default values), but for real technologies,
    it is often "gnd!" & "vdd!".
      The Blif parser is modificated to make use of it.
* Bug: In AnabaticEngine::unify(), set the resulting unified segment in
    the  center of the GCells common side. Gcells under a segment are
    found by using the edge that cover the segment axis. When we have
    a "bend" GCell stack and the axis is wrong, they could be ommited.
      This was causing deleted segments to be not removed from some
    Edges, then core dump.
* Change: In Anabatic::AutoSegment::create(), smarter choosing of the
    reference contact, select the fixed or terminal one instead of
    always the source one.
* New: In Anabatic::Edge::isEnding(), new function to check if a
    segment going through an Edge is starting/ending in either source
    or target GCell of the edge (active only when running in channel
    mode).
* New: In Anabatic::Edge::add(), a segment takes part in the occupancy
    only if it is not ending in either source or target (channel mode
    only). The occupancy due to terminal is pre-computed in Katana.
* New: In Anabatic::Edge::ripup(), in channel mode, never ripup a
    segment which is ending in either source or target (we *have* to
    access this edge to connect to the terminal).
* Bug: In Anabatic::GCell::hcut() and vcut(), force the update of
    the Edge which is on the side that will get splitted by the cut.
    It's capacity will be reduced to it must be updated.
* Change: In Anabatic::GCell::updateGContacts() add a flag to conditionnally
    update horizontals or verticals only. We may require only a partial
    update when resizing the GCell in only one direction.
      This, again, related to the fact that we compute the GCells under
    a segment thanks to it's axis position, so we need to be very careful
    when modificating axis.
* Change: In Katana::Block::resizeChannels(), only update GContact vertical
    position. Do not disturb X positions of segments.
* Bug: In Katana::GlobalRoute::DigitalDistance, in channel mode, some
    Edges can have a zero capacity, but still be reachable if the net has
    a terminal in either source or target. Look for this case and return
    a distance of zero instead of "unreachable". This was causing the
    global routing not to complete in channel mode.
      For computing the edge distance, makes the vertical edges much more
    long (10 times) than the horizontal ones as the vertical capacity is
    very limited. Hard coded for now, should make it a parameter in the
    future.
* Change: In KatanaEngine::annotateGlobalGraph(), decrease the capacity
    of edges with reserveCapacity for each terminal inside a GCell.
    Both north and south edges are decreased as we a terminal will
    block both north and south edges.
      As a counterpart, the Edge capacity is not decreased when the
    global router connect to a terminal.
* Change: In Katana::RoutingEvent::revalidate(), when in repair stage,
    do not expand the slack for horizontal segments in channel mode.
    So they may not overlap the standard cell row.
* Bug: In Stratus documentation, do not use the french option in babel,
    the documentation is in english!
* New: In Documentation, added Hurricane/Python tutorial, part for drawing
    layout.
2018-03-16 16:20:04 +01:00
Jean-Paul Chaput 59917680cb In BlifParser, revert gnd! and vdd! to vss and vdd. 2018-03-08 15:53:02 +01:00
Jean-Paul Chaput c7b8902c77 In documentation, if sphinx is not found, install the pre-generated doc. 2018-03-08 14:55:06 +01:00
Jean-Paul Chaput 8f25b97271 Improve Edge ripup method. Improve two-metal terminal management.
* New: In Anabatic::Edge::ripup(), sort edges to ripup by decreasing
    length so the longest gets riped up first.
      In two metals mode, ripup all segments *except* those who have
    terminal contact in the GCell, because they must use it anyway.
* Bug: In Anabatic::GCell::getEdgeAt(), the size hint flag was not
    correctly selected, leading to the use of an edge in the wrong
    side. So deleted segments where not deleted from their edges,
    leading to core dump. Don't understand how it can have not shown
    until now.
* New: In KatanaEngine::annotateGlobalGraph(), for two metal gauges,
    decrease the edge capacity on both north and south side for each
    terminal in the GCell. As a terminal must be accessed through
    north or south it blocks the whole vertical track (hence both
    edges).
2018-03-06 01:48:44 +01:00
Jean-Paul Chaput db8675e501 Disable dragging constraints for Device (analog) terminals.
* Bug: In Anabatic::AutoHorizontal::_makeDogleg(), do not take into
    account dragging constraints from perpandiculars if the terminal
    is from a analog Device. We can never drag over it as it is
    forbidden.
      Same modification for AutoVertical.
2018-03-02 16:58:21 +01:00
Jean-Paul Chaput aa7b6fd620 Correction for the two-metal routing mode.
* Bug: In AnabaticEngine::loadGlobalRouting(), call relaxOverconstraineds()
    only if we are *not* in two-metal mode.
* Bug: In NetBuilder::construct(), allow any number of globals (up to 6)
    when in two-metal mode. Should be sufficent for now.
* New: In AnabaticEngine, new method _updateGContacts() to re-compute
    the positions of the global routing contacts *after* a GCell
    resize.
* Bug: In Katana::Block::resizeChannels(), must call _updateGContacts()
    after the resize to properly shift their positions.
2018-03-02 16:55:01 +01:00
Jean-Paul Chaput e3d9ab5c23 Merge branch 'devel_anabatic' of ssh://bop-t/users/largo2/git/coriolis into devel_anabatic
Conflicts:
	anabatic/src/anabatic/GCell.h

        Die, GCell::updateGContacts(), Die !
2018-02-21 17:57:38 +01:00
Jean-Paul Chaput b664eee731 Problem of merging for GCell::updateGContacts(), again. 2018-02-21 17:33:01 +01:00
Jean-Paul Chaput 97d5a1f583 Bad computation of optimal position for analog segments.
* Bug: In Anabatic::AutoSegment::computeOptimal(), the "side stack"
    computing the intersection of all the sides of the GCell that the
    segment is going through was implicitly supposing that the
    resulting intersection wasn't empty. But for analog segment, we
    compute the position of all the segments linked though simple
    doglegs, and as dogleg occurs there can be a sufficient shift
    so the intersections of all the sides became empty.
      Now the "side stack" can manage configuration when instead
    of having an intersection we have a "hole" in the GCell side
    span (only one hole is supported at the moment). When a hole
    is present, the optimal position is the center of the hole.
      Should be refined so that the position is computed according
    to the longest GCell that we go through.
* Change: In Katana::SegmentFsm::_slackenGlobal(), when slackening
    a global from a ananlog net, allow to make a dog leg once
    instead of immediately moving up. The break point is the center
    of the segment.
* Change: In Katana::Manipulator::Makedogleg(DbU::Unit) if the break
    position is over a device, choose the left of right GCell.
2018-02-21 17:03:43 +01:00
Jean-Paul Chaput 793dbb26b2 Capacity managment by layer in Edges & GCells (plus fixes).
* New: In Anabatic::EdgeCapacity, dedicated object to manage the capacities
    of an edge by layer. This needed now because with real technologies
    layers capacities differs (unlike with symbolic technologies).
      This object is separated to be shared between Edges with identical
    characteristics (direction+interval). Deletion is automatic and
    done through refcounting. All the already allocateds EdgeCapacity
    are kept into a set in the AnabaticEngine (key is (direction,interval)).
* New: In Anabatic::Edge, capacities are stored in a shared EdgeCapacity
    object. The total capacity can be annotated (i.e. decreased).
      EdgeCapacity attribute is created during the materialize() call.
    The capacities are computed at this time.
      The incCapacity() function is renamed in reserveCapacity().
* New: In Anabatic::AnabaticEngine, added attribute _edgeCapacitiesLut
    to store the shared EdgeCapacity.
      Lookup/Creation of an EdgeCapacity is done through _createCapacity().
* Change: In Anabatic::Constants, rename Flags::IllimitedCapacity into
    Flags::InfiniteCapacity. Add Flags::NullCapacity (both for Edges).
* Change: In Anabatic::GCell, implement a by depth (for layer) getCapacity().
    This modification did expose a bug in the density calculation :
    per depth density where divided by the complete density instead of the
    density's depth. This was leading to greatly underestimated densities.
    Thoses underestimations where preventing Dijkstra and layer assignement
    to manage congestion correctly (in fact, it was acting as if there
    never was congestion).
      Also avoid a divide by zero (thus -NAN showing in densities).
* Change: In Anabatic::GCell, rename setEdgeOccupancy() into the more
    accurate forceEdgesCapacities().
      Note for Eric: only the first Edge on each side has it's capacity
    forced. What if there's more than one Edge ?
2018-02-21 00:16:50 +01:00
Jean-Paul Chaput 592c098ab2 Basic support for FreePDK 45 completed.
* New: In Commons, inspector support for std::pair<T,U>.
* New: In Hurricane::Layer, ContactLayer & ViaLayer, support for non
    square VIAs. The hole (cut) remains square, but the various metal
    extensions can now be different in X and Y. The ::getEnclosure()
    method now takes a flag EnclosureH / EnclosureV.
* New: In Hurricane::DbU, inspector support for:
         std::pair<DbU::Unit,DbU::Unit>
	 std::array<DbU::Unit,3>
     Must be defined here as DbU do not exists yet in Commons.h
* Bug: In Hurricane::Interval::getSize(), when the interval is "full span",
    do not return the difference between min and max, but directly DbU::Max.
    (the previous result was -1 !)
* New: In CRL Core Python/Technology.py, support for non square VIAs in
    the configuration files. Applied to FreePDK 45.
* New: In CRL::RoutingGauge, added a "symbolic" flag to tell if a gauge
    is for symbolic layout or not. Exported to Python.
* New: In Anabatic::AutoHorizontal::updatePosition(), differentiated
    computation for soure or target taking account of the VIA extension
    in the right segment metal (due to non-square VIAs).
* Change: In Anabatic::AutoHorizontal::_makeDogleg(), the dogleg is
    UP for HV gauges and DOWN for VH.
* New: In Anabatic::AutoSegment::_initialize(), create a cache of the
    various extension length for each layer (viaToTop, viaToBottom,
    viaToSame).
      New implementation of getExtensionCap() using the previous cached
    extension table. See updatePositions().
      New static functions to access the extension cache in the header:
    getViaTotopCap() ...
* Change: In Anabatic::AutoSegment, in various update methods, updateOrient()
    must always be called *before* updatePositions() as extensions are
    dependant on source/target.
* New: In Anabatic::AutoSegment::getEndAxes() compute the position of the
    first source and last target position (center/axes) on an *aligned*
    set of segments.
* New: In Anabatic::AutoSegment, add a new state flag SegAxisFixed to
    signal segments that can be put on only one track. Specific case
    to VH gauge for a M1 vertical terminal with a M2 vertical segment.
    The M2 is effectively bound to the M1 axis position.
* Bug: In Anabatic::NetBuilderVH::_do_xG_xM1_xM3(), in case of E/W global
    and only one RoutingPad the connexion to the RoutingPad was duplicated.
    It was valid, but totally stupid.
* Bug: In Anabatic::Session::_canonize(), for an aligned segment set,
    intersect the user constraints from all segments instead of only
    considering the canonical one.
      Issue a warning about too tight constraints only for symbolic
    gauges. It may be correct for the real ones.
* New: In Katata::DataNegociate::update(), more accurate computation
    of the perpandicular free interval. Use segment extension cap
    calculation. Create a special case for fixed axis segments allowing
    them to find alternative free interval, try under source and under
    target as they are likely to be draggable segments.
* Change: In Katana::Manipulator::relax(), use the extension cap value
    to compute the axis of the perpandicular segemnts.
* Change: In Katana::Manipulator::moveUp(), now move up the whole set
    of aligned segments instead of just the canonical one.
* Change: In Katana::NegociateWindow::loadRoutingPads(), more accurate
    TrackMarkers insertions for fixed terminals.
* New: In Katana::RoutingEvent::Key::Compare::operator(), segments with
    fixed axis are processed prior to any others.
* New: In Katana::RoutingEventLoop, store segment pointers instead of
    ids to generate more accurate error messages.
* Change: In Katana::RoutingPlane::create(), perform local track
    assignment only for HV gauges.
* Change: In Katana::SegmentFsm::_slackenLocal(), add a "dragMinimize"
    step in the automaton. Mutliple states transitions can occurs in
    a row if an action fails.
* New: In Katana::Session::_toIntervalAxis(), normalize interval
    bounds so they are on track positions (by shrinking the interval).
* Bug: In Katana::TrackMarker CTOR, the weigh computation was wrong.
2018-02-17 20:27:38 +01:00
EricLaoGitHub 0fba4695b8 Correction de la position des GContacts
*BUG: Ajouts méthodes de correction de position de GContacts.
2018-02-05 15:41:42 +01:00
Jean-Paul Chaput 7bcf47212b Improved management of AutoContactTerminal for VH gauges (real ones).
* New: In Anabatic & Katana, add the new "drag" feature.
    With VH gauges used by real technologies (M1-H, M2-V, M3-H) a new
    routing configuration that was not efficiently handled did appear.
      While the preferred routing direction for metal1 is officially
    horizontal, due to the way the standard cell must be designed,
    their metal1 terminals are still verticals (or punctuals).
      Thus, when connecting to them, we face the case where the metal1
    terminal (RoutingPad) is vertical *and* the metal2 wire is also
    vertical. With that setup, the position of the AutoContactTerminal
    via12 cannot be deduced, it may range all the way over the
    metal1 RoutingPad. What may define it's position is the metal3 the
    metal2 finally connects to. That, is, when we have one horizontal
    (the metal3) and one vertical (the metal1 RoutingPad).
      The intermediate wire of metal2 can be kept to a minimum size
    by "dragging" the via12 close to the via23 when the metal3 wire is
    moved.
* New: In Anabatic & Katana, problem of closely vertically aligneds
    RoutingPads in metal1 is managed first in PreProcess by restricting
    the span of the connecteds metal3 and in _makeDogleg also by restricting
    the span even more tightly (to the RoutingPad itself).
* New: In Anabatic::AutoContactTerminal, add the "drag" support.
    Automatically check if the connecting segment is in the same
    direction as the RoutingPad, if so, sets the "SegDrag" flag.
      The dragging state can be known with the "::canDrag()" predicate.
* New: In Anabatic::AutoHorizontal, add the "drag" support.
    The drag state can be known with the "::isDrag()" predicate.
      In "::_makeDogleg()", when making a dogleg on a dragable segment
    pass the drag state correctly and restrict the perpandicular span
    of the perpandicular to the RoutingPad (though segment user constraints).
    If we make a dogleg on the metal2 is it likely than we cannot go
    straigth out vertically from the RoutingPad, so the new perpandicular
    *is* restricted to the RoutingPad span.
      Idem for AutoVertical.
* New: In Katana::Manipulator, add method "::dragMinimize()" which find a
    hole where to minimize a draggable segment. We finally did not use it,
    but keep it for potential further use.
* New: In Katana::PreProcess, adds a "protectAlignedaccesses()" local
    function to check for vertically aligned metal1 RoutingPads, in that
    case setup user constraints on the metal3 segments so they cannot
    completly cover the other RoutingPad with metal2.
      We also keep a "metal2protect()" function that create a fixed segment
    to lock/protect a RoutingPad. Not used for now.
* New: In Katana::Session, add a RoutingPad locking event mechanism.
    This allows us to request the creation of a locking (fixed segment)
    over a draggable segment. Not used for now.
      Lock events are processeds before all others as they create new
    TrackElements.
* New: In Katana::Track, "::getNextFree()" and "::getPreviousFree()"
    method to find the nearest free interval in a Track after/before a
    position.
* Bug: In Anabatic::AutoHorizontal::getConstraints(), merge with user
    constraints *only* if it's not an empty interval (as we use min/max
    functions). Idem for AutoVertical.
* Bug: In AutoSegments_OnContacts::Locator::isValid(), the boolean test
    must be inverted. Seems it never worked, but we never used it until
    now...
2018-01-25 11:58:04 +01:00
Jean-Paul Chaput 19bdba0fcb Working aspect ratio and feed cell loading in Etesian.
* Bug: In Etesian::setDefaultAb(), the abutment box was miscalculated,
    it was always square.
* Bug: In Etesian::_postCreate(), improper loading of filler cells.
    Now we first try to find in memory (DataBase::getCell()) and if
    not found try to use the AllianceFramework loader.
      This is not a clean strategy. We should have something more
    clear.
2018-01-10 17:46:11 +01:00
Jean-Paul Chaput ba3ddafdf5 Adjustements for analog routing.
* Change: In Anabatic::GCell::doGrid(), remove the "3 slice height"
    limit (for small digital analog blocs).
* Bug: In Anabatic::NetBuilder::setStartHook(), perform a check for
    a RoutingPad still on a Plug. Diplay an error instead of crashing.
* Bug: In CRL::RoutingLayerGauge::getTrackIndex(), the upper bound
    of the track interval must be included instead of excluded.
* New: In Hurricane::Cell, add a StayOnPlugs flags for flattenNets().
    To keep the RoutingPad occurrences on Plug instead of selecting
    physical components.
* New: In Isobar::PyNet, add setAutomatic() and isAutomatic() to the
    interface.
* Bug: In Katana::protectRoutingPads(), do not create protections on
    PinOnly layers (mostly metal1).
2018-01-10 12:45:00 +01:00
Jean-Paul Chaput 95aba574a5 Happy New Year 2018 ! Update license years... 2018-01-06 17:55:44 +01:00
Jean-Paul Chaput 757451b324 Upgrade of Katana for support of real technologies.
* Bug: In Katana::PreProcess::protectCagedTerminals(), the contacts of
    the fixed segment must be fixed too.
* Change: In Katana::RoutingPlane constructor, more accurate computation
    of the extensionCap (for real technologies).
* Bug: In Katana::DataNegociate::update(), the perpandicular free
    interval must be shrunk of the extensionCap of the perpandicular
    layer. This problem did show with metal1 "half-offgrid" terminals.
* Change: In Katana::runGlobalRouter(), increase the number of ripup
    passes to ten. Display the overloaded edges and the related nets.
2018-01-06 17:08:38 +01:00
Jean-Paul Chaput 9b2648241d In Anabatic/Katana, add support for VH gauges (real technos).
* Change: In Anabatic::AutoContactTerminal::getNativeConstraintBox(),
    when the anchor is a RoutingPad (which must be always the case),
    perform the true computation of it's position based on the
    segment occurrence. It is a important change, previously the
    area was in fact the "center line" of the connector while now
    it is really an area (mandatory for "half-offgrid" terminals of
    real technologies).
      The change is not complete yet, the area should be shrinked
    by the half size of a VIA, because the area applies to the center
    coordinate of the VIA (to be done quickly).
* Bug: In Anabatic::AutoContactTurn::updateTopology(), when a dogleg
    is created (restore connexity after a layer change) the layer of
    the VIA, based on the segments it connects to must be re-computed
    *after* the dogleg has been made.
* Change: In all files of Anabatic, when comparing two layers, no longer
    use the Layer pointer itself, but the layer mask. This allow a
    transparent management of both real and symbolic layers (which
    do share the same mask). Real metal layers (not VIAs) will be
    BasicLayer and symbolic metal layers will be RegularLayer.
* New: Anabatic::Configuration::selectRpComponent(), select the best
    RoutingPad component for metal1 terminals. Look for the metal1
    component with the biggest accessibility on-grid.
      RoutingPad using other metals are left untoucheds.
* New: New function Anabatic::Vertex::getNeighbor(Edge*) to get the
    neighbor Vertex through an Edge*. This method allows to write
    clearer code as we no longer need to access the neighbor through
    the underlying GCell.
      Also add proxies for GCell methods in Vertex.
* Bug: In Anabatic::Dijkstra::_toSources(), in the ripup stage, when
    a component with multiples vertexes is reached *and* two of it's
    vertexes are reached *at the same time* (one from which we backtrack
    and one still in the queue) extraneous edges may be created by
    _materialize(). Case occurs on snx/c35b4, "abc_5360_n903_1".
      To solve this, Dijkstra::_toSource() is modificated, the "from"
    edges of the newly reacheds vertexes are reset to NULL, *except*
    for the one we will be backtracking from. That is, the one given
    in the source argument.
* Change: In Anabatic::NetBuilder class, put the various Hooks and
    RoutingPad sorting functions as class ones.
* Bug: In AutoSegment::setLayer(), raise the SegInvalidatedFayer flag.
    This unset flag was causing AutoContactTurn::updateTopology()
    to not work as expected and making gaps, this was the cause of
    the last remaining warnings about layer connexity.
2018-01-06 16:55:53 +01:00
Jean-Paul Chaput 3d0431b238 In CRL, update real conf. files. Smarter management of pin in LEF parser.
* Change: In CRL Core, etc/, update the configuration files of real
    technologies. Mostly for FreePDK 45. This work is also done for
    AMS c35b4 (350nm) but in a private (SoC) git repository.
      Added a new parameter 'lefImport.minTerminalwidth' for the
    minimum size (width) of a metal1 terminal in standard cells.
      Corrected bug of the minimum trace level which must be
    initialized to a great value and *not* zero;
* Change: In CRL Core, BlifParser, detect when there is no tie low
    or tie high defined, issue an error (connexion left open) but
    continue.
* New: In CRL::RoutingLayerGauge, new overlad of getTrackPosition()
    with the parameter set of getTrackIndex(). Used to know if a
    terminal is on-grid or not.
* New: In CRL::LefImport, smarter management of metal1 pins. Adds a
    _pinPostProcess() function to select the external components
    among the various shapes. If the gauge is VH, all the pin rectangles
    are translateds into vertical segments (even if the metal1 gauge
    says the tracks are horizontals).
      The _pinPostProcess() function adds as external components of
    a net, only the segments of a sufficent width as given in
    'lefImport.minTerminalWidth' and that are on-grid.
2018-01-06 16:18:33 +01:00
Jean-Paul Chaput 3e115eb056 In Etesian::AddFeed, do nothing if no feed of a suitable width is found. 2018-01-06 15:15:35 +01:00
Jean-Paul Chaput 864b031b6a Disable backtrace generation in Hurricane::Error constructor.
* Change: In Hurricane::Backtrace constructor, add a boolean parameter
    to enable/disable the actual backtrace generation.
* Change: In Hurricane::Error constructor, disable by default the
    backtrace generation. The backtrace is useful when the Error is
    thrown, and the program therefore stopped. But in many case we
    just issue the error message on the console and try to continue.
    But if the backtrace is enabled, it terribly slow down the
    program.
      Have to think about an clean way to re-enable the trace only
    when the exception is thrown.
2018-01-06 15:13:20 +01:00
Jean-Paul Chaput 24d8fe5957 Cleaner support for real technologies (Hurricane, CRL Core configuration).
* Change: In Hurricane::Technology, in all the layer connexity methods
    (getLayers(), getMetalAbove(), getCutAbove(), getViaBetween(), ...)
    the "useWorking" parameter is replaced by a more accurate "useSymbolic".
      BEHAVIOR CHANGE: formerly, if a symbolic layer was requested, and
    none was found, NULL was returned. Now, if the symbolic layer is not
    found, we try to return the associated real one (same layer mask,
    but not flagged as symbolic, and usually with a lowercase name).
      All thoses changes have been propagated to Python bindings.
* Change: In Hurricane::BasicLayer and derived classes, rename the
    "isWorking" attribute into "isSymbolic" (to match the technology
    renaming).
* Change: In Hurricane::Cell::flattenNets(), ignore power, ground and
    blockage nets for the flatten.
* Change: In CRL Core, in coriolisInit.py and Technology.py helpers,
    rename the tables describing the technology as follow:
      - symbolicLayersTable --> compositeLayersTable
      - workingLayersTable  --> symbolicLayersTable
      - symbolicRulesTable  --> layersExtensionsTable
    This is to give the table names a more clearer semantic after
    merging real technologies configurations (testbench AMS c35b4).
      In particular, we need to define a composite layer for the
    real VIAs, and not only the symbolic ones. And with correct
    enclosures expressed in real dimensions (microns).
2017-12-27 13:13:29 +01:00
Jean-Paul Chaput 24d5e9f172 The min debug level has to be high (10000) and not zero.
* Bug: In Hurricane the ::tstream class must be initialized with a
    minLevel of 10000 instead of zero, as the minLevel go *towards*
    zero as the debug slice [min:max[ is expanded by DebugSession.
      This default value must be repeated in the CRL::System CTOR
    and in the coriolis2/etc/commons/misc.conf.
* Bug: In Hurricane::IntrusiveSet, uses "tsetw(n)" dedicated cdebug
    stream manipulator instead of the STL one.
2017-12-21 17:29:29 +01:00
Jean-Paul Chaput a75c77626c More meaningful names in Anabatic::NetBuilder. Use of isTwoMetals(). 2017-12-19 00:28:38 +01:00
Jean-Paul Chaput f87bcf717c Complete the modularization of the detail routing converter.
* New: In Anabatic::NetBuilder, set all the attributes as private and
    create accessors and mutators.
      Finish virtualising all GCell build methods and transfer them
    into the NetBuilderHV class.
      Build methods now return a boolean to tell if the GCell was
    processed or not, to allow cascading in the "big switch".
      Reorganise the "big switch" in separate sections only partially
    cascading.
      Truly fuse the *big switch* for channel routing and over-the-cells.
      Create a new method "_do_globalSegment()" to delagate the
    drawing of global segments between two GCell to the derived classes.
2017-12-18 18:15:14 +01:00
Jean-Paul Chaput e17a50ca0b Suppress all static attributes & methods from Anabatic::NetBuilder. 2017-12-17 12:51:04 +01:00
Jean-Paul Chaput 4c57b0651a Modularize the global to detail routing converter.
* New: In Anabatic, rename GCellTopology to NetBuilder, expose  the class
    (no longer in a local namespace).
      NetBuilder become a base class performing the walkthrough the Net
    tree. Derived class are tasked to build routing for specific gauge.
      NetBuilderHV is created to manage all gauge with metal2 horizontal
    and metal3 vertical.
      In our terminolgy we consider that the first routing metal is
    metal2. Metal1 is used inside the standard cells.
2017-12-17 00:13:19 +01:00
Jean-Paul Chaput 21ec6fdbad Correct the doxygen CSS to be compliant with 1.8.13+. 2017-12-03 03:19:10 +01:00
Jean-Paul Chaput 3e1a7ec591 Updating the documentation of the startup procedure. 2017-12-02 15:51:21 +01:00
Jean-Paul Chaput 2b9c929f80 Compliance with cmake 3.0 (Debian 9.2). Corrects all warnings. 2017-12-02 14:30:05 +01:00
Jean-Paul Chaput 89dfc2179c Compliance with c++11 and clang 3.8.1 (Debian 9.2). 2017-12-02 14:25:03 +01:00
Jean-Paul Chaput 51d5313801 Added C++ & Python tutorial code." 2017-12-01 14:17:47 +01:00
Jean-Paul Chaput 62a433ad3c In CRL Core, added helpers.overload() to modificate Python tuples. 2017-11-29 17:06:24 +01:00
Jean-Paul Chaput e89eae6272 Bug, in FindLEFDEF.cmake, look for "libdef.so" and not ".a". 2017-11-27 14:16:10 +01:00
Jean-Paul Chaput e51ff95337 Support for non-square routing pitch. Allow loading of "foreign" cells.
* New: In CRL Core, AllianceFramework::getCell(), adds a new Catalog::State
    flags to request the loading of a "foreign" cell. That is, a Cell which
    is *not* in the Alliance libraries, but in *any* library starting from
    the root library. This is a temporary hack to allow the Blif parser to
    run.
* New: In CRL Core, RoutingGauge::getHorizontalGauge() and
    RoutingGauge::getVerticalGauge() to avoid relying on either metal names
    or depth to know the vertical and horizontal default routing
    informations. They return the metal layers gauges *closests* to the
    substrate which are likely to have the lesser pitch.
* New: In CRL Core, BlifParser, new configuration parameters:
    "etesian.cell.zero" & "etesian.cell.one" to figure out what are the
    tielow and tiehigh cells (instead of having the ones from sxlib
    hardwired).
* New: In Etesian, add support for non-square routing pitchs, that is,
    the lowest vertical and horizontal pitches are not equal. Needs to
    work with two pitches (H & V) instead of one.
      The Configuration associated class now also provides the
    RoutingGauge (not only the CellGauge).
      Use a new Configuration setting "etesian.feedNames" to set up
    the names of the filler cells. This a string of comma separated
    cell names.
* New: In Anabatic, Session::_getNearestGridPoint(), use the new
    non-square grid scheme.
2017-11-26 20:31:38 +01:00
Jean-Paul Chaput 0f74ff7029 In FindLEFDEF.cmake, do not look for C libraries. 2017-11-26 20:02:54 +01:00
Jean-Paul Chaput 3b093bf129 In Hurricane, make image snaphot great again. 2017-11-18 12:14:56 +01:00
Jean-Paul Chaput a8322252ce In Etesian, issue an error message in case of unplaced macro-block.
In Etesian, issue an error message in case of unplaced macro-block.
2017-11-18 12:13:16 +01:00
Jean-Paul Chaput 20eadc85f3 Bug: LEF/DEF includes in the wrong place. 2017-11-17 15:32:30 +01:00
Jean-Paul Chaput ef63f5f93d Update documentation for new technology scheme. 2017-11-17 12:04:33 +01:00
Jean-Paul Chaput 2b3b847162 New LEF importer for real technologies.
* New: In CRL Core, added LEF importer for real technologies. This is
    still a work in progress. Exported in Python interface.
* Bug: In CRL Core, CellGauge::getRecord() correctly display DbU
    attributes.
* Change: In Unicorn, mofificate ImportCell and ImportCellDialog to
    support the LEF importer. Add a template layer so we can work with
    loaders returning Cell* or Library*.
* Change: In Unicorn::UnicornGui::getCellFromDb(), in addition to the
    Alliance loader, uses the DataBase::getCell() too (for Cells that
    are *not* in Alliance).
2017-11-17 11:48:20 +01:00
Jean-Paul Chaput 51b3a11739 In Kite & Katana, segments may have been moved outside terminals.
* Bug: In Kite::NegociateWidow and Katana::NegociateWindow, when creating
    the TrackSegment from the AutoSegment, we put it on the nearest track
    from its current position. But it may happens that the nearest track
    is outside the terminal constraint interval (in the case of "nsxlib").
    Add the terminal constraint interval check.
      This was not affecting the routing result because the segment was
    put inside the right interval afterwards. It was only generating
    disgraceful transient error messages...
2017-11-17 11:17:21 +01:00
Jean-Paul Chaput bc1c7838d1 Reorganisation of technology configuration files.
* Change: In CRL Core, in coriolis2/etc the file an directory structure
    describing the technonolies is modified.
      Before, one technology was split in two: the symbolic part that
    may be shared across multiple real technology and the real technology
    itself. To configure this we needed in ".coriolis2/techno.py" two
    variables:
      * symbolicTechnology.
      * realTechnology.
      After, we duplicate the symbolic technology in each real ones, so
    to configure we only have to refer to one technology with the
    variable:
      * technology.
      Pure sympolic technologies are still availables, associated with
    a dummy real one.
      We provides:
      * 180/scn6m_deep_09  for MOSIS 180nm
      * 45/freepdk_45      for FreePDK 45nm (work in progress).
      * symbolic/cmos      for classical Alliance symbolic.
* Change: In CRL Core python/helpers, SymbolicTechnology.py and
    RealTechnology.py are now grouped under Technology.py.
2017-11-17 11:10:32 +01:00
Jean-Paul Chaput bed79c0156 New DataBase::getCell() and bug in Technology::getNthMetal().
* New: Hurricane::DataBase::getCell() method to search a cell through
    all the libraries of *all* the frameworks, not just Alliance.
    Also exported in Python interface.
* Bug: In Technology::getNthMetal() the function was not returning the
    right metal, there was an offset of one. And when the offset was
    0, no metal was even returned. Same fix goes for getNthCut().
      The fault was in Mask<>::nthbit().
* Change: In Hurricane::CellWidget, the initial window size is too tiny.
    Increase the size from 250 to 500 pixels.
2017-11-17 10:54:19 +01:00
Jean-Paul Chaput 4e8ac63408 In CRL Core Python helpers, new showPythonTrace().
* New: In CRL Core Python helpers, add a "showPythonTrace()" function to
    custom display the Python stack trace in case of exception. It ha
    been made to look like a gdb trace.
* In Unicorn, cgt.py, use showPythonTrace().
2017-11-03 15:41:29 +01:00
Jean-Paul Chaput 98061ba1a3 Merge branch 'devel_anabatic' of ssh://bop-t/users/largo2/git/coriolis into devel_anabatic 2017-11-03 00:07:49 +01:00
Jean-Paul Chaput 141cb6e7c2 In Occurrence_Contains(), accept everything when _instance is NULL.
* Bug: In Hurricane::Occurrence_Contains(), when the Instance to match
    is set to NULL, that means we have to accept *all* instances instead
    of rejecting them all. This bug was making the Cell::flattenedNets()
    to do nothing in digital mode.
2017-11-03 00:06:06 +01:00
EricLaoGitHub 7214f5343e Minor bug fixed, introduced by rails.
in Dijkstra:
   - NULL object verification added
in GCell:
   - NULL object verification added
2017-10-31 17:45:35 +01:00
Jean-Paul Chaput de02cf5685 In stratus.buildModel(), do not always save Logical AND Physical.
* Bug: In stratus.buildModel(), the physical view was always saved, even
    only the logical one was created. Also add the ability to run the
    simulator.
2017-10-30 15:41:26 +01:00
Jean-Paul Chaput c12a50b64b Integrate LEF/DEF 5.8 into the tree (Apache 2.0 licensing)
* New: As, starting from version 5.8, LEF/DEF parser/drivers are
    availables under Apache 2.0 license, integrate them inside the
    project. Rewrite the Makefiles into CMakeLists.txt, build only
    the C++ version. Create an entry for the LEF/DEF doc in the
    documentation.
2017-10-30 15:38:29 +01:00
Jean-Paul Chaput 4d6b06d368 Update documentation to build on Debian 9.2 (stretch).
* Change: In documentation/CMakeLists.txt, for add_custom_targets(),
    add_dependencies() no longer allow to give files (only others
    *target* in the sense of cmake). We must use the DEPENDS option
    of add_custom_target().
* Change: In documentation/UsersGuide, it seems that docutils no longer
    handle correctly '$' and/or '_' in verbatim in the LaTeX backend.
    (i.e. they are *not* escaped, resulting in math mode errors).
    Remove those characters as we can use others...
* Commit a snaphot of the current documentation.
2017-10-30 15:33:37 +01:00
Jean-Paul Chaput e4575cf8c2 Merge branch 'devel_anabatic' of ssh://bop-t/users/largo2/git/coriolis into devel_anabatic 2017-10-27 10:13:33 +02:00
Jean-Paul Chaput 0498ade143 In stratus.py, buildModel was always saving logical & physical. 2017-10-27 10:12:23 +02:00
EricLaoGitHub fac6076353 Merge branch 'devel_anabatic' of ssh://bop.soc.lip6.fr/users/largo2/git/coriolis into devel_anabatic
Conflicts:
	anabatic/src/Dijkstra.cpp
	anabatic/src/Edge.cpp
2017-09-15 16:06:15 +02:00
EricLaoGitHub fccebc10de Minor bug fixed
in Dijkstra.cpp and GCell.cpp:
   - Minor debug correction

in PyLayer.cpp/.h:
   - Python interface added for different kind of layer.
2017-08-25 15:39:18 +02:00
Jean-Paul Chaput 9872896538 Merge branch 'devel_anabatic' of ssh://bop-t/users/largo2/git/coriolis into devel_anabatic 2017-08-19 00:02:11 +02:00
Jean-Paul Chaput eae5d6bf83 Added support for 2-Metal block routing in Anabatic & Katana.
* New: In AnabaticEngine::invalidateRoutingPads() this method is a temporary
    workaround for a Hurricane problems. When an instance is moved, the
    RoutingPads that use it must be moved accordingly, but they are not
    invalidated so they stay in the wrong QuadTree.
      New method ::_resizeMatrix() to be called when the associated Cell
    is resized.
* Bug: In AutoHorizontal::getConstraints() and AutoVertical::getConstraints(),
    the *target* constraints where never merged.
* Change: In AutoHorizontal::getCells() and AutoVertical::getGCells(),
    now return a boolean to tell if it was ok (must not encounter a NULL
    GCell while progessing from source to target).
* New: In Anabatic::Configuration and Anabatic:Session, create new methods:
     - getDHorizontalLayer()
     - getDhorizontalDepth()
     - getDHorizontalWidth()
     - getDHorizontalPitch()
     And so on for Vertical and Contact.
       They supply depth-independant informations about the H/V layers to
     build the initial detailed routing.
        The AutoSegment::create() methods have been modificated accordingly.
* New: In Anabatic::GCell, add two new types "StdCellRow" and "ChannelRow"
    for implementing 2-Metal blocks.
      Rename the GCell::setXY() method in GCell::setSouthWestCorner(),
    move the contents of GCell::updateContactsPosition() into it and
    suppress it.
      WARNING: In case of a GCell shrink this may cause problems. But for
    now we only expand...
      New method GCell::getNetCount() to count the number of Net going
    though the GCell.
* Change: In Anabatic::Edge, add specific support for capacity of 2-Metal
    routing channels.
* Change: In Anabatic::Dijsktra various methods, replace the "gcell->isMatrix()"
    calls by "not gcell->isAnalog()". Add more check so that the methods
    pertaining to the analog routing (GRData) are not called in digital
    mode.
* New: In Anabatic::Dijkstra::materialize(), add support for 2-Metal specific
    cases. That is, always break in case of vertical pass-through or
    U-turn. The global routing must always be broken in H-Channel.
* New: In Anabatic::GCell & Anabatic::Edge, make use of the Session mechanism
    to ensure the revalidation. The "::revalidate()" method is then moved
    as "::materialize()" (overload of Go) and "::_invalidate()" becomes
    "::invalidate()"
* Change: In LoadGlobalRouting, cosmetic rename of SortHkByX in SortHookByX.
* New: In GCellTopology, added support for building 2-Metal topologies.
    * ForkStack is now an object attribute as many methods do need it.
    * To push segments/hook on the stack, a new method "push()" is
      available. Perform NULL and fromHook checking. Can also setup
      _southWestContact or _northEastContact if it is the "from" edge.
    * N/S/E/W edges are now vector as in digital channel mode there
      can be more than one.
    * Added build topological build methods:
      - doRp_2m_Access() RoutingPad stem access.
      - _do_2m_1G_1M1() North or south access.
      - _do_2m_2G_1M1() North AND south access.
      - _do_2m_xG() H-Channel routing.
* New: In Anabatic::Matrix, new ::resize() function, as Cell can be resizeds.
* New: In Anabatic::Vertex, new static method ::getValueString() for a
    friendly text rendering.
* New: In Katana::DigitalDistance, support for channel routing.
* Change: In KatanaEngine::digitalSetup() and KatanaEngine::runGlobalrouter(),
    for channel routing, calls to setupPowerRails() and
    protectRoutingPads() must be called after the core block has
    been fully dimensionned.
      ::runGlobalrouter() contains the code tasked with the grid creation
    and channel sizing.
* New: In KatanaEngine: Added support for core block, for 2-Metal routing.
    May be expanded for over-the-cell routing in the future.
      Added methods :
      - isDigitalMode()
      - isAnalogMode()
      - isMixedMode()
      - isChannelMode()
      - getBlock() / addBlock()
      - setupChannelMode()
      - createChannel()
* New: In Katana, new class Block to manage core blocks and perform
    channel routing.
* New: In Katana::Session, new convenience method "isOpen()".
2017-08-18 23:56:23 +02:00
Jean-Paul Chaput 809a91c9c1 Added Routing Gauge for 2-Metal technologies only.
* New: In CRL Core, etc/cmos/kite.conf new routing gauge "sxlib-2M" for
    two metals only technologies.
* New: In CRL Core, python/helpers/kite.py, new parameter to set the
    routing gauge to be used: "kite.routingGauge" (default: "sxlib").
* Change: In CRL/AllianceFramework.cpp, forgot to put the Cell gauges
    and RoutingGauges in the object Records (Inspector).
* New: In pyCRL/PyAllianceFramework.cpp, export the setRoutingGauge()
    function.
2017-08-18 18:16:43 +02:00
Jean-Paul Chaput 2127fa916b Inspector support for map<> with default sort.
* New: In Hurricane/Common.h, added inspector support for map<> using
    the default sort mechanism (less<>).
2017-08-18 18:08:01 +02:00
EricLaoGitHub d4826b6a0d Merge branch 'devel_anabatic' of ssh://bop.soc.lip6.fr/users/largo2/git/coriolis into devel_anabatic 2017-08-07 09:53:46 +02:00
Roselyne Chotin-Avot d4f37d30dd In katana Change return type of getAxisWeight from long to DbU::Unit 2017-08-03 10:22:17 +02:00
EricLaoGitHub 37d6a02b0e Merge branch 'devel_anabatic' of ssh://bop.soc.lip6.fr/users/largo2/git/coriolis into devel_anabatic
Conflicts:
	anabatic/src/Dijkstra.cpp
2017-06-21 18:04:43 +02:00
EricLaoGitHub 06d818695f Dijkstra can handle mixedsignal wires. 2017-06-21 18:02:37 +02:00
9013 changed files with 2112363 additions and 130282 deletions

7
.gitignore vendored
View File

@ -8,9 +8,10 @@ TAGS
GTAGS GTAGS
GPATH GPATH
GRTAGS GRTAGS
dir-locals.el .dir-locals.el
.projectile .projectile
lefdef/src/lef/lef/lef.tab.h
man/ man/
rtf/ rtf/
@ -36,3 +37,7 @@ documentation/RDS/RDS.pdf
documentation/RDS/RDS.tex documentation/RDS/RDS.tex
documentation/RDS/RDS.toc documentation/RDS/RDS.toc
cumulus/src/plugins/CoreToChip_c35b4.py
cumulus/src/plugins/core2chip/c35b4.py
/result*

54
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,54 @@
linux:
image: python:3.8
# make a docker daemon available for cibuildwheel to use
services:
- name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
command: ["dockerd-entrypoint.sh"]
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
# See https://github.com/docker-library/docker/pull/166
DOCKER_TLS_CERTDIR: ""
script:
- curl -sSL https://get.docker.com/ | sh
- python -m pip install cibuildwheel==2.11.3
- cibuildwheel --output-dir wheelhouse
parallel:
matrix:
- CIBW_BUILD: [cp38-manylinux*, cp39-manylinux*, cp310-manylinux*, cp311-manylinux*]
CIBW_ARCHS_LINUX: [auto64]
artifacts:
paths:
- wheelhouse/
dist:
image: python:3.8
needs:
- job: linux
artifacts: true
except:
- merge_requests
variables:
TWINE_PASSWORD: '${CI_JOB_TOKEN}'
TWINE_USERNAME: 'gitlab-ci-token'
TWINE_REPOSITORY_URL: 'https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/pypi'
script:
- python -m pip install --upgrade build twine
- python -m twine check --strict wheelhouse/*
- python -m twine upload --verbose wheelhouse/*
#windows:
# image: mcr.microsoft.com/windows/servercore:1809
# before_script:
# - choco install python -y --version 3.8.6
# - choco install git.install -y
# - py -m pip install cibuildwheel==2.11.3
# script:
# - py -m cibuildwheel --output-dir wheelhouse --platform windows
# artifacts:
# paths:
# - wheelhouse/
# tags:
# - windows

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

28
COPYRIGHT.rst Normal file
View File

@ -0,0 +1,28 @@
=========
COPYRIGHT
=========
* The **LEF/DEF** components of Coriolis are copyrighted by: ::
Cadence Design Systems 2012-2017
And released under the Apache 2.0 license
* The **flute** component of Coriolis is copyrighted by: ::
Dr. Chris C. N. Chu 2004
Iowa State University
http://home.engineering.iastate.edu/~cnchu/
And released under it's own license (derived from BSD)
* The **Hurricane** component of Coriolis is copyrighted by: ::
Bull S.A. 2000-2021 (now ATOS)
And released under the LGPL license
* **All other components** of Coriolis are copyrighted by: ::
Sorbonne Université 2000-2021 (formerly UPMC)
And released under the GPLv2 license

35
Coriolis/__init__.py Normal file
View File

@ -0,0 +1,35 @@
#This is needed for poetry to recognise the top level module
import os
import sys
import subprocess
__version__ = "0.0.0"
#TODO not PEP302 complient -probably a big porting job
coriolis_package_dir = os.path.abspath(os.path.dirname(__file__))
os.environ["CORIOLIS_TOP"] = coriolis_package_dir
CORIOLIS_DATA = os.path.join(os.path.dirname(__file__), 'data')
CORIOLIS_BIN = os.path.join(CORIOLIS_DATA,"bin")
def _program(name, args):
return subprocess.call([os.path.join(CORIOLIS_BIN, name)] + args, close_fds=False)
def blif2vst():
raise SystemExit(_program("blif2vst.py", sys.argv[1:]))
def cx2y():
raise SystemExit(_program("cx2y", sys.argv[1:]))
def cyclop():
raise SystemExit(_program("cyclop", sys.argv[1:]))
def tutorial():
raise SystemExit(_program("tutorial", sys.argv[1:]))
def unittests():
raise SystemExit(_program("unittests", sys.argv[1:]))
def yosys_coriolis():
raise SystemExit(_program("yosys.py", sys.argv[1:]))

376
LICENSE.rst Normal file
View File

@ -0,0 +1,376 @@
==========================
GNU GENERAL PUBLIC LICENSE
==========================
**Version 2, June 1991**
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
========
The licenses for most software are designed to take away your freedom
to share and change it. By contrast, the GNU General Public License
is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit
to using it. (Some other Free Software Foundation software is covered
by the GNU Lesser General Public License instead.) You can apply it
to your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge
for this service if you wish), that you receive source code or can
get it if you want it, that you can change the software or use pieces
of it in new free programs; and that you know you can do these
things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software,
and (2) offer you this license which gives you legal permission to
copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on,
we want its recipients to know that what they have is not the
original, so that any problems introduced by others will not reflect
on the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making
the program proprietary. To prevent this, we have made it clear that
any patent must be licensed for everyone's free use or not licensed
at all.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
===============================================================
0. This License applies to any program or other work which contains a
notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program",
below, refers to any such program or work, and a "work based on
the Program" means either the Program or any derivative work under
copyright law: that is to say, a work containing the Program or a
portion of it, either verbatim or with modifications and/or
translated into another language. (Hereinafter, translation is
included without limitation in the term "modification".) Each
licensee is addressed as "you".
Activities other than copying, distribution and modification are
not covered by this License; they are outside its scope. The act
of running the Program is not restricted, and the output from the
Program is covered only if its contents constitute a work based on
the Program (independent of having been made by running the
Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep
intact all the notices that refer to this License and to the
absence of any warranty; and give any other recipients of the
Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange
for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all
third parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display
an announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you
provide a warranty) and that users may redistribute the program
under these conditions, and telling the user how to view a copy
of this License. (Exception: if the Program itself is
interactive but does not normally print such an announcement,
your work based on the Program is not required to print an
announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the
Program, and can be reasonably considered independent and separate
works in themselves, then this License, and its terms, do not
apply to those sections when you distribute them as separate
works. But when you distribute the same sections as part of a
whole which is a work based on the Program, the distribution of
the whole must be on the terms of this License, whose permissions
for other licensees extend to the entire whole, and thus to each
and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or
contest your rights to work written entirely by you; rather, the
intent is to exercise the right to control the distribution of
derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the
Program with the Program (or with a work based on the Program) on
a volume of a storage or distribution medium does not bring the
other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms
of Sections 1 and 2 above provided that you also do one of the
following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Sections 1 and 2 above on a medium customarily used for
software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with
such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work
for making modifications to it. For an executable work, complete
source code means all the source code for all modules it contains,
plus any associated interface definition files, plus the scripts
used to control compilation and installation of the
executable. However, as a special exception, the source code
distributed need not include anything that is normally distributed
(in either source or binary form) with the major components
(compiler, kernel, and so on) of the operating system on which the
executable runs, unless that component itself accompanies the
executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this
License. However, parties who have received copies, or rights,
from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify
or distribute the Program or its derivative works. These actions
are prohibited by law if you do not accept this
License. Therefore, by modifying or distributing the Program (or
any work based on the Program), you indicate your acceptance of
this License to do so, and all its terms and conditions for
copying, distributing or modifying the Program or works based on
it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program
subject to these terms and conditions. You may not impose any
further restrictions on the recipients' exercise of the rights
granted herein. You are not responsible for enforcing compliance
by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent
issues), conditions are imposed on you (whether by court order,
agreement or otherwise) that contradict the conditions of this
License, they do not excuse you from the conditions of this
License. If you cannot distribute so as to satisfy simultaneously
your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the
Program at all. For example, if a patent license would not permit
royalty-free redistribution of the Program by all those who
receive copies directly or indirectly through you, then the only
way you could satisfy both it and this License would be to refrain
entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable
under any particular circumstance, the balance of the section is
intended to apply and the section as a whole is intended to apply
in other circumstances.
It is not the purpose of this section to induce you to infringe
any patents or other property right claims or to contest validity
of any such claims; this section has the sole purpose of
protecting the integrity of the free software distribution system,
which is implemented by public license practices. Many people have
made generous contributions to the wide range of software
distributed through that system in reliance on consistent
application of that system; it is up to the author/donor to decide
if he or she is willing to distribute software through any other
system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed
to be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces,
the original copyright holder who places the Program under this
License may add an explicit geographical distribution limitation
excluding those countries, so that distribution is permitted only
in or among countries not thus excluded. In such case, this
License incorporates the limitation as if written in the body of
this License.
9. The Free Software Foundation may publish revised and/or new
versions of the General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies a version number of this License which applies
to it and "any later version", you have the option of following
the terms and conditions either of that version or of any later
version published by the Free Software Foundation. If the Program
does not specify a version number of this License, you may choose
any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to
the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free
status of all derivatives of our free software and of promoting
the sharing and reuse of software generally.
**NO WARRANTY**
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS
OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH
ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
===========================
How to Apply These Terms to Your New Programs
=============================================
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make
it free software which everyone can redistribute and change under
these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
one line to give the program's name and an idea of what it does.
Copyright (C) yyyy name of author
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
Also add information on how to contact you by electronic and paper
mail.
If the program is interactive, make it output a short notice like
this when it starts in an interactive mode: ::
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type
"show w". This is free software, and you are welcome to
redistribute it under certain conditions; "type show c" for
details.
The hypothetical commands ``"show w"`` and ``"show c"`` should show
the appropriate parts of the General Public License. Of course, the
commands you use may be called something other than ``"show w"`` and
``"show c"``; they could even be mouse-clicks or menu items--whatever
suits your program.
You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the
program, if necessary. Here is a sample; alter the names: ::
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision`
(which makes passes at compilers) written
by James Hacker.
signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your
program into proprietary programs. If your program is a subroutine
library, you may consider it more useful to permit linking
proprietary applications with the library. If this is what you want
to do, use the [GNU Lesser General Public
License](https://www.gnu.org/licenses/lgpl.html) instead of this
License.

View File

@ -1,15 +1,16 @@
UNAME_S = $(shell uname -s) UNAME_S = $(shell uname -s)
UNAME_R = $(shell uname -r) UNAME_R = $(shell uname -r)
DEVTOOLSET_VERSION = 7
# We must use devtoolset-2 only under RHEL6 & clones. # We must use devtoolset only under RHEL6 & clones.
DEVTOOLSET_OPTION = DEVTOOLSET_OPTION =
ifeq ($(UNAME_S),Linux) ifeq ($(UNAME_S),Linux)
ifneq ($(findstring .el6.,$(UNAME_R)),) ifneq ($(findstring .el7.,$(UNAME_R)),)
DEVTOOLSET_OPTION = --devtoolset-2 DEVTOOLSET_OPTION = --devtoolset=$(DEVTOOLSET_VERSION)
endif endif
ifneq ($(findstring .slsoc6.,$(UNAME_R)),) ifneq ($(findstring .slsoc6.,$(UNAME_R)),)
DEVTOOLSET_OPTION = --devtoolset-2 DEVTOOLSET_OPTION = --devtoolset=$(DEVTOOLSET_VERSION)
endif endif
endif endif
@ -56,7 +57,6 @@ check_dir:
install: check_dir install: check_dir
@./bootstrap/ccb.py $(DEVTOOLSET_OPTION) --project=support --project=coriolis --make="$(SMP_FLAGS) install" @./bootstrap/ccb.py $(DEVTOOLSET_OPTION) --project=support --project=coriolis --make="$(SMP_FLAGS) install"
@./bootstrap/ccb.py $(DEVTOOLSET_OPTION) --project=support --project=coriolis --make="-j1 install" --doc
@echo ""; \ @echo ""; \
echo "============================================================================"; \ echo "============================================================================"; \
echo "Coriolis has been successfully built"; \ echo "Coriolis has been successfully built"; \

View File

@ -5,20 +5,19 @@
Coriolis README Coriolis README
=============== ===============
Coriolis is a free database, placement tool and routing tool for VLSI design.
Coriolis is a free database, placement tool and routing tool for VLSI designs.
Purpose Purpose
======= =======
Coriolis provides several tools to perform the layout of VLSI circuits. Its Coriolis provides several tools to perform the layout of VLSI circuits. Its
main components are the Hurricane database, the Etesian placer and the Kite main components are the Hurricane database, the Etesian placer and the Katana
router, but other tools can use the Hurricane database and the parsers router, but other tools can use the Hurricane database and the parsers
provided. provided.
The user interface <cgt> is the prefered way to use Coriolis, but all The user interface <cgt> is the prefered way to use Coriolis, but all
Coriolis tools are Python modules and thus scriptables. Coriolis tools are Python modules and thus scriptable.
Documentation Documentation
@ -26,14 +25,14 @@ Documentation
The complete documentation is available here, both in pdf & html: The complete documentation is available here, both in pdf & html:
./documentation/_build/html/index.html ./documentation/output/html
./documentation/UsersGuide/UsersGuide.pdf ./documentation/UsersGuide/UsersGuide.pdf
The documentation of the latest *stable* version is also The documentation of the latest *stable* version is also
available online. It may be quite outdated from the *devel* available online. It may be quite outdated from the *devel*
version. version.
https://soc-extras.lip6.fr/en/coriolis/coriolis2-users-guide/ https://www-soc.lip6.fr/sesi-docs/coriolis2-docs/coriolis2/en/latex/users-guide/UsersGuide.pdf
Building Coriolis Building Coriolis
@ -41,35 +40,29 @@ Building Coriolis
To build Coriolis, ensure the following prerequisites are met: To build Coriolis, ensure the following prerequisites are met:
* Python 2.7. * Python 3,
* cmake. * cmake,
* boost. * boost,
* bison & flex. * bison & flex,
* Qt 4 or 5. * Qt 4 or 5,
* libxml2. * libxml2,
* RapidJSON * RapidJSON,
* A C++11 compliant compiler. * A C++11 compliant compiler.
The build system relies on a fixed directory tree from the root The build system relies on a fixed directory tree from the root
of the user currently building it. Thus first step is to get a clone of of the user currently building it. Thus first step is to get a clone of
the repository in the right place. Proceed as follow: :: the repository in the right place. Proceed as follow: ::
ego@home:~$ mkdir -p ~/coriolis-2.x/src/support ego@home:~$ mkdir -p ~/coriolis-2.x/src/
ego@home:~$ cd ~/coriolis-2.x/src/support
ego@home:~$ git clone http://github.com/miloyip/rapidjson
ego@home:~$ git checkout ec322005072076ef53984462fb4a1075c27c7dfd
ego@home:~$ cd ~/coriolis-2.x/src ego@home:~$ cd ~/coriolis-2.x/src
ego@home:src$ git clone https://www-soc.lip6.fr/git/coriolis.git ego@home:src$ git clone https://gitlab.lip6.fr/vlsi-eda/coriolis.git
ego@home:src$ cd coriolis ego@home:src$ cd coriolis
If you want to use the *devel* branch: ::
ego@home:coriolis$ git checkout devel
Then, build the tool: :: Then, build the tool: ::
ego@home:coriolis$ make install ego@home:coriolis$ make install
If you encounter issues, please consult SUPPORT.rst for tips.
Coriolis gets installed at the root of the following tree: :: Coriolis gets installed at the root of the following tree: ::
~/coriolis-2.x/<OS>.<DISTRIB>/Release.Shared/install/ ~/coriolis-2.x/<OS>.<DISTRIB>/Release.Shared/install/
@ -85,11 +78,11 @@ The Coriolis main interface can be launched with the command: ::
ego@home:~: ~/coriolis-2.x/<OS>.<DISTRIB>/Release.Shared/install/bin/coriolis ego@home:~: ~/coriolis-2.x/<OS>.<DISTRIB>/Release.Shared/install/bin/coriolis
The ``coriolis`` script is tasked to guess it's location and setup appropriatly The ``coriolis`` script detects its location and setups the UNIX
the UNIX environment, then lauch ``cgt`` (or *any* command, with the environment appropriately, then lauches ``cgt`` (or *any* command, with the
``--run=<COMMAND>`` option). ``--run=<COMMAND>`` option).
Conversely, you can setup the current shell environement for Coriolis by Conversely, you can setup the current shell environment for Coriolis by
using the helper ``coriolisEnv.py``, then run any Coriolis tool: :: using the helper ``coriolisEnv.py``, then run any Coriolis tool: ::
ego@home:~$ eval `~/coriolis-2.x/src/coriolis/bootstrap/coriolisEnv.py` ego@home:~$ eval `~/coriolis-2.x/src/coriolis/bootstrap/coriolisEnv.py`

27
SUPPORT.rst Normal file
View File

@ -0,0 +1,27 @@
=================
Help and tooltips
=================
Compilation errors
==================
This section is here to help you with the build process, and help you fix dependency issues or workaround compilation errors if it happens on your distribution.
RapidJson
---------
Some versions of RapidJson do not build with newer compilers, while others build only with newer ones.
The version provided in README.rst should work for older compilers. Otherwise, consider pulling a newer version.
Qt5
---
To use Qt5, you should add the --qt5 option to the ccb.py line in Makefile.
On some distributions, you may need to replace the lines in bootstrap/cmake_modules/FindBootstrap.cmake from ::
find_package(Qt5Core REQUIRED)
to ::
find_package(Qt5 COMPONENTS REQUIRED Core)

44
Seabreeze/CMakeLists.txt Normal file
View File

@ -0,0 +1,44 @@
# -*- explicit-buffer-name: "CMakeLists.txt<Seabreeze>" -*-
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
project(SEABREEZE)
option(BUILD_DOC "Build the documentation (doxygen)" OFF)
option(CHECK_DATABASE "Run database in full check mode (very slow)" OFF)
option(USE_LIBBFD "Link with BFD libraries to print stack traces" OFF)
cmake_minimum_required(VERSION 3.16)
set(ignoreVariables "${BUILD_DOC} ${CMAKE_INSTALL_DIR}")
list(INSERT CMAKE_MODULE_PATH 0 "${DESTDIR}$ENV{CORIOLIS_TOP}/share/cmake/Modules/")
find_package(Bootstrap REQUIRED)
setup_project_paths(CORIOLIS)
set_cmake_policies()
setup_boost(program_options)
setup_qt()
setup_python()
find_package(Libexecinfo REQUIRED)
find_package(PythonSitePackages REQUIRED)
find_package(LEFDEF REQUIRED)
find_package(FLUTE REQUIRED)
find_package(HURRICANE REQUIRED)
find_package(CORIOLIS REQUIRED)
#find_package(ANABATIC REQUIRED)
#find_package(ETESIAN REQUIRED)
#find_package(COLOQUINTE REQUIRED)
find_package(Doxygen)
if(CHECK_DATABASE)
add_definitions(-DCHECK_DATABASE)
endif(CHECK_DATABASE)
if(CHECK_DETERMINISM)
add_definitions(-DCHECK_DETERMINISM)
endif(CHECK_DETERMINISM)
add_subdirectory(src)
#add_subdirectory(test)
add_subdirectory(cmake_modules)
#add_subdirectory(doc)

27
Seabreeze/README.txt Normal file
View File

@ -0,0 +1,27 @@
Fonctions dans Seabreeze.cpp :
---------------------------------------------------------------------
contFromNet ( Net* net )
{
ajouter les contacts dans net au set<Contact*> _conts;
}
buildTree ( RoutingPad* rp )
{
Construire l'arbre de rp, ça veux dire le contact trouvé dans rp sera la racine de l'arbre
}
build_from_Node ( Node* source, Segment* seg )
{
Après avoir crée le premier node / la racine dans buildTree, on va l'utiliser pour construire l'arbre.
}
build_branch ( double* R, double* C, Contact* contact )
{
Parcourir la branche et trouver le Node suivant de l'arbre
}
Set_RC ( double* R, double* C, Contact* ct, Segment* sm )
{
Calculer le RC de la branche ct-sm et ajouter la valeur dans R et C
}

View File

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

View File

@ -0,0 +1,38 @@
# - Find the Seabreeze includes and libraries.
# The following variables are set if Coriolis is found. If KATABATIC is not
# found, KATABATIC_FOUND is set to false.
# KATABATIC_FOUND - True when the Coriolis include directory is found.
# KATABATIC_INCLUDE_DIR - the path to where the Coriolis include files are.
# KATABATIC_LIBRARIES - The path to where the Coriolis library files are.
SET(SEABREEZE_INCLUDE_PATH_DESCRIPTION "directory containing the Katabatic include files. E.g /usr/local/include/coriolis2 or /asim/coriolis/include/coriolis2")
SET(SEABREEZE_DIR_MESSAGE "Set the SEABREEZE_INCLUDE_DIR cmake cache entry to the ${SEABREEZE_INCLUDE_PATH_DESCRIPTION}")
# don't even bother under WIN32
IF(UNIX)
#
# Look for an installation.
#
FIND_PATH(SEABREEZE_INCLUDE_PATH NAMES katabatic/KatabaticEngine.h PATHS
# Look in other places.
${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES include/coriolis2
# Help the user find it if we cannot.
DOC "The ${SEABREEZE_INCLUDE_PATH_DESCRIPTION}"
)
FIND_LIBRARY(SEABREEZE_LIBRARY_PATH
NAMES seabreeze
PATHS ${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES lib64 lib
# Help the user find it if we cannot.
DOC "The ${SEABREEZE_INCLUDE_PATH_DESCRIPTION}"
)
SET_LIBRARIES_PATH(SEABREEZE SEABREEZE)
HURRICANE_CHECK_LIBRARIES(SEABREEZE)
ENDIF(UNIX)

View File

@ -0,0 +1,22 @@
# -*- mode: CMAKE; explicit-buffer-name: # "CMakeLists.txt<Seabreeze/doc>" -*-
set ( htmlInstallDir share/doc/coriolis2/en/html/doc/Seabreeze )
set ( latexInstallDir share/doc/coriolis2/en/latex/Seabreeze )
set ( doxExtras customHierarchy.html
closed.png
open.png
tabs.css
)
if(BUILD_DOC AND DOXYGEN_FOUND)
add_custom_target ( doc ALL
cd ${SEABREEZE_SOURCE_DIR}/doc
&& ${DOXYGEN_EXECUTABLE} doxyfile
&& cp -f ${doxExtras} html
)
endif()
install ( DIRECTORY html/ DESTINATION ${htmlInstallDir} )
install ( DIRECTORY latex/ DESTINATION ${latexInstallDir} )
install ( FILES asimbook.cls DESTINATION ${latexInstallDir} )

49
Seabreeze/doc/Node.dox Normal file
View File

@ -0,0 +1,49 @@
// -*- C++ -*-
/*! \class Node
*! \brief Node description(\b API)
*
*/
/*! \var int Node::R
* The Resistor of a point in the circuit / node in the tree.
*/
/*! \var int Node::Rt
* The Resister "total" - the value of resistor that is used
* to compute the Elmore's delay.
*/
/*! \var int Node::C
* The Capacitor of a point in the circuit / node in the tree.
*/
/*! \var Node* Node::Np
* The parent node of current node
*/
/* \var std::vector<Node*> Node::Ne
* A list of children nodes of current node
*/
/*! \var int Node::label
* The label / Id of current node
*/
/*! \var int Node::ap
* A boolean variable to determine whether the current node
* is after or before node i at where we need to compute the
* Elmore's delay.
*/
/*! \function Node::Node();
* Default constructor.
*/
/*! \function Node::~Node();
* Default destructor.
*/

102
Seabreeze/doc/Seabreeze.dox Normal file
View File

@ -0,0 +1,102 @@
// -*- C++ -*-
namespace Seabreeze {
/*! \class Elmore
* \brief Main class for computing the Elmore's delay
*/
/*! \var vector<Contact*> Elmore::_conts
* The list of Contacts contained in the considered Net
*/
/*! \var vector<Contact*> Elmore::checker
* The list of Contacts that we have treated. It serves as a checker
* of circles. If a circle exists in the Net, Elmore's delay cannot be
* computed.
*/
/*! \var Tree Elmore::_tree
* The tree necessary to run the algorithm to compute Elmore's delay
*/
/*! \function Elmore::Elmore( Net* net = NULL )
* Constructor
*/
/*! \function Elmore::~Elmore()
* Default destructor
*/
/*! \function void Elmore::contFromNet( Net* net )
* Build the list _const from net
*/
/*! \function void Elmore::buildTree( Contact* ct )
* Build the _tree with ct as the root
*/
/*! \function void Elmore::clearTree()
* Clean the _tree and the list checker
*/
/*! \function Tree* Elmore::getTree()
* \Return the _tree
*/
/*! \function int Elmore::delayElmore()
* \Return the value of Elmore's delay
*/
/*! \function void Elmore::toTree( ostream& )
* Print the _tree to an output file
*/
/*! \class ElmoreProperty
*
*/
/*! \var Name ElmorerProperty::_name
*
*/
/*! \var Elmore ElmoreProperty::_elmore
*
*/
/*! \function ElmoreProperty::ElmoreProperty( Net* )
* Constructor
*/
/*! \function ElmoreProperty* ElmoreProperty::create( Net* net )
* \Return the ElmoreProperty created from the net
*/
/*! \function Name ElmoreProperty::getName()
* \Return the name of the property
*/
/*! \class ElmoreExtension
* \brief Useful to access to functions of Elmore class without having to calling it
*/
/*! \var Net* ElmoreExtension::Nets
*
*/
/*! \function void ElmoreExtension::destroyAll()
*
*/
/*! \function void ElmoreExtension::destroy()
*
*/
/*! \function Tree ElmoreExtension::getTree( Elmore* elmore )
* \Return the _tree of elmore
*/
/*! \function void ElmoreExtension::toTree( Elmore* elmore, std::ostream& out )
* Print the _tree of elmore to the output file out
*/
}

882
Seabreeze/doc/SoC.css Normal file
View File

@ -0,0 +1,882 @@
/*
* +-----------------------------------------------------------------+
* | HTML Standart Tags |
* +-----------------------------------------------------------------+
*/
html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 {
font-size: 11pt;
/* The Open Sans font family is supplied by TexLive. */
font-family: "Roboto", "Open Sans", Verdana, sans-serif;;
}
html {
background: #dddddd;
}
body {
color: black;
background: white;
background-color: white;
background-position: top left;
background-attachment: fixed;
background-repeat: no-repeat;
margin-top: 2em;
width: 600pt;
margin-right: auto;
margin-left: auto;
padding: 30pt;
/*
margin-right: 12%;
margin-left: 12%;
*/
}
hr {
height: 1px;
border: 0;
color: #004400;
background-color: #004400;
}
h1, h2, h3, h4, h5, h6 {
/*font-family: "URW Bookman L", "Liberation Serif", sans-serif;*/
font-family: "URW Bookman L";
}
h1.header { text-align: center; }
h1 { text-align: left; }
h2, h3, h4, h5, h6 { text-align: left;
padding-top: 11pt;
}
h1, h2, h3 { /*font-family: "Liberation Serif", sans-serif; */
/*color: #09550B;*/
}
h1 { font-weight: bold; font-size: 170%; /*letter-spacing:0.2em; word-spacing:0.4em;*/ }
h2 { font-weight: bold; font-size: 140%; /*letter-spacing:0.2em; word-spacing:0.4em;*/ }
h3 { font-weight: bold; font-size: 118%; /*letter-spacing:0.2em; word-spacing:0.4em;*/ }
h4 { font-weight: bold; font-size: 100%; }
h5 { font-style: italic; font-size: 100%; }
h6 { font-variant: small-caps; font-size: 100%; }
h2.classHierarchy {
/*border: 1px none #008500;*/
border: 1px none #000000;
border-top-width: 1px;
border-top-style: dotted;
padding-top: 1em;
}
.hide {
display: none;
color: white;
}
p {
margin-top: 0.6em;
margin-bottom: 0.6em;
margin-left: 0.0em;
margin-right: 0.0em;
}
address {
text-align: right;
font-weight: bold;
font-style: italic;
font-size: 80%;
}
caption { font-weight: bold }
blockquote {
margin-left: 4em;
margin-right: 4em;
margin-top: 0.8em;
margin-bottom: 0.8em;
font-style: italic;
color: #003300;
}
blockquote p {
margin-bottom: 0;
}
blockquote address {
margin: 0;
}
table {
border-collapse: collapse;
}
dt, dd { margin-top: 0; margin-bottom: 0; }
dt { font-weight: bold; }
pre, tt, code {
/*font-family: "andale mono", monospace;*/
font-size: 100%;
white-space: pre;
}
pre {
font-size: 80%;
/*border: dashed;*/
border-width: thin;
border-color: #003300;
/*background-color: #EEEEEE;*/
background-color: #FCFCE1;
padding: 0.5em;
margin-left: 2em;
margin-right: 2em
}
/*
tt { color: green; }
*/
em { font-style: italic;
font-weight: normal; }
strong { font-weight: bold; }
span.textit { font-style: italic; }
span.textbf { font-weight: bold; }
.small { font-size: 90%; }
.white { color: #FFFFFF; }
ul.toc {
list-style: disc;
list-style: none;
}
a:link img, a:visited img { border-style: none; }
a img { color: white; }
a {
color: black;
border-bottom: 1px solid black;
text-decoration: none;
}
a:link, a:active, a:visited {
/*color: #09550B;*/
/*text-decoration: none;*/
}
a:hover, a:focus {
/*color: #FF9900; */
border-bottom: 2px solid black;
}
/*
* +-----------------------------------------------------------------+
* | Doxygen Specific Classes |
* +-----------------------------------------------------------------+
*/
/* -------------------------------------------------------------------
* Header & Footer Classes (customized top page navigation bar).
*/
h1.header {
font-size: 200%;
/*font-family: times, verdana, sans-serif;*/
}
h2.memtitle {
display: none;
}
center.header {
background-color: #CCE6CA;
}
table.header {
/*width: 100%;*/
/*background-color: #EEEEEE;*/
background-color: #CCE6CA;
}
div.header {
text-align: center;
margin: 14pt 0pt 0pt 0pt;
}
div.summary {
color: white;
background-color: black;
border: 4px solid black;
}
div.summary a {
font-size: 90%;
color: white;
padding: 2px 0px;
text-align: center;
background-color: black;
border-bottom: none;
}
table.header td {
padding: 2px 14px;
text-align: center;
font-weight: bold;
/*font-family: verdana, sans-serif;*/
font-size: 110%;
}
table.UserDefined {
border: 1px solid;
}
table.UserDefined th {
border: 1px solid;
}
table.UserDefined td {
padding: 0px 5px;
}
table.DoxUser td, table.DoxUser th {
padding: 0px 5px;
border: 0px;
}
table.DoxUser th {
background-color: #CCE6CA;
}
table.footer1, table.footer2 { width: 100%; }
td.LFooter { text-align: left; }
td.RFooter { text-align: right; }
td.CFooter { text-align: center;}
table.footer2 td.RFooter { font-weight: bold; width: 35% }
table.footer2 td.CFooter { width: 30% }
table.footer2 td.LFooter { font-weight: bold; width: 35%; /*font-family: time;*/ }
table.classHierarchy {
border-collapse: separate;
border-spacing: 5px;
font-size: 110%;
}
table.classHierarchy a {
border-style: none;
border-bottom: none;
}
table.classHierarchy tr {
border: 1px solid blue;
}
table.classHierarchy td.normal {
border: 1px solid #dddddd;
width: 140pt;
text-align: center;
font-weight: bold;
background-color: #dddddd;
}
table.classHierarchy td.virtual {
border: 1px solid black;
width: 140pt;
text-align: center;
font-weight: bold;
}
table.classHierarchy td.wnormal {
border: 1px solid #dddddd;
width: 240pt;
text-align: center;
font-weight: bold;
background-color: #dddddd;
}
table.classHierarchy td.wvirtual {
border: 1px solid black;
width: 240pt;
text-align: center;
font-weight: bold;
}
div.ah, span.ah {
font-family: Times;
font-size: 300%;
font-weight: bold;
padding: 20px;
}
div.title {
text-align: center;
font-size: 200%;
font-weight: bold;
padding: 20px;
border: 2px solid black;
}
div.center, div.image {
text-align: center;
}
/* -------------------------------------------------------------------
* Top navigation lists.
*/
span.mlabels {
font-size: 90%;
font-style: italic;
padding-left: 10pt;
margin: 10pt;
border-left: 1px solid black
}
div.contents {
padding-top: 20pt;
}
div.tabs {
border-top: 1px solid black;
}
div.tabs, div.tabs1, div.tabs2, div.tabs3, div.tabs4 {
border-left: 1px solid black;
}
ul.tablist {
/*
padding: 5pt;
background-color: red;
*/
margin: 0pt;
padding: 0pt;
border-top: none;
border-bottom: none;
border-left: none;
border-right: none;
}
ul.tablist li {
/*
margin-left: auto;
margin-right: auto;
overflow: auto;
display: inline;
background-color: yellow;
*/
font-size: 90%;
border-top: none;
border-bottom: 1px solid black;
border-left: none;
border-right: 1px solid black;
display: table-cell;
text-align: center;
padding: 2pt;
width: 5%;
}
ul.tablist li:hover {
background-color: black;
color: white;
}
ul.tablist li:hover a {
background-color: black;
color: white;
}
ul.tablist * a { border-bottom: none; }
ul.tablist * a:link img, ul.tablist * a:visited img { border-style: none; border-bottom: none; }
ul.tablist * a:link, ul.tablist * a:visited {
color: black;
text-decoration: none;
}
ul.tablist * a:hover, ul.tablist * a:focus, ul.tablist * a:active {
color: white;
text-decoration: underline;
}
div.navpath {
padding: 5pt 0pt 0pt 0pt;
}
.navpath ul {
text-align: center;
}
.navpath ul li {
display: inline;
list-style-type: none;
padding-left: 20px;
padding-right: 10px;
background-image: url('closed.png');
background-repeat: no-repeat;
background-position: left;
color: #364D7C;
}
.navpath ul li a {
border: 2px solid black;
padding-left: 10px;
padding-right: 10px;
font-weight: bold;
color: black;
}
/* -------------------------------------------------------------------
* Quick Index Class (top page navigation bar).
*/
div.qindex, div.nav {
width: 100%-4px;
/*background-color: #DADAEF;*/
/*background-color: #eeeeff;*/
background-color: #cccccc;
/*background-color: #CCE6CA;*/
border: 0px solid #003300;
text-align: center;
margin: 0px;
padding: 2px;
line-height: 140%;
}
a.qindex, a.qindex:visited, a.qindex:hover, a.qindexHL, a.el, a.elRef {
text-decoration: none;
/*font-family: Courier;*/
font-weight: normal;
/*font-size: 110%;*/
}
a.qindex, a.qindex:visited {
/*color: #09550B;*/
color: black;
border: 2px solid #cccccc;
padding: 2px 2px;
border-bottom: none;
}
a.qindex:hover {
/*background-color: #ddddff;*/
font-weight: bold;
padding: 2px 2px;
border: 2px solid black;
}
a.qindexHL, a.qindexHL:hover, a.qindexHL:visited {
background-color: #0c780c;
color: #ffffff;
border: 1px double #9295C2;
}
a.code:link, a.code:visited, a.codeRef:link, a.codeRef:visited {
text-decoration: none;
font-weight: normal;
color: #0000ff;
}
.indexkey {
background-color: #eeeeff;
border: 1px solid #b0b0b0;
padding: 2px 15px;
}
.indexkey, .indexvalue {
background-color: #eeeeff;
border: 1px solid #b0b0b0;
padding: 2px 15px;
}
.indexkey {
width: 40%;
}
.indexvalue {
width: 80%;
}
h3 a[name="index__"],
h3 a[name="index_a"],
h3 a[name="index_b"],
h3 a[name="index_c"],
h3 a[name="index_d"],
h3 a[name="index_e"],
h3 a[name="index_f"],
h3 a[name="index_g"],
h3 a[name="index_h"],
h3 a[name="index_i"],
h3 a[name="index_j"],
h3 a[name="index_k"],
h3 a[name="index_l"],
h3 a[name="index_m"],
h3 a[name="index_n"],
h3 a[name="index_o"],
h3 a[name="index_p"],
h3 a[name="index_q"],
h3 a[name="index_r"],
h3 a[name="index_s"],
h3 a[name="index_t"],
h3 a[name="index_u"],
h3 a[name="index_v"],
h3 a[name="index_w"],
h3 a[name="index_x"],
h3 a[name="index_y"],
h3 a[name="index_z"],
h3 a[name="index_0"],
h3 a[name="index_1"],
h3 a[name="index_2"],
h3 a[name="index_3"],
h3 a[name="index_4"],
h3 a[name="index_5"],
h3 a[name="index_6"],
h3 a[name="index_7"],
h3 a[name="index_8"],
h3 a[name="index_9"]
h3 a[id="index__"],
h3 a#index_a,
h3 a#index_b,
h3 a#index_c,
h3 a#index_d,
h3 a#index_e,
h3 a#index_f,
h3 a#index_g,
h3 a#index_h,
h3 a#index_i,
h3 a#index_j,
h3 a#index_k,
h3 a#index_l,
h3 a#index_m,
h3 a#index_n,
h3 a#index_o,
h3 a#index_p,
h3 a#index_q,
h3 a#index_r,
h3 a#index_s,
h3 a#index_t,
h3 a#index_u,
h3 a#index_v,
h3 a#index_w,
h3 a#index_x,
h3 a#index_y,
h3 a#index_z,
h3 a#index_0,
h3 a#index_1,
h3 a#index_2,
h3 a#index_3,
h3 a#index_4,
h3 a#index_5,
h3 a#index_6,
h3 a#index_7,
h3 a#index_8,
h3 a#index_9,
h3 a#index_0x7e
{
font-family: time;
font-size: 250%;
text-align: center;
}
/* -------------------------------------------------------------------
* Verbatim Source Code / Examples.
*/
div.fragment {
font-family: "Roboto Mono", "Monospace";
font-size: 80%;
border: none;
/*border-width: thin; */
/*border-color: #003300;*/
/*background-color: #FCFCE1;*/
background-color: #fefefe;
padding: 0.5em;
margin-left: 5%;
margin-right: 5%
}
div.fragment a.code:link,
div.fragment a.code:visited,
div.fragment a.codeRef:link,
div.fragment a.codeRef:visited {
text-decoration: none;
font-weight: bold;
color: black;
border: none;
}
div.line {
white-space: pre;
padding: 0pt;
margin: 0pt;
}
span.keyword { color: #008000 }
span.keywordtype { color: #604020 }
span.keywordflow { color: #e08000 }
span.comment { color: #800000 }
span.preprocessor { color: #806020 }
span.stringliteral { color: #002080 }
span.charliteral { color: #008080 }
span.red { color: red }
/* -------------------------------------------------------------------
* Attributes Listing.
*/
a.el, a.elRef {
font-family: "Roboto Mono", Courier;
font-weight: bold;
font-size: 110%;
color: black;
border-bottom: none;
}
p.formulaDsp {
text-align: center;
}
.mdTable {
/*border: 1px solid #868686;*/
/*background-color: #DADAEF;*/
/*background-color: #F4F4FB;*/
border: 1px none #008500;
border-left-width: 1px;
border-left-style: solid;
/*background-color: #B8E6B8;*/
/*background-color: #CCE6CA;*/
margin-top: 25px;
font-size: 105%;
}
.mdRow {
padding: 5px 10px;
}
/* This Mozilla/Firefox bug has been corrected from v1.5.
* .mdname1 {
* padding: 3px 0px 0px 0px;
* }
*/
.mdescLeft, .mdescRight {
padding: 0px 8px 4px 8px;
font-size: 11px;
font-style: italic;
/*background-color: #FAFAFA;*/
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
}
.memitem {
margin-bottom: 30px;
border: 1px none #008500;
}
.memproto {
/*background-color: #CCE6CA;*/
background-color: #cccccc;
border-left-width: 4px;
border-left-style: solid;
/*border-color: #008500;*/
border-color: black;
}
.memname {
white-space: nowrap;
padding-left: 5px;
font-size: 105%;
}
table.memname * {
font-family: "Roboto Mono", "Monospace";
}
.memdoc{
padding-left: 5px;
/*margin-top: -8px;*/
border-left-width: 1px;
border-left-style: solid;
/*border-color: #008500;*/
border-color: black;
}
div.contents * table tr {
padding: 3px 3px 3px 8px;
}
.memSeparator {
font-size: 1pt;
}
.memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight {
vertical-align: top;
/*padding: 1px 0px 0px 8px;*/
padding: 3px 3px 3px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
/*
border-top-color: #0c0c0c;
border-right-color: #0c0c0c;
border-bottom-color: #0c0c0c;
border-left-color: #0c0c0c;
*/
border-top-style: none;
border-right-style: none;
/*
border-bottom-style: dotted;
*/
border-left-style: none;
/*background-color: #DADAEF;*/
/*background-color: #eeeeff;*/
/*background-color: #EEEEEE;*/
/*background-color: #CCE6CA;*/
font-family: "Roboto Mono", "Monospace";
}
.memTemplItemLeft, .memTemplItemRight {
border-bottom-width: 2px;
border-bottom-style: solid;
font-weight: bold;
}
.memItemLeft { font-size: 11px; width: 100pt; }
.memItemRight { font-size: 12px; }
.memTemplItemLeft { font-size: 11px; }
.memTemplItemRight { font-size: 12px; }
.memTemplParams {
color: #FFFFFF;
background-color: #000000;
font-size: 11px;
font-weight: bold;
}
.groupText, .groupHeader {
color: #09550B;
font-size: 130%;
font-weight: bold;
margin-top: 15px;
}
.groupHeader {
margin-bottom: -30pt;
}
.inherit {
display: none;
}
/* -------------------------------------------------------------------
* General Classes Index.
*/
span.icona {
margin-right: 10pt;
}
div.toc li.level1 {
margin-left: 0px;
}
div.toc li.level2 {
margin-left: 15px;
display: none;
}
div.toc li.level3 {
margin-left: 30px;
display: none;
}
div.toc li.level4 {
margin-left: 45px;
display: none;
}
.directory .levels {
white-space: nowrap;
width: 100%;
text-align: right;
font-size: 9pt;
}
.directory .levels span {
cursor: pointer;
padding-left: 2px;
padding-right: 2px;
color: #3D578C;
}
div.directory {
margin: 10px 0px;
border-top: 2px solid black;
border-bottom: 2px solid black;
width: 100%;
}
.directory table {
border-collapse: collapse;
}
.directory td {
margin: 0px;
padding: 0px;
vertical-align: top;
}
.directory td.entry {
white-space: nowrap;
padding-right: 6px;
padding-top: 3px;
}
.directory td.entry a {
outline: none;
}
.directory td.entry a img {
border: none;
}
.directory td.desc {
width: 100%;
padding-left: 6px;
padding-right: 6px;
padding-top: 3px;
border-left: 1px solid rgba(0,0,0,0.05);
}
.directory tr.even {
padding-left: 6px;
background-color: #F7F8FB;
}
.directory img {
vertical-align: -30%;
}

50
Seabreeze/doc/Tree.dox Normal file
View File

@ -0,0 +1,50 @@
// -*- C++ -*-
/*! \class Tree
* \brief The tree contains all points of the circuit as its' nodes.
*/
/*! \var vector<Node*> Tree::nodes
* The list of nodes contained in the tree
*/
/*! \function Tree::Tree()
* Default constructor
*/
/*! \function Tree:~Tree()
* Default destructor
*/
/*! \function int Tree::get_N()
* Returns the number of nodes in the tree / points in the circuit
*/
/*! \function Node* Tree::get_node( int i )
* Returns node at index i in the tree
*/
/*! \function vector<Node*> get_node_list()
* Returns the list of nodes contained in the tree
*/
/*! \function void Tree::new_node()
* Create and add a new node to the tree
*/
/*! \function void Tree::After_i( Node* node_i )
* For each node in the tree, determine if they are after or before node_i.
* In other words, change the value of ap of each node to 0 or 1 accordingly.
*/
/*! \function set<int> Tree::Branch_i( int i )
* Returns a set of indexes of nodes who are on the same branch as node i.
*/
/*! \function int Tree::Delay_Elmore( int i)
* Computes the Elmore's delay and returns the result.
*/
/*! \function void Tree::print( ostream& out )
* Prints the tree to the output file.
*/

View File

@ -0,0 +1,65 @@
<br>
<p><b>The complete class hierarchy could be accessed <a href="hierarchy.html">here</a>.</b></p>
<p>All the classes below are in the <a href="namespaceSeabreeze.html">Seabreeze</a> namespace.</p>
<p>The inheritance tree has been splitted/simplificated.</p>
<b>Legend :</b><br>
<pre class="fragment">
<table class="classHierarchy">
<tr><td width="70"><td class="virtual"><a href="#pagetop">ClassA</a><td><b>&nbsp;&nbsp;<tt>ClassA</tt> is abstract</b></tr>
<tr><td width="70"><td class="normal"><a href="#pagetop">ClassB</a><td><b>&nbsp;&nbsp;<tt>ClassB</tt> is instanciable</b></tr>
</table>
</pre>
<br>
<h2 class="classHierarchy">Utilities</h2>
<table class="classHierarchy">
<tr><td width="70"><td class="virtual"><a href="classSeabreeze_1_1BaseObserver.html">BaseObserver</a>
</table>
<table class="classHierarchy">
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1Observer.html">Observer</a>
</table>
<table class="classHierarchy">
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1Observable.html">Observable</a>
</table>
<h2 class="classHierarchy">Seabreeze Engine</h2>
<table class="classHierarchy">
<tr><td width="70"><td class="normal"><a href="namespaceSeabreeze.html">Seabreeze</a>
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1ChipTools.html">ChipTools</a>
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1SeabreezeEngine.html">SeabreezeEngine</a>
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1Session.html">Session</a>
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1DataAlgorithm.html">DataAlgorithm</a>
</table>
<h2 class="classHierarchy">Contacts</h2>
<table class="classHierarchy">
<tr><td width="70"><td class="virtual"><a href="classSeabreeze_1_1AutoContact.html">AutoContact</a>
</table>
<table class="classHierarchy">
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoContactTerminal.html">AutoContactTerminal</a>
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoContactTurn.html">AutoContactTurn</a>
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoContactHTee.html">AutoContactHTee</a>
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoContactVTee.html">AutoContactVTee</a>
</table>
<h2 class="classHierarchy">Segments</h2>
<table class="classHierarchy">
<tr><td width="70"><td class="virtual"><a href="classSeabreeze_1_1AutoSegment.html">AutoSegment</a>
</table>
<table class="classHierarchy">
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoHorizontal.html">AutoHorizontal</a>
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoVertical.html">AutoVertical</a>
</table>
<h2 class="classHierarchy">GCell</h2>
<table class="classHierarchy">
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1GCell.html">GCell</a>
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1BaseGrid_1_1Axis.html">BaseGrid::Axis</a>
<tr><td width="70"><td class="virtual"><a href="classSeabreeze_1_1BaseGrid.html">BaseGrid</a>
</table>
<table class="classHierarchy">
<tr><td width="140"><td class="virtual"><a href="classSeabreeze_1_1Grid.html">Grid</a>
</table>
<table class="classHierarchy">
<tr><td width="210"><td class="normal"><a href="classSeabreeze_1_1GCellGrid.html">GCellGrid</a>
</table>

View File

@ -0,0 +1,81 @@
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN'>
<!-- $Id: customSummary.html,v 1.1 2007/09/15 13:10:13 jpc Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>Seabreeze Documentation</title>
<link href="SoC.css" rel="stylesheet" type="text/css">
</head>
<h1 class="header">Seabreeze Documentation</h1>
<center class="header">
<table class="header">
<tr>
<td><a href="customSummary.html">Summary</a></td>
<td><a href="namespaces.html">Namespaces</a></td>
<td><a href="customHierarchy.html">Class Hierarchy</a></td>
<td><a href="annotated.html">Classes</a></td>
<td><a href="functions.html">Member Index</a></td>
<!-- <td><a href="classes.html">Index2</a></td> -->
</tr>
</table>
</center>
<br>
<hr>
<body>
<h1>Seabreeze Documentation Summary</h1>
<br>
<p><b>The classical Doxygen module documentation could be accessed <a href="modules.html">here</a>.</b></p>
<!--
<h2>Seabreeze Concepts (internal)</h2>
<ol>
<li><a class="el" href="group__buildRules.html">Rules for building wires.</a>
<br>Rules for building AutoContacts. Global/Locals AutoSegments.
<li><a class="el" href="group__loadGlobalRouting.html">Global Routing Loading.</a>
<br>How the Knik global routing is loaded into Seabreeze data-base.
Details the wiring topologies used to complete the routing to the
terminals.
<li><a class="el" href="group__collapseCanonical.html">AutoSegment Collapse &amp; Canonical.</a>
<br>How to force alignment of AutoSegments.
<li><a class="el" href="group__layerAssign.html">Layer Assignment.</a>
<br>Simple strategy to put long wires on higher routing metals.
<li><a class="el" href="group__NetConstraints.html">Constraints Computations.</a>
<br>Compute the legal range of variation of each wire (note that the
constraints are stored on AutoContacts).
<li><a class="el" href="group__NetOptimals.html">AutoSegment Optimal Placement.</a>
<br>Compute the optimal range of variation of each wire.
<li><a class="el" href="group__katabaticSession.html">Seabreeze Update Session Mechanism.</a>
<br>The Session mechanism for modifying the Seabreeze data-base.
</ol>
-->
<h2>API documentations</h2>
<ul>
<li><b><a href="customHierarchy.html">Synthetic Class Hierarchy.</a></b>
<li><b><a href="hierarchy.html">Complete Class Hierarchy (doxygen).</a></b>
<li><b><a href="annotated.html">Class List (doxygen).</a></b>
<li><b><a href="classes.html">Class Index (doxygen).</a></b>
<li><b><a href="modules.html">Modules (raw concepts).</a></b>
<li><b><a href="functions.html">Member Functions Index (doxygen).</a></b>
<li><b><a href="namespaces.html">Namespaces (doxygen).</a></b>
</ul>
<br>
<hr>
<table class="footer1">
<tr>
<td class="LFooter"><small>Customized Concepts (a.k.a. modules)</small></td>
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
</tr>
</table>
<table class="footer2">
<tr>
<td class="LFooter">Seabreeze Documentation</td>
<td class="RFooter"><small>Copyright &#169; 2005-2007 LIP6. All rights reserved</small></td>
</tr>
</table>
</body>
</html>

276
Seabreeze/doc/doxyfile Normal file
View File

@ -0,0 +1,276 @@
# -*- explicit-buffer-name: "doxyfile<Seabreeze/doc>" -*-
# Doxyfile 1.3.4
# --------------------------------------------------------------------
# Project related configuration options
PROJECT_NAME = "Seabreeze - Routing Toolbox"
PROJECT_NUMBER = 1.0
OUTPUT_DIRECTORY = .
OUTPUT_LANGUAGE = English
MARKDOWN_SUPPORT = NO
#USE_WINDOWS_ENCODING = NO
LAYOUT_FILE = DoxygenLayout.xml
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
#DETAILS_AT_TOP = YES
INHERIT_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 2
ALIASES = "function=\fn"\
"important=\par Important:\n"\
"remark=\par Remark:\n"\
"sreturn=\b Returns:"\
"True=\b True"\
"true=\b true"\
"False=\b False"\
"false=\b false"\
"VERTICAL=\b VERTICAL"\
"HORIZONTAL=\b HORIZONTAL"\
"NULL=\c NULL"\
"vector=\c vector"\
"Collection=\c Collection"\
"Collections=\c Collections"\
"Box=\c Box"\
"box=\c box"\
"Layer=\c Layer"\
"Layers=\c Layers"\
"Net=\c Net"\
"Nets=\c Nets"\
"Pin=\c Pin"\
"Pins=\c Pins"\
"Plug=\c Plug"\
"Plugs=\c Plugs"\
"RoutingPad=\c RoutingPad"\
"RoutingPads=\c RoutingPads"\
"Cell=\c Cell"\
"Cells=\c Cells"\
"ToolEngine=\c ToolEngine"\
"ToolEngines=\c ToolEngines"\
"GCell=\c GCell"\
"GCells=\c GCells"\
"Splitter=\c Splitter"\
"Splitters=\c Splitters"\
"SplitterContact=\c SplitterContact"\
"SplitterContacts=\c SplitterContacts"\
"Hurricane=<a href='../hurricane/Index.html'>Hurricane</a>"\
"STL=<a href='http://www.sgi.com/tech/stl/'>STL</a>"\
"red{1}=<span class=\"red\">\1</span>"
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
SUBGROUPING = YES
# --------------------------------------------------------------------
# Build related configuration options
EXTRACT_ALL = NO
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_ANON_NSPACES = YES
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_CLASSES = YES
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = YES
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 1
SHOW_USED_FILES = YES
# --------------------------------------------------------------------
# Configuration options related to warning and progress messages
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO
WARN_IF_DOC_ERROR = YES
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
# --------------------------------------------------------------------
# Configuration options related to the input files
INPUT = \
Seabreeze.dox \
../src/Seabreeze/Node.h ../src/Node.cpp Node.dox \
../src/Seabreeze/Tree.h ../src/Tree.cpp Tree.dox \
../src/Seabreeze/Seabreeze.h ../src/Seabreeze.cpp Seabreeze.dox \
../src/katabatic/SeabreezeEngine.h ../src/SeabreezeEngine.cpp SeabreezeEngine.dox
FILE_PATTERNS = *.h \
*.cpp \
*.dox
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH = .
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH = images
INPUT_FILTER =
FILTER_SOURCE_FILES = YES
# --------------------------------------------------------------------
# Configuration options related to source browsing
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
VERBATIM_HEADERS = YES
# --------------------------------------------------------------------
# Configuration options related to the alphabetical class index
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 2
IGNORE_PREFIX =
# --------------------------------------------------------------------
# Configuration options related to the HTML output
GENERATE_HTML = YES
#HTML_DYNAMIC_SECTIONS = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER = header.html
HTML_FOOTER = footer.html
HTML_STYLESHEET = SoC.css
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 1
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
# --------------------------------------------------------------------
# Configuration options related to the LaTeX output
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER = header.tex
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
# --------------------------------------------------------------------
# Configuration options related to the RTF output
GENERATE_RTF = YES
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
# --------------------------------------------------------------------
# Configuration options related to the man page output
GENERATE_MAN = YES
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
# --------------------------------------------------------------------
# Configuration options related to the XML output
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
# --------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
GENERATE_AUTOGEN_DEF = NO
# --------------------------------------------------------------------
# Configuration options related to the Perl module output
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
# --------------------------------------------------------------------
# Configuration options related to the preprocessor
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = __DOXYGEN__
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
# --------------------------------------------------------------------
# Configuration::addtions related to external references
TAGFILES = ../../hurricane/doc/hurricane/html/hurricane.tag=../hurricane \
../../hurricane/doc/viewer/html/viewer.tag=../viewer \
../../crlcore/doc/crlcore/html/crlcore.tag=../crlcore
GENERATE_TAGFILE = html/Seabreeze.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
# --------------------------------------------------------------------
# Configuration options related to the dot tool
CLASS_DIAGRAMS = NO
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
CLASS_GRAPH = YES
COLLABORATION_GRAPH = NO
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
GRAPHICAL_HIERARCHY = NO
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
#MAX_DOT_GRAPH_WIDTH = 512
#MAX_DOT_GRAPH_HEIGHT = 1024
#MAX_DOT_GRAPH_DEPTH = 0
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
# --------------------------------------------------------------------
# Configuration::addtions related to the search engine
SEARCHENGINE = NO

16
Seabreeze/doc/footer.html Normal file
View File

@ -0,0 +1,16 @@
<br>
<hr>
<table class="footer1">
<tr>
<td class="LFooter"><small>Generated by doxygen $doxygenversion on $date</small></td>
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
</tr>
</table>
<table class="footer2">
<tr>
<td class="LFooter">Seabreeze - Routing Toolbox</td>
<td class="RFooter"><small>Copyright &#169; 2008-2020 Sorbonne Universite. All rights reserved</small></td>
</tr>
</table>
</body>
</html>

26
Seabreeze/doc/header.html Normal file
View File

@ -0,0 +1,26 @@
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN'>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>Katabatic Documentation</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="SoC.css" rel="stylesheet" type="text/css">
<link href="tabs.css" rel="stylesheet" type="text/css">
</head>
<h1 id="pagetop" class="header">Seabreeze - Routing Toolbox</h1>
<!--
<center class="header">
<table class="header">
<tr>
<td><a href="customSummary.html">Summary</a></td>
<td><a href="namespaces.html">Namespaces</a></td>
<td><a href="customHierarchy.html">Class Hierarchy</a></td>
<td><a href="annotated.html">Classes</a></td>
<td><a href="functions.html">Member Index</a></td>
</tr>
</table>
</center>
-->
<br>
<body onload="javascript:toggleLevel(1)">

558
Seabreeze/doc/tabs.css Normal file
View File

@ -0,0 +1,558 @@
.sm
{
position:relative;
z-index:9999
}
.sm,.sm ul,.sm li
{
display:block;
list-style:none;
margin:0;
padding:2pt 7pt;
line-height:normal;
direction:ltr;
text-align:left;
-webkit-tap-highlight-color:rgba(0,0,0,0)
}
.sm-rtl,.sm-rtl ul,.sm-rtl li
{
direction:rtl;
text-align:right
}
.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6
{
margin:0;
padding:0
}
.sm ul
{
display:none
}
.sm li,.sm a
{
position:relative
}
.sm a
{
display:block
}
.sm a.disabled
{
cursor:not-allowed
}
.sm:after
{
content:"\00a0";
display:block;
height:0;
font:0/0 serif;
clear:both;
visibility:hidden;
overflow:hidden
}
.sm,.sm *,.sm *:before,.sm *:after
{
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
box-sizing:border-box
}
#doc-content
{
overflow:auto;
display:block;
padding:0;
margin:0;
-webkit-overflow-scrolling:touch
}
/*
.sm-dox
{
background-image:url("tab_b.png")
}
*/
/*
.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active
{
padding:0 12px;
padding-right:43px;
font-family:"Lucida Grande","Geneva","Helvetica",Arial,sans-serif;
font-size:13px;
font-weight:bold;
line-height:36px;
text-decoration:none;
text-shadow:0 1px 1px rgba(255,255,255,0.9);
color:#283a5d;
outline:0
}
*/
/*
.sm-dox a:hover
{
background-image:url("tab_a.png");
background-repeat:repeat-x;
color:white;
text-shadow:0 1px 1px black
}
*/
.sm-dox a.current
{
color:#d23600
}
.sm-dox a.disabled
{
color:#bbb
}
.sm-dox a span.sub-arrow
{
position:absolute;
top:50%;
margin-top:-14px;
left:auto;
right:3px;
width:28px;
height:28px;
overflow:hidden;
font:bold 12px/28px monospace!important;
text-align:center;
text-shadow:none;
background:rgba(255,255,255,0.5);
-moz-border-radius:5px;
-webkit-border-radius:5px;
border-radius:5px
}
.sm-dox a.highlighted span.sub-arrow:before
{
display:block;
content:'-'
}
/*
.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a
{
-moz-border-radius:5px 5px 0 0;
-webkit-border-radius:5px;
border-radius:5px 5px 0 0
}
.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul
{
-moz-border-radius:0 0 5px 5px;
-webkit-border-radius:0;
border-radius:0 0 5px 5px
}
.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted
{
-moz-border-radius:0;
-webkit-border-radius:0;
border-radius:0
}
*/
/*
.sm-dox ul
{
background:rgba(162,162,162,0.1)
}
*/
/*
.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active
{
font-size:12px;
border-left:8px solid transparent;
line-height:36px;
text-shadow:none;
background-color:white;
background-image:none
}
*/
/*
.sm-dox ul a:hover
{
background-image:url("tab_a.png");
background-repeat:repeat-x;
color:white;
text-shadow:0 1px 1px black
}
*/
.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active
{
border-left:16px solid transparent
}
.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active
{
border-left:24px solid transparent
}
.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active
{
border-left:32px solid transparent
}
.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active
{
border-left:40px solid transparent
}
.sm-dox ul
{
position:absolute;
width:12em
}
/*
.sm-dox li
{
float:left
}
.sm-dox.sm-rtl li
{
float:right
}
.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li
{
float:none
}
*/
.sm-dox a
{
white-space:nowrap
}
.sm-dox ul a,.sm-dox.sm-vertical a
{
white-space:normal
}
.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a
{
white-space:nowrap
}
/*
.sm-dox
{
padding:0 10px;
background-image:url("tab_b.png");
line-height:36px
}
*/
.sm-dox a span.sub-arrow
{
top:50%;
margin-top:-2px;
right:12px;
width:0;
height:0;
border-width:4px;
border-style:solid dashed dashed dashed;
border-color:#283a5d transparent transparent transparent;
background:transparent;
-moz-border-radius:0;
-webkit-border-radius:0;
border-radius:0
}
/*
.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted
{
padding:0 12px;
background-image:url("tab_s.png");
background-repeat:no-repeat;
background-position:right;
-moz-border-radius:0!important;
-webkit-border-radius:0;
border-radius:0!important
}
.sm-dox a:hover
{
background-image:url("tab_a.png");
background-repeat:repeat-x;
color:white;
text-shadow:0 1px 1px black
}
*/
.sm-dox a:hover span.sub-arrow
{
border-color:white transparent transparent transparent
}
.sm-dox a.has-submenu
{
padding-right:24px
}
.sm-dox li
{
border-top:0
}
.sm-dox>li>ul:before,.sm-dox>li>ul:after
{
content:'';
position:absolute;
top:-18px;
left:30px;
width:0;
height:0;
overflow:hidden;
border-width:9px;
border-style:dashed dashed solid dashed;
border-color:transparent transparent #bbb transparent
}
.sm-dox>li>ul:after
{
top:-16px;
left:31px;
border-width:8px;
border-color:transparent transparent #fff transparent
}
.sm-dox ul
{
border:1px solid #bbb;
padding:5px 0;
background:#fff;
/*
-moz-border-radius:5px!important;
-webkit-border-radius:5px;
border-radius:5px!important;
*/
-moz-box-shadow:0 5px 9px rgba(0,0,0,0.2);
-webkit-box-shadow:0 5px 9px rgba(0,0,0,0.2);
box-shadow:0 5px 9px rgba(0,0,0,0.2)
}
.sm-dox ul a span.sub-arrow
{
right:8px;
top:50%;
margin-top:-5px;
border-width:5px;
border-color:transparent transparent transparent #555;
border-style:dashed dashed dashed solid
}
.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted
{
color:#555;
background-image:none;
border:0!important;
color:#555;
background-image:none
}
/*
.sm-dox ul a:hover
{
background-image:url("tab_a.png");
background-repeat:repeat-x;
color:white;
text-shadow:0 1px 1px black
}
*/
.sm-dox ul a:hover span.sub-arrow
{
border-color:transparent transparent transparent white
}
.sm-dox span.scroll-up,.sm-dox span.scroll-down
{
position:absolute;
display:none;
visibility:hidden;
overflow:hidden;
background:#fff;
height:36px
}
.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover
{
background:#eee
}
.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow
{
border-color:transparent transparent #d23600 transparent
}
.sm-dox span.scroll-down:hover span.scroll-down-arrow
{
border-color:#d23600 transparent transparent transparent
}
.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow
{
position:absolute;
top:0;
left:50%;
margin-left:-6px;
width:0;
height:0;
overflow:hidden;
border-width:6px;
border-style:dashed dashed solid dashed;
border-color:transparent transparent #555 transparent
}
.sm-dox span.scroll-down-arrow
{
top:8px;
border-style:solid dashed dashed dashed;
border-color:#555 transparent transparent transparent
}
.sm-dox.sm-rtl a.has-submenu
{
padding-right:12px;
padding-left:24px
}
.sm-dox.sm-rtl a span.sub-arrow
{
right:auto;
left:12px
}
.sm-dox.sm-rtl.sm-vertical a.has-submenu
{
padding:10px 20px
}
.sm-dox.sm-rtl.sm-vertical a span.sub-arrow
{
right:auto;
left:8px;
border-style:dashed solid dashed dashed;
border-color:transparent #555 transparent transparent
}
.sm-dox.sm-rtl>li>ul:before
{
left:auto;
right:30px
}
.sm-dox.sm-rtl>li>ul:after
{
left:auto;
right:31px
}
.sm-dox.sm-rtl ul a.has-submenu
{
padding:10px 20px!important
}
.sm-dox.sm-rtl ul a span.sub-arrow
{
right:auto;
left:8px;
border-style:dashed solid dashed dashed;
border-color:transparent #555 transparent transparent
}
.sm-dox.sm-vertical
{
padding:10px 0;
-moz-border-radius:5px;
-webkit-border-radius:5px;
border-radius:5px
}
.sm-dox.sm-vertical a
{
padding:10px 20px
}
.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted
{
background:#fff
}
.sm-dox.sm-vertical a.disabled
{
background-image:url("tab_b.png")
}
.sm-dox.sm-vertical a span.sub-arrow
{
right:8px;
top:50%;
margin-top:-5px;
border-width:5px;
border-style:dashed dashed dashed solid;
border-color:transparent transparent transparent #555
}
.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after
{
display:none
}
.sm-dox.sm-vertical ul a
{
padding:10px 20px
}
.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted
{
background:#eee
}
.sm-dox.sm-vertical ul a.disabled
{
background:#fff
}
/* SoC Customisation. */
div#main-nav {
margin: 0pt;
border: 0pt;
padding: 0pt;
}
div ul#main-menu {
margin: 0pt;
border: 0pt;
padding: 0pt;
}
/*
.sm ul {
visibility: hidden;
overflow: hidden;
height: 0;
width: 0;
}
*/
.sm li {
list-style: none;
}
ul#main-menu {
display: table;
width: 100%;
}
ul#main-menu > li {
display: table-cell;
text-align: center;
/*width: 20%;*/
border-top: 1px solid black;
border-bottom: 1px solid black;
border-left: none;
border-right: 1px solid black;
padding: 2pt;
font-size: 90%;
}
ul#main-menu > li:first-child {
border-left: 1px solid black;
}
ul#main-menu > li > a {
border-bottom: none;
}
ul#main-menu > li:hover, ul#main-menu > li:hover > a, ul#main-menu > li > a:hover {
background-color: black;
color: white;
}
/*
.sm li {
margin: 0pt;
list-style: none;
font-size: 90%;
border-top: 1px solid black;
border-bottom: 1px solid black;
border-left: none;
border-right: 1px solid black;
display: table-cell;
text-align: center;
padding: 2pt;
width: 5%;
}
.sm li:first-child {
border-left: 1px solid black;
}
.sm li a {
border-style: none;
border-bottom: none;
}
.sm li:hover, .sm li:hover a, .sm li a:hover {
background-color: black;
color: white;
}
*/

View File

@ -0,0 +1,73 @@
# -*- explicit-buffer-name: "CMakeLists.txt<Seabreeze/src>" -*-
# include( ${QT_USE_FILE} )
include_directories( ${SEABREEZE_SOURCE_DIR}/src
${CORIOLIS_INCLUDE_DIR}
${HURRICANE_INCLUDE_DIR}
${CONFIGURATION_INCLUDE_DIR}
${QtX_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${Python_INCLUDE_DIRS}
)
set( includes seabreeze/SeabreezeEngine.h
#seabreeze/GraphicSeabreezeEngine.h
)
set( pyIncludes seabreeze/Configuration.h
seabreeze/Delay.h
seabreeze/Node.h
seabreeze/Tree.h
seabreeze/Elmore.h
seabreeze/PySeabreezeEngine.h
#seabreeze/PyGraphicSeabreezeEngine.h
)
#set( mocIncludes seabreeze/GraphicSeabreezeEngine.h )
set( cpps Configuration.cpp
Delay.cpp
Node.cpp
Tree.cpp
Elmore.cpp
SeabreezeEngine.cpp
#GraphicSeabreezeEngine.cpp
)
set( pyCpps PySeabreeze.cpp
PySeabreezeEngine.cpp
#PyGraphicSeabreezeEngine.cpp
)
#qtX_wrap_cpp( mocCpps ${mocIncludes} )
set( depLibs ${CORIOLIS_PYTHON_LIBRARIES}
${CORIOLIS_LIBRARIES}
${HURRICANE_PYTHON_LIBRARIES}
${HURRICANE_GRAPHICAL_LIBRARIES}
${HURRICANE_LIBRARIES}
${CONFIGURATION_LIBRARY}
${BOOKSHELF_LIBRARY}
${CIF_LIBRARY}
${AGDS_LIBRARY}
${UTILITIES_LIBRARY}
${LEFDEF_LIBRARIES}
${OA_LIBRARIES}
${QtX_LIBRARIES}
${Boost_LIBRARIES}
${LIBXML2_LIBRARIES}
-lutil
${LIBEXECINFO_LIBRARIES}
)
add_library( Seabreeze ${cpps} ${mocCpps} ${pyCpps} )
set_target_properties( Seabreeze PROPERTIES VERSION 1.0 SOVERSION 1 )
target_link_libraries( Seabreeze ${depLibs} )
add_python_module( "${pyCpps}"
"${pyIncludes}"
"Do_not_generate_C_library"
Seabreeze
"Seabreeze;${depLibs}"
include/coriolis2/seabreeze
)
install( TARGETS Seabreeze DESTINATION lib${LIB_SUFFIX} )
install( FILES ${includes}
${mocIncludes} DESTINATION include/coriolis2/seabreeze )

View File

@ -0,0 +1,102 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Configuration.cpp" |
// +-----------------------------------------------------------------+
#include <iostream>
#include <sstream>
#include <iomanip>
#include "hurricane/configuration/Configuration.h"
#include "hurricane/Warning.h"
#include "hurricane/Error.h"
#include "hurricane/Technology.h"
#include "hurricane/DataBase.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Contact.h"
#include "hurricane/Net.h"
#include "hurricane/Segment.h"
#include "hurricane/Cell.h"
#include "crlcore/Utilities.h"
#include "seabreeze/Configuration.h"
namespace Seabreeze {
using std::string;
using std::ostringstream;
using Hurricane::Warning;
using Hurricane::Error;
using Hurricane::Technology;
using Hurricane::RoutingPad;
using Hurricane::Contact;
using Hurricane::Segment;
using Hurricane::Cell;
using Hurricane::Net;
using Hurricane::DataBase;
using Hurricane::Record;
using Hurricane::Name;
using Hurricane::Layer;
using Hurricane::DbU;
//------------------------------------------------------------------------
// Class : "Seabreeze::Configuration"
Configuration::Configuration ()
: _Rct (1)
, _Rsm (1)
, _Csm (1)
{}
Configuration::~Configuration ()
{}
Configuration::Configuration ( const Configuration& other )
: _Rct (other._Rct)
, _Rsm (other._Rsm)
, _Csm (other._Csm)
{}
Configuration* Configuration::clone () const
{ return new Configuration( *this ); }
string Configuration::_getTypeName () const
{ return "Seabreeze::Configuration"; }
string Configuration::_getString () const
{
ostringstream os;
os << "<" << _getTypeName() << ">";
return os.str();
}
Record* Configuration::_getRecord () const
{
Record* record = new Record ( _getString() );
if (record != nullptr) {
record->add( getSlot("_Rct", _Rct) );
record->add( getSlot("_Rsm", _Rsm) );
record->add( getSlot("_Csm", _Csm) );
}
return record;
}
} // Seabreeze namespace.

71
Seabreeze/src/Delay.cpp Normal file
View File

@ -0,0 +1,71 @@
// -*- C++ -*-
// //
// // This file is part of the Coriolis Software.
// // Copyright (c) SU 2022-2022, All Rights Reserved
// //
// // +-----------------------------------------------------------------+
// // | C O R I O L I S |
// // | S e a b r e e z e - Timing Analysis |
// // | |
// // | Author : Vu Hoang Anh PHAM |
// // | E-mail : Jean-Paul.Chaput@lip6.fr |
// // | =============================================================== |
// // | C++ Header : "./seabreeze/Delay.h" |
// // +-----------------------------------------------------------------+
#include <map>
#include <iostream>
#include "hurricane/RoutingPad.h"
#include "seabreeze/Delay.h"
#include "seabreeze/Elmore.h"
using namespace std;
namespace Seabreeze {
using Hurricane::RoutingPad;
//---------------------------------------------------------
// Class : Seabreeze::Delay
Delay::Delay ( Elmore* elmore, RoutingPad* sink )
: _elmore(elmore)
, _sink (sink)
, _delay (0.0)
{ }
Delay::~Delay ()
{ }
string Delay::_getTypeName () const
{ return "Seabreeze::Delay"; }
string Delay::_getString () const
{
string s = "<Delay ";
s += getString( _sink );
s += " d=" + getString( _delay );
s += ">";
return s;
}
Record* Delay::_getRecord () const
{
Record* record = new Record ( _getString() );
if (record != nullptr) {
record->add( getSlot("_elmore" , _elmore) );
record->add( getSlot("_sink" , _sink ) );
record->add( getSlot("_delay" , _delay ) );
}
return record;
}
} // Seabreeze namespace.

577
Seabreeze/src/Elmore.cpp Normal file
View File

@ -0,0 +1,577 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Elmore.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/DebugSession.h"
#include "hurricane/Error.h"
#include "hurricane/Segment.h"
#include "hurricane/Plug.h"
#include "hurricane/Net.h"
#include "hurricane/Hook.h"
#include "seabreeze/Elmore.h"
#include "seabreeze/Node.h"
#include "seabreeze/SeabreezeEngine.h"
namespace Seabreeze {
using namespace std;
using Hurricane::Error;
using Hurricane::DBo;
using Hurricane::DbU;
using Hurricane::Plug;
using Hurricane::Net;
using Hurricane::Cell;
using Hurricane::Hook;
using Hurricane::Instance;
using Hurricane::Property;
using Hurricane::PrivateProperty;
using Hurricane::Component;
using Hurricane::Segment;
using Hurricane::DebugSession;
//---------------------------------------------------------
// Class : "Elmore"
Elmore::Elmore ( Net* net )
: _seabreeze(nullptr)
, _net (net)
, _driver (nullptr)
, _tree (new Tree(this))
, _delays ()
{}
Elmore::~Elmore ()
{
cdebug_log(199,0) << "Elmore::~Elmore() " << endl;
delete _tree;
for ( Delay* delay : _delays ) delete delay;
}
void Elmore::setup ()
{
cdebug_log(199,1) << "Elmore::findDriver()" << endl;
for ( RoutingPad* rp : _net->getRoutingPads() ) {
Plug* plug = static_cast<Plug*>( rp->getPlugOccurrence().getEntity() );
if (plug->getMasterNet()->getDirection() & Net::Direction::DirOut) {
if (_driver) {
cerr << Error( "Elmore::setup(): %s has more than one driver:\n"
" * Using: %s\n"
" * Ignoring: %s"
, getString(_net).c_str()
, getString(_driver).c_str()
, getString(rp).c_str()
) << endl;
continue;
}
_driver = rp;
} else {
_delays.push_back( new Delay(this,rp) );
}
}
cdebug_log(199,0) << "Found " << _delays.size() << " sink points:" << endl;
for ( Delay* delay : _delays ) {
cdebug_log(199,0) << "| " << delay << endl;
}
if (not _driver) {
cerr << Error( "Elmore::_postCreate(): No driver found on %s, aborting."
, getString(_net).c_str() ) << endl;
cdebug_tabw(199,-1);
return;
}
cdebug_tabw(199,-1);
}
const Configuration* Elmore::getConfiguration () const
{ return _seabreeze->getConfiguration(); }
Delay* Elmore::getDelay ( RoutingPad* rp ) const
{
for ( Delay* delay : _delays ) {
if (delay->getSink() == rp) return delay;
}
return nullptr;
}
void Elmore::buildTree ()
{
if (not _driver) {
cerr << Error( "Elmore::buildTree(): Net has no driver, aborting." ) << endl;
return;
}
Contact* rootContact = nullptr;
for ( Component* component : _driver->getSlaveComponents() ) {
Contact* contact = dynamic_cast<Contact*>(component);
if (contact) {
rootContact = contact;
break;
}
}
if (not rootContact) {
cerr << Error( "Elmore::buildTree(): No Contact anchored on %s."
, getString(_driver).c_str() ) << endl;
return;
}
cdebug_log(199,1) << "Elmore::buildTree()" << endl;
cdebug_log(199,0) << "Root contact " << rootContact << endl;
Node* rootNode = new Node( nullptr, rootContact );
double R = 0;
double C = 0;
setRC( &R, &C, rootContact, nullptr );
rootNode->setR( R );
rootNode->setC( (C == 0.0) ? 0.0 : 1/C );
Segment* segment = nullptr;
size_t count = 0;
for ( Component* component : rootContact->getSlaveComponents() ) {
segment = dynamic_cast<Segment*>( component );
if (not segment) continue;
++count;
}
if (count != 1) {
cerr << Error( "Elmore::buildTree(): Terminal contact has more than one segment (%d), aborting.\n"
" (on %s)"
, count
, getString(rootContact).c_str()
) << endl;
cdebug_tabw(199,-1);
return;
}
buildFromNode( rootNode, segment );
//---------- More than 1 Contact in main RoutingPad ------- ( 1 )
for ( Component* component : _driver->getSlaveComponents() ) {
Contact* sideContact = dynamic_cast<Contact*>(component);
if (sideContact && sideContact != rootContact) {
Node* sideNode = new Node( rootNode, sideContact );
double sR = 0;
double sC = 0;
setRC ( &sR, &sC, sideContact, nullptr );
sideNode->setR( sR );
sideNode->setC( (sC == 0.0 ) ? 0.0: 1/sC );
Segment* sideSegment = nullptr;
size_t count = 0;
for ( Component* component : sideContact->getSlaveComponents() ) {
sideSegment = dynamic_cast<Segment*>( component );
if (not sideSegment) continue;
++count;
}
if (count != 1) {
cerr << Error( "Elmore::buildTree(): Terminal contact has more than one segment (%d), aborting.\n"
" (on %s)"
, count
, getString(sideContact).c_str()
) << endl;
cdebug_tabw(199,-1);
return;
}
buildFromNode( sideNode, sideSegment );
}
}
//---------------------------------------------------------------
/*
//---------- More than 1 Contact in 1 RoutingPad ---------- ( 2 )
for ( RoutingPad* rp : getNet()->getRoutingPads() ) {
Node* mainNode = nullptr;
for ( Component* rpComp : rp->getSlaveComponents() ) {
Contact* mainContact = dynamic_cast<Contact*>(rpComp);
if ( not mainContact ) continue;
mainNode = _tree->getNode( mainContact );
if ( mainNode ) break;
}
if ( mainNode == nullptr ) {
cerr << "No mainNode found!" << endl;
break;
}
for ( Component* rpComp : rp->getSlaveComponents() ) {
Contact* sideContact = dynamic_cast<Contact*>(rpComp);
if ( not sideContact || sideContact == mainNode->contact() ) continue;
Node* sideNode = new Node( mainNode, sideContact );
double sR = 0;
double sC = 0;
setRC( &sR, &sC, sideContact, nullptr );
sideNode->setR( sR );
sideNode->setC( (sC == 0.0) ? 0.0 : 1/sC );
Segment* sideSegment = nullptr;
size_t sideCount = 0;
for ( Component* component : sideContact->getSlaveComponents() ) {
sideSegment = dynamic_cast<Segment*>( component );
if (not sideSegment) continue;
++sideCount;
}
if (sideCount != 1) {
cerr << Error( "Elmore::buildTree(): Terminal side contact has to have one segment (%d), aborting.\n"
" (on %s)"
, sideCount
, getString(sideContact).c_str()
) << endl;
cdebug_tabw(199,-1);
return;
}
buildFromNode( sideNode, sideSegment );
}
}
//---------------------------------------------------------
*/
cdebug_log(199,0) << "Elmore::buildTree() - Finished" << endl;
cdebug_tabw(199,-1);
_tree->print( cerr );
}
void Elmore::buildFromNode ( Node* rootNode, Segment* toSegment )
{
if (not rootNode->contact()) {
cerr << Error( "Elmore::buildFromNode(): rootNode has no contact, aborting." ) << endl;
return;
}
_tree->addNode( rootNode );
cdebug_log(199,1) << "Elmore::buildFromNode()" << endl;
cdebug_log(199,0) << "rootNode->_contact=" << rootNode->contact() << endl;
cdebug_log(199,0) << "toSegment=" << toSegment << endl;
Contact* opposite = dynamic_cast<Contact*>( toSegment->getOppositeAnchor( rootNode->contact()) );
if (not opposite or (rootNode->parent() and (opposite == rootNode->parent()->contact())) ) {
cdebug_tabw(199,-1);
return;
}
cdebug_log(199,0) << "opposite=" << opposite << endl;
double Rb = 0;
double Cb = 0;
opposite = buildBranch( &Rb, &Cb, opposite );
if (not opposite) {
cerr << Error( "Elmore::buildFromNode(): Branch end up on NULL Contact, pruned." ) << endl;
cdebug_tabw(199,-1);
return;
}
cdebug_log(199,0) << "Reached fork " << opposite << endl;
Node* node = new Node( rootNode, opposite);
node->setR( Rb );
node->setC( (Cb == 0.0) ? 0.0 : 1/Cb );
cdebug_log(199,0) << "R=" << Rb << " C=" << Cb << endl;
int count = 0;
for ( Component* component : opposite->getSlaveComponents() ) {
count += (dynamic_cast<Segment*>(component)) ? 1 : 0;
}
cdebug_log(199,0) << "Node's contact has : " << count << " segments" << endl;
if (count == 1) {
_tree->addNode( node );
} else if (count > 2) {
for ( Component* component : opposite->getSlaveComponents() ) {
Segment* segment = dynamic_cast<Segment*>( component );
if (not segment) continue;
cdebug_log(199,0) << "| " << segment << endl;
Contact* target = dynamic_cast<Contact*>( segment->getOppositeAnchor(opposite) );
if (not target) {
cerr << Error( "Elmore::buildFromNode(): Segment missing opposite anchor. pruned." ) << endl;
continue;
}
cdebug_log(199,0) << "target=" << target << endl;
if (not _tree->isReached(target)) {
buildFromNode( node, segment);
}
}
}
//---------- More than 1 Contact in this RoutingPad ------- ( 1 )
Hook* masterHook = opposite->getAnchorHook()->getMasterHook();
RoutingPad* currentRP = nullptr;
if ( masterHook ) {
currentRP = dynamic_cast<RoutingPad*>( masterHook->getComponent() );
cdebug_log(199,0) << " Look back = " <<currentRP << endl;
}
if ( currentRP ) {
for ( Component* component : currentRP->getSlaveComponents() ) {
Contact* sideContact = dynamic_cast<Contact*>(component);
if (sideContact && sideContact != opposite) {
Node* sideNode = new Node( node, sideContact );
double sR = 0;
double sC = 0;
setRC ( &sR, &sC, sideContact, nullptr );
sideNode->setR( sR );
sideNode->setC( (sC == 0.0 ) ? 0.0: 1/sC );
Segment* sideSegment = nullptr;
size_t count = 0;
for ( Component* component : sideContact->getSlaveComponents() ) {
sideSegment = dynamic_cast<Segment*>( component );
if (not sideSegment) continue;
++count;
}
if (count != 1) {
cerr << Error( "Elmore::buildTree(): Terminal contact has more than one segment (%d), aborting.\n"
" (on %s)"
, count
, getString(sideContact).c_str()
) << endl;
cdebug_tabw(199,-1);
return;
}
buildFromNode( sideNode, sideSegment );
}
}
}
//---------------------------------------------------------------
cdebug_tabw(199,-1);
}
Contact* Elmore::buildBranch ( double* R, double* C, Contact* current )
{
cdebug_log(199,1) << "Elmore::buildBranch()" << endl;
cdebug_log(199,0) << "current=" << current << endl;
while ( true ) {
_tree->setReached( current );
int count = 0;
Segment* segment = nullptr;
for ( Component* component : current->getSlaveComponents() ) {
segment = dynamic_cast<Segment*>( component );
if (not segment) continue;
Contact* opposite = dynamic_cast<Contact*>( segment->getOppositeAnchor(current) );
if (opposite and _tree->isReached(opposite)) {
setRC( R, C, current, segment );
cdebug_log(199,0) << "current=" << current << endl;
cdebug_log(199,0) << "segment=" << segment << endl;
cdebug_log(199,0) << "R=" << *R << endl;
cdebug_log(199,0) << "C=" << *C << endl;
}
++count;
}
if (not count) {
cerr << Error( "Elmore::buildBranch(): Contact seems to be a dead end, pruning.\n"
" (on %s)"
, getString(current).c_str() ) << endl;
cdebug_tabw(199,-1);
return nullptr;
}
else if (count != 2) {
break;
}
Contact* next = nullptr;
for ( Component* component : current->getSlaveComponents() ) {
segment = dynamic_cast<Segment*>( component );
if (not segment) continue;
cdebug_log(199,0) << "| " << segment << endl;
Contact* opposite = dynamic_cast<Contact*>( segment->getOppositeAnchor(current) );
cdebug_log(199,0) << "opposite=" << opposite << endl;
if (opposite and not _tree->isReached(opposite))
next = opposite;
}
if (not next) {
cerr << Error( "Elmore::buildBranch(): Wire loop detected.\n"
" (on %s)"
, getString(current).c_str() ) << endl;
cdebug_tabw(199,-1);
return nullptr;
}
current = next;
}
cdebug_tabw(199,-1);
return current;
}
void Elmore::setRC ( double* R, double* C, Contact* contact, Segment* segment )
{
double Rcont = getConfiguration()->getRct();
//double Hcont = DbU::toPhysical( contact->getHeight(), DbU::UnitPower::Nano );
//double Wcont = DbU::toPhysical( contact->getWidth (), DbU::UnitPower::Nano );
double Wcont = DbU::toLambda( contact->getWidth () );
double Acont = Wcont * Wcont;
*R += Rcont * Acont;
if (not segment) {
*C = 0;
} else {
double Rseg = getConfiguration()->getRsm();
double Cseg = getConfiguration()->getCsm();
//double Lseg = DbU::toPhysical( segment->getLength(), DbU::UnitPower::Nano );
//double Wseg = DbU::toPhysical( segment->getWidth (), DbU::UnitPower::Nano );
double Lseg = DbU::toLambda( segment->getLength() );
double Wseg = DbU::toLambda( segment->getWidth () );
double Aseg = Lseg * Wseg;
cdebug_log(199,0) << "Elmore::setRC() on " << segment << endl;
cdebug_log(199,0) << " Lseg=" << Lseg << " Wseg=" << Wseg << " Aseg=" << Aseg << endl;
*R += Rseg * Aseg;
*C += (Aseg) ? 1/(Cseg*Aseg) : 0.0;
}
}
Delay* Elmore::delayElmore ( RoutingPad* rp )
{ return _tree->computeElmoreDelay( rp ); }
void Elmore::toTree ( ostream& os ) const
{ _tree->print( os ); }
string Elmore::_getTypeName () const
{ return "Seabreeze::Elmore"; }
string Elmore::_getString () const
{
string s = "<" + _getTypeName() + ">";
return s;
}
Record* Elmore::_getRecord () const
{
Record* record = new Record ( _getString() );
if (record != nullptr) {
record->add( getSlot("_seabreeze", _seabreeze) );
record->add( getSlot("_net" , _net ) );
record->add( getSlot("_driver" , _driver ) );
record->add( getSlot("_tree" , _tree ) );
record->add( getSlot("_delays" , &_delays ) );
}
return record;
}
//---------------------------------------------------------
// Class : "ElmoreProperty"
Name ElmoreProperty::_name = "Seabreeze::Elmore";
ElmoreProperty::ElmoreProperty ( Net* net )
: PrivateProperty()
, _elmore (net)
{
if (net) {
SeabreezeEngine* seabreeze
= dynamic_cast<SeabreezeEngine*>( ToolEngine::get( net->getCell(), "Seabreeze" ));
if (not seabreeze) {
cerr << Error( "ElmoreProperty::ElmoreProperty(): Cannot find SeabreezeEngine on %s."
, getString(net->getCell()).c_str()) << endl;
}
_elmore.setSeabreeze( seabreeze );
_elmore.setup();
}
cdebug_log(199,0) << "ElmoreProperty::ElmoreProperty() on " << net << endl;
}
ElmoreProperty* ElmoreProperty::create ( Net* net )
{
ElmoreProperty* property = new ElmoreProperty( net );
property->_postCreate();
return property;
}
Name ElmoreProperty::staticGetName ()
{ return _name; }
Name ElmoreProperty::getName () const
{ return _name; }
string ElmoreProperty::_getTypeName () const
{ return "ElmoreProperty"; }
string ElmoreProperty::_getString () const
{
string s = PrivateProperty::_getString ();
s.insert ( s.length() - 1 , " " + getString(&_elmore) );
return s;
}
Record* ElmoreProperty::_getRecord () const
{
Record* record = PrivateProperty::_getRecord();
if ( record ) {
record->add( getSlot( "_name" , _name ) );
record->add( getSlot( "_elmore", &_elmore ) );
}
return record;
}
//---------------------------------------------------------
// Class : "ElmoreExtension"
Elmore* ElmoreExtension::create ( Net* net )
{
cdebug_log(199,1) << "ElmoreExtension::create() " << net << endl;
Elmore* elmore = get( net );
if (not elmore) {
ElmoreProperty* property = new ElmoreProperty( net );
net->put( property );
elmore = property->getElmore();
}
cdebug_tabw(199,-1);
return elmore;
}
void ElmoreExtension::destroy ( Net* net )
{
cdebug_log(199,1) << "ElmoreExtension::destroy() " << net << endl;
Property* property = net->getProperty( ElmoreProperty::staticGetName() );
if (property) net->remove( property );
cdebug_tabw(199,-1);
}
Elmore* ElmoreExtension::get ( Net* net )
{
Elmore* elmore = nullptr;
Property* property = net->getProperty( ElmoreProperty::staticGetName() );
if (property) elmore = static_cast<ElmoreProperty*>( property )->getElmore();
return elmore;
}
} // Seabreeze namespace.

86
Seabreeze/src/Node.cpp Normal file
View File

@ -0,0 +1,86 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Node.cpp" |
// +-----------------------------------------------------------------+
#include <iostream>
#include "seabreeze/Node.h"
namespace Seabreeze {
using std::string;
Node::Node ()
: _R (0.0)
, _Rt (0.0)
, _C (0.0)
, _parent (nullptr)
, _childs ()
, _contact(nullptr)
, _label (0)
, _ap (0)
{ }
Node::Node ( Node* parent, Contact* contact )
: _R (0.0)
, _Rt (0.0)
, _C (0.0)
, _parent (parent)
, _childs ()
, _contact(contact)
, _label (0)
, _ap (0)
{
if (parent) parent->addChild( this );
}
Node::~Node ()
{ }
string Node::_getTypeName () const
{ return "Seabreeze::Node"; }
string Node::_getString () const
{
string s = "<Node ";
s += getString( _contact );
s += " R=" + getString( _R );
s += " C=" + getString( _C );
s += ">";
return s;
}
Record* Node::_getRecord () const
{
Record* record = new Record ( _getString() );
if (record != nullptr) {
record->add( getSlot("_R" , _R ) );
record->add( getSlot("_Rt" , _Rt ) );
record->add( getSlot("_C" , _C ) );
record->add( getSlot("_parent" , _parent ) );
record->add( getSlot("_childs" , &_childs ) );
record->add( getSlot("_contact", _contact) );
record->add( getSlot("_label" , _label ) );
record->add( getSlot("_ap" , _ap ) );
}
return record;
}
} // Seabreeze namespace.

View File

@ -0,0 +1,103 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2017-2021, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | T o o l E n g i n e T u t o r i a l |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./PySeabreeze.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/isobar/PyHurricane.h"
#include "hurricane/isobar/PyCell.h"
#include "seabreeze/PySeabreezeEngine.h"
namespace Seabreeze {
using std::cerr;
using std::endl;
using Hurricane::tab;
using Isobar::__cs;
using Isobar::getPyHash;
using CRL::PyTypeToolEngine;
// using CRL::PyTypeGraphicTool;
#if !defined(__PYTHON_MODULE__)
// +=================================================================+
// | "PySeabreeze" Shared Library Code Part |
// +=================================================================+
# else // End of PyHurricane Shared Library Code Part.
// +=================================================================+
// | "PySeabreeze" Python Module Code Part |
// +=================================================================+
extern "C" {
// +-------------------------------------------------------------+
// | "PySeabreeze" Module Methods |
// +-------------------------------------------------------------+
static PyMethodDef PySeabreeze_Methods[] =
{ {NULL, NULL, 0, NULL} /* sentinel */
};
static PyModuleDef PySeabreeze_ModuleDef =
{ PyModuleDef_HEAD_INIT
, .m_name = "Seabreeze"
, .m_doc = "Show how to interface Coriolis/C++ to Python."
, .m_size = -1
, .m_methods = PySeabreeze_Methods
};
// ---------------------------------------------------------------
// Module Initialization : "PyInit_Seabreeze ()"
PyMODINIT_FUNC PyInit_Seabreeze ( void )
{
cdebug_log(40,0) << "PyInit_Seabreeze()" << endl;
PySeabreezeEngine_LinkPyType();
//PyGraphicSeabreezeEngine_LinkPyType();
PYTYPE_READY_SUB( SeabreezeEngine , ToolEngine );
//PYTYPE_READY_SUB( GraphicSeabreezeEngine, GraphicTool );
PyObject* module = PyModule_Create( &PySeabreeze_ModuleDef );
if (module == NULL) {
cerr << "[ERROR]\n"
<< " Failed to initialize Seabreeze module." << endl;
return NULL;
}
Py_INCREF( &PyTypeSeabreezeEngine );
PyModule_AddObject( module, "SeabreezeEngine", (PyObject*)&PyTypeSeabreezeEngine );
//Py_INCREF( &PyTypeGraphicSeabreezeEngine );
//PyModule_AddObject( module, "GraphicSeabreezeEngine", (PyObject*)&PyTypeGraphicSeabreezeEngine );
return module;
}
} // End of extern "C".
#endif // Python Module Code Part.
} // Seabreeze namespace.

View File

@ -0,0 +1,215 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2017-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | T o o l E n g i n e T u t o r i a l |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./PySeabreezeEngine.cpp" |
// +-----------------------------------------------------------------+
#include <functional>
#include "hurricane/isobar/PyCell.h"
#include "hurricane/viewer/PyCellViewer.h"
#include "hurricane/isobar/PyNet.h"
#include "hurricane/viewer/ExceptionWidget.h"
#include "hurricane/Cell.h"
#include "crlcore/Utilities.h"
#include "seabreeze/PySeabreezeEngine.h"
# undef ACCESS_OBJECT
# undef ACCESS_CLASS
# define ACCESS_OBJECT _baseObject._object
# define ACCESS_CLASS(_pyObject) &(_pyObject->_baseObject)
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(SeabreezeEngine,seabreeze,function)
namespace Seabreeze {
using std::cerr;
using std::endl;
using std::hex;
using std::ostringstream;
using Hurricane::tab;
using Hurricane::Exception;
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::ExceptionWidget;
using Isobar::ProxyProperty;
using Isobar::ProxyError;
using Isobar::ConstructorError;
using Isobar::HurricaneError;
using Isobar::HurricaneWarning;
using Isobar::getPyHash;
using Isobar::ParseOneArg;
using Isobar::ParseTwoArg;
using Isobar::PyCell;
using Isobar::PyCell_Link;
using Isobar::PyCellViewer;
using Isobar::PyTypeCellViewer;
using Isobar::PyNet;
using CRL::PyToolEngine;
extern "C" {
#if defined(__PYTHON_MODULE__)
// +=================================================================+
// | "PySeabreezeEngine" Python Module Code Part |
// +=================================================================+
static PyObject* PySeabreezeEngine_get ( PyObject*, PyObject* args )
{
cdebug_log(40,0) << "PySeabreezeEngine_get()" << endl;
SeabreezeEngine* seabreeze = NULL;
HTRY
PyObject* arg0;
if (not ParseOneArg("Seabreeze.get", args, CELL_ARG, &arg0)) return NULL;
seabreeze = SeabreezeEngine::get(PYCELL_O(arg0));
HCATCH
return PySeabreezeEngine_Link(seabreeze);
}
static PyObject* PySeabreezeEngine_create ( PyObject*, PyObject* args )
{
cdebug_log(40,0) << "PySeabreezeEngine_create()" << endl;
SeabreezeEngine* seabreeze = NULL;
HTRY
PyObject* arg0;
if (not ParseOneArg("Seabreeze.get", args, CELL_ARG, &arg0)) return NULL;
Cell* cell = PYCELL_O(arg0);
seabreeze = SeabreezeEngine::get(cell);
if (seabreeze == NULL) {
seabreeze = SeabreezeEngine::create(cell);
} else
cerr << Warning("%s already has a Seabreeze engine.",getString(cell).c_str()) << endl;
HCATCH
return PySeabreezeEngine_Link(seabreeze);
}
static PyObject* PySeabreezeEngine_setViewer ( PySeabreezeEngine* self, PyObject* args )
{
cdebug_log(40,0) << "PySeabreezeEngine_setViewer ()" << endl;
HTRY
METHOD_HEAD( "SeabreezeEngine.setViewer()" )
PyObject* pyViewer = NULL;
if (not PyArg_ParseTuple(args,"O:EtesianEngine.setViewer()",&pyViewer)) {
PyErr_SetString( ConstructorError, "Bad parameters given to EtesianEngine.setViewer()." );
return NULL;
}
if (IsPyCellViewer(pyViewer)) {
seabreeze->setViewer( PYCELLVIEWER_O(pyViewer) );
}
HCATCH
Py_RETURN_NONE;
}
/*
PyObject* PySeabreezeEngine_runTool ( PySeabreezeEngine* self )
{
cdebug_log(40,0) << "PySeabreezeEngine_runTool()" << endl;
Cell* cell = NULL;
HTRY
METHOD_HEAD("SeabreezeEngine.runTool()")
if (seabreeze->getViewer()) {
if (ExceptionWidget::catchAllWrapper( std::bind(&SeabreezeEngine::runTool,seabreeze) )) {
PyErr_SetString( HurricaneError, "SeabreezeEngine::runTool() has thrown an exception (C++)." );
return NULL;
}
cell = seabreeze->getCell();
} else {
cell = seabreeze->runTool();
}
HCATCH
return PyCell_Link( cell );
}
*/
static PyObject* PySeabreezeEngine_buildElmore ( PySeabreezeEngine* self, PyObject* args )
{
cdebug_log(40,0) << "PySeabreezeEngine_buildElmore()" << endl;
HTRY
PyObject* arg0 = NULL;
METHOD_HEAD("SeabreezeEngine.buildElmore()")
if (not ParseOneArg("Seabreeze.buildElmore()", args, NET_ARG, &arg0)) return NULL;
seabreeze->buildElmore(PYNET_O(arg0));
HCATCH
Py_RETURN_NONE;
}
// Standart Accessors (Attributes).
// Standart Destroy (Attribute).
DBoDestroyAttribute(PySeabreezeEngine_destroy,PySeabreezeEngine)
PyMethodDef PySeabreezeEngine_Methods[] =
{ { "get" , (PyCFunction)PySeabreezeEngine_get , METH_VARARGS|METH_STATIC
, "Returns the Seabreeze engine attached to the Cell, None if there isnt't." }
, { "create" , (PyCFunction)PySeabreezeEngine_create , METH_VARARGS|METH_STATIC
, "Create a Seabreeze engine on this cell." }
, { "setViewer" , (PyCFunction)PySeabreezeEngine_setViewer , METH_VARARGS
, "Associate a Viewer to this SeabreezeEngine." }
//, { "runDemoPart1" , (PyCFunction)PySeabreezeEngine_runDemoPart1 , METH_NOARGS
// , "Run the first part of the demo." }
, { "buildElmore" , (PyCFunction)PySeabreezeEngine_buildElmore , METH_VARARGS
, "Run the Seabreeze tool." }
, { "destroy" , (PyCFunction)PySeabreezeEngine_destroy , METH_NOARGS
, "Destroy the associated hurricane object. The python object remains." }
, {NULL, NULL, 0, NULL} /* sentinel */
};
DBoDeleteMethod(SeabreezeEngine)
PyTypeObjectLinkPyType(SeabreezeEngine)
#else // End of Python Module Code Part.
// +=================================================================+
// | "PySeabreezeEngine" Shared Library Code Part |
// +=================================================================+
// Link/Creation Method.
PyTypeInheritedObjectDefinitions(SeabreezeEngine,PyToolEngine)
DBoLinkCreateMethod(SeabreezeEngine)
#endif // Shared Library Code Part.
} // extern "C".
} // Seabreeze namespace.

View File

@ -0,0 +1,158 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./SeabreezeEngine.cpp" |
// +-----------------------------------------------------------------+
#include <iomanip>
#include "hurricane/utilities/Path.h"
#include "hurricane/DebugSession.h"
#include "hurricane/UpdateSession.h"
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/Layer.h"
#include "hurricane/Net.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Plug.h"
#include "hurricane/Cell.h"
#include "hurricane/Instance.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "crlcore/AllianceFramework.h"
#include "seabreeze/SeabreezeEngine.h"
#include "seabreeze/Elmore.h"
namespace Seabreeze {
using namespace std;
using Hurricane::dbo_ptr;
using Hurricane::UpdateSession;
using Hurricane::DebugSession;
using Hurricane::tab;
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::Breakpoint;
using Hurricane::Timer;
using Hurricane::DbU;
using Hurricane::Box;
using Hurricane::Layer;
using Hurricane::DataBase;
using Hurricane::Technology;
using Hurricane::Component;
using Hurricane::Contact;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::RoutingPad;
using Hurricane::Cell;
using Hurricane::Plug;
using Hurricane::Instance;
using Hurricane::Transformation;
using Hurricane::Occurrence;
//---------------------------------------------------------
// Class : "Seabreeze::SeabreezeEngine".
Name SeabreezeEngine::_toolName = "Seabreeze";
const Name& SeabreezeEngine::staticGetName ()
{ return _toolName; }
SeabreezeEngine* SeabreezeEngine::create ( Cell* cell )
{
SeabreezeEngine* seabreeze = new SeabreezeEngine ( cell );
seabreeze->_postCreate();
return seabreeze;
}
SeabreezeEngine* SeabreezeEngine::get ( const Cell* cell )
{ return static_cast<SeabreezeEngine*>(ToolEngine::get(cell, staticGetName())); }
const Name& SeabreezeEngine::getName () const
{ return _toolName; };
string SeabreezeEngine::_getTypeName () const
{ return getString(_toolName); }
string SeabreezeEngine::_getString () const
{
ostringstream os;
os << "<" << _toolName << " " << _cell->getName() << ">";
return os.str();
}
Record* SeabreezeEngine::_getRecord () const
{
Record* record = Super::_getRecord();
record->add( getSlot("_configuration", _configuration) );
return record;
}
void SeabreezeEngine::buildElmore ( Net* net )
{
DebugSession::open( net, 190, 200 );
cdebug_log(199,1) << "SeabreezeEngine::buildElmore()" << endl;
cdebug_log(199,0) << "Run on " << net << endl;
Elmore* elmore = ElmoreExtension::create( net );
elmore->buildTree();
cerr << "Net has " << elmore->getDelays().size() << " sink(s)." << endl;
for ( RoutingPad* rp : net->getRoutingPads() ) {
Plug* plug = static_cast<Plug*>( rp->getPlugOccurrence().getEntity() );
if (plug->getMasterNet()->getDirection() & Net::Direction::DirOut) {
continue;
}
cerr << "| Elmore's delay: " << elmore->delayElmore(rp) << endl;
}
cdebug_tabw(199,-1);
DebugSession::close();
}
SeabreezeEngine::SeabreezeEngine ( Cell* cell )
: Super (cell)
, _configuration(new Configuration())
, _viewer (NULL)
{}
SeabreezeEngine::~SeabreezeEngine ()
{
delete _configuration;
}
void SeabreezeEngine::_postCreate()
{
Super::_postCreate ();
}
void SeabreezeEngine::_preDestroy ()
{}
} // Seabreeze namespace.

207
Seabreeze/src/Tree.cpp Normal file
View File

@ -0,0 +1,207 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Tree.cpp" |
// +-----------------------------------------------------------------+
#include <string>
#include <iostream>
#include <algorithm>
#include "hurricane/Error.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Net.h"
#include "seabreeze/Elmore.h"
#include "seabreeze/Tree.h"
#include "seabreeze/Node.h"
#include "seabreeze/Delay.h"
namespace Seabreeze {
using std::string;
using std::find;
using std::set;
using std::cerr;
using std::endl;
using std::ostream;
using Hurricane::Error;
using Hurricane::Hook;
using Hurricane::Component;
Tree::Tree ( Elmore* elmore )
: _elmore (elmore)
, _nodes ()
, _reacheds()
{}
Tree::~Tree ()
{
for( Node* n : _nodes) delete n;
}
Node* Tree::getNode ( Contact* contact )
{
for ( Node* n : _nodes ) {
if (n->contact() == contact) return n;
}
return nullptr;
}
void Tree::addNode ( Node* node )
{
if (find(_nodes.begin(), _nodes.end(), node) == _nodes.end()) {
setReached( node->contact() );
_nodes.push_back( node );
}
}
void Tree::markNodeAfter ( Node *ni )
{
if (not ni) return;
ni->setAp( 1 );
for ( Node* child : ni->childs() ) {
markNodeAfter( child );
}
}
void Tree::getBranch ( Contact* contact )
{
for ( Node* n : _nodes ) {
n->setLabel(0);
}
Node *ni = getNode( contact );
ni->setLabel(1);
while ( ni->parent() ) {
ni->parent()->setLabel(1);
ni = ni->parent();
}
}
Delay* Tree::computeElmoreDelay ( RoutingPad* rp )
{
if (not rp) {
cerr << Error( "Tree::computeDelay(): Sink RoutingPad argument is NULL." ) << endl;
return nullptr;
}
Delay* delay = _elmore->getDelay( rp );
if (not delay) {
cerr << Error( "Tree::computeDelay(): No delay for %s, aborting."
, getString(rp).c_str() ) << endl;
return nullptr;
}
Contact* sink = nullptr;
for ( Component* component : rp->getSlaveComponents() ) {
Contact* contact = dynamic_cast<Contact*>( component );
if (contact) {
sink = contact;
break;
}
}
if (not sink) {
cerr << Error( "Tree::computeDelay(): No Contact anchored on RoutingPad, aborting.\n"
" (on %s)"
, getString(rp).c_str()
) << endl;
return nullptr;
}
Hook* masterHook = sink->getAnchorHook()->getMasterHook();
if (masterHook) {
RoutingPad* myrp = dynamic_cast<RoutingPad*>( masterHook->getComponent() );
cdebug_log(199,0) << " Look back=" << myrp << endl;
}
cdebug_log(199,1) << "Tree::computeDelay()" << endl;
cdebug_log(199,0) << " rp=" << rp << endl;
cdebug_log(199,0) << " sink=" << sink << endl;
getBranch( sink );
Node* ni = getNode( sink );
markNodeAfter( ni );
ni->setAp( 0 );
// Compute Rt of all nodes
for ( size_t k = 0; k < _nodes.size(); k++ ) {
if (k == 0)
_nodes[k]->setRt( _nodes[k]->R() );
else {
if (_nodes[k]->ap() == 0) {
if (_nodes[k]->label() == 1) {
_nodes[k]->setRt( _nodes[k]->parent()->Rt() + _nodes[k]->R() );
} else {
_nodes[k]->setRt( _nodes[k]->parent()->Rt() );
}
} else {
_nodes[k]->setRt( ni->Rt() );
}
}
}
// Compute Elmore delay time
delay->setDelay( 0.0 );
for ( size_t k = 0; k < _nodes.size(); k++ ) {
delay->incDelay( (_nodes[k]->Rt()) * (_nodes[k]->C()) );
}
return delay;
}
void Tree::printNode ( ostream& os, Node* node, size_t depth )
{
string indent ( depth*2, ' ');
os << indent << node->contact() << " R=" << node->R() << " C=" << node->C() << endl;
for ( Node* child : node->childs() ) {
printNode( os, child, depth+1 );
}
}
void Tree::print ( ostream& os )
{
os << "Elmore Tree of " << _nodes[0]->contact()->getNet() << endl;
os << " Tree has " << _nodes.size() << " nodes :" << endl;
printNode( os, _nodes[0], 0 );
}
string Tree::_getTypeName () const
{ return "Seabreeze::Tree"; }
string Tree::_getString () const
{
string s = "<" + _getTypeName() + ">";
return s;
}
Record* Tree::_getRecord () const
{
Record* record = new Record ( _getString() );
if (record != nullptr) {
record->add( getSlot("_nodes" , &_nodes ) );
record->add( getSlot("_reacheds", &_reacheds) );
}
return record;
}
} // Seabreeze namespace.

View File

@ -0,0 +1,64 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./seabreeze/Configuration.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <string>
#include <vector>
#include <hurricane/DbU.h>
namespace Seabreeze {
using std::string;
using Hurricane::Record;
using Hurricane::Name;
using Hurricane::Layer;
using Hurricane::DbU;
using Hurricane::Contact;
using Hurricane::Segment;
//------------------------------------------------------------------------
// Class : "Seabreeze::Configuration"
class Configuration {
public :
Configuration ();
Configuration ( const Configuration& );
virtual ~Configuration ();
virtual Configuration* clone () const;
inline double getRct () const;
inline double getRsm () const;
inline double getCsm () const;
string _getTypeName () const;
string _getString () const;
Record* _getRecord () const;
protected :
// Attributes
double _Rct;
double _Rsm;
double _Csm;
private :
Configuration& operator= ( const Configuration& ) = delete;
};
inline double Configuration::getRct () const { return _Rct; }
inline double Configuration::getRsm () const { return _Rsm; }
inline double Configuration::getCsm () const { return _Csm; }
} // Seabreeze namespace.
INSPECTOR_P_SUPPORT(Seabreeze::Configuration);

View File

@ -0,0 +1,64 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./seabreeze/Delay.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <map>
#include <iostream>
#include "hurricane/RoutingPad.h"
namespace Seabreeze {
using Hurricane::Record;
using Hurricane::DBo;
using Hurricane::RoutingPad;
class Elmore;
//---------------------------------------------------------
// Class : Seabreeze::Delay
class Delay {
public:
Delay ( Elmore*, RoutingPad* );
~Delay ();
inline Elmore* getElmore () const;
inline RoutingPad* getSink () const;
inline double getDelay () const;
inline void setDelay ( double );
inline void incDelay ( double );
std::string _getTypeName () const;
std::string _getString () const;
Record* _getRecord () const;
private:
Elmore* _elmore;
RoutingPad* _sink;
double _delay;
};
inline Elmore* Delay::getElmore () const { return _elmore; }
inline RoutingPad* Delay::getSink () const { return _sink; }
inline double Delay::getDelay () const { return _delay; }
inline void Delay::setDelay ( double delay ) { _delay = delay; }
inline void Delay::incDelay ( double delay ) { _delay += delay; }
} // Seabreeze namespace.
INSPECTOR_P_SUPPORT(Seabreeze::Delay);

View File

@ -0,0 +1,149 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./seabreeze/Elmore.cpp" |
// +-----------------------------------------------------------------+
#include <string>
#include <vector>
#include <set>
#include "hurricane/Property.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Contact.h"
#include "hurricane/Segment.h"
#include "Configuration.h"
#include "Tree.h"
#include "Delay.h"
namespace Hurricane {
class Net;
class Instance;
}
namespace Seabreeze {
using Hurricane::Name;
using Hurricane::DBo;
using Hurricane::Net;
using Hurricane::Cell;
using Hurricane::RoutingPad;
using Hurricane::Contact;
using Hurricane::Instance;
using Hurricane::Segment;
using Hurricane::PrivateProperty;
class SeabreezeEngine;
class ElmoreProperty;
//----------------------------------------------------------
// Class : Seabreeze::Elmore
class Elmore {
friend class ElmoreProperty;
public:
Elmore ( Net* );
~Elmore ();
inline SeabreezeEngine* getSeabreeze () const;
const Configuration* getConfiguration () const;
inline Net* getNet () const;
inline RoutingPad* getDriver () const;
Delay* getDelay ( RoutingPad* ) const;
inline const std::vector<Delay*>&
getDelays () const;
void buildTree ();
void buildFromNode ( Node* source, Segment* );
Contact* buildBranch ( double* R, double* C, Contact* contact );
void setRC ( double* R, double* C, Contact* , Segment* );
inline Tree* getTree ();
void setup ();
Delay* delayElmore ( RoutingPad* );
void toTree ( std::ostream& ) const;
inline void setSeabreeze ( SeabreezeEngine* );
Record* _getRecord () const;
std::string _getString () const;
std::string _getTypeName () const;
private:
private:
SeabreezeEngine* _seabreeze;
Net* _net;
RoutingPad* _driver;
Tree* _tree;
std::vector<Delay*> _delays;
};
inline SeabreezeEngine* Elmore::getSeabreeze () const { return _seabreeze; }
inline Net* Elmore::getNet () const { return _net; }
inline RoutingPad* Elmore::getDriver () const { return _driver; }
inline Tree* Elmore::getTree () { return _tree; }
inline void Elmore::setSeabreeze ( SeabreezeEngine* seabreeze ) { _seabreeze = seabreeze; }
inline const std::vector<Delay*>& Elmore::getDelays () const { return _delays; }
//---------------------------------------------------------
// Class : Seabreeze::ElmoreProperty
class ElmoreProperty : public Hurricane::PrivateProperty {
friend class ElmoreExtension;
private:
static Name _name;
public:
static ElmoreProperty* create ( Net* net );
static Name staticGetName ();
Name getName () const;
inline Elmore* getElmore ();
virtual string _getTypeName () const;
virtual Record* _getRecord () const;
virtual std::string _getString () const;
protected:
Elmore _elmore;
protected:
ElmoreProperty ( Net* );
};
inline Elmore* ElmoreProperty::getElmore ()
{ return &_elmore; }
//---------------------------------------------------------
// Class : Seabreeze::ElmoreExtension
class ElmoreExtension {
public:
static Elmore* create ( Net* );
static Elmore* get ( Net* );
static inline Tree* getTree ( Net* );
static inline void toTree ( Net*, std::ostream& );
static void destroy ( Net* );
};
inline Tree* ElmoreExtension::getTree ( Net* net )
{
Elmore* elmore = get( net );
return (elmore) ? elmore->getTree() : nullptr;
}
inline void ElmoreExtension::toTree ( Net* net, std::ostream& os )
{
Elmore* elmore = get( net );
if (elmore) elmore->toTree( os );
}
} // Seabreeze Namespace
INSPECTOR_P_SUPPORT(Seabreeze::Elmore);
INSPECTOR_P_SUPPORT(Seabreeze::ElmoreProperty);

View File

@ -0,0 +1,83 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./seabreeze/Node.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <vector>
#include "hurricane/Contact.h"
namespace Seabreeze {
using Hurricane::Record;
using Hurricane::Contact;
//----------------------------------------------------------
// Class : Seabreeze::Node.
class Node {
public:
Node ();
Node ( Node* parent, Contact* );
~Node ();
inline double R () const;
inline double Rt () const;
inline double C () const;
inline int label () const;
inline int ap () const;
inline Contact* contact () const;
inline Node* parent () const;
inline const std::vector<Node*>& childs () const;
inline void addChild ( Node* );
inline void setLabel ( int );
inline void setAp ( int );
inline void setRt ( double );
inline void setR ( double );
inline void setC ( double );
Record* _getRecord () const;
std::string _getString () const;
std::string _getTypeName () const;
private :
double _R;
double _Rt;
double _C;
Node* _parent;
std::vector<Node*> _childs;
Contact* _contact;
int _label;
int _ap;
};
inline double Node::R () const { return _R; }
inline double Node::Rt () const { return _Rt; }
inline double Node::C () const { return _C; }
inline int Node::label () const { return _label; }
inline int Node::ap () const { return _ap; }
inline Contact* Node::contact () const { return _contact; }
inline Node* Node::parent () const { return _parent; }
inline const std::vector<Node*>& Node::childs () const { return _childs; }
inline void Node::addChild ( Node* child ) { _childs.push_back( child ); }
inline void Node::setLabel ( int label ) { _label = label; }
inline void Node::setAp ( int ap ) { _ap = ap; }
inline void Node::setRt ( double rt ) { _Rt = rt; }
inline void Node::setR ( double r ) { _R = r; }
inline void Node::setC ( double c ) { _C = c; }
} // Seabreeze namespace;
INSPECTOR_P_SUPPORT(Seabreeze::Node);

View File

@ -0,0 +1,42 @@
#ifndef PY_SEABREEZE_ENGINE_H
#define PY_SEABREEZE_ENGINE_H
#include "hurricane/isobar/PyHurricane.h"
#include "crlcore/PyToolEngine.h"
#include "seabreeze/SeabreezeEngine.h"
namespace Seabreeze {
extern "C" {
// -------------------------------------------------------------------
// Python Object : "PySeabreezeEngine".
typedef struct {
CRL::PyToolEngine _baseObject;
} PySeabreezeEngine;
// -------------------------------------------------------------------
// Functions & Types exported to "PySeabreeze.ccp".
extern PyTypeObject PyTypeSeabreezeEngine;
extern PyMethodDef PySeabreezeEngine_Methods[];
extern PyObject* PySeabreezeEngine_Link ( Seabreeze::SeabreezeEngine* );
extern void PySeabreezeEngine_LinkPyType ();
extern void PySeabreezeEngine_postModuleInit ();
#define IsPySeabreezeEngine(v) ( (v)->ob_type == &PyTypeSeabreezeEngine )
#define PYSEABREEZEENGINE(v) ( (PySeabreezeEngine*)(v) )
#define PYSEABREEZEENGINE_O(v) ( PYSEABREEZEENGINE(v)->_baseObject._object )
} // extern "C".
} // Tutorial namespace.
#endif // PY_SEABREEZE_ENGINE_H

View File

@ -0,0 +1,94 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./seabreeze/SeabreezeEngine.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <string>
#include <iostream>
#include "hurricane/Name.h"
#include "hurricane/viewer/CellViewer.h"
#include "hurricane/RoutingPad.h"
namespace Hurricane {
class Net;
class Cell;
}
#include "crlcore/ToolEngine.h"
#include "seabreeze/Configuration.h"
namespace Seabreeze {
using Hurricane::Record;
using Hurricane::Name;
using Hurricane::Net;
using Hurricane::Cell;
using Hurricane::CellViewer;
using Hurricane::RoutingPad;
using CRL::ToolEngine;
//----------------------------------------------------------
// Class : "Seabreeze::SeabreezeEngine"
class SeabreezeEngine : public ToolEngine {
public :
typedef ToolEngine Super;
public :
static const Name& staticGetName ();
static SeabreezeEngine* create ( Cell* );
static SeabreezeEngine* get ( const Cell* );
public :
inline CellViewer* getViewer () const;
inline ToolEngine* base ();
virtual const Name& getName () const;
inline const Configuration* getConfiguration () const;
inline double getRct () const;
inline double getRsm () const;
inline double getCsm () const;
inline void setViewer ( CellViewer* );
virtual Record* _getRecord () const;
virtual std::string _getString () const;
virtual std::string _getTypeName () const;
virtual void buildElmore ( Net* net );
protected :
SeabreezeEngine ( Cell* );
virtual ~SeabreezeEngine ();
virtual void _postCreate ();
virtual void _preDestroy ();
private :
SeabreezeEngine ( const SeabreezeEngine& ) = delete;
SeabreezeEngine& operator= ( const SeabreezeEngine& ) = delete;
private :
// Attributes.
static Name _toolName;
protected :
Configuration* _configuration;
CellViewer* _viewer;
};
// Inline Functions.
inline ToolEngine* SeabreezeEngine::base () { return static_cast<ToolEngine*>(this); }
inline const Configuration* SeabreezeEngine::getConfiguration () const { return _configuration; }
inline double SeabreezeEngine::getRct () const { return getConfiguration()->getRct(); }
inline double SeabreezeEngine::getRsm () const { return getConfiguration()->getRsm(); }
inline double SeabreezeEngine::getCsm () const { return getConfiguration()->getCsm(); }
inline CellViewer* SeabreezeEngine::getViewer () const { return _viewer; }
inline void SeabreezeEngine::setViewer ( CellViewer* viewer ) { _viewer = viewer; }
} // Seabreeze namespace.
INSPECTOR_P_SUPPORT(Seabreeze::SeabreezeEngine);

View File

@ -0,0 +1,77 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./seabreeze/Tree.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <set>
#include <vector>
#include <iostream>
#include "hurricane/RoutingPad.h"
namespace Seabreeze {
using Hurricane::Record;
using Hurricane::DBo;
using Hurricane::Contact;
using Hurricane::RoutingPad;
class Node;
class Delay;
class Elmore;
//---------------------------------------------------------
// Class : Seabreeze::Tree.
class Tree {
public:
typedef std::set<Contact*,DBo::CompareById> ContactSet;
public:
Tree ( Elmore* );
~Tree ();
inline bool isReached ( Contact* ) const;
inline Elmore* getElmore () const;
inline size_t getN ();
Node* getNode ( Contact* );
inline const std::vector<Node*>& getNodeList () const;
inline void setReached ( Contact* );
void addNode ( Node* );
void markNodeAfter ( Node* );
void getBranch ( Contact* );
Delay* computeElmoreDelay ( RoutingPad* );
void printNode ( std::ostream& , Node* , size_t depth );
void print ( std::ostream& );
Record* _getRecord () const;
std::string _getString () const;
std::string _getTypeName () const;
private:
Elmore* _elmore;
std::vector<Node*> _nodes;
ContactSet _reacheds;
};
inline Elmore* Tree::getElmore () const { return _elmore; }
inline size_t Tree::getN () { return _nodes.size(); }
inline const std::vector<Node*>& Tree::getNodeList () const { return _nodes; }
inline void Tree::setReached ( Contact* contact ) { _reacheds.insert( contact ); }
inline bool Tree::isReached ( Contact* contact ) const { return _reacheds.count( contact ); }
} // Seabreeze namespace.
INSPECTOR_P_SUPPORT(Seabreeze::Tree);

143
Seabreeze/src/test.cpp Normal file
View File

@ -0,0 +1,143 @@
#include <iostream>
#include <cassert>
#include <fstream>
#include <string>
#include <sstream>
#include <stdlib.h>
#include <map>
#include <vector>
#include "Seabreeze/Node.h"
#include "Seabreeze/Tree.h"
using namespace std;
void build_tree(std::ifstream &file, Tree &t){
if(file.is_open()){
string line;
getline(file, line);
char RoC;
int lb1, lb2, vl; // possible labels of current node (can be parrent - current or current - child), value of R(or C)
vector<string> infos; // memoriser of infos taken from line
// Read file, line by line, get infomations
while(getline(file, line)){
stringstream tmp(line);
string word;
while(tmp >> word){
infos.push_back(word);
}
// Format is :
// infos[0] = RoC
// infos[1] = lb1 = label of current node
// infos[2] = lb2 = label of child node
// infos[3] = vl = value of RoC
char RoC = infos[0].at(0);
// infos[i>0] has type of string, so we need to turn it into integer using strtol
lb1 = strtol(infos[1].c_str(), NULL, 10);
lb2 = strtol(infos[2].c_str(), NULL, 10);
vl = strtol(infos[3].c_str(), NULL, 10);
infos.clear();
if(lb1 < 0 || lb2 == 0 || lb2 < -1){
// No node can have the root as a child
// A parent node cannot have label < 0 (<0 means -1, which is the ground)
cout << "Please check your configuration !" << endl;
cout << RoC << "\t" << lb1 << "\t" << lb2 << "\t" << vl << endl;
return;
}
else if(lb1 >= 0 && lb2 == -1){
// In this case, the branch is connected to "the ground"
// lb1 is the label of current node
// Check if current node is already created
if(RoC == 'R'){
cout << "Please check your configuration !" << endl;
cout << RoC << "\t" << lb1 << "\t" << lb2 << "\t" << vl << endl;
return;
}
//----------------------------------------------------------------------------------
// cout << "Node label : " << lb1 << " " << lb2 << " " << RoC << " " << vl << endl;
//----------------------------------------------------------------------------------
if(t.get_node(lb1)->label == -1)
t.get_node(lb1)->label = lb1;
if(RoC == 'C')
t.get_node(lb1)->C = vl;
//----------------------------------------------------------------------------------
// cout << "Node " << t.get_node(lb1).label << " -> " << lb2 << " C = " << t.get_node(lb1).C << endl << endl;
//----------------------------------------------------------------------------------
}
else if(lb1 >= 0 && lb2 > 0){
// lb1 is the label of parent node
// lb2 is the label of current node
//----------------------------------------------------------------------------------
// cout << "Node label : " << lb1 << " " << lb2 << " " << RoC << " " << vl << endl;
// cout << "Exist ? " << " n1 : " << t.get_node(lb1).label+1 << " n2 : " << t.get_node(lb2).label+1 << endl;
//----------------------------------------------------------------------------------
if(t.get_node(lb1)->label == -1)
t.get_node(lb1)->label = lb1;
if(t.get_node(lb2)->label == -1)
t.get_node(lb2)->label = lb2;
// Get the nodes
if(RoC == 'R')
t.get_node(lb2)->R = vl;
else if(RoC == 'C')
t.get_node(lb2)->C = vl;
//-----------------------------------------------------------------------------------
// cout << "Node : " << t.get_node(lb1).label << " -> " << t.get_node(lb2).label << " R = " << t.get_node(lb2).R << " C = " << t.get_node(lb2).C << endl;
//-----------------------------------------------------------------------------------
((t.get_node(lb1))->Ne).push_back(t.get_node(lb2));
((t.get_node(lb2))->Np) = t.get_node(lb1);
//-----------------------------------------------------------------------------------
// cout << "Check : " << t.get_node(lb2).Np->label << " -> " << t.get_node(lb2).label << " R = " << t.get_node(lb2).R << " C = " << t.get_node(lb2).C << endl;
//-----------------------------------------------------------------------------------
}
}
//-----------------------------------------------------------------------------------
// cout << "Double check !" << endl;
// for(int i = 1; i < t.get_N(); i++){
// cout << t.get_node(i).Np->label << " -> " << t.get_node(i).label << " R = " << t.get_node(i).R << " C = " << t.get_node(i).C << endl;
// }
//-----------------------------------------------------------------------------------
}
}
int main(int argc, char *argv[]){
if(argc < 4){
cout << "Usage : ./test <file name> <nodes number> <point index>" << endl
<< "Example : " << argv[0] << " data.txt 10 3" << endl;
return 0;
}
cout << "Testing with data from : " << argv[1] << endl;
ifstream f(argv[1]);
assert(f.is_open());
int num = strtol(argv[2], NULL, 10);
Tree t;
for(int i = 0; i < num; i++){
t.new_node();
}
build_tree(f, t);
filebuf fb;
fb.open ( "output.txt", ios::out );
ostream fout(&fb);
t.print(fout);
int idx = strtol(argv[3], NULL, 10);
int time = t.Delay_Elmore(idx);
cout << "Elmore delay time : " << time << endl;
fb.close();
return 0;
}

5
Seabreeze/test/data1.txt Normal file
View File

@ -0,0 +1,5 @@
R1 0 1 10
C1 1 -1 20
R2 1 2 30
C2 2 -1 10

15
Seabreeze/test/data2.txt Normal file
View File

@ -0,0 +1,15 @@
R1 0 1 10
C1 1 -1 15
R2 1 2 20
C2 2 -1 25
R3 1 3 30
C3 3 -1 35
R4 3 4 40
C4 4 -1 45
R5 3 5 50
C5 5 -1 55
R6 3 6 60
C6 6 -1 65
R7 5 7 70
C7 7 -1 75

1
Seabreeze/test/todo.txt Normal file
View File

@ -0,0 +1 @@
node : not only left and right children, can have multiple children

View File

@ -3,35 +3,34 @@
set(CMAKE_LEGACY_CYGWIN_WIN32 0) set(CMAKE_LEGACY_CYGWIN_WIN32 0)
project(ANABATIC) project(ANABATIC)
set(ignoreVariables "${BUILD_DOC} ${CMAKE_INSTALL_DIR}")
option(BUILD_DOC "Build the documentation (doxygen)" OFF) option(BUILD_DOC "Build the documentation (doxygen)" OFF)
option(CHECK_DATABASE "Run database in full check mode (very slow)" OFF) option(CHECK_DATABASE "Run database in full check mode (very slow)" OFF)
option(USE_LIBBFD "Link with BFD libraries to print stack traces" OFF)
cmake_minimum_required(VERSION 2.8.9) cmake_minimum_required(VERSION 3.16)
list(INSERT CMAKE_MODULE_PATH 0 "${DESTDIR}$ENV{CORIOLIS_TOP}/share/cmake/Modules/") list(INSERT CMAKE_MODULE_PATH 0 "${DESTDIR}$ENV{CORIOLIS_TOP}/share/cmake/Modules/")
find_package(Bootstrap REQUIRED) find_package(Bootstrap REQUIRED)
setup_project_paths(CORIOLIS) setup_project_paths(CORIOLIS)
set_cmake_policies() set_cmake_policies()
set_lib_link_mode()
setup_boost() setup_boost()
setup_qt() setup_qt()
setup_python()
find_package(PythonLibs 2 REQUIRED)
find_package(PythonSitePackages REQUIRED) find_package(PythonSitePackages REQUIRED)
find_package(VLSISAPD REQUIRED) find_package(FLUTE REQUIRED)
find_package(HURRICANE REQUIRED) find_package(HURRICANE REQUIRED)
find_package(CORIOLIS REQUIRED) find_package(CORIOLIS REQUIRED)
find_package(ETESIAN REQUIRED)
find_package(COLOQUINTE REQUIRED)
find_package(Doxygen)
add_subdirectory(src) add_subdirectory(src)
add_subdirectory(cmake_modules) add_subdirectory(cmake_modules)
#add_subdirectory(doc)
#if(BUILD_DOC)
# find_package(Doxygen)
# if(DOXYGEN_FOUND)
# add_subdirectory(doc)
# endif()
#endif()
if(CHECK_DATABASE) if(CHECK_DATABASE)
add_definitions(-DCHECK_DATABASE) add_definitions(-DCHECK_DATABASE)

View File

@ -6,7 +6,7 @@
# ANABATIC_LIBRARIES - The path to where the Coriolis library files are. # ANABATIC_LIBRARIES - The path to where the Coriolis library files are.
SET(ANABATIC_INCLUDE_PATH_DESCRIPTION "directory containing the Katabatic include files. E.g /usr/local/include/coriolis or /asim/coriolis/include/coriolis") SET(ANABATIC_INCLUDE_PATH_DESCRIPTION "directory containing the Katabatic include files. E.g /usr/local/include/coriolis2 or /asim/coriolis/include/coriolis2")
SET(ANABATIC_DIR_MESSAGE "Set the ANABATIC_INCLUDE_DIR cmake cache entry to the ${ANABATIC_INCLUDE_PATH_DESCRIPTION}") SET(ANABATIC_DIR_MESSAGE "Set the ANABATIC_INCLUDE_DIR cmake cache entry to the ${ANABATIC_INCLUDE_PATH_DESCRIPTION}")
@ -18,7 +18,7 @@ IF(UNIX)
FIND_PATH(ANABATIC_INCLUDE_PATH NAMES anabatic/AnabaticEngine.h PATHS FIND_PATH(ANABATIC_INCLUDE_PATH NAMES anabatic/AnabaticEngine.h PATHS
# Look in other places. # Look in other places.
${CORIOLIS_DIR_SEARCH} ${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES include/coriolis PATH_SUFFIXES include/coriolis2
# Help the user find it if we cannot. # Help the user find it if we cannot.
DOC "The ${ANABATIC_INCLUDE_PATH_DESCRIPTION}" DOC "The ${ANABATIC_INCLUDE_PATH_DESCRIPTION}"
) )
@ -26,7 +26,7 @@ IF(UNIX)
FIND_LIBRARY(ANABATIC_LIBRARY_PATH FIND_LIBRARY(ANABATIC_LIBRARY_PATH
NAMES anabatic NAMES anabatic
PATHS ${CORIOLIS_DIR_SEARCH} PATHS ${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES lib${LIB_SUFFIX} PATH_SUFFIXES lib64 lib
# Help the user find it if we cannot. # Help the user find it if we cannot.
DOC "The ${ANABATIC_INCLUDE_PATH_DESCRIPTION}" DOC "The ${ANABATIC_INCLUDE_PATH_DESCRIPTION}"
) )

346
anabatic/doc/NetBuilder.dox Normal file
View File

@ -0,0 +1,346 @@
// -*- C++ -*-
namespace Anabatic {
/*! \defgroup LoadGlobalRouting Global Routing Loading
* \brief Translation rules to build detailed routing from global
*
* This module documents how the global routing built by \c Knik is
* loaded into the \c Anabatic data-base. It is intented for developpers
* only.
*/
//! \addtogroup LoadGlobalRouting
//! \{
//! \enum LocalFunctionFlag
//! A set of flags for all functions of the LoadGlobalRouting module.
//! They can be combined to form the \e flags argument of functions.
//! the functions will ignore flags that are not intended to them.
//!
//! For \c HSmall, \c VSmall & \c Punctual see checkRoutingPadSize().
//! \var LocalFunctionFlag::NoFlags
//! A simple alias over zero to explicitly tell that no flag at all is
//! passed to the function.
//! \var LocalFunctionFlag::HAccess
//! The constructed topology will be accessed through an horizontal
//! segment. The absence of this flag tell that the access will be done
//! trough a vertical.
//! \var LocalFunctionFlag::VSmall
//! The RoutingPad vertically covers a very small number of access points,
//! so it is likely overconstrained for direct horizontal connexion.
//! \var LocalFunctionFlag::HSmall
//! The RoutingPad horizontally covers a very small number of access points,
//! so it is likely overconstrained for direct vertical connexion.
//! \var LocalFunctionFlag::Punctual
//! The RoutingPad covers only an access point in either direction.
//! \var LocalFunctionFlag::DoSourceContact
//! When creating Anabatic::AutoContactTerminal on non-punctual RoutingPad, this flag
//! request the creation of a contact <em>on the source point</em>.
//! \var LocalFunctionFlag::DoTargetContact
//! When creating Anabatic::AutoContactTerminal on non-punctual RoutingPad, this flag
//! request the creation of a contact <em>on the target point</em>.
//! \function uint64_t checkRoutingPadSize ( Component* rp );
//!
//! Look at the geometrical size of the Component and assess if
//! it's span is too narrow either horizontally or vertically.
//! Return a combination of flags indicating it's state:
//! - HSmall : less than 3 pitches in horizontal direction.
//! - VSmall : less than 3 pitches in vertical direction.
//! - Punctual : one pitch in either directions.
//!
//! The component can be a RoutingPad, a Vertical or an Horizontal.
//!
//! \image html checkRoutingPadSize.png "checkRoutingPadSize()"
/*! \class NetBuilder
*
* \brief Build the wiring for a Net inside a GCell (\b internal).
*
* As this class is called to initially construct the Anabatic wiring,
* it must build a \b connex wiring. That is without gaps in layer depth,
* because the topology restauration mechanism (AutoContact::updateTopology())
* of the AutoContact cannot work until all AutoSegments are revalidated at
* least once. The topology restauration work by creating doglegs which in turn,
* call the canonization, which needs all the caches to be up to date.
*/
//! \function void NetBuilder::doRp_AutoContacts ( GCell* gcell, Component* rp, AutoContact*& source, AutoContact*& target, uint64_t flags );
//! \param gcell The GCell into which create the AutoContact.
//! \param rp The Component we want to access.
//! \param source The AutoContact created on the \c source (\e returned).
//! \param target The AutoContact created on the \c target (\e returned).
//! \param flags Managed by this function:
//! - LocalFunctionFlag::DoSourceContact
//! - LocalFunctionFlag::DoTargetContact
//!
//! Create the AutoContact directly anchored on the Component (terminal).
//! Three cases are manageds:
//! -# <b>Ordinary (non-punctual) \c METAL1 terminal</b>: an AutoContactTerminal
//! is anchored on the RoutingPad.
//! -# <b>Punctual \c METAL1 terminal</b>, the access must never be blocked
//! by other routing. To ensure it, we create a fixed AutoSegment (anchored
//! on two AutoContactTerminal) to cover it. The \e normal AutoContactTerminal
//! is also created.
//! -# <b>non \c METAL1 terminal</b>, as for the punctual \c METAL1, a
//! fixed protection is added over the RoutingPad. If we access
//! horizontally a vertical RoutingPad or vertically an horizontal
//! one, an extra AutoContactTerminal is added (to allow is displacement
//! along the RoutingPad).
//!
//! To avoid creating a fixed protection over a RoutingPad multiple times,
//! the RoutingPad and it's associated protection is stored in a static
//! \c map : \c __routingPadAutoSegments.
//!
//! Conversely, because an AutoContactTerminal can only be connected to one
//! segment, each time this function is called a new terminal will be created
//! (or maybe two in case of non-punctual terminals). If only one AutoContact
//! is requested, it is created centered on the RoutingPad. The initial
//! position of AutoContact <em>do not prevent them to move afterwards</em>,
//! even those created on source/target on a non-punctual RoutingPad.
//!
//! \remark For clarity we describe the layer management of this function in term
//! of \c METAL, but it is the RoutingGauge depth which is actually used.
//!
//! \image html doRp_AutoContacts.png "doRp_AutoContacts()"
//! \function AutoContact* NetBuilder::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags );
//! \param gcell The GCell into which create the AutoContact.
//! \param rp The Component onto which anchor the access contact.
//! \param flags Relevant flags are:
//! - HAccess, the terminal is to be accessed through an horizontal
//! segment.
//! - VSmall, force the terminal to be considered as small in the
//! vertical direction.
//!
//! If \c HAccess is set, the Component is to be accessed trough an horizontal
//! segment. If unset, the access is done vertically.
//!
//! Create an AutoContact to access a Component (terminal). If the Component
//! is not to be accessed through an horizontal segment, and do not cover a
//! large span in the horizontal direction (flag \c VSmall), a local horizontal
//! AutoSegment is added to slacken the vertical constraints.
//!
//! \image html doRp_Access.png "doRp_Access()"
//! \function AutoContact* NetBuilder::doRp_AccessPad ( RoutingPad* rp, uint64_t flags );
//! \param rp The Component onto which anchor the access contact.
//! \param flags Relevant flags are:
//! - HAccess, the terminal is to be accessed through an horizontal
//! segment.
//! - VSmall, force the terminal to be considered as small in the
//! vertical direction.
//! \return A Anabatic::AutoContactTerminal .
//!
//! The Component \c rp is a RoutingPad which belongs to a pad cell. This case
//! occurs when we are routing a complete chip. This method build, from the
//! \c rp a stack of articulated punctual segments and contacts to reach the
//! default H/V routing layers (usually \c METAL2 & \c METAL3). This may be
//! needed when the pad terminal is in \c METAL5, for instance.
//!
//! The returned AutoContactTerminal is anchored on the last punctual segment
//! build.
//!
//! The GCell into which the AutoContactTerminal is created may be under the
//! pads area. However, it will be right on the border of the GCell.
//! The global router vertexes of GCell under the pad area are marked as
//! blocked so will never be used for routing.
//!
//! \remark The segments and contacts added to ensure the layer connexity are not
//! put into the Anabatic database. They are plain Hurricane objects, invisibles
//! from it.
//! \function void NetBuilder::doRp_StairCaseH ( GCell* gcell, Component* rp1, Component* rp2 );
//!
//! Build the wiring to connect to horizontal Component. Two cases:
//! - The Component are aligneds, then only a straight wire is created.
//! - They are \e not aligned, then a complete dogleg is created.
//!
//! \image html doRp_StairCaseH.png "doRp_StairCaseH()"
//! \function void NetBuilder::doRp_StairCaseV ( GCell* gcell, Component* rp1, Component* rp2 );
//!
//! Build the wiring to connect to vertical Components. Two cases:
//! - The Components are aligneds, then only a straight wire is created.
//! - They are \e not aligned, then a complete dogleg is created.
//!
//! \image html doRp_StairCaseV.png "doRp_StairCaseV()"
//! \function void NetBuilder::_do_xG_1Pad ();
//!
//! Construct the topology, when there is only global wires and one local
//! terminal, but coming from a Pad. As thoses connectors will always be
//! on one border of the GCell they can be considered as a kind of global.
//!
//! So this method mostly calls NetBuilder::doRp_AccessPad() to create
//! the AutoContactTerminal, then calls NetBuilder::_do_xG(), except
//! for straight lines which are managed directly.
//! \function void NetBuilder::_do_xG ();
//!
//! Construct the topology, when there is only global wires (no local terminals).
//!
//! Some topology are not handled because they must not be managed by this
//! function:
//! <ul>
//! <li>One global: nonsensical because there also must be a terminal.
//! <li>Two aligned globals: in that case we do a straight wire whithout
//! any AutoContact (handled by the source/target of the wire).
//! </ul>
//!
//! \image html _do_xG.png "_do_xG()"
//! \function void NetBuilder::_do_1G_1M1 ();
//!
//! Construct a topology where there is \e one global and one RoutingPad
//! in \c METAL1. The \c METAL1 is assumed to be vertical.
//!
//! \remark When accessing the RoutingPad through an horizontal global segment
//! and the vertical extension of the segment is small, the global is
//! still directly attached to the terminal, inducing a high constraint
//! on it. We left to job of slackening it to the router.
//!
//! \image html _do_1G_1M1.png "_do_1G_1M1()"
//! \function void NetBuilder::_do_1G_xM1 ();
//!
//! Construct a topology where there is \e one global and any number of
//! RoutingPad in \c METAL1. The \c METAL1 is assumed to be vertical.
//!
//! The RoutingPads are linked together two by two. If the horizontal
//! segments are not aligned by the router, part of the routage will be
//! done through the RoutingPad itself. The global incoming segment will
//! connected to the leftmost, rightmost or centermost RoutingPad according
//! from wich side it comes from.
//!
//! \image html _do_1G_xM1.png "_do_1G_xM1()"
//! \function void NetBuilder::_do_xG_1M1_1M2 ();
//!
//! Construct a topology where there is at least one global (and up to 4),
//! one \c METAL1 RoutingPad (assumed V) and one \c METAL2 RoutingPad (assumed H).
//!
//! In this topology, we want to try to reuse the \c METAL2 RoutingPad as a
//! feedtrough in the horizontal routage. Thus:
//! - The \c METAL1 and \c METAL2 RoutingPad are connected through a separate wiring.
//! - The south & west global wiring is attached to the leftmost contact of
//! the \c METAL2.
//! - The north & east global wiring is attached to the rightmost contact of
//! the \c METAL2.
//!
//! South/west and north/south can be build independantly. Depending on the number
//! of globals, they can consist of:
//! - Nothing (no south nor west).
//! - An AutoContact (west present).
//! - An horizontal plus a turn (south present).
//! - An horizontal plus a HTee (south & west present).
//!
//! \remark Not all configurations are represented below.
//!
//! \image html _do_xG_1M1_1M2.png "_do_xG_1M1_1M2()"
//! \function void NetBuilder::_do_xG_xM1_xM3 ();
//!
//! Construct a topology where there is at least one global (and up to 4),
//! at least one \c METAL1 RoutingPad (assumed V) and at least one \c METAL3
//! RoutingPad (assumed V).
//!
//! In this topology, we want to try to reuse the \c METAL3 RoutingPad as a
//! feedtrough in the vertical routage. Thus:
//! - The \c METAL1 and \c METAL3 RoutingPad are connected through a separate
//! wiring made of separate horizontals.
//! - The south-west global wiring is attached to the leftmost RoutingPad
//! if there isn't south or to the first \c METAL3 otherwise.
//! - The north-east global wiring is attached to the rightmost RoutingPad
//! if there isn't north or to the first \c METAL3 otherwise.
//!
//! South/west and north/south can be build independantly. Depending on the number
//! of globals, they can consist of:
//! - Nothing (no south nor west).
//! - An AutoContact on the leftmost RoutingPad (west present).
//! - An AutoContact on the first \c METAL3 (only south present).
//! - An AutoContact plus a vertical plus a VTee (south & west present).
//!
//! \image html _do_xG_xM1_xM3.png "_do_xG_xM1_xM3()"
//! \function void NetBuilder::_do_xG_xM2 ();
//!
//! Construct a topology where there is at least one global (and up to 4),
//! and any number of \c METAL2 RoutingPads (assumeds H).
//!
//! In this topology, we want to try to reuse the \c METAL2 RoutingPad as a
//! feedtrough in the horizontal routage. Thus:
//! - The RoutingPad are connecteds trough a separate staircase (or
//! straight wire if aligneds).
//! - The south-west global wiring is attached to the leftmost RoutingPad
//! if there isn't south or to the biggest horizontal RoutingPad otherwise.
//! - The north-east global wiring is attached to the rightmost RoutingPad
//! if there isn't south or to the biggest horizontal RoutingPad otherwise.
//!
//! \image html _do_xG_xM2.png "_do_xG_xM2()"
//! \function void NetBuilder::_do_1G_1M3 ();
//!
//! Construct a topology where there is one global and one \c METAL3 RoutingPad
//! (assumeds V).
//!
//! In this topology, we reuse the \c METAL3 RoutingPad as a feedtrough in the
//! vertical routage. Thus:
//! - If the global is either north or south, we directly connect to the
//! north end or south end of the RoutingPad. \red{The vertical global will}
//! \red{have no slack at all we assume that METAL3 terminals are only from}
//! \red{blocks and are aligneds vertically.}
//! - If the global is east or west \e and the RoutingPad is sufficiently
//! extended in the vertical direction, we connect an horizontal in the
//! normal way.
//! - If the global is not sufficiently extended, we add a turn to give some
//! slack to the global.
//!
//!
//! \image html _do_1G_1M3.png "_do_1G_1M3()"
//! \function void NetBuilder::_do_xG_xM3 ();
//!
//! Construct a topology where there at least one global and two \c METAL3 RoutingPad
//! (assumed V).
//!
//! In this topology, we reuse the \c METAL3 RoutingPad as a feedtrough in the
//! vertical routage. \red{We assume that the most likely relative position}
//! \red{of the RoutingPads is to be aligned vertically}.
//! Thus:
//! - All RoutingPads are linked two by two trough vertical staircases.
//! - The south-west global wiring is attached to the bottommost RoutingPad
//! (without vertical slack). If a misalignment is detected, then a
//! dogleg is added.
//! - The north-east global wiring is attached to the topmost RoutingPad
//! (without vertical slack).
//!
//! South/west and north/south can be build independantly. Depending on the number
//! of globals, they can consist of:
//! - Nothing (no south nor west).
//! - An sliding AutoContact on the bottommost RoutingPad (west present).
//! - An fixed AutoContact on the bottommost RoutingPad (only south present).
//! - An fixed AutoContact plus a vertical plus a VTee (south & west present).
//!
//! \image html _do_xG_xM3.png "_do_xG_xM3()"
//! \function void singleGCell ( AnabaticEngine* anbt, Net* net );
//!
//! All the RoutingPads of the net are concentrated under a single
//! GCell. This function assumes that all the terminals are in
//! \c METAL1 (vertical), and link them two by two by horizontal
//! wires.
//! \}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved // Copyright (c) UPMC 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -110,7 +110,7 @@ namespace Anabatic {
void AutoContact::_preDestroy () void AutoContact::_preDestroy ()
{ {
DebugSession::open( _contact->getNet(), 140, 150 ); DebugSession::open( _contact->getNet(), 145, 150 );
cdebug_log(145,0) << "AutoContact::_preDestroy() - <AutoContact id:" << _id << ">" << endl; cdebug_log(145,0) << "AutoContact::_preDestroy() - <AutoContact id:" << _id << ">" << endl;
@ -178,23 +178,45 @@ namespace Anabatic {
AutoHorizontal* AutoContact::getHorizontal2 () const { return NULL; } AutoHorizontal* AutoContact::getHorizontal2 () const { return NULL; }
AutoVertical* AutoContact::getVertical1 () const { return NULL; } AutoVertical* AutoContact::getVertical1 () const { return NULL; }
AutoVertical* AutoContact::getVertical2 () const { return NULL; } AutoVertical* AutoContact::getVertical2 () const { return NULL; }
bool AutoContact::isOnPin () const { return false; }
void AutoContact::getDepthSpan ( size_t& minDepth, size_t& maxDepth ) const void AutoContact::getDepthSpan ( size_t& minDepth, size_t& maxDepth ) const
{ {
cdebug_log(145,1) << "AutoContact::getDepthSpan() of " << this << endl;
minDepth = (size_t)-1; minDepth = (size_t)-1;
maxDepth = 0; maxDepth = 0;
Component* anchor = getAnchor (); Component* anchor = getAnchor ();
if (anchor) { if (anchor) {
cdebug_log(145,0) << "* Anchor depth: "
<< Session::getRoutingGauge()->getLayerDepth(anchor->getLayer())<< endl;
minDepth = std::min( minDepth, Session::getRoutingGauge()->getLayerDepth(anchor->getLayer()) ); minDepth = std::min( minDepth, Session::getRoutingGauge()->getLayerDepth(anchor->getLayer()) );
maxDepth = std::max( maxDepth, Session::getRoutingGauge()->getLayerDepth(anchor->getLayer()) ); maxDepth = std::max( maxDepth, Session::getRoutingGauge()->getLayerDepth(anchor->getLayer()) );
} }
for ( AutoSegment* segment : const_cast<AutoContact*>(this)->getAutoSegments() ) { for ( AutoSegment* segment : const_cast<AutoContact*>(this)->getAutoSegments() ) {
cdebug_log(145,0) << "* segment depth: "
<< Session::getRoutingGauge()->getLayerDepth(segment->getLayer())<< endl;
minDepth = std::min( minDepth, Session::getRoutingGauge()->getLayerDepth(segment->getLayer()) ); minDepth = std::min( minDepth, Session::getRoutingGauge()->getLayerDepth(segment->getLayer()) );
maxDepth = std::max( maxDepth, Session::getRoutingGauge()->getLayerDepth(segment->getLayer()) ); maxDepth = std::max( maxDepth, Session::getRoutingGauge()->getLayerDepth(segment->getLayer()) );
} }
cdebug_tabw(145,-1);
}
void AutoContact::updateLayer ()
{
size_t minDepth = (size_t)-1;
size_t maxDepth = 0;
getDepthSpan( minDepth, maxDepth );
setLayerAndWidth( maxDepth-minDepth, minDepth );
// if (minDepth == maxDepth)
// setLayer( Session::getRoutingGauge()->getRoutingLayer(minDepth) );
// else
// setLayer( Session::getRoutingGauge()->getContactLayer(minDepth) );
} }
@ -212,14 +234,17 @@ namespace Anabatic {
size_t depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer()); size_t depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer());
DbU::Unit length; DbU::Unit length;
if (segment->isLocal()) { if (segment->isLocal()) {
length = segment->getLength(); length = segment->getAnchoredLength();
lengths[depth] += length; lengths[depth] += length;
DbU::Unit sideLength = (segment->isHorizontal()) ? hSideLength : vSideLength; DbU::Unit sideLength = (segment->isHorizontal()) ? hSideLength : vSideLength;
if ( not segment->isUnbound() and (abs(length) > sideLength) ) if ( not segment->isUnbound() and (abs(length) > sideLength) )
cerr << Error("Suspicious length:%.2f of %s." cerr << Error( "AutoContact::getLength(): Suspicious length %s (> %s) of %s.\n"
,DbU::getValueString(length).c_str() " (on: %s)"
,getString(segment).c_str()) << endl; , DbU::getValueString(length).c_str()
, DbU::getValueString(sideLength).c_str()
, getString(segment).c_str()
, getString(this).c_str()) << endl;
} else { } else {
if (segment->isHorizontal()) { if (segment->isHorizontal()) {
if (isSourceHook) if (isSourceHook)
@ -274,10 +299,11 @@ namespace Anabatic {
void AutoContact::invalidate ( Flags flags ) void AutoContact::invalidate ( Flags flags )
{ {
if (flags & Flags::Topology ) setFlags( CntInvalidatedCache );
if (not isInvalidated()) { if (not isInvalidated()) {
cdebug_log(145,1) << "AutoContact::invalidate() - " << this << endl; cdebug_log(145,1) << "AutoContact::invalidate() - " << this << endl;
cdebug_log(145,0) << "flags:" << flags.asString(FlagsFunction) << endl;
setFlags( CntInvalidated ); setFlags( CntInvalidated );
if (flags & Flags::Topology ) setFlags( CntInvalidatedCache );
Session::invalidate( this ); Session::invalidate( this );
_invalidate( flags ); _invalidate( flags );
@ -455,11 +481,13 @@ namespace Anabatic {
void AutoContact::setConstraintBox ( const Box& box ) void AutoContact::setConstraintBox ( const Box& box )
{ {
cdebug_log(149,0) << "setConstraintBox() " << this << " " << getConstraintBox()
<< " from:" << box << endl;
setCBXMin ( box.getXMin() ); setCBXMin ( box.getXMin() );
setCBXMax ( box.getXMax() ); setCBXMax ( box.getXMax() );
setCBYMin ( box.getYMin() ); setCBYMin ( box.getYMin() );
setCBYMax ( box.getYMax() ); setCBYMax ( box.getYMax() );
cdebug_log(149,0) << "setConstraintBox() - " << this << " " << getConstraintBox() << endl; cdebug_log(149,0) << "setConstraintBox() " << this << " " << getConstraintBox() << endl;
cdebug_log(149,0) << "* " << _gcell << endl; cdebug_log(149,0) << "* " << _gcell << endl;
} }
@ -550,6 +578,30 @@ namespace Anabatic {
} }
void AutoContact::setLayerAndWidth ( size_t delta, size_t depth )
{
cdebug_log(145,1) << "AutoContact::setLayerAndWidth() " << this << endl;
cdebug_log(145,0) << "delta:" << delta << " depth:" << depth << endl;
if (delta == 0) {
setLayer( Session::getRoutingLayer(depth) );
if (Session::getDirection(depth) & Flags::Horizontal) {
setSizes( Session::getPWireWidth(depth)
, Session::getWireWidth (depth) );
} else {
setSizes( Session::getWireWidth (depth)
, Session::getPWireWidth(depth) );
}
} else {
setLayer( Session::getContactLayer(depth) );
setSizes( Session::getViaWidth (depth)
, Session::getViaWidth (depth) );
}
cdebug_tabw(145,-1);
}
AutoContact* AutoContact::createFrom ( Contact* hurricaneContact ) AutoContact* AutoContact::createFrom ( Contact* hurricaneContact )
{ {
AutoContact* autoContact = NULL; AutoContact* autoContact = NULL;
@ -627,6 +679,7 @@ namespace Anabatic {
//s.insert( 4, getString(_id) ); //s.insert( 4, getString(_id) );
s.insert( s.size()-1, (isFixed ())?" F":" -" ); s.insert( s.size()-1, (isFixed ())?" F":" -" );
s.insert( s.size()-1, (isTerminal ())? "T": "-" ); s.insert( s.size()-1, (isTerminal ())? "T": "-" );
s.insert( s.size()-1, (canDrag ())? "D": "-" );
s.insert( s.size()-1, (isHTee ())? "h": "-" ); s.insert( s.size()-1, (isHTee ())? "h": "-" );
s.insert( s.size()-1, (isVTee ())? "v": "-" ); s.insert( s.size()-1, (isVTee ())? "v": "-" );
s.insert( s.size()-1, (isInvalidated ())? "i": "-" ); s.insert( s.size()-1, (isInvalidated ())? "i": "-" );

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved // Copyright (c) UPMC 2012-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -91,8 +91,11 @@ namespace Anabatic {
} }
AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* ) const AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* from ) const
{ return NULL; } {
if ( (from == _horizontal1) or (from == _horizontal2) ) return _vertical1;
return NULL;
}
AutoSegment* AutoContactHTee::getSegment ( unsigned int index ) const AutoSegment* AutoContactHTee::getSegment ( unsigned int index ) const
@ -115,14 +118,15 @@ namespace Anabatic {
AutoVertical* AutoContactHTee::getVertical1 () const { return _vertical1; }; AutoVertical* AutoContactHTee::getVertical1 () const { return _vertical1; };
void AutoContactHTee::_invalidate ( Flags ) void AutoContactHTee::_invalidate ( Flags flags )
{ {
Flags flags = Flags::Propagate; flags |= Flags::Propagate;
if (_horizontal1 and _horizontal2) { if (_horizontal1 and _horizontal2) {
if (_horizontal1->isInvalidated() xor _horizontal2->isInvalidated()) if (_horizontal1->isInvalidated() xor _horizontal2->isInvalidated())
flags = Flags::NoFlags; flags.reset( Flags::Propagate );
} }
cdebug_log(145,0) << "flags:" << flags.asString(FlagsFunction) << endl;
if (_horizontal1) _horizontal1->invalidate( flags ); if (_horizontal1) _horizontal1->invalidate( flags );
if (_horizontal2) _horizontal2->invalidate( flags ); if (_horizontal2) _horizontal2->invalidate( flags );
if (_vertical1 ) _vertical1 ->invalidate(); if (_vertical1 ) _vertical1 ->invalidate();
@ -196,7 +200,7 @@ namespace Anabatic {
void AutoContactHTee::updateCache () void AutoContactHTee::updateCache ()
{ {
DebugSession::open( getNet(), 140, 150 ); DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl; cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
@ -245,7 +249,7 @@ namespace Anabatic {
void AutoContactHTee::updateGeometry () void AutoContactHTee::updateGeometry ()
{ {
DebugSession::open( getNet(), 140, 150 ); DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl; cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
@ -273,7 +277,7 @@ namespace Anabatic {
void AutoContactHTee::updateTopology () void AutoContactHTee::updateTopology ()
{ {
DebugSession::open( getNet(), 140, 150 ); DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl; cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
@ -305,10 +309,10 @@ namespace Anabatic {
if (depthH1 == depthH2) { if (depthH1 == depthH2) {
// Dogleg on the vertical. // Dogleg on the vertical.
switch ( delta ) { switch ( delta ) {
case 0: setLayer( rg->getRoutingLayer(minDepth) ); break; case 0:
case 1: setLayer( rg->getContactLayer(minDepth) ); break; case 1: setLayerAndWidth( delta, minDepth ); break;
default: default:
setLayer( rg->getContactLayer( depthH1 + ((depthH1==minDepth)?0:-1) ) ); setLayerAndWidth( delta, depthH1 + ((depthH1==minDepth)?0:-1) );
_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) ); _vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
break; break;
} }
@ -318,12 +322,12 @@ namespace Anabatic {
int deltaH2 = (int)depthH2 - (int)depthV1; int deltaH2 = (int)depthH2 - (int)depthV1;
if (std::abs(deltaH1) > std::abs(deltaH2)) { if (std::abs(deltaH1) > std::abs(deltaH2)) {
setLayer( rg->getContactLayer( depthH2 + ((depthH2<depthV1)?0:-1) ) ); setLayerAndWidth( 2, depthH2 + ((depthH2<depthV1)?0:-1) );
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) ); //_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
_horizontal1->makeDogleg(this); _horizontal1->makeDogleg(this);
cdebug_log(145,0) << "New h1:" << _horizontal1 << endl; cdebug_log(145,0) << "New h1:" << _horizontal1 << endl;
} else { } else {
setLayer( rg->getContactLayer( depthH1 + ((depthH1<depthV1)?0:-1) ) ); setLayerAndWidth( 2, depthH1 + ((depthH1<depthV1)?0:-1) );
//_horizontal2 = static_cast<AutoHorizontal*>( _horizontal2->makeDogleg(this) ); //_horizontal2 = static_cast<AutoHorizontal*>( _horizontal2->makeDogleg(this) );
_horizontal2->makeDogleg(this); _horizontal2->makeDogleg(this);
cdebug_log(145,0) << "New h2:" << _horizontal2 << endl; cdebug_log(145,0) << "New h2:" << _horizontal2 << endl;

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved // Copyright (c) UPMC 2012-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -29,6 +29,7 @@
#include "hurricane/RoutingPad.h" #include "hurricane/RoutingPad.h"
#include "hurricane/Vertical.h" #include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h" #include "hurricane/Horizontal.h"
#include "hurricane/Pin.h"
#include "hurricane/DebugSession.h" #include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h" #include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactTerminal.h" #include "anabatic/AutoContactTerminal.h"
@ -46,6 +47,8 @@ namespace Anabatic {
using Hurricane::DebugSession; using Hurricane::DebugSession;
using Hurricane::Transformation; using Hurricane::Transformation;
using Hurricane::Entity; using Hurricane::Entity;
using Hurricane::Occurrence;
using Hurricane::Pin;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -60,7 +63,7 @@ namespace Anabatic {
, DbU::Unit height , DbU::Unit height
) )
{ {
cdebug_log(145,1) << "AutoContactTerminal::create(... Point, ...)" << endl; cdebug_log(145,1) << "AutoContactTerminal::create(... Point, ...) " << endl;
cdebug_log(145,0) << "@" << point << endl; cdebug_log(145,0) << "@" << point << endl;
anchor->getBodyHook()->detach(); anchor->getBodyHook()->detach();
@ -85,7 +88,7 @@ namespace Anabatic {
, const DbU::Unit height , const DbU::Unit height
) )
{ {
cdebug_log(145,0) << "AutoContactTerminal::create(... x, y, ...)" << endl; cdebug_log(145,0) << "AutoContactTerminal::create(... x, y, ...) " << endl;
cdebug_log(145,0) << "@ x:" << DbU::getValueString(x) << " y:" << DbU::getValueString(y) << endl; cdebug_log(145,0) << "@ x:" << DbU::getValueString(x) << " y:" << DbU::getValueString(y) << endl;
_preCreate( gcell, anchor->getNet(), layer ); _preCreate( gcell, anchor->getNet(), layer );
@ -128,6 +131,13 @@ namespace Anabatic {
} }
bool AutoContactTerminal::isOnPin () const
{
RoutingPad* rp = dynamic_cast<RoutingPad*>( getAnchor() );
return (dynamic_cast<Pin*>(rp->getOccurrence().getEntity()) != NULL);
}
AutoSegment* AutoContactTerminal::getOpposite ( const AutoSegment* ) const AutoSegment* AutoContactTerminal::getOpposite ( const AutoSegment* ) const
{ return NULL; } { return NULL; }
@ -171,7 +181,34 @@ namespace Anabatic {
if (component == NULL) { if (component == NULL) {
cerr << Error( "%s is not anchored.", getString(this).c_str() ) << endl; cerr << Error( "%s is not anchored.", getString(this).c_str() ) << endl;
cdebug_tabw(145,-1); cdebug_tabw(145,-1);
return _gcell->getBoundingBox (); return _gcell->getBoundingBox();
}
RoutingLayerGauge* lg = Session::getLayerGauge( Session::getLayerDepth(component->getLayer()) );
DbU::Unit xborder = 0;
DbU::Unit yborder = 0;
const Layer* viaLayer = Session::getContactLayer( lg->getDepth() );
if (viaLayer) {
if (lg->isHorizontal() and (lg->getDepth() != 0)) {
xborder = Session::getViaWidth( lg->getDepth() )/2
+ viaLayer->getBottomEnclosure( Layer::EnclosureH );
} else {
yborder = Session::getViaWidth( lg->getDepth() )/2
+ viaLayer->getBottomEnclosure( Layer::EnclosureV );
xborder = Session::getViaWidth( lg->getDepth() )/2
+ viaLayer->getBottomEnclosure( Layer::EnclosureH );
if (Session::getRoutingGauge()->isSymbolic()) {
// SxLib bug: METAL1 terminal segments are 0.5 lambdas too shorts on
// their extremities. Should modificate all the standard cells layout...
// HARDCODED.
if (getString(Session::getRoutingGauge()->getName()).substr(0,6) == "msxlib")
yborder -= DbU::fromLambda( 1.0 );
else
yborder -= DbU::fromLambda( 0.5 );
}
}
} }
DbU::Unit xMin; DbU::Unit xMin;
@ -195,6 +232,42 @@ namespace Anabatic {
xMin = xMax xMin = xMax
= vertical->getTargetPosition().getX(); = vertical->getTargetPosition().getX();
} else if ( (routingPad = dynamic_cast<RoutingPad*>(component)) ) { } else if ( (routingPad = dynamic_cast<RoutingPad*>(component)) ) {
Occurrence occurrence = routingPad->getOccurrence();
Transformation transformation = occurrence.getPath().getTransformation();
Horizontal* horizontal = dynamic_cast<Horizontal*>( occurrence.getEntity() );
Vertical* vertical = dynamic_cast<Vertical* >( occurrence.getEntity() );
cdebug_log(145,0) << "Anchor: " << occurrence.getEntity() << endl;
cdebug_log(145,0) << "transf: " << transformation << endl;
if (horizontal or vertical) {
Box bb;
// Assume that transformation contains no rotations (for now).
if (horizontal) { bb = horizontal->getBoundingBox(); const_cast<AutoContactTerminal*>(this)->setFlags( CntOnHorizontal ); }
if (vertical) { bb = vertical ->getBoundingBox(); const_cast<AutoContactTerminal*>(this)->setFlags( CntOnVertical ); }
transformation.applyOn( bb );
cdebug_log(145,0) << "Shrink border x:" << DbU::getValueString(xborder)
<< " y:" << DbU::getValueString(yborder)
<< endl;
// HARDCODED.
if ( (Session::getRoutingGauge()->getName() == "sxlib")
and (bb.getWidth() == DbU::fromLambda(1.0)) ) {
bb.inflate( DbU::fromLambda(0.5), 0 );
}
bb.inflate( -xborder, -yborder );
xMin = bb.getXMin();
yMin = bb.getYMin();
xMax = bb.getXMax();
yMax = bb.getYMax();
} else {
xMin = xMax = component->getPosition().getX();
yMin = yMax = component->getPosition().getY();
}
#if FOR_SYMBOLIC_LAYERS
Entity* entity = routingPad->getOccurrence().getEntity(); Entity* entity = routingPad->getOccurrence().getEntity();
Transformation transf = routingPad->getOccurrence().getPath().getTransformation(); Transformation transf = routingPad->getOccurrence().getPath().getTransformation();
cdebug_log(145,0) << "Anchor: " << routingPad << endl; cdebug_log(145,0) << "Anchor: " << routingPad << endl;
@ -238,6 +311,7 @@ namespace Anabatic {
yMin = yMax = routingPad->getPosition().getY(); yMin = yMax = routingPad->getPosition().getY();
break; break;
} }
#endif
} else { } else {
xMin = xMax = component->getPosition().getX(); xMin = xMax = component->getPosition().getX();
yMin = yMax = component->getPosition().getY(); yMin = yMax = component->getPosition().getY();
@ -255,7 +329,7 @@ namespace Anabatic {
cdebug_log(145,0) << "| Using (y): " cdebug_log(145,0) << "| Using (y): "
<< DbU::getValueString(bb.getYMin()) << " " << DbU::getValueString(bb.getYMin()) << " "
<< DbU::getValueString(bb.getYMax()) << endl; << DbU::getValueString(bb.getYMax()) << " " << bb << endl;
cdebug_tabw(145,-1); cdebug_tabw(145,-1);
return bb; return bb;
@ -264,36 +338,57 @@ namespace Anabatic {
void AutoContactTerminal::_invalidate ( Flags flags ) void AutoContactTerminal::_invalidate ( Flags flags )
{ {
if (_segment) _segment->invalidate(); cdebug_log(145,0) << "flags:" << flags.asString(FlagsFunction) << endl;
if (_segment) _segment->invalidate( flags|Flags::Propagate );
} }
void AutoContactTerminal::cacheDetach ( AutoSegment* segment ) void AutoContactTerminal::cacheDetach ( AutoSegment* segment )
{ {
if (_segment == segment) { if (_segment == segment) {
//_segment->unsetFlags( AutoSegment::SegAxisSet );
_segment = NULL; _segment = NULL;
setFlags( CntInvalidatedCache ); setFlags( CntInvalidatedCache );
unsetFlags( CntDrag );
} }
} }
void AutoContactTerminal::cacheAttach ( AutoSegment* segment ) void AutoContactTerminal::cacheAttach ( AutoSegment* segment )
{ {
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::cacheAttach() " << this << endl;
if (_segment) { if (_segment) {
cerr << Bug( "%s::cacheAttach() On %s,\n" cerr << Bug( "%s::cacheAttach() On %s,\n"
" cache has not been cleared first, cancelled." " cache has not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str() , _getTypeName().c_str(), getString(this).c_str()
) << endl; ) << endl;
cdebug_tabw(145,-1);
DebugSession::close();
return; return;
} }
_segment = segment; _segment = segment;
unsetFlags( CntInvalidatedCache ); unsetFlags( CntInvalidatedCache );
if ( (dynamic_cast<AutoHorizontal*>(_segment) and (getFlags() & CntOnHorizontal))
or (dynamic_cast<AutoVertical*> (_segment) and (getFlags() & CntOnVertical )) ) {
_segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegAxisSet );
setFlags( CntDrag );
cdebug_log(145,0) << "Drag Contact/Segment set" << endl;
}
cdebug_log(145,0) << "Cached:" << _segment << endl;
cdebug_tabw(145,-1);
DebugSession::close();
} }
void AutoContactTerminal::updateCache () void AutoContactTerminal::updateCache ()
{ {
DebugSession::open( getNet(), 140, 150 ); DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl; cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
@ -311,13 +406,21 @@ namespace Anabatic {
if (horizontals[1] != NULL) ++count; if (horizontals[1] != NULL) ++count;
if (verticals [0] != NULL) ++count; if (verticals [0] != NULL) ++count;
if (verticals [1] != NULL) ++count; if (verticals [1] != NULL) ++count;
if (count > 1) { if (count != 1) {
showTopologyError( "Terminal has more than one segment." ); showTopologyError( "Terminal has not *exactly* one segment." );
} }
if (horizontals[0] != NULL ) { if (horizontals[0] != NULL ) {
_segment = Session::lookup( horizontals[0] ); _segment = Session::lookup( horizontals[0] );
if (getFlags() & CntOnHorizontal) {
setFlags( CntDrag );
_segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegFixedAxis );
}
} else { } else {
_segment = Session::lookup( verticals[0] ); _segment = Session::lookup( verticals[0] );
if (getFlags() & CntOnVertical) {
setFlags( CntDrag );
_segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegFixedAxis );
}
} }
if (_segment == NULL) { if (_segment == NULL) {
ostringstream os; ostringstream os;
@ -344,7 +447,7 @@ namespace Anabatic {
void AutoContactTerminal::updateGeometry () void AutoContactTerminal::updateGeometry ()
{ {
DebugSession::open( getNet(), 140, 150 ); DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl; cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
@ -396,9 +499,27 @@ namespace Anabatic {
cdebug_log(145,0) << "Contact for wide segment." << endl; cdebug_log(145,0) << "Contact for wide segment." << endl;
} }
if (canDrag()) {
AutoContact* opposite = _segment->getOppositeAnchor(this);
AutoSegment* perpandicular = opposite->getPerpandicular( _segment );
if (perpandicular) {
cdebug_log(145,0) << "Draging V interval ["
<< DbU::getValueString(getCBYMin()) << " "
<< DbU::getValueString(getCBYMax()) << "]" << endl;
DbU::Unit y = perpandicular->getAxis();
y = std::min( y, getCBYMax() );
y = std::max( y, getCBYMin() );
Point onGrid = Session::getNearestGridPoint( Point(getX(),y), getConstraintBox() );
setY( onGrid.getY() );
cdebug_log(145,0) << "Draging to Y @" << DbU::getValueString(y)
<< " pitched:" << DbU::getValueString(onGrid.getY())
<< " " << getConstraintBox() << endl;
}
}
if (not getUConstraints(Flags::Horizontal).contains(axis)) { if (not getUConstraints(Flags::Horizontal).contains(axis)) {
cdebug_log(145,0) << "Cached: " << _segment << endl; cdebug_log(145,0) << "Cached: " << _segment << endl;
message << "Terminal vertical segment X" << DbU::getValueString(axis) message << "Terminal vertical segment X " << DbU::getValueString(axis)
<< " axis is outside RoutingPad " << getUConstraints(Flags::Horizontal) << "."; << " axis is outside RoutingPad " << getUConstraints(Flags::Horizontal) << ".";
Flags flags = Flags::NoFlags; Flags flags = Flags::NoFlags;
@ -416,7 +537,7 @@ namespace Anabatic {
void AutoContactTerminal::updateTopology () void AutoContactTerminal::updateTopology ()
{ {
DebugSession::open( getNet(), 140, 150 ); DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl; cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
@ -441,11 +562,11 @@ namespace Anabatic {
if (delta > 1) { if (delta > 1) {
//_segment = _segment->makeDogleg( this ); //_segment = _segment->makeDogleg( this );
_segment->makeDogleg( this ); _segment->makeDogleg( this );
cdebug_log(145,0) << "Update seg: " << _segment << endl;
delta = abssub( anchorDepth, rg->getLayerDepth( _segment->getLayer() ) ); delta = abssub( anchorDepth, rg->getLayerDepth( _segment->getLayer() ) );
cdebug_log(145,0) << "Delta: " << delta << " Update seg: " << _segment << endl;
} }
else if (delta == 0) setLayer( rg->getRoutingLayer(anchorDepth) ); if (delta == 0) setLayerAndWidth( delta, anchorDepth );
else if (delta == 1) setLayer( rg->getContactLayer(std::min(anchorDepth,segmentDepth)) ); if (delta == 1) setLayerAndWidth( delta, std::min(anchorDepth,segmentDepth) );
} }
_segment->invalidate( this ); _segment->invalidate( this );

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved // Copyright (c) UPMC 2012-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -88,8 +88,17 @@ namespace Anabatic {
AutoSegment* AutoContactTurn::getPerpandicular ( const AutoSegment* reference ) const AutoSegment* AutoContactTurn::getPerpandicular ( const AutoSegment* reference ) const
{ {
cdebug_log(149,0) << _getTypeName() << "::getPerpandicular() " << this
<< " to:" << reference << endl;
cdebug_log(149,0) << "| _horizontal1:" << _horizontal1 << endl;
cdebug_log(149,0) << "| _vertical1 :" << _vertical1 << endl;
if (reference == _horizontal1) return _vertical1; if (reference == _horizontal1) return _vertical1;
if (reference == _vertical1 ) return _horizontal1; if (reference == _vertical1 ) return _horizontal1;
cdebug_log(149,0) << _getTypeName() << "::getPerpandicular() " << this
<< " to:" << reference << " failed." << endl;
return NULL; return NULL;
} }
@ -110,13 +119,16 @@ namespace Anabatic {
void AutoContactTurn::_invalidate ( Flags flags ) void AutoContactTurn::_invalidate ( Flags flags )
{ {
if (_horizontal1) _horizontal1->invalidate(); if (_horizontal1) _horizontal1->invalidate( flags|Flags::Propagate );
if (_vertical1 ) _vertical1 ->invalidate(); if (_vertical1 ) _vertical1 ->invalidate( flags|Flags::Propagate );
} }
void AutoContactTurn::cacheDetach ( AutoSegment* segment ) void AutoContactTurn::cacheDetach ( AutoSegment* segment )
{ {
cdebug_log(149,0) << _getTypeName() << "::cacheDetach() " << this
<< " from:" << segment << endl;
if (segment == _horizontal1) _horizontal1 = NULL; if (segment == _horizontal1) _horizontal1 = NULL;
else if (segment == _vertical1) _vertical1 = NULL; else if (segment == _vertical1) _vertical1 = NULL;
else return; else return;
@ -127,6 +139,9 @@ namespace Anabatic {
void AutoContactTurn::cacheAttach ( AutoSegment* segment ) void AutoContactTurn::cacheAttach ( AutoSegment* segment )
{ {
cdebug_log(149,0) << _getTypeName() << "::cacheAttach() " << this
<< " to:" << segment << endl;
if (segment->getDirection() == Flags::Horizontal) { if (segment->getDirection() == Flags::Horizontal) {
if (_horizontal1) { if (_horizontal1) {
cerr << Bug( "%s::cacheAttach() On %s,\n" cerr << Bug( "%s::cacheAttach() On %s,\n"
@ -154,7 +169,7 @@ namespace Anabatic {
void AutoContactTurn::updateCache () void AutoContactTurn::updateCache ()
{ {
DebugSession::open( getNet(), 140, 150 ); DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl; cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
@ -195,7 +210,7 @@ namespace Anabatic {
void AutoContactTurn::updateGeometry () void AutoContactTurn::updateGeometry ()
{ {
DebugSession::open( getNet(), 140, 150 ); DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl; cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
@ -223,7 +238,7 @@ namespace Anabatic {
void AutoContactTurn::updateTopology () void AutoContactTurn::updateTopology ()
{ {
DebugSession::open ( getNet(), 140, 150 ); DebugSession::open ( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl; cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
@ -239,7 +254,7 @@ namespace Anabatic {
RoutingGauge* rg = Session::getRoutingGauge(); RoutingGauge* rg = Session::getRoutingGauge();
size_t depthH1 = rg->getLayerDepth( getHorizontal1()->getLayer() ); size_t depthH1 = rg->getLayerDepth( getHorizontal1()->getLayer() );
size_t depthV1 = rg->getLayerDepth( getVertical1 ()->getLayer() ); size_t depthV1 = rg->getLayerDepth( getVertical1 ()->getLayer() );
size_t depthContact = (depthH1 < depthV1) ? depthH1 : depthH1-1; size_t depthContact = (depthH1 <= depthV1) ? depthH1 : depthH1-1;
size_t delta = abssub ( depthH1, depthV1 ); size_t delta = abssub ( depthH1, depthV1 );
unsetFlags( CntWeakTerminal ); unsetFlags( CntWeakTerminal );
@ -247,22 +262,25 @@ namespace Anabatic {
showTopologyError( "Sheared Turn, layer delta exceed 3." ); showTopologyError( "Sheared Turn, layer delta exceed 3." );
setFlags( CntBadTopology ); setFlags( CntBadTopology );
} else { } else {
if (delta == 3) { if (delta > 1) {
if (_horizontal1->isInvalidatedLayer()) { bool updateH1 = (_horizontal1->isInvalidatedLayer() and not _horizontal1->isNonPref())
or _vertical1->isNonPref();
if (updateH1) {
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) ); //_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
_horizontal1->makeDogleg(this); _horizontal1->makeDogleg(this);
depthH1 = rg->getLayerDepth( _horizontal1->getLayer() );
cdebug_log(145,0) << "Update h1: " << _horizontal1 << endl; cdebug_log(145,0) << "Update h1: " << _horizontal1 << endl;
} else /*if (_vertical1->isInvalidatedLayer())*/ { } else /*if (_vertical1->isInvalidatedLayer())*/ {
//_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) ); //_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
_vertical1->makeDogleg(this); _vertical1->makeDogleg(this);
depthV1 = rg->getLayerDepth( _vertical1->getLayer() );
cdebug_log(145,0) << "Update v1: " << _vertical1 << endl; cdebug_log(145,0) << "Update v1: " << _vertical1 << endl;
} }
delta = abssub ( depthH1, depthV1 ); depthH1 = rg->getLayerDepth( _horizontal1->getLayer() );
depthV1 = rg->getLayerDepth( _vertical1->getLayer() );
depthContact = (depthH1 <= depthV1) ? depthH1 : depthH1-1;
delta = abssub ( depthH1, depthV1 );
} }
setLayer ( (delta == 0) ? rg->getRoutingLayer(depthContact) : rg->getContactLayer(depthContact) ); setLayerAndWidth( delta, depthContact );
} }
_horizontal1->invalidate( this ); _horizontal1->invalidate( this );

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved // Copyright (c) UPMC 2012-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -91,8 +91,11 @@ namespace Anabatic {
} }
AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* ) const AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* from ) const
{ return NULL; } {
if ( (from == _vertical1) or (from == _vertical2) ) return _horizontal1;
return NULL;
}
AutoSegment* AutoContactVTee::getSegment ( unsigned int index ) const AutoSegment* AutoContactVTee::getSegment ( unsigned int index ) const
@ -111,12 +114,12 @@ namespace Anabatic {
AutoVertical* AutoContactVTee::getVertical2 () const { return _vertical2; }; AutoVertical* AutoContactVTee::getVertical2 () const { return _vertical2; };
void AutoContactVTee::_invalidate ( Flags ) void AutoContactVTee::_invalidate ( Flags flags )
{ {
Flags flags = Flags::Propagate; flags |= Flags::Propagate;
if (_vertical1 and _vertical2) { if (_vertical1 and _vertical2) {
if (_vertical1->isInvalidated() xor _vertical2->isInvalidated()) if (_vertical1->isInvalidated() xor _vertical2->isInvalidated())
flags = Flags::NoFlags; flags.reset( Flags::NoFlags );
} }
if (_vertical1 ) _vertical1 ->invalidate( flags ); if (_vertical1 ) _vertical1 ->invalidate( flags );
@ -166,7 +169,7 @@ namespace Anabatic {
void AutoContactVTee::updateCache () void AutoContactVTee::updateCache ()
{ {
DebugSession::open( getNet(), 140, 150 ); DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateCache() " << this << endl; cdebug_log(145,1) << "AutoContactVTee::updateCache() " << this << endl;
@ -212,7 +215,7 @@ namespace Anabatic {
void AutoContactVTee::updateGeometry () void AutoContactVTee::updateGeometry ()
{ {
DebugSession::open( getNet(), 140, 150 ); DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateGeometry() " << this << endl; cdebug_log(145,1) << "AutoContactVTee::updateGeometry() " << this << endl;
@ -240,7 +243,7 @@ namespace Anabatic {
void AutoContactVTee::updateTopology () void AutoContactVTee::updateTopology ()
{ {
DebugSession::open ( getNet(), 140, 150 ); DebugSession::open ( getNet(), 145, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateTopology() " << this << endl; cdebug_log(145,1) << "AutoContactVTee::updateTopology() " << this << endl;
@ -275,11 +278,11 @@ namespace Anabatic {
cdebug_log(145,0) << "depthV1 == depthV2 (" << depthV1 << ")" << endl; cdebug_log(145,0) << "depthV1 == depthV2 (" << depthV1 << ")" << endl;
// Dogleg on the horizontal. // Dogleg on the horizontal.
switch ( delta ) { switch ( delta ) {
case 0: setLayer( rg->getRoutingLayer(minDepth) ); break; case 0:
case 1: setLayer( rg->getContactLayer(minDepth) ); break; case 1: setLayerAndWidth( delta, minDepth ); break;
default: default:
cdebug_log(145,0) << "Restore connectivity: dogleg on h1." << endl; cdebug_log(145,0) << "Restore connectivity: dogleg on h1." << endl;
setLayer( rg->getContactLayer( depthV1 + ((depthV1==minDepth)?0:-1) ) ); setLayerAndWidth( delta, depthV1 + ((depthV1==minDepth)?0:-1) );
_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) ); _horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
break; break;
} }
@ -289,11 +292,11 @@ namespace Anabatic {
int deltaV2 = (int)depthV2 - (int)depthH1; int deltaV2 = (int)depthV2 - (int)depthH1;
if (std::abs(deltaV1) > std::abs(deltaV2)) { if (std::abs(deltaV1) > std::abs(deltaV2)) {
setLayer( rg->getContactLayer( depthV2 + ((depthV2<depthH1)?0:-1) ) ); setLayerAndWidth( 2, depthV2 + ((depthV2<depthH1)?0:-1) );
//_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) ); //_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
_vertical1->makeDogleg(this); _vertical1->makeDogleg(this);
} else { } else {
setLayer( rg->getContactLayer( depthV1 + ((depthV1<depthH1)?0:-1) ) ); setLayerAndWidth( 2, depthV1 + ((depthV1<depthH1)?0:-1) );
//_vertical2 = static_cast<AutoVertical*>( _vertical2->makeDogleg(this) ); //_vertical2 = static_cast<AutoVertical*>( _vertical2->makeDogleg(this) );
_vertical2->makeDogleg(this); _vertical2->makeDogleg(this);
} }

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved // Copyright (c) UPMC 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -14,17 +14,19 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#include <algorithm> #include <algorithm>
#include "hurricane/Bug.h" #include "hurricane/Bug.h"
#include "hurricane/Error.h" #include "hurricane/Error.h"
#include "hurricane/DebugSession.h" #include "hurricane/Warning.h"
#include "hurricane/RoutingPad.h" #include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h" #include "hurricane/ViaLayer.h"
#include "anabatic/Configuration.h" #include "hurricane/RoutingPad.h"
#include "anabatic/AutoContactTerminal.h" #include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactTurn.h" #include "anabatic/Configuration.h"
#include "anabatic/AutoHorizontal.h" #include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoVertical.h" #include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/AutoVertical.h"
namespace Anabatic { namespace Anabatic {
@ -32,9 +34,12 @@ namespace Anabatic {
using std::min; using std::min;
using std::max; using std::max;
using Hurricane::Error; using std::abs;
using Hurricane::Bug; using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::DebugSession; using Hurricane::DebugSession;
using Hurricane::ViaLayer;
using Hurricane::RoutingPad; using Hurricane::RoutingPad;
@ -45,13 +50,11 @@ namespace Anabatic {
Segment* AutoHorizontal::base () { return _horizontal; } Segment* AutoHorizontal::base () { return _horizontal; }
Segment* AutoHorizontal::base () const { return _horizontal; } Segment* AutoHorizontal::base () const { return _horizontal; }
Horizontal* AutoHorizontal::getHorizontal () { return _horizontal; } Horizontal* AutoHorizontal::getHorizontal () { return _horizontal; }
DbU::Unit AutoHorizontal::getSourceU () const { return _horizontal->getSourceX(); } DbU::Unit AutoHorizontal::getSourceU () const { return _horizontal->getSource()->getX(); }
DbU::Unit AutoHorizontal::getTargetU () const { return _horizontal->getTargetX(); } DbU::Unit AutoHorizontal::getTargetU () const { return _horizontal->getTarget()->getX(); }
DbU::Unit AutoHorizontal::getDuSource () const { return _horizontal->getDxSource(); } DbU::Unit AutoHorizontal::getDuSource () const { return _horizontal->getDxSource(); }
DbU::Unit AutoHorizontal::getDuTarget () const { return _horizontal->getDxTarget(); } DbU::Unit AutoHorizontal::getDuTarget () const { return _horizontal->getDxTarget(); }
Interval AutoHorizontal::getSpanU () const { return Interval(_horizontal->getSourceX(),_horizontal->getTargetX()); } Interval AutoHorizontal::getSpanU () const { return Interval(_horizontal->getSourceX(),_horizontal->getTargetX()); }
void AutoHorizontal::setDuSource ( DbU::Unit du ) { _horizontal->setDxSource(du); }
void AutoHorizontal::setDuTarget ( DbU::Unit du ) { _horizontal->setDxTarget(du); }
string AutoHorizontal::_getTypeName () const { return "AutoHorizontal"; } string AutoHorizontal::_getTypeName () const { return "AutoHorizontal"; }
@ -91,6 +94,14 @@ namespace Anabatic {
mergeNativeMax( gcell->getConstraintYMax() ); mergeNativeMax( gcell->getConstraintYMax() );
} }
} }
// if (getId() == 1518590) {
// cerr << "AutoHorizontal::_postCreate(): " << this << endl;
// cerr << "| Source contact:" << source << endl;
// cerr << "| Source GCell: " << getGCell() << endl;
// cerr << "| Target contact:" << target << endl;
// cerr << "| Target GCell: " << target->getGCell() << endl;
// }
} }
@ -120,6 +131,30 @@ namespace Anabatic {
} }
void AutoHorizontal::setDuSource ( DbU::Unit du )
{
_horizontal->setDxSource(du);
if (abs(du) > getPitch())
cerr << Warning( "AutoHorizontal::setDuSource(): Suspiciously big du=%s (should not exceed routing pitch %s)\n"
" On %s"
, DbU::getValueString(du).c_str()
, DbU::getValueString(getPitch()).c_str()
, getString(this).c_str() ) << endl;
}
void AutoHorizontal::setDuTarget ( DbU::Unit du )
{
_horizontal->setDxTarget(du);
if (abs(du) > getPitch())
cerr << Warning( "AutoHorizontal::setDuTarget(): Suspiciously big du=%s (should not exceed routing pitch %s)\n"
" On %s"
, DbU::getValueString(du).c_str()
, DbU::getValueString(getPitch()).c_str()
, getString(this).c_str() ) << endl;
}
Interval AutoHorizontal::getSourceConstraints ( Flags flags ) const Interval AutoHorizontal::getSourceConstraints ( Flags flags ) const
{ {
if (flags & Flags::NativeConstraints) { if (flags & Flags::NativeConstraints) {
@ -142,33 +177,58 @@ namespace Anabatic {
bool AutoHorizontal::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const bool AutoHorizontal::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const
{ {
cdebug_log(155,1) << "getConstraints() " << this << endl;
constraintMin = getNativeMin(); constraintMin = getNativeMin();
constraintMax = getNativeMax(); constraintMax = getNativeMax();
cdebug_log(144,0) << "Native constraints: [" cdebug_log(155,0) << "Native constraints: ["
<< DbU::getValueString(constraintMin) << ":" << DbU::getValueString(constraintMin) << ":"
<< DbU::getValueString(constraintMax) << "]" << DbU::getValueString(constraintMax) << "]"
<< endl; << endl;
constraintMin = std::max ( constraintMin, getAutoSource()->getCBYMin() ); constraintMin = std::max ( constraintMin, getAutoSource()->getCBYMin() );
constraintMax = std::min ( constraintMax, getAutoSource()->getCBYMax() ); constraintMax = std::min ( constraintMax, getAutoSource()->getCBYMax() );
cdebug_log(144,0) << "Merge with source constraints: [" cdebug_log(155,0) << "Merge with source constraints: ["
<< DbU::getValueString(getAutoSource()->getCBYMin()) << ":" << DbU::getValueString(getAutoSource()->getCBYMin()) << ":"
<< DbU::getValueString(getAutoSource()->getCBYMax()) << "]" << DbU::getValueString(getAutoSource()->getCBYMax()) << "]"
<< endl; << endl;
constraintMin = std::max ( constraintMin, getUserConstraints().getVMin() ); constraintMin = std::max ( constraintMin, getAutoTarget()->getCBYMin() );
constraintMax = std::min ( constraintMax, getUserConstraints().getVMax() ); constraintMax = std::min ( constraintMax, getAutoTarget()->getCBYMax() );
cdebug_log(144,0) << "Merge with user constraints: [" cdebug_log(155,0) << "Merge with target constraints: ["
<< DbU::getValueString(getUserConstraints().getVMin()) << ":" << DbU::getValueString(getAutoTarget()->getCBYMin()) << ":"
<< DbU::getValueString(getUserConstraints().getVMax()) << "]" << DbU::getValueString(getAutoTarget()->getCBYMax()) << "]"
<< endl; << endl;
cdebug_log(145,0) << "Resulting constraints: " << " [" Interval userConstraints = getUserConstraints();
if (not userConstraints.isEmpty()) {
constraintMin = std::max ( constraintMin, userConstraints.getVMin() );
constraintMax = std::min ( constraintMax, userConstraints.getVMax() );
cdebug_log(155,0) << "Merge with user constraints: ["
<< DbU::getValueString(userConstraints.getVMin()) << ":"
<< DbU::getValueString(userConstraints.getVMax()) << "]"
<< endl;
} else
cdebug_log(155,0) << "Empty user constraints" << endl;
cdebug_log(155,0) << "Resulting constraints: ["
<< DbU::getValueString(constraintMin) << ":" << DbU::getValueString(constraintMin) << ":"
<< DbU::getValueString(constraintMax) << "]" << DbU::getValueString(constraintMax) << "]"
<< endl; << endl;
if (constraintMin > constraintMax)
cerr << Error( "AutoHorizontal::getConstraints(): Invalid interval [%s : %s] -> [%d : %d]\n"
" on %s"
, DbU::getValueString(constraintMin).c_str()
, DbU::getValueString(constraintMax).c_str()
, constraintMin
, constraintMax
, getString(this).c_str()
) << endl;
cdebug_tabw(155,-1);
return true; return true;
} }
@ -177,13 +237,14 @@ namespace Anabatic {
{ return Flags::Horizontal; } { return Flags::Horizontal; }
size_t AutoHorizontal::getGCells ( vector<GCell*>& gcells ) const bool AutoHorizontal::getGCells ( vector<GCell*>& gcells ) const
{ {
vector<GCell*>().swap( gcells ); vector<GCell*>().swap( gcells );
DbU::Unit yprobe = getY(); bool success = true;
GCell* gcell = getAutoSource()->getGCell(); DbU::Unit yprobe = getY();
GCell* end = getAutoTarget()->getGCell(); GCell* gcell = getAutoSource()->getGCell();
GCell* end = getAutoTarget()->getGCell();
cdebug_log(144,0) << "yprobe: " << DbU::getValueString(yprobe) << endl; cdebug_log(144,0) << "yprobe: " << DbU::getValueString(yprobe) << endl;
@ -195,20 +256,23 @@ namespace Anabatic {
while ( gcell != end ) { while ( gcell != end ) {
gcell = gcell->getEast( yprobe ); gcell = gcell->getEast( yprobe );
if (not gcell) { if (not gcell) {
cerr << Error( "AutoHorizontal::getGCells() : NULL GCell under %s\n" success = false;
" begin:%s\n" if (not isCreated()) {
" end: %s" cerr << Error( "AutoHorizontal::getGCells() : NULL GCell under %s\n"
, getString(this).c_str() " begin:%s\n"
, getString(getAutoSource()->getGCell()).c_str() " end: %s"
, getString(getAutoTarget()->getGCell()).c_str() , getString(this).c_str()
) << endl; , getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
}
break; break;
} }
gcells.push_back( gcell ); gcells.push_back( gcell );
} }
return gcells.size(); return success;
} }
@ -216,24 +280,35 @@ namespace Anabatic {
{ {
cdebug_tabw(149,1); cdebug_tabw(149,1);
Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Vertical ); AutoContact* source = getAutoSource();
Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Vertical ); AutoContact* target = getAutoTarget();
Interval sourceConstraints = Interval(getAutoSource()->getCBYMin(),getAutoSource()->getCBYMax()); if (source->isOnPin() or target->isOnPin()) { cdebug_tabw(149,-1); return false; }
Interval targetConstraints = Interval(getAutoTarget()->getCBYMin(),getAutoTarget()->getCBYMax());
Interval sourceSide = source->getGCell()->getSide( Flags::Vertical );
Interval targetSide = target->getGCell()->getSide( Flags::Vertical );
Interval sourceConstraints = Interval(source->getCBYMin(),source->getCBYMax());
Interval targetConstraints = Interval(target->getCBYMin(),target->getCBYMax());
bool sourceGoStraight = source->getGCell()->isGoStraight();
bool targetGoStraight = target->getGCell()->isGoStraight();
// Expand by a tiny amount for the "contains" to work for sure. // Expand by a tiny amount for the "contains" to work for sure.
sourceConstraints.inflate( 1 ); sourceConstraints.inflate( 1 );
targetConstraints.inflate( 1 ); targetConstraints.inflate( 1 );
cdebug_log(149,0) << "source " << getAutoSource() << endl; cdebug_log(149,0) << "source " << source << endl;
cdebug_log(149,0) << "source constraints: " << sourceConstraints cdebug_log(149,0) << "source constraints: " << sourceConstraints
<< " " << DbU::getValueString(sourceConstraints.getSize()) << endl; << " " << DbU::getValueString(sourceConstraints.getSize()) << endl;
cdebug_log(149,0) << "target " << getAutoTarget() << endl; cdebug_log(149,0) << "target " << target << endl;
cdebug_log(149,0) << "target constraints: " << targetConstraints cdebug_log(149,0) << "target constraints: " << targetConstraints
<< " " << DbU::getValueString(targetConstraints.getSize()) << endl; << " " << DbU::getValueString(targetConstraints.getSize()) << endl;
if (not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; } if (not sourceGoStraight and not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; }
if (not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; } if (not targetGoStraight and not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; }
if (not isUnbreakable()) {
if (source->isTurn() and (source->getPerpandicular(this)->getLayer() == getLayer())) { cdebug_tabw(149,-1); return true; }
if (target->isTurn() and (target->getPerpandicular(this)->getLayer() == getLayer())) { cdebug_tabw(149,-1); return true; }
}
cdebug_tabw(149,-1); cdebug_tabw(149,-1);
return false; return false;
@ -249,30 +324,52 @@ namespace Anabatic {
const Configuration* configuration = Session::getConfiguration(); const Configuration* configuration = Session::getConfiguration();
const Layer* metal2 = configuration->getRoutingLayer( 1 ); const Layer* metal2 = configuration->getRoutingLayer( 1 );
bool success = false; bool success = false;
bool isMetal2Source = false; bool isMetal2Source = false;
bool isMetal2Target = false; bool isMetal2Target = false;
DbU::Unit height = 0; bool isNonPrefSource = false;
AutoContact* source = getAutoSource(); bool isNonPrefTarget = false;
AutoContact* target = getAutoTarget(); DbU::Unit height = 0;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
bool slackenSource = false;
bool slackenTarget = false;
if (source->isTerminal()) { if (source->isTerminal()) {
height = (static_cast<RoutingPad*>(source->getAnchor()))->getBoundingBox().getHeight(); height = (static_cast<RoutingPad*>(source->getAnchor()))->getBoundingBox().getHeight();
isMetal2Source = (source->getLayer() == metal2); isMetal2Source = (source->getLayer() == metal2);
slackenSource = true;
} }
if (target->isTerminal()) { if (target->isTerminal()) {
height = std::min( height, (static_cast<RoutingPad*>(target->getAnchor()))->getBoundingBox().getHeight() ); height = std::min( height, (static_cast<RoutingPad*>(target->getAnchor()))->getBoundingBox().getHeight() );
isMetal2Target = (target->getLayer() == metal2); isMetal2Target = (target->getLayer() == metal2);
slackenTarget = true;
}
if (source->isTurn() and (source->getPerpandicular(this)->getLayer() == getLayer())) {
isNonPrefSource = true;
slackenSource = true;
} }
if (height >= 4*getPitch()) { cdebug_log(149,0) << "target:" << target << endl;
if (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < 5*getPitch())) cdebug_log(149,0) << "target->getPerpandicular(this):" << target->getPerpandicular(this) << endl;
return false; if (target->isTurn() and (target->getPerpandicular(this)->getLayer() == getLayer())) {
isNonPrefTarget = true;
slackenTarget = true;
} }
cdebug_tabw(149,1); cdebug_tabw(149,1);
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl; cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
cdebug_log(149,0) << "test:" << (getLength() < 5*getPitch()) << endl; cdebug_log(149,0) << "test:" << (getAnchoredLength() < 5*getPitch()) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl; cdebug_log(149,0) << "length:" << DbU::getValueString(getAnchoredLength()) << endl;
if (height >= 4*getPitch()) {
if (not (_flags & (SegGlobal|SegWeakGlobal)) and (getAnchoredLength() < 5*getPitch())) {
cdebug_log(149,0) << "Too short terminal segment to slacken." << endl;
cdebug_tabw(149,-1);
return false;
}
}
int lowSlack = (flags & Flags::HalfSlacken) ? 3 : 10; int lowSlack = (flags & Flags::HalfSlacken) ? 3 : 10;
bool sourceSlackened = false; bool sourceSlackened = false;
@ -281,7 +378,7 @@ namespace Anabatic {
DbU::Unit targetPosition = getTargetPosition(); DbU::Unit targetPosition = getTargetPosition();
AutoSegment* parallel = this; AutoSegment* parallel = this;
if (source->isTerminal()) { if (slackenSource) {
Interval perpandConstraints = getAutoTarget()->getUConstraints(Flags::Horizontal); Interval perpandConstraints = getAutoTarget()->getUConstraints(Flags::Horizontal);
Interval constraints = source->getUConstraints (Flags::Vertical|Flags::NoGCellShrink); Interval constraints = source->getUConstraints (Flags::Vertical|Flags::NoGCellShrink);
Interval nativeConstraints = source->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink); Interval nativeConstraints = source->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink);
@ -293,7 +390,7 @@ namespace Anabatic {
<< " native slack:" << nativeSlack << endl; << " native slack:" << nativeSlack << endl;
cdebug_log(149,0) << "Perpand constraints on target: " << perpandConstraints << endl; cdebug_log(149,0) << "Perpand constraints on target: " << perpandConstraints << endl;
// Ugly: GCell's track number is hardwired. // Ugly: GCell's track number is hardwired.
if ((nativeSlack < lowSlack) or (nativeSlack - slack < 3)) { if (isNonPrefSource or (nativeSlack < lowSlack) or (nativeSlack - slack < 3)) {
cdebug_log(149,0) << "Slackening from Source: " << source << endl; cdebug_log(149,0) << "Slackening from Source: " << source << endl;
_makeDogleg( source->getGCell(), Flags::NoFlags ); _makeDogleg( source->getGCell(), Flags::NoFlags );
sourceSlackened = true; sourceSlackened = true;
@ -303,7 +400,7 @@ namespace Anabatic {
const vector<AutoSegment*>& doglegs = Session::getDoglegs(); const vector<AutoSegment*>& doglegs = Session::getDoglegs();
if (sourceSlackened and (doglegs.size() >= 2)) { if (sourceSlackened and (doglegs.size() >= 2)) {
cdebug_log(149,0) << "AutoHorizontal::_slacken(): Source @" << DbU::getValueString(getSourcePosition()) << endl; cdebug_log(149,0) << "Slackened from source @" << DbU::getValueString(getSourcePosition()) << endl;
doglegs[doglegs.size()-2]->setAxis( getSourcePosition() ); doglegs[doglegs.size()-2]->setAxis( getSourcePosition() );
success = true; success = true;
@ -321,7 +418,7 @@ namespace Anabatic {
if (parallel) target = parallel->getAutoTarget(); if (parallel) target = parallel->getAutoTarget();
if (target->isTerminal()) { if (slackenTarget) {
Interval constraints = target->getUConstraints (Flags::Vertical|Flags::NoGCellShrink); Interval constraints = target->getUConstraints (Flags::Vertical|Flags::NoGCellShrink);
Interval nativeConstraints = target->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink); Interval nativeConstraints = target->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink);
int slack = constraints.getSize() / getPitch(); int slack = constraints.getSize() / getPitch();
@ -331,7 +428,7 @@ namespace Anabatic {
cdebug_log(149,0) << "Target constraint: " << constraints cdebug_log(149,0) << "Target constraint: " << constraints
<< " slack:" << slack << " slack:" << slack
<< " native slack:" << nativeSlack << endl; << " native slack:" << nativeSlack << endl;
if ((nativeSlack < lowSlack) or (nativeSlack - slack < 3)) { if (isNonPrefTarget or (nativeSlack < lowSlack) or (nativeSlack - slack < 3)) {
cdebug_log(149,0) << "Slackening from Target: " << target << endl; cdebug_log(149,0) << "Slackening from Target: " << target << endl;
parallel->_makeDogleg( target->getGCell(), Flags::NoFlags ); parallel->_makeDogleg( target->getGCell(), Flags::NoFlags );
targetSlackened = true; targetSlackened = true;
@ -341,7 +438,15 @@ namespace Anabatic {
const vector<AutoSegment*>& doglegs = Session::getDoglegs(); const vector<AutoSegment*>& doglegs = Session::getDoglegs();
if (targetSlackened and (doglegs.size() >= 2)) { if (targetSlackened and (doglegs.size() >= 2)) {
cdebug_log(149,0) << "AutoHorizontal::_slacken(): Target @" << DbU::getValueString(targetPosition) << endl; GCell* targetGCell = target->getGCell();
Box constraintBox = target->getConstraintBox();
cdebug_log(149,0) << "slacken from Target @" << DbU::getValueString(targetPosition) << endl;
if (targetPosition >= targetGCell->getXMax()) {
cdebug_log(149,0) << "On the rigthmost track, adjust of one P-pitch to the left." << endl;
targetPosition -= getPPitch();
constraintBox.inflate( getPPitch(), 0, 0, 0 );
}
doglegs[doglegs.size()-2]->setAxis( targetPosition ); doglegs[doglegs.size()-2]->setAxis( targetPosition );
success = true; success = true;
@ -349,7 +454,7 @@ namespace Anabatic {
cdebug_log(149,0) << "Fixing on target terminal contact: " cdebug_log(149,0) << "Fixing on target terminal contact: "
<< doglegs[doglegs.size()-2]->getAutoTarget() << endl; << doglegs[doglegs.size()-2]->getAutoTarget() << endl;
//doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntFixed ); //doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntFixed );
doglegs[doglegs.size()-2]->getAutoTarget()->setConstraintBox( target->getConstraintBox() ); doglegs[doglegs.size()-2]->getAutoTarget()->setConstraintBox( constraintBox );
doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntUserNativeConstraints ); doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntUserNativeConstraints );
} }
} }
@ -406,9 +511,10 @@ namespace Anabatic {
void AutoHorizontal::updateOrient () void AutoHorizontal::updateOrient ()
{ {
if (_horizontal->getTargetX() < _horizontal->getSourceX()) { if (_horizontal->getTarget()->getX() < _horizontal->getSource()->getX()) {
cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl; cdebug_log(149,1) << "updateOrient() " << this << " (before S/T swap)" << endl;
_horizontal->invert(); _horizontal->invert();
cdebug_log(149,0) << "updateOrient() " << this << " (after S/T swap)" << endl;
uint64_t spinFlags = _flags & SegDepthSpin; uint64_t spinFlags = _flags & SegDepthSpin;
unsetFlags( SegDepthSpin ); unsetFlags( SegDepthSpin );
@ -426,14 +532,15 @@ namespace Anabatic {
unsetFlags( SegStrongTerminal ); unsetFlags( SegStrongTerminal );
if (terminalFlags & SegSourceTerminal) setFlags( SegTargetTerminal ); if (terminalFlags & SegSourceTerminal) setFlags( SegTargetTerminal );
if (terminalFlags & SegTargetTerminal) setFlags( SegSourceTerminal ); if (terminalFlags & SegTargetTerminal) setFlags( SegSourceTerminal );
cdebug_tabw(149,-1);
} }
} }
void AutoHorizontal::updatePositions () void AutoHorizontal::updatePositions ()
{ {
_sourcePosition = _horizontal->getSourceX() - getExtensionCap(); _sourcePosition = getSourceU() - getExtensionCap(Flags::Source);
_targetPosition = _horizontal->getTargetX() + getExtensionCap(); _targetPosition = getTargetU() + getExtensionCap(Flags::Target);
} }
@ -453,10 +560,13 @@ namespace Anabatic {
bool AutoHorizontal::checkPositions () const bool AutoHorizontal::checkPositions () const
{ {
bool coherency = true; bool coherency = true;
DbU::Unit sourcePosition = _horizontal->getSourceX() - getExtensionCap(); DbU::Unit sourcePosition = _horizontal->getSource()->getX() - getExtensionCap(Flags::Source);
DbU::Unit targetPosition = _horizontal->getTargetX() + getExtensionCap(); DbU::Unit targetPosition = _horizontal->getTarget()->getX() + getExtensionCap(Flags::Target);
if ( _sourcePosition != sourcePosition ) { if ( _sourcePosition != sourcePosition ) {
cerr << "extensionCap: " << DbU::getValueString(getExtensionCap(Flags::Source)) << endl;
cerr << "ppitch: " << DbU::getValueString(getPPitch()) << endl;
cerr << "via width: " << DbU::getValueString(Session::getViaWidth(getLayer())) << endl;
cerr << Error ( "%s\n Source position incoherency: " cerr << Error ( "%s\n Source position incoherency: "
"shadow: %s, real: %s." "shadow: %s, real: %s."
, _getString().c_str() , _getString().c_str()
@ -730,16 +840,18 @@ namespace Anabatic {
Flags AutoHorizontal::_makeDogleg ( GCell* doglegGCell, Flags flags ) Flags AutoHorizontal::_makeDogleg ( GCell* doglegGCell, Flags flags )
{ {
DebugSession::open( getNet(), 140, 150 ); DebugSession::open( getNet(), 145, 150 );
cdebug_log(149,0) << "AutoHorizontal::_makeDogleg(GCell*) in " << doglegGCell << endl; cdebug_log(149,0) << "AutoHorizontal::_makeDogleg(GCell*) in " << doglegGCell << endl;
cdebug_tabw(149,1); cdebug_tabw(149,1);
//Session::doglegReset(); //Session::doglegReset();
AutoContact* autoTarget = getAutoTarget(); AutoContact* autoTarget = getAutoTarget();
AutoContact* autoSource = getAutoSource(); AutoContact* autoSource = getAutoSource();
GCell* begin = autoSource->getGCell(); GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell(); GCell* end = autoTarget->getGCell();
if (not autoSource->canDrag()) unsetFlags( SegDrag );
DbU::Unit doglegAxis = (doglegGCell->getXMax() + doglegGCell->getXMin()) / 2; DbU::Unit doglegAxis = (doglegGCell->getXMax() + doglegGCell->getXMin()) / 2;
if (isLocal()) if (isLocal())
@ -759,10 +871,19 @@ namespace Anabatic {
} while ( gcell and (gcell != end) ); } while ( gcell and (gcell != end) );
} }
size_t depth = Session::getRoutingGauge()->getLayerDepth( _horizontal->getLayer() ); size_t depth = Session::getRoutingGauge()->getLayerDepth( _horizontal->getLayer() );
bool upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); bool upLayer = true;
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer( depth + ((upLayer)?0:-1) );
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer( depth + ((upLayer)?1:-1) ); if (Session::getRoutingGauge()->isTwoMetals()) {
upLayer = (not Session::getRoutingGauge()->isVH());
} else if (Session::getRoutingGauge()->isVH()) {
upLayer = (depth < 2);
} else {
upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
}
size_t doglegDepth = depth + ((upLayer)?1:-1);
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer( depth + ((upLayer)?0:-1) );
Session::dogleg( this ); Session::dogleg( this );
targetDetach(); targetDetach();
@ -771,7 +892,7 @@ namespace Anabatic {
AutoContact* dlContact1 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer ); AutoContact* dlContact1 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer );
AutoContact* dlContact2 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer ); AutoContact* dlContact2 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer );
AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Vertical ); AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Vertical );
segment1->setLayer( doglegLayer ); segment1->setLayer( doglegDepth );
segment1->_setAxis( doglegAxis ); segment1->_setAxis( doglegAxis );
segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned ); segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned );
@ -782,36 +903,61 @@ namespace Anabatic {
targetAttach( dlContact1 ); targetAttach( dlContact1 );
AutoSegment* segment2 = AutoSegment::create( dlContact2 , autoTarget, Flags::Horizontal ); AutoSegment* segment2 = AutoSegment::create( dlContact2 , autoTarget, Flags::Horizontal );
autoTarget->cacheAttach( segment2 ); autoTarget->cacheAttach( segment2 );
segment2->setLayer( getLayer() ); segment2->setLayer( depth );
segment2->_setAxis( getY() ); segment2->_setAxis( getY() );
segment2->setFlags( (isSlackened()?SegSlackened:0) ); segment2->setFlags( (isSlackened()?SegSlackened:0) );
Session::dogleg( segment2 ); Session::dogleg( segment2 );
if (autoSource->isTerminal()) { if (autoSource->isTerminal() and autoTarget->isTerminal()) {
segment1->setFlags( SegWeakTerminal1 ); dlContact1->setFlags ( CntWeakTerminal );
segment2->setFlags( SegWeakTerminal1 ); dlContact2->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
} else if (autoSource->isTerminal()) {
autoTarget->unsetFlags( CntWeakTerminal ); autoTarget->unsetFlags( CntWeakTerminal );
dlContact1->setFlags ( CntWeakTerminal ); dlContact1->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
dlContact1->migrateConstraintBox( autoTarget );
} else if (autoTarget->isTerminal()) { } else if (autoTarget->isTerminal()) {
unsetFlags( SegTargetTerminal ); unsetFlags( SegTargetTerminal );
setFlags( SegWeakTerminal1 ); setFlags( SegWeakTerminal1 );
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegTargetTerminal );
autoSource->unsetFlags( CntWeakTerminal ); autoSource->unsetFlags( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal ); dlContact2->setFlags ( CntWeakTerminal );
if (autoSource->getGCell() == doglegGCell) if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
dlContact2->migrateConstraintBox( autoSource ); } else if (isWeakTerminal()) {
} else if (isWeakTerminal()) {
segment1->setFlags( SegWeakTerminal1 ); segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 ); segment2->setFlags( SegWeakTerminal1 );
} }
// if (autoSource->isTerminal()) {
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegWeakTerminal1 );
// autoTarget->unsetFlags( CntWeakTerminal );
// dlContact1->setFlags ( CntWeakTerminal );
// if (autoTarget->getGCell() == doglegGCell)
// dlContact1->migrateConstraintBox( autoTarget );
// } else if (autoTarget->isTerminal()) {
// unsetFlags( SegTargetTerminal );
// setFlags( SegWeakTerminal1 );
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegTargetTerminal );
// autoSource->unsetFlags( CntWeakTerminal );
// dlContact2->setFlags ( CntWeakTerminal );
// if (autoSource->getGCell() == doglegGCell)
// dlContact2->migrateConstraintBox( autoSource );
// } else if (isWeakTerminal()) {
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegWeakTerminal1 );
// }
if (isAnalog()) { if (isAnalog()) {
segment1->setFlags( SegAnalog ); segment1->setFlags( SegAnalog );
segment2->setFlags( SegAnalog ); segment2->setFlags( SegAnalog );
} }
if (isNoMoveUp()) {
segment1->setFlags( SegNoMoveUp );
segment2->setFlags( SegNoMoveUp );
}
cdebug_log(149,0) << "Session::dogleg[x+1] perpand: " << segment1 << endl; cdebug_log(149,0) << "Session::dogleg[x+1] perpand: " << segment1 << endl;
cdebug_log(149,0) << "Session::dogleg[x+2] new paral: " << segment2 << endl; cdebug_log(149,0) << "Session::dogleg[x+2] new paral: " << segment2 << endl;
@ -827,6 +973,18 @@ namespace Anabatic {
updateNativeConstraints(); updateNativeConstraints();
segment2->updateNativeConstraints(); segment2->updateNativeConstraints();
if ( isLocal()) autoSource->setFlags( AutoContactFlag::CntVDogleg );
if (segment2->isLocal()) autoTarget->setFlags( AutoContactFlag::CntVDogleg );
if (autoTarget->canDrag() and not autoSource->canDrag()) {
if (not autoTarget->getGCell()->isDevice() and (segment1->getGCell() == autoTarget->getGCell())) {
Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Horizontal);
segment1->mergeUserConstraints( dragConstraints );
cdebug_log(149,0) << "Perpandicular has drag constraints: " << dragConstraints << endl;
}
}
cdebug_tabw(149,-1); cdebug_tabw(149,-1);
DebugSession::close(); DebugSession::close();

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved // Copyright (c) UPMC 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -93,14 +93,12 @@ namespace Anabatic {
bool AutoSegments_OnContact::Locator::isValid () const bool AutoSegments_OnContact::Locator::isValid () const
{ return !_hook; } { return _hook; }
void AutoSegments_OnContact::Locator::progress () void AutoSegments_OnContact::Locator::progress ()
{ {
cdebug_log(145,0) << "AutoSegments_OnContact::Locator::progress()" << endl; while (_hook) {
while (_hook and not _hook->isMaster()) {
_hook = _hook->getNextHook(); _hook = _hook->getNextHook();
_element = NULL; _element = NULL;
@ -108,7 +106,6 @@ namespace Anabatic {
Segment* segment = dynamic_cast<Segment*>( _hook->getComponent() ); Segment* segment = dynamic_cast<Segment*>( _hook->getComponent() );
if (segment) _element = Session::lookup( segment ); if (segment) _element = Session::lookup( segment );
if (not _element or (_element == _master)) continue; if (not _element or (_element == _master)) continue;
break; break;
@ -147,7 +144,7 @@ namespace Anabatic {
AutoSegments_OnRoutingPad::Locator::Locator ( RoutingPad* rp, const AutoContactTerminal* contact ) AutoSegments_OnRoutingPad::Locator::Locator ( RoutingPad* rp, const AutoContactTerminal* contact )
: AutoSegmentHL() : AutoSegmentHL()
, _elements ({NULL,NULL,NULL,NULL}) , _elements ({{NULL,NULL,NULL,NULL}})
, _index (0) , _index (0)
{ {
if (rp) { if (rp) {

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved // Copyright (c) UPMC 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -16,6 +16,8 @@
#include <algorithm> #include <algorithm>
#include "hurricane/Bug.h" #include "hurricane/Bug.h"
#include "hurricane/Warning.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/Vertical.h" #include "hurricane/Vertical.h"
#include "crlcore/RoutingGauge.h" #include "crlcore/RoutingGauge.h"
#include "anabatic/Configuration.h" #include "anabatic/Configuration.h"
@ -28,8 +30,11 @@ namespace Anabatic {
using std::min; using std::min;
using std::max; using std::max;
using Hurricane::Error; using std::abs;
using Hurricane::Bug; using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::ViaLayer;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -39,13 +44,11 @@ namespace Anabatic {
Segment* AutoVertical::base () { return _vertical; } Segment* AutoVertical::base () { return _vertical; }
Segment* AutoVertical::base () const { return _vertical; } Segment* AutoVertical::base () const { return _vertical; }
Vertical* AutoVertical::getVertical () { return _vertical; } Vertical* AutoVertical::getVertical () { return _vertical; }
DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSourceY(); } DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSource()->getY(); }
DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTargetY(); } DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTarget()->getY(); }
DbU::Unit AutoVertical::getDuSource () const { return _vertical->getDySource(); } DbU::Unit AutoVertical::getDuSource () const { return _vertical->getDySource(); }
DbU::Unit AutoVertical::getDuTarget () const { return _vertical->getDyTarget(); } DbU::Unit AutoVertical::getDuTarget () const { return _vertical->getDyTarget(); }
Interval AutoVertical::getSpanU () const { return Interval(_vertical->getSourceY(),_vertical->getTargetY()); } Interval AutoVertical::getSpanU () const { return Interval(_vertical->getSourceY(),_vertical->getTargetY()); }
void AutoVertical::setDuSource ( DbU::Unit du ) { _vertical->setDySource(du); }
void AutoVertical::setDuTarget ( DbU::Unit du ) { _vertical->setDyTarget(du); }
string AutoVertical::_getTypeName () const { return "AutoVertical"; } string AutoVertical::_getTypeName () const { return "AutoVertical"; }
@ -115,6 +118,30 @@ namespace Anabatic {
} }
void AutoVertical::setDuSource ( DbU::Unit du )
{
_vertical->setDySource(du);
if (abs(du) > getPitch())
cerr << Warning( "AutoVertical::setDuSource(): Suspiciously big du=%s (should not exceed routing pitch %s)\n"
" On %s"
, DbU::getValueString(du).c_str()
, DbU::getValueString(getPitch()).c_str()
, getString(this).c_str() ) << endl;
}
void AutoVertical::setDuTarget ( DbU::Unit du )
{
_vertical->setDyTarget(du);
if (abs(du) > getPitch())
cerr << Warning( "AutoVertical::setDuTarget(): Suspiciously big du=%s (should not exceed routing pitch %s)\n"
" On %s"
, DbU::getValueString(du).c_str()
, DbU::getValueString(getPitch()).c_str()
, getString(this).c_str() ) << endl;
}
Interval AutoVertical::getSourceConstraints ( Flags flags ) const Interval AutoVertical::getSourceConstraints ( Flags flags ) const
{ {
if (flags & Flags::NativeConstraints) { if (flags & Flags::NativeConstraints) {
@ -137,6 +164,8 @@ namespace Anabatic {
bool AutoVertical::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const bool AutoVertical::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const
{ {
cdebug_log(149,1) << "getConstraints() " << this << endl;
constraintMin = getNativeMin(); constraintMin = getNativeMin();
constraintMax = getNativeMax(); constraintMax = getNativeMax();
@ -152,19 +181,39 @@ namespace Anabatic {
<< DbU::getValueString(getAutoSource()->getCBXMax()) << "]" << DbU::getValueString(getAutoSource()->getCBXMax()) << "]"
<< endl; << endl;
constraintMin = max ( constraintMin, getUserConstraints().getVMin() ); constraintMin = std::max ( constraintMin, getAutoTarget()->getCBXMin() );
constraintMax = min ( constraintMax, getUserConstraints().getVMax() ); constraintMax = std::min ( constraintMax, getAutoTarget()->getCBXMax() );
cdebug_log(149,0) << "Merge with target constraints: ["
cdebug_log(149,0) << "Merge with user constraints: [" << DbU::getValueString(getAutoTarget()->getCBXMin()) << ":"
<< DbU::getValueString(getUserConstraints().getVMin()) << ":" << DbU::getValueString(getAutoTarget()->getCBXMax()) << "]"
<< DbU::getValueString(getUserConstraints().getVMax()) << "]"
<< endl; << endl;
cdebug_log(149,0) << "Resulting constraints: " << " [" Interval userConstraints = getUserConstraints();
if (not userConstraints.isEmpty()) {
constraintMin = max ( constraintMin, userConstraints.getVMin() );
constraintMax = min ( constraintMax, userConstraints.getVMax() );
cdebug_log(149,0) << "Merge with user constraints: ["
<< DbU::getValueString(userConstraints.getVMin()) << ":"
<< DbU::getValueString(userConstraints.getVMax()) << "]"
<< endl;
} else
cdebug_log(155,0) << "Empty user constraints" << endl;
cdebug_log(149,0) << "Resulting constraints: ["
<< DbU::getValueString(constraintMin) << ":" << DbU::getValueString(constraintMin) << ":"
<< DbU::getValueString(constraintMax) << "]" << DbU::getValueString(constraintMax) << "]"
<< endl; << endl;
if (constraintMin > constraintMax)
cerr << Error( "AutoVertical::getConstraints(): Invalid interval [%s : %s]\n"
" on %s"
, DbU::getValueString(constraintMin).c_str()
, DbU::getValueString(constraintMax).c_str()
, getString(this).c_str()
) << endl;
cdebug_tabw(149,-1);
return true; return true;
} }
@ -173,13 +222,14 @@ namespace Anabatic {
{ return Flags::Vertical; } { return Flags::Vertical; }
size_t AutoVertical::getGCells ( vector<GCell*>& gcells ) const bool AutoVertical::getGCells ( vector<GCell*>& gcells ) const
{ {
vector<GCell*>().swap( gcells ); vector<GCell*>().swap( gcells );
DbU::Unit xprobe = getX(); bool success = true;
GCell* gcell = getAutoSource()->getGCell(); DbU::Unit xprobe = getX();
GCell* end = getAutoTarget()->getGCell(); GCell* gcell = getAutoSource()->getGCell();
GCell* end = getAutoTarget()->getGCell();
cdebug_log(144,0) << "xprobe: " << DbU::getValueString(xprobe) << endl; cdebug_log(144,0) << "xprobe: " << DbU::getValueString(xprobe) << endl;
@ -192,20 +242,23 @@ namespace Anabatic {
gcell = gcell->getNorth( xprobe ); gcell = gcell->getNorth( xprobe );
if (not gcell) { if (not gcell) {
cerr << Error( "AutoVertical::getGCells() : NULL GCell under %s\n" success = false;
" begin:%s\n" if (not isCreated()) {
" end: %s" cerr << Error( "AutoVertical::getGCells() : NULL GCell under %s\n"
, getString(this).c_str() " begin:%s\n"
, getString(getAutoSource()->getGCell()).c_str() " end: %s"
, getString(getAutoTarget()->getGCell()).c_str() , getString(this).c_str()
) << endl; , getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
}
break; break;
} }
gcells.push_back( gcell ); gcells.push_back( gcell );
} }
return gcells.size(); return success;
} }
@ -213,17 +266,21 @@ namespace Anabatic {
{ {
cdebug_tabw(149,-1); cdebug_tabw(149,-1);
if (getAutoSource()->isOnPin() or getAutoTarget()->isOnPin()) { cdebug_tabw(149,-1); return false; }
Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Horizontal ); Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Horizontal );
Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Horizontal ); Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Horizontal );
Interval sourceConstraints = Interval(getAutoSource()->getCBXMin(),getAutoSource()->getCBXMax()); Interval sourceConstraints = Interval(getAutoSource()->getCBXMin(),getAutoSource()->getCBXMax());
Interval targetConstraints = Interval(getAutoTarget()->getCBXMin(),getAutoTarget()->getCBXMax()); Interval targetConstraints = Interval(getAutoTarget()->getCBXMin(),getAutoTarget()->getCBXMax());
bool sourceGoStraight = getAutoSource()->getGCell()->isGoStraight();
bool targetGoStraight = getAutoTarget()->getGCell()->isGoStraight();
// Expand by a tiny amount for the "contains" to work for sure. // Expand by a tiny amount for the "contains" to work for sure.
sourceConstraints.inflate( 1 ); sourceConstraints.inflate( 1 );
targetConstraints.inflate( 1 ); targetConstraints.inflate( 1 );
if (not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; } if (not sourceGoStraight and not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; }
if (not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; } if (not targetGoStraight and not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; }
cdebug_tabw(149,-1); cdebug_tabw(149,-1);
return false; return false;
@ -234,13 +291,15 @@ namespace Anabatic {
{ {
cdebug_log(149,1) << "AutoVertical::_slacken() " << this << endl; cdebug_log(149,1) << "AutoVertical::_slacken() " << this << endl;
if ( not isStrongTerminal() if (not isDrag()) {
or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < getPitch()*5)) ) if ( not isStrongTerminal()
{ cdebug_tabw(149,-1); return false; } or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getAnchoredLength() < getPitch()*5)) )
{ cdebug_tabw(149,-1); return false; }
}
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl; cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
cdebug_log(149,0) << "test:" << (getLength() < getPitch()*5) << endl; cdebug_log(149,0) << "test:" << (getAnchoredLength() < getPitch()*5) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl; cdebug_log(149,0) << "length:" << DbU::getValueString(getAnchoredLength()) << endl;
bool success = false; bool success = false;
bool sourceSlackened = false; bool sourceSlackened = false;
@ -371,8 +430,8 @@ namespace Anabatic {
void AutoVertical::updatePositions () void AutoVertical::updatePositions ()
{ {
_sourcePosition = _vertical->getSourceY() - getExtensionCap(); _sourcePosition = getSourceU() - getExtensionCap(Flags::Source);
_targetPosition = _vertical->getTargetY() + getExtensionCap(); _targetPosition = getTargetU() + getExtensionCap(Flags::Target);
} }
@ -392,8 +451,8 @@ namespace Anabatic {
bool AutoVertical::checkPositions () const bool AutoVertical::checkPositions () const
{ {
bool coherency = true; bool coherency = true;
DbU::Unit sourcePosition = _vertical->getSourceY() - getExtensionCap(); DbU::Unit sourcePosition = _vertical->getSource()->getY() - getExtensionCap(Flags::Source);
DbU::Unit targetPosition = _vertical->getTargetY() + getExtensionCap(); DbU::Unit targetPosition = _vertical->getTarget()->getY() + getExtensionCap(Flags::Target);
if ( _sourcePosition != sourcePosition ) { if ( _sourcePosition != sourcePosition ) {
cerr << Error ( "%s\n Source position incoherency: " cerr << Error ( "%s\n Source position incoherency: "
@ -650,12 +709,14 @@ namespace Anabatic {
{ {
cdebug_log(149,0) << "AutoVertical::_makeDogleg(GCell*)" << endl; cdebug_log(149,0) << "AutoVertical::_makeDogleg(GCell*)" << endl;
//Session::doglegReset();
AutoContact* autoSource = getAutoSource(); AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget(); AutoContact* autoTarget = getAutoTarget();
GCell* begin = autoSource->getGCell(); GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell(); GCell* end = autoTarget->getGCell();
//Session::doglegReset(); if (not autoSource->canDrag()) unsetFlags( SegDrag );
DbU::Unit doglegAxis = (doglegGCell->getYMax() + doglegGCell->getYMin()) / 2; DbU::Unit doglegAxis = (doglegGCell->getYMax() + doglegGCell->getYMin()) / 2;
if (isLocal()) if (isLocal())
@ -671,10 +732,19 @@ namespace Anabatic {
} while ( gcell and (gcell != end) ); } while ( gcell and (gcell != end) );
} }
size_t depth = Session::getRoutingGauge()->getLayerDepth ( _vertical->getLayer() ); size_t depth = Session::getRoutingGauge()->getLayerDepth ( _vertical->getLayer() );
bool upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); bool upLayer = true;
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer ( depth + ((upLayer)?0:-1) );
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer ( depth + ((upLayer)?1:-1) ); if (Session::getRoutingGauge()->isTwoMetals()) {
upLayer = (Session::getRoutingGauge()->isVH());
} else if (Session::getRoutingGauge()->isVH()) {
upLayer = (depth < 2);
} else {
upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
}
size_t doglegDepth = depth + ((upLayer)?1:-1);
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer ( depth + ((upLayer)?0:-1) );
Session::dogleg( this ); Session::dogleg( this );
targetDetach(); targetDetach();
@ -686,7 +756,7 @@ namespace Anabatic {
cdebug_log(149,0) << dlContact2 << endl; cdebug_log(149,0) << dlContact2 << endl;
AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Horizontal ); AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Horizontal );
cdebug_log(149,0) << segment1 << endl; cdebug_log(149,0) << segment1 << endl;
segment1->setLayer( doglegLayer ); segment1->setLayer( doglegDepth );
segment1->_setAxis( doglegAxis ); segment1->_setAxis( doglegAxis );
segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned ); segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned );
cdebug_log(149,0) << "New " << dlContact1->base() << "." << endl; cdebug_log(149,0) << "New " << dlContact1->base() << "." << endl;
@ -696,36 +766,61 @@ namespace Anabatic {
targetAttach( dlContact1 ); targetAttach( dlContact1 );
AutoSegment* segment2 = AutoVertical::create ( dlContact2, autoTarget, Flags::Vertical ); AutoSegment* segment2 = AutoVertical::create ( dlContact2, autoTarget, Flags::Vertical );
autoTarget->cacheAttach( segment2 ); autoTarget->cacheAttach( segment2 );
segment2->setLayer( getLayer() ); segment2->setLayer( depth );
segment2->_setAxis( getX() ); segment2->_setAxis( getX() );
segment2->setFlags( (isSlackened()?SegSlackened:0) ); segment2->setFlags( (isSlackened()?SegSlackened:0) );
Session::dogleg( segment2 ); Session::dogleg( segment2 );
if (isSourceTerminal()) { if (autoSource->isTerminal() and autoTarget->isTerminal()) {
segment1->setFlags( SegWeakTerminal1 ); dlContact1->setFlags ( CntWeakTerminal );
segment2->setFlags( SegWeakTerminal1 ); dlContact2->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
} else if (autoSource->isTerminal()) {
autoTarget->unsetFlags( CntWeakTerminal ); autoTarget->unsetFlags( CntWeakTerminal );
dlContact1->setFlags ( CntWeakTerminal ); dlContact1->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
dlContact1->migrateConstraintBox( autoTarget ); } else if (autoTarget->isTerminal()) {
} else if (isTargetTerminal()) {
unsetFlags( SegTargetTerminal ); unsetFlags( SegTargetTerminal );
setFlags( SegWeakTerminal1 ); setFlags( SegWeakTerminal1 );
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegTargetTerminal );
autoSource->unsetFlags( CntWeakTerminal ); autoSource->unsetFlags( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal ); dlContact2->setFlags ( CntWeakTerminal );
if (autoSource->getGCell() == doglegGCell) if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
dlContact2->migrateConstraintBox( autoSource ); } else if (isWeakTerminal()) {
} else if (isWeakTerminal()) {
segment1->setFlags( SegWeakTerminal1 ); segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 ); segment2->setFlags( SegWeakTerminal1 );
} }
// if (isSourceTerminal()) {
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegWeakTerminal1 );
// autoTarget->unsetFlags( CntWeakTerminal );
// dlContact1->setFlags ( CntWeakTerminal );
// if (autoTarget->getGCell() == doglegGCell)
// dlContact1->migrateConstraintBox( autoTarget );
// } else if (isTargetTerminal()) {
// unsetFlags( SegTargetTerminal );
// setFlags( SegWeakTerminal1 );
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegTargetTerminal );
// autoSource->unsetFlags( CntWeakTerminal );
// dlContact2->setFlags ( CntWeakTerminal );
// if (autoSource->getGCell() == doglegGCell)
// dlContact2->migrateConstraintBox( autoSource );
// } else if (isWeakTerminal()) {
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegWeakTerminal1 );
// }
if (isAnalog()) { if (isAnalog()) {
segment1->setFlags( SegAnalog ); segment1->setFlags( SegAnalog );
segment2->setFlags( SegAnalog ); segment2->setFlags( SegAnalog );
} }
if (isNoMoveUp()) {
segment1->setFlags( SegNoMoveUp );
segment2->setFlags( SegNoMoveUp );
}
cdebug_log(149,0) << "Session::dogleg[x+1] perpand: " << segment1 << endl; cdebug_log(149,0) << "Session::dogleg[x+1] perpand: " << segment1 << endl;
cdebug_log(149,0) << "Session::dogleg[x+2] new paral: " << segment2 << endl; cdebug_log(149,0) << "Session::dogleg[x+2] new paral: " << segment2 << endl;
@ -741,6 +836,18 @@ namespace Anabatic {
updateNativeConstraints(); updateNativeConstraints();
segment2->updateNativeConstraints(); segment2->updateNativeConstraints();
if ( isLocal()) autoSource->setFlags( AutoContactFlag::CntHDogleg );
if (segment2->isLocal()) autoTarget->setFlags( AutoContactFlag::CntHDogleg );
if (autoTarget->canDrag() and not autoSource->canDrag()) {
if (not autoTarget->getGCell()->isDevice() and (segment1->getGCell() == autoTarget->getGCell())) {
Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Vertical);
segment1->mergeUserConstraints( dragConstraints );
cdebug_log(149,0) << "Perpandicular has drag constraints: " << dragConstraints << endl;
}
}
return (upLayer) ? Flags::AboveLayer : Flags::BelowLayer; return (upLayer) ? Flags::AboveLayer : Flags::BelowLayer;
} }

View File

@ -6,15 +6,18 @@ endif ( CHECK_DETERMINISM )
include_directories( ${ANABATIC_SOURCE_DIR}/src include_directories( ${ANABATIC_SOURCE_DIR}/src
${CORIOLIS_INCLUDE_DIR} ${CORIOLIS_INCLUDE_DIR}
${ETESIAN_INCLUDE_DIR}
${HURRICANE_INCLUDE_DIR} ${HURRICANE_INCLUDE_DIR}
${CONFIGURATION_INCLUDE_DIR} ${CONFIGURATION_INCLUDE_DIR}
${FLUTE_INCLUDE_DIR}
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
${QtX_INCLUDE_DIR} ${QtX_INCLUDE_DIRS}
${PYTHON_INCLUDE_PATH} ${Python_INCLUDE_DIRS}
) )
set( includes anabatic/Constants.h set( includes anabatic/Constants.h
anabatic/Configuration.h anabatic/Configuration.h
anabatic/Matrix.h anabatic/Matrix.h
anabatic/EdgeCapacity.h
anabatic/Edge.h anabatic/Edges.h anabatic/Edge.h anabatic/Edges.h
anabatic/GCell.h #anabatic/GCells.h anabatic/GCell.h #anabatic/GCells.h
anabatic/AnabaticEngine.h anabatic/AnabaticEngine.h
@ -29,18 +32,22 @@ endif ( CHECK_DETERMINISM )
anabatic/AutoHorizontal.h anabatic/AutoHorizontal.h
anabatic/AutoVertical.h anabatic/AutoVertical.h
anabatic/Session.h anabatic/Session.h
anabatic/NetBuilder.h
anabatic/NetBuilderM2.h
anabatic/NetBuilderHV.h
anabatic/NetBuilderVH.h
anabatic/NetBuilderHybridVH.h
anabatic/ChipTools.h anabatic/ChipTools.h
) )
set( pyIncludes ) set( pyIncludes anabatic/PyStyleFlags.h )
set( cpps Constants.cpp set( cpps Constants.cpp
Configuration.cpp Configuration.cpp
Matrix.cpp Matrix.cpp
EdgeCapacity.cpp
Edge.cpp Edge.cpp
Edges.cpp Edges.cpp
GCell.cpp GCell.cpp
AnabaticEngine.cpp
Dijkstra.cpp Dijkstra.cpp
AutoContact.cpp AutoContact.cpp
AutoContactTerminal.cpp AutoContactTerminal.cpp
AutoContactTurn.cpp AutoContactTurn.cpp
@ -52,15 +59,23 @@ endif ( CHECK_DETERMINISM )
Session.cpp Session.cpp
NetConstraints.cpp NetConstraints.cpp
NetOptimals.cpp NetOptimals.cpp
LoadGlobalRouting.cpp NetBuilder.cpp
NetBuilderM2.cpp
NetBuilderHV.cpp
NetBuilderVH.cpp
NetBuilderHybridVH.cpp
ChipTools.cpp ChipTools.cpp
LayerAssign.cpp LayerAssign.cpp
AntennaProtect.cpp
PreRouteds.cpp PreRouteds.cpp
AnabaticEngine.cpp
) )
set( pyCpps PyAnabatic.cpp set( pyCpps PyStyleFlags.cpp
PyAnabatic.cpp
) )
set( depLibs ${CORIOLIS_PYTHON_LIBRARIES} set( depLibs ${ETESIAN_LIBRARIES}
${CORIOLIS_PYTHON_LIBRARIES}
${CORIOLIS_LIBRARIES} ${CORIOLIS_LIBRARIES}
${HURRICANE_PYTHON_LIBRARIES} ${HURRICANE_PYTHON_LIBRARIES}
${HURRICANE_GRAPHICAL_LIBRARIES} ${HURRICANE_GRAPHICAL_LIBRARIES}
@ -68,12 +83,15 @@ endif ( CHECK_DETERMINISM )
${CONFIGURATION_LIBRARY} ${CONFIGURATION_LIBRARY}
${CIF_LIBRARY} ${CIF_LIBRARY}
${AGDS_LIBRARY} ${AGDS_LIBRARY}
${COLOQUINTE_LIBRARIES}
${FLUTE_LIBRARIES}
${LEFDEF_LIBRARIES} ${LEFDEF_LIBRARIES}
${OA_LIBRARIES} ${OA_LIBRARIES}
${QtX_LIBRARIES} ${QtX_LIBRARIES}
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${LIBXML2_LIBRARIES} ${LIBXML2_LIBRARIES}
${PYTHON_LIBRARIES} -lutil ${Python3_LIBRARIES}
-lutil
) )
add_library( anabatic ${cpps} ) add_library( anabatic ${cpps} )

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved // Copyright (c) UPMC 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Configuration.cpp<anabatic>" -*- // -*- mode: C++; explicit-buffer-name: "Configuration.cpp<anabatic>" -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved // Copyright (c) Sorbonne Université 2016-2022, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -17,12 +17,17 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <vector> #include <vector>
#include "vlsisapd/configuration/Configuration.h" #include "hurricane/configuration/Configuration.h"
#include "hurricane/Warning.h" #include "hurricane/Warning.h"
#include "hurricane/Error.h" #include "hurricane/Error.h"
#include "hurricane/Technology.h" #include "hurricane/Technology.h"
#include "hurricane/DataBase.h" #include "hurricane/DataBase.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h" #include "hurricane/RegularLayer.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Pin.h"
#include "hurricane/Pad.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/Cell.h" #include "hurricane/Cell.h"
#include "crlcore/Utilities.h" #include "crlcore/Utilities.h"
#include "crlcore/CellGauge.h" #include "crlcore/CellGauge.h"
@ -46,9 +51,18 @@ namespace Anabatic {
using Hurricane::tab; using Hurricane::tab;
using Hurricane::Warning; using Hurricane::Warning;
using Hurricane::Error; using Hurricane::Error;
using Hurricane::Transformation;
using Hurricane::Technology; using Hurricane::Technology;
using Hurricane::DataBase; using Hurricane::DataBase;
using Hurricane::BasicLayer;
using Hurricane::RegularLayer; using Hurricane::RegularLayer;
using Hurricane::Segment;
using Hurricane::Pad;
using Hurricane::Pin;
using Hurricane::Plug;
using Hurricane::Path;
using Hurricane::Occurrence;
using Hurricane::NetExternalComponents;
using CRL::AllianceFramework; using CRL::AllianceFramework;
using CRL::RoutingGauge; using CRL::RoutingGauge;
using CRL::RoutingLayerGauge; using CRL::RoutingLayerGauge;
@ -59,30 +73,56 @@ namespace Anabatic {
Configuration::Configuration ( const CellGauge* cg, const RoutingGauge* rg ) Configuration::Configuration ( const CellGauge* cg, const RoutingGauge* rg )
: _cg (NULL) : _gdepthv (ndepth)
, _rg (NULL) , _gdepthh (ndepth)
, _extensionCaps () , _ddepthv (ndepth)
, _saturateRatio (Cfg::getParamPercentage("katabatic.saturateRatio",80.0)->asDouble()) , _ddepthh (ndepth)
, _saturateRp (Cfg::getParamInt ("katabatic.saturateRp" ,8 )->asInt()) , _ddepthc (ndepth)
, _globalThreshold(0) , _netBuilderStyle (Cfg::getParamString("anabatic.netBuilderStyle","HV,3RL+")->asString() )
, _allowedDepth (0) , _routingStyle (Cfg::getParamInt ("anabatic.routingStyle" ,StyleFlags::NoStyle)->asInt() )
, _edgeLength (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeLength",24)->asInt())) , _cg (NULL)
, _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt())) , _rg (NULL)
, _edgeCostH (Cfg::getParamDouble("anabatic.edgeCostH", 9.0)->asDouble()) , _extensionCaps ()
, _edgeCostK (Cfg::getParamDouble("anabatic.edgeCostK",-10.0)->asDouble()) , _saturateRatio (Cfg::getParamPercentage("anabatic.saturateRatio",80.0)->asDouble())
, _edgeHInc (Cfg::getParamDouble("anabatic.edgeHInc" , 1.5)->asDouble()) , _saturateRp (Cfg::getParamInt ("anabatic.saturateRp" ,8 )->asInt())
, _globalThreshold (0)
, _allowedDepth (0)
, _edgeLength (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeLength",24)->asInt()))
, _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt()))
, _edgeCostH (Cfg::getParamDouble("anabatic.edgeCostH" , 9.0)->asDouble())
, _edgeCostK (Cfg::getParamDouble("anabatic.edgeCostK" , -10.0)->asDouble())
, _edgeHInc (Cfg::getParamDouble("anabatic.edgeHInc" , 1.5)->asDouble())
, _edgeHScaling (Cfg::getParamDouble("anabatic.edgeHScaling" , 1.0)->asDouble())
, _globalIterations (Cfg::getParamInt ("anabatic.globalIterations", 10 )->asInt())
, _diodeName (Cfg::getParamString("etesian.diodeName" , "dio_x0")->asString() )
, _antennaGateMaxWL (Cfg::getParamInt ("etesian.antennaGateMaxWL" , 0 )->asInt())
, _antennaDiodeMaxWL(Cfg::getParamInt ("etesian.antennaDiodeMaxWL", 0 )->asInt())
{ {
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() ); GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
if (cg == NULL) cg = AllianceFramework::get()->getCellGauge(); string gaugeName = Cfg::getParamString("anabatic.routingGauge","sxlib")->asString();
if (rg == NULL) rg = AllianceFramework::get()->getRoutingGauge(); if (not cg)
cg = AllianceFramework::get()->getCellGauge( gaugeName );
if (not cg) {
string cellGaugeName = Cfg::getParamString("anabatic.cellGauge","sxlib")->asString();
cg = AllianceFramework::get()->getCellGauge( cellGaugeName );
}
if (not cg)
throw Error( "AnabaticEngine::Configuration(): Unable to find cell gauge \"%s\""
, gaugeName.c_str() );
if (not rg)
rg = AllianceFramework::get()->getRoutingGauge( gaugeName );
if (not rg)
throw Error( "AnabaticEngine::Configuration(): Unable to find routing gauge \"%s\""
, gaugeName.c_str() );
_cg = cg->getClone(); _cg = cg->getClone();
_rg = rg->getClone(); _rg = rg->getClone();
if (Cfg::hasParameter("anabatic.topRoutingLayer")) { _allowedDepth = rg->getDepth()-1;
if (Cfg::hasParameter("anabatic.topRoutingLayer"))
_setTopRoutingLayer( Cfg::getParamString("anabatic.topRoutingLayer")->asString() ); _setTopRoutingLayer( Cfg::getParamString("anabatic.topRoutingLayer")->asString() );
} else
_allowedDepth = rg->getDepth()-1;
_gmetalh = DataBase::getDB()->getTechnology()->getLayer("gmetalh"); _gmetalh = DataBase::getDB()->getTechnology()->getLayer("gmetalh");
_gmetalv = DataBase::getDB()->getTechnology()->getLayer("gmetalv"); _gmetalv = DataBase::getDB()->getTechnology()->getLayer("gmetalv");
@ -94,36 +134,77 @@ namespace Anabatic {
//DbU::Unit sliceHeight = _cg->getSliceHeight(); //DbU::Unit sliceHeight = _cg->getSliceHeight();
_ddepthc = (_allowedDepth > 1) ? 1 : 0;
const vector<RoutingLayerGauge*>& layerGauges = rg->getLayerGauges(); const vector<RoutingLayerGauge*>& layerGauges = rg->getLayerGauges();
for ( size_t depth=0 ; depth < layerGauges.size() ; ++depth ) { for ( size_t depth=0 ; depth < layerGauges.size() ; ++depth ) {
if ( (_gdepthh == ndepth)
and layerGauges[depth]->isHorizontal()
and (layerGauges[depth]->getType() == Constant::LayerGaugeType::Default) ) {
_gdepthh = depth;
_ddepthh = depth;
}
if ( (_gdepthv == ndepth)
and layerGauges[depth]->isVertical()
and (layerGauges[depth]->getType() == Constant::LayerGaugeType::Default) ) {
_gdepthv = depth;
_ddepthv = depth;
}
const RegularLayer* regularLayer = dynamic_cast<const RegularLayer*>( layerGauges[depth]->getLayer() ); const RegularLayer* regularLayer = dynamic_cast<const RegularLayer*>( layerGauges[depth]->getLayer() );
if (regularLayer) if (regularLayer)
_extensionCaps.push_back( regularLayer->getExtentionCap() ); _extensionCaps.push_back( regularLayer->getExtentionCap() );
else { else {
_extensionCaps.push_back( 0 ); const BasicLayer* basicLayer = dynamic_cast<const BasicLayer*>( layerGauges[depth]->getLayer() );
cerr << Warning( "Routing layer at depth %d is *not* a RegularLayer, cannot guess extension cap.\n" if (basicLayer) {
" (%s)" _extensionCaps.push_back( layerGauges[depth]->getHalfWireWidth() );
, depth } else {
, getString(layerGauges[depth]->getLayer()).c_str() _extensionCaps.push_back( 0 );
) << endl; cerr << Warning( "Routing layer at depth %d is *not* a RegularLayer, cannot guess extension cap.\n"
" (%s)"
, depth
, getString(layerGauges[depth]->getLayer()).c_str()
) << endl;
}
} }
} }
if (_antennaGateMaxWL and not _antennaDiodeMaxWL) {
_antennaDiodeMaxWL = _antennaGateMaxWL;
cerr << Warning( "Anabatic::Configuration(): \"etesian.antennaGateMaxWL\" is defined but not \"etesian.antennaDiodeMaxWL\".\n"
" Setting both to %s"
, DbU::getValueString(_antennaGateMaxWL).c_str()
) << endl;
}
} }
Configuration::Configuration ( const Configuration& other ) Configuration::Configuration ( const Configuration& other )
: _gmetalh (other._gmetalh) : _gmetalh (other._gmetalh)
, _gmetalv (other._gmetalv) , _gmetalv (other._gmetalv)
, _gcontact (other._gcontact) , _gcontact (other._gcontact)
, _cg (NULL) , _gdepthv (other._gdepthv)
, _rg (NULL) , _gdepthh (other._gdepthh)
, _extensionCaps (other._extensionCaps) , _ddepthv (other._ddepthv)
, _saturateRatio (other._saturateRatio) , _ddepthh (other._ddepthh)
, _globalThreshold(other._globalThreshold) , _ddepthc (other._ddepthc)
, _allowedDepth (other._allowedDepth) , _netBuilderStyle (other._netBuilderStyle)
, _edgeCostH (other._edgeCostH) , _routingStyle (other._routingStyle)
, _edgeCostK (other._edgeCostK) , _cg (NULL)
, _edgeHInc (other._edgeHInc) , _rg (NULL)
, _extensionCaps (other._extensionCaps)
, _saturateRatio (other._saturateRatio)
, _globalThreshold (other._globalThreshold)
, _allowedDepth (other._allowedDepth)
, _edgeCostH (other._edgeCostH)
, _edgeCostK (other._edgeCostK)
, _edgeHInc (other._edgeHInc)
, _edgeHScaling (other._edgeHScaling)
, _globalIterations (other._globalIterations)
, _diodeName (other._diodeName)
, _antennaGateMaxWL (other._antennaGateMaxWL)
, _antennaDiodeMaxWL(other._antennaDiodeMaxWL)
{ {
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() ); GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
@ -144,6 +225,22 @@ namespace Anabatic {
{ return new Configuration(*this); } { return new Configuration(*this); }
bool Configuration::isTwoMetals () const
{ return _rg->isTwoMetals(); }
bool Configuration::isHybrid () const
{ return _routingStyle & StyleFlags::Hybrid; }
bool Configuration::isHV () const
{ return _rg->isHV(); }
bool Configuration::isVH () const
{ return _rg->isVH(); }
bool Configuration::isGMetal ( const Layer* layer ) const bool Configuration::isGMetal ( const Layer* layer ) const
{ return (layer and ((layer == _gmetalh) or (layer == _gmetalv))); } { return (layer and ((layer == _gmetalh) or (layer == _gmetalv))); }
@ -151,15 +248,19 @@ namespace Anabatic {
bool Configuration::isGContact ( const Layer* layer ) const bool Configuration::isGContact ( const Layer* layer ) const
{ return (layer and (layer == _gcontact)); } { return (layer and (layer == _gcontact)); }
const Layer* Configuration::getGContactLayer () const const Layer* Configuration::getGContactLayer () const
{ return _gcontact; } { return _gcontact; }
const Layer* Configuration::getGHorizontalLayer () const const Layer* Configuration::getGHorizontalLayer () const
{ return _gmetalh; } { return _gmetalh; }
const Layer* Configuration::getGVerticalLayer () const const Layer* Configuration::getGVerticalLayer () const
{ return _gmetalv; } { return _gmetalv; }
size_t Configuration::getDepth () const size_t Configuration::getDepth () const
{ return _rg->getDepth(); } { return _rg->getDepth(); }
@ -216,6 +317,10 @@ namespace Anabatic {
{ return getWireWidth( getLayerDepth(layer) ); } { return getWireWidth( getLayerDepth(layer) ); }
DbU::Unit Configuration::getPWireWidth ( const Layer* layer ) const
{ return getPWireWidth( getLayerDepth(layer) ); }
Flags Configuration::getDirection ( const Layer* layer ) const Flags Configuration::getDirection ( const Layer* layer ) const
{ return getDirection( getLayerDepth(layer) ); } { return getDirection( getLayerDepth(layer) ); }
@ -267,6 +372,9 @@ namespace Anabatic {
{ return _rg->getLayerWireWidth(depth); } { return _rg->getLayerWireWidth(depth); }
DbU::Unit Configuration::getPWireWidth ( size_t depth ) const
{ return _rg->getLayerPWireWidth(depth); }
DbU::Unit Configuration::getExtensionCap ( size_t depth ) const DbU::Unit Configuration::getExtensionCap ( size_t depth ) const
{ return _extensionCaps[depth]; } { return _extensionCaps[depth]; }
@ -288,7 +396,7 @@ namespace Anabatic {
} }
} }
cerr << Error( "In Configuration::Concrete::_setTopRoutingLayer():\n" cerr << Error( "In Configuration::Concrete::_setTopRoutingLayer():\n"
" The routing gauge <%s> has no layer named <%s>" " The routing gauge <%s> has no layer named <%s>"
, getString(_rg->getName()).c_str() , getString(_rg->getName()).c_str()
, getString(name).c_str() ) << endl; , getString(name).c_str() ) << endl;
} }
@ -326,6 +434,144 @@ namespace Anabatic {
{ return _edgeHInc; } { return _edgeHInc; }
float Configuration::getEdgeHScaling () const
{ return _edgeHScaling; }
int Configuration::getGlobalIterations () const
{ return _globalIterations; }
DbU::Unit Configuration::isOnRoutingGrid ( RoutingPad* rp ) const
{
Box ab = rp->getCell()->getBoundingBox();
Box bb = rp->getBoundingBox();
Point center = rp->getCenter();
RoutingLayerGauge* gauge = getLayerGauge( 1 );
if (gauge->isHorizontal()) return 0;
DbU::Unit nearestX = gauge->getTrackPosition( ab.getXMin(), ab.getXMax(), center.getX(), Constant::Nearest );
if ( (nearestX >= bb.getXMin()) and (nearestX <= bb.getXMax()) ) return 0;
return nearestX;
}
bool Configuration::selectRpComponent ( RoutingPad* rp ) const
{
cdebug_log(112,1) << "selectRpComponent(): " << rp << endl;
if (rp->isAtTopLevel()) {
cdebug_log(112,0) << "> RP is at top level, must not change it." << endl;
cdebug_tabw(112,-1);
return true;
}
#define BETTER_FOR_TSMC 0
#if BETTER_FOR_TSMC
rp->setOnBestComponent( RoutingPad::BiggestArea );
cdebug_tabw(112,-1);
return true;
#else
Box ab = rp->getCell()->getAbutmentBox();
const Layer* metal1 = getLayerGauge( 0 )->getLayer();
RoutingLayerGauge* gauge = getLayerGauge( 1 );
Occurrence occurrence = rp->getPlugOccurrence();
Plug* plug = dynamic_cast<Plug*>( occurrence.getEntity() );
Net* masterNet = plug->getMasterNet();
Path path = Path( occurrence.getPath(), plug->getInstance() );
Transformation transformation = path.getTransformation();
Segment* current = dynamic_cast<Segment*>( rp->getOccurrence().getEntity() );
if (current and (current->getLayer()->getMask() != metal1->getMask())) {
cdebug_log(112,0) << "> using default non-metal1 segment." << endl;
cdebug_tabw(112,-1);
return true;
}
DbU::Unit bestSpan = 0;
Component* bestComponent = NULL;
cdebug_log(112,0) << "Looking into: " << masterNet->getCell() << endl;
for ( Component* component : masterNet->getComponents() ) {
cdebug_log(112,0) << "@ " << component << endl;
if (not NetExternalComponents::isExternal(component)) {
cdebug_log(112,0) << " Not an external component, skip." << endl;
continue;
}
if (dynamic_cast<Pin*>(component)) {
cdebug_log(112,0) << " Pins are always considered best candidates:" << component << endl;
bestComponent = component;
break;
}
Component* candidate = dynamic_cast<Segment*>( component );
if (not candidate
or (candidate->getLayer()->getMask() != metal1->getMask()) )
candidate = dynamic_cast<Pin*>(component);
if (not candidate)
candidate = dynamic_cast<Pad*>( component );
if (not candidate) continue;
Box bb = transformation.getBox( candidate->getBoundingBox() );
DbU::Unit trackPos = 0;
DbU::Unit minPos = DbU::Max;
DbU::Unit maxPos = DbU::Min;
if (gauge->isVertical()) {
trackPos = gauge->getTrackPosition( ab.getXMin()
, ab.getXMax()
, bb.getCenter().getX()
, Constant::Nearest );
minPos = bb.getXMin();
maxPos = bb.getXMax();
cdebug_log(112,0) << "Vertical gauge: " << gauge << endl;
cdebug_log(112,0) << "ab.getXMin(): " << DbU::getValueString(bb.getXMin()) << endl;
cdebug_log(112,0) << "ab.getXMax(): " << DbU::getValueString(bb.getXMax()) << endl;
cdebug_log(112,0) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getX()) << endl;
} else {
trackPos = gauge->getTrackPosition( ab.getYMin()
, ab.getYMax()
, bb.getCenter().getY()
, Constant::Nearest );
minPos = bb.getYMin();
maxPos = bb.getYMax();
cdebug_log(112,0) << "Horizontal gauge: " << gauge << endl;
cdebug_log(112,0) << "ab.getYMin(): " << DbU::getValueString(bb.getYMin()) << endl;
cdebug_log(112,0) << "ab.getYMax(): " << DbU::getValueString(bb.getYMax()) << endl;
cdebug_log(112,0) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getY()) << endl;
}
cdebug_log(112,0) << "| " << occurrence.getPath() << endl;
cdebug_log(112,0) << "| " << transformation << endl;
cdebug_log(112,0) << "| " << bb << " of:" << candidate << endl;
cdebug_log(112,0) << "| Nearest Pos: " << DbU::getValueString(trackPos) << endl;
if ( (trackPos >= minPos) and (trackPos <= maxPos) ) {
if (not bestComponent or (bestSpan < maxPos-minPos)) {
bestComponent = component;
bestSpan = maxPos - minPos;
}
}
}
if (bestComponent) {
rp->setExternalComponent( bestComponent );
cdebug_log(112,0) << "Using best candidate:" << bestComponent << endl;
cdebug_tabw(112,-1);
return true;
}
cdebug_tabw(112,-1);
return false;
#endif
}
void Configuration::print ( Cell* cell ) const void Configuration::print ( Cell* cell ) const
{ {
if (not cmess1.enabled()) return; if (not cmess1.enabled()) return;
@ -338,6 +584,7 @@ namespace Anabatic {
cout << " o Configuration of ToolEngine<Anabatic> for Cell <" << cell->getName() << ">" << endl; cout << " o Configuration of ToolEngine<Anabatic> for Cell <" << cell->getName() << ">" << endl;
cout << Dots::asIdentifier(" - Routing Gauge" ,getString(_rg->getName())) << endl; cout << Dots::asIdentifier(" - Routing Gauge" ,getString(_rg->getName())) << endl;
cout << Dots::asString (" - Top routing layer" ,topLayerName) << endl; cout << Dots::asString (" - Top routing layer" ,topLayerName) << endl;
cout << Dots::asUInt (" - Maximum GR iterations" ,_globalIterations) << endl;
} }
@ -360,15 +607,22 @@ namespace Anabatic {
Record* Configuration::_getRecord () const Record* Configuration::_getRecord () const
{ {
Record* record = new Record ( _getString() ); Record* record = new Record ( _getString() );
record->add ( getSlot( "_rg" , _rg ) ); record->add( getSlot( "_gdepthh" , _gdepthh ) );
record->add ( getSlot( "_gmetalh" , _gmetalh ) ); record->add( getSlot( "_gdepthv" , _gdepthv ) );
record->add ( getSlot( "_gmetalv" , _gmetalv ) ); record->add( getSlot( "_rg" , _rg ) );
record->add ( getSlot( "_gcontact" , _gcontact ) ); record->add( getSlot( "_gmetalh" , _gmetalh ) );
record->add ( getSlot( "_allowedDepth", _allowedDepth ) ); record->add( getSlot( "_gmetalv" , _gmetalv ) );
record->add ( getSlot( "_edgeCostH" , _edgeCostH ) ); record->add( getSlot( "_gcontact" , _gcontact ) );
record->add ( getSlot( "_edgeCostK" , _edgeCostK ) ); record->add( getSlot( "_allowedDepth" , _allowedDepth ) );
record->add( getSlot( "_edgeCostH" , _edgeCostH ) );
record->add( getSlot( "_edgeCostK" , _edgeCostK ) );
record->add( getSlot( "_edgeHInc" , _edgeHInc ) );
record->add( getSlot( "_edgeHScaling" , _edgeHScaling ) );
record->add( getSlot( "_globalIterations", _globalIterations ) );
record->add( DbU::getValueSlot( "_antennaGateMaxWL" , &_antennaGateMaxWL ) );
record->add( DbU::getValueSlot( "_antennaDiodeMaxWL", &_antennaDiodeMaxWL ) );
return ( record ); return record;
} }

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Constants.cpp<anabatic>" -*- // -*- mode: C++; explicit-buffer-name: "Constants.cpp<anabatic>" -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved // Copyright (c) UPMC 2016-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -14,16 +14,22 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#include "hurricane/Error.h"
#include "anabatic/Constants.h" #include "anabatic/Constants.h"
namespace Anabatic { namespace Anabatic {
using std::hex;
using std::string; using std::string;
using std::ostringstream; using std::ostringstream;
using Hurricane::BaseFlags; using Hurricane::BaseFlags;
using Hurricane::Error;
// -------------------------------------------------------------------
// Class : "Anabatic::Flags".
const BaseFlags Flags::NoFlags = 0; const BaseFlags Flags::NoFlags = 0;
// Flags used for both objects states & functions arguments. // Flags used for both objects states & functions arguments.
const BaseFlags Flags::Horizontal = (1L << 0); const BaseFlags Flags::Horizontal = (1L << 0);
@ -39,14 +45,27 @@ namespace Anabatic {
const BaseFlags Flags::MatrixGCell = (1L << 9); const BaseFlags Flags::MatrixGCell = (1L << 9);
const BaseFlags Flags::IoPadGCell = (1L << 10); const BaseFlags Flags::IoPadGCell = (1L << 10);
const BaseFlags Flags::Saturated = (1L << 11); const BaseFlags Flags::Saturated = (1L << 11);
const BaseFlags Flags::StdCellRow = (1L << 12);
const BaseFlags Flags::ChannelRow = (1L << 13);
const BaseFlags Flags::HRailGCell = (1L << 14);
const BaseFlags Flags::VRailGCell = (1L << 15);
const BaseFlags Flags::GoStraight = (1L << 16);
// Flags for Edge objects states only.
const BaseFlags Flags::NullCapacity = (1L << 5);
const BaseFlags Flags::InfiniteCapacity = (1L << 6);
// Flags for Anabatic objects states only. // Flags for Anabatic objects states only.
const BaseFlags Flags::DemoMode = (1L << 5); const BaseFlags Flags::DemoMode = (1L << 5);
const BaseFlags Flags::WarnOnGCellOverload = (1L << 6); const BaseFlags Flags::WarnOnGCellOverload = (1L << 6);
const BaseFlags Flags::DestroyGCell = (1L << 7); const BaseFlags Flags::DestroyGCell = (1L << 7);
const BaseFlags Flags::DestroyBaseContact = (1L << 8); const BaseFlags Flags::DestroyBaseContact = (1L << 8);
const BaseFlags Flags::DestroyBaseSegment = (1L << 9); const BaseFlags Flags::DestroyBaseSegment = (1L << 9);
const BaseFlags Flags::DisableCanonize = (1L << 10);
// Flags for NetDatas objects states only. // Flags for NetDatas objects states only.
const BaseFlags Flags::GlobalRouted = (1L << 5); const BaseFlags Flags::GlobalFixed = (1L << 5);
const BaseFlags Flags::GlobalEstimated = (1L << 6);
const BaseFlags Flags::GlobalRouted = (1L << 7);
const BaseFlags Flags::DetailRouted = (1L << 8);
const BaseFlags Flags::ExcludeRoute = (1L << 9);
// Masks. // Masks.
const BaseFlags Flags::WestSide = Horizontal|Target; const BaseFlags Flags::WestSide = Horizontal|Target;
const BaseFlags Flags::EastSide = Horizontal|Source; const BaseFlags Flags::EastSide = Horizontal|Source;
@ -56,7 +75,27 @@ namespace Anabatic {
const BaseFlags Flags::EndsMask = Source|Target; const BaseFlags Flags::EndsMask = Source|Target;
const BaseFlags Flags::DirectionMask = Horizontal|Vertical; const BaseFlags Flags::DirectionMask = Horizontal|Vertical;
const BaseFlags Flags::DestroyMask = DestroyGCell|DestroyBaseContact|DestroyBaseSegment; const BaseFlags Flags::DestroyMask = DestroyGCell|DestroyBaseContact|DestroyBaseSegment;
const BaseFlags Flags::GCellTypeMask = DeviceGCell|HChannelGCell|VChannelGCell|StrutGCell|MatrixGCell|IoPadGCell; const BaseFlags Flags::GCellTypeMask = DeviceGCell
| HChannelGCell
| VChannelGCell
| StrutGCell
| MatrixGCell
| IoPadGCell
| StdCellRow
| ChannelRow
| HRailGCell
| VRailGCell;
const BaseFlags Flags::RowGCellMask = StdCellRow|ChannelRow;
const BaseFlags Flags::AnalogGCellMask = DeviceGCell
| HChannelGCell
| VChannelGCell
| StrutGCell
| HRailGCell
| VRailGCell;
const BaseFlags Flags::EdgeCapacityMask = Horizontal
| Vertical
| NullCapacity
| InfiniteCapacity ;
// Flags for functions arguments only. // Flags for functions arguments only.
const BaseFlags Flags::Create = (1L << 5); const BaseFlags Flags::Create = (1L << 5);
const BaseFlags Flags::WithPerpands = (1L << 6); const BaseFlags Flags::WithPerpands = (1L << 6);
@ -86,6 +125,14 @@ namespace Anabatic {
const BaseFlags Flags::CheckLowDensity = (1L << 30); const BaseFlags Flags::CheckLowDensity = (1L << 30);
const BaseFlags Flags::CheckLowUpDensity = (1L << 31); const BaseFlags Flags::CheckLowUpDensity = (1L << 31);
const BaseFlags Flags::NoUpdate = (1L << 32); const BaseFlags Flags::NoUpdate = (1L << 32);
const BaseFlags Flags::NorthPath = (1L << 33);
const BaseFlags Flags::UseNonPref = (1L << 34);
const BaseFlags Flags::Force = (1L << 35);
const BaseFlags Flags::LayerCapOnly = (1L << 36);
const BaseFlags Flags::NoMinLength = (1L << 37);
const BaseFlags Flags::NoSegExt = (1L << 38);
const BaseFlags Flags::NullLength = (1L << 39);
const BaseFlags Flags::OnVSmall = (1L << 40);
Flags::~Flags () Flags::~Flags ()
@ -139,6 +186,7 @@ namespace Anabatic {
return s.str(); return s.str();
} }
string Flags::_getTypeName () const string Flags::_getTypeName () const
{ return "Anabatic::Flags"; } { return "Anabatic::Flags"; }
@ -146,23 +194,93 @@ namespace Anabatic {
string Flags::_getString () const string Flags::_getString () const
{ {
string s = ""; string s = "";
s += (_flags & (uint64_t)Horizontal ) ? 'h' : '-'; s += (_flags & (uint64_t)Horizontal ) ? 'h' : '-';
s += (_flags & (uint64_t)Vertical ) ? 'v' : '-'; s += (_flags & (uint64_t)Vertical ) ? 'v' : '-';
s += (_flags & (uint64_t)Source ) ? 'S' : '-'; s += (_flags & (uint64_t)Source ) ? 'S' : '-';
s += (_flags & (uint64_t)Target ) ? 'T' : '-'; s += (_flags & (uint64_t)Target ) ? 'T' : '-';
s += (_flags & (uint64_t)DeviceGCell ) ? 'd' : '-'; s += (_flags & (uint64_t)DeviceGCell ) ? 'd' : '-';
s += (_flags & (uint64_t)HChannelGCell) ? 'c' : '-'; s += (_flags & (uint64_t)HChannelGCell) ? 'c' : '-';
s += (_flags & (uint64_t)VChannelGCell) ? 'c' : '-'; s += (_flags & (uint64_t)VChannelGCell) ? 'c' : '-';
s += (_flags & (uint64_t)StrutGCell ) ? 's' : '-'; s += (_flags & (uint64_t)HRailGCell ) ? 'H' : '-';
s += (_flags & (uint64_t)MatrixGCell ) ? 'm' : '-'; s += (_flags & (uint64_t)VRailGCell ) ? 'V' : '-';
s += (_flags & (uint64_t)StrutGCell ) ? 'S' : '-';
s += (_flags & (uint64_t)MatrixGCell ) ? 'M' : '-';
s += (_flags & (uint64_t)StdCellRow ) ? 'R' : '-';
s += (_flags & (uint64_t)ChannelRow ) ? 'C' : '-';
s += (_flags & (uint64_t)GoStraight ) ? 'g' : '-';
s += ","; s += ",";
s += (_flags & (uint64_t)Invalidated ) ? 'i' : '-'; s += (_flags & (uint64_t)Invalidated ) ? 'i' : '-';
s += (_flags & (uint64_t)DestroyGCell ) ? 'D' : '-'; s += (_flags & (uint64_t)DestroyGCell ) ? 'D' : '-';
s += (_flags & (uint64_t)AboveLayer ) ? 'A' : '-'; s += (_flags & (uint64_t)AboveLayer ) ? 'A' : '-';
s += (_flags & (uint64_t)BelowLayer ) ? 'B' : '-'; s += (_flags & (uint64_t)BelowLayer ) ? 'B' : '-';
return s; return s;
} }
// -------------------------------------------------------------------
// Class : "Anabatic::StyleFlags".
const BaseFlags StyleFlags::NoStyle = 0;
const BaseFlags StyleFlags::HV = (1L << 0);
const BaseFlags StyleFlags::VH = (1L << 1);
const BaseFlags StyleFlags::OTH = (1L << 2);
const BaseFlags StyleFlags::Channel = (1L << 3);
const BaseFlags StyleFlags::Hybrid = (1L << 4);
StyleFlags::~StyleFlags ()
{ }
StyleFlags StyleFlags::toFlag ( std::string textFlag )
{
if (textFlag == "HV") return HV;
if (textFlag == "VH") return VH;
if (textFlag == "OTH") return OTH;
if (textFlag == "Channel") return Channel;
if (textFlag == "Hybrid") return Hybrid;
if (textFlag == "NoStyle") return NoStyle;
std::cerr << Error( "StyleFlags::toFlag(): Unknown flag value \"%s\"", textFlag.c_str() ) << std::endl;
return NoStyle;
}
StyleFlags StyleFlags::from ( std::string textFlags )
{
size_t start = 0;
size_t stop = textFlags.find( '|' );
while ( stop != string::npos ) {
*this |= toFlag( textFlags.substr( start, stop-start-1 ));
start = stop + 1;
stop = textFlags.find( '|', start );
}
*this |= toFlag( textFlags.substr( stop+1 ));
return *this;
}
string StyleFlags::asString () const
{
ostringstream s;
if (_flags & (uint64_t)HV) { s << (s.tellp() ? "|" : "") << "HV"; }
if (_flags & (uint64_t)VH) { s << (s.tellp() ? "|" : "") << "VH"; }
if (_flags & (uint64_t)OTH) { s << (s.tellp() ? "|" : "") << "OTH"; }
if (_flags & (uint64_t)Channel) { s << (s.tellp() ? "|" : "") << "Channel"; }
if (_flags & (uint64_t)Hybrid ) { s << (s.tellp() ? "|" : "") << "Hybrid"; }
s << " (0x" << hex << _flags << ")";
return s.str();
}
string StyleFlags::_getTypeName () const
{ return "Anabatic::StyleFlags"; }
string StyleFlags::_getString () const
{ return asString(); }
} // Anabatic namespace. } // Anabatic namespace.

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Edge.cpp<anabatic>" -*- // -*- mode: C++; explicit-buffer-name: "Edge.cpp<anabatic>" -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved // Copyright (c) UPMC 2016-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -17,6 +17,7 @@
#include <iostream> #include <iostream>
#include "hurricane/Error.h" #include "hurricane/Error.h"
#include "hurricane/Segment.h" #include "hurricane/Segment.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/DataBase.h" #include "hurricane/DataBase.h"
#include "hurricane/Technology.h" #include "hurricane/Technology.h"
#include "anabatic/Edge.h" #include "anabatic/Edge.h"
@ -24,11 +25,51 @@
#include "anabatic/AnabaticEngine.h" #include "anabatic/AnabaticEngine.h"
namespace {
using namespace std;
using namespace Hurricane;
using Anabatic::NetData;
using Anabatic::AnabaticEngine;
class SortSegmentByLength {
public:
inline SortSegmentByLength ( AnabaticEngine* );
inline bool operator() ( const Segment*, const Segment* );
private:
AnabaticEngine* _anabatic;
};
inline SortSegmentByLength::SortSegmentByLength ( AnabaticEngine* anabatic )
: _anabatic(anabatic)
{ }
inline bool SortSegmentByLength::operator() ( const Segment* lhs, const Segment* rhs )
{
NetData* lhsNData = _anabatic->getNetData( lhs->getNet() );
NetData* rhsNData = _anabatic->getNetData( rhs->getNet() );
if (lhsNData->isGlobalFixed() and not rhsNData->isGlobalFixed()) return true;
if (rhsNData->isGlobalFixed() and not lhsNData->isGlobalFixed()) return false;
DbU::Unit delta = rhs->getLength() - lhs->getLength();
if (delta > 0) return true;
if (delta < 0) return false;
return (lhs->getId() < rhs->getId());
}
} // Anonymous namespace.
namespace Anabatic { namespace Anabatic {
using std::cerr; using std::cerr;
using std::endl; using std::endl;
using Hurricane::Error; using Hurricane::Error;
using Hurricane::RoutingPad;
Name Edge::_extensionName = "Anabatic::Edge"; Name Edge::_extensionName = "Anabatic::Edge";
@ -38,7 +79,8 @@ namespace Anabatic {
Edge::Edge ( GCell* source, GCell* target, Flags flags ) Edge::Edge ( GCell* source, GCell* target, Flags flags )
: Super(source->getCell()) : Super(source->getCell())
, _flags (flags|Flags::Invalidated) , _flags (flags|Flags::Invalidated)
, _capacity (0) , _capacities (NULL)
, _reservedCapacity (0)
, _realOccupancy (0) , _realOccupancy (0)
, _estimateOccupancy(0.0) , _estimateOccupancy(0.0)
, _historicCost (0.0) , _historicCost (0.0)
@ -104,6 +146,7 @@ namespace Anabatic {
void Edge::_preDestroy () void Edge::_preDestroy ()
{ {
_source->getAnabatic()->_unrefCapacity( _capacities );
_source->_remove( this, _flags|Flags::Source ); _source->_remove( this, _flags|Flags::Source );
_target->_remove( this, _flags|Flags::Target ); _target->_remove( this, _flags|Flags::Target );
@ -169,7 +212,7 @@ namespace Anabatic {
DbU::Unit dy = targetCenter.getY() - sourceCenter.getY(); DbU::Unit dy = targetCenter.getY() - sourceCenter.getY();
if (dx < 0) dx = -dx; if (dx < 0) dx = -dx;
if (dx) dx += DbU::fromLambda( 0.1 ); //if (dx) dx += DbU::fromLambda( 0.1 );
return dx + ((dy > 0) ? dy : -dy); return dx + ((dy > 0) ? dy : -dy);
} }
@ -179,16 +222,18 @@ namespace Anabatic {
{ {
unsigned int occupancy = 0; unsigned int occupancy = 0;
if ((int)_realOccupancy + delta > 0) occupancy = _realOccupancy + delta; if ((int)_realOccupancy + delta > 0) occupancy = _realOccupancy + delta;
if ((_realOccupancy <= _capacity) and (occupancy > _capacity)) getAnabatic()->addOv ( this ); if ((_realOccupancy <= getCapacity()) and (occupancy > getCapacity())) getAnabatic()->addOv ( this );
if ((_realOccupancy > _capacity) and (occupancy <= _capacity)) getAnabatic()->removeOv( this ); if ((_realOccupancy > getCapacity()) and (occupancy <= getCapacity())) getAnabatic()->removeOv( this );
_realOccupancy = occupancy; _realOccupancy = occupancy;
} }
void Edge::incRealOccupancy2 ( int value ) void Edge::incRealOccupancy2 ( int value )
{ {
_realOccupancy += value; _realOccupancy += value;
} }
Segment* Edge::getSegment ( const Net* owner ) const Segment* Edge::getSegment ( const Net* owner ) const
{ {
for ( Segment* segment : _segments ) { for ( Segment* segment : _segments ) {
@ -198,16 +243,81 @@ namespace Anabatic {
} }
bool Edge::isEnding ( Segment* segment ) const
{
cdebug_log(112,0) << "Edge::isEnding() " << this << endl;
cdebug_log(112,0) << "| Sbb " << _source->getBoundingBox() << endl;
cdebug_log(112,0) << "| Tbb " << _target->getBoundingBox() << endl;
cdebug_log(112,0) << "| " << segment << endl;
if (Session::getRoutingGauge()->isTwoMetals()) {
Contact* contact = dynamic_cast<Contact*>( segment->getSource() );
cdebug_log(112,0) << "| source" << contact << endl;
if (contact) {
if ( (_source->isStdCellRow() and _source->getBoundingBox().contains(contact->getCenter()))
or (_target->isStdCellRow() and _target->getBoundingBox().contains(contact->getCenter())) )
return true;
}
contact = dynamic_cast<Contact*>( segment->getTarget() );
cdebug_log(112,0) << "| target" << contact << endl;
if (contact) {
if ( (_source->isStdCellRow() and _source->getBoundingBox().contains(contact->getCenter()))
or (_target->isStdCellRow() and _target->getBoundingBox().contains(contact->getCenter())) )
return true;
}
} else {
// This part is not used (yet). We don't call isEnding() when running
// in over-the-cell mode.
Contact* contact = dynamic_cast<Contact*>( segment->getSource() );
cdebug_log(112,0) << "| source" << contact << endl;
if (contact) {
for ( Hook* hook : contact->getBodyHook()->getHooks() ) {
if (dynamic_cast<RoutingPad*>(hook->getComponent())) {
if ( _source->getBoundingBox().contains(contact->getCenter())
or _target->getBoundingBox().contains(contact->getCenter()) )
return true;
break;
}
}
}
contact = dynamic_cast<Contact*>( segment->getTarget() );
cdebug_log(112,0) << "| target" << contact << endl;
if (contact) {
for ( Hook* hook : contact->getBodyHook()->getHooks() ) {
if (dynamic_cast<RoutingPad*>(hook->getComponent())) {
if ( _source->getBoundingBox().contains(contact->getCenter())
or _target->getBoundingBox().contains(contact->getCenter()) )
return true;
break;
}
}
}
}
return false;
}
void Edge::add ( Segment* segment ) void Edge::add ( Segment* segment )
{ {
_segments.push_back( segment ); _segments.push_back( segment );
Horizontal* h = dynamic_cast<Horizontal*>(segment); Horizontal* h = dynamic_cast<Horizontal*>(segment);
Vertical* v = dynamic_cast<Vertical*>(segment); Vertical* v = dynamic_cast<Vertical*>(segment);
DbU::Unit pitch = 0; DbU::Unit pitch = 0;
if (h) pitch = Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL2")); if (h) pitch = Session::getGHorizontalPitch();
if (v) pitch = Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL3")); if (v) pitch = Session::getGVerticalPitch();
incRealOccupancy( segment->getWidth()/pitch ); // Need to take the wire width into account. int deltaOccupancy = 0;
if (not Session::getRoutingGauge()->isTwoMetals()) deltaOccupancy = segment->getWidth()/pitch;
else {
// In channel routing, do not increase edge occupancy on terminals,
// because the capacity has already been decreased in annotedGlobalGraph (Katana).
if (not isEnding(segment)) deltaOccupancy = segment->getWidth()/pitch;
}
incRealOccupancy( deltaOccupancy );
} }
@ -215,12 +325,35 @@ namespace Anabatic {
{ {
for ( size_t i=0 ; i<_segments.size() ; ++i ) { for ( size_t i=0 ; i<_segments.size() ; ++i ) {
if (_segments[i] == segment) { if (_segments[i] == segment) {
cdebug_log(110,0) << "On " << this << endl;
cdebug_log(110,0) << "| remove:" << segment << endl;
std::swap( _segments[i], _segments[_segments.size()-1] ); std::swap( _segments[i], _segments[_segments.size()-1] );
_segments.pop_back(); _segments.pop_back();
incRealOccupancy( -1 ); // Need to take the wire width into account.
Horizontal* h = dynamic_cast<Horizontal*>(segment);
Vertical* v = dynamic_cast<Vertical*>(segment);
DbU::Unit pitch = 0;
if (h) pitch = Session::getGHorizontalPitch();
if (v) pitch = Session::getGVerticalPitch();
int deltaOccupancy = 0;
if (not Session::getRoutingGauge()->isTwoMetals()) deltaOccupancy = segment->getWidth()/pitch;
else {
// In channel routing, do not increase edge occupancy on terminals,
// because the capacity has already been decreased in annotedGlobalGraph (Katana).
if (not isEnding(segment)) deltaOccupancy = segment->getWidth()/pitch;
}
incRealOccupancy( -deltaOccupancy );
return; return;
} }
} }
cerr << Error( "On %s,\n segment doesn't belong: %s"
, getString(this).c_str()
, getString(segment).c_str() ) << endl;
} }
@ -237,19 +370,43 @@ namespace Anabatic {
size_t Edge::ripup () size_t Edge::ripup ()
{ {
AnabaticEngine* anabatic = getAnabatic(); AnabaticEngine* anabatic = getAnabatic();
DbU::Unit globalThreshold = Session::getSliceHeight()*3; size_t netCount = 0;
size_t netCount = 0;
for ( size_t i=0 ; i<_segments.size(); ) { sort( _segments.begin(), _segments.end(), SortSegmentByLength(anabatic) );
if (_segments[i]->getLength() >= globalThreshold) {
NetData* netData = anabatic->getNetData( _segments[i]->getNet() );
if (netData->isGlobalRouted()) ++netCount;
anabatic->ripup( _segments[i], Flags::Propagate ); if (Session::getRoutingGauge()->isTwoMetals()) {
} else for ( size_t i=0 ; i<_segments.size() ; ) {
if (not isEnding(_segments[i])) {
NetData* netData = anabatic->getNetData( _segments[i]->getNet() );
if (netData->isGlobalFixed ()) break;
if (netData->isGlobalRouted()) ++netCount;
anabatic->ripup( _segments[i], Flags::Propagate );
continue;
}
++i; ++i;
}
} else {
size_t truncate = (size_t)( (getCapacity()*2) / 3 );
while ( _segments.size() > truncate ) {
NetData* netData = anabatic->getNetData( _segments[truncate]->getNet() );
if (netData->isGlobalFixed ()) break;
if (netData->isGlobalRouted()) ++netCount;
anabatic->ripup( _segments[truncate], Flags::Propagate );
}
// DbU::Unit globalThreshold = Session::getSliceHeight()*3;
// for ( size_t i=0 ; i<_segments.size() ; ) {
// if (_segments[i]->getLength() >= globalThreshold) {
// NetData* netData = anabatic->getNetData( _segments[i]->getNet() );
// if (netData->isGlobalRouted()) ++netCount;
// anabatic->ripup( _segments[i], Flags::Propagate );
// } else {
// ++i;
// }
// }
} }
return netCount; return netCount;
} }
@ -259,7 +416,7 @@ namespace Anabatic {
if (source == _target) if (source == _target)
throw Error("Edge::_setSource(): Source & target are the same (%s).", getString(source).c_str() ); throw Error("Edge::_setSource(): Source & target are the same (%s).", getString(source).c_str() );
_invalidate(); invalidate( false );
_source=source; _source=source;
} }
@ -269,26 +426,41 @@ namespace Anabatic {
if (_source == target) if (_source == target)
throw Error("Edge::_setTarget(): Source & target are the same (%s).", getString(target).c_str() ); throw Error("Edge::_setTarget(): Source & target are the same (%s).", getString(target).c_str() );
_invalidate(); invalidate( false );
_target=target; _target=target;
} }
void Edge::_invalidate () void Edge::invalidate ( bool )
{ {
cdebug_log(110,1) << "Edge::invalidate() " << this << endl;
_flags |= Flags::Invalidated; _flags |= Flags::Invalidated;
Super::invalidate( false ); Super::invalidate( false );
cdebug_tabw(110,-1);
} }
void Edge::_revalidate () void Edge::materialize ()
{ {
Interval side = getSide(); cdebug_log(110,1) << "Edge::materialize() " << this << endl;
_axis = side.getCenter();
_capacity = getAnabatic()->getCapacity( side, _flags ); Flags flags = _flags;
Interval side = getSide();
_axis = side.getCenter();
if (getSource()->isStdCellRow() and getTarget()->isStdCellRow()) flags |= Flags::NullCapacity;
else if (getSource()->isChannelRow() and getTarget()->isChannelRow()) flags |= Flags::InfiniteCapacity;
_capacities = getAnabatic()->_createCapacity( _flags, side );
_flags.reset( Flags::Invalidated ); _flags.reset( Flags::Invalidated );
cdebug_log(110,0) << "Edge::_revalidate() " << this << endl; cdebug_log(110,0) << "Edge::materialize() " << this << endl;
Super::materialize();
cdebug_tabw(110,-1);
} }
@ -301,28 +473,31 @@ namespace Anabatic {
static DbU::Unit halfThickness = getAnabatic()->getConfiguration()->getEdgeWidth () / 2; static DbU::Unit halfThickness = getAnabatic()->getConfiguration()->getEdgeWidth () / 2;
static DbU::Unit halfLength = getAnabatic()->getConfiguration()->getEdgeLength() / 2; static DbU::Unit halfLength = getAnabatic()->getConfiguration()->getEdgeLength() / 2;
if (_flags.isset(Flags::Horizontal)) Box bb;
return Box( _target->getXMin() - halfLength, _axis - halfThickness
, _target->getXMin() + halfLength, _axis + halfThickness
);
return Box( _axis - halfThickness, _target->getYMin() - halfLength if (_flags.isset(Flags::Horizontal))
bb = Box( _target->getXMin() - halfLength, _axis - halfThickness
, _target->getXMin() + halfLength, _axis + halfThickness
);
else
bb = Box( _axis - halfThickness, _target->getYMin() - halfLength
, _axis + halfThickness, _target->getYMin() + halfLength , _axis + halfThickness, _target->getYMin() + halfLength
); );
return bb;
} }
bool Edge::isMaxCapacity ( Net* net ) const bool Edge::isMaxCapacity ( Net* net ) const
{ {
if (net){ unsigned int wpitch = 0;
Hurricane::NetRoutingState* state = Hurricane::NetRoutingExtension::get( net ); if (net) {
//cerr << "bool Edge::isMaxCapacity ( Net* net ) const: " << net << endl; cdebug_log(112,0) << "_capacity:" << getCapacity() << endl;
//cerr << "WPitch: " << state->getWPitch() << endl;
return ( (_realOccupancy +state->getWPitch()) > _capacity ) ? true : false; Hurricane::NetRoutingState* state = Hurricane::NetRoutingExtension::get( net );
} else { wpitch = (state) ? state->getWPitch()-1 : 0;
return ( _realOccupancy >= _capacity ) ? true : false;
} }
return (_realOccupancy + wpitch >= getCapacity());
} }
@ -348,7 +523,7 @@ namespace Anabatic {
s.insert( s.size()-1, " " +DbU::getValueString(center.getY()) ); s.insert( s.size()-1, " " +DbU::getValueString(center.getY()) );
s.insert( s.size()-1, "] " +DbU::getValueString(_axis) ); s.insert( s.size()-1, "] " +DbU::getValueString(_axis) );
s.insert( s.size()-1, " " +getString(_realOccupancy) ); s.insert( s.size()-1, " " +getString(_realOccupancy) );
s.insert( s.size()-1, "/" +getString(_capacity) ); s.insert( s.size()-1, "/" +getString(getCapacity()) );
s.insert( s.size()-1, " h:" +getString(_historicCost) ); s.insert( s.size()-1, " h:" +getString(_historicCost) );
s.insert( s.size()-1, " " +getString(_flags) ); s.insert( s.size()-1, " " +getString(_flags) );
return s; return s;
@ -359,7 +534,8 @@ namespace Anabatic {
{ {
Record* record = Super::_getRecord(); Record* record = Super::_getRecord();
record->add( getSlot("_flags" , _flags ) ); record->add( getSlot("_flags" , _flags ) );
record->add( getSlot("_capacity" , _capacity ) ); record->add( getSlot("_capacities" , _capacities ) );
record->add( getSlot("_reservedCapacity" , _reservedCapacity ) );
record->add( getSlot("_realOccupancy" , _realOccupancy ) ); record->add( getSlot("_realOccupancy" , _realOccupancy ) );
record->add( getSlot("_estimateOccupancy", _estimateOccupancy) ); record->add( getSlot("_estimateOccupancy", _estimateOccupancy) );
record->add( getSlot("_source" , _source ) ); record->add( getSlot("_source" , _source ) );

View File

@ -0,0 +1,123 @@
// -*- mode: C++; explicit-buffer-name: "EdgeCapacity.cpp<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2018-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./EdgeCapacity.cpp" |
// +-----------------------------------------------------------------+
#include <sstream>
#include "anabatic/EdgeCapacity.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using std::ostringstream;
EdgeCapacity::EdgeCapacity ( AnabaticEngine* anabatic, Flags direction, Interval span, size_t depth )
: _anabatic (anabatic)
, _refCount (0)
, _flags (direction)
, _depth (depth+1)
, _span (span)
, _capacities()
{
int defcap = (_flags & Flags::InfiniteCapacity) ? 100 : 0;
_capacities.reserve( _depth );
for ( size_t i=0 ; i<_depth ; ++i ) _capacities.push_back( defcap );
if (_flags & (Flags::NullCapacity|Flags::InfiniteCapacity)) return;
Box ab = _anabatic->getCell()->getAbutmentBox();
RoutingGauge* rg = _anabatic->getConfiguration()->getRoutingGauge();
span = _span;
span.inflate( 0, -1 );
if (span.isEmpty()) return;
const vector<RoutingLayerGauge*>& layerGauges = rg->getLayerGauges();
for ( size_t depth=0 ; depth < _depth ; ++depth ) {
if (layerGauges[depth]->getType() != Constant::Default) continue;
if (_flags & Flags::Horizontal) {
if (layerGauges[depth]->getDirection() != Constant::Horizontal) continue;
_capacities[depth] = layerGauges[depth]->getTrackNumber( span.getVMin() - ab.getYMin()
, span.getVMax() - ab.getYMin() );
//cdebug_log(110,0) << "Horizontal edge capacity:" << capacity << endl;
}
if (_flags & Flags::Vertical) {
if (layerGauges[depth]->getDirection() != Constant::Vertical) continue;
_capacities[depth] = layerGauges[depth]->getTrackNumber( span.getVMin() - ab.getXMin()
, span.getVMax() - ab.getXMin() );
//cdebug_log(110,0) << "Vertical edge capacity:" << capacity << endl;
}
}
}
void EdgeCapacity::forceCapacity ( unsigned int capacity )
{
bool forced = false;
RoutingGauge* rg = _anabatic->getConfiguration()->getRoutingGauge();
const vector<RoutingLayerGauge*>& layerGauges = rg->getLayerGauges();
for ( size_t i=0 ; i<_depth ; ++i ) {
if (layerGauges[i]->getType() != Constant::Default) continue;
if ( (_flags & Flags::Horizontal) xor layerGauges[i]->isHorizontal() ) continue;
if (forced) _capacities[i] = 0;
else {
_capacities[i] = capacity;
forced = true;
}
}
}
string EdgeCapacity::_getString () const
{
ostringstream os;
os << "<EdgeCapacity ";
if (_flags & Flags::Horizontal) os << "Horizontal ";
else if (_flags & Flags::Vertical ) os << "Vertical ";
else os << "Unknown ";
os << "[" << DbU::getValueString(_span.getVMin())
<< " : " << DbU::getValueString(_span.getVMax())
<< "] " << getCapacity()
<< " refs:" << _refCount
<< ">";
return os.str();
}
Record* EdgeCapacity::_getRecord () const
{
Record* record = new Record( getString(this) );
record->add( getSlot( "_anabatic", _anabatic ) );
record->add( getSlot( "_refCount", _refCount ) );
record->add( getSlot( "_flags" , &_flags ) );
record->add( getSlot( "_span" , &_span ) );
RoutingGauge* rg = getAnabatic()->getConfiguration()->getRoutingGauge();
for ( size_t depth=0 ; depth<_depth ; ++depth ) {
ostringstream s;
const Layer* layer = rg->getRoutingLayer(depth);
s << "_capacities[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
record->add( getSlot ( s.str(), _capacities[depth] ) );
}
return record;
}
} // Anabatic namespace.

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Edges.cpp<anabatic>" -*- // -*- mode: C++; explicit-buffer-name: "Edges.cpp<anabatic>" -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved // Copyright (c) UPMC 2016-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -20,6 +20,7 @@
namespace Anabatic { namespace Anabatic {
using std::cerr;
using std::endl; using std::endl;
@ -63,10 +64,10 @@ namespace Anabatic {
{ {
cdebug_log(110,0) << "GCell_Edges::Locator::progress() [from] " << _stateFlags << " iedge:" << _iedge << endl; cdebug_log(110,0) << "GCell_Edges::Locator::progress() [from] " << _stateFlags << " iedge:" << _iedge << endl;
cdebug_log(110,0) << " _filterFlags:" << _filterFlags << endl; cdebug_log(110,0) << " _filterFlags:" << _filterFlags << endl;
cdebug_log(110,0) << " East:" << _gcell->getEastEdges().size() cdebug_log(110,0) << " East:" << _gcell->getEastEdges ().size()
<< " North:" << _gcell->getNorthEdges().size() << " North:" << _gcell->getNorthEdges().size()
<< " West:" << _gcell->getWestEdges().size() << " West:" << _gcell->getWestEdges ().size()
<< " South:" << _gcell->getSouthEdges().size() << endl; << " South:" << _gcell->getSouthEdges().size() << endl;
cdebug_log(110,0) << this << endl; cdebug_log(110,0) << this << endl;
++_iedge; ++_iedge;
@ -74,7 +75,7 @@ namespace Anabatic {
if (_stateFlags.contains(Flags::EastSide)) { if (_stateFlags.contains(Flags::EastSide)) {
if ( (_iedge < _gcell->getEastEdges().size()) if ( (_iedge < _gcell->getEastEdges().size())
and _filterFlags.contains(Flags::EastSide)) break; and _filterFlags.contains(Flags::EastSide)) break;
// cdebug_log(110,0) << "Switching to North side." << endl; //cdebug_log(110,0) << "Switching to North side." << endl;
_stateFlags = Flags::NorthSide; _stateFlags = Flags::NorthSide;
_iedge = 0; _iedge = 0;
// cdebug_log(110,0) << this << endl; // cdebug_log(110,0) << this << endl;
@ -83,7 +84,7 @@ namespace Anabatic {
if (_stateFlags.contains(Flags::NorthSide)) { if (_stateFlags.contains(Flags::NorthSide)) {
if ( (_iedge < _gcell->getNorthEdges().size()) if ( (_iedge < _gcell->getNorthEdges().size())
and _filterFlags.contains(Flags::NorthSide)) break; and _filterFlags.contains(Flags::NorthSide)) break;
// cdebug_log(110,0) << "Switching to West side." << endl; //cdebug_log(110,0) << "Switching to West side." << endl;
_stateFlags = Flags::WestSide; _stateFlags = Flags::WestSide;
_iedge = 0; _iedge = 0;
// cdebug_log(110,0) << this << endl; // cdebug_log(110,0) << this << endl;
@ -92,7 +93,7 @@ namespace Anabatic {
if (_stateFlags.contains(Flags::WestSide)) { if (_stateFlags.contains(Flags::WestSide)) {
if ( (_iedge < _gcell->getWestEdges().size()) if ( (_iedge < _gcell->getWestEdges().size())
and _filterFlags.contains(Flags::WestSide)) break; and _filterFlags.contains(Flags::WestSide)) break;
// cdebug_log(110,0) << "Switching to South side." << endl; //cdebug_log(110,0) << "Switching to South side." << endl;
_stateFlags = Flags::SouthSide; _stateFlags = Flags::SouthSide;
_iedge = 0; _iedge = 0;
continue; continue;
@ -100,7 +101,7 @@ namespace Anabatic {
if (_stateFlags.contains(Flags::SouthSide)) { if (_stateFlags.contains(Flags::SouthSide)) {
if ( (_iedge < _gcell->getSouthEdges().size()) if ( (_iedge < _gcell->getSouthEdges().size())
and _filterFlags.contains(Flags::SouthSide)) break; and _filterFlags.contains(Flags::SouthSide)) break;
// cdebug_log(110,0) << "All edges done." << endl; //cdebug_log(110,0) << "All edges done." << endl;
_stateFlags = 0; _stateFlags = 0;
_iedge = 0; _iedge = 0;
break;; break;;
@ -141,4 +142,144 @@ namespace Anabatic {
} }
// -------------------------------------------------------------------
// Class : "Anabatic::Path_Edges".
Path_Edges::Locator::Locator ( const GCell* source, const GCell* target, Flags pathFlags )
: EdgesHL()
, _source (source)
, _target (target)
, _stateFlags(Flags::NoFlags)
, _uprobe (0)
, _edge (NULL)
{
if (_source == _target) return;
Interval hoverlap = _source->getHSide().getIntersection( _target->getHSide() );
Interval voverlap = _source->getVSide().getIntersection( _target->getVSide() );
if (not voverlap.isEmpty()) {
if (_source->getXMin() > _target->getXMin()) std::swap( _source, _target );
_stateFlags |= Flags::EastSide;
_uprobe = voverlap.getCenter();
} else if (not hoverlap.isEmpty()) {
if (_source->getYMin() > _target->getYMin()) std::swap( _source, _target );
_stateFlags |= Flags::NorthSide;
_uprobe = hoverlap.getCenter();
} else {
if (_source->getXMin() > _target->getXMin()) {
std::swap( _source, _target );
}
if (_source->getYMin() < _target->getYMin()) {
if (pathFlags & Flags::NorthPath) {
_stateFlags |= Flags::NorthSide;
_uprobe = _source->getXCenter();
} else {
_stateFlags |= Flags::EastSide;
_uprobe = _source->getYCenter();
}
} else {
if (pathFlags & Flags::NorthPath) {
_stateFlags |= Flags::EastSide;
_uprobe = _source->getYCenter();
} else {
_stateFlags |= Flags::SouthSide;
_uprobe = _source->getXCenter();
}
}
}
_edge = _source->getEdgeAt( _stateFlags, _uprobe );
}
EdgesHL* Path_Edges::Locator::getClone () const
{ return new Locator (*this); }
Edge* Path_Edges::Locator::getElement () const
{ return _edge; }
bool Path_Edges::Locator::isValid () const
{ return (_edge != NULL); }
void Path_Edges::Locator::progress ()
{
if (not _edge) return;
GCell* neighbor = NULL;
if (_stateFlags.contains(Flags::SouthSide) or _stateFlags.contains(Flags::WestSide)) neighbor = _edge->getSource();
if (_stateFlags.contains(Flags::NorthSide) or _stateFlags.contains(Flags::EastSide)) neighbor = _edge->getTarget();
if (neighbor == _target) { _edge = NULL; return; }
if (_stateFlags.contains(Flags::EastSide)) {
Interval overlap = neighbor->getHSide().getIntersection( _target->getHSide() );
if (not overlap.isEmpty()) {
overlap = neighbor->getVSide().getIntersection( _target->getVSide() );
if (not overlap.isEmpty()) { _edge = NULL; return; }
_stateFlags.reset( Flags::EastSide );
_stateFlags |= (_target->getYMin() < _source->getYMin()) ? Flags::SouthSide
: Flags::NorthSide;
_uprobe = overlap.getCenter();
}
} else if (_stateFlags.contains(Flags::SouthSide)) {
Interval overlap = neighbor->getVSide().getIntersection( _target->getVSide() );
if (not overlap.isEmpty()) {
overlap = neighbor->getHSide().getIntersection( _target->getHSide() );
if (not overlap.isEmpty()) {
_edge = NULL; return; }
_stateFlags.reset( Flags::SouthSide );
_stateFlags |= Flags::EastSide;
_uprobe = overlap.getCenter();
}
} else if (_stateFlags.contains(Flags::NorthSide)) {
Interval overlap = neighbor->getVSide().getIntersection( _target->getVSide() );
if (not overlap.isEmpty()) {
overlap = neighbor->getHSide().getIntersection( _target->getHSide() );
if (not overlap.isEmpty()) { _edge = NULL; return; }
_stateFlags.reset( Flags::NorthSide );
_stateFlags |= Flags::EastSide;
_uprobe = overlap.getCenter();
}
}
_edge = neighbor->getEdgeAt( _stateFlags, _uprobe );
}
string Path_Edges::Locator::_getString () const
{
string s = "<Path_Edges::Locator @" + getString(_edge) + ">";
return s;
}
EdgesHC* Path_Edges::getClone () const
{ return new Path_Edges( *this ); }
EdgesHL* Path_Edges::getLocator () const
{ return new Locator (_source,_target,_pathFlags); }
string Path_Edges::_getString () const
{
string s = "<Path_Edges from:"
+ getString(_source) + "to:"
+ getString(_target)
+ ">";
return s;
}
} // Anabatic namespace. } // Anabatic namespace.

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "GCell.cpp<anabatic>" -*- // -*- mode: C++; explicit-buffer-name: "GCell.cpp<anabatic>" -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved // Copyright (c) UPMC 2016-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -55,7 +55,7 @@ namespace {
private: private:
class AxisCompare { class AxisCompare {
public: public:
bool operator() ( const Axis* lhs, const Axis* rhs ); bool operator() ( const Axis* lhs, const Axis* rhs ) const;
}; };
class AxisMatch : public unary_function<Axis*,bool> { class AxisMatch : public unary_function<Axis*,bool> {
@ -155,7 +155,7 @@ namespace {
} }
inline bool UsedFragments::AxisCompare::operator() ( const Axis* lhs, const Axis* rhs ) inline bool UsedFragments::AxisCompare::operator() ( const Axis* lhs, const Axis* rhs ) const
{ {
if (lhs->getAxis () < rhs->getAxis ()) return true; if (lhs->getAxis () < rhs->getAxis ()) return true;
return false; return false;
@ -259,7 +259,7 @@ namespace Anabatic {
{ } { }
bool GCell::CompareByDensity::operator() ( GCell* lhs, GCell* rhs ) bool GCell::CompareByDensity::operator() ( GCell* lhs, GCell* rhs ) const
{ {
float difference = lhs->getDensity(_depth) - rhs->getDensity(_depth); float difference = lhs->getDensity(_depth) - rhs->getDensity(_depth);
if (difference != 0.0) return (difference > 0.0); if (difference != 0.0) return (difference > 0.0);
@ -273,6 +273,8 @@ namespace Anabatic {
Name GCell::_extensionName = "Anabatic::GCell"; Name GCell::_extensionName = "Anabatic::GCell";
uint32_t GCell::_displayMode = GCell::Boundary; uint32_t GCell::_displayMode = GCell::Boundary;
DbU::Unit GCell::_matrixHSide = 0;
DbU::Unit GCell::_matrixVSide = 0;
uint32_t GCell::getDisplayMode () { return _displayMode; } uint32_t GCell::getDisplayMode () { return _displayMode; }
@ -283,7 +285,7 @@ namespace Anabatic {
: Super(anabatic->getCell()) : Super(anabatic->getCell())
, _observable () , _observable ()
, _anabatic (anabatic) , _anabatic (anabatic)
, _flags (Flags::HChannelGCell|Flags::Invalidated) , _flags (Flags::Invalidated)
, _westEdges () , _westEdges ()
, _eastEdges () , _eastEdges ()
, _southEdges () , _southEdges ()
@ -296,6 +298,8 @@ namespace Anabatic {
, _contacts () , _contacts ()
, _depth (Session::getRoutingGauge()->getDepth()) , _depth (Session::getRoutingGauge()->getDepth())
, _pinDepth (0) , _pinDepth (0)
, _satProcessed (0)
, _rpCount (0)
, _blockages (new DbU::Unit [_depth]) , _blockages (new DbU::Unit [_depth])
, _cDensity (0.0) , _cDensity (0.0)
, _densities (new float [_depth]) , _densities (new float [_depth])
@ -303,7 +307,16 @@ namespace Anabatic {
, _fragmentations(new float [_depth]) , _fragmentations(new float [_depth])
, _globalsCount (new float [_depth]) , _globalsCount (new float [_depth])
, _key (this,1) , _key (this,1)
, _lastClonedKey (NULL)
{ {
if (not _matrixHSide) {
_matrixVSide = Session::getSliceHeight();
_matrixHSide = Session::getSliceHeight();
if (_matrixHSide % Session::getSliceStep())
_matrixHSide += Session::getSliceStep() - _matrixHSide % Session::getSliceStep();
}
for ( size_t i=0 ; i<_depth ; i++ ) { for ( size_t i=0 ; i<_depth ; i++ ) {
_blockages [i] = 0; _blockages [i] = 0;
_densities [i] = 0.0; _densities [i] = 0.0;
@ -331,13 +344,13 @@ namespace Anabatic {
if (not anabatic) throw Error( "GCell::create(): NULL anabatic argument." ); if (not anabatic) throw Error( "GCell::create(): NULL anabatic argument." );
if (not anabatic->getCell()) throw Error( "GCell::create(): AnabaticEngine has no Cell loaded." ); if (not anabatic->getCell()) throw Error( "GCell::create(): AnabaticEngine has no Cell loaded." );
anabatic->openSession(); bool reUseSession = Session::isOpen();
if (not reUseSession) anabatic->openSession();
GCell* gcell = new GCell ( anabatic GCell* gcell = new GCell ( anabatic
, anabatic->getCell()->getAbutmentBox().getXMin() , anabatic->getCell()->getAbutmentBox().getXMin()
, anabatic->getCell()->getAbutmentBox().getYMin() ); , anabatic->getCell()->getAbutmentBox().getYMin() );
gcell->_postCreate(); gcell->_postCreate();
gcell->_revalidate(); if (not reUseSession) Session::close();
Session::close();
return gcell; return gcell;
} }
@ -447,6 +460,14 @@ namespace Anabatic {
} }
bool GCell::isHorizontalPlane ( size_t depth ) const
{ return _anabatic->getConfiguration()->getLayerGauge(depth)->isHorizontal(); }
bool GCell::isVerticalPlane ( size_t depth ) const
{ return _anabatic->getConfiguration()->getLayerGauge(depth)->isVertical(); }
Contact* GCell::hasGContact ( const Net* net ) const Contact* GCell::hasGContact ( const Net* net ) const
{ {
for ( Contact* contact : _gcontacts ) { for ( Contact* contact : _gcontacts ) {
@ -456,6 +477,26 @@ namespace Anabatic {
} }
bool GCell::hasNet ( const Net* net ) const
{
if (hasGContact(net)) return true;
for ( Edge* edge : _eastEdges ) {
for ( Segment* segment : edge->getSegments() ) {
if (segment->getNet() == net) return true;
}
}
for ( Edge* edge : _northEdges ) {
for ( Segment* segment : edge->getSegments() ) {
if (segment->getNet() == net) return true;
}
}
return false;
}
Contact* GCell::hasGContact ( const Contact* owned ) const Contact* GCell::hasGContact ( const Contact* owned ) const
{ {
for ( Contact* contact : _gcontacts ) { for ( Contact* contact : _gcontacts ) {
@ -467,6 +508,9 @@ namespace Anabatic {
Contact* GCell::breakGoThrough ( Net* net ) Contact* GCell::breakGoThrough ( Net* net )
{ {
Contact* gcontact = hasGContact( net );
if (gcontact) return gcontact;
for ( Edge* edge : _eastEdges ) { for ( Edge* edge : _eastEdges ) {
for ( Segment* segment : edge->getSegments() ) { for ( Segment* segment : edge->getSegments() ) {
if (segment->getNet() == net) if (segment->getNet() == net)
@ -481,6 +525,22 @@ namespace Anabatic {
} }
} }
return getGContact( net );
}
Segment* GCell::hasGoThrough ( Net* net ) const
{
for ( Edge* edge : _eastEdges ) {
for ( Segment* segment : edge->getSegments() ) {
if (segment->getNet() == net) return segment;
}
}
for ( Edge* edge : _northEdges ) {
for ( Segment* segment : edge->getSegments() ) {
if (segment->getNet() == net) return segment;
}
}
return NULL; return NULL;
} }
@ -498,13 +558,49 @@ namespace Anabatic {
{ {
for ( Edge* edge : getEdges(sideHint) ) { for ( Edge* edge : getEdges(sideHint) ) {
GCell* side = edge->getOpposite(this); GCell* side = edge->getOpposite(this);
if ( (sideHint & (Flags::WestSide |Flags::EastSide )) and (u < side->getYMax()) ) return edge; if ( (sideHint.contains(Flags::WestSide) or sideHint.contains(Flags::EastSide ))
if ( (sideHint & (Flags::SouthSide|Flags::NorthSide)) and (u < side->getXMax()) ) return edge; and (u < side->getYMax()) ) {
cdebug_log(112,0) << "H Opposite @" << DbU::getValueString(u) << " is: " << side << endl;
return edge;
}
if ( (sideHint.contains(Flags::SouthSide) or sideHint.contains(Flags::NorthSide))
and (u < side->getXMax()) ) {
cdebug_log(112,0) << "V Opposite @" << DbU::getValueString(u) << " is: " << side << endl;
return edge;
}
} }
return NULL; return NULL;
} }
GCell* GCell::getEastNMatrix() const
{
if (!this->getEast()->isMatrix()) return this->getEast();
else {
GCell* gcell = this->getEast();
while(gcell->getEast()){
if (!gcell->getEast()->isMatrix()) break;
else gcell = gcell->getEast();
}
return gcell->getEast();
}
}
GCell* GCell::getNorthNMatrix() const
{
if (!this->getNorth()->isMatrix()) return this->getNorth();
else {
GCell* gcell = this->getNorth();
while(gcell->getNorth()){
if (!gcell->getNorth()->isMatrix()) break;
else gcell = gcell->getNorth();
}
return gcell->getNorth();
}
}
GCell* GCell::getWest ( DbU::Unit y ) const GCell* GCell::getWest ( DbU::Unit y ) const
{ {
for ( Edge* edge : _westEdges ) { for ( Edge* edge : _westEdges ) {
@ -559,8 +655,6 @@ namespace Anabatic {
{ {
const GCell* current = this; const GCell* current = this;
if (not this) cerr << Error("*this* is NULL!") << endl;
while ( current ) { while ( current ) {
if (not current->isFlat() and current->getBoundingBox().contains(x,y)) break; if (not current->isFlat() and current->getBoundingBox().contains(x,y)) break;
@ -633,15 +727,17 @@ namespace Anabatic {
size_t iedge = 0; size_t iedge = 0;
for ( ; (iedge < _southEdges.size()) ; ++iedge ) { for ( ; (iedge < _southEdges.size()) ; ++iedge ) {
cdebug_log(110,0) << "[" << iedge << "] xmax of:" cdebug_log(110,0) << "[" << iedge << "] xmax of:"
<< _southEdges[iedge]->getOpposite(this) << _southEdges[iedge]->getOpposite(this)
<< " " << _southEdges[iedge] << endl; << " " << _southEdges[iedge] << endl;
if (x <= _southEdges[iedge]->getOpposite(this)->getXMax()) break; if (x <= _southEdges[iedge]->getOpposite(this)->getXMax()) break;
} }
if ( (x < _southEdges[iedge]->getOpposite(this)->getXMax()) if ( (x < _southEdges[iedge]->getOpposite(this)->getXMax())
or ( (x == _southEdges[iedge]->getOpposite(this)->getXMax()) or ( (x == _southEdges[iedge]->getOpposite(this)->getXMax())
and (chunk->getXMax() == getXMax())) ) and (chunk->getXMax() == getXMax())) ) {
Edge::create( _southEdges[iedge]->getOpposite(this), chunk, Flags::Vertical ); Edge::create( _southEdges[iedge]->getOpposite(this), chunk, Flags::Vertical );
_southEdges[iedge]->invalidate( false );
}
_moveEdges( chunk, iedge+1, Flags::SouthSide ); _moveEdges( chunk, iedge+1, Flags::SouthSide );
} }
@ -655,15 +751,14 @@ namespace Anabatic {
if ( (x < _northEdges[iedge]->getOpposite(this)->getXMax()) if ( (x < _northEdges[iedge]->getOpposite(this)->getXMax())
or ( (x == _northEdges[iedge]->getOpposite(this)->getXMax()) or ( (x == _northEdges[iedge]->getOpposite(this)->getXMax())
and (chunk->getXMax() == getXMax())) ) and (chunk->getXMax() == getXMax())) ) {
Edge::create( chunk, _northEdges[iedge]->getOpposite(this), Flags::Vertical ); Edge::create( chunk, _northEdges[iedge]->getOpposite(this), Flags::Vertical );
_northEdges[iedge]->invalidate( false );
}
_moveEdges( chunk, iedge+1, Flags::NorthSide ); _moveEdges( chunk, iedge+1, Flags::NorthSide );
} }
_revalidate();
chunk->_revalidate();
cdebug_tabw(110,-1); cdebug_tabw(110,-1);
return chunk; return chunk;
@ -694,8 +789,10 @@ namespace Anabatic {
if ( (y < _westEdges[iedge]->getOpposite(this)->getYMax()) if ( (y < _westEdges[iedge]->getOpposite(this)->getYMax())
or ( (y == _westEdges[iedge]->getOpposite(this)->getYMax()) or ( (y == _westEdges[iedge]->getOpposite(this)->getYMax())
and (chunk->getYMax() == getYMax())) ) and (chunk->getYMax() == getYMax())) ) {
Edge::create( _westEdges[iedge]->getOpposite(this), chunk, Flags::Horizontal ); Edge::create( _westEdges[iedge]->getOpposite(this), chunk, Flags::Horizontal );
_westEdges[iedge]->invalidate( false );
}
_moveEdges( chunk, iedge+1, Flags::WestSide ); _moveEdges( chunk, iedge+1, Flags::WestSide );
} }
@ -707,15 +804,14 @@ namespace Anabatic {
if ( (y < _eastEdges[iedge]->getOpposite(this)->getYMax()) if ( (y < _eastEdges[iedge]->getOpposite(this)->getYMax())
or ( (y == _eastEdges[iedge]->getOpposite(this)->getYMax()) or ( (y == _eastEdges[iedge]->getOpposite(this)->getYMax())
and (chunk->getYMax() == getYMax())) ) and (chunk->getYMax() == getYMax())) ) {
Edge::create( chunk, _eastEdges[iedge]->getOpposite(this), Flags::Horizontal ); Edge::create( chunk, _eastEdges[iedge]->getOpposite(this), Flags::Horizontal );
_eastEdges[iedge]->invalidate( false );
}
_moveEdges( chunk, iedge+1, Flags::EastSide ); _moveEdges( chunk, iedge+1, Flags::EastSide );
} }
_revalidate();
chunk->_revalidate();
cdebug_tabw(110,-1); cdebug_tabw(110,-1);
return chunk; return chunk;
@ -724,47 +820,49 @@ namespace Anabatic {
bool GCell::doGrid () bool GCell::doGrid ()
{ {
getAnabatic()->openSession(); bool openSession = Session::isOpen();
if (not openSession) getAnabatic()->openSession();
DbU::Unit side = Session::getSliceHeight(); DbU::Unit vside = getMatrixVSide();
DbU::Unit hside = getMatrixHSide();
Interval hspan = getSide( Flags::Horizontal ); Interval hspan = getSide( Flags::Horizontal );
Interval vspan = getSide( Flags::Vertical ); Interval vspan = getSide( Flags::Vertical );
if (hspan.getSize() < 3*side) { // if (hspan.getSize() < 2*hside) {
cerr << Error( "GCell::doGrid(): GCell is too narrow (dx:%s) to build a grid.\n" // cerr << Error( "GCell::doGrid(): GCell is too narrow (dx:%s) to build a grid.\n"
" (%s)" // " (%s)"
, DbU::getValueString(hspan.getSize()).c_str() // , DbU::getValueString(hspan.getSize()).c_str()
, getString(this).c_str() // , getString(this).c_str()
) << endl; // ) << endl;
Session::close(); // Session::close();
return false; // return false;
} // }
if (vspan.getSize() < 3*side) { // if (vspan.getSize() < 2*vside) {
cerr << Error( "GCell::doGrid(): GCell is too narrow (dy:%s) to build a grid.\n" // cerr << Error( "GCell::doGrid(): GCell is too narrow (dy:%s) to build a grid.\n"
" (%s)" // " (%s)"
, DbU::getValueString(vspan.getSize()).c_str() // , DbU::getValueString(vspan.getSize()).c_str()
, getString(this).c_str() // , getString(this).c_str()
) << endl; // ) << endl;
return false; // return false;
} // }
GCell* row = this; GCell* row = this;
GCell* column = NULL; GCell* column = NULL;
DbU::Unit ycut = vspan.getVMin()+side; DbU::Unit ycut = vspan.getVMin()+vside;
for ( ; ycut < vspan.getVMax() ; ycut += side ) { for ( ; ycut < vspan.getVMax() ; ycut += vside ) {
column = row; column = row;
row = row->hcut( ycut ); row = row->hcut( ycut );
row->setType( Flags::MatrixGCell ); row->setType( Flags::MatrixGCell );
for ( DbU::Unit xcut = hspan.getVMin()+side ; xcut < hspan.getVMax() ; xcut += side ) { for ( DbU::Unit xcut = hspan.getVMin()+hside ; xcut < hspan.getVMax() ; xcut += hside ) {
column = column->vcut( xcut ); column = column->vcut( xcut );
column->setType( Flags::MatrixGCell ); column->setType( Flags::MatrixGCell );
} }
} }
column = row; column = row;
for ( DbU::Unit xcut = hspan.getVMin()+side ; xcut < hspan.getVMax() ; xcut += side ) { for ( DbU::Unit xcut = hspan.getVMin()+hside ; xcut < hspan.getVMax() ; xcut += hside ) {
column = column->vcut( xcut ); column = column->vcut( xcut );
column->setType( Flags::MatrixGCell ); column->setType( Flags::MatrixGCell );
} }
@ -782,26 +880,39 @@ namespace Anabatic {
// } // }
//} //}
Session::close(); if (not openSession) Session::close();
return true; return true;
} }
void GCell::_revalidate () void GCell::invalidate ( bool propagateFlag )
{ {
cdebug_log(110,1) << "GCell::revalidate() " << this << endl; cdebug_log(110,1) << "GCell::invalidate() " << this << endl;
cdebug_log(110,1) << "West side." << endl; for ( Edge* edge : _westEdges ) edge->revalidate(); cdebug_tabw(110,-1); Super::invalidate( propagateFlag );
cdebug_log(110,1) << "East side." << endl; for ( Edge* edge : _eastEdges ) edge->revalidate(); cdebug_tabw(110,-1); _flags |= Flags::Invalidated;
cdebug_log(110,1) << "South side." << endl; for ( Edge* edge : _southEdges ) edge->revalidate(); cdebug_tabw(110,-1);
cdebug_log(110,1) << "North side." << endl; for ( Edge* edge : _northEdges ) edge->revalidate(); cdebug_tabw(110,-1); cdebug_log(110,1) << "West side." << endl; for ( Edge* edge : _westEdges ) edge->invalidate(); cdebug_tabw(110,-1);
cdebug_log(110,1) << "East side." << endl; for ( Edge* edge : _eastEdges ) edge->invalidate(); cdebug_tabw(110,-1);
cdebug_log(110,1) << "South side." << endl; for ( Edge* edge : _southEdges ) edge->invalidate(); cdebug_tabw(110,-1);
cdebug_log(110,1) << "North side." << endl; for ( Edge* edge : _northEdges ) edge->invalidate(); cdebug_tabw(110,-1);
cdebug_tabw(110,-1);
}
void GCell::materialize ()
{
cdebug_log(110,1) << "GCell::materialize() " << this << endl;
if (_xmin > getXMax()+1) if (_xmin > getXMax()+1)
cerr << Error( "GCell::_revalidate(): %s, X Min is greater than Max.", getString(this).c_str() ); cerr << Error( "GCell::materialize(): %s, X Min is greater than Max.", getString(this).c_str() );
if (_ymin > getYMax()+1) if (_ymin > getYMax()+1)
cerr << Error( "GCell::_revalidate(): %s, Y Min is greater than Max.", getString(this).c_str() ); cerr << Error( "GCell::materialize(): %s, Y Min is greater than Max.", getString(this).c_str() );
_anabatic->_updateLookup( this ); _anabatic->_updateLookup( this );
//_anabatic->getMatrix()->show(); //_anabatic->getMatrix()->show();
Super::materialize();
cdebug_tabw(110,-1); cdebug_tabw(110,-1);
} }
@ -898,36 +1009,52 @@ namespace Anabatic {
} }
void GCell::setXY ( DbU::Unit x, DbU::Unit y ) void GCell::setSouthWestCorner ( DbU::Unit x, DbU::Unit y )
{ {
UpdateSession::open(); //DbU::Unit dx = x - _xmin;
//DbU::Unit dy = y - _ymin;
/*for ( Contact* contact : _gcontacts ) {
Point position = contact->getPosition().translate( dx, dy );
for ( Component* component : contact->getSlaveComponents() ) {
Horizontal* horizontal = dynamic_cast<Horizontal*>( component );
if (horizontal) {
horizontal->setY( position.getY() );
} else {
Vertical* vertical = dynamic_cast<Vertical*>( component );
vertical->setX( position.getX() );
}
}
if (not contact->getAnchor()) contact->setPosition( Point(x,y) );
}*/
_xmin = x; _xmin = x;
_ymin = y; _ymin = y;
UpdateSession::close();
invalidate( false );
} }
void GCell::updateContactsPosition () void GCell::updateGContacts ( Flags flags )
{ {
UpdateSession::open(); Point center ( _xmin+getWidth()/2, _ymin+getHeight()/2 );
DbU::Unit xc = (getXMax() + getXMin())/2;
DbU::Unit yc = (getYMax() + getYMin())/2; for ( Contact* contact : _gcontacts ) {
for (vector<Contact*>::iterator it = _gcontacts.begin(); it != _gcontacts.end(); it++){ for ( Component* component : contact->getSlaveComponents() ) {
for ( Component* c : (*it)->getSlaveComponents() ){ Horizontal* horizontal = dynamic_cast<Horizontal*>( component );
Horizontal* h = dynamic_cast<Horizontal*>(c); if (horizontal and (flags & Flags::Vertical)) {
Vertical* v = dynamic_cast<Vertical*> (c); horizontal->setY( center.getY() );
if (h){ } else {
//if (h->getY() == (*it)->getY()) h->setY(yc); Vertical* vertical = dynamic_cast<Vertical*>( component );
h->setY(yc); if (vertical and (flags & Flags::Horizontal)) {
} else if (v) { vertical->setX( center.getX() );
//if (v->getX() == (*it)->getX()) v->setX(xc); }
v->setX(xc);
} }
} }
(*it)->setX(xc); if (not contact->getAnchor()) contact->setPosition( center );
(*it)->setY(yc);
} }
UpdateSession::close();
} }
@ -964,7 +1091,7 @@ namespace Anabatic {
if (_gcontacts[i] == unref) { if (_gcontacts[i] == unref) {
if (_gcontacts[i]->getSlaveComponents().getLocator()->isValid()) return false; if (_gcontacts[i]->getSlaveComponents().getLocator()->isValid()) return false;
cdebug_log(112,0) << " Effective destroy." << endl; cdebug_log(112,0) << " Effective destroy " << (void*)unref << endl;
std::swap( _gcontacts[i], _gcontacts[_gcontacts.size()-1] ); std::swap( _gcontacts[i], _gcontacts[_gcontacts.size()-1] );
_gcontacts[ _gcontacts.size()-1 ]->destroy(); _gcontacts[ _gcontacts.size()-1 ]->destroy();
_gcontacts.pop_back(); _gcontacts.pop_back();
@ -1100,7 +1227,7 @@ namespace Anabatic {
} }
float GCell::getHCapacity () const int GCell::getHCapacity () const
{ {
int capacity = 0; int capacity = 0;
if (not _eastEdges.empty()) { if (not _eastEdges.empty()) {
@ -1108,11 +1235,11 @@ namespace Anabatic {
} else { } else {
for ( Edge* edge : _westEdges ) capacity += edge->getCapacity(); for ( Edge* edge : _westEdges ) capacity += edge->getCapacity();
} }
return (float)capacity; return capacity;
} }
float GCell::getVCapacity () const int GCell::getVCapacity () const
{ {
int capacity = 0; int capacity = 0;
if (not _northEdges.empty()) { if (not _northEdges.empty()) {
@ -1120,7 +1247,20 @@ namespace Anabatic {
} else { } else {
for ( Edge* edge : _southEdges ) capacity += edge->getCapacity(); for ( Edge* edge : _southEdges ) capacity += edge->getCapacity();
} }
return (float)capacity; return capacity;
}
int GCell::getCapacity ( size_t depth ) const
{
const vector<Edge*>* edges = NULL;
if (isHorizontalPlane(depth)) edges = (_eastEdges .empty()) ? &_westEdges : &_eastEdges;
else edges = (_northEdges.empty()) ? &_southEdges : &_northEdges;
int capacity = 0;
for ( Edge* edge : *edges ) capacity += edge->getCapacity(depth);
return capacity;
} }
@ -1143,8 +1283,8 @@ namespace Anabatic {
float vdensity = 0.0; float vdensity = 0.0;
for ( size_t i=_pinDepth ; i<_depth ; i++ ) { for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
if ( i%2 ) { hdensity += _densities[i]; ++hplanes; } if (isHorizontalPlane(i)) { hdensity += _densities[i]; ++hplanes; }
else { vdensity += _densities[i]; ++vplanes; } else { vdensity += _densities[i]; ++vplanes; }
} }
if (hplanes) hdensity /= hplanes; if (hplanes) hdensity /= hplanes;
@ -1169,7 +1309,7 @@ namespace Anabatic {
float hdensity = 0.0; float hdensity = 0.0;
for ( size_t i=_pinDepth ; i<_depth ; i++ ) { for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
if (i%2) { hdensity += _densities[i]; ++hplanes; } if (isHorizontalPlane(i)) { hdensity += _densities[i]; ++hplanes; }
} }
if (hplanes) hdensity /= hplanes; if (hplanes) hdensity /= hplanes;
@ -1179,7 +1319,7 @@ namespace Anabatic {
float vdensity = 0.0; float vdensity = 0.0;
for ( size_t i=_pinDepth ; i<_depth ; i++ ) { for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
if (i%2 == 0) { vdensity += _densities[i]; ++vplanes; } if (isVerticalPlane(i)) { vdensity += _densities[i]; ++vplanes; }
} }
if (vplanes) vdensity /= vplanes; if (vplanes) vdensity /= vplanes;
@ -1191,11 +1331,11 @@ namespace Anabatic {
} }
} else if (getAnabatic()->getDensityMode() == MaxHDensity) { } else if (getAnabatic()->getDensityMode() == MaxHDensity) {
for ( size_t i=_pinDepth ; i<_depth ; i++ ) { for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
if ((i%2) and (_densities[i] > density)) density = _densities[i]; if (isHorizontalPlane(i) and (_densities[i] > density)) density = _densities[i];
} }
} else if (getAnabatic()->getDensityMode() == MaxVDensity) { } else if (getAnabatic()->getDensityMode() == MaxVDensity) {
for ( size_t i=_pinDepth ; i<_depth ; i++ ) { for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
if ((i%2 == 0) and (_densities[i] > density)) density = _densities[i]; if (isVerticalPlane(i) and (_densities[i] > density)) density = _densities[i];
} }
} }
@ -1203,6 +1343,26 @@ namespace Anabatic {
} }
void GCell::postGlobalAnnotate ()
{
if (isInvalidated()) updateDensity();
for ( size_t depth=0 ; depth<_depth ; ++depth ) {
RoutingLayerGauge* rlg = Session::getLayerGauge( depth );
if (rlg->getType() & Constant::PinOnly) continue;
if (_densities[depth] >= 0.9) {
if (depth+2 < _depth) {
Edge* edge = (rlg->getDirection() == Constant::Vertical) ? getNorthEdge()
: getEastEdge();
if (edge) {
edge->reserveCapacity( 2 );
}
}
}
}
}
void GCell::addBlockage ( size_t depth, DbU::Unit length ) void GCell::addBlockage ( size_t depth, DbU::Unit length )
{ {
if (depth >= _depth) return; if (depth >= _depth) return;
@ -1210,7 +1370,7 @@ namespace Anabatic {
_blockages[depth] += length; _blockages[depth] += length;
_flags |= Flags::Invalidated; _flags |= Flags::Invalidated;
cdebug_log(149,0) << "GCell:addBlockage() " << this << " " cdebug_log(149,0) << "GCell::addBlockage() " << this << " "
<< depth << ":" << DbU::getValueString(_blockages[depth]) << endl; << depth << ":" << DbU::getValueString(_blockages[depth]) << endl;
} }
@ -1231,6 +1391,7 @@ namespace Anabatic {
if (found) { if (found) {
cdebug_log(149,0) << "remove " << ac << " from " << this << endl; cdebug_log(149,0) << "remove " << ac << " from " << this << endl;
_contacts.pop_back(); _contacts.pop_back();
_flags |= Flags::Invalidated;
} else { } else {
cerr << Bug("%p:%s do not belong to %s." cerr << Bug("%p:%s do not belong to %s."
,ac->base(),getString(ac).c_str(),_getString().c_str()) << endl; ,ac->base(),getString(ac).c_str(),_getString().c_str()) << endl;
@ -1244,11 +1405,17 @@ namespace Anabatic {
size_t begin = 0; size_t begin = 0;
for ( ; begin < end ; begin++ ) { for ( ; begin < end ; begin++ ) {
if (not _hsegments[begin])
cerr << Bug( "GCell::removeHSegment(): In %s, NULL segment at [%u/%u]."
, _getString().c_str(), begin, _hsegments.size() ) << endl;
if (_hsegments[begin] == segment) std::swap( _hsegments[begin], _hsegments[--end] ); if (_hsegments[begin] == segment) std::swap( _hsegments[begin], _hsegments[--end] );
cdebug_log(9000,0) << "GCell::removeHSegment() " << this << endl;
cdebug_log(9000,0) << " " << segment << endl;
} }
if (_hsegments.size() == end) { if (_hsegments.size() == end) {
cerr << Bug( "%s do not go through %s." cerr << Bug( "GCell::removeHSegment(): %s do not go through %s."
, getString(segment).c_str(), _getString().c_str() ) << endl; , getString(segment).c_str(), _getString().c_str() ) << endl;
return; return;
} }
@ -1258,6 +1425,7 @@ namespace Anabatic {
, _getString().c_str(), getString(segment).c_str() ) << endl; , _getString().c_str(), getString(segment).c_str() ) << endl;
_hsegments.erase( _hsegments.begin() + end, _hsegments.end() ); _hsegments.erase( _hsegments.begin() + end, _hsegments.end() );
_flags |= Flags::Invalidated;
} }
@ -1283,6 +1451,7 @@ namespace Anabatic {
, getString(segment).c_str() ) << endl; , getString(segment).c_str() ) << endl;
_vsegments.erase( _vsegments.begin() + end, _vsegments.end() ); _vsegments.erase( _vsegments.begin() + end, _vsegments.end() );
_flags |= Flags::Invalidated;
} }
@ -1296,57 +1465,45 @@ namespace Anabatic {
_flags.reset( Flags::Saturated ); _flags.reset( Flags::Saturated );
for ( size_t i=0 ; i<_vsegments.size() ; i++ ) {
if ( _vsegments[i] == NULL )
cerr << "NULL Autosegment at index " << i << endl;
}
sort( _hsegments.begin(), _hsegments.end(), AutoSegment::CompareByDepthLength() ); sort( _hsegments.begin(), _hsegments.end(), AutoSegment::CompareByDepthLength() );
sort( _vsegments.begin(), _vsegments.end(), AutoSegment::CompareByDepthLength() ); sort( _vsegments.begin(), _vsegments.end(), AutoSegment::CompareByDepthLength() );
float hcapacity = getHCapacity (); float ccapacity = getHCapacity() * getVCapacity() * (_depth-_pinDepth);
float vcapacity = getVCapacity (); DbU::Unit width = getXMax() - getXMin();
float ccapacity = hcapacity * vcapacity * 4; DbU::Unit height = getYMax() - getYMin();
DbU::Unit width = getXMax() - getXMin(); DbU::Unit hpenalty = 0 /*_box.getWidth () / 3*/;
DbU::Unit height = getYMax() - getYMin(); DbU::Unit vpenalty = 0 /*_box.getHeight() / 3*/;
DbU::Unit hpenalty = 0 /*_box.getWidth () / 3*/; DbU::Unit uLengths1 [ _depth ];
DbU::Unit vpenalty = 0 /*_box.getHeight() / 3*/; DbU::Unit uLengths2 [ _depth ];
DbU::Unit uLengths1 [ _depth ]; float localCounts [ _depth ];
DbU::Unit uLengths2 [ _depth ]; vector<UsedFragments> ufragments ( _depth );
float localCounts [ _depth ];
vector<UsedFragments> ufragments ( _depth );
for ( size_t i=0 ; i<_depth ; i++ ) { for ( size_t i=0 ; i<_depth ; i++ ) {
ufragments[i].setPitch ( Session::getPitch(i) ); ufragments[i].setPitch ( Session::getPitch(i) );
_feedthroughs[i] = 0.0; _feedthroughs[i] = 0.0;
uLengths1 [i] = 0;
uLengths2 [i] = 0; uLengths2 [i] = 0;
localCounts [i] = 0.0; localCounts [i] = 0.0;
_globalsCount[i] = 0.0; _globalsCount[i] = 0.0;
if (Session::getDirection(i) & Flags::Horizontal) { ufragments[i].setCapacity( (size_t)getCapacity(i) );
ufragments[i].setSpan ( getXMin(), getXMax() ); if (isHorizontalPlane(i)) ufragments[i].setSpan( getXMin(), getXMax() );
ufragments[i].setCapacity( (size_t)hcapacity ); else ufragments[i].setSpan( getYMin(), getYMax() );
} else {
ufragments[i].setSpan ( getYMin(), getYMax() );
ufragments[i].setCapacity( (size_t)vcapacity );
}
} }
// Compute wirelength associated to contacts (in DbU::Unit converted to float). // Compute wirelength associated to contacts (in DbU::Unit converted to float).
AutoSegment::DepthLengthSet processeds; AutoSegment::DepthLengthSet processeds;
for ( AutoContact* contact : _contacts ) { for ( AutoContact* contact : _contacts ) {
for ( size_t i=0 ; i<_depth ; i++ ) uLengths1[i] = 0; for ( size_t i=0 ; i<_depth ; i++ ) uLengths1[i] = 0;
contact->getLengths ( uLengths1, processeds ); contact->getLengths( uLengths1, processeds );
for ( size_t i=0 ; i<_depth ; i++ ) { for ( size_t i=0 ; i<_depth ; i++ ) {
if (Session::getDirection(i) & Flags::Horizontal) if (isHorizontalPlane(i)) uLengths2[i] += uLengths1[i]+hpenalty;
uLengths2[i] += uLengths1[i]+hpenalty; else uLengths2[i] += uLengths1[i]+vpenalty;
else
uLengths2[i] += uLengths1[i]+vpenalty; break;
} }
} }
// Add the "pass through" horizontal segments. // Add the "pass through" horizontal segments.
if ( _hsegments.size() ) { if (not _hsegments.empty()) {
const Layer* layer = _hsegments[0]->getLayer(); const Layer* layer = _hsegments[0]->getLayer();
size_t depth = Session::getRoutingGauge()->getLayerDepth(layer); size_t depth = Session::getRoutingGauge()->getLayerDepth(layer);
size_t count = 0; size_t count = 0;
@ -1370,7 +1527,7 @@ namespace Anabatic {
} }
// Add the "pass through" vertical segments. // Add the "pass through" vertical segments.
if ( _vsegments.size() ) { if (not _vsegments.empty()) {
const Layer* layer = _vsegments[0]->getLayer(); const Layer* layer = _vsegments[0]->getLayer();
size_t depth = Session::getRoutingGauge()->getLayerDepth(layer); size_t depth = Session::getRoutingGauge()->getLayerDepth(layer);
size_t count = 0; size_t count = 0;
@ -1378,7 +1535,7 @@ namespace Anabatic {
_globalsCount[depth] += 1.0; _globalsCount[depth] += 1.0;
ufragments[depth].incGlobals(); ufragments[depth].incGlobals();
if ( layer != _vsegments[i]->getLayer() ) { if (layer != _vsegments[i]->getLayer()) {
uLengths2[depth] += count * height; uLengths2[depth] += count * height;
count = 0; count = 0;
@ -1388,25 +1545,43 @@ namespace Anabatic {
count++; count++;
_feedthroughs[depth] += 1.0; _feedthroughs[depth] += 1.0;
} }
if ( count ) { if (count) {
uLengths2[depth] += count * height; uLengths2[depth] += count * height;
} }
} }
// Add the blockages. // Add the blockages.
for ( size_t i=0 ; i<_depth ; i++ ) { if (isStdCellRow() or isChannelRow()) {
uLengths2[i] += _blockages[i]; flags().reset( Flags::GoStraight );
} else {
int contiguousNonSaturated = 0;
for ( size_t i=0 ; i<_depth ; i++ ) {
uLengths2[i] += _blockages[i];
if (Session::getLayerGauge(i)->getType() & Constant::PinOnly)
continue;
if (Session::getLayerGauge(i)->getType() & Constant::PowerSupply)
continue;
if ((float)(_blockages[i] * Session::getPitch(i)) > 0.60*(float)(width*height))
contiguousNonSaturated = 0;
else
contiguousNonSaturated++;
}
if (contiguousNonSaturated < 2) {
flags() |= Flags::GoStraight;
//cerr << "| Set GoStraight on " << this << endl;
}
} }
// Compute the number of non pass-through tracks. // Compute the number of non pass-through tracks.
if (processeds.size()) { if (not processeds.empty()) {
AutoSegment::DepthLengthSet::iterator isegment = processeds.begin(); AutoSegment::DepthLengthSet::iterator isegment = processeds.begin();
const Layer* layer = (*isegment)->getLayer(); const Layer* layer = (*isegment)->getLayer();
DbU::Unit axis = (*isegment)->getAxis(); DbU::Unit axis = (*isegment)->getAxis();
size_t depth = Session::getRoutingGauge()->getLayerDepth(layer); size_t depth = Session::getRoutingGauge()->getLayerDepth(layer);
size_t count = 0; size_t count = 0;
for ( ; isegment != processeds.end(); ++isegment ) { for ( ; isegment != processeds.end(); ++isegment ) {
_feedthroughs[depth] += ((*isegment)->isGlobal()) ? 0.50 : 0.33; //_feedthroughs[depth] += ((*isegment)->isGlobal()) ? 0.50 : 0.33;
_feedthroughs[depth] += 0.50;
localCounts [depth] += 1.0; localCounts [depth] += 1.0;
if ( (*isegment)->isGlobal() ) _globalsCount[depth] += 1.0; if ( (*isegment)->isGlobal() ) _globalsCount[depth] += 1.0;
@ -1423,9 +1598,11 @@ namespace Anabatic {
// Normalize: 0 < d < 1.0 (divide by H/V capacity). // Normalize: 0 < d < 1.0 (divide by H/V capacity).
for ( size_t i=0 ; i<_depth ; i++ ) { for ( size_t i=0 ; i<_depth ; i++ ) {
int capacity = getCapacity(i);
if (Session::getDirection(i) & Flags::Horizontal) { if (Session::getDirection(i) & Flags::Horizontal) {
if (width) { if (width and capacity) {
_densities [i] = ((float)uLengths2[i]) / ( hcapacity * (float)width ); _densities [i] = ((float)uLengths2[i]) / (float)( capacity * width );
_feedthroughs [i] += (float)(_blockages[i] / width); _feedthroughs [i] += (float)(_blockages[i] / width);
_fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)width; _fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)width;
} else { } else {
@ -1434,8 +1611,8 @@ namespace Anabatic {
_fragmentations[i] = 0; _fragmentations[i] = 0;
} }
} else { } else {
if (height) { if (height and capacity) {
_densities [i] = ((float)uLengths2[i]) / ( vcapacity * (float)height ); _densities [i] = ((float)uLengths2[i]) / (float)( capacity * height );
_feedthroughs [i] += (float)(_blockages[i] / height); _feedthroughs [i] += (float)(_blockages[i] / height);
_fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)height; _fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)height;
} else { } else {
@ -1448,10 +1625,8 @@ namespace Anabatic {
if (_densities[i] >= 1.0) _flags |= Flags::Saturated; if (_densities[i] >= 1.0) _flags |= Flags::Saturated;
} }
if (ccapacity) if (ccapacity) _cDensity = ( (float)_contacts.size() ) / ccapacity;
_cDensity = ( (float)_contacts.size() ) / ccapacity; else _cDensity = 0;
else
_cDensity = 0;
_flags.reset( Flags::Invalidated ); _flags.reset( Flags::Invalidated );
checkDensity(); checkDensity();
@ -1462,17 +1637,16 @@ namespace Anabatic {
void GCell::truncDensities () void GCell::truncDensities ()
{ {
int hcapacity = (int)getHCapacity(); Box bBox = getBoundingBox();
int vcapacity = (int)getVCapacity();
Box bBox = getBoundingBox();
for ( size_t i=0 ; i<_depth ; i++ ) { for ( size_t i=0 ; i<_depth ; i++ ) {
if (Session::getDirection(i) & Flags::Horizontal) { int capacity = getCapacity(i);
if (_blockages[i] > hcapacity * bBox.getWidth()) if (isHorizontalPlane(i)) {
_blockages[i] = hcapacity * bBox.getWidth(); if (_blockages[i] > capacity * bBox.getWidth())
_blockages[i] = capacity * bBox.getWidth();
} else { } else {
if (_blockages[i] > vcapacity * bBox.getHeight()) if (_blockages[i] > capacity * bBox.getHeight())
_blockages[i] = vcapacity * bBox.getHeight(); _blockages[i] = capacity * bBox.getHeight();
} }
} }
_flags &= ~Flags::Saturated; _flags &= ~Flags::Saturated;
@ -1508,20 +1682,31 @@ namespace Anabatic {
{ {
if (isInvalidated()) const_cast<GCell*>(this)->updateDensity(); if (isInvalidated()) const_cast<GCell*>(this)->updateDensity();
float capacity = 0.0; float capacity = getCapacity(depth);
if (Session::getDirection(depth) & Flags::Horizontal) capacity = getHCapacity();
else capacity = getVCapacity();
cdebug_log(149,0) << " | hasFreeTrack [" << getId() << "] depth:" << depth << " " cdebug_log(149,0) << " | hasFreeTrack [" << getId() << "] depth:" << depth << " "
<< Session::getRoutingGauge()->getRoutingLayer(depth)->getName() << Session::getRoutingGauge()->getRoutingLayer(depth)->getName()
//<< " " << (_densities[depth]*capacity) << " vs. " << capacity //<< " " << (_densities[depth]*capacity) << " vs. " << capacity
<< " " << _feedthroughs[depth] << " vs. " << capacity << " " << _feedthroughs[depth] << " vs. " << capacity
<< " " << this << endl; << " " << this << endl;
return (_feedthroughs[depth] + 0.99 + reserve <= capacity); return (_feedthroughs[depth] + 0.99 + reserve <= capacity);
} }
size_t GCell::getNetCount () const
{
set<Net*> nets;
for ( Edge* edge : _westEdges ) for ( Segment* segment : edge->getSegments() ) nets.insert( segment->getNet() );
for ( Edge* edge : _eastEdges ) for ( Segment* segment : edge->getSegments() ) nets.insert( segment->getNet() );
for ( Edge* edge : _northEdges ) for ( Segment* segment : edge->getSegments() ) nets.insert( segment->getNet() );
for ( Edge* edge : _southEdges ) for ( Segment* segment : edge->getSegments() ) nets.insert( segment->getNet() );
return nets.size();
}
void GCell::rpDesaturate ( set<Net*>& globalNets ) void GCell::rpDesaturate ( set<Net*>& globalNets )
{ {
set<RoutingPad*> rps; set<RoutingPad*> rps;
@ -1634,7 +1819,7 @@ namespace Anabatic {
bool GCell::stepNetDesaturate ( size_t depth, set<Net*>& globalNets, GCell::Set& invalidateds ) bool GCell::stepNetDesaturate ( size_t depth, set<Net*>& globalNets, GCell::Set& invalidateds )
{ {
cdebug_log(9000,0) << "Deter| GCell::stepNetDesaturate() depth:" << depth << endl; cdebug_log(149,0) << "GCell::stepNetDesaturate() depth:" << depth << endl;
cdebug_log(9000,0) << "Deter| " << this << endl; cdebug_log(9000,0) << "Deter| " << this << endl;
updateDensity(); updateDensity();
@ -1656,7 +1841,7 @@ namespace Anabatic {
if (segmentDepth < depth) continue; if (segmentDepth < depth) continue;
if (segmentDepth > depth) break; if (segmentDepth > depth) break;
cdebug_log(9000,0) << "Deter| Move up " << (*isegment) << endl; cdebug_log(149,0) << "Move up " << (*isegment) << endl;
if (getAnabatic()->moveUpNetTrunk(*isegment,globalNets,invalidateds)) if (getAnabatic()->moveUpNetTrunk(*isegment,globalNets,invalidateds))
return true; return true;
@ -1666,16 +1851,16 @@ namespace Anabatic {
} }
void GCell::setEdgesOccupancy ( unsigned int width, unsigned int height ) void GCell::forceEdgesCapacities ( unsigned int hcapacity, unsigned int vcapacity )
{ {
getEastEdge()->setCapacity(width); if (getEastEdge() ) getEastEdge ()->forceCapacity( hcapacity );
getWestEdge()->setCapacity(width); if (getWestEdge() ) getWestEdge ()->forceCapacity( hcapacity );
getNorthEdge()->setCapacity(height); if (getNorthEdge()) getNorthEdge()->forceCapacity( vcapacity );
getSouthEdge()->setCapacity(height); if (getSouthEdge()) getSouthEdge()->forceCapacity( vcapacity );
getEastEdge()->setRealOccupancy(0); if (getEastEdge() ) getEastEdge ()->setRealOccupancy(0);
getWestEdge()->setRealOccupancy(0); if (getWestEdge() ) getWestEdge ()->setRealOccupancy(0);
getNorthEdge()->setRealOccupancy(0); if (getNorthEdge()) getNorthEdge()->setRealOccupancy(0);
getSouthEdge()->setRealOccupancy(0); if (getSouthEdge()) getSouthEdge()->setRealOccupancy(0);
} }
@ -1688,6 +1873,13 @@ namespace Anabatic {
string s = Super::_getString(); string s = Super::_getString();
s.insert( s.size()-1, " "+getString(getBoundingBox()) ); s.insert( s.size()-1, " "+getString(getBoundingBox()) );
s.insert( s.size()-1, " "+getString(_flags) ); s.insert( s.size()-1, " "+getString(_flags) );
s.insert( s.size()-1, " "+getString(_rpCount) );
/* string s = "<GCell at(" + DbU::getValueString(getXMin())
+ "-" + DbU::getValueString(getYMin())
+ "-" + DbU::getValueString(getXMax())
+ "-" + DbU::getValueString(getYMax())
+ "-" + DbU::getValueString(getHeight())
+ "-" + DbU::getValueString(getWidth()) + ")";*/
return s; return s;
} }
@ -1702,6 +1894,7 @@ namespace Anabatic {
record->add( getSlot("_northEdges" , &_northEdges) ); record->add( getSlot("_northEdges" , &_northEdges) );
record->add( DbU::getValueSlot("_xmin", &_xmin) ); record->add( DbU::getValueSlot("_xmin", &_xmin) );
record->add( DbU::getValueSlot("_ymin", &_ymin) ); record->add( DbU::getValueSlot("_ymin", &_ymin) );
record->add( getSlot ( "_gcontacts", &_gcontacts ) );
record->add( getSlot ( "_vsegments", &_vsegments ) ); record->add( getSlot ( "_vsegments", &_vsegments ) );
record->add( getSlot ( "_hsegments", &_hsegments ) ); record->add( getSlot ( "_hsegments", &_hsegments ) );
record->add( getSlot ( "_contacts" , &_contacts ) ); record->add( getSlot ( "_contacts" , &_contacts ) );
@ -1713,7 +1906,7 @@ namespace Anabatic {
ostringstream s; ostringstream s;
const Layer* layer = rg->getRoutingLayer(depth)->getBlockageLayer(); const Layer* layer = rg->getRoutingLayer(depth)->getBlockageLayer();
s << "_blockages[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]"; s << "_blockages[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
record->add( getSlot ( s.str(), &_blockages[depth] ) ); record->add( DbU::getValueSlot( s.str(), &_blockages[depth] ) );
} }
for ( size_t depth=0 ; depth<_depth ; ++depth ) { for ( size_t depth=0 ; depth<_depth ; ++depth ) {
@ -1722,6 +1915,13 @@ namespace Anabatic {
s << "_densities[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]"; s << "_densities[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
record->add( getSlot ( s.str(), &_densities[depth] ) ); record->add( getSlot ( s.str(), &_densities[depth] ) );
} }
for ( size_t depth=0 ; depth<_depth ; ++depth ) {
ostringstream s;
const Layer* layer = rg->getRoutingLayer(depth);
s << "_feedthroughs[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
record->add( getSlot ( s.str(), &_feedthroughs[depth] ) );
}
return record; return record;
} }

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved // Copyright (c) UPMC 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -31,11 +31,288 @@
#include "hurricane/Horizontal.h" #include "hurricane/Horizontal.h"
#include "hurricane/Cell.h" #include "hurricane/Cell.h"
#include "crlcore/RoutingGauge.h" #include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContact.h" #include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoSegment.h" #include "anabatic/AutoSegment.h"
#include "anabatic/AnabaticEngine.h" #include "anabatic/AnabaticEngine.h"
namespace {
using namespace std;
using namespace CRL;
using namespace Hurricane;
using namespace Anabatic;
class SortRpByX {
public:
inline SortRpByX ();
inline bool operator() ( RoutingPad* rp1, RoutingPad* rp2 );
};
inline SortRpByX::SortRpByX ()
{ }
inline bool SortRpByX::operator() ( RoutingPad* rp1, RoutingPad* rp2 )
{
DbU::Unit x1 = rp1->getCenter().getX();
DbU::Unit x2 = rp2->getCenter().getX();
if (x1 == x2) return false;
return (x1 < x2);
}
// -----------------------------------------------------------------
// Class : "RpsInRow".
class RpsInRow {
public:
class Compare {
public:
bool operator() ( const RpsInRow* lhs, const RpsInRow* rhs ) const;
};
public:
inline RpsInRow ( RoutingPad*, AnabaticEngine* );
inline const vector<RoutingPad*>& getRps () const;
inline size_t getSouth () const;
inline size_t getNorth () const;
inline const Interval& getRpsHSpan () const;
inline const Interval& getRpsVSpan () const;
void slacken ();
private:
void _findTopology ();
inline void _merge ( RoutingPad* );
private:
AnabaticEngine* _anabatic;
vector<RoutingPad*> _rps;
size_t _north;
size_t _south;
Interval _hSpan;
Interval _vSpan;
};
inline RpsInRow::RpsInRow ( RoutingPad* seed, AnabaticEngine* anabatic )
: _anabatic(anabatic)
, _rps ()
, _north (0)
, _south (0)
, _hSpan ()
, _vSpan ( false )
{
_rps.push_back( seed );
_findTopology();
}
inline const vector<RoutingPad*>& RpsInRow::getRps () const { return _rps; }
inline size_t RpsInRow::getSouth () const { return _south; }
inline size_t RpsInRow::getNorth () const { return _north; }
inline const Interval& RpsInRow::getRpsHSpan () const { return _hSpan; }
inline const Interval& RpsInRow::getRpsVSpan () const { return _vSpan; }
bool RpsInRow::Compare::operator() ( const RpsInRow* lhs, const RpsInRow* rhs ) const
{
if ( (lhs->_rps.size() == 2) and (rhs->_rps.size() != 2) ) return true;
if ( (lhs->_rps.size() != 2) and (rhs->_rps.size() == 2) ) return false;
if ( lhs->_rps.size() != rhs->_rps.size() ) return lhs->_rps.size() < rhs->_rps.size();
size_t lhsNs = lhs->_south + lhs->_north;
size_t rhsNs = rhs->_south + rhs->_north;
if (lhsNs != rhsNs) return lhsNs < rhsNs;
if (lhs->_vSpan != rhs->_vSpan) return lhs->_vSpan.getSize() < rhs->_vSpan.getSize();
if (lhs->_hSpan != rhs->_hSpan) return lhs->_hSpan.getSize() < rhs->_hSpan.getSize();
return lhs->_rps[0]->getId() < rhs->_rps[0]->getId();
}
inline void RpsInRow::_merge ( RoutingPad* rp )
{
if (rp != _rps[0]) _rps.push_back( rp );
Box bb ( _rps.back()->getBoundingBox() );
_hSpan.merge( bb.getCenter().getX() );
_vSpan.intersection( bb.getYMin(), bb.getYMax() );
}
void RpsInRow::_findTopology ()
{
cdebug_log(146,1) << "RpsInRow::findTopology() - " << _rps[0] << endl;
_merge( _rps[0] );
AutoSegmentStack stack;
for ( Component* component : _rps[0]->getSlaveComponents() ) {
cdebug_log(146,0) << "slave component: " << component << endl;
AutoContact* rpContact = Session::lookup( dynamic_cast<Contact*>(component) );
if (rpContact) {
cdebug_log(146,0) << "Start rp: " << rpContact << endl;
for ( AutoSegment* segment : rpContact->getAutoSegments() ) {
cdebug_log(146,0) << "Examining: " << segment << endl;
AutoContact* target = segment->getOppositeAnchor(rpContact);
if (target) {
if (segment->isHorizontal()) {
stack.push( target, segment );
} else {
if (segment->isLocal()) {
stack.push( target, segment );
} else {
if (segment->getAutoSource() == rpContact) ++_north;
else ++_south;
}
}
}
}
// Find Rps in same horizontal GCell range.
cdebug_log(146,0) << "Find Rps in same horizontal GCell range" << endl;
while ( not stack.isEmpty() ) {
AutoSegment* from = stack.getAutoSegment();
AutoContact* contact = stack.getAutoContact();
stack.pop();
for ( AutoSegment* segment : contact->getAutoSegments() ) {
if (segment == from) continue;
if (segment->isVertical() and not segment->isLocal()) {
if (segment->getAutoSource() == contact) ++_north;
else ++_south;
continue;
}
AutoContact* target = segment->getOppositeAnchor( contact );
AutoContactTerminal* terminal = dynamic_cast<AutoContactTerminal*>( target );
if (terminal) {
_merge( terminal->getRoutingPad() );
}
stack.push( target, segment );
}
}
}
}
sort( _rps.begin(), _rps.end(), SortRpByX() );
cdebug_log(146,0) << "findHAlignedsRps() - Exit" << endl;
cdebug_tabw(146,-1);
}
void RpsInRow::slacken ()
{
cdebug_log(149,1) << "RpsInRow::slacken()" << endl;
for ( RoutingPad* rp : _rps ) {
cdebug_log(149,0) << "Slacken from: " << rp << endl;
if (rp->getLayer()) {
if (_anabatic->getConfiguration()->getLayerDepth(rp->getLayer()) == 1) {
cdebug_log(149,0) << "In METAL2, skiping" << endl;
continue;
}
}
for ( Component* component : rp->getSlaveComponents() ) {
AutoContact* rpContact = Session::lookup( dynamic_cast<Contact*>(component) );
if (rpContact) {
cdebug_log(149,0) << "+ " << rpContact << endl;
for ( AutoSegment* segment : rpContact->getAutoSegments() ) {
cdebug_log(149,0) << "| " << segment << endl;
if (segment->isVertical()) {
if (segment->getDepth() == 1) {
cdebug_log(149,0) << "| Slacken: " << segment << endl;
segment->changeDepth( 2, Flags::NoFlags );
cdebug_log(149,0) << "| After Slacken: " << segment << endl;
}
} else {
segment->makeDogleg( rpContact->getGCell() );
cdebug_log(149,0) << "| Make dogleg: " << segment << endl;
}
}
}
}
}
cdebug_tabw(149,-1);
}
// -----------------------------------------------------------------
// Class : "GCellRps".
class GCellRps {
public:
class Compare {
public:
bool operator() ( const GCellRps* lhs, const GCellRps* rhs ) const;
};
public:
GCellRps ( GCell*, AnabaticEngine* );
~GCellRps ();
inline GCell* getGCell () const;
inline size_t add ( RoutingPad* );
inline void consolidate ();
inline RpsInRow* getRpsInRow ( size_t i );
inline const vector<RpsInRow*>& getRpsInRows () const;
private:
AnabaticEngine* _anabatic;
GCell* _gcell;
vector<RpsInRow*> _rpsInRows;
};
GCellRps::GCellRps ( GCell* gcell, AnabaticEngine* anabatic )
: _anabatic (anabatic)
, _gcell (gcell)
, _rpsInRows()
{ }
GCellRps::~GCellRps ()
{
for ( RpsInRow* elem : _rpsInRows ) delete elem;
}
inline GCell* GCellRps::getGCell () const { return _gcell; }
inline size_t GCellRps::add ( RoutingPad* rp )
{
_rpsInRows.push_back( new RpsInRow(rp,_anabatic) );
return _rpsInRows.size() - 1;
}
inline void GCellRps::consolidate ()
{
sort( _rpsInRows.begin(), _rpsInRows.end(), RpsInRow::Compare() );
}
inline RpsInRow* GCellRps::getRpsInRow ( size_t i ) { return _rpsInRows[i]; }
inline const vector<RpsInRow*>& GCellRps::getRpsInRows () const { return _rpsInRows; }
bool GCellRps::Compare::operator() ( const GCellRps* lhs, const GCellRps* rhs ) const
{ return lhs->getGCell()->getId() < rhs->getGCell()->getId(); }
} // Anonymous namespace.
namespace Anabatic { namespace Anabatic {
using Hurricane::DebugSession; using Hurricane::DebugSession;
@ -59,9 +336,58 @@ namespace Anabatic {
cmess1 << " o Desaturate layer " cmess1 << " o Desaturate layer "
<< Session::getRoutingGauge()->getRoutingLayer(depth)->getName() << endl; << Session::getRoutingGauge()->getRoutingLayer(depth)->getName() << endl;
cdebug_log(149,0) << "Session::getSaturateRatio()=" << Session::getSaturateRatio() << endl;
GCellKeyQueue queue;
GCell::Set invalidateds;
for ( GCell* gcell : getGCells() ) queue.push( gcell->cloneKey(depth) );
bool optimized = true;
bool finished = false;
while ( optimized ) {
Session::revalidate ();
optimized = false;
while ( not queue.empty() ) {
GCell::Key* topKey = queue.top();
GCell* gcell = const_cast<GCell*>( topKey->getGCell() );
queue.pop();
if (topKey->isActive()) {
cdebug_log(149,0) << "_desaturate: [" << depth << "]:"
<< gcell->getDensity(depth) << " " << gcell << endl;
if (not gcell->isSaturated(depth)) {
cdebug_log(149,0) << "STOP desaturated: " << gcell << endl;
finished = true;
} else {
if (finished) {
cparanoid << "[ERROR] Still saturated: " << gcell << endl;
}
}
if (not finished) {
optimized = gcell->stepNetDesaturate( depth, globalNets, invalidateds );
gcell->setSatProcessed( depth );
if (optimized) {
for ( GCell* gcell : invalidateds ) {
if (not gcell->isSatProcessed(depth))
queue.push( gcell->cloneKey(depth) );
}
invalidateds.clear();
}
}
}
delete topKey;
}
}
#if OLD_QUEUE_DISABLED
GCellDensitySet queue ( depth, getGCells() ); GCellDensitySet queue ( depth, getGCells() );
GCell::Set invalidateds; GCell::Set invalidateds;
bool optimized = true; bool optimized = true;
while ( optimized ) { while ( optimized ) {
@ -73,7 +399,7 @@ namespace Anabatic {
size_t i = 0; size_t i = 0;
for ( ; igcell!=queue.getGCells().end() ; ++igcell, ++i ) { for ( ; igcell!=queue.getGCells().end() ; ++igcell, ++i ) {
cdebug_log(149,0) << "_desaturate: [" << depth << "]:" cdebug_log(149,0) << "_desaturate: [" << depth << "]:"
<< (*igcell)->getDensity(depth) << " " << *igcell << endl; << (*igcell)->getDensity(depth) << " " << *igcell << endl;
if (not (*igcell)->isSaturated(depth)) { if (not (*igcell)->isSaturated(depth)) {
cdebug_log(149,0) << "STOP desaturated: @" << i << " " << *igcell << endl; cdebug_log(149,0) << "STOP desaturated: @" << i << " " << *igcell << endl;
@ -95,6 +421,7 @@ namespace Anabatic {
} }
} }
} }
#endif
} }
@ -117,8 +444,14 @@ namespace Anabatic {
} }
global++; global++;
if ((*isegment)->getLayer() == Session::getRoutingLayer(1)) (*isegment)->setLayer( Session::getRoutingLayer(3) ); if ((*isegment)->getLayer() == Session::getRoutingLayer(1)) {
if ((*isegment)->getLayer() == Session::getRoutingLayer(2)) (*isegment)->setLayer( Session::getRoutingLayer(4) ); (*isegment)->setLayer( Session::getRoutingLayer(3) );
(*isegment)->setWidth( Session::getWireWidth (3) );
}
if ((*isegment)->getLayer() == Session::getRoutingLayer(2)) {
(*isegment)->setLayer( Session::getRoutingLayer(4) );
(*isegment)->setWidth( Session::getWireWidth (4) );
}
} }
} }
@ -142,7 +475,7 @@ namespace Anabatic {
void AnabaticEngine::_layerAssignByTrunk ( Net* net, set<Net*>& globalNets, unsigned long& total, unsigned long& global ) void AnabaticEngine::_layerAssignByTrunk ( Net* net, set<Net*>& globalNets, unsigned long& total, unsigned long& global )
{ {
DebugSession::open( net, 140, 150 ); DebugSession::open( net, 145, 150 );
cdebug_log(149,0) << "Anabatic::_layerAssignByTrunk ( " << net << " )" << endl; cdebug_log(149,0) << "Anabatic::_layerAssignByTrunk ( " << net << " )" << endl;
cdebug_tabw(145,1); cdebug_tabw(145,1);
@ -172,8 +505,14 @@ namespace Anabatic {
netGlobal++; netGlobal++;
cdebug_log(145,0) << "Migrate to M4/M5: " << autoSegment << endl; cdebug_log(145,0) << "Migrate to M4/M5: " << autoSegment << endl;
if (autoSegment->isHorizontal()) autoSegment->setLayer( Session::getRoutingLayer(3) ); if (autoSegment->isHorizontal()) {
if (autoSegment->isVertical ()) autoSegment->setLayer( Session::getRoutingLayer(4) ); autoSegment->setLayer( Session::getRoutingLayer(3) );
autoSegment->setWidth( Session::getWireWidth (3) );
}
if (autoSegment->isVertical()) {
autoSegment->setLayer( Session::getRoutingLayer(4) );
autoSegment->setWidth( Session::getWireWidth (4) );
}
} }
} }
} }
@ -199,11 +538,125 @@ namespace Anabatic {
} }
void AnabaticEngine::_layerAssignNoGlobalM2V ( Net* net, set<Net*>& globalNets, unsigned long& total, unsigned long& global )
{
cdebug_log(149,0) << "Anabatic::_layerAssignNoGlobalM2V ( " << net << " )" << endl;
cdebug_tabw(145,1);
bool isGlobalNet = false;
unsigned long netGlobal = 0;
unsigned long netTotal = 0;
set<AutoContact*> globalContacts;
for ( Segment* baseSegment : net->getSegments() ) {
++netTotal;
AutoSegment* segment = Session::lookup( baseSegment );
if (not segment or segment->isLocal()) continue;
isGlobalNet = true;
netTotal = 0;
globalNets.insert( net );
break;
}
if (isGlobalNet) {
vector<AutoSegment*> horizontals;
for ( Segment* baseSegment : net->getSegments() ) {
AutoSegment* segment = Session::lookup( baseSegment );
if (not segment or not segment->isCanonical()) continue;
if (segment->isHorizontal()) horizontals.push_back( segment );
}
for ( AutoSegment* horizontal : horizontals ) {
vector<AutoSegment*> collapseds;
vector< tuple<AutoSegment*,Flags> > perpandicularsDatas;
//vector<AutoSegment*> northBounds;
//vector<AutoSegment*> southBounds;
DbU::Unit leftBound;
DbU::Unit rightBound;
//bool hasNorth = false;
//bool hasSouth = false;
AutoSegment::getTopologicalInfos( horizontal
, collapseds
, perpandicularsDatas
, leftBound
, rightBound
);
for ( auto perpandicularDatas : perpandicularsDatas ) {
AutoSegment* perpandicular = std::get<0>( perpandicularDatas );
if (Session::getLayerDepth(perpandicular->getLayer()) > 2) continue;
bool hasGlobal = false;
for ( AutoSegment* aligned : perpandicular->getAligneds(Flags::NoCheckLayer|Flags::WithSelf) ) {
if (aligned->isGlobal()) { hasGlobal = true; break; }
}
if (not hasGlobal) continue;
// if (perpandicular->getSourceY() == horizontal->getAxis()) {
// hasNorth = true;
// if (hasGlobal) northBounds.push_back( perpandicular );
// } else {
// hasSouth = true;
// if (hasGlobal) southBounds.push_back( perpandicular );
// }
if ( perpandicular->getAutoSource()->getGCell()->getNorth()
!= perpandicular->getAutoTarget()->getGCell()) {
perpandicular->changeDepth( 3, Flags::Propagate );
++netGlobal;
continue;
}
}
// if (hasSouth and hasNorth) {
// if (not northBounds.empty()) {
// for ( AutoSegment* perpandicular : northBounds )
// perpandicular->changeDepth( 3, Flags::Propagate );
// } else {
// for ( AutoSegment* perpandicular : southBounds )
// perpandicular->changeDepth( 3, Flags::Propagate );
// }
// }
}
}
total += netTotal;
global += netGlobal;
cdebug_tabw(145,-1);
}
void AnabaticEngine::_layerAssignNoGlobalM2V ( unsigned long& total, unsigned long& global, set<Net*>& globalNets )
{
cmess1 << " o Assign Layer (no global vertical metal2)." << endl;
for ( Net* net : getCell()->getNets() ) {
DebugSession::open( net, 145, 150 );
NetRoutingState* state = NetRoutingExtension::get( net );
if (not state or state->isAutomaticGlobalRoute()) {
_layerAssignNoGlobalM2V( net, globalNets, total, global );
} else {
cdebug_log(145,0) << net << " is not automatic routed, skipped." << endl;
}
DebugSession::close();
}
}
#if THIS_IS_DISABLED #if THIS_IS_DISABLED
void AnabaticEngine::moveULeft ( AutoSegment* seed, set<Net*>& globalNets, GCell::Set& invalidateds ) void AnabaticEngine::moveULeft ( AutoSegment* seed, set<Net*>& globalNets, GCell::Set& invalidateds )
{ {
Net* net = seed->getNet(); Net* net = seed->getNet();
DebugSession::open( net, 140, 150 ); DebugSession::open( net, 145, 150 );
cdebug_log(9000,0) << "Deter| Move left: " << seed << endl; cdebug_log(9000,0) << "Deter| Move left: " << seed << endl;
@ -240,7 +693,7 @@ namespace Anabatic {
void AnabaticEngine::moveURight ( AutoSegment* seed, set<Net*>& globalNets, GCell::Set& invalidateds ) void AnabaticEngine::moveURight ( AutoSegment* seed, set<Net*>& globalNets, GCell::Set& invalidateds )
{ {
Net* net = seed->getNet(); Net* net = seed->getNet();
DebugSession::open( net, 140, 150 ); DebugSession::open( net, 145, 150 );
cdebug_log(9000,0) << "Deter| Move right: " << seed << endl; cdebug_log(9000,0) << "Deter| Move right: " << seed << endl;
@ -280,7 +733,7 @@ namespace Anabatic {
Net* net = seed->getNet(); Net* net = seed->getNet();
unsigned int seedDepth = Session::getRoutingGauge()->getLayerDepth(seed->getLayer()); unsigned int seedDepth = Session::getRoutingGauge()->getLayerDepth(seed->getLayer());
DebugSession::open( net, 140, 150 ); DebugSession::open( net, 145, 150 );
cdebug_log(9000,0) << "Deter| moveUpNetTrunk() depth:" << seedDepth << " " << seed << endl; cdebug_log(9000,0) << "Deter| moveUpNetTrunk() depth:" << seedDepth << " " << seed << endl;
if (not seed->canMoveUp( 1.0, Flags::Propagate|Flags::AllowTerminal|Flags::NoCheckLayer) ) { if (not seed->canMoveUp( 1.0, Flags::Propagate|Flags::AllowTerminal|Flags::NoCheckLayer) ) {
@ -306,7 +759,7 @@ namespace Anabatic {
if (not segment->isStrongTerminal()) locals.push_back( segment ); if (not segment->isStrongTerminal()) locals.push_back( segment );
continue; continue;
} }
if ( (segment->getLength() < 3*Session::getSliceHeight()) and (segment != seed) ) { if ( (segment->getAnchoredLength() < 3*Session::getSliceHeight()) and (segment != seed) ) {
locals.push_back( segment ); locals.push_back( segment );
continue; continue;
} }
@ -382,7 +835,7 @@ namespace Anabatic {
cmess1 << " o Balance Global Density " cmess1 << " o Balance Global Density "
<< Session::getRoutingGauge()->getRoutingLayer(depth)->getName() << endl; << Session::getRoutingGauge()->getRoutingLayer(depth)->getName() << endl;
GCellDensitySet queue ( depth, getGCells()) ); GCellDensitySet queue ( depth, getGCells() );
GCell::Set invalidateds; GCell::Set invalidateds;
bool optimized = true; bool optimized = true;
@ -474,6 +927,8 @@ namespace Anabatic {
void AnabaticEngine::layerAssign ( uint32_t method ) void AnabaticEngine::layerAssign ( uint32_t method )
{ {
//DebugSession::open( 145, 150 );
cdebug_log(9000,0) << "Deter| Layer Assignment" << endl; cdebug_log(9000,0) << "Deter| Layer Assignment" << endl;
set<Net*> globalNets; set<Net*> globalNets;
@ -486,8 +941,9 @@ namespace Anabatic {
if (Session::getAllowedDepth() >= 3) { if (Session::getAllowedDepth() >= 3) {
switch ( method ) { switch ( method ) {
case EngineLayerAssignByLength: _layerAssignByLength( total, global, globalNets ); break; case EngineLayerAssignByLength: _layerAssignByLength ( total, global, globalNets ); break;
case EngineLayerAssignByTrunk: _layerAssignByTrunk ( total, global, globalNets ); break; case EngineLayerAssignByTrunk: _layerAssignByTrunk ( total, global, globalNets ); break;
case EngineLayerAssignNoGlobalM2V: _layerAssignNoGlobalM2V ( total, global, globalNets ); break;
case EngineNoNetLayerAssign: break; case EngineNoNetLayerAssign: break;
default: default:
stopMeasures(); stopMeasures();
@ -502,7 +958,8 @@ namespace Anabatic {
globalNets.clear(); globalNets.clear();
Session::revalidate(); Session::revalidate();
if (getConfiguration()->getAllowedDepth() > 2) { if ( (method != EngineLayerAssignNoGlobalM2V)
and (getConfiguration()->getAllowedDepth() > 2) ) {
for ( size_t depth=1 ; depth <= getConfiguration()->getAllowedDepth()-2; ++depth ) { for ( size_t depth=1 ; depth <= getConfiguration()->getAllowedDepth()-2; ++depth ) {
_desaturate( depth, globalNets, total, global ); _desaturate( depth, globalNets, total, global );
if ( (depth > 1) and ((depth-1)%2 == 1) ) Session::revalidate(); if ( (depth > 1) and ((depth-1)%2 == 1) ) Session::revalidate();
@ -519,6 +976,54 @@ namespace Anabatic {
Session::setAnabaticFlags( Flags::WarnOnGCellOverload ); Session::setAnabaticFlags( Flags::WarnOnGCellOverload );
} }
set<GCellRps*,GCellRps::Compare> gcellRpss;
for ( GCell* gcell : getGCells() ) {
set<RoutingPad*,Entity::CompareById> rps;
const vector<AutoContact*> contacts = gcell->getContacts();
for ( AutoContact* contact : contacts ) {
AutoContactTerminal* terminal = dynamic_cast<AutoContactTerminal*>( contact );
if (terminal) {
rps.insert( terminal->getRoutingPad() );
}
}
if (rps.size() > getConfiguration()->getSaturateRp()) {
GCellRps* gcellRps = new GCellRps ( gcell, this );
gcellRpss.insert( gcellRps );
for ( RoutingPad* rp : rps ) gcellRps->add( rp );
}
}
for ( GCellRps* gcellRps : gcellRpss ) {
gcellRps->consolidate();
const vector<RpsInRow*>& rpsInRows = gcellRps->getRpsInRows();
cdebug_log(149,0) << gcellRps->getGCell() << " has " << rpsInRows.size() << " terminals." << endl;
size_t count = 0;
for ( RpsInRow* rpsInRow : rpsInRows ) {
cdebug_log(149,0) << "North:" << rpsInRow->getNorth() << " South:"
<< rpsInRow->getSouth() << " net:"
<< rpsInRow->getRps()[0]->getNet()->getName() << endl;
cdebug_log(149,0) << "H-Span:" << rpsInRow->getRpsHSpan() << " V-Span:" << rpsInRow->getRpsVSpan() << endl;
for ( RoutingPad* arp : rpsInRow->getRps() ) {
cdebug_log(149,0) << "| " << arp << endl;
}
if (++count < 2) rpsInRow->slacken();
}
for ( AutoSegment* segment : gcellRps->getGCell()->getHSegments() ) {
if (segment->canPivotUp()) {
cdebug_log(149,0) << "Move up horizontal: " << segment << endl;
segment->moveUp( Flags::Propagate );
}
}
delete gcellRps;
}
checkGCellDensities(); checkGCellDensities();
Session::close(); Session::close();
@ -529,6 +1034,8 @@ namespace Anabatic {
// cmess2 << " - Global segments : " << global << endl; // cmess2 << " - Global segments : " << global << endl;
// cmess2 << " - Ratio : " // cmess2 << " - Ratio : "
// << ((float)global/(float)total)*100.0 << "%." << endl; // << ((float)global/(float)total)*100.0 << "%." << endl;
//DebugSession::close();
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Matrix.cpp<anabatic>" -*- // -*- mode: C++; explicit-buffer-name: "Matrix.cpp<anabatic>" -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved // Copyright (c) UPMC 2016-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -78,8 +78,10 @@ namespace Anabatic {
int index = xy2maxIndex(x,y); int index = xy2maxIndex(x,y);
cdebug_log(110,0) << "Matrix::getUnder() (" cdebug_log(110,0) << "Matrix::getUnder() ("
<< DbU::getValueString(x) << " " << DbU::getValueString(x) << " "
<< DbU::getValueString(y) << ") index:" << index << endl; << DbU::getValueString(y) << ") index:" << index
<< " " << ((index < 0) ? NULL : _gcells[index]->getUnder(x,y)) << endl;
return (index < 0) ? NULL : _gcells[index]->getUnder(x,y); return (index < 0) ? NULL : _gcells[index]->getUnder(x,y);
} }
@ -117,7 +119,7 @@ namespace Anabatic {
DbU::Unit dy = updateArea.getYMin() - _area.getYMin(); DbU::Unit dy = updateArea.getYMin() - _area.getYMin();
cdebug_log(110,0) << "raw_i:" << (dx / _side + ((dx%_side) ? 1 : 0)) cdebug_log(110,0) << "raw_i:" << (dx / _side + ((dx%_side) ? 1 : 0))
<< " raw_j:" << (dy / _side + ((dy%_side) ? 1 : 0)) << endl; << " raw_j:" << (dy / _side + ((dy%_side) ? 1 : 0)) << endl;
cdebug_log(110,0) << "indexMin:" << indexMin << endl; cdebug_log(110,0) << "indexMin:" << indexMin << endl;
cdebug_log(110,0) << "indexMax:" << indexMax << endl; cdebug_log(110,0) << "indexMax:" << indexMax << endl;
cdebug_log(110,0) << "xspan: " << xspan << endl; cdebug_log(110,0) << "xspan: " << xspan << endl;
@ -138,6 +140,13 @@ namespace Anabatic {
} }
void Matrix::resize ( Cell* cell, const vector<GCell*>& gcells )
{
setCell( cell, _side );
for ( GCell* gcell : gcells ) updateLookup( gcell );
}
void Matrix::show () const void Matrix::show () const
{ {
cdebug_log(111,0) << this << endl; cdebug_log(111,0) << this << endl;

2600
anabatic/src/NetBuilder.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,643 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./NetBuilderHybridVH.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DebugSession.h"
#include "hurricane/Layer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/DataBase.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/NetRoutingProperty.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/RoutingPads.h"
#include "hurricane/Pin.h"
#include "hurricane/Pad.h"
#include "hurricane/Plug.h"
#include "hurricane/Cell.h"
#include "hurricane/Instance.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "crlcore/AllianceFramework.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/Measures.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoContactHTee.h"
#include "anabatic/AutoContactVTee.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/NetBuilderHybridVH.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using std::swap;
using Hurricane::Error;
using Hurricane::Pin;
NetBuilderHybridVH::NetBuilderHybridVH ()
: NetBuilder()
{ }
NetBuilderHybridVH::~NetBuilderHybridVH () { }
string NetBuilderHybridVH::getStyle ()
{ return "VH,2RL"; }
void NetBuilderHybridVH::doRp_AutoContacts ( GCell* gcell
, Component* rp
, AutoContact*& source
, AutoContact*& target
, uint64_t flags
)
{
throw Error ( "%s::dpRp_AutoContacts() method must never be called.", getTypeName().c_str() );
}
AutoContact* NetBuilderHybridVH::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
{
cdebug_log(145,1) << getTypeName() << "::doRp_Access()" << endl;
cdebug_log(145,0) << rp << endl;
const Layer* rpLayer = rp->getLayer();
//const Layer* viaLayer = Session::getDContactLayer();
DbU::Unit viaSide = Session::getDContactWidth();
Point position = rp->getCenter();
AutoContact* rpContact = AutoContactTerminal::create( gcell, rp, rpLayer, position, viaSide, viaSide );
cdebug_tabw(145,-1);
return rpContact;
}
AutoContact* NetBuilderHybridVH::doRp_AccessNorthSouthPin ( GCell* gcell, RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_AccessNorthSouthPin() " << rp << endl;
AutoContact* rpContact = doRp_Access( gcell, rp, NoFlags );
AutoContact* turn = NULL;
Net* net = rp->getNet();
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
if (pinDir == Pin::AccessDirection::NORTH) {
turn = AutoContactTurn::create( gcell, net, Session::getBuildRoutingLayer(0) );
AutoSegment* segment = AutoSegment::create( rpContact, turn, Flags::Vertical );
segment->setAxis( rp->getX(), Flags::Force );
segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
rpContact = turn;
turn = AutoContactTurn::create( gcell, net, Session::getBuildContactLayer(0) );
segment = AutoSegment::create( rpContact, turn, Flags::Horizontal );
rpContact = turn;
DbU::Unit axis = gcell->getYMax() - Session::getDHorizontalPitch();
cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl;
segment->setAxis( axis, Flags::Force );
//segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
cdebug_log(145,0) << segment << endl;
} else {
turn = rpContact;
}
cdebug_tabw(145,-1);
return turn;
}
AutoContact* NetBuilderHybridVH::doRp_AccessEastWestPin ( GCell* gcell, RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_AccessEastWestPin() " << rp << endl;
Net* net = rp->getNet();
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
AutoContact* rpContact = doRp_Access( gcell, rp, NoFlags );
AutoContact* turn = NULL;
AutoSegment* segment = NULL;
turn = AutoContactTurn::create( gcell, net, Session::getBuildContactLayer(0) );
segment = AutoSegment::create( rpContact, turn, Flags::Horizontal );
segment->setAxis( pin->getCenter().getY(), Flags::Force );
rpContact = turn;
turn = AutoContactTurn::create( gcell, net, Session::getBuildContactLayer(0) );
segment = AutoSegment::create( rpContact, turn, Flags::Vertical );
DbU::Unit axis = 0;
if (pinDir == Pin::AccessDirection::EAST)
axis = gcell->getXMax() - Session::getDVerticalPitch();
else
axis = gcell->getXMin() + Session::getDVerticalPitch();
segment->setAxis( axis );
cdebug_tabw(145,-1);
return turn;
}
bool NetBuilderHybridVH::doRp_xG_1M1 ( RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_xG_1M1()" << endl;
AutoContact* swContact = nullptr;
if (west() or south()) {
AutoContact* termContact = doRp_Access( getGCell(), rp, NoFlags );
if (west() and south()) {
swContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( termContact, swContact, Flags::Vertical );
} else {
if (west()) {
swContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( termContact, swContact, Flags::Vertical );
} else
swContact = termContact;
}
setSouthWestContact( swContact );
}
AutoContact* neContact = nullptr;
if (east() or north()) {
AutoContact* termContact = doRp_Access( getGCell(), rp, NoFlags );
if (east() and north()) {
neContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( termContact, neContact, Flags::Vertical );
} else {
if (east()) {
neContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( termContact, neContact, Flags::Vertical );
} else
neContact = termContact;
}
setNorthEastContact( neContact );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_xG_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1M1()" << endl;
doRp_xG_1M1( getRoutingPads()[0] );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_2G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_1M1()" << endl;
doRp_xG_1M1( getRoutingPads()[0] );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::doRp_xG_xM1_xM3 ( const vector<RoutingPad*>& rps )
{
cdebug_log(145,1) << getTypeName() << "::doRp_xG_xM1()" << endl;
AutoContact* prevContact = nullptr;
AutoContact* currContact = nullptr;
for ( size_t i=0 ; i<rps.size() ; ++i ) {
prevContact = currContact;
AutoContact* currTerm = doRp_Access( getGCell(), rps[i], NoFlags );
if (i == 0) {
if (west() or south()) {
AutoContact* swContact = nullptr;
currContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
if (west() and south()) {
swContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
} else {
if (west())
swContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
else
swContact = currContact;
}
if (swContact != currContact)
AutoSegment::create( currContact, swContact, Flags::Vertical );
setSouthWestContact( swContact );
} else {
currContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
}
AutoSegment::create( currTerm, currContact, Flags::Vertical );
continue;
}
if (i+1 == rps.size()) {
if (east() or north()) {
AutoContact* neContact = nullptr;
currContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
if (east() and north()) {
neContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
} else {
if (east())
neContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
else
neContact = currContact;
}
if (neContact != currContact)
AutoSegment::create( currContact, neContact, Flags::Vertical );
setNorthEastContact( neContact );
} else {
currContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
}
} else {
currContact = AutoContactHTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
}
AutoSegment::create( currTerm , currContact, Flags::Vertical );
AutoSegment::create( prevContact, currContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_xG_xM1_xM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_xM1()" << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
doRp_xG_xM1_xM3( getRoutingPads() );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_xM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1()" << endl;
if (getConnexity().fields.M1 == 1)
_do_xG_1M1();
else
_do_xG_xM1_xM3();
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_xG ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG()" << endl;
const Layer* viaLayer = Session::getBuildContactLayer( 0 );
if (getConnexity().fields.globals == 2) {
setBothCornerContacts( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
} else if (getConnexity().fields.globals == 3) {
if (east() and west()) {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer ) );
if (south()) swapCornerContacts();
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Vertical );
} else {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer ) );
if (west()) swapCornerContacts();
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Horizontal );
}
} else { // fields.globals == 4.
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
setSouthWestContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer ) );
AutoSegment::create( getSouthWestContact(), turn, Flags::Horizontal );
AutoSegment::create( turn, getNorthEastContact(), Flags::Vertical );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_1PinM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM1() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpContact = doRp_AccessNorthSouthPin( getGCell(), getRoutingPads()[0] );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( rpContact, turn1, Flags::Vertical );
if (north() or south()) {
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( turn1, turn2, Flags::Horizontal );
turn1 = turn2;
}
setBothCornerContacts( turn1 );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_2G_1PinM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_1PinM1() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpContact = doRp_AccessNorthSouthPin( getGCell(), getRoutingPads()[0] );
AutoContact* tee = nullptr;
if (east() and west()) {
tee = AutoContactHTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
} else {
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
}
AutoSegment::create( rpContact, tee, Flags::Vertical );
setBothCornerContacts( tee );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_xM1_1PinM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1_1PinM1() [Managed Configuration - Optimized] " << getTopology() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
RoutingPad* rpM2 = nullptr;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) rpM2 = rp;
else rpsM1.push_back( rp );
}
if (rpsM1.size() > 1)
doRp_xG_xM1_xM3( rpsM1 );
else
doRp_xG_1M1( rpsM1[0] );
AutoContact* rpContact = doRp_AccessNorthSouthPin( getGCell(), rpM2 );
AutoContact* rpM1Contact = doRp_Access( getGCell(), rpsM1.front(), NoFlags );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( rpM1Contact, turn1, Flags::Vertical );
AutoSegment::create( rpContact , turn2, Flags::Vertical );
AutoSegment::create( turn1 , turn2, Flags::Horizontal );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::doRp_1G_1PinM2 ( RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpContact = doRp_AccessEastWestPin( getGCell(), rp );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( rpContact, turn1, Flags::Horizontal );
if (east() or west()) {
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( turn1, turn2, Flags::Vertical );
turn1 = turn2;
}
setBothCornerContacts( turn1 );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
doRp_1G_1PinM2( getRoutingPads()[0] );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_xG_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1PinM2()" << endl;
AutoContact* rpContact = doRp_AccessEastWestPin( getGCell(), getRoutingPads()[0] );
AutoContact* neContact = nullptr;
AutoContact* swContact = nullptr;
const Layer* viaLayer = Session::getBuildContactLayer( 0 );
if (getConnexity().fields.globals == 2) {
if (north() and south())
neContact = AutoContactVTee::create( getGCell(), getNet(), viaLayer );
else
neContact = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
AutoSegment::create( rpContact, neContact, Flags::Horizontal );
setBothCornerContacts( neContact );
} else if (getConnexity().fields.globals == 3) {
swContact = AutoContactVTee::create( getGCell(), getNet(), viaLayer );
neContact = AutoContactVTee::create( getGCell(), getNet(), viaLayer );
if (west())
AutoSegment::create( rpContact, neContact, Flags::Horizontal );
else
AutoSegment::create( rpContact, swContact, Flags::Horizontal );
AutoSegment::create( swContact, neContact, Flags::Vertical );
setNorthEastContact( neContact );
setSouthWestContact( swContact );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_xM1_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
RoutingPad* rpM2 = nullptr;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) rpM2 = rp;
else rpsM1.push_back( rp );
}
if (rpsM1.size() > 1)
doRp_xG_xM1_xM3( rpsM1 );
else
doRp_xG_1M1( rpsM1[0] );
Pin* pin = dynamic_cast<Pin*>( rpM2->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
AutoContact* rpContact = doRp_AccessEastWestPin( getGCell(), rpM2 );
AutoContact* rpM1Contact = nullptr;
if (pinDir == Pin::AccessDirection::EAST)
rpM1Contact = doRp_Access( getGCell(), rpsM1.back(), NoFlags );
else
rpM1Contact = doRp_Access( getGCell(), rpsM1.front(), NoFlags );
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( rpM1Contact, turn, Flags::Vertical );
AutoSegment::create( rpContact , turn, Flags::Horizontal );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_1M1 () { return false; }
// bool NetBuilderHybridVH::_do_xG_1Pad () { return false; }
// bool NetBuilderHybridVH::_do_xG_xM2 () { return false; }
// bool NetBuilderHybridVH::_do_1G_1M3 () { return false; }
// bool NetBuilderHybridVH::_do_xG_xM3 () { return false; }
// bool NetBuilderHybridVH::_do_xG_1M1_1M2 () { return false; }
// bool NetBuilderHybridVH::_do_4G_1M2 () { return false; }
bool NetBuilderHybridVH::_do_2G () { return false; }
bool NetBuilderHybridVH::_do_globalSegment ()
{
cdebug_log(145,1) << getTypeName() << "::_do_globalSegment()" << endl;
cdebug_log(145,0) << "getSourceFlags():" << getSourceFlags()
<< " getFlags():" << getFlags() << endl;
if (getSourceContact()) {
uint64_t segmentBound = getSegmentHookType( getFromHook() );
AutoContact* targetContact
= (segmentBound & (NorthBound|EastBound)) ? getNorthEastContact() : getSouthWestContact() ;
if (not getFromHook()) cerr << "getFromHook() is NULL !" << endl;
AutoContact* sourceContact = getSourceContact();
if (segmentBound & (NorthBound|SouthBound)) {
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( sourceContact, turn, Flags::Vertical );
sourceContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( sourceContact, turn, Flags::Horizontal );
}
Segment* baseSegment = static_cast<Segment*>( getFromHook()->getComponent() );
AutoSegment* globalSegment = AutoSegment::create( sourceContact
, targetContact
, baseSegment
);
globalSegment->setFlags( (getDegree() == 2) ? AutoSegment::SegBipoint : 0 );
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
addToFixSegments( globalSegment );
if (getConnexity().fields.globals < 2) {
cdebug_tabw(145,-1);
return false;
}
} else
setFromHook( NULL );
push( east (), getNorthEastContact() );
push( west (), getSouthWestContact() );
push( north(), getNorthEastContact() );
push( south(), getSouthWestContact() );
cdebug_tabw(145,-1);
return true;
}
void NetBuilderHybridVH::singleGCell ( AnabaticEngine* anbt, Net* net )
{
cdebug_log(145,1) << getTypeName() << "::singleGCell() " << net << endl;
vector<RoutingPad*> rps;
for ( RoutingPad* irp : net->getRoutingPads() )
rps.push_back( irp );
if (rps.size() < 2) {
cerr << Error( "%s::singleGCell(): For %s, less than two Plugs/Pins (%d)."
, getTypeName().c_str()
, getString(net).c_str()
, rps.size() ) << endl;
cdebug_tabw(145,-1);
return;
}
sortRpByX( rps, NetBuilder::NoFlags ); // increasing X.
GCell* gcell1 = anbt->getGCellUnder( rps.front()->getCenter() );
GCell* gcell2 = anbt->getGCellUnder( rps.back ()->getCenter() );
if (not gcell1) {
cerr << Error( "No GCell under %s.", getString(rps.front()).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (gcell1 != gcell2) {
cerr << Error( "Not under a single GCell %s.", getString(rps.back()).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
AutoContact* prevContact = nullptr;
AutoContact* currContact = nullptr;
for ( size_t i=0 ; i<rps.size() ; ++i ) {
prevContact = currContact;
AutoContact* currTerm = doRp_Access( gcell1, rps[i], NoFlags );
if (i == 0) {
currContact = AutoContactTurn::create( gcell1, net, Session::getBuildContactLayer(0) );
AutoSegment::create( currTerm, currContact, Flags::Vertical );
continue;
}
if (i+1 == rps.size()) {
currContact = AutoContactTurn::create( gcell1, net, Session::getBuildContactLayer(0) );
} else {
currContact = AutoContactHTee::create( gcell1, net, Session::getBuildContactLayer(0) );
}
AutoSegment::create( currTerm , currContact, Flags::Vertical );
AutoSegment::create( prevContact, currContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
}
string NetBuilderHybridVH::getTypeName () const
{ return "NetBuilderHybridVH"; }
} // Anabatic namespace.

View File

@ -0,0 +1,356 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./NetBuilderM2.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DebugSession.h"
#include "hurricane/Layer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/DataBase.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/NetRoutingProperty.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/RoutingPads.h"
#include "hurricane/Pad.h"
#include "hurricane/Plug.h"
#include "hurricane/Cell.h"
#include "hurricane/Instance.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "crlcore/AllianceFramework.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/Measures.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoContactHTee.h"
#include "anabatic/AutoContactVTee.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/NetBuilderM2.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using std::swap;
NetBuilderM2::NetBuilderM2 ()
: NetBuilder()
{ }
NetBuilderM2::~NetBuilderM2 () { }
string NetBuilderM2::getStyle ()
{ return "2RL-"; }
void NetBuilderM2::doRp_AutoContacts ( GCell* gcell
, Component* rp
, AutoContact*& source
, AutoContact*& target
, uint64_t flags
)
{
cdebug_log(145,1) << "NetBuilderM2::doRp_AutoContacts()" << endl;
cdebug_log(145,0) << rp << endl;
source = target = NULL;
Point sourcePosition;
Point targetPosition;
const Layer* rpLayer = rp->getLayer();
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
Flags direction = Session::getDirection ( rpDepth );
DbU::Unit viaSide = Session::getViaWidth ( rpDepth );
getPositions( rp, sourcePosition, targetPosition );
if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition );
if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition );
GCell* sourceGCell = Session::getAnabatic()->getGCellUnder( sourcePosition );
GCell* targetGCell = Session::getAnabatic()->getGCellUnder( targetPosition );
if (rpDepth == 0) {
rpLayer = Session::getContactLayer(0);
direction = Flags::Horizontal;
viaSide = Session::getViaWidth( rpDepth );
}
// Non-M1 terminal or punctual M1 protections.
if ((rpDepth != 0) or (sourcePosition == targetPosition)) {
map<Component*,AutoSegment*>::iterator irp = getRpLookup().find( rp );
if (irp == getRpLookup().end()) {
AutoContact* sourceProtect = AutoContactTerminal::create( sourceGCell
, rp
, rpLayer
, sourcePosition
, viaSide, viaSide
);
AutoContact* targetProtect = AutoContactTerminal::create( targetGCell
, rp
, rpLayer
, targetPosition
, viaSide, viaSide
);
sourceProtect->setFlags( CntFixed );
targetProtect->setFlags( CntFixed );
AutoSegment* segment = AutoSegment::create( sourceProtect, targetProtect, direction );
segment->setFlags( AutoSegment::SegFixed );
getRpLookup().insert( make_pair(rp,segment) );
}
}
if (sourcePosition != targetPosition) {
if (flags & DoSourceContact)
source = AutoContactTerminal::create( sourceGCell
, rp
, rpLayer
, sourcePosition
, viaSide, viaSide
);
if (flags & DoTargetContact)
target = AutoContactTerminal::create( targetGCell
, rp
, rpLayer
, targetPosition
, viaSide, viaSide
);
}
if (not source and not target) {
source = target = AutoContactTerminal::create( gcell
, rp
, rpLayer
, rp->getCenter()
, viaSide, viaSide
);
}
cdebug_tabw(145,-1);
return;
}
AutoContact* NetBuilderM2::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
{
cdebug_log(145,1) << getTypeName() << "::doRp_Access()" << endl;
cdebug_log(145,0) << rp << endl;
Point sourcePosition;
Point targetPosition;
const Layer* rpLayer = rp->getLayer();
const Layer* viaLayer = Session::getDContactLayer();
DbU::Unit viaSide = Session::getDContactWidth();
DbU::Unit ypitch = Session::getDVerticalPitch();
getPositions( rp, sourcePosition, targetPosition );
if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition );
if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition );
Point position = rp->getCenter();
if (not (flags & Middle)) {
if (flags & NorthBound) position = targetPosition;
if (flags & SouthBound) position = sourcePosition;
}
DbU::Unit ycontact = (flags & SouthBound) ? gcell->getYMin() : gcell->getYMax()-ypitch;
AutoContact* rpContact = AutoContactTerminal::create( gcell, rp, rpLayer, position, viaSide, viaSide );
AutoContact* contact1 = AutoContactTurn::create( gcell, getNet(), viaLayer );
AutoContact* contact2 = AutoContactTurn::create( gcell, getNet(), viaLayer );
contact1->setPosition( position.getX(), ycontact );
contact2->setPosition( position.getX(), ycontact );
rpContact->setFlags( CntFixed );
contact1 ->setFlags( CntFixed );
contact2 ->setFlags( CntFixed );
AutoSegment* fixed = AutoSegment::create( rpContact, contact1, Flags::Vertical );
AutoSegment* dogleg = AutoSegment::create( contact1 , contact2, Flags::Horizontal|Flags::UseNonPref );
fixed ->setFlags( AutoSegment::SegFixed );
dogleg->setFlags( AutoSegment::SegFixed );
cdebug_tabw(145,-1);
return contact2;
}
bool NetBuilderM2::_do_1G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1()" << endl;
uint64_t flags = NoFlags;
if (north()) flags |= NorthBound;
else if (south()) flags |= SouthBound;
AutoContact* contact = NULL;
contact = doRp_Access( getGCell(), getRoutingPads()[0], flags );
setNorthEastContact( contact );
push( north(), contact, SouthWest );
push( south(), contact, SouthWest );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderM2::_do_2G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_1M1()" << endl;
AutoContact* contact = NULL;
contact = doRp_Access( getGCell(), getRoutingPads()[0], SouthBound|NorthBound );
push( north(), contact, SouthWest|Middle );
contact = doRp_Access( getGCell(), getRoutingPads()[0], SouthBound|NorthBound );
push( south(), contact, SouthWest|Middle );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderM2::_do_xG ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG()" << endl;
vector<Hook*> hooksNS = getNorths();
hooksNS.insert( hooksNS.end(), getSouths().begin(), getSouths().end() );
sortHookByX( hooksNS, NoFlags );
const Layer* viaLayer = Session::getDContactLayer();
AutoContact* contactW = NULL;
AutoContact* contactE = NULL;
// Simple turn.
if ( (west() and not east() and (hooksNS.size() == 1))
or (east() and not west() and (hooksNS.size() == 1)) ) {
contactW = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
push( west() , contactW, SouthWest );
push( east() , contactW, SouthWest );
push( hooksNS[0], contactW, SouthWest );
cdebug_tabw(145,-1);
return true;
}
// Simple HTee.
if (west() and east() and (hooksNS.size() == 1)) {
contactW = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
push( west() , contactW, SouthWest );
push( east() , contactW, SouthWest );
push( hooksNS[0], contactW, SouthWest );
cdebug_tabw(145,-1);
return true;
}
cdebug_log(145,0) << "West side processing." << endl;
// West side processing.
if (west()) {
contactW = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
push( west() , contactW, SouthWest );
push( hooksNS[0], contactW, SouthWest );
} else {
contactW = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
push( hooksNS[0], contactW, SouthWest );
}
cdebug_log(145,0) << "Middle processing." << endl;
// Middle (North & South) processing.
if (hooksNS.size() > 2) {
for ( size_t i=1 ; i<hooksNS.size()-1 ; ++i ) {
AutoContact* current = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
AutoSegment::create( contactW, current, Flags::Horizontal );
push( hooksNS[i], current, SouthWest );
contactW = current;
}
}
cdebug_log(145,0) << "East side processing." << endl;
// East side processing.
if (east()) {
contactE = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
push( east(), contactE, SouthWest );
if (hooksNS.size() > 1)
push( hooksNS[hooksNS.size()-1], contactE, SouthWest );
} else {
contactE = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
push( hooksNS[hooksNS.size()-1], contactE, SouthWest );
}
AutoSegment::create( contactW, contactE, Flags::Horizontal );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderM2::_do_globalSegment ()
{
cdebug_log(145,1) << getTypeName() << "::_do_globalSegment()" << endl;
if (getSourceContact()) {
Segment* segment = static_cast <Segment*> ( getFromHook()->getComponent() );
AutoSegment* globalSegment = AutoSegment::create( getSourceContact(), getSouthWestContact(), segment );
globalSegment->setFlags( (getDegree() == 2) ? AutoSegment::SegBipoint : 0 );
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
addToFixSegments( globalSegment );
if (getConnexity().fields.globals < 2) {
cdebug_tabw(145,-1);
return false;
}
} else
setFromHook( NULL );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderM2::_do_1G_xM1 () { return false; }
bool NetBuilderM2::_do_xG_1Pad () { return false; }
bool NetBuilderM2::_do_1G_1PinM2 () { return false; }
bool NetBuilderM2::_do_xG_xM2 () { return false; }
bool NetBuilderM2::_do_1G_1M3 () { return false; }
bool NetBuilderM2::_do_xG_xM3 () { return false; }
bool NetBuilderM2::_do_xG_1M1_1M2 () { return false; }
bool NetBuilderM2::_do_xG_xM1_xM3 () { return false; }
bool NetBuilderM2::_do_4G_1M2 () { return false; }
bool NetBuilderM2::_do_2G () { return false; }
string NetBuilderM2::getTypeName () const
{ return "NetBuilderM2"; }
} // Anabatic namespace.

View File

@ -0,0 +1,650 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2018-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./NetBuilderVH.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DebugSession.h"
#include "hurricane/Layer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/DataBase.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/NetRoutingProperty.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/RoutingPads.h"
#include "hurricane/Pad.h"
#include "hurricane/Pin.h"
#include "hurricane/Plug.h"
#include "hurricane/Cell.h"
#include "hurricane/Instance.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "crlcore/AllianceFramework.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/Measures.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoContactHTee.h"
#include "anabatic/AutoContactVTee.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/NetBuilderVH.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using std::swap;
using Hurricane::Transformation;
using Hurricane::Warning;
using Hurricane::Error;
using Hurricane::Pin;
NetBuilderVH::NetBuilderVH ()
: NetBuilder()
{ }
NetBuilderVH::~NetBuilderVH () { }
string NetBuilderVH::getStyle ()
{ return "VH,3RL+"; }
void NetBuilderVH::doRp_AutoContacts ( GCell* gcell
, Component* rp
, AutoContact*& source
, AutoContact*& target
, uint64_t flags
)
{
cdebug_log(145,1) << getTypeName() << "::doRp_AutoContacts()" << endl;
cdebug_log(145,0) << rp << endl;
source = target = NULL;
Point sourcePosition;
Point targetPosition;
const Layer* rpLayer = rp->getLayer();
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
Flags direction = Session::getDirection ( rpDepth );
DbU::Unit viaSide = Session::getViaWidth ( rpDepth );
getPositions( rp, sourcePosition, targetPosition );
if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition );
if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition );
GCell* sourceGCell = Session::getAnabatic()->getGCellUnder( sourcePosition );
GCell* targetGCell = Session::getAnabatic()->getGCellUnder( targetPosition );
if (rpDepth == 0) {
rpLayer = Session::getContactLayer(0);
direction = Flags::Vertical;
viaSide = Session::getViaWidth( rpDepth );
RoutingPad* rrp = dynamic_cast<RoutingPad*>( rp );
if (rrp) {
// if (not getAnabatic()->getConfiguration()->selectRpComponent(rrp)) {
// cerr << Warning( "%s::doRp_AutoContacts(): %s has no components on grid."
// , getTypeName().c_str()
// , getString(rp).c_str() ) << endl;
// }
} else {
cerr << Warning( "%s::doRp_AutoContacts(): %s is *not* a RoutingPad."
, getTypeName().c_str()
, getString(rp).c_str() ) << endl;
}
}
// Non-M1 terminal or punctual M1 protections.
if ( (rpDepth != 0) or (sourcePosition == targetPosition) ) {
map<Component*,AutoSegment*>::iterator irp = getRpLookup().find( rp );
if (irp == getRpLookup().end()) {
AutoContact* sourceProtect = AutoContactTerminal::create( sourceGCell
, rp
, rpLayer
, sourcePosition
, viaSide, viaSide
);
AutoContact* targetProtect = AutoContactTerminal::create( targetGCell
, rp
, rpLayer
, targetPosition
, viaSide, viaSide
);
sourceProtect->setFlags( CntFixed );
targetProtect->setFlags( CntFixed );
AutoSegment* segment = AutoSegment::create( sourceProtect, targetProtect, direction );
segment->setFlags( AutoSegment::SegFixed );
getRpLookup().insert( make_pair(rp,segment) );
}
}
if (sourcePosition != targetPosition) {
if (flags & DoSourceContact)
source = AutoContactTerminal::create( sourceGCell
, rp
, rpLayer
, sourcePosition
, viaSide, viaSide
);
if (flags & DoTargetContact)
target = AutoContactTerminal::create( targetGCell
, rp
, rpLayer
, targetPosition
, viaSide, viaSide
);
}
if ( (rpDepth > 0) and not Session::getRoutingGauge()->isSuperPitched() ) {
rpLayer = Session::getContactLayer( rpDepth );
}
if (not source and not target) {
source = target = AutoContactTerminal::create( gcell
, rp
, rpLayer
, rp->getCenter()
, viaSide, viaSide
);
}
cdebug_tabw(145,-1);
return;
}
AutoContact* NetBuilderVH::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
{
cdebug_log(145,1) << getTypeName() << "::doRp_Access() - flags:" << flags << endl;
AutoContact* rpContactSource = NULL;
AutoContact* rpContactTarget = NULL;
const Layer* rpLayer = rp->getLayer();
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
flags |= checkRoutingPadSize( rp );
doRp_AutoContacts( gcell, rp, rpContactSource, rpContactTarget, flags );
if (rpDepth % 2 == 0) { // RP should be vertical (M1, M3).
if (not (flags & (HAccess|HAccessEW))) {
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
AutoContact* subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
AutoSegment::create( rpContactSource, subContact1, Flags::Vertical , rpDepth+2 );
AutoSegment::create( subContact1, subContact2, Flags::Horizontal, rpDepth+1 );
rpContactSource = subContact2;
} else {
if (flags & VSmall) {
AutoContact* subContact1 = NULL;
if (flags & HAccessEW)
subContact1 = AutoContactHTee::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
else
subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
AutoSegment::create( rpContactSource, subContact1, Flags::Vertical );
rpContactSource = subContact1;
}
}
} else { // RP should be horizontal (M2).
if (flags & (HAccess|HAccessEW)) {
AutoContact* subContact1 = NULL;
if (flags & HAccessEW)
subContact1 = AutoContactHTee::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
else
subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
AutoSegment::create( rpContactSource, subContact1, Flags::Vertical, rpDepth+1 );
rpContactSource = subContact1;
}
}
cdebug_tabw(145,-1);
return rpContactSource;
}
bool NetBuilderVH::_do_1G_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
Pin* pin = dynamic_cast<Pin*>( getRoutingPads()[0]->getOccurrence().getEntity() );
if ( (pin->getAccessDirection() != Pin::AccessDirection::SOUTH)
and (pin->getAccessDirection() != Pin::AccessDirection::NORTH) ) {
cerr << Error( "%s::do_1G_1PinM2(): %s *must* be north or south."
, getTypeName().c_str()
, getString(pin).c_str() ) << endl;
}
uint64_t flags = NoFlags;
if (east()) { flags |= HAccess|VSmall; }
else if (west()) { flags |= HAccess|VSmall; }
setBothCornerContacts( doRp_Access(getGCell(),getRoutingPads()[0],flags) );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_xG_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1PinM2() [Managed Configuration] " << getTopology() << endl;
Pin* pin = dynamic_cast<Pin*>( getRoutingPads()[0]->getOccurrence().getEntity() );
if ( (pin->getAccessDirection() != Pin::AccessDirection::SOUTH)
and (pin->getAccessDirection() != Pin::AccessDirection::NORTH) ) {
cerr << Error( "%s::do_xG_1PinM2(): %s *must* be north or south."
, getTypeName().c_str()
, getString(pin).c_str() ) << endl;
}
RoutingPad* rp = getRoutingPads()[0];
AutoContact* pinContact = NULL;
doRp_AutoContacts( getGCell(), rp, pinContact, pinContact, HSmall|VSmall );
if (not north() and not south()) {
AutoContact* subContact1 = AutoContactHTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact, subContact1, Flags::Vertical );
setBothCornerContacts( subContact1 );
} else {
AutoContact* subContact1 = AutoContactVTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact, subContact1, Flags::Vertical );
if (east() and west()) {
AutoContact* subContact2 = AutoContactVTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( subContact1, subContact2, Flags::Vertical );
setSouthWestContact( (south()) ? subContact1 : subContact2 );
setNorthEastContact( (south()) ? subContact2 : subContact1 );
} else
setBothCornerContacts( subContact1 );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_1G_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
Pin* pin = dynamic_cast<Pin*>( getRoutingPads()[0]->getOccurrence().getEntity() );
if ( (pin->getAccessDirection() != Pin::AccessDirection::EAST)
and (pin->getAccessDirection() != Pin::AccessDirection::WEST) ) {
cerr << Error( "%s::do_1G_1PinM2(): %s *must* be east or west."
, getTypeName().c_str()
, getString(pin).c_str() ) << endl;
}
AutoContact* pinContact = NULL;
doRp_AutoContacts( getGCell(), getRoutingPads()[0], pinContact, pinContact, HSmall|VSmall );
if (east() or west()) {
AutoContact* subContact1 = AutoContactTurn::create( getGCell(), getRoutingPads()[0]->getNet(), Session::getContactLayer(1) );
AutoContact* subContact2 = AutoContactTurn::create( getGCell(), getRoutingPads()[0]->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact , subContact1, Flags::Horizontal );
AutoSegment::create( subContact1, subContact2, Flags::Vertical );
pinContact = subContact2;
} else {
AutoContact* subContact1 = NULL;
subContact1 = AutoContactTurn::create( getGCell(), getRoutingPads()[0]->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact, subContact1, Flags::Horizontal );
pinContact = subContact1;
}
setBothCornerContacts( pinContact );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_xG_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1PinM3() [Managed Configuration] " << getTopology() << endl;
RoutingPad* rp = getRoutingPads()[0];
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
if ( (pin->getAccessDirection() != Pin::AccessDirection::EAST)
and (pin->getAccessDirection() != Pin::AccessDirection::WEST) ) {
cerr << Error( "%s::do_xG_1PinM3(): %s *must* be east or west."
, getTypeName().c_str()
, getString(pin).c_str() ) << endl;
}
AutoContact* pinContact = NULL;
doRp_AutoContacts( getGCell(), rp, pinContact, pinContact, HSmall|VSmall );
if (not east() and not west()) {
AutoContact* subContact1 = AutoContactVTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact, subContact1, Flags::Horizontal );
setBothCornerContacts( subContact1 );
} else {
AutoContact* subContact1 = AutoContactHTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact, subContact1, Flags::Horizontal );
if (north() and south()) {
AutoContact* subContact2 = AutoContactHTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( subContact1, subContact2, Flags::Horizontal );
setSouthWestContact( (west()) ? subContact1 : subContact2 );
setNorthEastContact( (west()) ? subContact2 : subContact1 );
} else
setBothCornerContacts( subContact1 );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_1G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1() [Managed Configuration - Optimized] " << getTopology() << endl;
uint64_t flags = NoFlags;
if (east()) { flags |= HAccess|VSmall; }
else if (west()) { flags |= HAccess|VSmall; }
setBothCornerContacts( doRp_Access(getGCell(),getRoutingPads()[0],flags) );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_1G_xM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_" << (int)getConnexity().fields.M1 << "M1() [Defered Configuration]" << endl;
_do_xG_xM1_xM3();
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_2G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_1M1 [Managed Configuration]" << endl;
cdebug_log(145,0) << "north: " << north() << endl;
cdebug_log(145,0) << "south: " << south() << endl;
cdebug_log(145,0) << "east: " << east() << endl;
cdebug_log(145,0) << "west: " << west() << endl;
AutoContact* tee = NULL;
if (east() and west()) {
tee = doRp_Access( getGCell(), getRoutingPads()[0], HAccessEW|VSmall );
} else {
AutoContact* turn = doRp_Access( getGCell(), getRoutingPads()[0], HAccess|VSmall );
if (east() or west())
tee = AutoContactHTee::create( getGCell(), getNet(), Session::getDContactLayer() );
else
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getDContactLayer() );
AutoSegment::create( turn, tee, Flags::Horizontal );
}
setBothCornerContacts( tee );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_xG_xM1_xM3 ()
{
// Implicit hypothesis : we have at least two globals and at least one terminal.
cdebug_log(145,1) << getTypeName()
<< "::_do_xG_" << (int)getConnexity().fields.M1
<< "M1_" << (int)getConnexity().fields.M3
<< "M3() [G:" << (int)getConnexity().fields.globals << " Managed Configuration]" << endl;
cdebug_log(145,0) << "getConnexity(): " << getConnexity().connexity << endl;
cdebug_log(145,0) << "north: " << north() << endl;
cdebug_log(145,0) << "south: " << south() << endl;
cdebug_log(145,0) << "east: " << east() << endl;
cdebug_log(145,0) << "west: " << west() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
size_t iLast = getRoutingPads().size()-1;
AutoContact* leftContact = NULL;
AutoContact* rightContact = NULL;
if (south() or west()) {
leftContact = doRp_Access( getGCell(), getRoutingPads()[0], HAccessEW|VSmall );
if (south() and west()) {
setSouthWestContact( AutoContactHTee::create( getGCell(), getNet(), Session::getDContactLayer() ) );
AutoSegment::create( getSouthWestContact(), leftContact, Flags::Horizontal );
} else {
if (west())
setSouthWestContact( leftContact );
else {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), Session::getDContactLayer() ) );
AutoSegment::create( leftContact, getSouthWestContact(), Flags::Horizontal );
}
}
} else {
leftContact = doRp_Access( getGCell(), getRoutingPads()[0], HAccess|VSmall );
}
for ( size_t i=1 ; i<getRoutingPads().size()-1 ; ++i ) {
rightContact = doRp_Access( getGCell(), getRoutingPads()[i], HAccessEW|VSmall );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
leftContact = rightContact;
}
if (north() or east()) {
if (getRoutingPads().size() > 1) {
rightContact = doRp_Access( getGCell(), getRoutingPads()[iLast], HAccessEW|VSmall );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
} else {
rightContact = leftContact;
}
if (north() and east()) {
setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), Session::getDContactLayer() ) );
AutoSegment::create( rightContact, getNorthEastContact(), Flags::Horizontal );
} else {
if (east())
setNorthEastContact( rightContact );
else {
setNorthEastContact( AutoContactTurn::create( getGCell(), getNet(), Session::getDContactLayer() ) );
AutoSegment::create( rightContact, getNorthEastContact(), Flags::Horizontal );
}
}
} else {
rightContact = doRp_Access( getGCell(), getRoutingPads()[iLast], HAccess|VSmall );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_2G ()
{
cdebug_log(145,0) << getTypeName() << "::_do_2G()" << endl;
return _do_xG();
}
bool NetBuilderVH::_do_xG ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG()" << endl;
const Layer* viaLayer = Session::getDContactLayer();
if (getConnexity().fields.globals == 2) {
setBothCornerContacts( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
} else if (getConnexity().fields.globals == 3) {
if (east() and west()) {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer ) );
if (south()) swapCornerContacts();
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Vertical );
} else {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer ) );
if (west()) swapCornerContacts();
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Horizontal );
}
} else { // fields.globals == 4.
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
setSouthWestContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer ) );
AutoSegment::create( getSouthWestContact(), turn, Flags::Horizontal );
AutoSegment::create( turn, getNorthEastContact(), Flags::Vertical );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_globalSegment ()
{
cdebug_log(145,1) << getTypeName() << "::_do_globalSegment()" << endl;
if (getSourceContact()) {
AutoContact* targetContact
= ( getSegmentHookType(getFromHook()) & (NorthBound|EastBound) )
? getNorthEastContact() : getSouthWestContact() ;
AutoSegment* globalSegment = AutoSegment::create( getSourceContact()
, targetContact
, static_cast<Segment*>( getFromHook()->getComponent() )
);
globalSegment->setFlags( (getDegree() == 2) ? AutoSegment::SegBipoint : 0 );
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
addToFixSegments( globalSegment );
if (getConnexity().fields.globals < 2) {
cdebug_tabw(145,-1);
return false;
}
} else
setFromHook( NULL );
push( east (), getNorthEastContact() );
push( west (), getSouthWestContact() );
push( north(), getNorthEastContact() );
push( south(), getSouthWestContact() );
cdebug_tabw(145,-1);
return true;
}
void NetBuilderVH::singleGCell ( AnabaticEngine* anbt, Net* net )
{
cdebug_log(145,1) << getTypeName() << "::singleGCell() " << net << endl;
vector<RoutingPad*> rps;
for ( RoutingPad* rp : net->getRoutingPads() ) {
if (Session::getRoutingGauge()->getLayerDepth(rp->getLayer()) == 0) {
rps.push_back( rp );
continue;
}
cerr << Error( "%s::singleGCell(): Non metal1 terminals are not managed yet.\n"
" (%s)"
, getTypeName().c_str()
, getString(rp).c_str()
) << endl;
cdebug_tabw(145,-1);
return;
}
if (rps.size() < 2) {
cerr << Error( "%s::singleGCell(): For %s, less than two Plugs/Pins (%d)."
, getTypeName().c_str()
, getString(net).c_str()
, rps.size() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (rps.empty()) {
cerr << Error( "%s::singleGCell(): No terminals for Net \"%s\"."
, getTypeName().c_str()
, getString(net->getName()).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
sortRpByX( rps, NetBuilder::NoFlags ); // increasing X.
GCell* gcell1 = anbt->getGCellUnder( (*rps.begin ())->getCenter() );
GCell* gcell2 = anbt->getGCellUnder( (*rps.rbegin())->getCenter() );
if (not gcell1) {
cerr << Error( "%s::singleGCell(): No GCell under %s."
, getTypeName().c_str()
, getString(*(rps.begin())).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (gcell1 != gcell2) {
cerr << Error( "%s::singleGCell(): Not under a single GCell %s."
, getTypeName().c_str()
, getString(*(rps.rbegin())).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
cdebug_log(145,0) << "singleGCell " << gcell1 << endl;
AutoContact* source = NULL;
AutoContact* target = NULL;
for ( size_t irp=1 ; irp<rps.size() ; ++irp ) {
source = doRp_Access( gcell1, rps[irp-1], HAccess|VSmall );
target = doRp_Access( gcell1, rps[irp ], HAccess|VSmall );
AutoSegment::create( source, target, Flags::Horizontal );
}
cdebug_tabw(145,-1);
}
string NetBuilderVH::getTypeName () const
{ return "NetBuilderVH"; }
} // Anabatic namespace.

View File

@ -61,55 +61,55 @@ namespace {
void propagateConstraintFromRp ( RoutingPad* rp ) void propagateConstraintFromRp ( RoutingPad* rp )
{ {
cdebug_log(145,1) << "propagateConstraintFromRp() - " << rp << endl; cdebug_log(146,1) << "propagateConstraintFromRp() - " << rp << endl;
for ( Component* component : rp->getSlaveComponents() ) { for ( Component* component : rp->getSlaveComponents() ) {
cdebug_log(145,0) << "slave component: " << component << endl; cdebug_log(146,0) << "slave component: " << component << endl;
AutoContact* sourceContact = Session::lookup( dynamic_cast<Contact*>(component) ); AutoContact* sourceContact = Session::lookup( dynamic_cast<Contact*>(component) );
if (sourceContact) { if (sourceContact) {
cdebug_log(145,0) << "Start slave: " << sourceContact << endl; Box constraintBox = sourceContact->getConstraintBox();
cdebug_log(146,0) << "Start slave: " << sourceContact << endl;
cdebug_log(146,0) << "Constraint: " << constraintBox << endl;
set<AutoSegment*> verticalSegments; set<AutoSegment*> verticalSegments;
set<AutoSegment*> horizontalSegments; set<AutoSegment*> horizontalSegments;
for ( AutoSegment* segment : sourceContact->getAutoSegments() ) { for ( AutoSegment* segment : sourceContact->getAutoSegments() ) {
cdebug_log(145,0) << "Examining: " << segment << endl; cdebug_log(146,0) << "Examining: " << segment << endl;
AutoContact* targetContact = segment->getOppositeAnchor(sourceContact); AutoContact* targetContact = segment->getOppositeAnchor(sourceContact);
if (targetContact) { if (targetContact) {
if (segment->isHorizontal()) { if (segment->isHorizontal()) {
cdebug_log(145,0) << "On horizontal stack " << segment << endl; cdebug_log(146,0) << "On horizontal stack " << segment << endl;
horizontalSegments.insert( segment ); horizontalSegments.insert( segment );
} else { } else {
cdebug_log(145,0) << "On vertical stack " << segment << endl; cdebug_log(146,0) << "On vertical stack " << segment << endl;
verticalSegments.insert( segment ); verticalSegments.insert( segment );
} }
} }
} }
Box constraintBox = sourceContact->getConstraintBox();
cdebug_log(145,0) << "Contraint: " << constraintBox << endl;
// Propagate constraint through horizontally aligned segments. // Propagate constraint through horizontally aligned segments.
cdebug_log(145,0) << "Propagate constraint on horizontal segments" << endl; cdebug_log(146,0) << "Propagate constraint on horizontal segments" << endl;
for ( AutoSegment* horizontal : horizontalSegments ) { for ( AutoSegment* horizontal : horizontalSegments ) {
AutoContact* contact = NULL; AutoContact* contact = NULL;
for ( AutoSegment* aligned : horizontal->getAligneds(Flags::WithSelf) ) { for ( AutoSegment* aligned : horizontal->getAligneds(Flags::WithSelf) ) {
cdebug_log(145,0) << "aligned horizontal: " << aligned << endl; cdebug_log(146,0) << "aligned horizontal: " << aligned << endl;
contact = aligned->getAutoTarget(); contact = aligned->getAutoTarget();
cdebug_log(145,0) << "contact: " << contact << endl; cdebug_log(146,0) << "contact: " << contact << endl;
if (contact) { if (contact) {
cdebug_log(145,0) << "Apply to (target): " << contact << endl; cdebug_log(146,0) << "Apply to (target): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getYMin() contact->restrictConstraintBox( constraintBox.getYMin()
, constraintBox.getYMax() , constraintBox.getYMax()
, Flags::Horizontal|Flags::WarnOnError ); , Flags::Horizontal|Flags::WarnOnError );
} }
contact = aligned->getAutoSource(); contact = aligned->getAutoSource();
cdebug_log(145,0) << "contact: " << contact << endl; cdebug_log(146,0) << "contact: " << contact << endl;
if (contact) { if (contact) {
cdebug_log(145,0) << "Apply to (source): " << contact << endl; cdebug_log(146,0) << "Apply to (source): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getYMin() contact->restrictConstraintBox( constraintBox.getYMin()
, constraintBox.getYMax() , constraintBox.getYMax()
, Flags::Horizontal|Flags::WarnOnError ); , Flags::Horizontal|Flags::WarnOnError );
@ -118,23 +118,23 @@ namespace {
} }
// Propagate constraint through vertically aligned segments. // Propagate constraint through vertically aligned segments.
cdebug_log(145,0) << "Propagate constraint on vertical segments" << endl; cdebug_log(146,0) << "Propagate constraint on vertical segments" << endl;
for ( AutoSegment* vertical : verticalSegments ) { for ( AutoSegment* vertical : verticalSegments ) {
AutoContact* contact = NULL; AutoContact* contact = NULL;
for ( AutoSegment* aligned : vertical->getAligneds(Flags::WithSelf) ) { for ( AutoSegment* aligned : vertical->getAligneds(Flags::WithSelf) ) {
cdebug_log(145,0) << "aligned vertical: " << aligned << endl; cdebug_log(146,0) << "aligned vertical: " << aligned << endl;
contact = aligned->getAutoTarget(); contact = aligned->getAutoTarget();
if (contact) { if (contact) {
cdebug_log(145,0) << "Apply to (target): " << contact << endl; cdebug_log(146,0) << "Apply to (target): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getXMin() contact->restrictConstraintBox( constraintBox.getXMin()
, constraintBox.getXMax() , constraintBox.getXMax()
, Flags::Vertical|Flags::WarnOnError ); , Flags::Vertical|Flags::WarnOnError );
} }
contact = aligned->getAutoSource(); contact = aligned->getAutoSource();
if (contact) { if (contact) {
cdebug_log(145,0) << "Apply to (source): " << contact << endl; cdebug_log(146,0) << "Apply to (source): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getXMin() contact->restrictConstraintBox( constraintBox.getXMin()
, constraintBox.getXMax() , constraintBox.getXMax()
, Flags::Vertical|Flags::WarnOnError ); , Flags::Vertical|Flags::WarnOnError );
@ -144,8 +144,8 @@ namespace {
} }
} }
cdebug_log(145,0) << "propagateConstraintFromRp() - Exit" << endl; cdebug_log(146,0) << "propagateConstraintFromRp() - Exit" << endl;
cdebug_tabw(145,-1); cdebug_tabw(146,-1);
} }
@ -159,35 +159,128 @@ namespace Anabatic {
using Hurricane::Cell; using Hurricane::Cell;
void propagateDistanceFromRp ( RoutingPad* rp )
{
cdebug_log(146,1) << "propagateDistanceFromRp() - " << rp << endl;
unsigned int distance = 0;
vector< pair<AutoContact*,AutoSegment*> > currents;
vector< pair<AutoContact*,AutoSegment*> > successors;
for ( Component* component : rp->getSlaveComponents() ) {
cdebug_log(146,0) << "slave component: " << component << endl;
AutoContact* sourceContact = Session::lookup( dynamic_cast<Contact*>(component) );
if (sourceContact) {
cdebug_log(146,0) << "Start slave: " << sourceContact << endl;
for ( AutoSegment* segment : sourceContact->getAutoSegments() ) {
cdebug_log(146,0) << "Pushing: " << segment << endl;
currents.push_back( make_pair(sourceContact,segment) );
}
}
}
while ( not currents.empty() ) {
for ( size_t i = 0 ; i<currents.size() ; ++i ) {
AutoContact* source = currents[i].first;
AutoSegment* segment = currents[i].second;
if ( (distance == 1) and (segment->getRpDistance() == 1) ) {
vector<GCell*> gcells;
segment->getGCells( gcells );
if (gcells.size() < 3)
segment->setFlags( AutoSegment::SegUnbreakable );
}
if (distance >= segment->getRpDistance()) continue;
segment->setRpDistance( distance );
cdebug_log(146,0) << "Popped: " << segment << endl;
AutoContact* target = segment->getOppositeAnchor( source );
if (target) {
for ( AutoSegment* successor : target->getAutoSegments() ) {
if (successor == segment) continue;
// if (successor->isNonPref()) {
// cdebug_log(146,0) << "Pushing (non-pref): " << successor << endl;
// currents.push_back( make_pair(target,successor) );
// } else {
cdebug_log(146,0) << "Pushing: " << successor << endl;
successors.push_back( make_pair(target,successor) );
// }
}
}
}
if (++distance > 15) break;
currents.clear();
currents.swap( successors );
}
cdebug_log(146,0) << "propagateDistanceFromRp() - Exit" << endl;
cdebug_tabw(146,-1);
}
void AnabaticEngine::computeNetConstraints ( Net* net ) void AnabaticEngine::computeNetConstraints ( Net* net )
{ {
DebugSession::open( net, 140, 150); DebugSession::open( net, 146, 150);
cdebug_log(149,0) << "Anabatic::computeNetConstraints( " << net << " )" << endl; cdebug_log(149,0) << "Anabatic::computeNetConstraints( " << net << " )" << endl;
cdebug_tabw(145,1); cdebug_tabw(146,1);
vector<RoutingPad*> routingPads; vector<RoutingPad*> routingPads;
forEach ( Component*, icomponent, net->getComponents() ) { for ( Component* component : net->getComponents() ) {
Contact* contact = dynamic_cast<Contact*>( *icomponent ); Contact* contact = dynamic_cast<Contact*>( component );
if (contact) { if (contact) {
AutoContact* autoContact = Session::lookup( contact ); AutoContact* autoContact = Session::lookup( contact );
if (autoContact) if (autoContact)
autoContact->restoreNativeConstraintBox(); autoContact->restoreNativeConstraintBox();
} else { } else {
RoutingPad* routingPad = dynamic_cast<RoutingPad*>( *icomponent ); Segment* segment = dynamic_cast<Segment*>( component );
if (routingPad) routingPads.push_back( routingPad ); if (segment) {
AutoSegment* autoSegment = Session::lookup( segment );
if (autoSegment)
autoSegment->setRpDistance( 15 );
} else {
RoutingPad* routingPad = dynamic_cast<RoutingPad*>( component );
if (routingPad) routingPads.push_back( routingPad );
}
} }
} }
for ( size_t i=0 ; i<routingPads.size() ; i++ ) for ( size_t i=0 ; i<routingPads.size() ; i++ ) {
propagateConstraintFromRp( routingPads[i] ); propagateConstraintFromRp( routingPads[i] );
propagateDistanceFromRp ( routingPads[i] );
}
for ( Segment* segment : net->getSegments() ) {
AutoSegment* autoSegment = Session::lookup( segment );
if (not autoSegment) continue;
if (autoSegment->isUnbreakable()) continue;
if (autoSegment->getRpDistance() >= 2) continue;
if (autoSegment->getRpDistance() == 1) continue;
vector<GCell*> gcells;
autoSegment->getGCells( gcells );
if (gcells.size() > 2) continue;
//if ( (gcells.size() == 2)
// and ( not autoSegment->getAutoSource()->isTerminal()
// or not autoSegment->getAutoTarget()->isTerminal()) ) continue;
autoSegment->setFlags( AutoSegment::SegUnbreakable );
}
// forEach ( Segment*, isegment, net->getSegments() ) { // forEach ( Segment*, isegment, net->getSegments() ) {
// AutoSegment* autoSegment = Session::lookup( *isegment ); // AutoSegment* autoSegment = Session::lookup( *isegment );
// if (autoSegment) autoSegment->toConstraintAxis(); // if (autoSegment) autoSegment->toConstraintAxis();
// } // }
cdebug_tabw(145,-1); cdebug_tabw(146,-1);
DebugSession::close(); DebugSession::close();
} }

View File

@ -2,7 +2,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved // Copyright (c) UPMC 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -61,7 +61,7 @@ namespace Anabatic {
void AnabaticEngine::toOptimals ( Net* net ) void AnabaticEngine::toOptimals ( Net* net )
{ {
DebugSession::open( net, 140, 150 ); DebugSession::open( net, 145, 150 );
cdebug_log(149,0) << "Anabatic::_toOptimals( " << net << " )" << endl; cdebug_log(149,0) << "Anabatic::_toOptimals( " << net << " )" << endl;
cdebug_tabw(145,1); cdebug_tabw(145,1);

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2014-2016, All Rights Reserved // Copyright (c) UPMC 2014-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -35,6 +35,7 @@ namespace Anabatic {
using Hurricane::RegularLayer; using Hurricane::RegularLayer;
using Hurricane::Component; using Hurricane::Component;
using Hurricane::Pin; using Hurricane::Pin;
using Hurricane::Plug;
using Hurricane::DeepNet; using Hurricane::DeepNet;
using Hurricane::Cell; using Hurricane::Cell;
using Hurricane::NetRoutingExtension; using Hurricane::NetRoutingExtension;
@ -66,64 +67,103 @@ namespace Anabatic {
void AnabaticEngine::setupPreRouteds () size_t AnabaticEngine::setupPreRouteds ()
{ {
cmess1 << " o Looking for fixed or manually global routed nets." << endl; cmess1 << " o Looking for fixed or manually global routed nets." << endl;
openSession(); openSession();
size_t toBeRouteds = 0;
Box ab = getCell()->getAbutmentBox();
ab.inflate( -1 );
for ( Net* net : getCell()->getNets() ) { for ( Net* net : getCell()->getNets() ) {
if (net == _blockageNet) continue; if (net == _blockageNet) continue;
if (net->getType() == Net::Type::POWER ) continue; if (net->getType() == Net::Type::POWER ) continue;
if (net->getType() == Net::Type::GROUND) continue; if (net->getType() == Net::Type::GROUND) continue;
// Don't skip the clock. // Don't skip the clock.
vector<Pin*> pins;
vector<Segment*> segments; vector<Segment*> segments;
vector<Contact*> contacts; vector<Contact*> contacts;
bool isPreRouted = false; bool isManualGlobalRouted = false;
bool isFixed = false; bool isManualDetailRouted = false;
size_t rpCount = 0; bool isFixed = false;
size_t rpCount = 0;
if (net->isDeepNet()) { for( Component* component : net->getComponents() ) {
rpCount = 2; Pin* pin = dynamic_cast<Pin *>( component );
if (pin) {
Net* rootNet = dynamic_cast<Net*>( pins.push_back( pin );
dynamic_cast<DeepNet*>(net)->getRootNetOccurrence().getEntity() ); continue;
for( Component* component : rootNet->getComponents() ) {
if (dynamic_cast<Horizontal*>(component)) { isFixed = true; break; }
if (dynamic_cast<Vertical*> (component)) { isFixed = true; break; }
if (dynamic_cast<Contact*> (component)) { isFixed = true; break; }
} }
} else { if (dynamic_cast<Plug*>(component)) continue;
for( Component* component : net->getComponents() ) {
if (dynamic_cast<Pin*>(component)) continue;
const RegularLayer* layer = dynamic_cast<const RegularLayer*>(component->getLayer()); const RegularLayer* layer = dynamic_cast<const RegularLayer*>(component->getLayer());
if (layer and (layer->getBasicLayer()->getMaterial() == BasicLayer::Material::blockage)) if (layer and (layer->getBasicLayer()->getMaterial() == BasicLayer::Material::blockage))
continue; continue;
Horizontal* horizontal = dynamic_cast<Horizontal*>(component); if ( not Session::isGaugeLayer(component->getLayer())
if (horizontal) { and not Session::isGLayer (component->getLayer())) {
segments.push_back( horizontal ); const BasicLayer* basicLayer = dynamic_cast<const BasicLayer*>( component->getLayer() );
isPreRouted = true; if (basicLayer and (basicLayer->getMaterial() == BasicLayer::Material::cut))
continue;
throw Error( "AnabaticEngine::setupPreRouted(): A component of \"%s\" has a routing gauge umanaged layer.\n"
" (%s)"
, getString(net->getName()).c_str()
, getString(component).c_str()
);
}
Horizontal* horizontal = dynamic_cast<Horizontal*>(component);
if (horizontal) {
if ( not ab.contains(horizontal->getSourcePosition())
and not ab.contains(horizontal->getTargetPosition()) ) continue;
segments.push_back( horizontal );
if (Session::isGLayer(component->getLayer())) {
isManualGlobalRouted = true;
} else {
isManualDetailRouted = true;
if (horizontal->getWidth() != Session::getWireWidth(horizontal->getLayer())) if (horizontal->getWidth() != Session::getWireWidth(horizontal->getLayer()))
isFixed = true; isFixed = true;
} else { }
Vertical* vertical = dynamic_cast<Vertical*>(component); } else {
if (vertical) { Vertical* vertical = dynamic_cast<Vertical*>(component);
isPreRouted = true; if (vertical) {
if ( not ab.contains(vertical->getSourcePosition())
and not ab.contains(vertical->getTargetPosition()) ) continue;
if (Session::isGLayer(component->getLayer())) {
isManualGlobalRouted = true;
} else {
isManualDetailRouted = true;
segments.push_back( vertical ); segments.push_back( vertical );
if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer())) if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer()))
isFixed = true; isFixed = true;
}
} else {
Pin* pin = dynamic_cast<Pin*>(component);
if (pin) {
//cerr << "| " << pin << endl;
if (not ab.intersect(pin->getBoundingBox())) continue;
pins.push_back( pin );
} else { } else {
Contact* contact = dynamic_cast<Contact*>(component); Contact* contact = dynamic_cast<Contact*>(component);
if (contact) { if (contact) {
isPreRouted = true; if (not ab.contains(contact->getCenter())) continue;
contacts.push_back( contact );
if ( (contact->getWidth () != Session::getViaWidth(contact->getLayer())) if (Session::isGLayer(component->getLayer())) {
or (contact->getHeight() != Session::getViaWidth(contact->getLayer())) ) isManualGlobalRouted = true;
isFixed = true; } else {
isManualGlobalRouted = true;
contacts.push_back( contact );
if ( (contact->getWidth () != Session::getViaWidth(contact->getLayer()))
or (contact->getHeight() != Session::getViaWidth(contact->getLayer()))
or (contact->getLayer () == Session::getContactLayer(0)) )
isFixed = true;
}
} else { } else {
RoutingPad* rp = dynamic_cast<RoutingPad*>(component); RoutingPad* rp = dynamic_cast<RoutingPad*>(component);
if (rp) { if (rp) {
@ -141,38 +181,75 @@ namespace Anabatic {
} }
} }
if (isFixed or isPreRouted or (rpCount < 2)) { // cerr << net << " deepNet:" << net->isDeepNet()
// << " pins:" << pins.size()
// << " segments:" << segments.size() << endl;
if (not net->isDeepNet() and (pins.size() >= 1) and (segments.size() < 2)) {
++toBeRouteds;
continue;
}
if ( (not isFixed)
and (not isManualGlobalRouted)
and (not isManualDetailRouted)
and net->isDeepNet()) {
Net* rootNet = dynamic_cast<Net*>(
dynamic_cast<DeepNet*>(net)->getRootNetOccurrence().getEntity() );
for( Component* component : rootNet->getComponents() ) {
if (dynamic_cast<Horizontal*>(component)) { isFixed = true; break; }
if (dynamic_cast<Vertical*> (component)) { isFixed = true; break; }
if (dynamic_cast<Contact*> (component)) { isFixed = true; break; }
}
}
if (isFixed or isManualDetailRouted or isManualGlobalRouted or (rpCount < 2)) {
NetData* ndata = getNetData( net, Flags::Create ); NetData* ndata = getNetData( net, Flags::Create );
NetRoutingState* state = ndata->getNetRoutingState(); NetRoutingState* state = ndata->getNetRoutingState();
state->unsetFlags( NetRoutingState::AutomaticGlobalRoute ); state->unsetFlags( NetRoutingState::AutomaticGlobalRoute );
state->setFlags ( NetRoutingState::ManualGlobalRoute ); if (isManualGlobalRouted) {
state->setFlags( NetRoutingState::ManualGlobalRoute );
ndata->setGlobalFixed( true );
}
if (isManualDetailRouted)
state->setFlags( NetRoutingState::ManualDetailRoute );
ndata->setGlobalRouted( true ); ndata->setGlobalRouted( true );
if (rpCount < 2) if (rpCount < 2)
state->setFlags ( NetRoutingState::Unconnected ); state->setFlags( NetRoutingState::Unconnected );
if (isFixed) { if (isFixed) {
cmess2 << " - <" << net->getName() << "> is fixed." << endl; if (rpCount > 1)
state->unsetFlags( NetRoutingState::ManualGlobalRoute ); cmess2 << " - <" << net->getName() << "> is fixed." << endl;
state->unsetFlags( NetRoutingState::ManualGlobalRoute|NetRoutingState::ManualDetailRoute );
state->setFlags ( NetRoutingState::Fixed ); state->setFlags ( NetRoutingState::Fixed );
} else { } else if (isManualGlobalRouted) {
cmess2 << " - <" << net->getName() << "> is manually global routed." << endl;
} else if (isManualDetailRouted) {
if (rpCount > 1) { if (rpCount > 1) {
cmess2 << " - <" << net->getName() << "> is manually global routed." << endl; ++toBeRouteds;
for ( auto icontact : contacts ) { cmess2 << " - <" << net->getName() << "> is manually detail routed." << endl;
AutoContact::createFrom( icontact ); for ( auto contact : contacts ) {
AutoContact::createFrom( contact );
} }
for ( auto segment : segments ) {
for ( auto isegment : segments ) { AutoContact* source = Session::lookup( dynamic_cast<Contact*>( segment->getSource() ));
AutoContact* source = Session::lookup( dynamic_cast<Contact*>( isegment->getSource() )); AutoContact* target = Session::lookup( dynamic_cast<Contact*>( segment->getTarget() ));
AutoContact* target = Session::lookup( dynamic_cast<Contact*>( isegment->getTarget() )); if (not source or not target) {
AutoSegment* autoSegment = AutoSegment::create( source, target, isegment ); cerr << Error( "Unable to protect %s", getString(segment).c_str() ) << endl;
continue;
}
AutoSegment* autoSegment = AutoSegment::create( source, target, segment );
autoSegment->setFlags( AutoSegment::SegUserDefined|AutoSegment::SegAxisSet ); autoSegment->setFlags( AutoSegment::SegUserDefined|AutoSegment::SegAxisSet );
} }
} }
} }
} else {
++toBeRouteds;
} }
} }
Session::close(); Session::close();
return toBeRouteds;
} }

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved // Copyright (c) UPMC 2016-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -16,7 +16,7 @@
#include "hurricane/isobar/PyHurricane.h" #include "hurricane/isobar/PyHurricane.h"
#include "hurricane/isobar/PyCell.h" #include "hurricane/isobar/PyCell.h"
#include "anabatic/Constants.h" #include "anabatic/PyStyleFlags.h"
namespace Anabatic { namespace Anabatic {
@ -55,27 +55,53 @@ extern "C" {
}; };
static PyModuleDef PyAnabatic_ModuleDef =
{ PyModuleDef_HEAD_INIT
, "Anabatic" /* m_name */
, "Low level database for global & detailed routing."
/* m_doc */
, -1 /* m_size */
, PyAnabatic_Methods /* m_methods */
, NULL /* m_reload */
, NULL /* m_traverse */
, NULL /* m_clear */
, NULL /* m_free */
};
// --------------------------------------------------------------- // ---------------------------------------------------------------
// Module Initialization : "initAnabatic ()" // Module Initialization : "initAnabatic ()"
DL_EXPORT(void) initAnabatic () { PyMODINIT_FUNC PyInit_Anabatic ( void )
cdebug_log(32,0) << "initAnabatic()" << endl; {
cdebug_log(32,0) << "PyInit_Anabatic()" << endl;
PyObject* module = Py_InitModule( "Anabatic", PyAnabatic_Methods ); PyStyleFlags_LinkPyType();
PYTYPE_READY( StyleFlags );
PyObject* module = PyModule_Create( &PyAnabatic_ModuleDef );
if (module == NULL) { if (module == NULL) {
cerr << "[ERROR]\n" cerr << "[ERROR]\n"
<< " Failed to initialize Anabatic module." << endl; << " Failed to initialize Anabatic module." << endl;
return; return NULL;
} }
Py_INCREF( &PyTypeStyleFlags );
PyModule_AddObject( module, "StyleFlags", (PyObject*)&PyTypeStyleFlags );
PyObject* dictionnary = PyModule_GetDict(module); PyObject* dictionnary = PyModule_GetDict(module);
PyObject* constant; PyObject* constant;
LoadObjectConstant( dictionnary,EngineLoadGrByNet ,"EngineLoadGrByNet" ); LoadObjectConstant( dictionnary,EngineLoadGrByNet ,"EngineLoadGrByNet" );
LoadObjectConstant( dictionnary,EngineLoadGrByGCell ,"EngineLoadGrByGCell" ); LoadObjectConstant( dictionnary,EngineLoadGrByGCell ,"EngineLoadGrByGCell" );
LoadObjectConstant( dictionnary,EngineLayerAssignByLength,"EngineLayerAssignByLength" ); LoadObjectConstant( dictionnary,EngineLayerAssignByLength ,"EngineLayerAssignByLength" );
LoadObjectConstant( dictionnary,EngineLayerAssignByTrunk ,"EngineLayerAssignByTrunk" ); LoadObjectConstant( dictionnary,EngineLayerAssignByTrunk ,"EngineLayerAssignByTrunk" );
LoadObjectConstant( dictionnary,EngineNoNetLayerAssign ,"EngineNoNetLayerAssign" ); LoadObjectConstant( dictionnary,EngineLayerAssignNoGlobalM2V,"EngineLayerAssignNoGlobalM2V" );
LoadObjectConstant( dictionnary,EngineNoNetLayerAssign ,"EngineNoNetLayerAssign" );
PyStyleFlags_postModuleInit();
return module;
} }

View File

@ -0,0 +1,123 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./PyStyleFlags.h" |
// +-----------------------------------------------------------------+
#include "anabatic/PyStyleFlags.h"
namespace Anabatic {
using std::cerr;
using std::endl;
using std::hex;
using std::ostringstream;
using Hurricane::tab;
using Hurricane::Error;
using Hurricane::Warning;
using Isobar::ProxyProperty;
using Isobar::ProxyError;
using Isobar::ConstructorError;
using Isobar::HurricaneError;
using Isobar::HurricaneWarning;
using Isobar::ParseOneArg;
using Isobar::ParseTwoArg;
using Isobar::getPyHash;
extern "C" {
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(StyleFlags,status,function)
// +=================================================================+
// | "PyStyleFlags" Python Module Code Part |
// +=================================================================+
#if defined(__PYTHON_MODULE__)
PyMethodDef PyStyleFlags_Methods[] =
{ {NULL, NULL, 0, NULL} /* sentinel */
};
PythonOnlyDeleteMethod(StyleFlags)
DirectReprMethod (PyStyleFlags_Repr, PyStyleFlags, StyleFlags)
DirectStrMethod (PyStyleFlags_Str, PyStyleFlags, StyleFlags)
DirectCmpByValueMethod(PyStyleFlags_Cmp, IsPyStyleFlags, PyStyleFlags)
DirectHashMethod (PyStyleFlags_Hash, StyleFlags)
extern void PyStyleFlags_LinkPyType() {
cdebug_log(20,0) << "PyStyleFlags_LinkType()" << endl;
PyTypeStyleFlags.tp_dealloc = (destructor) PyStyleFlags_DeAlloc;
PyTypeStyleFlags.tp_richcompare = (richcmpfunc)PyStyleFlags_Cmp;
PyTypeStyleFlags.tp_repr = (reprfunc) PyStyleFlags_Repr;
PyTypeStyleFlags.tp_str = (reprfunc) PyStyleFlags_Str;
PyTypeStyleFlags.tp_hash = (hashfunc) PyStyleFlags_Hash;
PyTypeStyleFlags.tp_methods = PyStyleFlags_Methods;
}
#else // End of Python Module Code Part.
// +=================================================================+
// | "PyStyleFlags" Shared Library Code Part |
// +=================================================================+
// Link/Creation Method.
PyTypeObjectDefinitions(StyleFlags)
extern void PyStyleFlags_postModuleInit ()
{
PyObject* constant = NULL;
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::NoStyle, "NoStyle" );
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::HV , "HV" );
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::VH , "VH" );
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::OTH , "OTH" );
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::Channel, "Channel" );
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::Hybrid , "Hybrid" );
}
#endif // Shared Library Code Part.
} // extern "C".
#if !defined(__PYTHON_MODULE__)
extern StyleFlags PyInt_AsStyleFlags ( PyObject* object )
{
uint64_t value = (uint64_t)Isobar::PyAny_AsLong( object );
if ( (value == (uint64_t)StyleFlags::NoStyle)
or (value == (uint64_t)StyleFlags::HV)
or (value == (uint64_t)StyleFlags::VH)
or (value == (uint64_t)StyleFlags::OTH)
or (value == (uint64_t)StyleFlags::Channel)
or (value == (uint64_t)StyleFlags::Hybrid))
return value;
return StyleFlags::NoStyle;
}
#endif
} // Isobar namespace.

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Session.cpp<anabatic>" -*- // -*- mode: C++; explicit-buffer-name: "Session.cpp<anabatic>" -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved // Copyright (c) UPMC 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -17,6 +17,7 @@
#include <cstdlib> #include <cstdlib>
#include <sstream> #include <sstream>
#include "hurricane/Error.h" #include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Horizontal.h" #include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h" #include "hurricane/Vertical.h"
#include "hurricane/Cell.h" #include "hurricane/Cell.h"
@ -47,6 +48,7 @@ namespace Anabatic {
using namespace std; using namespace std;
using Hurricane::tab; using Hurricane::tab;
using Hurricane::Error; using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::ForEachIterator; using Hurricane::ForEachIterator;
using Hurricane::UpdateSession; using Hurricane::UpdateSession;
using Hurricane::Horizontal; using Hurricane::Horizontal;
@ -80,7 +82,12 @@ namespace Anabatic {
, _segmentRevalidateds() , _segmentRevalidateds()
, _netInvalidateds () , _netInvalidateds ()
, _netRevalidateds () , _netRevalidateds ()
{ } {
_autoContacts .reserve( 1024 );
_doglegs .reserve( 1024 );
_segmentInvalidateds.reserve( 1024 );
_segmentRevalidateds.reserve( 1024 );
}
void Session::_postCreate () void Session::_postCreate ()
@ -158,6 +165,7 @@ namespace Anabatic {
canonical->setFlags( AutoSegment::SegCanonical ); canonical->setFlags( AutoSegment::SegCanonical );
cdebug_log(145,0) << "Canonical: " << canonical << endl; cdebug_log(145,0) << "Canonical: " << canonical << endl;
Interval userConstraints = canonical->getUserConstraints();
for ( size_t j=0 ; j<aligneds.size() ; j++ ) { for ( size_t j=0 ; j<aligneds.size() ; j++ ) {
if (isWeakGlobal and not aligneds[j]->isGlobal()) aligneds[j]->setFlags ( AutoSegment::SegWeakGlobal ); if (isWeakGlobal and not aligneds[j]->isGlobal()) aligneds[j]->setFlags ( AutoSegment::SegWeakGlobal );
@ -171,14 +179,29 @@ namespace Anabatic {
} }
aligneds[j]->unsetFlags( AutoSegment::SegCanonical ); aligneds[j]->unsetFlags( AutoSegment::SegCanonical );
cdebug_log(145,0) << "Secondary: " << aligneds[j] << endl; cdebug_log(145,0) << "Secondary: " << aligneds[j] << endl;
userConstraints.intersection( aligneds[j]->getUserConstraints() );
} }
if (aligneds.empty()) canonical->setFlags( AutoSegment::SegNotAligned ); if (aligneds.empty()) canonical->setFlags( AutoSegment::SegNotAligned );
if (not getRoutingGauge()->isSymbolic()
and (userConstraints.getSize() < Session::getPitch(1)*2) ) {
cerr << Warning( "Session::_canonize(): On %s\n"
" Combined user constraints are too tight [%s : %s]."
, getString(canonical).c_str()
, DbU::getValueString(userConstraints.getVMin()).c_str()
, DbU::getValueString(userConstraints.getVMax()).c_str()
) << endl;
}
cdebug_log(149,0) << "Align on canonical:" << canonical << endl; cdebug_log(149,0) << "Align on canonical:" << canonical << endl;
cdebug_log(145,0) << "Combined user constraints: " << userConstraints << endl;
//canonical->setAxis( canonical->getAxis(), Flags::Realignate ); //canonical->setAxis( canonical->getAxis(), Flags::Realignate );
if (canonical->isUnsetAxis()) canonical->toOptimalAxis( Flags::Realignate|Flags::Propagate ); if (canonical->isUnsetAxis() and not canonical->isFixed())
else canonical->setAxis( canonical->getAxis(), Flags::Realignate|Flags::Propagate ); canonical->toOptimalAxis( Flags::Realignate|Flags::Propagate );
else
canonical->setAxis( canonical->getAxis(), Flags::Realignate|Flags::Propagate );
aligneds.clear(); aligneds.clear();
cdebug_tabw(145,-1); cdebug_tabw(145,-1);
} }
@ -192,21 +215,23 @@ namespace Anabatic {
{ {
cdebug_log(145,1) << "Anabatic::Session::_revalidateTopology()" << endl; cdebug_log(145,1) << "Anabatic::Session::_revalidateTopology()" << endl;
set<Net*>::iterator inet = _netInvalidateds.begin(); _anabatic->disableCanonize();
for ( Net* net : _netInvalidateds ) {
for ( ; inet != _netInvalidateds.end() ; inet++ ) { cdebug_log(145,0) << "Anabatic::Session::_revalidateTopology(Net*)" << net << endl;
cdebug_log(145,0) << "Anabatic::Session::_revalidateTopology(Net*)" << *inet << endl; _anabatic->updateNetTopology ( net );
_anabatic->updateNetTopology ( *inet ); _anabatic->computeNetConstraints( net );
_anabatic->computeNetConstraints( *inet ); _anabatic->_computeNetOptimals ( net );
_anabatic->_computeNetOptimals ( *inet ); //_anabatic->_computeNetTerminals ( net );
_anabatic->_computeNetTerminals ( *inet );
} }
_anabatic->enableCanonize();
_canonize (); _canonize ();
AutoSegment* segment = NULL;
for ( size_t i=0 ; i<_segmentInvalidateds.size() ; ++i ) { for ( size_t i=0 ; i<_segmentInvalidateds.size() ; ++i ) {
if (_segmentInvalidateds[i]->isCanonical()) { segment = _segmentInvalidateds[i];
if (_segmentInvalidateds[i]->isUnsetAxis()) _segmentInvalidateds[i]->toOptimalAxis(); if (segment->isCanonical()) {
else _segmentInvalidateds[i]->toConstraintAxis(); if (segment->isUnsetAxis()) segment->toOptimalAxis();
else segment->toConstraintAxis();
} }
} }
@ -236,6 +261,8 @@ namespace Anabatic {
cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl; cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl;
_segmentRevalidateds.clear(); _segmentRevalidateds.clear();
std::sort( _segmentInvalidateds.begin(), _segmentInvalidateds.end()
, AutoSegment::CompareByRevalidate() );
for ( size_t i=0 ; i < _segmentInvalidateds.size() ; ++i, ++count ) { for ( size_t i=0 ; i < _segmentInvalidateds.size() ; ++i, ++count ) {
_segmentInvalidateds[i]->revalidate(); _segmentInvalidateds[i]->revalidate();
if ( not _destroyedSegments.empty() if ( not _destroyedSegments.empty()
@ -337,20 +364,46 @@ namespace Anabatic {
} }
DbU::Unit Session::_getNearestTrackAxis ( const Layer* layer, DbU::Unit axis, uint32_t mode )
{
Box ab = _anabatic->getCell()->getAbutmentBox();
RoutingLayerGauge* lg = _routingGauge->getLayerGauge( layer );
if (not lg) return axis;
DbU::Unit minAxis = 0;
DbU::Unit maxAxis = 0;
if (lg->getDirection() == Constant::Horizontal) {
minAxis = ab.getYMin();
maxAxis = ab.getYMax();
} else {
minAxis = ab.getXMin();
maxAxis = ab.getXMax();
}
DbU::Unit trackAxis = lg->getTrackPosition( minAxis
, lg->getTrackIndex( minAxis
, maxAxis
, axis
, mode ) );
return trackAxis;
}
Point Session::_getNearestGridPoint ( Point p, Box constraint ) Point Session::_getNearestGridPoint ( Point p, Box constraint )
{ {
Box ab = _anabatic->getCell()->getAbutmentBox(); Box ab = _anabatic->getCell()->getAbutmentBox();
RoutingLayerGauge* lg = _routingGauge->getLayerGauge( 1 ); RoutingLayerGauge* lg = _routingGauge->getVerticalGauge();
DbU::Unit x = lg->getTrackPosition( ab.getXMin() DbU::Unit x = lg->getTrackPosition( ab.getXMin()
, lg->getTrackIndex( ab.getXMin() , lg->getTrackIndex( ab.getXMin()
, ab.getXMax() , ab.getXMax()
, p.getX() , p.getX()
, Constant::Nearest ) ); , Constant::Nearest ) );
if (x < constraint.getXMin()) x += lg->getPitch(); if (x < constraint.getXMin()) x += lg->getPitch();
if (x > constraint.getXMax()) x -= lg->getPitch(); if (x > constraint.getXMax()) x -= lg->getPitch();
lg = _routingGauge->getLayerGauge( 2 ); lg = _routingGauge->getHorizontalGauge();
DbU::Unit y = lg->getTrackPosition( ab.getYMin() DbU::Unit y = lg->getTrackPosition( ab.getYMin()
, lg->getTrackIndex( ab.getYMin() , lg->getTrackIndex( ab.getYMin()
, ab.getYMax() , ab.getYMax()
@ -359,14 +412,25 @@ namespace Anabatic {
if (y < constraint.getYMin()) y += lg->getPitch(); if (y < constraint.getYMin()) y += lg->getPitch();
if (y > constraint.getYMax()) y -= lg->getPitch(); if (y > constraint.getYMax()) y -= lg->getPitch();
y = std::max( y, constraint.getYMin() );
y = std::min( y, constraint.getYMax() );
return Point(x,y); return Point(x,y);
} }
StyleFlags Session::getRoutingStyle ()
{ return get("getRoutingStyle()")->_anabatic->getRoutingStyle(); }
bool Session::isInDemoMode () bool Session::isInDemoMode ()
{ return get("isInDemoMode()")->_anabatic->isInDemoMode(); } { return get("isInDemoMode()")->_anabatic->isInDemoMode(); }
bool Session::isChannelStyle ()
{ return get("isChannelStyle()")->_anabatic->isChannelStyle(); }
float Session::getSaturateRatio () float Session::getSaturateRatio ()
{ return get("getSaturateRatio()")->_anabatic->getSaturateRatio(); } { return get("getSaturateRatio()")->_anabatic->getSaturateRatio(); }

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved // Copyright (c) UPMC 2016-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -14,20 +14,16 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_ANABATIC_ENGINE_H #pragma once
#define ANABATIC_ANABATIC_ENGINE_H
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include <set> #include <set>
#include "hurricane/NetRoutingProperty.h" #include "hurricane/NetRoutingProperty.h"
namespace Hurricane { namespace Hurricane {
class Instance; class Instance;
class CellViewer; class CellViewer;
} }
#include "crlcore/ToolEngine.h" #include "crlcore/ToolEngine.h"
#include "anabatic/Configuration.h" #include "anabatic/Configuration.h"
#include "anabatic/Matrix.h" #include "anabatic/Matrix.h"
@ -49,6 +45,7 @@ namespace Anabatic {
using Hurricane::NetRoutingState; using Hurricane::NetRoutingState;
using CRL::ToolEngine; using CRL::ToolEngine;
class NetBuilder;
class AnabaticEngine; class AnabaticEngine;
@ -68,6 +65,8 @@ namespace Anabatic {
}; };
public: public:
RawGCellsUnder ( const AnabaticEngine*, Segment* ); RawGCellsUnder ( const AnabaticEngine*, Segment* );
RawGCellsUnder ( const AnabaticEngine*, Point source, Point target );
void commonCtor ( const AnabaticEngine*, Point source, Point target );
inline bool empty () const; inline bool empty () const;
inline size_t size () const; inline size_t size () const;
inline GCell* gcellAt ( size_t ) const; inline GCell* gcellAt ( size_t ) const;
@ -102,46 +101,66 @@ namespace Anabatic {
class NetData { class NetData {
public: public:
NetData ( Net* ); NetData ( Net*, AnabaticEngine* );
inline bool isGlobalEstimated () const;
inline bool isGlobalRouted () const; inline bool isGlobalRouted () const;
inline bool isGlobalFixed () const;
inline bool isMixedPreRoute () const; inline bool isMixedPreRoute () const;
inline bool isFixed () const; inline bool isFixed () const;
inline bool isExcluded () const;
inline bool isNoMoveUp ( Segment* ) const;
inline Net* getNet () const; inline Net* getNet () const;
inline NetRoutingState* getNetRoutingState () const; inline NetRoutingState* getNetRoutingState () const;
inline const Box& getSearchArea () const; inline const Box& getSearchArea () const;
inline DbU::Unit getHalfPerimeter () const; inline DbU::Unit getHalfPerimeter () const;
inline size_t getRpCount () const; inline size_t getRpCount () const;
inline size_t getDiodeRpCount () const;
inline DbU::Unit getSparsity () const; inline DbU::Unit getSparsity () const;
inline void setNetRoutingState ( NetRoutingState* ); inline void setNetRoutingState ( NetRoutingState* );
inline void setSearchArea ( Box ); inline void setSearchArea ( Box );
inline void setGlobalEstimated ( bool );
inline void setGlobalRouted ( bool ); inline void setGlobalRouted ( bool );
inline void setGlobalFixed ( bool );
inline void setExcluded ( bool );
inline void setRpCount ( size_t ); inline void setRpCount ( size_t );
inline void setNoMoveUp ( Segment* );
private: private:
NetData ( const NetData& ); NetData ( const NetData& );
NetData& operator= ( const NetData& ); NetData& operator= ( const NetData& );
inline void _update (); inline void _update ();
private: private:
Net* _net; Net* _net;
NetRoutingState* _state; NetRoutingState* _state;
Box _searchArea; Box _searchArea;
size_t _rpCount; size_t _rpCount;
DbU::Unit _sparsity; size_t _diodeCount;
Flags _flags; DbU::Unit _sparsity;
Flags _flags;
std::set<Segment*,DBo::CompareById> _noMoveUp;
}; };
inline bool NetData::isGlobalEstimated () const { return _flags & Flags::GlobalEstimated; }
inline bool NetData::isGlobalRouted () const { return _flags & Flags::GlobalRouted; } inline bool NetData::isGlobalRouted () const { return _flags & Flags::GlobalRouted; }
inline bool NetData::isGlobalFixed () const { return _flags & Flags::GlobalFixed; }
inline bool NetData::isMixedPreRoute () const { return (_state) ? _state->isMixedPreRoute() : false; } inline bool NetData::isMixedPreRoute () const { return (_state) ? _state->isMixedPreRoute() : false; }
inline bool NetData::isFixed () const { return (_state) ? _state->isFixed () : false; } inline bool NetData::isFixed () const { return (_state) ? _state->isFixed () : false; }
inline bool NetData::isExcluded () const { return _flags & Flags::ExcludeRoute; }
inline bool NetData::isNoMoveUp ( Segment* segment ) const { return (_noMoveUp.find(segment) != _noMoveUp.end()); }
inline Net* NetData::getNet () const { return _net; } inline Net* NetData::getNet () const { return _net; }
inline NetRoutingState* NetData::getNetRoutingState () const { return _state; } inline NetRoutingState* NetData::getNetRoutingState () const { return _state; }
inline const Box& NetData::getSearchArea () const { return _searchArea; } inline const Box& NetData::getSearchArea () const { return _searchArea; }
inline DbU::Unit NetData::getHalfPerimeter () const { return (_searchArea.isEmpty()) ? 0.0 : (_searchArea.getWidth()+_searchArea.getHeight()); } inline DbU::Unit NetData::getHalfPerimeter () const { return (_searchArea.isEmpty()) ? 0.0 : (_searchArea.getWidth()+_searchArea.getHeight()); }
inline size_t NetData::getRpCount () const { return _rpCount; } inline size_t NetData::getRpCount () const { return _rpCount; }
inline size_t NetData::getDiodeRpCount () const { return _diodeCount; }
inline void NetData::setNetRoutingState ( NetRoutingState* state ) { _state=state; } inline void NetData::setNetRoutingState ( NetRoutingState* state ) { _state=state; }
inline DbU::Unit NetData::getSparsity () const { return _sparsity; } inline DbU::Unit NetData::getSparsity () const { return _sparsity; }
inline void NetData::setGlobalRouted ( bool state ) { _flags.set(Flags::GlobalRouted,state); } inline void NetData::setGlobalEstimated ( bool state ) { _flags.set(Flags::GlobalEstimated,state); }
inline void NetData::setGlobalRouted ( bool state ) { _flags.set(Flags::GlobalRouted ,state); }
inline void NetData::setGlobalFixed ( bool state ) { _flags.set(Flags::GlobalFixed ,state); }
inline void NetData::setExcluded ( bool state ) { _flags.set(Flags::ExcludeRoute ,state); }
inline void NetData::setRpCount ( size_t count ) { _rpCount=count; _update(); } inline void NetData::setRpCount ( size_t count ) { _rpCount=count; _update(); }
inline void NetData::setNoMoveUp ( Segment* segment ) { _noMoveUp.insert(segment); }
inline void NetData::_update () inline void NetData::_update ()
@ -153,7 +172,12 @@ namespace Anabatic {
inline bool operator() ( const NetData* lhs, const NetData* rhs ) const inline bool operator() ( const NetData* lhs, const NetData* rhs ) const
{ {
if (lhs->isMixedPreRoute() != rhs->isMixedPreRoute()) return lhs->isMixedPreRoute(); if (lhs->isMixedPreRoute() != rhs->isMixedPreRoute()) return lhs->isMixedPreRoute();
if (lhs->getSparsity() != rhs->getSparsity() ) return lhs->getSparsity() < rhs->getSparsity(); if ((lhs->getRpCount() > 10) or (rhs->getRpCount() > 10)) {
if (lhs->getRpCount() != rhs->getRpCount())
return lhs->getRpCount() > rhs->getRpCount();
}
if (lhs->getSparsity() != rhs->getSparsity()) return lhs->getSparsity() < rhs->getSparsity();
return lhs->getNet()->getId() < rhs->getNet()->getId(); return lhs->getNet()->getId() < rhs->getNet()->getId();
} }
}; };
@ -168,185 +192,245 @@ namespace Anabatic {
class AnabaticEngine : public ToolEngine { class AnabaticEngine : public ToolEngine {
public: public:
enum DensityMode { AverageHVDensity=1 // Average between all densities. static const uint32_t DigitalMode = (1 << 0);
, AverageHDensity =2 // Average between all H densities. static const uint32_t AnalogMode = (1 << 1);
, AverageVDensity =3 // Average between all V densities. static const uint32_t MixedMode = (1 << 2);
, MaxHVDensity =4 // Maximum between average H and average V. static const uint32_t AverageHVDensity = 1; // Average between all densities.
, MaxVDensity =5 // Maximum of V densities. static const uint32_t AverageHDensity = 2; // Average between all H densities.
, MaxHDensity =6 // Maximum of H densities. static const uint32_t AverageVDensity = 3; // Average between all V densities.
, MaxDensity =7 // Maximum of H & V densities. static const uint32_t MaxHVDensity = 4; // Maximum between average H and average V.
}; static const uint32_t MaxVDensity = 5; // Maximum of V densities.
static const uint32_t MaxHDensity = 6; // Maximum of H densities.
static const uint32_t MaxDensity = 7; // Maximum of H & V densities.
public: public:
typedef ToolEngine Super; typedef ToolEngine Super;
public: public:
static AnabaticEngine* create ( Cell* ); static AnabaticEngine* create ( Cell* );
static AnabaticEngine* get ( const Cell* ); static AnabaticEngine* get ( const Cell* );
static const Name& staticGetName (); inline bool isCanonizeDisabled () const;
virtual const Name& getName () const; inline bool isDigitalMode () const;
virtual Configuration* getConfiguration (); inline bool isAnalogMode () const;
inline uint64_t getDensityMode () const; inline bool isMixedMode () const;
inline CellViewer* getViewer () const; inline bool isChannelStyle () const;
inline void setViewer ( CellViewer* ); inline bool isHybridStyle () const;
inline EngineState getState () const; static const Name& staticGetName ();
inline const Matrix* getMatrix () const; virtual const Name& getName () const;
inline const vector<GCell*>& getGCells () const; virtual Configuration* getConfiguration ();
inline const vector<Edge*>& getOvEdges () const; virtual const Configuration* getConfiguration () const;
inline GCell* getSouthWestGCell () const; inline std::string getNetBuilderStyle () const;
inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const; inline StyleFlags getRoutingStyle () const;
inline GCell* getGCellUnder ( Point ) const; inline uint64_t getDensityMode () const;
inline GCellsUnder getGCellsUnder ( Segment* ) const; inline CellViewer* getViewer () const;
Interval getUSide ( Flags direction ) const; inline void setViewer ( CellViewer* );
int getCapacity ( Interval, Flags ) const; inline EngineState getState () const;
size_t getNetsFromEdge ( const Edge*, NetSet& ); inline const Matrix* getMatrix () const;
virtual void openSession (); inline const vector<GCell*>& getGCells () const;
inline void setState ( EngineState state ); inline const vector<Edge*>& getOvEdges () const;
inline void setDensityMode ( uint64_t ); inline GCell* getSouthWestGCell () const;
inline void addOv ( Edge* ); inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const;
inline void removeOv ( Edge* ); inline GCell* getGCellUnder ( Point ) const;
inline const NetDatas& getNetDatas () const; inline GCellsUnder getGCellsUnder ( Segment* ) const;
NetData* getNetData ( Net*, Flags flags=Flags::NoFlags ); inline GCellsUnder getGCellsUnder ( Point source, Point target ) const;
void setupNetDatas (); inline Edges getEdgesUnderPath ( GCell* source, GCell* target, Flags pathFlags=Flags::NorthPath ) const;
void updateMatrix (); Interval getUSide ( Flags direction ) const;
int getCapacity ( Interval, Flags ) const;
size_t getNetsFromEdge ( const Edge*, NetSet& );
virtual void openSession ();
inline void setState ( EngineState state );
inline void setDensityMode ( uint64_t );
inline void disableCanonize ();
inline void enableCanonize ();
inline void addOv ( Edge* );
inline void removeOv ( Edge* );
inline const NetDatas& getNetDatas () const;
NetData* getNetData ( Net*, Flags flags=Flags::NoFlags );
void setupNetDatas ();
void exclude ( const Name& netName );
void exclude ( Net* );
void updateMatrix ();
bool checkPlacement () const;
// Dijkstra related functions. // Dijkstra related functions.
inline int getStamp () const; inline int getStamp () const;
inline int incStamp (); inline int incStamp ();
Contact* breakAt ( Segment*, GCell* ); Contact* breakAt ( Segment*, GCell* );
void ripup ( Segment*, Flags ); void ripup ( Segment*, Flags );
bool unify ( Contact* ); bool unify ( Contact* );
// Global routing related functions. // Global routing related functions.
void globalRoute (); void globalRoute ();
void cleanupGlobal (); void cleanupGlobal ();
void relaxOverConstraineds ();
// Detailed routing related functions. // Detailed routing related functions.
inline bool isInDemoMode () const; inline bool isInDemoMode () const;
inline bool isChip () const; inline bool isChip () const;
inline bool doWarnOnGCellOverload () const; inline bool doWarnOnGCellOverload () const;
inline bool doDestroyBaseContact () const; inline bool doDestroyBaseContact () const;
inline bool doDestroyBaseSegment () const; inline bool doDestroyBaseSegment () const;
inline bool doDestroyTool () const; inline bool doDestroyTool () const;
inline DbU::Unit getGlobalThreshold () const; inline DbU::Unit getAntennaGateMaxWL () const;
inline float getSaturateRatio () const; inline DbU::Unit getAntennaDiodeMaxWL () const;
inline size_t getSaturateRp () const; inline DbU::Unit getGlobalThreshold () const;
inline DbU::Unit getExtensionCap () const; inline float getSaturateRatio () const;
inline Net* getBlockageNet () const; inline size_t getSaturateRp () const;
inline const ChipTools& getChipTools () const; inline DbU::Unit getExtensionCap () const;
inline const vector<NetData*>& getNetOrdering () const; inline Cell* getDiodeCell () const;
void updateDensity (); inline Net* getBlockageNet () const;
size_t checkGCellDensities (); inline const ChipTools& getChipTools () const;
inline void setGlobalThreshold ( DbU::Unit ); inline const vector<NetData*>& getNetOrdering () const;
inline void setSaturateRatio ( float ); void invalidateRoutingPads ();
inline void setSaturateRp ( size_t ); void updateDensity ();
inline void setBlockageNet ( Net* ); size_t checkGCellDensities ();
void chipPrep (); void setupNetBuilder ();
void setupSpecialNets (); inline void setRoutingMode ( uint32_t );
void setupPreRouteds (); inline void resetRoutingMode ( uint32_t );
void loadGlobalRouting ( uint32_t method ); inline void setGlobalThreshold ( DbU::Unit );
void computeNetConstraints ( Net* ); inline void setSaturateRatio ( float );
void toOptimals ( Net* ); inline void setSaturateRp ( size_t );
void updateNetTopology ( Net* ); inline void setBlockageNet ( Net* );
bool moveUpNetTrunk ( AutoSegment*, set<Net*>& globalNets, GCell::Set& invalidateds ); void chipPrep ();
void layerAssign ( uint32_t method ); void computeEdgeCapacities ( int maxHCap, int maxVCap, int termSatThreshold, int maxTermSat );
void finalizeLayout (); void antennaProtect ( Net*, uint32_t& failed, uint32_t& total );
inline const AutoContactLut& _getAutoContactLut () const; void antennaProtect ();
inline const AutoSegmentLut& _getAutoSegmentLut () const; void setupSpecialNets ();
void _link ( AutoContact* ); size_t setupPreRouteds ();
void _link ( AutoSegment* ); void loadGlobalRouting ( uint32_t method );
void _unlink ( AutoContact* ); void computeNetConstraints ( Net* );
void _unlink ( AutoSegment* ); void toOptimals ( Net* );
AutoContact* _lookup ( Contact* ) const; void updateNetTopology ( Net* );
AutoSegment* _lookup ( Segment* ) const; bool moveUpNetTrunk ( AutoSegment*, set<Net*>& globalNets, GCell::Set& invalidateds );
void _loadGrByNet (); void layerAssign ( uint32_t method );
void _loadNetGlobalRouting ( Net* ); void finalizeLayout ();
void _computeNetOptimals ( Net* ); void exportExternalNets ();
void _computeNetTerminals ( Net* ); inline const AutoContactLut& _getAutoContactLut () const;
void _alignate ( Net* ); inline const AutoSegmentLut& _getAutoSegmentLut () const;
void _desaturate ( unsigned int depth, set<Net*>&, unsigned long& total, unsigned long& globals ); void _link ( AutoContact* );
void _layerAssignByLength ( unsigned long& total, unsigned long& global, set<Net*>& ); void _link ( AutoSegment* );
void _layerAssignByLength ( Net*, unsigned long& total, unsigned long& global, set<Net*>& ); void _unlink ( AutoContact* );
void _layerAssignByTrunk ( unsigned long& total, unsigned long& global, set<Net*>& ); void _unlink ( AutoSegment* );
void _layerAssignByTrunk ( Net*, set<Net*>&, unsigned long& total, unsigned long& global ); AutoContact* _lookup ( Contact* ) const;
void _saveNet ( Net* ); AutoSegment* _lookup ( Segment* ) const;
void _destroyAutoContacts (); EdgeCapacity* _createCapacity ( Flags, Interval );
void _destroyAutoSegments (); size_t _unrefCapacity ( EdgeCapacity* );
void _check ( Net* net ) const; void _loadGrByNet ();
bool _check ( const char* message ) const; void _computeNetOptimals ( Net* );
void printMeasures ( const string& tag ) const; void _computeNetTerminals ( Net* );
void _alignate ( Net* );
void _desaturate ( unsigned int depth, set<Net*>&, unsigned long& total, unsigned long& globals );
void _layerAssignByLength ( unsigned long& total, unsigned long& global, set<Net*>& );
void _layerAssignByLength ( Net*, unsigned long& total, unsigned long& global, set<Net*>& );
void _layerAssignByTrunk ( unsigned long& total, unsigned long& global, set<Net*>& );
void _layerAssignByTrunk ( Net*, set<Net*>&, unsigned long& total, unsigned long& global );
void _layerAssignNoGlobalM2V ( unsigned long& total, unsigned long& global, set<Net*>& );
void _layerAssignNoGlobalM2V ( Net*, set<Net*>&, unsigned long& total, unsigned long& global );
void _saveNet ( Net* );
void _destroyAutoContacts ();
void _destroyAutoSegments ();
void _check ( Net* net ) const;
bool _check ( const char* message ) const;
void printMeasures ( const string& tag ) const;
// Misc. functions. // Misc. functions.
inline const Flags& flags () const; inline const Flags& flags () const;
inline Flags& flags (); inline Flags& flags ();
void reset (); void reset ();
inline void _add ( GCell* ); inline void _add ( GCell* );
inline void _remove ( GCell* ); inline void _remove ( GCell* );
inline void _updateLookup ( GCell* ); inline void _updateLookup ( GCell* );
inline bool _inDestroy () const; inline void _updateGContacts ( Flags flags=Flags::Horizontal|Flags::Vertical );
inline void _resizeMatrix ();
inline bool _inDestroy () const;
// Inspector support. // Inspector support.
virtual Record* _getRecord () const; virtual Record* _getRecord () const;
virtual string _getString () const; virtual string _getString () const;
virtual string _getTypeName () const; virtual string _getTypeName () const;
protected: protected:
AnabaticEngine ( Cell* ); AnabaticEngine ( Cell* );
virtual ~AnabaticEngine (); virtual ~AnabaticEngine ();
virtual void _postCreate (); virtual void _postCreate ();
virtual void _preDestroy (); virtual void _preDestroy ();
void _gutAnabatic (); void _gutAnabatic ();
virtual Configuration* _createConfiguration ();
private: private:
AnabaticEngine ( const AnabaticEngine& ); AnabaticEngine ( const AnabaticEngine& );
AnabaticEngine& operator= ( const AnabaticEngine& ); AnabaticEngine& operator= ( const AnabaticEngine& );
private: private:
static Name _toolName; static Name _toolName;
Configuration* _configuration; protected:
ChipTools _chipTools; Configuration* _configuration;
EngineState _state; private:
Matrix _matrix; ChipTools _chipTools;
vector<GCell*> _gcells; EngineState _state;
vector<Edge*> _ovEdges; Matrix _matrix;
vector<NetData*> _netOrdering; vector<GCell*> _gcells;
NetDatas _netDatas; vector<Edge*> _ovEdges;
CellViewer* _viewer; vector<NetData*> _netOrdering;
Flags _flags; NetDatas _netDatas;
int _stamp; CellViewer* _viewer;
uint64_t _densityMode; Flags _flags;
AutoSegmentLut _autoSegmentLut; int _stamp;
AutoContactLut _autoContactLut; uint32_t _routingMode;
Net* _blockageNet; uint64_t _densityMode;
AutoSegmentLut _autoSegmentLut;
AutoContactLut _autoContactLut;
EdgeCapacityLut _edgeCapacitiesLut;
Net* _blockageNet;
Cell* _diodeCell;
}; };
inline EngineState AnabaticEngine::getState () const { return _state; } inline bool AnabaticEngine::isDigitalMode () const { return (_routingMode & DigitalMode); };
inline void AnabaticEngine::setState ( EngineState state ) { _state = state; } inline bool AnabaticEngine::isAnalogMode () const { return (_routingMode & AnalogMode); };
inline CellViewer* AnabaticEngine::getViewer () const { return _viewer; } inline bool AnabaticEngine::isMixedMode () const { return (_routingMode & MixedMode); };
inline void AnabaticEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; } inline bool AnabaticEngine::isChannelStyle () const { return (_configuration->getRoutingStyle() & StyleFlags::Channel); };
inline const Matrix* AnabaticEngine::getMatrix () const { return &_matrix; } inline bool AnabaticEngine::isHybridStyle () const { return (_configuration->getRoutingStyle() & StyleFlags::Hybrid); };
inline const vector<GCell*>& AnabaticEngine::getGCells () const { return _gcells; } inline void AnabaticEngine::setRoutingMode ( uint32_t mode ) { _routingMode |= mode; };
inline const vector<Edge*>& AnabaticEngine::getOvEdges () const { return _ovEdges; } inline void AnabaticEngine::resetRoutingMode ( uint32_t mode ) { _routingMode &= ~mode; };
inline GCell* AnabaticEngine::getSouthWestGCell () const { return _gcells[0]; } inline EngineState AnabaticEngine::getState () const { return _state; }
inline GCell* AnabaticEngine::getGCellUnder ( DbU::Unit x, DbU::Unit y ) const { return _matrix.getUnder(x,y); } inline void AnabaticEngine::setState ( EngineState state ) { _state = state; }
inline GCell* AnabaticEngine::getGCellUnder ( Point p ) const { return _matrix.getUnder(p); } inline CellViewer* AnabaticEngine::getViewer () const { return _viewer; }
inline GCellsUnder AnabaticEngine::getGCellsUnder ( Segment* s ) const { return std::shared_ptr<RawGCellsUnder>( new RawGCellsUnder(this,s) ); } inline void AnabaticEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; }
inline uint64_t AnabaticEngine::getDensityMode () const { return _densityMode; } inline const Matrix* AnabaticEngine::getMatrix () const { return &_matrix; }
inline void AnabaticEngine::setDensityMode ( uint64_t mode ) { _densityMode=mode; } inline const vector<GCell*>& AnabaticEngine::getGCells () const { return _gcells; }
inline void AnabaticEngine::setBlockageNet ( Net* net ) { _blockageNet = net; } inline const vector<Edge*>& AnabaticEngine::getOvEdges () const { return _ovEdges; }
inline const AutoContactLut& AnabaticEngine::_getAutoContactLut () const { return _autoContactLut; } inline GCell* AnabaticEngine::getSouthWestGCell () const { return _gcells[0]; }
inline const AutoSegmentLut& AnabaticEngine::_getAutoSegmentLut () const { return _autoSegmentLut; } inline GCell* AnabaticEngine::getGCellUnder ( DbU::Unit x, DbU::Unit y ) const { return _matrix.getUnder(x,y); }
inline const Flags& AnabaticEngine::flags () const { return _flags; } inline GCell* AnabaticEngine::getGCellUnder ( Point p ) const { return _matrix.getUnder(p); }
inline Flags& AnabaticEngine::flags () { return _flags; } inline GCellsUnder AnabaticEngine::getGCellsUnder ( Segment* s ) const { return std::shared_ptr<RawGCellsUnder>( new RawGCellsUnder(this,s) ); }
inline bool AnabaticEngine::doDestroyBaseContact () const { return _flags & Flags::DestroyBaseContact; } inline GCellsUnder AnabaticEngine::getGCellsUnder ( Point source, Point target ) const { return std::shared_ptr<RawGCellsUnder>( new RawGCellsUnder(this,source,target) ); }
inline bool AnabaticEngine::doDestroyBaseSegment () const { return _flags & Flags::DestroyBaseSegment; } inline Edges AnabaticEngine::getEdgesUnderPath ( GCell* source, GCell* target, Flags pathFlags ) const { return new Path_Edges(source,target,pathFlags); }
inline bool AnabaticEngine::doDestroyTool () const { return _state >= EngineGutted; } inline uint64_t AnabaticEngine::getDensityMode () const { return _densityMode; }
inline bool AnabaticEngine::doWarnOnGCellOverload () const { return _flags & Flags::WarnOnGCellOverload; } inline void AnabaticEngine::setDensityMode ( uint64_t mode ) { _densityMode=mode; }
inline bool AnabaticEngine::isInDemoMode () const { return _flags & Flags::DemoMode; } inline void AnabaticEngine::setBlockageNet ( Net* net ) { _blockageNet = net; }
inline bool AnabaticEngine::isChip () const { return _chipTools.isChip(); } inline const AutoContactLut& AnabaticEngine::_getAutoContactLut () const { return _autoContactLut; }
inline DbU::Unit AnabaticEngine::getGlobalThreshold () const { return _configuration->getGlobalThreshold(); } inline const AutoSegmentLut& AnabaticEngine::_getAutoSegmentLut () const { return _autoSegmentLut; }
inline float AnabaticEngine::getSaturateRatio () const { return _configuration->getSaturateRatio(); } inline const Flags& AnabaticEngine::flags () const { return _flags; }
inline size_t AnabaticEngine::getSaturateRp () const { return _configuration->getSaturateRp(); } inline Flags& AnabaticEngine::flags () { return _flags; }
inline void AnabaticEngine::setSaturateRatio ( float ratio ) { _configuration->setSaturateRatio(ratio); } inline bool AnabaticEngine::doDestroyBaseContact () const { return _flags & Flags::DestroyBaseContact; }
inline void AnabaticEngine::setSaturateRp ( size_t threshold ) { _configuration->setSaturateRp(threshold); } inline bool AnabaticEngine::doDestroyBaseSegment () const { return _flags & Flags::DestroyBaseSegment; }
inline Net* AnabaticEngine::getBlockageNet () const { return _blockageNet; } inline bool AnabaticEngine::doDestroyTool () const { return _state >= EngineGutted; }
inline const ChipTools& AnabaticEngine::getChipTools () const { return _chipTools; } inline bool AnabaticEngine::doWarnOnGCellOverload () const { return _flags & Flags::WarnOnGCellOverload; }
inline const vector<NetData*>& AnabaticEngine::getNetOrdering () const { return _netOrdering; } inline bool AnabaticEngine::isCanonizeDisabled () const { return _flags & Flags::DisableCanonize; }
inline void AnabaticEngine::setGlobalThreshold ( DbU::Unit threshold ) { _configuration->setGlobalThreshold(threshold); } inline bool AnabaticEngine::isInDemoMode () const { return _flags & Flags::DemoMode; }
inline const NetDatas& AnabaticEngine::getNetDatas () const { return _netDatas; } inline bool AnabaticEngine::isChip () const { return _chipTools.isChip(); }
inline void AnabaticEngine::_updateLookup ( GCell* gcell ) { _matrix.updateLookup(gcell); } inline std::string AnabaticEngine::getNetBuilderStyle () const { return _configuration->getNetBuilderStyle(); }
inline bool AnabaticEngine::_inDestroy () const { return _flags & Flags::DestroyMask; } inline StyleFlags AnabaticEngine::getRoutingStyle () const { return _configuration->getRoutingStyle(); }
inline DbU::Unit AnabaticEngine::getAntennaGateMaxWL () const { return _configuration->getAntennaGateMaxWL(); }
inline DbU::Unit AnabaticEngine::getAntennaDiodeMaxWL () const { return _configuration->getAntennaDiodeMaxWL(); }
inline DbU::Unit AnabaticEngine::getGlobalThreshold () const { return _configuration->getGlobalThreshold(); }
inline float AnabaticEngine::getSaturateRatio () const { return _configuration->getSaturateRatio(); }
inline size_t AnabaticEngine::getSaturateRp () const { return _configuration->getSaturateRp(); }
inline void AnabaticEngine::setSaturateRatio ( float ratio ) { _configuration->setSaturateRatio(ratio); }
inline void AnabaticEngine::setSaturateRp ( size_t threshold ) { _configuration->setSaturateRp(threshold); }
inline Cell* AnabaticEngine::getDiodeCell () const { return _diodeCell; }
inline Net* AnabaticEngine::getBlockageNet () const { return _blockageNet; }
inline const ChipTools& AnabaticEngine::getChipTools () const { return _chipTools; }
inline const vector<NetData*>& AnabaticEngine::getNetOrdering () const { return _netOrdering; }
inline void AnabaticEngine::setGlobalThreshold ( DbU::Unit threshold ) { _configuration->setGlobalThreshold(threshold); }
inline const NetDatas& AnabaticEngine::getNetDatas () const { return _netDatas; }
inline void AnabaticEngine::_updateLookup ( GCell* gcell ) { _matrix.updateLookup(gcell); }
inline void AnabaticEngine::_resizeMatrix () { _matrix.resize( getCell(), getGCells() ); }
inline void AnabaticEngine::_updateGContacts ( Flags flags ) { for ( GCell* gcell : getGCells() ) gcell->updateGContacts(flags); }
inline bool AnabaticEngine::_inDestroy () const { return _flags & Flags::DestroyMask; }
inline void AnabaticEngine::disableCanonize () { _flags |= Flags::DisableCanonize; }
inline void AnabaticEngine::enableCanonize () { _flags.reset( Flags::DisableCanonize ); }
inline void AnabaticEngine::_add ( GCell* gcell ) inline void AnabaticEngine::_add ( GCell* gcell )
{ {
@ -367,12 +451,15 @@ namespace Anabatic {
inline int AnabaticEngine::getStamp () const { return _stamp; } inline int AnabaticEngine::getStamp () const { return _stamp; }
inline int AnabaticEngine::incStamp () { return ++_stamp; } inline int AnabaticEngine::incStamp () { return ++_stamp; }
inline void AnabaticEngine::addOv ( Edge* edge ) { _ovEdges.push_back(edge); } inline void AnabaticEngine::addOv ( Edge* edge ) {
_ovEdges.push_back(edge);
}
inline void AnabaticEngine::removeOv ( Edge* edge ) inline void AnabaticEngine::removeOv ( Edge* edge )
{ {
for ( auto iedge = _ovEdges.begin() ; iedge != _ovEdges.end() ; ++iedge ) for ( auto iedge = _ovEdges.begin() ; iedge != _ovEdges.end() ; ++iedge ) {
if (*iedge == edge) { _ovEdges.erase(iedge); break; } if (*iedge == edge) { _ovEdges.erase(iedge); return; }
}
} }
@ -382,5 +469,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::AnabaticEngine); INSPECTOR_P_SUPPORT(Anabatic::AnabaticEngine);
#endif // ANABATIC_ANABATIC_ENGINE_H

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved // Copyright (c) UPMC 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -35,6 +35,7 @@ namespace Anabatic {
using Hurricane::setInBound; using Hurricane::setInBound;
using Hurricane::tab; using Hurricane::tab;
using Hurricane::Name; using Hurricane::Name;
using Hurricane::Entity;
using Hurricane::Net; using Hurricane::Net;
using Hurricane::Component; using Hurricane::Component;
using Hurricane::Components; using Hurricane::Components;
@ -48,7 +49,7 @@ namespace Anabatic {
class AutoContact; class AutoContact;
typedef std::map<Contact*,AutoContact*> AutoContactLut; typedef std::map<Contact*,AutoContact*,Entity::CompareById> AutoContactLut;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -67,6 +68,11 @@ namespace Anabatic {
, CntIgnoreAnchor = (1 << 11) , CntIgnoreAnchor = (1 << 11)
, CntWeakTerminal = (1 << 12) , CntWeakTerminal = (1 << 12)
, CntUserNativeConstraints = (1 << 13) , CntUserNativeConstraints = (1 << 13)
, CntOnVertical = (1 << 14)
, CntOnHorizontal = (1 << 15)
, CntDrag = (1 << 16)
, CntHDogleg = (1 << 17)
, CntVDogleg = (1 << 18)
}; };
class AutoContact { class AutoContact {
@ -97,7 +103,7 @@ namespace Anabatic {
inline void setSizes ( DbU::Unit width, DbU::Unit height ); inline void setSizes ( DbU::Unit width, DbU::Unit height );
inline void setX ( DbU::Unit ); inline void setX ( DbU::Unit );
inline void setY ( DbU::Unit ); inline void setY ( DbU::Unit );
inline void setPosition ( DbU::Unit width, DbU::Unit height ); inline void setPosition ( DbU::Unit x, DbU::Unit y );
inline void setPosition ( const Point& ); inline void setPosition ( const Point& );
inline void setDx ( DbU::Unit ); inline void setDx ( DbU::Unit );
inline void setDy ( DbU::Unit ); inline void setDy ( DbU::Unit );
@ -115,15 +121,20 @@ namespace Anabatic {
inline bool isVTee () const; inline bool isVTee () const;
inline bool isFixed () const; inline bool isFixed () const;
inline bool isUserNativeConstraints () const; inline bool isUserNativeConstraints () const;
inline bool isHDogleg () const;
inline bool isVDogleg () const;
virtual bool isOnPin () const;
inline bool hasBadTopology () const; inline bool hasBadTopology () const;
bool canDestroy ( Flags flags=Flags::NoFlags ) const; bool canDestroy ( Flags flags=Flags::NoFlags ) const;
bool canMoveUp ( const AutoSegment* moved ) const; bool canMoveUp ( const AutoSegment* moved ) const;
inline bool canDrag () const;
// Accessors. // Accessors.
inline Contact* base () const; inline Contact* base () const;
static size_t getAllocateds (); static size_t getAllocateds ();
static const Name& getStaticName (); static const Name& getStaticName ();
virtual const Name& getName () const; virtual const Name& getName () const;
inline size_t getId () const; inline size_t getId () const;
inline Flags getFlags () const;
virtual Box getBoundingBox () const; virtual Box getBoundingBox () const;
inline GCell* getGCell () const; inline GCell* getGCell () const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const = 0; virtual AutoSegment* getOpposite ( const AutoSegment* ) const = 0;
@ -153,6 +164,7 @@ namespace Anabatic {
virtual void cacheDetach ( AutoSegment* ) = 0; virtual void cacheDetach ( AutoSegment* ) = 0;
virtual void cacheAttach ( AutoSegment* ) = 0; virtual void cacheAttach ( AutoSegment* ) = 0;
virtual void updateCache () = 0; virtual void updateCache () = 0;
void updateLayer ();
void updateSize (); void updateSize ();
virtual void updateGeometry () = 0; virtual void updateGeometry () = 0;
virtual void updateTopology () = 0; virtual void updateTopology () = 0;
@ -172,6 +184,7 @@ namespace Anabatic {
, Flags flags=Flags::WarnOnError ); , Flags flags=Flags::WarnOnError );
void restoreNativeConstraintBox (); void restoreNativeConstraintBox ();
void migrateConstraintBox ( AutoContact* other ); void migrateConstraintBox ( AutoContact* other );
void setLayerAndWidth ( size_t delta, size_t depth );
void destroy (); void destroy ();
// Inspector Management. // Inspector Management.
Record* _getRecord () const; Record* _getRecord () const;
@ -252,8 +265,12 @@ namespace Anabatic {
inline bool AutoContact::isTerminal () const { return _flags&CntTerminal; } inline bool AutoContact::isTerminal () const { return _flags&CntTerminal; }
inline bool AutoContact::isHTee () const { return _flags&CntHTee; } inline bool AutoContact::isHTee () const { return _flags&CntHTee; }
inline bool AutoContact::isVTee () const { return _flags&CntVTee; } inline bool AutoContact::isVTee () const { return _flags&CntVTee; }
inline bool AutoContact::isHDogleg () const { return _flags&CntHDogleg; }
inline bool AutoContact::isVDogleg () const { return _flags&CntVDogleg; }
inline bool AutoContact::hasBadTopology () const { return _flags&CntBadTopology; } inline bool AutoContact::hasBadTopology () const { return _flags&CntBadTopology; }
inline bool AutoContact::canDrag () const { return _flags&CntDrag; }
inline size_t AutoContact::getId () const { return _id; } inline size_t AutoContact::getId () const { return _id; }
inline Flags AutoContact::getFlags () const { return _flags; }
inline Contact* AutoContact::base () const { return _contact; } inline Contact* AutoContact::base () const { return _contact; }
inline GCell* AutoContact::getGCell () const { return _gcell; } inline GCell* AutoContact::getGCell () const { return _gcell; }
inline Box AutoContact::getConstraintBox () const { return Box(getCBXMin(),getCBYMin(),getCBXMax(),getCBYMax()); } inline Box AutoContact::getConstraintBox () const { return Box(getCBXMin(),getCBYMin(),getCBXMax(),getCBYMax()); }

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved // Copyright (c) UPMC 2012-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2012-2016, All Rights Reserved // Copyright (c) UPMC/LIP6 2012-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -60,6 +60,7 @@ namespace Anabatic {
virtual void _invalidate ( Flags flags ); virtual void _invalidate ( Flags flags );
public: public:
bool isEndPoint () const; bool isEndPoint () const;
virtual bool isOnPin () const;
virtual Box getNativeConstraintBox () const; virtual Box getNativeConstraintBox () const;
RoutingPad* getRoutingPad () const; RoutingPad* getRoutingPad () const;
inline AutoSegment* getSegment () const; inline AutoSegment* getSegment () const;

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved // Copyright (c) UPMC 2012-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2016, All Rights Reserved // Copyright (c) UPMC 2012-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |

View File

@ -14,11 +14,9 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOHORIZONTAL_H #pragma once
#define ANABATIC_AUTOHORIZONTAL_H #include "hurricane/Horizontal.h"
#include "anabatic/AutoSegment.h"
#include "hurricane/Horizontal.h"
#include "anabatic/AutoSegment.h"
namespace Anabatic { namespace Anabatic {
@ -49,7 +47,7 @@ namespace Anabatic {
virtual Interval getSourceConstraints ( Flags flags=0 ) const; virtual Interval getSourceConstraints ( Flags flags=0 ) const;
virtual Interval getTargetConstraints ( Flags flags=0 ) const; virtual Interval getTargetConstraints ( Flags flags=0 ) const;
virtual Flags getDirection () const; virtual Flags getDirection () const;
virtual size_t getGCells ( vector<GCell*>& ) const; virtual bool getGCells ( vector<GCell*>& ) const;
// Modifiers. // Modifiers.
virtual void setDuSource ( DbU::Unit ); virtual void setDuSource ( DbU::Unit );
virtual void setDuTarget ( DbU::Unit ); virtual void setDuTarget ( DbU::Unit );
@ -91,6 +89,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::AutoHorizontal); INSPECTOR_P_SUPPORT(Anabatic::AutoHorizontal);
#endif // ANABATIC_AUTOHORIZONTAL_H

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved // Copyright (c) UPMC 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -14,9 +14,8 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOSEGMENT_H #pragma once
#define ANABATIC_AUTOSEGMENT_H #include <tuple>
#include <set> #include <set>
#include <iostream> #include <iostream>
#include <functional> #include <functional>
@ -39,6 +38,8 @@ namespace Hurricane {
namespace Anabatic { namespace Anabatic {
using std::tuple;
using std::array;
using std::set; using std::set;
using std::cerr; using std::cerr;
using std::endl; using std::endl;
@ -57,11 +58,10 @@ namespace Anabatic {
class AutoHorizontal; class AutoHorizontal;
class AutoVertical; class AutoVertical;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "AutoSegment". // Class : "AutoSegment".
class AutoSegment { class AutoSegment {
friend class AutoHorizontal; friend class AutoHorizontal;
friend class AutoVertical; friend class AutoVertical;
@ -70,38 +70,46 @@ namespace Anabatic {
static const uint64_t SegNoFlags = 0L; static const uint64_t SegNoFlags = 0L;
static const uint64_t SegHorizontal = (1L<< 0); static const uint64_t SegHorizontal = (1L<< 0);
static const uint64_t SegFixed = (1L<< 1); static const uint64_t SegFixed = (1L<< 1);
static const uint64_t SegGlobal = (1L<< 2); static const uint64_t SegFixedAxis = (1L<< 2);
static const uint64_t SegWeakGlobal = (1L<< 3); static const uint64_t SegGlobal = (1L<< 3);
static const uint64_t SegLongLocal = (1L<< 4); static const uint64_t SegWeakGlobal = (1L<< 4);
static const uint64_t SegCanonical = (1L<< 5); static const uint64_t SegLongLocal = (1L<< 5);
static const uint64_t SegBipoint = (1L<< 6); static const uint64_t SegCanonical = (1L<< 6);
static const uint64_t SegDogleg = (1L<< 7); static const uint64_t SegBipoint = (1L<< 7);
static const uint64_t SegStrap = (1L<< 8); static const uint64_t SegDogleg = (1L<< 8);
static const uint64_t SegSourceTop = (1L<< 9); static const uint64_t SegStrap = (1L<< 9);
static const uint64_t SegSourceBottom = (1L<<10); static const uint64_t SegSourceTop = (1L<<10);
static const uint64_t SegTargetTop = (1L<<11); static const uint64_t SegSourceBottom = (1L<<11);
static const uint64_t SegTargetBottom = (1L<<12); static const uint64_t SegTargetTop = (1L<<12);
static const uint64_t SegIsReduced = (1L<<13); static const uint64_t SegTargetBottom = (1L<<13);
static const uint64_t SegLayerChange = (1L<<14); static const uint64_t SegIsReduced = (1L<<14);
static const uint64_t SegSourceTerminal = (1L<<15); // Replace Terminal. static const uint64_t SegDrag = (1L<<15);
static const uint64_t SegTargetTerminal = (1L<<16); // Replace Terminal. static const uint64_t SegLayerChange = (1L<<16);
static const uint64_t SegSourceTerminal = (1L<<17); // Replace Terminal.
static const uint64_t SegTargetTerminal = (1L<<18); // Replace Terminal.
static const uint64_t SegStrongTerminal = SegSourceTerminal|SegTargetTerminal; static const uint64_t SegStrongTerminal = SegSourceTerminal|SegTargetTerminal;
static const uint64_t SegWeakTerminal1 = (1L<<17); // Replace TopologicalEnd. static const uint64_t SegWeakTerminal1 = (1L<<19); // Replace TopologicalEnd.
static const uint64_t SegWeakTerminal2 = (1L<<18); // Replace TopologicalEnd. static const uint64_t SegWeakTerminal2 = (1L<<20); // Replace TopologicalEnd.
static const uint64_t SegNotSourceAligned = (1L<<19); static const uint64_t SegNotSourceAligned = (1L<<21);
static const uint64_t SegNotTargetAligned = (1L<<20); static const uint64_t SegNotTargetAligned = (1L<<22);
static const uint64_t SegUnbound = (1L<<21); static const uint64_t SegUnbound = (1L<<23);
static const uint64_t SegHalfSlackened = (1L<<22); static const uint64_t SegHalfSlackened = (1L<<24);
static const uint64_t SegSlackened = (1L<<23); static const uint64_t SegSlackened = (1L<<25);
static const uint64_t SegAxisSet = (1L<<24); static const uint64_t SegAxisSet = (1L<<26);
static const uint64_t SegInvalidated = (1L<<25); static const uint64_t SegInvalidated = (1L<<27);
static const uint64_t SegInvalidatedSource = (1L<<26); static const uint64_t SegInvalidatedSource = (1L<<28);
static const uint64_t SegInvalidatedTarget = (1L<<27); static const uint64_t SegInvalidatedTarget = (1L<<29);
static const uint64_t SegInvalidatedLayer = (1L<<28); static const uint64_t SegInvalidatedLayer = (1L<<30);
static const uint64_t SegCreated = (1L<<29); static const uint64_t SegCreated = (1L<<31);
static const uint64_t SegUserDefined = (1L<<30); static const uint64_t SegUserDefined = (1L<<32);
static const uint64_t SegAnalog = (1L<<31); static const uint64_t SegAnalog = (1L<<33);
static const uint64_t SegWide = (1L<<32); static const uint64_t SegWide = (1L<<34);
static const uint64_t SegShortNet = (1L<<35);
static const uint64_t SegUnbreakable = (1L<<36);
static const uint64_t SegNonPref = (1L<<37);
static const uint64_t SegAtMinArea = (1L<<38);
static const uint64_t SegNoMoveUp = (1L<<39);
static const uint64_t SegOnVSmall = (1L<<40);
// Masks. // 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;
@ -130,252 +138,287 @@ namespace Anabatic {
public: public:
typedef std::function< void(AutoSegment*) > RevalidateCb_t; typedef std::function< void(AutoSegment*) > RevalidateCb_t;
public: public:
static void setAnalogMode ( bool ); static void setAnalogMode ( bool );
static bool getAnalogMode (); static bool getAnalogMode ();
static AutoSegment* create ( AutoContact* source static void setShortNetMode ( bool );
, AutoContact* target inline static DbU::Unit getViaToTopCap ( size_t depth );
, Segment* hurricaneSegment inline static DbU::Unit getViaToBottomCap ( size_t depth );
); inline static DbU::Unit getViaToSameCap ( size_t depth );
static AutoSegment* create ( AutoContact* source inline static DbU::Unit getMinimalLength ( size_t depth );
, AutoContact* target static AutoSegment* create ( AutoContact* source
, Flags dir , AutoContact* target
, size_t depth=RoutingGauge::nlayerdepth , Segment* hurricaneSegment
); );
void destroy (); static AutoSegment* create ( AutoContact* source
, AutoContact* target
, Flags dir
, size_t depth=RoutingGauge::nlayerdepth
);
void destroy ();
// Wrapped Segment Functions. // Wrapped Segment Functions.
virtual Segment* base () const = 0; virtual Segment* base () const = 0;
virtual Segment* base () = 0; virtual Segment* base () = 0;
virtual Horizontal* getHorizontal () { return NULL; }; virtual Horizontal* getHorizontal () { return NULL; };
virtual Vertical* getVertical () { return NULL; }; virtual Vertical* getVertical () { return NULL; };
inline Cell* getCell () const; inline Cell* getCell () const;
inline Net* getNet () const; inline Net* getNet () const;
inline const Layer* getLayer () const; inline const Layer* getLayer () const;
inline Box getBoundingBox () const; inline Box getBoundingBox () const;
inline Hook* getSourceHook (); inline Hook* getSourceHook ();
inline Hook* getTargetHook (); inline Hook* getTargetHook ();
inline Contact* getSource () const; inline Contact* getSource () const;
inline Contact* getTarget () const; inline Contact* getTarget () const;
inline Component* getOppositeAnchor ( Component* ) const; inline Component* getOppositeAnchor ( Component* ) const;
inline Components getAnchors () const; inline Components getAnchors () const;
virtual DbU::Unit getX () const; virtual DbU::Unit getX () const;
virtual DbU::Unit getY () const; virtual DbU::Unit getY () const;
inline DbU::Unit getWidth () const; inline DbU::Unit getWidth () const;
inline DbU::Unit getContactWidth () const; inline DbU::Unit getContactWidth () const;
inline DbU::Unit getLength () const; inline DbU::Unit getLength () const;
inline DbU::Unit getSourcePosition () const; inline DbU::Unit getSpanLength () const;
inline DbU::Unit getTargetPosition () const; inline DbU::Unit getAnchoredLength () const;
inline DbU::Unit getSourceX () const; inline DbU::Unit getSourcePosition () const;
inline DbU::Unit getSourceY () const; inline DbU::Unit getTargetPosition () const;
inline DbU::Unit getTargetX () const; inline DbU::Unit getSourceX () const;
inline DbU::Unit getTargetY () const; inline DbU::Unit getSourceY () const;
inline void invert (); inline DbU::Unit getTargetX () const;
inline void setLayer ( const Layer* ); inline DbU::Unit getTargetY () const;
inline void invert ();
inline void setLayer ( const Layer* );
inline void setLayer ( size_t depth );
inline void setWidth ( DbU::Unit );
// Predicates. // Predicates.
inline bool isHorizontal () const; inline bool isHorizontal () const;
inline bool isVertical () const; inline bool isVertical () const;
inline bool isGlobal () const; inline bool isGlobal () const;
inline bool isWeakGlobal () const; inline bool isWeakGlobal () const;
inline bool isLongLocal () const; inline bool isLongLocal () const;
inline bool isLocal () const; inline bool isLocal () const;
inline bool isFixed () const; inline bool isFixed () const;
inline bool isBipoint () const; inline bool isFixedAxis () const;
inline bool isWeakTerminal () const; inline bool isBipoint () const;
inline bool isWeakTerminal1 () const; inline bool isWeakTerminal () const;
inline bool isWeakTerminal2 () const; inline bool isWeakTerminal1 () const;
inline bool isTerminal () const; inline bool isWeakTerminal2 () const;
inline bool isNotSourceAligned () const; inline bool isTerminal () const;
inline bool isNotTargetAligned () const; inline bool isUnbreakable () const;
inline bool isNotAligned () const; inline bool isNonPref () const;
bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const; inline bool isNonPrefOnVSmall () const;
inline bool isSourceTerminal () const; inline bool isDrag () const;
inline bool isTargetTerminal () const; inline bool isAtMinArea () const;
inline bool isLayerChange () const; inline bool isNotSourceAligned () const;
inline bool isSpinTop () const; inline bool isNotTargetAligned () const;
inline bool isSpinBottom () const; inline bool isNotAligned () const;
inline bool isSpinTopOrBottom () const; bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const;
inline bool isReduced () const; inline bool isSourceTerminal () const;
inline bool isStrap () const; inline bool isTargetTerminal () const;
inline bool isDogleg () const; inline bool isLayerChange () const;
inline bool isUnbound () const; inline bool isStackedStrap () const;
inline bool isInvalidated () const; inline bool isSpinTop () const;
inline bool isInvalidatedLayer () const; inline bool isSpinBottom () const;
inline bool isCreated () const; inline bool isSpinTopOrBottom () const;
inline bool isCanonical () const; inline bool isReduced () const;
inline bool isUnsetAxis () const; inline bool isStrap () const;
inline bool isSlackened () const; inline bool isDogleg () const;
inline bool isUserDefined () const; inline bool isUnbound () const;
bool isReduceCandidate () const; inline bool isInvalidated () const;
bool isUTurn () const; inline bool isInvalidatedLayer () const;
inline bool isAnalog () const; inline bool isCreated () const;
inline bool isWide () const; inline bool isCanonical () const;
virtual bool _canSlacken () const = 0; inline bool isUnsetAxis () const;
bool canReduce () const; inline bool isSlackened () const;
bool mustRaise () const; inline bool isUserDefined () const;
Flags canDogleg ( Interval ); bool isNearMinArea () const;
virtual bool canMoveULeft ( float reserve=0.0 ) const = 0; bool isReduceCandidate () const;
virtual bool canMoveURight ( float reserve=0.0 ) const = 0; bool isUTurn () const;
bool canMoveUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; inline bool isAnalog () const;
bool canPivotUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; inline bool isWide () const;
bool canPivotDown ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; inline bool isShortNet () const;
bool canSlacken ( Flags flags=Flags::NoFlags ) const; inline bool isNoMoveUp () const;
virtual bool checkPositions () const = 0; virtual bool _canSlacken () const = 0;
virtual bool checkConstraints () const = 0; bool canReduce ( Flags flags=Flags::WithPerpands ) const;
bool checkDepthSpin () const; bool mustRaise () const;
Flags canDogleg ( Interval );
virtual bool canMoveULeft ( float reserve=0.0 ) const = 0;
virtual bool canMoveURight ( float reserve=0.0 ) const = 0;
bool canMoveUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const;
bool canPivotUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const;
bool canPivotDown ( float reserve=0.0, Flags flags=Flags::NoFlags ) const;
bool canSlacken ( Flags flags=Flags::NoFlags ) const;
virtual bool checkPositions () const = 0;
virtual bool checkConstraints () const = 0;
bool checkDepthSpin () const;
// Accessors. // Accessors.
inline unsigned long getId () const; inline unsigned long getId () const;
inline uint64_t getFlags () const; inline uint64_t getFlags () const;
virtual Flags getDirection () const = 0; virtual Flags getDirection () const = 0;
inline GCell* getGCell () const; inline GCell* getGCell () const;
virtual size_t getGCells ( vector<GCell*>& ) const = 0; virtual bool getGCells ( vector<GCell*>& ) const = 0;
inline AutoContact* getAutoSource () const; inline AutoContact* getAutoSource () const;
inline AutoContact* getAutoTarget () const; inline AutoContact* getAutoTarget () const;
AutoContact* getOppositeAnchor ( AutoContact* ) const; AutoContact* getOppositeAnchor ( AutoContact* ) const;
size_t getPerpandicularsBound ( set<AutoSegment*>& ); size_t getPerpandicularsBound ( set<AutoSegment*>& );
inline AutoSegment* getParent () const; inline AutoSegment* getParent () const;
inline unsigned int getDepth () const; inline unsigned int getRpDistance () const;
inline DbU::Unit getPitch () const; inline unsigned int getDepth () const;
DbU::Unit getPPitch () const; inline DbU::Unit getPitch () const;
DbU::Unit getExtensionCap () const; DbU::Unit getPPitch () const;
inline DbU::Unit getAxis () const; #if DISABLED
virtual DbU::Unit getSourceU () const = 0; DbU::Unit getExtensionCap () const;
virtual DbU::Unit getTargetU () const = 0; #endif
virtual DbU::Unit getDuSource () const = 0; DbU::Unit getExtensionCap ( Flags ) const;
virtual DbU::Unit getDuTarget () const = 0; inline DbU::Unit getAxis () const;
inline DbU::Unit getOrigin () const; void getEndAxes ( DbU::Unit& sourceAxis, DbU::Unit& targetAxis ) const;
inline DbU::Unit getExtremity () const; virtual DbU::Unit getSourceU () const = 0;
virtual Interval getSpanU () const = 0; virtual DbU::Unit getTargetU () const = 0;
Interval getMinSpanU () const; virtual DbU::Unit getDuSource () const = 0;
virtual Interval getSourceConstraints ( Flags flags=Flags::NoFlags ) const = 0; virtual DbU::Unit getDuTarget () const = 0;
virtual Interval getTargetConstraints ( Flags flags=Flags::NoFlags ) const = 0; inline DbU::Unit getOrigin () const;
virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const = 0; inline DbU::Unit getExtremity () const;
inline bool getConstraints ( Interval& i ) const; virtual Interval getSpanU () const = 0;
inline const Interval& getUserConstraints () const; Interval getMinSpanU () const;
inline const Interval& getNativeConstraints () const; virtual Interval getSourceConstraints ( Flags flags=Flags::NoFlags ) const = 0;
virtual DbU::Unit getSlack () const; virtual Interval getTargetConstraints ( Flags flags=Flags::NoFlags ) const = 0;
inline DbU::Unit getOptimalMin () const; virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const = 0;
inline DbU::Unit getOptimalMax () const; inline bool getConstraints ( Interval& i ) const;
inline DbU::Unit getNativeMin () const; inline const Interval& getUserConstraints () const;
inline DbU::Unit getNativeMax () const; inline const Interval& getNativeConstraints () const;
Interval& getOptimal ( Interval& i ) const; virtual DbU::Unit getSlack () const;
virtual DbU::Unit getCost ( DbU::Unit axis ) const; inline DbU::Unit getOptimalMin () const;
virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max ); inline DbU::Unit getOptimalMax () const;
inline AutoSegment* getCanonical ( Interval& i ); inline DbU::Unit getNativeMin () const;
float getMaxUnderDensity ( Flags flags ); inline DbU::Unit getNativeMax () const;
Interval& getOptimal ( Interval& i ) const;
virtual DbU::Unit getCost ( DbU::Unit axis ) const;
virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max );
inline AutoSegment* getCanonical ( Interval& i );
float getMaxUnderDensity ( Flags flags );
inline uint32_t getReduceds () const;
uint32_t getNonReduceds ( Flags flags=Flags::WithPerpands ) const;
// Modifiers. // Modifiers.
inline void unsetFlags ( uint64_t ); inline void unsetFlags ( uint64_t );
inline void setFlags ( uint64_t ); inline void setFlags ( uint64_t );
void setFlagsOnAligneds ( uint64_t ); void setFlagsOnAligneds ( uint64_t );
inline void incReduceds (); inline void setRpDistance ( unsigned int );
inline void decReduceds (); inline void incReduceds ();
virtual void setDuSource ( DbU::Unit du ) = 0; inline void decReduceds ();
virtual void setDuTarget ( DbU::Unit du ) = 0; virtual void setDuSource ( DbU::Unit du ) = 0;
void computeTerminal (); virtual void setDuTarget ( DbU::Unit du ) = 0;
virtual void updateOrient () = 0; void computeTerminal ();
virtual void updatePositions () = 0; virtual void updateOrient () = 0;
virtual void updateNativeConstraints () = 0; virtual void updatePositions () = 0;
void updateSourceSpin (); virtual void updateNativeConstraints () = 0;
void updateTargetSpin (); void updateSourceSpin ();
void sourceDetach (); void updateTargetSpin ();
void targetDetach (); void sourceDetach ();
void sourceAttach ( AutoContact* ); void targetDetach ();
void targetAttach ( AutoContact* ); void sourceAttach ( AutoContact* );
//inline void mergeUserConstraints ( const Interval& ); void targetAttach ( AutoContact* );
void mergeUserConstraints ( const Interval& ); //inline void mergeUserConstraints ( const Interval& );
inline void resetUserConstraints (); void mergeUserConstraints ( const Interval& );
inline void setOptimalMin ( DbU::Unit min ); inline void resetUserConstraints ();
inline void setOptimalMax ( DbU::Unit max ); inline void setOptimalMin ( DbU::Unit min );
inline void mergeNativeMin ( DbU::Unit min ); inline void setOptimalMax ( DbU::Unit max );
inline void mergeNativeMax ( DbU::Unit max ); inline void mergeNativeMin ( DbU::Unit min );
inline void resetNativeConstraints ( DbU::Unit min, DbU::Unit max ); inline void mergeNativeMax ( DbU::Unit max );
bool checkNotInvalidated () const; inline void resetNativeConstraints ( DbU::Unit min, DbU::Unit max );
inline void setParent ( AutoSegment* ); bool checkNotInvalidated () const;
void revalidate (); inline void setParent ( AutoSegment* );
AutoSegment* makeDogleg ( AutoContact* ); void revalidate ();
Flags makeDogleg ( Interval, Flags flags=Flags::NoFlags ); AutoSegment* makeDogleg ( AutoContact* );
Flags makeDogleg ( GCell* , Flags flags=Flags::NoFlags ); Flags makeDogleg ( Interval, Flags flags=Flags::NoFlags );
virtual Flags _makeDogleg ( GCell* , Flags flags ) = 0; Flags makeDogleg ( GCell* , Flags flags=Flags::NoFlags );
virtual bool moveULeft () = 0; virtual Flags _makeDogleg ( GCell* , Flags flags ) = 0;
virtual bool moveURight () = 0; virtual bool moveULeft () = 0;
bool slacken ( Flags flags ); virtual bool moveURight () = 0;
virtual bool _slacken ( Flags flags ) = 0; bool slacken ( Flags flags );
void _changeDepth ( unsigned int depth, Flags flags ); virtual bool _slacken ( Flags flags ) = 0;
void changeDepth ( unsigned int depth, Flags flags ); void _changeDepth ( unsigned int depth, Flags flags );
bool moveUp ( Flags flags=Flags::NoFlags ); void changeDepth ( unsigned int depth, Flags flags );
bool moveDown ( Flags flags=Flags::NoFlags ); bool moveUp ( Flags flags=Flags::NoFlags );
bool reduceDoglegLayer (); bool moveDown ( Flags flags=Flags::NoFlags );
bool reduce (); bool reduceDoglegLayer ();
bool raise (); bool bloatStackedStrap ();
bool reduce ( Flags flags=Flags::WithPerpands );
bool raise ();
void expandToMinLength ( Interval );
void unexpandToMinLength ();
// Canonical Modifiers. // Canonical Modifiers.
AutoSegment* canonize ( Flags flags=Flags::NoFlags ); AutoSegment* canonize ( Flags flags=Flags::NoFlags );
virtual void invalidate ( Flags flags=Flags::Propagate ); virtual void invalidate ( Flags flags=Flags::Propagate );
void invalidate ( AutoContact* ); void invalidate ( AutoContact* );
void computeOptimal ( set<AutoSegment*>& processeds ); void computeOptimal ( set<AutoSegment*>& processeds );
void setAxis ( DbU::Unit, Flags flags=Flags::NoFlags ); void setAxis ( DbU::Unit, Flags flags=Flags::NoFlags );
bool toConstraintAxis ( Flags flags=Flags::Realignate ); bool toConstraintAxis ( Flags flags=Flags::Realignate );
bool toOptimalAxis ( Flags flags=Flags::Realignate ); bool toOptimalAxis ( Flags flags=Flags::Realignate );
// Collections & Filters. // Collections & Filters.
AutoSegments getOnSourceContact ( Flags direction ); AutoSegments getOnSourceContact ( Flags direction );
AutoSegments getOnTargetContact ( Flags direction ); AutoSegments getOnTargetContact ( Flags direction );
AutoSegments getCachedOnSourceContact ( Flags direction ); AutoSegments getCachedOnSourceContact ( Flags direction );
AutoSegments getCachedOnTargetContact ( Flags direction ); AutoSegments getCachedOnTargetContact ( Flags direction );
AutoSegments getAligneds ( Flags flags=Flags::NoFlags ); AutoSegments getAligneds ( Flags flags=Flags::NoFlags );
AutoSegments getConnecteds ( Flags flags=Flags::NoFlags ); AutoSegments getConnecteds ( Flags flags=Flags::NoFlags );
AutoSegments getPerpandiculars ( Flags flags=Flags::NoFlags ); AutoSegments getPerpandiculars ( Flags flags=Flags::NoFlags );
size_t getAlignedContacts ( map<AutoContact*,int>& ) const ; size_t getAlignedContacts ( map<AutoContact*,int>& ) const ;
// Observers. // Observers.
template< typename OwnerT > template< typename OwnerT >
inline OwnerT* getObserver ( size_t slot ); inline OwnerT* getObserver ( size_t slot );
inline void setObserver ( size_t slot, BaseObserver* ); inline void setObserver ( size_t slot, BaseObserver* );
inline void notify ( unsigned int flags ); inline void notify ( unsigned int flags );
// Inspector Management. // Inspector Management.
virtual Record* _getRecord () const = 0; virtual Record* _getRecord () const = 0;
virtual string _getString () const = 0; virtual string _getString () const = 0;
virtual string _getTypeName () const = 0; virtual string _getTypeName () const = 0;
// Non-reviewed atomic modifiers. // Non-reviewed atomic modifiers.
bool _check () const; bool _check () const;
#if THIS_IS_DISABLED #if THIS_IS_DISABLED
virtual void desalignate ( AutoContact* ) = 0; virtual void desalignate ( AutoContact* ) = 0;
bool shearUp ( GCell* bool shearUp ( GCell*
, AutoSegment*& movedUp , AutoSegment*& movedUp
, float reserve , float reserve
, Flags flags ); , Flags flags );
#endif #endif
protected: protected:
// Internal: Static Attributes. // Internal: Static Attributes.
static size_t _allocateds; static size_t _allocateds;
static size_t _globalsCount; static size_t _globalsCount;
static bool _analogMode; static bool _analogMode;
static bool _shortNetMode;
static bool _initialized;
static vector< array<DbU::Unit*,4> > _extensionCaps;
// Internal: Attributes. // Internal: Attributes.
const unsigned long _id; const unsigned long _id;
GCell* _gcell; GCell* _gcell;
uint64_t _flags; uint64_t _flags;
unsigned int _depth : 8; unsigned int _depth : 8;
unsigned int _optimalMin :16; unsigned int _optimalMin :16;
unsigned int _optimalMax :16; unsigned int _optimalMax :16;
unsigned int _reduceds : 2; unsigned int _reduceds : 2;
DbU::Unit _sourcePosition; unsigned int _rpDistance : 4;
DbU::Unit _targetPosition; DbU::Unit _sourcePosition;
Interval _userConstraints; DbU::Unit _targetPosition;
Interval _nativeConstraints; Interval _userConstraints;
AutoSegment* _parent; Interval _nativeConstraints;
Observable _observers; AutoSegment* _parent;
Observable _observers;
// Internal: Constructors & Destructors. // Internal: Constructors & Destructors.
protected: protected:
AutoSegment ( Segment* segment ); AutoSegment ( Segment* segment );
virtual ~AutoSegment (); virtual ~AutoSegment ();
static void _preCreate ( AutoContact* source, AutoContact* target ); static void _preCreate ( AutoContact* source, AutoContact* target );
virtual void _postCreate (); virtual void _postCreate ();
virtual void _preDestroy (); virtual void _preDestroy ();
static void _initialize ();
private: private:
AutoSegment ( const AutoSegment& ); AutoSegment ( const AutoSegment& );
AutoSegment& operator= ( const AutoSegment& ); AutoSegment& operator= ( const AutoSegment& );
protected: protected:
void _invalidate (); void _invalidate ();
inline uint64_t _getFlags () const; inline uint64_t _getFlags () const;
std::string _getStringFlags () const; std::string _getStringFlags () const;
virtual void _setAxis ( DbU::Unit ) = 0; virtual void _setAxis ( DbU::Unit ) = 0;
public: public:
struct CompareId : public binary_function<AutoSegment*,AutoSegment*,bool> { struct CompareId : public binary_function<AutoSegment*,AutoSegment*,bool> {
@ -389,8 +432,20 @@ namespace Anabatic {
struct CompareByDepthAxis : public binary_function<AutoSegment*,AutoSegment*,bool> { struct CompareByDepthAxis : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const; bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
}; };
public:
struct CompareBySourceU : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
struct CompareByRevalidate : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
struct CompareByReduceds : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public: public:
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet; typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
typedef std::set<AutoSegment*,CompareId> IdSet;
// Static Utilities. // Static Utilities.
public: public:
@ -414,7 +469,8 @@ namespace Anabatic {
); );
static void getTopologicalInfos ( AutoSegment* seed static void getTopologicalInfos ( AutoSegment* seed
, vector<AutoSegment*>& collapseds , vector<AutoSegment*>& collapseds
, vector<AutoSegment*>& perpandiculars , vector< tuple<AutoSegment*,Flags> >&
perpandiculars
, DbU::Unit& leftBound , DbU::Unit& leftBound
, DbU::Unit& rightBound , DbU::Unit& rightBound
); );
@ -429,6 +485,10 @@ namespace Anabatic {
// Inline Functions. // Inline Functions.
inline DbU::Unit AutoSegment::getViaToTopCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][0]) : 0; }
inline DbU::Unit AutoSegment::getViaToBottomCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][1]) : 0; }
inline DbU::Unit AutoSegment::getViaToSameCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][2]) : 0; }
inline DbU::Unit AutoSegment::getMinimalLength ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][3]) : 0; }
inline unsigned long AutoSegment::getId () const { return _id; } inline unsigned long AutoSegment::getId () const { return _id; }
inline Cell* AutoSegment::getCell () const { return base()->getCell(); } inline Cell* AutoSegment::getCell () const { return base()->getCell(); }
inline Net* AutoSegment::getNet () const { return base()->getNet(); } inline Net* AutoSegment::getNet () const { return base()->getNet(); }
@ -455,6 +515,7 @@ namespace Anabatic {
inline bool AutoSegment::getConstraints ( Interval& i ) const { return getConstraints(i.getVMin(),i.getVMax()); } inline bool AutoSegment::getConstraints ( Interval& i ) const { return getConstraints(i.getVMin(),i.getVMax()); }
inline AutoSegment* AutoSegment::getCanonical ( Interval& i ) { return getCanonical(i.getVMin(),i.getVMax()); } inline AutoSegment* AutoSegment::getCanonical ( Interval& i ) { return getCanonical(i.getVMin(),i.getVMax()); }
inline unsigned int AutoSegment::getDepth () const { return _depth; } inline unsigned int AutoSegment::getDepth () const { return _depth; }
inline unsigned int AutoSegment::getRpDistance () const { return _rpDistance; }
inline DbU::Unit AutoSegment::getPitch () const { return Session::getPitch(getDepth(),Flags::NoFlags); } inline DbU::Unit AutoSegment::getPitch () const { return Session::getPitch(getDepth(),Flags::NoFlags); }
inline DbU::Unit AutoSegment::getAxis () const { return isHorizontal()?base()->getY():base()->getX(); } inline DbU::Unit AutoSegment::getAxis () const { return isHorizontal()?base()->getY():base()->getX(); }
inline DbU::Unit AutoSegment::getOrigin () const { return isHorizontal()?_gcell->getYMin():_gcell->getXMin(); } inline DbU::Unit AutoSegment::getOrigin () const { return isHorizontal()?_gcell->getYMin():_gcell->getXMin(); }
@ -465,21 +526,28 @@ namespace Anabatic {
inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); } inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); }
inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; } inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; }
inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; } inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; }
inline uint32_t AutoSegment::getReduceds () const { return _reduceds; }
inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; } inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; }
inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); } inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); }
inline bool AutoSegment::isFixed () const { return _flags & SegFixed; } inline bool AutoSegment::isFixed () const { return _flags & SegFixed; }
inline bool AutoSegment::isFixedAxis () const { return _flags & SegFixedAxis; }
inline bool AutoSegment::isGlobal () const { return _flags & SegGlobal; } inline bool AutoSegment::isGlobal () const { return _flags & SegGlobal; }
inline bool AutoSegment::isWeakGlobal () const { return _flags & SegWeakGlobal; } inline bool AutoSegment::isWeakGlobal () const { return _flags & SegWeakGlobal; }
inline bool AutoSegment::isLongLocal () const { return _flags & SegLongLocal; } inline bool AutoSegment::isLongLocal () const { return _flags & SegLongLocal; }
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::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 _flags & SegWeakTerminal; } inline bool AutoSegment::isWeakTerminal () const { return (_rpDistance < 2); }
inline bool AutoSegment::isWeakTerminal1 () const { return _flags & SegWeakTerminal1; } inline bool AutoSegment::isWeakTerminal1 () const { return (_rpDistance == 1); }
inline bool AutoSegment::isWeakTerminal2 () const { return _flags & SegWeakTerminal2; } inline bool AutoSegment::isWeakTerminal2 () const { return (_rpDistance == 2); }
inline bool AutoSegment::isSourceTerminal () const { return _flags & SegSourceTerminal; } inline bool AutoSegment::isSourceTerminal () const { return _flags & SegSourceTerminal; }
inline bool AutoSegment::isTargetTerminal () const { return _flags & SegTargetTerminal; } inline bool AutoSegment::isTargetTerminal () const { return _flags & SegTargetTerminal; }
inline bool AutoSegment::isTerminal () const { return _flags & SegStrongTerminal; } inline bool AutoSegment::isTerminal () const { return (_rpDistance == 0); }
inline bool AutoSegment::isDrag () const { return _flags & SegDrag; }
inline bool AutoSegment::isAtMinArea () const { return _flags & SegAtMinArea; }
inline bool AutoSegment::isNotSourceAligned () const { return _flags & SegNotSourceAligned; } inline bool AutoSegment::isNotSourceAligned () const { return _flags & SegNotSourceAligned; }
inline bool AutoSegment::isNotTargetAligned () const { return _flags & SegNotTargetAligned; } inline bool AutoSegment::isNotTargetAligned () const { return _flags & SegNotTargetAligned; }
inline bool AutoSegment::isNotAligned () const { return (_flags & SegNotAligned) == SegNotAligned; } inline bool AutoSegment::isNotAligned () const { return (_flags & SegNotAligned) == SegNotAligned; }
@ -500,14 +568,18 @@ namespace Anabatic {
inline bool AutoSegment::isUserDefined () const { return _flags & SegUserDefined; } inline bool AutoSegment::isUserDefined () const { return _flags & SegUserDefined; }
inline bool AutoSegment::isAnalog () const { return _flags & SegAnalog; } inline bool AutoSegment::isAnalog () const { return _flags & SegAnalog; }
inline bool AutoSegment::isWide () const { return _flags & SegWide; } inline bool AutoSegment::isWide () const { return _flags & SegWide; }
inline bool AutoSegment::isShortNet () const { return _flags & SegShortNet; }
inline bool AutoSegment::isNoMoveUp () const { return _flags & SegNoMoveUp; }
inline void AutoSegment::setFlags ( uint64_t flags ) { _flags |= flags; } inline void AutoSegment::setFlags ( uint64_t flags ) { _flags |= flags; }
inline void AutoSegment::unsetFlags ( uint64_t flags ) { _flags &= ~flags; } inline void AutoSegment::unsetFlags ( uint64_t flags ) { _flags &= ~flags; }
inline uint64_t AutoSegment::getFlags () const { return _flags; } inline uint64_t AutoSegment::getFlags () const { return _flags; }
inline uint64_t AutoSegment::_getFlags () const { return _flags; } inline uint64_t AutoSegment::_getFlags () const { return _flags; }
inline void AutoSegment::setRpDistance ( unsigned int distance ) { _rpDistance=distance; }
inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; } inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; }
inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; } inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; }
inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); } inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); _flags|=SegInvalidatedLayer; }
inline void AutoSegment::setWidth ( DbU::Unit width ) { base()->setWidth(width); }
inline void AutoSegment::setOptimalMin ( DbU::Unit min ) { _optimalMin = (unsigned int)DbU::getLambda(min-getOrigin()); } inline void AutoSegment::setOptimalMin ( DbU::Unit min ) { _optimalMin = (unsigned int)DbU::getLambda(min-getOrigin()); }
inline void AutoSegment::setOptimalMax ( DbU::Unit max ) { _optimalMax = (unsigned int)DbU::getLambda(max-getOrigin()); } inline void AutoSegment::setOptimalMax ( DbU::Unit max ) { _optimalMax = (unsigned int)DbU::getLambda(max-getOrigin()); }
inline void AutoSegment::mergeNativeMin ( DbU::Unit min ) { _nativeConstraints.getVMin() = std::max( min, _nativeConstraints.getVMin() ); } inline void AutoSegment::mergeNativeMin ( DbU::Unit min ) { _nativeConstraints.getVMin() = std::max( min, _nativeConstraints.getVMin() ); }
@ -515,11 +587,25 @@ namespace Anabatic {
inline void AutoSegment::resetNativeConstraints ( DbU::Unit min, DbU::Unit max ) { _nativeConstraints = Interval( min, max ); } inline void AutoSegment::resetNativeConstraints ( DbU::Unit min, DbU::Unit max ) { _nativeConstraints = Interval( min, max ); }
//inline void AutoSegment::mergeUserConstraints ( const Interval& constraints ) { _userConstraints.intersection(constraints); } //inline void AutoSegment::mergeUserConstraints ( const Interval& constraints ) { _userConstraints.intersection(constraints); }
inline void AutoSegment::resetUserConstraints () { _userConstraints = Interval(false); } inline void AutoSegment::resetUserConstraints () { _userConstraints = Interval(false); }
inline DbU::Unit AutoSegment::getAnchoredLength () const { return std::abs(getTargetU() - getSourceU()); }
inline void AutoSegment::setLayer ( size_t depth )
{
RoutingLayerGauge* layerGauge = Session::getLayerGauge( depth );
base()->setLayer( layerGauge->getLayer () );
base()->setWidth( layerGauge->getWireWidth() );
_depth = depth;
_flags|=SegInvalidatedLayer;
}
inline DbU::Unit AutoSegment::getContactWidth () const inline DbU::Unit AutoSegment::getContactWidth () const
{ return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); } { return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); }
inline DbU::Unit AutoSegment::getSpanLength () const
{ return getAnchoredLength() + getExtensionCap( Flags::Source|Flags::LayerCapOnly|Flags::NoMinLength )
+ getExtensionCap( Flags::Target|Flags::LayerCapOnly|Flags::NoMinLength );
}
inline void AutoSegment::setParent ( AutoSegment* parent ) inline void AutoSegment::setParent ( AutoSegment* parent )
{ {
@ -529,7 +615,6 @@ namespace Anabatic {
_parent = parent; _parent = parent;
} }
inline bool AutoSegment::CompareId::operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const inline bool AutoSegment::CompareId::operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const
{ return lhs->getId() < rhs->getId(); } { return lhs->getId() < rhs->getId(); }
@ -585,7 +670,8 @@ namespace Anabatic {
cdebug_log(145,0) << "getTerminalCount() - " << seed << endl; cdebug_log(145,0) << "getTerminalCount() - " << seed << endl;
vector<AutoSegment*> collapseds; vector<AutoSegment*> collapseds;
vector<AutoSegment*> perpandiculars; vector< tuple<AutoSegment*,Flags> >
perpandiculars;
DbU::Unit leftBound; DbU::Unit leftBound;
DbU::Unit rightBound; DbU::Unit rightBound;
@ -621,6 +707,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::AutoSegment); INSPECTOR_P_SUPPORT(Anabatic::AutoSegment);
# endif // ANABATIC_AUTOSEGMENT_H

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2016, All Rights Reserved // Copyright (c) UPMC/LIP6 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -48,6 +48,7 @@ namespace Anabatic {
using Hurricane::DbU; using Hurricane::DbU;
using Hurricane::Box; using Hurricane::Box;
using Hurricane::Hook; using Hurricane::Hook;
using Hurricane::Entity;
using Hurricane::Component; using Hurricane::Component;
using Hurricane::Contact; using Hurricane::Contact;
using Hurricane::Segment; using Hurricane::Segment;
@ -70,13 +71,13 @@ namespace Anabatic {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Collections. // Collections.
typedef Hurricane::Filter<AutoSegment*> AutoSegmentHF; typedef Hurricane::Filter<AutoSegment*> AutoSegmentHF;
typedef Hurricane::Locator<AutoSegment*> AutoSegmentHL; typedef Hurricane::Locator<AutoSegment*> AutoSegmentHL;
typedef Hurricane::Collection<AutoSegment*> AutoSegmentHC; typedef Hurricane::Collection<AutoSegment*> AutoSegmentHC;
typedef GenericCollection<AutoSegment*> AutoSegments; typedef GenericCollection<AutoSegment*> AutoSegments;
typedef GenericLocator<AutoSegment*> AutoSegmentLocator; typedef GenericLocator<AutoSegment*> AutoSegmentLocator;
typedef GenericFilter<AutoSegment*> AutoSegmentFilter; typedef GenericFilter<AutoSegment*> AutoSegmentFilter;
typedef map<Segment*,AutoSegment*> AutoSegmentLut; typedef map<Segment*,AutoSegment*,Entity::CompareById> AutoSegmentLut;
// ------------------------------------------------------------------- // -------------------------------------------------------------------

View File

@ -14,11 +14,9 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOVERTICAL_H #pragma once
#define ANABATIC_AUTOVERTICAL_H #include "hurricane/Vertical.h"
#include "anabatic/AutoSegment.h"
#include "hurricane/Vertical.h"
#include "anabatic/AutoSegment.h"
namespace Anabatic { namespace Anabatic {
@ -49,7 +47,7 @@ namespace Anabatic {
virtual Interval getSourceConstraints ( Flags flags=0 ) const; virtual Interval getSourceConstraints ( Flags flags=0 ) const;
virtual Interval getTargetConstraints ( Flags flags=0 ) const; virtual Interval getTargetConstraints ( Flags flags=0 ) const;
virtual Flags getDirection () const; virtual Flags getDirection () const;
virtual size_t getGCells ( vector<GCell*>& ) const; virtual bool getGCells ( vector<GCell*>& ) const;
// Modifiers. // Modifiers.
virtual void setDuSource ( DbU::Unit ); virtual void setDuSource ( DbU::Unit );
virtual void setDuTarget ( DbU::Unit ); virtual void setDuTarget ( DbU::Unit );
@ -91,6 +89,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::AutoVertical); INSPECTOR_P_SUPPORT(Anabatic::AutoVertical);
#endif // ANABATIC_AUTOHORIZONTAL_H

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2016, All Rights Reserved // Copyright (c) UPMC/LIP6 2008-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_CHIP_TOOLS_H #pragma once
#define ANABATIC_CHIP_TOOLS_H
#include <string> #include <string>
#include "hurricane/DbU.h" #include "hurricane/DbU.h"
#include "hurricane/Torus.h" #include "hurricane/Torus.h"
@ -113,6 +111,4 @@ namespace Anabatic {
} // Anabatic namespace. } // Anabatic namespace.
INSPECTOR_PV_SUPPORT(Anabatic::ChipTools); INSPECTOR_PR_SUPPORT(Anabatic::ChipTools);
#endif // ANABATIC_CHIP_TOOLS_H

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Configuration.h<anabatic>" -*- // -*- mode: C++; explicit-buffer-name: "Configuration.h<anabatic>" -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved // Copyright (c) Sorbonne Université 2016-2022, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_CONFIGURATION_H #pragma once
#define ANABATIC_CONFIGURATION_H
#include <string> #include <string>
#include <vector> #include <vector>
@ -24,6 +22,7 @@
namespace Hurricane { namespace Hurricane {
class Layer; class Layer;
class Cell; class Cell;
class RoutingPad;
} }
namespace CRL { namespace CRL {
@ -43,6 +42,7 @@ namespace Anabatic {
using Hurricane::Name; using Hurricane::Name;
using Hurricane::Layer; using Hurricane::Layer;
using Hurricane::DbU; using Hurricane::DbU;
using Hurricane::RoutingPad;
using Hurricane::Cell; using Hurricane::Cell;
using CRL::CellGauge; using CRL::CellGauge;
using CRL::RoutingGauge; using CRL::RoutingGauge;
@ -53,59 +53,106 @@ namespace Anabatic {
// Class : "Anabatic::Configuration". // Class : "Anabatic::Configuration".
class Configuration { class Configuration {
public:
static const size_t ndepth = (size_t)-1;
public: public:
// Constructor & Destructor. // Constructor & Destructor.
Configuration ( const CellGauge* cg=NULL, const RoutingGauge* rg=NULL ); Configuration ( const CellGauge* cg=NULL, const RoutingGauge* rg=NULL );
Configuration ( const Configuration& ); Configuration ( const Configuration& );
virtual ~Configuration (); virtual ~Configuration ();
virtual Configuration* clone () const; virtual Configuration* clone () const;
// Methods. // Methods.
bool isGMetal ( const Layer* ) const; inline bool isGLayer ( const Layer* ) const;
bool isGContact ( const Layer* ) const; bool isGMetal ( const Layer* ) const;
const Layer* getGContactLayer () const; bool isGContact ( const Layer* ) const;
const Layer* getGHorizontalLayer () const; bool isTwoMetals () const;
const Layer* getGVerticalLayer () const; bool isHybrid () const;
size_t getDepth () const; bool isHV () const;
size_t getAllowedDepth () const; bool isVH () const;
size_t getLayerDepth ( const Layer* ) const; inline std::string getNetBuilderStyle () const;
CellGauge* getCellGauge () const; inline StyleFlags getRoutingStyle () const;
RoutingGauge* getRoutingGauge () const; const Layer* getGContactLayer () const;
RoutingLayerGauge* getLayerGauge ( size_t depth ) const; const Layer* getGHorizontalLayer () const;
const Layer* getRoutingLayer ( size_t depth ) const; const Layer* getGVerticalLayer () const;
Layer* getContactLayer ( size_t depth ) const; inline size_t getGVerticalDepth () const;
DbU::Unit getSliceHeight () const; inline DbU::Unit getGVerticalPitch () const;
DbU::Unit getSliceStep () const; inline size_t getGHorizontalDepth () const;
DbU::Unit getPitch ( size_t depth, Flags flags ) const; inline DbU::Unit getGHorizontalPitch () const;
DbU::Unit getOffset ( size_t depth ) const; inline size_t getDVerticalDepth () const;
DbU::Unit getWireWidth ( size_t depth ) const; inline const Layer* getDVerticalLayer () const;
DbU::Unit getExtensionCap ( size_t depth ) const; inline DbU::Unit getDVerticalWidth () const;
Flags getDirection ( size_t depth ) const; inline DbU::Unit getDPVerticalWidth () const;
DbU::Unit getPitch ( const Layer*, Flags flags ) const; inline DbU::Unit getDVerticalPitch () const;
DbU::Unit getOffset ( const Layer* ) const; inline DbU::Unit getDVerticalOffset () const;
DbU::Unit getWireWidth ( const Layer* ) const; inline size_t getDHorizontalDepth () const;
DbU::Unit getExtensionCap ( const Layer* ) const; inline const Layer* getDHorizontalLayer () const;
Flags getDirection ( const Layer* ) const; inline DbU::Unit getDHorizontalWidth () const;
float getSaturateRatio () const; inline DbU::Unit getDPHorizontalWidth () const;
size_t getSaturateRp () const; inline DbU::Unit getDHorizontalPitch () const;
DbU::Unit getGlobalThreshold () const; inline DbU::Unit getDHorizontalOffset () const;
void setAllowedDepth ( size_t ); inline size_t getDContactDepth () const;
void setSaturateRatio ( float ); inline const Layer* getDContactLayer () const;
void setSaturateRp ( size_t ); inline DbU::Unit getDContactWidth () const;
void setGlobalThreshold ( DbU::Unit ); inline DbU::Unit getDContactPitch () const;
DbU::Unit getEdgeLength () const; size_t getDepth () const;
DbU::Unit getEdgeWidth () const; size_t getAllowedDepth () const;
float getEdgeCostH () const; size_t getLayerDepth ( const Layer* ) const;
float getEdgeCostK () const; CellGauge* getCellGauge () const;
float getEdgeHInc () const; RoutingGauge* getRoutingGauge () const;
virtual void print ( Cell* ) const; RoutingLayerGauge* getLayerGauge ( size_t depth ) const;
virtual Record* _getRecord () const; const Layer* getRoutingLayer ( size_t depth ) const;
virtual string _getString () const; Layer* getContactLayer ( size_t depth ) const;
virtual string _getTypeName () const; DbU::Unit getSliceHeight () const;
DbU::Unit getSliceStep () const;
DbU::Unit getPitch ( size_t depth, Flags flags ) const;
DbU::Unit getOffset ( size_t depth ) const;
DbU::Unit getWireWidth ( size_t depth ) const;
DbU::Unit getPWireWidth ( size_t depth ) const;
DbU::Unit getExtensionCap ( size_t depth ) const;
Flags getDirection ( size_t depth ) const;
DbU::Unit getPitch ( const Layer*, Flags flags ) const;
DbU::Unit getOffset ( const Layer* ) const;
DbU::Unit getWireWidth ( const Layer* ) const;
DbU::Unit getPWireWidth ( const Layer* ) const;
DbU::Unit getExtensionCap ( const Layer* ) const;
Flags getDirection ( const Layer* ) const;
float getSaturateRatio () const;
size_t getSaturateRp () const;
inline std::string getDiodeName () const;
inline DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getAntennaDiodeMaxWL () const;
DbU::Unit getGlobalThreshold () const;
void setAllowedDepth ( size_t );
void setSaturateRatio ( float );
void setSaturateRp ( size_t );
void setGlobalThreshold ( DbU::Unit );
DbU::Unit getEdgeLength () const;
DbU::Unit getEdgeWidth () const;
float getEdgeCostH () const;
float getEdgeCostK () const;
float getEdgeHInc () const;
float getEdgeHScaling () const;
int getGlobalIterations () const;
DbU::Unit isOnRoutingGrid ( RoutingPad* ) const;
bool selectRpComponent ( RoutingPad* ) const;
inline void setRoutingStyle ( StyleFlags );
inline void resetRoutingStyle ( StyleFlags );
virtual void print ( Cell* ) const;
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
protected: protected:
// Attributes. // Attributes.
const Layer* _gmetalh; const Layer* _gmetalh;
const Layer* _gmetalv; const Layer* _gmetalv;
const Layer* _gcontact; const Layer* _gcontact;
size_t _gdepthv;
size_t _gdepthh;
size_t _ddepthv;
size_t _ddepthh;
size_t _ddepthc;
std::string _netBuilderStyle;
StyleFlags _routingStyle;
CellGauge* _cg; CellGauge* _cg;
RoutingGauge* _rg; RoutingGauge* _rg;
std::vector<DbU::Unit> _extensionCaps; std::vector<DbU::Unit> _extensionCaps;
@ -118,15 +165,48 @@ namespace Anabatic {
float _edgeCostH; float _edgeCostH;
float _edgeCostK; float _edgeCostK;
float _edgeHInc; float _edgeHInc;
float _edgeHScaling;
int _globalIterations;
std::string _diodeName;
DbU::Unit _antennaGateMaxWL;
DbU::Unit _antennaDiodeMaxWL;
private: private:
Configuration& operator= ( const Configuration& ) = delete; Configuration& operator= ( const Configuration& ) = delete;
void _setTopRoutingLayer ( Name name ); void _setTopRoutingLayer ( Name name );
}; };
inline std::string Configuration::getNetBuilderStyle () const { return _netBuilderStyle; }
inline StyleFlags Configuration::getRoutingStyle () const { return _routingStyle; }
inline bool Configuration::isGLayer ( const Layer* layer ) const { return isGMetal(layer) or isGContact(layer); }
inline size_t Configuration::getGHorizontalDepth () const { return _gdepthh; }
inline size_t Configuration::getGVerticalDepth () const { return _gdepthv; }
inline DbU::Unit Configuration::getGHorizontalPitch () const { return getPitch( getGHorizontalDepth(), Flags::NoFlags ); }
inline DbU::Unit Configuration::getGVerticalPitch () const { return getPitch( getGVerticalDepth (), Flags::NoFlags ); }
inline size_t Configuration::getDVerticalDepth () const { return _ddepthv; }
inline const Layer* Configuration::getDVerticalLayer () const { return getRoutingLayer( getDVerticalDepth() ); }
inline DbU::Unit Configuration::getDVerticalWidth () const { return getWireWidth ( getDVerticalDepth() ); }
inline DbU::Unit Configuration::getDPVerticalWidth () const { return getPWireWidth ( getDVerticalDepth() ); }
inline DbU::Unit Configuration::getDVerticalPitch () const { return getPitch ( getDVerticalDepth(), Flags::NoFlags ); }
inline DbU::Unit Configuration::getDVerticalOffset () const { return getOffset ( getDVerticalDepth() ); }
inline size_t Configuration::getDHorizontalDepth () const { return _ddepthh; }
inline const Layer* Configuration::getDHorizontalLayer () const { return getRoutingLayer( getDHorizontalDepth() ); }
inline DbU::Unit Configuration::getDHorizontalWidth () const { return getWireWidth ( getDHorizontalDepth() ); }
inline DbU::Unit Configuration::getDPHorizontalWidth () const { return getPWireWidth ( getDHorizontalDepth() ); }
inline DbU::Unit Configuration::getDHorizontalPitch () const { return getPitch ( getDHorizontalDepth(), Flags::NoFlags ); }
inline DbU::Unit Configuration::getDHorizontalOffset () const { return getOffset ( getDHorizontalDepth() ); }
inline size_t Configuration::getDContactDepth () const { return _ddepthc; }
inline const Layer* Configuration::getDContactLayer () const { return getContactLayer( getDContactDepth() ); }
inline DbU::Unit Configuration::getDContactWidth () const { return getWireWidth ( getDContactDepth() ); }
inline DbU::Unit Configuration::getDContactPitch () const { return getPitch ( getDContactDepth(), Flags::NoFlags ); }
inline std::string Configuration::getDiodeName () const { return _diodeName; }
inline DbU::Unit Configuration::getAntennaGateMaxWL () const { return _antennaGateMaxWL; }
inline DbU::Unit Configuration::getAntennaDiodeMaxWL () const { return _antennaDiodeMaxWL; }
inline void Configuration::setRoutingStyle ( StyleFlags flags ) { _routingStyle = flags; }
inline void Configuration::resetRoutingStyle ( StyleFlags flags ) { _routingStyle &= ~flags; }
} // Anabatic namespace. } // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::Configuration); INSPECTOR_P_SUPPORT(Anabatic::Configuration);
#endif // ANABATIC_CONFIGURATION_H

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Constants.h<anabatic>" -*- // -*- mode: C++; explicit-buffer-name: "Constants.h<anabatic>" -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved // Copyright (c) UPMC 2016-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -14,14 +14,15 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_CONSTANTS_H #pragma once
#define ANABATIC_CONSTANTS_H
#include "hurricane/Flags.h" #include "hurricane/Flags.h"
namespace Anabatic { namespace Anabatic {
// -------------------------------------------------------------------
// Class : "Anabatic::Flags".
class Flags : public Hurricane::BaseFlags { class Flags : public Hurricane::BaseFlags {
public: public:
static const BaseFlags NoFlags ; // = 0; static const BaseFlags NoFlags ; // = 0;
@ -39,14 +40,27 @@ namespace Anabatic {
static const BaseFlags MatrixGCell ; // = (1 << 9); static const BaseFlags MatrixGCell ; // = (1 << 9);
static const BaseFlags IoPadGCell ; // = (1 << 10); static const BaseFlags IoPadGCell ; // = (1 << 10);
static const BaseFlags Saturated ; // = (1 << 11); static const BaseFlags Saturated ; // = (1 << 11);
static const BaseFlags StdCellRow ; // = (1 << 12);
static const BaseFlags ChannelRow ; // = (1 << 13);
static const BaseFlags HRailGCell ; // = (1 << 14);
static const BaseFlags VRailGCell ; // = (1 << 15);
static const BaseFlags GoStraight ; // = (1 << 16);
// Flags for Edge objects states only.
static const BaseFlags NullCapacity ; // = (1 << 5);
static const BaseFlags InfiniteCapacity ; // = (1 << 6);
// Flags for Anabatic objects states only. // Flags for Anabatic objects states only.
static const BaseFlags DemoMode ; // = (1 << 5); static const BaseFlags DemoMode ; // = (1 << 5);
static const BaseFlags WarnOnGCellOverload ; // = (1 << 6); static const BaseFlags WarnOnGCellOverload ; // = (1 << 6);
static const BaseFlags DestroyGCell ; // = (1 << 7); static const BaseFlags DestroyGCell ; // = (1 << 7);
static const BaseFlags DestroyBaseContact ; // = (1 << 8); static const BaseFlags DestroyBaseContact ; // = (1 << 8);
static const BaseFlags DestroyBaseSegment ; // = (1 << 9); static const BaseFlags DestroyBaseSegment ; // = (1 << 9);
static const BaseFlags DisableCanonize ; // = (1 << 10);
// Flags for NetDatas objects states only. // Flags for NetDatas objects states only.
static const BaseFlags GlobalRouted ; // = (1 << 5); static const BaseFlags GlobalFixed ; // = (1 << 5);
static const BaseFlags GlobalEstimated ; // = (1 << 6);
static const BaseFlags GlobalRouted ; // = (1 << 7);
static const BaseFlags DetailRouted ; // = (1 << 8);
static const BaseFlags ExcludeRoute ; // = (1 << 9);
// Masks. // Masks.
static const BaseFlags WestSide ; // = Horizontal|Target; static const BaseFlags WestSide ; // = Horizontal|Target;
static const BaseFlags EastSide ; // = Horizontal|Source; static const BaseFlags EastSide ; // = Horizontal|Source;
@ -56,7 +70,10 @@ namespace Anabatic {
static const BaseFlags EndsMask ; // = Source|Target; static const BaseFlags EndsMask ; // = Source|Target;
static const BaseFlags DirectionMask ; // = Horizontal|Vertical; static const BaseFlags DirectionMask ; // = Horizontal|Vertical;
static const BaseFlags DestroyMask ; // = DestroyGCell|DestroyBaseContact|DestroyBaseSegment; static const BaseFlags DestroyMask ; // = DestroyGCell|DestroyBaseContact|DestroyBaseSegment;
static const BaseFlags GCellTypeMask ; // = DeviceGCell|HChannelGCell|VChannelGCell|StrutGCell|MatrixGCell|IoPadGCell; static const BaseFlags GCellTypeMask ; // = DeviceGCell|HChannelGCell|VChannelGCell|StrutGCell|MatrixGCell|IoPadGCell|HRailGCell|VRailGCell;
static const BaseFlags RowGCellMask ; // = StdCellRow|ChannelRow;
static const BaseFlags AnalogGCellMask ; // = DeviceGCell|HChannelGCell|VChannelGCell|StrutGCell|HRailGCell|VRailGCell;
static const BaseFlags EdgeCapacityMask ; // = Horizontal|Vertical|NullCapacity|InfiniteCapacity ;
// Flags for functions arguments only. // Flags for functions arguments only.
static const BaseFlags Create ; // = (1 << 5); static const BaseFlags Create ; // = (1 << 5);
static const BaseFlags WithPerpands ; static const BaseFlags WithPerpands ;
@ -86,6 +103,14 @@ namespace Anabatic {
static const BaseFlags CheckLowDensity ; static const BaseFlags CheckLowDensity ;
static const BaseFlags CheckLowUpDensity ; static const BaseFlags CheckLowUpDensity ;
static const BaseFlags NoUpdate ; static const BaseFlags NoUpdate ;
static const BaseFlags NorthPath ;
static const BaseFlags UseNonPref ;
static const BaseFlags Force ;
static const BaseFlags LayerCapOnly ;
static const BaseFlags NoMinLength ;
static const BaseFlags NoSegExt ;
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& );
@ -100,6 +125,39 @@ namespace Anabatic {
Flags::Flags ( const Hurricane::BaseFlags& flags ) : BaseFlags(flags) { } Flags::Flags ( const Hurricane::BaseFlags& flags ) : BaseFlags(flags) { }
// -------------------------------------------------------------------
// Class : "Anabatic::StyleFlags".
class StyleFlags : public Hurricane::BaseFlags {
public:
static const BaseFlags NoStyle; // = 0;
static const BaseFlags HV ; // = (1 << 0);
static const BaseFlags VH ; // = (1 << 1);
static const BaseFlags OTH ; // = (1 << 2);
static const BaseFlags Channel; // = (1 << 3);
static const BaseFlags Hybrid ; // = (1 << 4);
public:
inline StyleFlags ( std::string );
inline StyleFlags ( uint64_t flags = NoStyle );
inline StyleFlags ( const Hurricane::BaseFlags& );
virtual ~StyleFlags ();
static StyleFlags toFlag ( std::string );
StyleFlags from ( std::string );
virtual std::string asString () const;
virtual std::string _getTypeName () const;
virtual std::string _getString () const;
};
StyleFlags::StyleFlags ( std::string textFlags ) : BaseFlags(NoStyle) { from(textFlags); }
StyleFlags::StyleFlags ( uint64_t flags ) : BaseFlags(flags) { }
StyleFlags::StyleFlags ( const Hurricane::BaseFlags& flags ) : BaseFlags(flags) { }
// -------------------------------------------------------------------
// Misc. enums.
enum FlagsMode { FlagsFunction = 1 enum FlagsMode { FlagsFunction = 1
}; };
@ -112,11 +170,12 @@ namespace Anabatic {
, EngineGutted = 6 , EngineGutted = 6
}; };
enum EngineAlgorithm { EngineLoadGrByNet = (1 << 0) enum EngineAlgorithm { EngineLoadGrByNet = (1 << 0)
, EngineLoadGrByGCell = (1 << 1) , EngineLoadGrByGCell = (1 << 1)
, EngineLayerAssignByLength = (1 << 2) , EngineLayerAssignByLength = (1 << 2)
, EngineLayerAssignByTrunk = (1 << 3) , EngineLayerAssignByTrunk = (1 << 3)
, EngineNoNetLayerAssign = (1 << 4) , EngineLayerAssignNoGlobalM2V = (1 << 4)
, EngineNoNetLayerAssign = (1 << 5)
}; };
@ -131,6 +190,4 @@ namespace Anabatic {
} // Anabatic namespace. } // Anabatic namespace.
INSPECTOR_PV_SUPPORT(Anabatic::Flags) INSPECTOR_PR_SUPPORT(Anabatic::Flags);
#endif // ANABATIC_CONSTANTS_H

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Dijkstra.h<anabatic>" -*- // -*- mode: C++; explicit-buffer-name: "Dijkstra.h<anabatic>" -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2016, All Rights Reserved // Copyright (c) UPMC 2016-2018, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_DIJKSTRA_H #pragma once
#define ANABATIC_DIJKSTRA_H
#include <set> #include <set>
#include <iomanip> #include <iomanip>
#include "hurricane/Observer.h" #include "hurricane/Observer.h"
@ -44,16 +42,17 @@ namespace Anabatic {
class IntervalC class IntervalC
{ {
public: public:
enum iFlag { None = 0 enum iFlag { None = 0
, iHorizontal = (1<<0) , iFHorizontal = (1<<0)
, iVertical = (1<<1) , iFVertical = (1<<1)
, iSet = (1<<2) , iSet = (1<<2)
}; };
public: public:
IntervalC(); IntervalC();
IntervalC(const IntervalC&); IntervalC(const IntervalC&);
IntervalC(IntervalC&); IntervalC(IntervalC&);
IntervalC( DbU::Unit, DbU::Unit, DbU::Unit );
~IntervalC(); ~IntervalC();
void set ( DbU::Unit, DbU::Unit, DbU::Unit ); void set ( DbU::Unit, DbU::Unit, DbU::Unit );
void setRange ( DbU::Unit, DbU::Unit ); void setRange ( DbU::Unit, DbU::Unit );
@ -83,8 +82,8 @@ namespace Anabatic {
DbU::Unit _axis; DbU::Unit _axis;
}; };
inline void IntervalC::setAsH () { _flags = ((_flags & ~(0x3)) | iHorizontal); } inline void IntervalC::setAsH () { _flags = ((_flags & ~(0x3)) | iFHorizontal); }
inline void IntervalC::setAsV () { _flags = ((_flags & ~(0x3)) | iVertical ); } inline void IntervalC::setAsV () { _flags = ((_flags & ~(0x3)) | iFVertical ); }
inline void IntervalC::setAxis ( DbU::Unit axis ) { _axis = axis; } inline void IntervalC::setAxis ( DbU::Unit axis ) { _axis = axis; }
inline DbU::Unit IntervalC::getAxis () const { return _axis; } inline DbU::Unit IntervalC::getAxis () const { return _axis; }
inline DbU::Unit IntervalC::getCenter() const { return getMin()+getMax(); } inline DbU::Unit IntervalC::getCenter() const { return getMin()+getMax(); }
@ -92,8 +91,8 @@ namespace Anabatic {
inline DbU::Unit IntervalC::getMax () const { return _max; } inline DbU::Unit IntervalC::getMax () const { return _max; }
inline void IntervalC::setiSet () { _flags |= iSet; } inline void IntervalC::setiSet () { _flags |= iSet; }
inline bool IntervalC::isiSet () const { return _flags & iSet; } inline bool IntervalC::isiSet () const { return _flags & iSet; }
inline bool IntervalC::isH () const { return _flags & iHorizontal; } inline bool IntervalC::isH () const { return _flags & iFHorizontal; }
inline bool IntervalC::isV () const { return _flags & iVertical ; } inline bool IntervalC::isV () const { return _flags & iFVertical ; }
inline void IntervalC::setFlags ( Flags flags ) { _flags = flags; } inline void IntervalC::setFlags ( Flags flags ) { _flags = flags; }
inline Flags IntervalC::getFlags () const { return _flags; } inline Flags IntervalC::getFlags () const { return _flags; }
@ -164,10 +163,13 @@ namespace Anabatic {
inline void GRAData::printInterv () const { _interv.print() ; } inline void GRAData::printInterv () const { _interv.print() ; }
inline void GRAData::printIntervfrom () const { _intervfrom.print(); } inline void GRAData::printIntervfrom () const { _intervfrom.print(); }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Anabatic::Vertex". // Class : "Anabatic::Vertex".
class Vertex { class Vertex {
public:
static inline std::string getValueString ( DbU::Unit );
public: public:
class CompareById { class CompareById {
public: public:
@ -185,84 +187,87 @@ namespace Anabatic {
, iHorizontal = (1<<7) , iHorizontal = (1<<7)
, iVertical = (1<<8) , iVertical = (1<<8)
, iSet = (1<<9) , iSet = (1<<9)
, Driver = (1<<10)
}; };
public: public:
static DbU::Unit unreached; static DbU::Unit unreached;
static DbU::Unit unreachable; static DbU::Unit unreachable;
public: public:
static void notify ( Vertex*, unsigned flags ); static void notify ( Vertex*, unsigned flags );
static inline Vertex* lookup ( GCell* );
public: public:
inline Vertex ( GCell* ); inline Vertex ( GCell* );
//inline Vertex ( size_t id ); //inline Vertex ( size_t id );
inline ~Vertex (); inline ~Vertex ();
inline bool hasDoneAllRps () const; inline bool isDriver () const;
inline Contact* hasGContact ( Net* ) const; inline bool isAnalog () const;
inline unsigned int getId () const; inline bool hasDoneAllRps () const;
inline GCell* getGCell () const; inline Contact* hasGContact ( Net* ) const;
inline AnabaticEngine* getAnabatic () const; inline unsigned int getId () const;
inline Contact* getGContact ( Net* ); inline GCell* getGCell () const;
bool hasValidStamp () const; inline Box getBoundingBox () const;
inline Point getCenter () const; inline Edges getEdges ( Flags sides=Flags::AllSides ) const;
inline DbU::Unit getDistance () const; inline AnabaticEngine* getAnabatic () const;
inline int getStamp () const; inline Contact* getGContact ( Net* );
inline int getBranchId () const; bool hasValidStamp () const;
inline int getConnexId () const; inline Point getCenter () const;
inline int getDegree () const; inline DbU::Unit getDistance () const;
inline int getRpCount () const; inline int getStamp () const;
inline Edge* getFrom () const; inline int getBranchId () const;
inline Vertex* getPredecessor () const; inline int getConnexId () const;
inline void setDistance ( DbU::Unit ); inline int getDegree () const;
inline void setStamp ( int ); inline int getRpCount () const;
inline void setConnexId ( int ); Edge* getFrom () const;
inline void setBranchId ( int ); inline Vertex* getPredecessor () const;
inline void setDegree ( int ); inline Vertex* getNeighbor ( Edge* ) const;
inline void incDegree ( int delta=1 ); inline void setDriver ( bool state );
inline void setRpCount ( int ); inline void setDistance ( DbU::Unit );
inline void incRpCount ( int delta=1 ); inline void setStamp ( int );
inline void setFrom ( Edge* ); inline void setConnexId ( int );
inline void add ( RoutingPad* ); inline void setBranchId ( int );
inline void clearRps (); inline void setDegree ( int );
inline Contact* breakGoThrough ( Net* ); inline void incDegree ( int delta=1 );
inline void setRpCount ( int );
//////////////////////////////////////// Analog inline void incRpCount ( int delta=1 );
inline bool isNorth ( const Vertex* ) const; inline void setFrom ( Edge* );
inline bool isSouth ( const Vertex* ) const; inline void add ( RoutingPad* );
inline bool isEast ( const Vertex* ) const; inline void clearRps ();
inline bool isWest ( const Vertex* ) const; inline Contact* breakGoThrough ( Net* );
inline bool isNRestricted () const; // Analog related methods.
inline bool isSRestricted () const; inline bool isNorth ( const Vertex* ) const;
inline bool isERestricted () const; inline bool isSouth ( const Vertex* ) const;
inline bool isWRestricted () const; inline bool isEast ( const Vertex* ) const;
inline bool hasRestrictions() const; inline bool isWest ( const Vertex* ) const;
inline bool isNRestricted () const;
inline void setRestricted (); inline bool isSRestricted () const;
inline void clearRestriction (); inline bool isERestricted () const;
inline void setNRestricted (); inline bool isWRestricted () const;
inline void setSRestricted (); inline bool hasRestrictions () const;
inline void setERestricted (); void setRestricted ();
inline void setWRestricted (); void clearRestriction ();
bool hasRP ( Net* ) const; inline void setNRestricted ();
bool hasVRP ( Net* ) const; inline void setSRestricted ();
bool hasHRP ( Net* ) const; inline void setERestricted ();
static bool isRestricted ( const Vertex* v1, const Vertex* v2, const Edge* e, DbU::Unit hpitch = 0, DbU::Unit vpitch = 0, Net* net = NULL); inline void setWRestricted ();
bool areSameSide ( const Vertex*, const Vertex* ) const; bool hasRP ( Net* ) const;
bool hasVRP ( Net* ) const;
inline bool isFromFrom2 () const; bool hasHRP ( Net* ) const;
inline bool isFrom2Mode () const; static bool isRestricted ( const Vertex* v1, const Vertex* v2, const Edge* e, DbU::Unit hpitch = 0, DbU::Unit vpitch = 0, Net* net = NULL);
inline bool isAxisTarget () const; bool areSameSide ( const Vertex*, const Vertex* ) const;
inline bool isiHorizontal() const; inline bool isFromFrom2 () const;
inline bool isiVertical () const; inline bool isFrom2Mode () const;
inline void setFlags ( uint32_t ); inline bool isAxisTarget () const;
inline void unsetFlags ( uint32_t ); inline bool isiHorizontal () const;
bool isH () const; inline bool isiVertical () const;
bool isV () const; inline void setFlags ( uint32_t );
inline void createAData (); inline void unsetFlags ( uint32_t );
//////////////////////////////////// bool isH () const;
bool isV () const;
inline void createAData ();
Point getStartPathPoint ( const Vertex* next ) const; Point getStartPathPoint ( const Vertex* next ) const;
Point getNextPathPoint ( Point, const Vertex* ) const; Point getNextPathPoint ( Point, const Vertex* ) const;
//////////////////////////////////////// GRDATA
void setIntervals ( Vertex* ); void setIntervals ( Vertex* );
inline bool hasAData () const;
bool isiSet () const; bool isiSet () const;
DbU::Unit getIAxis () const; DbU::Unit getIAxis () const;
DbU::Unit getIMax () const; DbU::Unit getIMax () const;
@ -277,7 +282,6 @@ namespace Anabatic {
void clearFrom2 (); void clearFrom2 ();
Edge* getFrom2 () const; Edge* getFrom2 () const;
void setFrom2 ( Edge* ); void setFrom2 ( Edge* );
void createIntervFrom2 ();
DbU::Unit getPIMax2 () const; DbU::Unit getPIMax2 () const;
DbU::Unit getPIMin2 () const; DbU::Unit getPIMin2 () const;
DbU::Unit getPIAxis2 () const; DbU::Unit getPIAxis2 () const;
@ -289,10 +293,10 @@ namespace Anabatic {
GCell* getGPrev ( uint32_t criteria=0 ) const; GCell* getGPrev ( uint32_t criteria=0 ) const;
// Inspector support. // Inspector support.
string _getString () const; string _getString () const;
private: private:
Vertex ( const Vertex& ); Vertex ( const Vertex& );
Vertex& operator= ( const Vertex& ); Vertex& operator= ( const Vertex& );
private: private:
size_t _id; size_t _id;
GCell* _gcell; GCell* _gcell;
@ -328,7 +332,12 @@ namespace Anabatic {
} }
inline Vertex* Vertex::lookup ( GCell* gcell ) { return gcell->getObserver<Vertex>(GCell::Observable::Vertex); }
inline Vertex::~Vertex () { _gcell->setObserver( GCell::Observable::Vertex, NULL ); } inline Vertex::~Vertex () { _gcell->setObserver( GCell::Observable::Vertex, NULL ); }
inline bool Vertex::isDriver () const { return _flags & Driver; }
inline bool Vertex::isAnalog () const { return _gcell->isAnalog(); }
inline Box Vertex::getBoundingBox () const { return _gcell->getBoundingBox(); }
inline Edges Vertex::getEdges ( Flags sides ) const { return _gcell->getEdges(sides); }
inline Contact* Vertex::hasGContact ( Net* net ) const { return _gcell->hasGContact(net); } inline Contact* Vertex::hasGContact ( Net* net ) const { return _gcell->hasGContact(net); }
inline unsigned int Vertex::getId () const { return _id; } inline unsigned int Vertex::getId () const { return _id; }
inline GCell* Vertex::getGCell () const { return _gcell; } inline GCell* Vertex::getGCell () const { return _gcell; }
@ -341,7 +350,7 @@ namespace Anabatic {
inline int Vertex::getBranchId () const { return hasValidStamp() ? _branchId : 0; } inline int Vertex::getBranchId () const { return hasValidStamp() ? _branchId : 0; }
inline int Vertex::getDegree () const { return hasValidStamp() ? _degree : 0; } inline int Vertex::getDegree () const { return hasValidStamp() ? _degree : 0; }
inline int Vertex::getRpCount () const { return hasValidStamp() ? _rpCount : 0; } inline int Vertex::getRpCount () const { return hasValidStamp() ? _rpCount : 0; }
inline Edge* Vertex::getFrom () const { return _from; } //inline Edge* Vertex::getFrom () const { return _from; }
inline void Vertex::setDistance ( DbU::Unit distance ) { _distance=distance; } inline void Vertex::setDistance ( DbU::Unit distance ) { _distance=distance; }
inline void Vertex::setFrom ( Edge* from ) { _from=from; } inline void Vertex::setFrom ( Edge* from ) { _from=from; }
inline void Vertex::setStamp ( int stamp ) { _stamp=stamp; } inline void Vertex::setStamp ( int stamp ) { _stamp=stamp; }
@ -356,6 +365,18 @@ namespace Anabatic {
inline Vertex* Vertex::getPredecessor () const inline Vertex* Vertex::getPredecessor () const
{ return (hasValidStamp() and _from) ? _from->getOpposite(_gcell)->getObserver<Vertex>(GCell::Observable::Vertex) : NULL; } { return (hasValidStamp() and _from) ? _from->getOpposite(_gcell)->getObserver<Vertex>(GCell::Observable::Vertex) : NULL; }
inline Vertex* Vertex::getNeighbor ( Edge* edge ) const
{
GCell* gcell = edge->getOpposite( getGCell() );
return (gcell) ? gcell->getObserver<Vertex>(GCell::Observable::Vertex) : NULL;
}
inline void Vertex::setDriver ( bool state )
{
if (state) _flags |= Driver;
else _flags &= ~Driver;
}
inline bool Vertex::CompareById::operator() ( const Vertex* lhs, const Vertex* rhs ) const inline bool Vertex::CompareById::operator() ( const Vertex* lhs, const Vertex* rhs ) const
{ return lhs->getId() < rhs->getId(); } { return lhs->getId() < rhs->getId(); }
@ -372,8 +393,9 @@ namespace Anabatic {
inline bool Vertex::isWRestricted () const { return (_flags & WRestricted); } inline bool Vertex::isWRestricted () const { return (_flags & WRestricted); }
inline bool Vertex::hasRestrictions () const { return ( isNRestricted()||isSRestricted()||isERestricted()||isWRestricted()) ; } inline bool Vertex::hasRestrictions () const { return ( isNRestricted()||isSRestricted()||isERestricted()||isWRestricted()) ; }
inline void Vertex::setRestricted () { _flags |= 0xF; } inline bool Vertex::hasAData () const { return (_adata !=NULL)? true : false; }
inline void Vertex::clearRestriction () { _flags &= ~(0xF); } //inline void Vertex::setRestricted () { _flags |= 0xF; }
//inline void Vertex::clearRestriction () { _flags &= ~(0xF); }
inline void Vertex::setNRestricted () { _flags |= NRestricted; } inline void Vertex::setNRestricted () { _flags |= NRestricted; }
inline void Vertex::setSRestricted () { _flags |= SRestricted; } inline void Vertex::setSRestricted () { _flags |= SRestricted; }
inline void Vertex::setERestricted () { _flags |= ERestricted; } inline void Vertex::setERestricted () { _flags |= ERestricted; }
@ -387,45 +409,63 @@ namespace Anabatic {
inline void Vertex::setFlags ( uint32_t mask ) { _flags |= mask ; } inline void Vertex::setFlags ( uint32_t mask ) { _flags |= mask ; }
inline void Vertex::unsetFlags ( uint32_t mask ) { _flags &= ~mask; } inline void Vertex::unsetFlags ( uint32_t mask ) { _flags &= ~mask; }
inline std::string Vertex::getValueString ( DbU::Unit distance )
{
if (distance == Vertex::unreachable) return "unreachable";
if (distance == Vertex::unreached ) return "unreached";
return DbU::getValueString( distance );
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Anabatic::PriorityQueue". // Class : "Anabatic::PriorityQueue".
class PriorityQueue { class PriorityQueue {
public: public:
inline PriorityQueue (); inline PriorityQueue ();
inline ~PriorityQueue (); inline ~PriorityQueue ();
inline bool empty () const; inline bool empty () const;
inline size_t size () const; inline size_t size () const;
inline void push ( Vertex* ); inline void push ( Vertex* );
inline void erase ( Vertex* ); inline void erase ( Vertex* );
inline Vertex* top (); inline Vertex* top ();
inline void pop (); inline void pop ();
inline void clear (); inline void clear ();
inline void dump () const; inline void dump () const;
inline void setAttractor ( const Point& );
inline const Point& getAttractor () const;
inline bool hasAttractor () const;
private: private:
class CompareByDistance { class CompareByDistance {
public: public:
inline bool operator() ( const Vertex* lhs, const Vertex* rhs ); inline CompareByDistance ();
bool operator() ( const Vertex* lhs, const Vertex* rhs ) const;
static inline void setQueue ( PriorityQueue* );
private:
static PriorityQueue* _pqueue;
}; };
private: private:
bool _hasAttractor;
Point _attractor;
multiset<Vertex*,CompareByDistance> _queue; multiset<Vertex*,CompareByDistance> _queue;
}; };
inline bool PriorityQueue::CompareByDistance::operator() ( const Vertex* lhs, const Vertex* rhs ) inline PriorityQueue::CompareByDistance::CompareByDistance () { }
{
if (lhs->getDistance() == rhs->getDistance()) return lhs->getBranchId() > rhs->getBranchId(); inline void PriorityQueue::CompareByDistance::setQueue ( PriorityQueue* pqueue ) { _pqueue = pqueue; }
return lhs->getDistance() < rhs->getDistance();
}
inline PriorityQueue::PriorityQueue () : _queue() { } inline PriorityQueue::PriorityQueue () : _hasAttractor(false), _attractor(), _queue() { PriorityQueue::CompareByDistance::setQueue(this); }
inline PriorityQueue::~PriorityQueue () { } inline PriorityQueue::~PriorityQueue () { }
inline bool PriorityQueue::empty () const { return _queue.empty(); } inline bool PriorityQueue::empty () const { return _queue.empty(); }
inline size_t PriorityQueue::size () const { return _queue.size(); } inline size_t PriorityQueue::size () const { return _queue.size(); }
inline void PriorityQueue::push ( Vertex* v ) { _queue.insert(v); } inline void PriorityQueue::push ( Vertex* v ) { _queue.insert(v); }
inline Vertex* PriorityQueue::top () { return _queue.empty() ? NULL : *_queue.begin(); } inline Vertex* PriorityQueue::top () { return _queue.empty() ? NULL : *_queue.begin(); }
inline void PriorityQueue::clear () { _queue.clear(); } inline void PriorityQueue::clear () { _queue.clear(); _hasAttractor=false; }
inline void PriorityQueue::setAttractor ( const Point& p ) { _attractor=p; _hasAttractor=true; }
inline bool PriorityQueue::hasAttractor () const { return _hasAttractor; }
inline const Point& PriorityQueue::getAttractor () const { return _attractor; }
inline void PriorityQueue::pop () inline void PriorityQueue::pop ()
{ {
@ -475,51 +515,54 @@ namespace Anabatic {
public: public:
typedef std::function<DbU::Unit(const Vertex*,const Vertex*,const Edge*)> distance_t; typedef std::function<DbU::Unit(const Vertex*,const Vertex*,const Edge*)> distance_t;
public: public:
Dijkstra ( AnabaticEngine* ); Dijkstra ( AnabaticEngine* );
~Dijkstra (); ~Dijkstra ();
public: public:
inline bool isBipoint () const; inline bool isBipoint () const;
inline bool isSourceVertex ( Vertex* ) const; inline bool isSourceVertex ( Vertex* ) const;
inline bool isTargetVertex ( Vertex* ) const; inline Net* getNet () const;
inline DbU::Unit getSearchAreaHalo () const; inline bool isTargetVertex ( Vertex* ) const;
DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getSearchAreaHalo () const;
template<typename DistanceT> template<typename DistanceT>
inline DistanceT* setDistance ( DistanceT ); inline DistanceT* setDistance ( DistanceT );
inline void setSearchAreaHalo ( DbU::Unit ); inline void setSearchAreaHalo ( DbU::Unit );
void load ( Net* net ); void load ( Net* net );
void run ( Mode mode=Mode::Standart ); void loadFixedGlobal ( Net* net );
void run ( Mode mode=Mode::Standart );
inline const VertexSet& getSources () const;
private: private:
Dijkstra ( const Dijkstra& ); Dijkstra ( const Dijkstra& );
Dijkstra& operator= ( const Dijkstra& ); Dijkstra& operator= ( const Dijkstra& );
static DbU::Unit _distance ( const Vertex*, const Vertex*, const Edge* ); static DbU::Unit _distance ( const Vertex*, const Vertex*, const Edge* );
Point _getPonderedPoint () const; Point _getPonderedPoint () const;
void _cleanup (); void _cleanup ();
bool _propagate ( Flags enabledSides ); bool _propagate ( Flags enabledSides );
void _traceback ( Vertex* ); void _traceback ( Vertex* );
void _materialize (); void _materialize ();
void _selectFirstSource (); void _selectFirstSource ();
void _toSources ( Vertex*, int connexId ); void _toSources ( Vertex*, int connexId );
void _getConnecteds ( Vertex*, VertexSet& ); void _getConnecteds ( Vertex*, VertexSet& );
void _checkEdges () const; void _checkEdges () const;
void _createSelfSymSeg ( Segment* ); void _createSelfSymSeg ( Segment* );
inline void setAxisTarget (); inline void setAxisTarget ();
inline bool needAxisTarget () const; inline bool needAxisTarget () const;
inline void setFlags ( Flags ); inline void setFlags ( Flags );
inline void unsetFlags ( Flags ); inline void unsetFlags ( Flags );
void setAxisTargets (); void setAxisTargets ();
void unsetAxisTargets (); void unsetAxisTargets ();
bool _attachSymContactsHook ( RoutingPad* );
void _limitSymSearchArea ( RoutingPad* rp );
void _setSourcesGRAData ( Vertex*, RoutingPad*);
bool _checkFrom2 ( Edge*, Vertex* );
bool _isDistance2Shorter ( DbU::Unit&, Vertex*, Vertex*, Edge* );
void _pushEqualDistance ( DbU::Unit, bool, Vertex*, Vertex*, Edge* );
void _updateGRAData ( Vertex*, bool, Vertex* );
void _initiateUpdateIntervals ( Vertex* );
bool _updateIntervals ( bool&, Vertex*, bool&, int&, Edge* );
void _updateRealOccupancy ( Vertex* );
bool _attachSymContactsHook ( RoutingPad* );
void _limitSymSearchArea ( RoutingPad* rp );
void _setSourcesGRAData ( Vertex*, RoutingPad*);
bool _checkFrom2 ( Edge*, Vertex* );
bool _isDistance2Shorter ( DbU::Unit&, Vertex*, Vertex*, Edge* );
void _pushEqualDistance ( DbU::Unit, bool, Vertex*, Vertex*, Edge* );
void _updateGRAData ( Vertex*, bool, Vertex* );
void _initiateUpdateIntervals ( Vertex* );
bool _updateIntervals ( bool&, Vertex*, bool&, int&, Edge* );
void _updateRealOccupancy ( Vertex* );
private: private:
AnabaticEngine* _anabatic; AnabaticEngine* _anabatic;
vector<Vertex*> _vertexes; vector<Vertex*> _vertexes;
@ -543,6 +586,7 @@ namespace Anabatic {
inline bool Dijkstra::isBipoint () const { return _net and (_targets.size()+_sources.size() == 2); } inline bool Dijkstra::isBipoint () const { return _net and (_targets.size()+_sources.size() == 2); }
inline bool Dijkstra::isSourceVertex ( Vertex* v ) const { return (_sources.find(v) != _sources.end()); } inline bool Dijkstra::isSourceVertex ( Vertex* v ) const { return (_sources.find(v) != _sources.end()); }
inline bool Dijkstra::isTargetVertex ( Vertex* v ) const { return (_targets.find(v) != _targets.end()); } inline bool Dijkstra::isTargetVertex ( Vertex* v ) const { return (_targets.find(v) != _targets.end()); }
inline Net* Dijkstra::getNet () const { return _net; }
inline DbU::Unit Dijkstra::getSearchAreaHalo () const { return _searchAreaHalo; } inline DbU::Unit Dijkstra::getSearchAreaHalo () const { return _searchAreaHalo; }
inline void Dijkstra::setSearchAreaHalo ( DbU::Unit halo ) { _searchAreaHalo = halo; } inline void Dijkstra::setSearchAreaHalo ( DbU::Unit halo ) { _searchAreaHalo = halo; }
@ -552,12 +596,11 @@ namespace Anabatic {
inline void Dijkstra::setFlags ( Flags mask ) { _flags |= mask; } inline void Dijkstra::setFlags ( Flags mask ) { _flags |= mask; }
inline bool Dijkstra::needAxisTarget () const { return (_flags & Mode::AxisTarget); } inline bool Dijkstra::needAxisTarget () const { return (_flags & Mode::AxisTarget); }
inline void Dijkstra::unsetFlags ( Flags mask ) { _flags &= ~mask; } inline void Dijkstra::unsetFlags ( Flags mask ) { _flags &= ~mask; }
inline const VertexSet& Dijkstra::getSources () const { return _sources; }
} // Anabatic namespace. } // Anabatic namespace.
GETSTRING_POINTER_SUPPORT(Anabatic::Vertex); GETSTRING_POINTER_SUPPORT(Anabatic::Vertex);
IOSTREAM_POINTER_SUPPORT(Anabatic::Vertex); IOSTREAM_POINTER_SUPPORT(Anabatic::Vertex);
INSPECTOR_PV_SUPPORT(Anabatic::Dijkstra::Mode); INSPECTOR_PR_SUPPORT(Anabatic::Dijkstra::Mode);
#endif // ANABATIC_DIJKSTRA_H

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