Compare commits

..

592 Commits

Author SHA1 Message Date
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
7351 changed files with 1558184 additions and 66978 deletions

6
.gitignore vendored
View File

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

View File

@ -1,15 +1,16 @@
UNAME_S = $(shell uname -s)
UNAME_R = $(shell uname -r)
UNAME_S = $(shell uname -s)
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 =
ifeq ($(UNAME_S),Linux)
ifneq ($(findstring .el6.,$(UNAME_R)),)
DEVTOOLSET_OPTION = --devtoolset-2
ifneq ($(findstring .el7.,$(UNAME_R)),)
DEVTOOLSET_OPTION = --devtoolset=$(DEVTOOLSET_VERSION)
endif
ifneq ($(findstring .slsoc6.,$(UNAME_R)),)
DEVTOOLSET_OPTION = --devtoolset-2
DEVTOOLSET_OPTION = --devtoolset=$(DEVTOOLSET_VERSION)
endif
endif
@ -56,7 +57,6 @@ 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="-j1 install" --doc
@echo ""; \
echo "============================================================================"; \
echo "Coriolis has been successfully built"; \

View File

@ -5,20 +5,19 @@
Coriolis README
===============
Coriolis is a free database, placement tool and routing tool for VLSI designs.
Coriolis is a free database, placement tool and routing tool for VLSI design.
Purpose
=======
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
provided.
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
@ -26,14 +25,14 @@ Documentation
The complete documentation is available here, both in pdf & html:
./documentation/_build/html/index.html
./documentation/output/html
./documentation/UsersGuide/UsersGuide.pdf
The documentation of the latest *stable* version is also
available online. It may be quite outdated from the *devel*
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
@ -85,8 +84,8 @@ The Coriolis main interface can be launched with the command: ::
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 UNIX environment, then lauch ``cgt`` (or *any* command, with the
The ``coriolis`` script detects its location and setups the UNIX
environment appropriately, then lauches ``cgt`` (or *any* command, with the
``--run=<COMMAND>`` option).
Conversely, you can setup the current shell environement for Coriolis by

View File

@ -3,6 +3,8 @@
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
project(ANABATIC)
set(ignoreVariables "${BUILD_DOC} ${CMAKE_INSTALL_DIR}")
option(BUILD_DOC "Build the documentation (doxygen)" OFF)
option(CHECK_DATABASE "Run database in full check mode (very slow)" OFF)
@ -13,25 +15,21 @@
setup_project_paths(CORIOLIS)
set_cmake_policies()
set_lib_link_mode()
setup_boost()
setup_qt()
find_package(PythonLibs 2 REQUIRED)
find_package(PythonSitePackages REQUIRED)
find_package(FLUTE REQUIRED)
find_package(VLSISAPD REQUIRED)
find_package(HURRICANE REQUIRED)
find_package(CORIOLIS REQUIRED)
find_package(ETESIAN REQUIRED)
find_package(Doxygen)
add_subdirectory(src)
add_subdirectory(cmake_modules)
#if(BUILD_DOC)
# find_package(Doxygen)
# if(DOXYGEN_FOUND)
# add_subdirectory(doc)
# endif()
#endif()
#add_subdirectory(doc)
if(CHECK_DATABASE)
add_definitions(-DCHECK_DATABASE)

View File

@ -26,7 +26,7 @@ IF(UNIX)
FIND_LIBRARY(ANABATIC_LIBRARY_PATH
NAMES anabatic
PATHS ${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES lib${LIB_SUFFIX}
PATH_SUFFIXES lib64 lib
# Help the user find it if we cannot.
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++ -*-
//
// 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 |
@ -110,7 +110,7 @@ namespace Anabatic {
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;
@ -178,6 +178,7 @@ namespace Anabatic {
AutoHorizontal* AutoContact::getHorizontal2 () const { return NULL; }
AutoVertical* AutoContact::getVertical1 () 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
@ -198,6 +199,20 @@ namespace Anabatic {
}
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) );
}
void AutoContact::getLengths ( DbU::Unit* lengths, AutoSegment::DepthLengthSet& processeds )
{
DbU::Unit hSideLength = getGCell()->getSide( Flags::Horizontal ).getSize();
@ -212,14 +227,17 @@ namespace Anabatic {
size_t depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer());
DbU::Unit length;
if (segment->isLocal()) {
length = segment->getLength();
length = segment->getAnchoredLength();
lengths[depth] += length;
DbU::Unit sideLength = (segment->isHorizontal()) ? hSideLength : vSideLength;
if ( not segment->isUnbound() and (abs(length) > sideLength) )
cerr << Error("Suspicious length:%.2f of %s."
,DbU::getValueString(length).c_str()
,getString(segment).c_str()) << endl;
cerr << Error( "AutoContact::getLength(): Suspicious length %s (> %s) of %s.\n"
" (on: %s)"
, DbU::getValueString(length).c_str()
, DbU::getValueString(sideLength).c_str()
, getString(segment).c_str()
, getString(this).c_str()) << endl;
} else {
if (segment->isHorizontal()) {
if (isSourceHook)
@ -274,10 +292,11 @@ namespace Anabatic {
void AutoContact::invalidate ( Flags flags )
{
if (flags & Flags::Topology ) setFlags( CntInvalidatedCache );
if (not isInvalidated()) {
cdebug_log(145,1) << "AutoContact::invalidate() - " << this << endl;
cdebug_log(145,0) << "flags:" << flags.asString(FlagsFunction) << endl;
setFlags( CntInvalidated );
if (flags & Flags::Topology ) setFlags( CntInvalidatedCache );
Session::invalidate( this );
_invalidate( flags );
@ -455,11 +474,13 @@ namespace Anabatic {
void AutoContact::setConstraintBox ( const Box& box )
{
cdebug_log(149,0) << "setConstraintBox() " << this << " " << getConstraintBox()
<< " from:" << box << endl;
setCBXMin ( box.getXMin() );
setCBXMax ( box.getXMax() );
setCBYMin ( box.getYMin() );
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;
}
@ -550,6 +571,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 = NULL;
@ -627,6 +672,7 @@ namespace Anabatic {
//s.insert( 4, getString(_id) );
s.insert( s.size()-1, (isFixed ())?" F":" -" );
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, (isVTee ())? "v": "-" );
s.insert( s.size()-1, (isInvalidated ())? "i": "-" );

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -91,8 +91,11 @@ namespace Anabatic {
}
AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* ) const
{ return NULL; }
AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* from ) const
{
if ( (from == _horizontal1) or (from == _horizontal2) ) return _vertical1;
return NULL;
}
AutoSegment* AutoContactHTee::getSegment ( unsigned int index ) const
@ -115,14 +118,15 @@ namespace Anabatic {
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->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 (_horizontal2) _horizontal2->invalidate( flags );
if (_vertical1 ) _vertical1 ->invalidate();
@ -196,7 +200,7 @@ namespace Anabatic {
void AutoContactHTee::updateCache ()
{
DebugSession::open( getNet(), 140, 150 );
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
@ -245,7 +249,7 @@ namespace Anabatic {
void AutoContactHTee::updateGeometry ()
{
DebugSession::open( getNet(), 140, 150 );
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
@ -273,7 +277,7 @@ namespace Anabatic {
void AutoContactHTee::updateTopology ()
{
DebugSession::open( getNet(), 140, 150 );
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
@ -305,10 +309,10 @@ namespace Anabatic {
if (depthH1 == depthH2) {
// Dogleg on the vertical.
switch ( delta ) {
case 0: setLayer( rg->getRoutingLayer(minDepth) ); break;
case 1: setLayer( rg->getContactLayer(minDepth) ); break;
case 0:
case 1: setLayerAndWidth( delta, minDepth ); break;
default:
setLayer( rg->getContactLayer( depthH1 + ((depthH1==minDepth)?0:-1) ) );
setLayerAndWidth( delta, depthH1 + ((depthH1==minDepth)?0:-1) );
_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
break;
}
@ -318,12 +322,12 @@ namespace Anabatic {
int deltaH2 = (int)depthH2 - (int)depthV1;
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->makeDogleg(this);
cdebug_log(145,0) << "New h1:" << _horizontal1 << endl;
} else {
setLayer( rg->getContactLayer( depthH1 + ((depthH1<depthV1)?0:-1) ) );
setLayerAndWidth( 2, depthH1 + ((depthH1<depthV1)?0:-1) );
//_horizontal2 = static_cast<AutoHorizontal*>( _horizontal2->makeDogleg(this) );
_horizontal2->makeDogleg(this);
cdebug_log(145,0) << "New h2:" << _horizontal2 << endl;

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -29,6 +29,7 @@
#include "hurricane/RoutingPad.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Pin.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactTerminal.h"
@ -46,6 +47,8 @@ namespace Anabatic {
using Hurricane::DebugSession;
using Hurricane::Transformation;
using Hurricane::Entity;
using Hurricane::Occurrence;
using Hurricane::Pin;
// -------------------------------------------------------------------
@ -60,7 +63,7 @@ namespace Anabatic {
, 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;
anchor->getBodyHook()->detach();
@ -85,7 +88,7 @@ namespace Anabatic {
, 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;
_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
{ return NULL; }
@ -171,7 +181,34 @@ namespace Anabatic {
if (component == NULL) {
cerr << Error( "%s is not anchored.", getString(this).c_str() ) << endl;
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;
@ -195,6 +232,42 @@ namespace Anabatic {
xMin = xMax
= vertical->getTargetPosition().getX();
} 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();
Transformation transf = routingPad->getOccurrence().getPath().getTransformation();
cdebug_log(145,0) << "Anchor: " << routingPad << endl;
@ -238,6 +311,7 @@ namespace Anabatic {
yMin = yMax = routingPad->getPosition().getY();
break;
}
#endif
} else {
xMin = xMax = component->getPosition().getX();
yMin = yMax = component->getPosition().getY();
@ -255,7 +329,7 @@ namespace Anabatic {
cdebug_log(145,0) << "| Using (y): "
<< DbU::getValueString(bb.getYMin()) << " "
<< DbU::getValueString(bb.getYMax()) << endl;
<< DbU::getValueString(bb.getYMax()) << " " << bb << endl;
cdebug_tabw(145,-1);
return bb;
@ -264,36 +338,57 @@ namespace Anabatic {
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 )
{
if (_segment == segment) {
//_segment->unsetFlags( AutoSegment::SegAxisSet );
_segment = NULL;
setFlags( CntInvalidatedCache );
unsetFlags( CntDrag );
}
}
void AutoContactTerminal::cacheAttach ( AutoSegment* segment )
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::cacheAttach() " << this << endl;
if (_segment) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" cache has not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
cdebug_tabw(145,-1);
DebugSession::close();
return;
}
_segment = segment;
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 ()
{
DebugSession::open( getNet(), 140, 150 );
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
@ -316,8 +411,16 @@ namespace Anabatic {
}
if (horizontals[0] != NULL ) {
_segment = Session::lookup( horizontals[0] );
if (getFlags() & CntOnHorizontal) {
setFlags( CntDrag );
_segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegFixedAxis );
}
} else {
_segment = Session::lookup( verticals[0] );
if (getFlags() & CntOnVertical) {
setFlags( CntDrag );
_segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegFixedAxis );
}
}
if (_segment == NULL) {
ostringstream os;
@ -344,7 +447,7 @@ namespace Anabatic {
void AutoContactTerminal::updateGeometry ()
{
DebugSession::open( getNet(), 140, 150 );
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
@ -396,9 +499,24 @@ namespace Anabatic {
cdebug_log(145,0) << "Contact for wide segment." << endl;
}
if (canDrag()) {
AutoContact* opposite = _segment->getOppositeAnchor(this);
AutoSegment* perpandicular = opposite->getPerpandicular( _segment );
if (perpandicular) {
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)) {
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) << ".";
Flags flags = Flags::NoFlags;
@ -416,7 +534,7 @@ namespace Anabatic {
void AutoContactTerminal::updateTopology ()
{
DebugSession::open( getNet(), 140, 150 );
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
@ -444,8 +562,8 @@ namespace Anabatic {
cdebug_log(145,0) << "Update seg: " << _segment << endl;
delta = abssub( anchorDepth, rg->getLayerDepth( _segment->getLayer() ) );
}
else if (delta == 0) setLayer( rg->getRoutingLayer(anchorDepth) );
else if (delta == 1) setLayer( rg->getContactLayer(std::min(anchorDepth,segmentDepth)) );
else if (delta == 0) setLayerAndWidth( delta, anchorDepth );
else if (delta == 1) setLayerAndWidth( delta, std::min(anchorDepth,segmentDepth) );
}
_segment->invalidate( this );

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -88,8 +88,17 @@ namespace Anabatic {
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 == _vertical1 ) return _horizontal1;
cdebug_log(149,0) << _getTypeName() << "::getPerpandicular() " << this
<< " to:" << reference << " failed." << endl;
return NULL;
}
@ -110,13 +119,16 @@ namespace Anabatic {
void AutoContactTurn::_invalidate ( Flags flags )
{
if (_horizontal1) _horizontal1->invalidate();
if (_vertical1 ) _vertical1 ->invalidate();
if (_horizontal1) _horizontal1->invalidate( flags|Flags::Propagate );
if (_vertical1 ) _vertical1 ->invalidate( flags|Flags::Propagate );
}
void AutoContactTurn::cacheDetach ( AutoSegment* segment )
{
cdebug_log(149,0) << _getTypeName() << "::cacheDetach() " << this
<< " from:" << segment << endl;
if (segment == _horizontal1) _horizontal1 = NULL;
else if (segment == _vertical1) _vertical1 = NULL;
else return;
@ -127,6 +139,9 @@ namespace Anabatic {
void AutoContactTurn::cacheAttach ( AutoSegment* segment )
{
cdebug_log(149,0) << _getTypeName() << "::cacheAttach() " << this
<< " to:" << segment << endl;
if (segment->getDirection() == Flags::Horizontal) {
if (_horizontal1) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
@ -154,7 +169,7 @@ namespace Anabatic {
void AutoContactTurn::updateCache ()
{
DebugSession::open( getNet(), 140, 150 );
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
@ -195,7 +210,7 @@ namespace Anabatic {
void AutoContactTurn::updateGeometry ()
{
DebugSession::open( getNet(), 140, 150 );
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
@ -223,7 +238,7 @@ namespace Anabatic {
void AutoContactTurn::updateTopology ()
{
DebugSession::open ( getNet(), 140, 150 );
DebugSession::open ( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
@ -239,7 +254,7 @@ namespace Anabatic {
RoutingGauge* rg = Session::getRoutingGauge();
size_t depthH1 = rg->getLayerDepth( getHorizontal1()->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 );
unsetFlags( CntWeakTerminal );
@ -247,22 +262,23 @@ namespace Anabatic {
showTopologyError( "Sheared Turn, layer delta exceed 3." );
setFlags( CntBadTopology );
} else {
if (delta == 3) {
if (delta > 1) {
if (_horizontal1->isInvalidatedLayer()) {
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
_horizontal1->makeDogleg(this);
depthH1 = rg->getLayerDepth( _horizontal1->getLayer() );
cdebug_log(145,0) << "Update h1: " << _horizontal1 << endl;
} else /*if (_vertical1->isInvalidatedLayer())*/ {
//_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
_vertical1->makeDogleg(this);
depthV1 = rg->getLayerDepth( _vertical1->getLayer() );
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 );

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -91,8 +91,11 @@ namespace Anabatic {
}
AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* ) const
{ return NULL; }
AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* from ) const
{
if ( (from == _vertical1) or (from == _vertical2) ) return _horizontal1;
return NULL;
}
AutoSegment* AutoContactVTee::getSegment ( unsigned int index ) const
@ -111,12 +114,12 @@ namespace Anabatic {
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->isInvalidated() xor _vertical2->isInvalidated())
flags = Flags::NoFlags;
flags.reset( Flags::NoFlags );
}
if (_vertical1 ) _vertical1 ->invalidate( flags );
@ -166,7 +169,7 @@ namespace Anabatic {
void AutoContactVTee::updateCache ()
{
DebugSession::open( getNet(), 140, 150 );
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateCache() " << this << endl;
@ -212,7 +215,7 @@ namespace Anabatic {
void AutoContactVTee::updateGeometry ()
{
DebugSession::open( getNet(), 140, 150 );
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateGeometry() " << this << endl;
@ -240,7 +243,7 @@ namespace Anabatic {
void AutoContactVTee::updateTopology ()
{
DebugSession::open ( getNet(), 140, 150 );
DebugSession::open ( getNet(), 145, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateTopology() " << this << endl;
@ -275,11 +278,11 @@ namespace Anabatic {
cdebug_log(145,0) << "depthV1 == depthV2 (" << depthV1 << ")" << endl;
// Dogleg on the horizontal.
switch ( delta ) {
case 0: setLayer( rg->getRoutingLayer(minDepth) ); break;
case 1: setLayer( rg->getContactLayer(minDepth) ); break;
case 0:
case 1: setLayerAndWidth( delta, minDepth ); break;
default:
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) );
break;
}
@ -289,11 +292,11 @@ namespace Anabatic {
int deltaV2 = (int)depthV2 - (int)depthH1;
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->makeDogleg(this);
} else {
setLayer( rg->getContactLayer( depthV1 + ((depthV1<depthH1)?0:-1) ) );
setLayerAndWidth( 2, depthV1 + ((depthV1<depthH1)?0:-1) );
//_vertical2 = static_cast<AutoVertical*>( _vertical2->makeDogleg(this) );
_vertical2->makeDogleg(this);
}

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -18,6 +18,7 @@
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/DebugSession.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/RoutingPad.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/Configuration.h"
@ -35,6 +36,7 @@ namespace Anabatic {
using Hurricane::Error;
using Hurricane::Bug;
using Hurricane::DebugSession;
using Hurricane::ViaLayer;
using Hurricane::RoutingPad;
@ -45,8 +47,8 @@ namespace Anabatic {
Segment* AutoHorizontal::base () { return _horizontal; }
Segment* AutoHorizontal::base () const { return _horizontal; }
Horizontal* AutoHorizontal::getHorizontal () { return _horizontal; }
DbU::Unit AutoHorizontal::getSourceU () const { return _horizontal->getSourceX(); }
DbU::Unit AutoHorizontal::getTargetU () const { return _horizontal->getTargetX(); }
DbU::Unit AutoHorizontal::getSourceU () const { return _horizontal->getSource()->getX(); }
DbU::Unit AutoHorizontal::getTargetU () const { return _horizontal->getTarget()->getX(); }
DbU::Unit AutoHorizontal::getDuSource () const { return _horizontal->getDxSource(); }
DbU::Unit AutoHorizontal::getDuTarget () const { return _horizontal->getDxTarget(); }
Interval AutoHorizontal::getSpanU () const { return Interval(_horizontal->getSourceX(),_horizontal->getTargetX()); }
@ -91,6 +93,14 @@ namespace Anabatic {
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;
// }
}
@ -142,33 +152,58 @@ namespace Anabatic {
bool AutoHorizontal::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const
{
cdebug_log(155,1) << "getConstraints() " << this << endl;
constraintMin = getNativeMin();
constraintMax = getNativeMax();
cdebug_log(144,0) << "Native constraints: ["
cdebug_log(155,0) << "Native constraints: ["
<< DbU::getValueString(constraintMin) << ":"
<< DbU::getValueString(constraintMax) << "]"
<< endl;
constraintMin = std::max ( constraintMin, getAutoSource()->getCBYMin() );
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()->getCBYMax()) << "]"
<< endl;
constraintMin = std::max ( constraintMin, getUserConstraints().getVMin() );
constraintMax = std::min ( constraintMax, getUserConstraints().getVMax() );
cdebug_log(144,0) << "Merge with user constraints: ["
<< DbU::getValueString(getUserConstraints().getVMin()) << ":"
<< DbU::getValueString(getUserConstraints().getVMax()) << "]"
constraintMin = std::max ( constraintMin, getAutoTarget()->getCBYMin() );
constraintMax = std::min ( constraintMax, getAutoTarget()->getCBYMax() );
cdebug_log(155,0) << "Merge with target constraints: ["
<< DbU::getValueString(getAutoTarget()->getCBYMin()) << ":"
<< DbU::getValueString(getAutoTarget()->getCBYMax()) << "]"
<< 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(constraintMax) << "]"
<< 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;
}
@ -177,13 +212,14 @@ namespace Anabatic {
{ return Flags::Horizontal; }
size_t AutoHorizontal::getGCells ( vector<GCell*>& gcells ) const
bool AutoHorizontal::getGCells ( vector<GCell*>& gcells ) const
{
vector<GCell*>().swap( gcells );
DbU::Unit yprobe = getY();
GCell* gcell = getAutoSource()->getGCell();
GCell* end = getAutoTarget()->getGCell();
bool success = true;
DbU::Unit yprobe = getY();
GCell* gcell = getAutoSource()->getGCell();
GCell* end = getAutoTarget()->getGCell();
cdebug_log(144,0) << "yprobe: " << DbU::getValueString(yprobe) << endl;
@ -195,20 +231,23 @@ namespace Anabatic {
while ( gcell != end ) {
gcell = gcell->getEast( yprobe );
if (not gcell) {
cerr << Error( "AutoHorizontal::getGCells() : NULL GCell under %s\n"
" begin:%s\n"
" end: %s"
, getString(this).c_str()
, getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
success = false;
if (not isCreated()) {
cerr << Error( "AutoHorizontal::getGCells() : NULL GCell under %s\n"
" begin:%s\n"
" end: %s"
, getString(this).c_str()
, getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
}
break;
}
gcells.push_back( gcell );
}
return gcells.size();
return success;
}
@ -216,24 +255,35 @@ namespace Anabatic {
{
cdebug_tabw(149,1);
Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Vertical );
Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Vertical );
Interval sourceConstraints = Interval(getAutoSource()->getCBYMin(),getAutoSource()->getCBYMax());
Interval targetConstraints = Interval(getAutoTarget()->getCBYMin(),getAutoTarget()->getCBYMax());
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
if (source->isOnPin() or target->isOnPin()) { cdebug_tabw(149,-1); return false; }
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.
sourceConstraints.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
<< " " << 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
<< " " << DbU::getValueString(targetConstraints.getSize()) << endl;
if (not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; }
if (not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; }
if (not sourceGoStraight and not sourceConstraints.contains(sourceSide)) { 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);
return false;
@ -249,30 +299,52 @@ namespace Anabatic {
const Configuration* configuration = Session::getConfiguration();
const Layer* metal2 = configuration->getRoutingLayer( 1 );
bool success = false;
bool isMetal2Source = false;
bool isMetal2Target = false;
DbU::Unit height = 0;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
bool success = false;
bool isMetal2Source = false;
bool isMetal2Target = false;
bool isNonPrefSource = false;
bool isNonPrefTarget = false;
DbU::Unit height = 0;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
bool slackenSource = false;
bool slackenTarget = false;
if (source->isTerminal()) {
height = (static_cast<RoutingPad*>(source->getAnchor()))->getBoundingBox().getHeight();
isMetal2Source = (source->getLayer() == metal2);
slackenSource = true;
}
if (target->isTerminal()) {
height = std::min( height, (static_cast<RoutingPad*>(target->getAnchor()))->getBoundingBox().getHeight() );
isMetal2Target = (target->getLayer() == metal2);
slackenTarget = true;
}
if (source->isTurn() and (source->getPerpandicular(this)->getLayer() == getLayer())) {
isNonPrefSource = true;
slackenSource = true;
}
if (height >= 4*getPitch()) {
if (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < 5*getPitch()))
return false;
cdebug_log(149,0) << "target:" << target << endl;
cdebug_log(149,0) << "target->getPerpandicular(this):" << target->getPerpandicular(this) << endl;
if (target->isTurn() and (target->getPerpandicular(this)->getLayer() == getLayer())) {
isNonPrefTarget = true;
slackenTarget = true;
}
cdebug_tabw(149,1);
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
cdebug_log(149,0) << "test:" << (getLength() < 5*getPitch()) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl;
cdebug_log(149,0) << "test:" << (getAnchoredLength() < 5*getPitch()) << 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;
bool sourceSlackened = false;
@ -281,7 +353,7 @@ namespace Anabatic {
DbU::Unit targetPosition = getTargetPosition();
AutoSegment* parallel = this;
if (source->isTerminal()) {
if (slackenSource) {
Interval perpandConstraints = getAutoTarget()->getUConstraints(Flags::Horizontal);
Interval constraints = source->getUConstraints (Flags::Vertical|Flags::NoGCellShrink);
Interval nativeConstraints = source->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink);
@ -293,7 +365,7 @@ namespace Anabatic {
<< " native slack:" << nativeSlack << endl;
cdebug_log(149,0) << "Perpand constraints on target: " << perpandConstraints << endl;
// 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;
_makeDogleg( source->getGCell(), Flags::NoFlags );
sourceSlackened = true;
@ -303,7 +375,7 @@ namespace Anabatic {
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
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() );
success = true;
@ -321,7 +393,7 @@ namespace Anabatic {
if (parallel) target = parallel->getAutoTarget();
if (target->isTerminal()) {
if (slackenTarget) {
Interval constraints = target->getUConstraints (Flags::Vertical|Flags::NoGCellShrink);
Interval nativeConstraints = target->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink);
int slack = constraints.getSize() / getPitch();
@ -331,7 +403,7 @@ namespace Anabatic {
cdebug_log(149,0) << "Target constraint: " << constraints
<< " slack:" << slack
<< " 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;
parallel->_makeDogleg( target->getGCell(), Flags::NoFlags );
targetSlackened = true;
@ -341,7 +413,15 @@ namespace Anabatic {
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
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 );
success = true;
@ -349,7 +429,7 @@ namespace Anabatic {
cdebug_log(149,0) << "Fixing on target terminal contact: "
<< doglegs[doglegs.size()-2]->getAutoTarget() << endl;
//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 );
}
}
@ -406,9 +486,18 @@ namespace Anabatic {
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;
_horizontal->invert();
if (isAtMinArea()) {
DbU::Unit sourceX = _horizontal->getSourceX();
DbU::Unit targetX = _horizontal->getTargetX();
_horizontal->invert();
setDuSource( sourceX - getSourceU() );
setDuTarget( targetX - getTargetU() );
} else {
_horizontal->invert();
}
cdebug_log(145,0) << "updateOrient() " << this << " (after S/T swap)" << endl;
uint64_t spinFlags = _flags & SegDepthSpin;
unsetFlags( SegDepthSpin );
@ -432,8 +521,8 @@ namespace Anabatic {
void AutoHorizontal::updatePositions ()
{
_sourcePosition = _horizontal->getSourceX() - getExtensionCap();
_targetPosition = _horizontal->getTargetX() + getExtensionCap();
_sourcePosition = getSourceU() - getExtensionCap(Flags::Source);
_targetPosition = getTargetU() + getExtensionCap(Flags::Target);
}
@ -453,10 +542,13 @@ namespace Anabatic {
bool AutoHorizontal::checkPositions () const
{
bool coherency = true;
DbU::Unit sourcePosition = _horizontal->getSourceX() - getExtensionCap();
DbU::Unit targetPosition = _horizontal->getTargetX() + getExtensionCap();
DbU::Unit sourcePosition = _horizontal->getSource()->getX() - getExtensionCap(Flags::Source);
DbU::Unit targetPosition = _horizontal->getTarget()->getX() + getExtensionCap(Flags::Target);
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: "
"shadow: %s, real: %s."
, _getString().c_str()
@ -730,7 +822,7 @@ namespace Anabatic {
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_tabw(149,1);
@ -741,6 +833,8 @@ namespace Anabatic {
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
if (not autoSource->canDrag()) unsetFlags( SegDrag );
DbU::Unit doglegAxis = (doglegGCell->getXMax() + doglegGCell->getXMin()) / 2;
if (isLocal())
doglegAxis = (getSourceX() + getTargetX()) / 2;
@ -759,10 +853,19 @@ namespace Anabatic {
} while ( gcell and (gcell != end) );
}
size_t depth = Session::getRoutingGauge()->getLayerDepth( _horizontal->getLayer() );
bool upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer( depth + ((upLayer)?0:-1) );
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer( depth + ((upLayer)?1:-1) );
size_t depth = Session::getRoutingGauge()->getLayerDepth( _horizontal->getLayer() );
bool upLayer = true;
if (Session::getRoutingGauge()->isTwoMetals()) {
upLayer = (depth == 0);
} 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 );
targetDetach();
@ -771,7 +874,7 @@ namespace Anabatic {
AutoContact* dlContact1 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer );
AutoContact* dlContact2 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer );
AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Vertical );
segment1->setLayer( doglegLayer );
segment1->setLayer( doglegDepth );
segment1->_setAxis( doglegAxis );
segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned );
@ -782,32 +885,53 @@ namespace Anabatic {
targetAttach( dlContact1 );
AutoSegment* segment2 = AutoSegment::create( dlContact2 , autoTarget, Flags::Horizontal );
autoTarget->cacheAttach( segment2 );
segment2->setLayer( getLayer() );
segment2->setLayer( depth );
segment2->_setAxis( getY() );
segment2->setFlags( (isSlackened()?SegSlackened:0) );
Session::dogleg( segment2 );
if (autoSource->isTerminal()) {
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 );
if (autoSource->isTerminal() and autoTarget->isTerminal()) {
dlContact1->setFlags ( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
} else if (autoSource->isTerminal()) {
autoTarget->unsetFlags( CntWeakTerminal );
dlContact1->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell)
dlContact1->migrateConstraintBox( autoTarget );
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()) {
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
} else if (isWeakTerminal()) {
segment1->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()) {
segment1->setFlags( SegAnalog );
segment2->setFlags( SegAnalog );
@ -827,6 +951,18 @@ namespace Anabatic {
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);
DebugSession::close();

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -93,14 +93,12 @@ namespace Anabatic {
bool AutoSegments_OnContact::Locator::isValid () const
{ return !_hook; }
{ return _hook; }
void AutoSegments_OnContact::Locator::progress ()
{
cdebug_log(145,0) << "AutoSegments_OnContact::Locator::progress()" << endl;
while (_hook and not _hook->isMaster()) {
while (_hook) {
_hook = _hook->getNextHook();
_element = NULL;
@ -108,7 +106,6 @@ namespace Anabatic {
Segment* segment = dynamic_cast<Segment*>( _hook->getComponent() );
if (segment) _element = Session::lookup( segment );
if (not _element or (_element == _master)) continue;
break;
@ -147,7 +144,7 @@ namespace Anabatic {
AutoSegments_OnRoutingPad::Locator::Locator ( RoutingPad* rp, const AutoContactTerminal* contact )
: AutoSegmentHL()
, _elements ({NULL,NULL,NULL,NULL})
, _elements ({{NULL,NULL,NULL,NULL}})
, _index (0)
{
if (rp) {

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -16,6 +16,7 @@
#include <algorithm>
#include "hurricane/Bug.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/Vertical.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/Configuration.h"
@ -30,6 +31,7 @@ namespace Anabatic {
using std::max;
using Hurricane::Error;
using Hurricane::Bug;
using Hurricane::ViaLayer;
// -------------------------------------------------------------------
@ -39,8 +41,8 @@ namespace Anabatic {
Segment* AutoVertical::base () { return _vertical; }
Segment* AutoVertical::base () const { return _vertical; }
Vertical* AutoVertical::getVertical () { return _vertical; }
DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSourceY(); }
DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTargetY(); }
DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSource()->getY(); }
DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTarget()->getY(); }
DbU::Unit AutoVertical::getDuSource () const { return _vertical->getDySource(); }
DbU::Unit AutoVertical::getDuTarget () const { return _vertical->getDyTarget(); }
Interval AutoVertical::getSpanU () const { return Interval(_vertical->getSourceY(),_vertical->getTargetY()); }
@ -137,6 +139,8 @@ namespace Anabatic {
bool AutoVertical::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const
{
cdebug_log(149,1) << "getConstraints() " << this << endl;
constraintMin = getNativeMin();
constraintMax = getNativeMax();
@ -152,19 +156,39 @@ namespace Anabatic {
<< DbU::getValueString(getAutoSource()->getCBXMax()) << "]"
<< endl;
constraintMin = max ( constraintMin, getUserConstraints().getVMin() );
constraintMax = min ( constraintMax, getUserConstraints().getVMax() );
cdebug_log(149,0) << "Merge with user constraints: ["
<< DbU::getValueString(getUserConstraints().getVMin()) << ":"
<< DbU::getValueString(getUserConstraints().getVMax()) << "]"
constraintMin = std::max ( constraintMin, getAutoTarget()->getCBXMin() );
constraintMax = std::min ( constraintMax, getAutoTarget()->getCBXMax() );
cdebug_log(149,0) << "Merge with target constraints: ["
<< DbU::getValueString(getAutoTarget()->getCBXMin()) << ":"
<< DbU::getValueString(getAutoTarget()->getCBXMax()) << "]"
<< 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(constraintMax) << "]"
<< 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;
}
@ -173,13 +197,14 @@ namespace Anabatic {
{ return Flags::Vertical; }
size_t AutoVertical::getGCells ( vector<GCell*>& gcells ) const
bool AutoVertical::getGCells ( vector<GCell*>& gcells ) const
{
vector<GCell*>().swap( gcells );
DbU::Unit xprobe = getX();
GCell* gcell = getAutoSource()->getGCell();
GCell* end = getAutoTarget()->getGCell();
bool success = true;
DbU::Unit xprobe = getX();
GCell* gcell = getAutoSource()->getGCell();
GCell* end = getAutoTarget()->getGCell();
cdebug_log(144,0) << "xprobe: " << DbU::getValueString(xprobe) << endl;
@ -192,20 +217,23 @@ namespace Anabatic {
gcell = gcell->getNorth( xprobe );
if (not gcell) {
cerr << Error( "AutoVertical::getGCells() : NULL GCell under %s\n"
" begin:%s\n"
" end: %s"
, getString(this).c_str()
, getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
success = false;
if (not isCreated()) {
cerr << Error( "AutoVertical::getGCells() : NULL GCell under %s\n"
" begin:%s\n"
" end: %s"
, getString(this).c_str()
, getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
}
break;
}
gcells.push_back( gcell );
}
return gcells.size();
return success;
}
@ -213,17 +241,21 @@ namespace Anabatic {
{
cdebug_tabw(149,-1);
if (getAutoSource()->isOnPin() or getAutoTarget()->isOnPin()) { cdebug_tabw(149,-1); return false; }
Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Horizontal );
Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Horizontal );
Interval sourceConstraints = Interval(getAutoSource()->getCBXMin(),getAutoSource()->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.
sourceConstraints.inflate( 1 );
targetConstraints.inflate( 1 );
if (not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; }
if (not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; }
if (not sourceGoStraight and not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; }
if (not targetGoStraight and not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; }
cdebug_tabw(149,-1);
return false;
@ -234,13 +266,15 @@ namespace Anabatic {
{
cdebug_log(149,1) << "AutoVertical::_slacken() " << this << endl;
if ( not isStrongTerminal()
or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < getPitch()*5)) )
{ cdebug_tabw(149,-1); return false; }
if (not isDrag()) {
if ( not isStrongTerminal()
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) << "test:" << (getLength() < getPitch()*5) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl;
cdebug_log(149,0) << "test:" << (getAnchoredLength() < getPitch()*5) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getAnchoredLength()) << endl;
bool success = false;
bool sourceSlackened = false;
@ -348,6 +382,10 @@ namespace Anabatic {
if (_vertical->getTargetY() < _vertical->getSourceY()) {
cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl;
_vertical->invert();
DbU::Unit duSource = getDuSource();
DbU::Unit duTarget = getDuTarget();
setDuSource( -duTarget );
setDuTarget( -duSource );
unsigned int spinFlags = _flags & SegDepthSpin;
unsetFlags( SegDepthSpin );
@ -371,8 +409,8 @@ namespace Anabatic {
void AutoVertical::updatePositions ()
{
_sourcePosition = _vertical->getSourceY() - getExtensionCap();
_targetPosition = _vertical->getTargetY() + getExtensionCap();
_sourcePosition = getSourceU() - getExtensionCap(Flags::Source);
_targetPosition = getTargetU() + getExtensionCap(Flags::Target);
}
@ -392,8 +430,8 @@ namespace Anabatic {
bool AutoVertical::checkPositions () const
{
bool coherency = true;
DbU::Unit sourcePosition = _vertical->getSourceY() - getExtensionCap();
DbU::Unit targetPosition = _vertical->getTargetY() + getExtensionCap();
DbU::Unit sourcePosition = _vertical->getSource()->getY() - getExtensionCap(Flags::Source);
DbU::Unit targetPosition = _vertical->getTarget()->getY() + getExtensionCap(Flags::Target);
if ( _sourcePosition != sourcePosition ) {
cerr << Error ( "%s\n Source position incoherency: "
@ -650,12 +688,14 @@ namespace Anabatic {
{
cdebug_log(149,0) << "AutoVertical::_makeDogleg(GCell*)" << endl;
//Session::doglegReset();
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
//Session::doglegReset();
if (not autoSource->canDrag()) unsetFlags( SegDrag );
DbU::Unit doglegAxis = (doglegGCell->getYMax() + doglegGCell->getYMin()) / 2;
if (isLocal())
@ -671,10 +711,19 @@ namespace Anabatic {
} while ( gcell and (gcell != end) );
}
size_t depth = Session::getRoutingGauge()->getLayerDepth ( _vertical->getLayer() );
bool upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer ( depth + ((upLayer)?0:-1) );
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer ( depth + ((upLayer)?1:-1) );
size_t depth = Session::getRoutingGauge()->getLayerDepth ( _vertical->getLayer() );
bool upLayer = true;
if (Session::getRoutingGauge()->isTwoMetals()) {
upLayer = (depth == 0);
} 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 );
targetDetach();
@ -686,7 +735,7 @@ namespace Anabatic {
cdebug_log(149,0) << dlContact2 << endl;
AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Horizontal );
cdebug_log(149,0) << segment1 << endl;
segment1->setLayer( doglegLayer );
segment1->setLayer( doglegDepth );
segment1->_setAxis( doglegAxis );
segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned );
cdebug_log(149,0) << "New " << dlContact1->base() << "." << endl;
@ -696,32 +745,53 @@ namespace Anabatic {
targetAttach( dlContact1 );
AutoSegment* segment2 = AutoVertical::create ( dlContact2, autoTarget, Flags::Vertical );
autoTarget->cacheAttach( segment2 );
segment2->setLayer( getLayer() );
segment2->setLayer( depth );
segment2->_setAxis( getX() );
segment2->setFlags( (isSlackened()?SegSlackened:0) );
Session::dogleg( segment2 );
if (isSourceTerminal()) {
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 );
if (autoSource->isTerminal() and autoTarget->isTerminal()) {
dlContact1->setFlags ( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
} else if (autoSource->isTerminal()) {
autoTarget->unsetFlags( CntWeakTerminal );
dlContact1->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell)
dlContact1->migrateConstraintBox( autoTarget );
} else if (isTargetTerminal()) {
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()) {
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
} else if (isWeakTerminal()) {
segment1->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()) {
segment1->setFlags( SegAnalog );
segment2->setFlags( SegAnalog );
@ -741,6 +811,18 @@ namespace Anabatic {
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;
}

View File

@ -8,6 +8,7 @@ endif ( CHECK_DETERMINISM )
${CORIOLIS_INCLUDE_DIR}
${HURRICANE_INCLUDE_DIR}
${CONFIGURATION_INCLUDE_DIR}
${FLUTE_INCLUDE_DIR}
${Boost_INCLUDE_DIRS}
${QtX_INCLUDE_DIR}
${PYTHON_INCLUDE_PATH}
@ -15,6 +16,7 @@ endif ( CHECK_DETERMINISM )
set( includes anabatic/Constants.h
anabatic/Configuration.h
anabatic/Matrix.h
anabatic/EdgeCapacity.h
anabatic/Edge.h anabatic/Edges.h
anabatic/GCell.h #anabatic/GCells.h
anabatic/AnabaticEngine.h
@ -29,18 +31,21 @@ endif ( CHECK_DETERMINISM )
anabatic/AutoHorizontal.h
anabatic/AutoVertical.h
anabatic/Session.h
anabatic/NetBuilder.h
anabatic/NetBuilderM2.h
anabatic/NetBuilderHV.h
anabatic/NetBuilderVH.h
anabatic/ChipTools.h
)
set( pyIncludes )
set( cpps Constants.cpp
Configuration.cpp
Matrix.cpp
EdgeCapacity.cpp
Edge.cpp
Edges.cpp
GCell.cpp
AnabaticEngine.cpp
Dijkstra.cpp
AutoContact.cpp
AutoContactTerminal.cpp
AutoContactTurn.cpp
@ -52,15 +57,21 @@ endif ( CHECK_DETERMINISM )
Session.cpp
NetConstraints.cpp
NetOptimals.cpp
LoadGlobalRouting.cpp
NetBuilder.cpp
NetBuilderM2.cpp
NetBuilderHV.cpp
NetBuilderVH.cpp
ChipTools.cpp
LayerAssign.cpp
AntennaProtect.cpp
PreRouteds.cpp
AnabaticEngine.cpp
)
set( pyCpps PyAnabatic.cpp
)
set( depLibs ${CORIOLIS_PYTHON_LIBRARIES}
set( depLibs ${ETESIAN_LIBRARIES}
${CORIOLIS_PYTHON_LIBRARIES}
${CORIOLIS_LIBRARIES}
${HURRICANE_PYTHON_LIBRARIES}
${HURRICANE_GRAPHICAL_LIBRARIES}
@ -68,6 +79,7 @@ endif ( CHECK_DETERMINISM )
${CONFIGURATION_LIBRARY}
${CIF_LIBRARY}
${AGDS_LIBRARY}
${FLUTE_LIBRARIES}
${LEFDEF_LIBRARIES}
${OA_LIBRARIES}
${QtX_LIBRARIES}

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Configuration.cpp<anabatic>" -*-
//
// 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 |
@ -22,7 +22,11 @@
#include "hurricane/Error.h"
#include "hurricane/Technology.h"
#include "hurricane/DataBase.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Pin.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/Cell.h"
#include "crlcore/Utilities.h"
#include "crlcore/CellGauge.h"
@ -46,9 +50,17 @@ namespace Anabatic {
using Hurricane::tab;
using Hurricane::Warning;
using Hurricane::Error;
using Hurricane::Transformation;
using Hurricane::Technology;
using Hurricane::DataBase;
using Hurricane::BasicLayer;
using Hurricane::RegularLayer;
using Hurricane::Segment;
using Hurricane::Pin;
using Hurricane::Plug;
using Hurricane::Path;
using Hurricane::Occurrence;
using Hurricane::NetExternalComponents;
using CRL::AllianceFramework;
using CRL::RoutingGauge;
using CRL::RoutingLayerGauge;
@ -59,30 +71,49 @@ namespace Anabatic {
Configuration::Configuration ( const CellGauge* cg, const RoutingGauge* rg )
: _cg (NULL)
, _rg (NULL)
, _extensionCaps ()
, _saturateRatio (Cfg::getParamPercentage("katabatic.saturateRatio",80.0)->asDouble())
, _saturateRp (Cfg::getParamInt ("katabatic.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())
: _gdepthv (ndepth)
, _gdepthh (ndepth)
, _ddepthv (ndepth)
, _ddepthh (ndepth)
, _ddepthc (ndepth)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps ()
, _saturateRatio (Cfg::getParamPercentage("anabatic.saturateRatio",80.0)->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() );
if (cg == NULL) cg = AllianceFramework::get()->getCellGauge();
if (rg == NULL) rg = AllianceFramework::get()->getRoutingGauge();
string gaugeName = Cfg::getParamString("anabatic.routingGauge","sxlib")->asString();
if (cg == NULL) {
cg = AllianceFramework::get()->getCellGauge( gaugeName );
if (cg == NULL)
throw Error( "AnabaticEngine::Configuration(): Unable to find default cell gauge." );
}
if (rg == NULL) {
rg = AllianceFramework::get()->getRoutingGauge( gaugeName );
if (rg == NULL)
throw Error( "AnabaticEngine::Configuration(): No routing gauge named \"%s\"", gaugeName.c_str() );
}
_cg = cg->getClone();
_rg = rg->getClone();
if (Cfg::hasParameter("anabatic.topRoutingLayer")) {
_allowedDepth = rg->getDepth()-1;
if (Cfg::hasParameter("anabatic.topRoutingLayer"))
_setTopRoutingLayer( Cfg::getParamString("anabatic.topRoutingLayer")->asString() );
} else
_allowedDepth = rg->getDepth()-1;
_gmetalh = DataBase::getDB()->getTechnology()->getLayer("gmetalh");
_gmetalv = DataBase::getDB()->getTechnology()->getLayer("gmetalv");
@ -94,36 +125,75 @@ namespace Anabatic {
//DbU::Unit sliceHeight = _cg->getSliceHeight();
_ddepthc = (_allowedDepth > 1) ? 1 : 0;
const vector<RoutingLayerGauge*>& layerGauges = rg->getLayerGauges();
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() );
if (regularLayer)
_extensionCaps.push_back( regularLayer->getExtentionCap() );
else {
_extensionCaps.push_back( 0 );
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;
const BasicLayer* basicLayer = dynamic_cast<const BasicLayer*>( layerGauges[depth]->getLayer() );
if (basicLayer) {
_extensionCaps.push_back( layerGauges[depth]->getHalfWireWidth() );
} else {
_extensionCaps.push_back( 0 );
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 )
: _gmetalh (other._gmetalh)
, _gmetalv (other._gmetalv)
, _gcontact (other._gcontact)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps (other._extensionCaps)
, _saturateRatio (other._saturateRatio)
, _globalThreshold(other._globalThreshold)
, _allowedDepth (other._allowedDepth)
, _edgeCostH (other._edgeCostH)
, _edgeCostK (other._edgeCostK)
, _edgeHInc (other._edgeHInc)
: _gmetalh (other._gmetalh)
, _gmetalv (other._gmetalv)
, _gcontact (other._gcontact)
, _gdepthv (other._gdepthv)
, _gdepthh (other._gdepthh)
, _ddepthv (other._ddepthv)
, _ddepthh (other._ddepthh)
, _ddepthc (other._ddepthc)
, _cg (NULL)
, _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() );
@ -144,6 +214,18 @@ namespace Anabatic {
{ return new Configuration(*this); }
bool Configuration::isTwoMetals () const
{ return _rg->isTwoMetals(); }
bool Configuration::isHV () const
{ return _rg->isHV(); }
bool Configuration::isVH () const
{ return _rg->isVH(); }
bool Configuration::isGMetal ( const Layer* layer ) const
{ return (layer and ((layer == _gmetalh) or (layer == _gmetalv))); }
@ -151,15 +233,19 @@ namespace Anabatic {
bool Configuration::isGContact ( const Layer* layer ) const
{ return (layer and (layer == _gcontact)); }
const Layer* Configuration::getGContactLayer () const
{ return _gcontact; }
const Layer* Configuration::getGHorizontalLayer () const
{ return _gmetalh; }
const Layer* Configuration::getGVerticalLayer () const
{ return _gmetalv; }
size_t Configuration::getDepth () const
{ return _rg->getDepth(); }
@ -216,6 +302,10 @@ namespace Anabatic {
{ return getWireWidth( getLayerDepth(layer) ); }
DbU::Unit Configuration::getPWireWidth ( const Layer* layer ) const
{ return getPWireWidth( getLayerDepth(layer) ); }
Flags Configuration::getDirection ( const Layer* layer ) const
{ return getDirection( getLayerDepth(layer) ); }
@ -267,6 +357,9 @@ namespace Anabatic {
{ return _rg->getLayerWireWidth(depth); }
DbU::Unit Configuration::getPWireWidth ( size_t depth ) const
{ return _rg->getLayerPWireWidth(depth); }
DbU::Unit Configuration::getExtensionCap ( size_t depth ) const
{ return _extensionCaps[depth]; }
@ -288,7 +381,7 @@ namespace Anabatic {
}
}
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(name).c_str() ) << endl;
}
@ -326,6 +419,142 @@ namespace Anabatic {
{ 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) 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
{
if (not cmess1.enabled()) return;
@ -338,6 +567,7 @@ namespace Anabatic {
cout << " o Configuration of ToolEngine<Anabatic> for Cell <" << cell->getName() << ">" << endl;
cout << Dots::asIdentifier(" - Routing Gauge" ,getString(_rg->getName())) << endl;
cout << Dots::asString (" - Top routing layer" ,topLayerName) << endl;
cout << Dots::asUInt (" - Maximum GR iterations" ,_globalIterations) << endl;
}
@ -360,15 +590,22 @@ namespace Anabatic {
Record* Configuration::_getRecord () const
{
Record* record = new Record ( _getString() );
record->add ( getSlot( "_rg" , _rg ) );
record->add ( getSlot( "_gmetalh" , _gmetalh ) );
record->add ( getSlot( "_gmetalv" , _gmetalv ) );
record->add ( getSlot( "_gcontact" , _gcontact ) );
record->add ( getSlot( "_allowedDepth", _allowedDepth ) );
record->add ( getSlot( "_edgeCostH" , _edgeCostH ) );
record->add ( getSlot( "_edgeCostK" , _edgeCostK ) );
record->add( getSlot( "_gdepthh" , _gdepthh ) );
record->add( getSlot( "_gdepthv" , _gdepthv ) );
record->add( getSlot( "_rg" , _rg ) );
record->add( getSlot( "_gmetalh" , _gmetalh ) );
record->add( getSlot( "_gmetalv" , _gmetalv ) );
record->add( getSlot( "_gcontact" , _gcontact ) );
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>" -*-
//
// 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 |
@ -39,6 +39,14 @@ namespace Anabatic {
const BaseFlags Flags::MatrixGCell = (1L << 9);
const BaseFlags Flags::IoPadGCell = (1L << 10);
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.
const BaseFlags Flags::DemoMode = (1L << 5);
const BaseFlags Flags::WarnOnGCellOverload = (1L << 6);
@ -46,7 +54,11 @@ namespace Anabatic {
const BaseFlags Flags::DestroyBaseContact = (1L << 8);
const BaseFlags Flags::DestroyBaseSegment = (1L << 9);
// 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.
const BaseFlags Flags::WestSide = Horizontal|Target;
const BaseFlags Flags::EastSide = Horizontal|Source;
@ -56,7 +68,27 @@ namespace Anabatic {
const BaseFlags Flags::EndsMask = Source|Target;
const BaseFlags Flags::DirectionMask = Horizontal|Vertical;
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.
const BaseFlags Flags::Create = (1L << 5);
const BaseFlags Flags::WithPerpands = (1L << 6);
@ -86,6 +118,13 @@ namespace Anabatic {
const BaseFlags Flags::CheckLowDensity = (1L << 30);
const BaseFlags Flags::CheckLowUpDensity = (1L << 31);
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);
Flags::~Flags ()
@ -139,6 +178,7 @@ namespace Anabatic {
return s.str();
}
string Flags::_getTypeName () const
{ return "Anabatic::Flags"; }
@ -146,20 +186,25 @@ namespace Anabatic {
string Flags::_getString () const
{
string s = "";
s += (_flags & (uint64_t)Horizontal ) ? 'h' : '-';
s += (_flags & (uint64_t)Vertical ) ? 'v' : '-';
s += (_flags & (uint64_t)Source ) ? 'S' : '-';
s += (_flags & (uint64_t)Target ) ? 'T' : '-';
s += (_flags & (uint64_t)DeviceGCell ) ? 'd' : '-';
s += (_flags & (uint64_t)Horizontal ) ? 'h' : '-';
s += (_flags & (uint64_t)Vertical ) ? 'v' : '-';
s += (_flags & (uint64_t)Source ) ? 'S' : '-';
s += (_flags & (uint64_t)Target ) ? 'T' : '-';
s += (_flags & (uint64_t)DeviceGCell ) ? 'd' : '-';
s += (_flags & (uint64_t)HChannelGCell) ? 'c' : '-';
s += (_flags & (uint64_t)VChannelGCell) ? 'c' : '-';
s += (_flags & (uint64_t)StrutGCell ) ? 's' : '-';
s += (_flags & (uint64_t)MatrixGCell ) ? 'm' : '-';
s += (_flags & (uint64_t)HRailGCell ) ? 'H' : '-';
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 += (_flags & (uint64_t)Invalidated ) ? 'i' : '-';
s += (_flags & (uint64_t)DestroyGCell ) ? 'D' : '-';
s += (_flags & (uint64_t)AboveLayer ) ? 'A' : '-';
s += (_flags & (uint64_t)BelowLayer ) ? 'B' : '-';
s += (_flags & (uint64_t)Invalidated ) ? 'i' : '-';
s += (_flags & (uint64_t)DestroyGCell ) ? 'D' : '-';
s += (_flags & (uint64_t)AboveLayer ) ? 'A' : '-';
s += (_flags & (uint64_t)BelowLayer ) ? 'B' : '-';
return s;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Edge.cpp<anabatic>" -*-
//
// 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 |
@ -17,6 +17,7 @@
#include <iostream>
#include "hurricane/Error.h"
#include "hurricane/Segment.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "anabatic/Edge.h"
@ -24,11 +25,51 @@
#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 {
using std::cerr;
using std::endl;
using Hurricane::Error;
using Hurricane::RoutingPad;
Name Edge::_extensionName = "Anabatic::Edge";
@ -38,7 +79,8 @@ namespace Anabatic {
Edge::Edge ( GCell* source, GCell* target, Flags flags )
: Super(source->getCell())
, _flags (flags|Flags::Invalidated)
, _capacity (0)
, _capacities (NULL)
, _reservedCapacity (0)
, _realOccupancy (0)
, _estimateOccupancy(0.0)
, _historicCost (0.0)
@ -104,6 +146,7 @@ namespace Anabatic {
void Edge::_preDestroy ()
{
_source->getAnabatic()->_unrefCapacity( _capacities );
_source->_remove( this, _flags|Flags::Source );
_target->_remove( this, _flags|Flags::Target );
@ -169,7 +212,7 @@ namespace Anabatic {
DbU::Unit dy = targetCenter.getY() - sourceCenter.getY();
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);
}
@ -179,16 +222,18 @@ namespace Anabatic {
{
unsigned int occupancy = 0;
if ((int)_realOccupancy + delta > 0) occupancy = _realOccupancy + delta;
if ((_realOccupancy <= _capacity) and (occupancy > _capacity)) getAnabatic()->addOv ( this );
if ((_realOccupancy > _capacity) and (occupancy <= _capacity)) getAnabatic()->removeOv( this );
if ((_realOccupancy <= getCapacity()) and (occupancy > getCapacity())) getAnabatic()->addOv ( this );
if ((_realOccupancy > getCapacity()) and (occupancy <= getCapacity())) getAnabatic()->removeOv( this );
_realOccupancy = occupancy;
}
void Edge::incRealOccupancy2 ( int value )
{
_realOccupancy += value;
}
Segment* Edge::getSegment ( const Net* owner ) const
{
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 )
{
_segments.push_back( segment );
Horizontal* h = dynamic_cast<Horizontal*>(segment);
Vertical* v = dynamic_cast<Vertical*>(segment);
DbU::Unit pitch = 0;
if (h) pitch = Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL2"));
if (v) pitch = Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL3"));
if (h) pitch = Session::getGHorizontalPitch();
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 ) {
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] );
_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;
}
}
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 ()
{
AnabaticEngine* anabatic = getAnabatic();
DbU::Unit globalThreshold = Session::getSliceHeight()*3;
size_t netCount = 0;
AnabaticEngine* anabatic = getAnabatic();
size_t netCount = 0;
for ( size_t i=0 ; i<_segments.size(); ) {
if (_segments[i]->getLength() >= globalThreshold) {
NetData* netData = anabatic->getNetData( _segments[i]->getNet() );
if (netData->isGlobalRouted()) ++netCount;
sort( _segments.begin(), _segments.end(), SortSegmentByLength(anabatic) );
anabatic->ripup( _segments[i], Flags::Propagate );
} else
if (Session::getRoutingGauge()->isTwoMetals()) {
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;
}
} 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;
}
@ -259,7 +416,7 @@ namespace Anabatic {
if (source == _target)
throw Error("Edge::_setSource(): Source & target are the same (%s).", getString(source).c_str() );
_invalidate();
invalidate( false );
_source=source;
}
@ -269,26 +426,41 @@ namespace Anabatic {
if (_source == target)
throw Error("Edge::_setTarget(): Source & target are the same (%s).", getString(target).c_str() );
_invalidate();
invalidate( false );
_target=target;
}
void Edge::_invalidate ()
void Edge::invalidate ( bool )
{
cdebug_log(110,1) << "Edge::invalidate() " << this << endl;
_flags |= Flags::Invalidated;
Super::invalidate( false );
cdebug_tabw(110,-1);
}
void Edge::_revalidate ()
void Edge::materialize ()
{
Interval side = getSide();
_axis = side.getCenter();
_capacity = getAnabatic()->getCapacity( side, _flags );
cdebug_log(110,1) << "Edge::materialize() " << this << endl;
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 );
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 halfLength = getAnabatic()->getConfiguration()->getEdgeLength() / 2;
if (_flags.isset(Flags::Horizontal))
return Box( _target->getXMin() - halfLength, _axis - halfThickness
, _target->getXMin() + halfLength, _axis + halfThickness
);
Box bb;
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
);
return bb;
}
bool Edge::isMaxCapacity ( Net* net ) const
bool Edge::isMaxCapacity ( Net* net ) const
{
if (net){
Hurricane::NetRoutingState* state = Hurricane::NetRoutingExtension::get( net );
//cerr << "bool Edge::isMaxCapacity ( Net* net ) const: " << net << endl;
//cerr << "WPitch: " << state->getWPitch() << endl;
unsigned int wpitch = 0;
if (net) {
cdebug_log(112,0) << "_capacity:" << getCapacity() << endl;
return ( (_realOccupancy +state->getWPitch()) > _capacity ) ? true : false;
} else {
return ( _realOccupancy >= _capacity ) ? true : false;
Hurricane::NetRoutingState* state = Hurricane::NetRoutingExtension::get( net );
wpitch = (state) ? state->getWPitch()-1 : 0;
}
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(_axis) );
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, " " +getString(_flags) );
return s;
@ -359,7 +534,8 @@ namespace Anabatic {
{
Record* record = Super::_getRecord();
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("_estimateOccupancy", _estimateOccupancy) );
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>" -*-
//
// 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 |
@ -20,6 +20,7 @@
namespace Anabatic {
using std::cerr;
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) << " _filterFlags:" << _filterFlags << endl;
cdebug_log(110,0) << " East:" << _gcell->getEastEdges().size()
<< " North:" << _gcell->getNorthEdges().size()
<< " West:" << _gcell->getWestEdges().size()
<< " South:" << _gcell->getSouthEdges().size() << endl;
cdebug_log(110,0) << " East:" << _gcell->getEastEdges ().size()
<< " North:" << _gcell->getNorthEdges().size()
<< " West:" << _gcell->getWestEdges ().size()
<< " South:" << _gcell->getSouthEdges().size() << endl;
cdebug_log(110,0) << this << endl;
++_iedge;
@ -74,7 +75,7 @@ namespace Anabatic {
if (_stateFlags.contains(Flags::EastSide)) {
if ( (_iedge < _gcell->getEastEdges().size())
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;
_iedge = 0;
// cdebug_log(110,0) << this << endl;
@ -83,7 +84,7 @@ namespace Anabatic {
if (_stateFlags.contains(Flags::NorthSide)) {
if ( (_iedge < _gcell->getNorthEdges().size())
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;
_iedge = 0;
// cdebug_log(110,0) << this << endl;
@ -92,7 +93,7 @@ namespace Anabatic {
if (_stateFlags.contains(Flags::WestSide)) {
if ( (_iedge < _gcell->getWestEdges().size())
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;
_iedge = 0;
continue;
@ -100,7 +101,7 @@ namespace Anabatic {
if (_stateFlags.contains(Flags::SouthSide)) {
if ( (_iedge < _gcell->getSouthEdges().size())
and _filterFlags.contains(Flags::SouthSide)) break;
// cdebug_log(110,0) << "All edges done." << endl;
//cdebug_log(110,0) << "All edges done." << endl;
_stateFlags = 0;
_iedge = 0;
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.

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "GCell.cpp<anabatic>" -*-
//
// 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 |
@ -273,6 +273,8 @@ namespace Anabatic {
Name GCell::_extensionName = "Anabatic::GCell";
uint32_t GCell::_displayMode = GCell::Boundary;
DbU::Unit GCell::_matrixHSide = 0;
DbU::Unit GCell::_matrixVSide = 0;
uint32_t GCell::getDisplayMode () { return _displayMode; }
@ -296,6 +298,7 @@ namespace Anabatic {
, _contacts ()
, _depth (Session::getRoutingGauge()->getDepth())
, _pinDepth (0)
, _rpCount (0)
, _blockages (new DbU::Unit [_depth])
, _cDensity (0.0)
, _densities (new float [_depth])
@ -303,7 +306,16 @@ namespace Anabatic {
, _fragmentations(new float [_depth])
, _globalsCount (new float [_depth])
, _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++ ) {
_blockages [i] = 0;
_densities [i] = 0.0;
@ -331,13 +343,13 @@ namespace Anabatic {
if (not anabatic) throw Error( "GCell::create(): NULL anabatic argument." );
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
, anabatic->getCell()->getAbutmentBox().getXMin()
, anabatic->getCell()->getAbutmentBox().getYMin() );
gcell->_postCreate();
gcell->_revalidate();
Session::close();
if (not reUseSession) Session::close();
return gcell;
}
@ -447,6 +459,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
{
for ( Contact* contact : _gcontacts ) {
@ -456,6 +476,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
{
for ( Contact* contact : _gcontacts ) {
@ -467,6 +507,9 @@ namespace Anabatic {
Contact* GCell::breakGoThrough ( Net* net )
{
Contact* gcontact = hasGContact( net );
if (gcontact) return gcontact;
for ( Edge* edge : _eastEdges ) {
for ( Segment* segment : edge->getSegments() ) {
if (segment->getNet() == net)
@ -481,6 +524,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;
}
@ -498,13 +557,49 @@ namespace Anabatic {
{
for ( Edge* edge : getEdges(sideHint) ) {
GCell* side = edge->getOpposite(this);
if ( (sideHint & (Flags::WestSide |Flags::EastSide )) and (u < side->getYMax()) ) return edge;
if ( (sideHint & (Flags::SouthSide|Flags::NorthSide)) and (u < side->getXMax()) ) return edge;
if ( (sideHint.contains(Flags::WestSide) or sideHint.contains(Flags::EastSide ))
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;
}
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
{
for ( Edge* edge : _westEdges ) {
@ -559,8 +654,6 @@ namespace Anabatic {
{
const GCell* current = this;
if (not this) cerr << Error("*this* is NULL!") << endl;
while ( current ) {
if (not current->isFlat() and current->getBoundingBox().contains(x,y)) break;
@ -633,15 +726,17 @@ namespace Anabatic {
size_t iedge = 0;
for ( ; (iedge < _southEdges.size()) ; ++iedge ) {
cdebug_log(110,0) << "[" << iedge << "] xmax of:"
<< _southEdges[iedge]->getOpposite(this)
<< " " << _southEdges[iedge] << endl;
<< _southEdges[iedge]->getOpposite(this)
<< " " << _southEdges[iedge] << endl;
if (x <= _southEdges[iedge]->getOpposite(this)->getXMax()) break;
}
if ( (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 );
_southEdges[iedge]->invalidate( false );
}
_moveEdges( chunk, iedge+1, Flags::SouthSide );
}
@ -655,15 +750,14 @@ namespace Anabatic {
if ( (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 );
_northEdges[iedge]->invalidate( false );
}
_moveEdges( chunk, iedge+1, Flags::NorthSide );
}
_revalidate();
chunk->_revalidate();
cdebug_tabw(110,-1);
return chunk;
@ -694,8 +788,10 @@ namespace Anabatic {
if ( (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 );
_westEdges[iedge]->invalidate( false );
}
_moveEdges( chunk, iedge+1, Flags::WestSide );
}
@ -707,15 +803,14 @@ namespace Anabatic {
if ( (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 );
_eastEdges[iedge]->invalidate( false );
}
_moveEdges( chunk, iedge+1, Flags::EastSide );
}
_revalidate();
chunk->_revalidate();
cdebug_tabw(110,-1);
return chunk;
@ -724,47 +819,49 @@ namespace Anabatic {
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 vspan = getSide( Flags::Vertical );
if (hspan.getSize() < 3*side) {
cerr << Error( "GCell::doGrid(): GCell is too narrow (dx:%s) to build a grid.\n"
" (%s)"
, DbU::getValueString(hspan.getSize()).c_str()
, getString(this).c_str()
) << endl;
Session::close();
return false;
}
// if (hspan.getSize() < 2*hside) {
// cerr << Error( "GCell::doGrid(): GCell is too narrow (dx:%s) to build a grid.\n"
// " (%s)"
// , DbU::getValueString(hspan.getSize()).c_str()
// , getString(this).c_str()
// ) << endl;
// Session::close();
// return false;
// }
if (vspan.getSize() < 3*side) {
cerr << Error( "GCell::doGrid(): GCell is too narrow (dy:%s) to build a grid.\n"
" (%s)"
, DbU::getValueString(vspan.getSize()).c_str()
, getString(this).c_str()
) << endl;
return false;
}
// if (vspan.getSize() < 2*vside) {
// cerr << Error( "GCell::doGrid(): GCell is too narrow (dy:%s) to build a grid.\n"
// " (%s)"
// , DbU::getValueString(vspan.getSize()).c_str()
// , getString(this).c_str()
// ) << endl;
// return false;
// }
GCell* row = this;
GCell* column = NULL;
DbU::Unit ycut = vspan.getVMin()+side;
for ( ; ycut < vspan.getVMax() ; ycut += side ) {
DbU::Unit ycut = vspan.getVMin()+vside;
for ( ; ycut < vspan.getVMax() ; ycut += vside ) {
column = row;
row = row->hcut( ycut );
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->setType( Flags::MatrixGCell );
}
}
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->setType( Flags::MatrixGCell );
}
@ -782,26 +879,39 @@ namespace Anabatic {
// }
//}
Session::close();
if (not openSession) Session::close();
return true;
}
void GCell::_revalidate ()
void GCell::invalidate ( bool propagateFlag )
{
cdebug_log(110,1) << "GCell::revalidate() " << this << endl;
cdebug_log(110,1) << "West side." << endl; for ( Edge* edge : _westEdges ) edge->revalidate(); cdebug_tabw(110,-1);
cdebug_log(110,1) << "East side." << endl; for ( Edge* edge : _eastEdges ) edge->revalidate(); cdebug_tabw(110,-1);
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) << "GCell::invalidate() " << this << endl;
Super::invalidate( propagateFlag );
_flags |= Flags::Invalidated;
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)
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)
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->getMatrix()->show();
Super::materialize();
cdebug_tabw(110,-1);
}
@ -898,36 +1008,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;
_ymin = y;
UpdateSession::close();
invalidate( false );
}
void GCell::updateContactsPosition ()
void GCell::updateGContacts ( Flags flags )
{
UpdateSession::open();
DbU::Unit xc = (getXMax() + getXMin())/2;
DbU::Unit yc = (getYMax() + getYMin())/2;
for (vector<Contact*>::iterator it = _gcontacts.begin(); it != _gcontacts.end(); it++){
for ( Component* c : (*it)->getSlaveComponents() ){
Horizontal* h = dynamic_cast<Horizontal*>(c);
Vertical* v = dynamic_cast<Vertical*> (c);
if (h){
//if (h->getY() == (*it)->getY()) h->setY(yc);
h->setY(yc);
} else if (v) {
//if (v->getX() == (*it)->getX()) v->setX(xc);
v->setX(xc);
Point center ( _xmin+getWidth()/2, _ymin+getHeight()/2 );
for ( Contact* contact : _gcontacts ) {
for ( Component* component : contact->getSlaveComponents() ) {
Horizontal* horizontal = dynamic_cast<Horizontal*>( component );
if (horizontal and (flags & Flags::Vertical)) {
horizontal->setY( center.getY() );
} else {
Vertical* vertical = dynamic_cast<Vertical*>( component );
if (vertical and (flags & Flags::Horizontal)) {
vertical->setX( center.getX() );
}
}
}
(*it)->setX(xc);
(*it)->setY(yc);
if (not contact->getAnchor()) contact->setPosition( center );
}
UpdateSession::close();
}
@ -964,7 +1090,7 @@ namespace Anabatic {
if (_gcontacts[i] == unref) {
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] );
_gcontacts[ _gcontacts.size()-1 ]->destroy();
_gcontacts.pop_back();
@ -1100,7 +1226,7 @@ namespace Anabatic {
}
float GCell::getHCapacity () const
int GCell::getHCapacity () const
{
int capacity = 0;
if (not _eastEdges.empty()) {
@ -1108,11 +1234,11 @@ namespace Anabatic {
} else {
for ( Edge* edge : _westEdges ) capacity += edge->getCapacity();
}
return (float)capacity;
return capacity;
}
float GCell::getVCapacity () const
int GCell::getVCapacity () const
{
int capacity = 0;
if (not _northEdges.empty()) {
@ -1120,7 +1246,20 @@ namespace Anabatic {
} else {
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 +1282,8 @@ namespace Anabatic {
float vdensity = 0.0;
for ( size_t i=_pinDepth ; i<_depth ; i++ ) {
if ( i%2 ) { hdensity += _densities[i]; ++hplanes; }
else { vdensity += _densities[i]; ++vplanes; }
if (isHorizontalPlane(i)) { hdensity += _densities[i]; ++hplanes; }
else { vdensity += _densities[i]; ++vplanes; }
}
if (hplanes) hdensity /= hplanes;
@ -1169,7 +1308,7 @@ namespace Anabatic {
float hdensity = 0.0;
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;
@ -1179,7 +1318,7 @@ namespace Anabatic {
float vdensity = 0.0;
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;
@ -1191,11 +1330,11 @@ namespace Anabatic {
}
} else if (getAnabatic()->getDensityMode() == MaxHDensity) {
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) {
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];
}
}
@ -1210,7 +1349,7 @@ namespace Anabatic {
_blockages[depth] += length;
_flags |= Flags::Invalidated;
cdebug_log(149,0) << "GCell:addBlockage() " << this << " "
cdebug_log(149,0) << "GCell::addBlockage() " << this << " "
<< depth << ":" << DbU::getValueString(_blockages[depth]) << endl;
}
@ -1244,11 +1383,17 @@ namespace Anabatic {
size_t begin = 0;
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] );
cdebug_log(9000,0) << "GCell::removeHSegment() " << this << endl;
cdebug_log(9000,0) << " " << segment << endl;
}
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;
return;
}
@ -1296,57 +1441,45 @@ namespace Anabatic {
_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( _vsegments.begin(), _vsegments.end(), AutoSegment::CompareByDepthLength() );
float hcapacity = getHCapacity ();
float vcapacity = getVCapacity ();
float ccapacity = hcapacity * vcapacity * 4;
DbU::Unit width = getXMax() - getXMin();
DbU::Unit height = getYMax() - getYMin();
DbU::Unit hpenalty = 0 /*_box.getWidth () / 3*/;
DbU::Unit vpenalty = 0 /*_box.getHeight() / 3*/;
DbU::Unit uLengths1 [ _depth ];
DbU::Unit uLengths2 [ _depth ];
float localCounts [ _depth ];
vector<UsedFragments> ufragments ( _depth );
float ccapacity = getHCapacity() * getVCapacity() * (_depth-_pinDepth);
DbU::Unit width = getXMax() - getXMin();
DbU::Unit height = getYMax() - getYMin();
DbU::Unit hpenalty = 0 /*_box.getWidth () / 3*/;
DbU::Unit vpenalty = 0 /*_box.getHeight() / 3*/;
DbU::Unit uLengths1 [ _depth ];
DbU::Unit uLengths2 [ _depth ];
float localCounts [ _depth ];
vector<UsedFragments> ufragments ( _depth );
for ( size_t i=0 ; i<_depth ; i++ ) {
ufragments[i].setPitch ( Session::getPitch(i) );
_feedthroughs[i] = 0.0;
uLengths1 [i] = 0;
uLengths2 [i] = 0;
localCounts [i] = 0.0;
_globalsCount[i] = 0.0;
if (Session::getDirection(i) & Flags::Horizontal) {
ufragments[i].setSpan ( getXMin(), getXMax() );
ufragments[i].setCapacity( (size_t)hcapacity );
} else {
ufragments[i].setSpan ( getYMin(), getYMax() );
ufragments[i].setCapacity( (size_t)vcapacity );
}
ufragments[i].setCapacity( (size_t)getCapacity(i) );
if (isHorizontalPlane(i)) ufragments[i].setSpan( getXMin(), getXMax() );
else ufragments[i].setSpan( getYMin(), getYMax() );
}
// Compute wirelength associated to contacts (in DbU::Unit converted to float).
AutoSegment::DepthLengthSet processeds;
for ( AutoContact* contact : _contacts ) {
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++ ) {
if (Session::getDirection(i) & Flags::Horizontal)
uLengths2[i] += uLengths1[i]+hpenalty;
else
uLengths2[i] += uLengths1[i]+vpenalty; break;
if (isHorizontalPlane(i)) uLengths2[i] += uLengths1[i]+hpenalty;
else uLengths2[i] += uLengths1[i]+vpenalty;
}
}
// Add the "pass through" horizontal segments.
if ( _hsegments.size() ) {
if (not _hsegments.empty()) {
const Layer* layer = _hsegments[0]->getLayer();
size_t depth = Session::getRoutingGauge()->getLayerDepth(layer);
size_t count = 0;
@ -1370,7 +1503,7 @@ namespace Anabatic {
}
// Add the "pass through" vertical segments.
if ( _vsegments.size() ) {
if (not _vsegments.empty()) {
const Layer* layer = _vsegments[0]->getLayer();
size_t depth = Session::getRoutingGauge()->getLayerDepth(layer);
size_t count = 0;
@ -1378,7 +1511,7 @@ namespace Anabatic {
_globalsCount[depth] += 1.0;
ufragments[depth].incGlobals();
if ( layer != _vsegments[i]->getLayer() ) {
if (layer != _vsegments[i]->getLayer()) {
uLengths2[depth] += count * height;
count = 0;
@ -1388,7 +1521,7 @@ namespace Anabatic {
count++;
_feedthroughs[depth] += 1.0;
}
if ( count ) {
if (count) {
uLengths2[depth] += count * height;
}
}
@ -1396,17 +1529,23 @@ namespace Anabatic {
// Add the blockages.
for ( size_t i=0 ; i<_depth ; i++ ) {
uLengths2[i] += _blockages[i];
if (not i) continue;
if ((float)(_blockages[i] * Session::getPitch(i)) > 0.40*(float)(width*height)) {
flags() |= Flags::GoStraight;
//cerr << "| Set GoStraight on " << this << endl;
}
}
// Compute the number of non pass-through tracks.
if (processeds.size()) {
if (not processeds.empty()) {
AutoSegment::DepthLengthSet::iterator isegment = processeds.begin();
const Layer* layer = (*isegment)->getLayer();
DbU::Unit axis = (*isegment)->getAxis();
size_t depth = Session::getRoutingGauge()->getLayerDepth(layer);
size_t count = 0;
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;
if ( (*isegment)->isGlobal() ) _globalsCount[depth] += 1.0;
@ -1423,9 +1562,11 @@ namespace Anabatic {
// Normalize: 0 < d < 1.0 (divide by H/V capacity).
for ( size_t i=0 ; i<_depth ; i++ ) {
int capacity = getCapacity(i);
if (Session::getDirection(i) & Flags::Horizontal) {
if (width) {
_densities [i] = ((float)uLengths2[i]) / ( hcapacity * (float)width );
if (width and capacity) {
_densities [i] = ((float)uLengths2[i]) / (float)( capacity * width );
_feedthroughs [i] += (float)(_blockages[i] / width);
_fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)width;
} else {
@ -1434,8 +1575,8 @@ namespace Anabatic {
_fragmentations[i] = 0;
}
} else {
if (height) {
_densities [i] = ((float)uLengths2[i]) / ( vcapacity * (float)height );
if (height and capacity) {
_densities [i] = ((float)uLengths2[i]) / (float)( capacity * height );
_feedthroughs [i] += (float)(_blockages[i] / height);
_fragmentations[i] = (float)ufragments[i].getMaxFree().getSize() / (float)height;
} else {
@ -1448,10 +1589,8 @@ namespace Anabatic {
if (_densities[i] >= 1.0) _flags |= Flags::Saturated;
}
if (ccapacity)
_cDensity = ( (float)_contacts.size() ) / ccapacity;
else
_cDensity = 0;
if (ccapacity) _cDensity = ( (float)_contacts.size() ) / ccapacity;
else _cDensity = 0;
_flags.reset( Flags::Invalidated );
checkDensity();
@ -1462,17 +1601,16 @@ namespace Anabatic {
void GCell::truncDensities ()
{
int hcapacity = (int)getHCapacity();
int vcapacity = (int)getVCapacity();
Box bBox = getBoundingBox();
Box bBox = getBoundingBox();
for ( size_t i=0 ; i<_depth ; i++ ) {
if (Session::getDirection(i) & Flags::Horizontal) {
if (_blockages[i] > hcapacity * bBox.getWidth())
_blockages[i] = hcapacity * bBox.getWidth();
int capacity = getCapacity(i);
if (isHorizontalPlane(i)) {
if (_blockages[i] > capacity * bBox.getWidth())
_blockages[i] = capacity * bBox.getWidth();
} else {
if (_blockages[i] > vcapacity * bBox.getHeight())
_blockages[i] = vcapacity * bBox.getHeight();
if (_blockages[i] > capacity * bBox.getHeight())
_blockages[i] = capacity * bBox.getHeight();
}
}
_flags &= ~Flags::Saturated;
@ -1508,20 +1646,31 @@ namespace Anabatic {
{
if (isInvalidated()) const_cast<GCell*>(this)->updateDensity();
float capacity = 0.0;
if (Session::getDirection(depth) & Flags::Horizontal) capacity = getHCapacity();
else capacity = getVCapacity();
float capacity = getCapacity(depth);
cdebug_log(149,0) << " | hasFreeTrack [" << getId() << "] depth:" << depth << " "
<< Session::getRoutingGauge()->getRoutingLayer(depth)->getName()
//<< " " << (_densities[depth]*capacity) << " vs. " << capacity
<< " " << _feedthroughs[depth] << " vs. " << capacity
<< " " << this << endl;
<< Session::getRoutingGauge()->getRoutingLayer(depth)->getName()
//<< " " << (_densities[depth]*capacity) << " vs. " << capacity
<< " " << _feedthroughs[depth] << " vs. " << capacity
<< " " << this << endl;
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 )
{
set<RoutingPad*> rps;
@ -1634,7 +1783,7 @@ namespace Anabatic {
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;
updateDensity();
@ -1656,7 +1805,7 @@ namespace Anabatic {
if (segmentDepth < depth) continue;
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))
return true;
@ -1666,16 +1815,16 @@ namespace Anabatic {
}
void GCell::setEdgesOccupancy ( unsigned int width, unsigned int height )
void GCell::forceEdgesCapacities ( unsigned int hcapacity, unsigned int vcapacity )
{
getEastEdge()->setCapacity(width);
getWestEdge()->setCapacity(width);
getNorthEdge()->setCapacity(height);
getSouthEdge()->setCapacity(height);
getEastEdge()->setRealOccupancy(0);
getWestEdge()->setRealOccupancy(0);
getNorthEdge()->setRealOccupancy(0);
getSouthEdge()->setRealOccupancy(0);
if (getEastEdge() ) getEastEdge ()->forceCapacity( hcapacity );
if (getWestEdge() ) getWestEdge ()->forceCapacity( hcapacity );
if (getNorthEdge()) getNorthEdge()->forceCapacity( vcapacity );
if (getSouthEdge()) getSouthEdge()->forceCapacity( vcapacity );
if (getEastEdge() ) getEastEdge ()->setRealOccupancy(0);
if (getWestEdge() ) getWestEdge ()->setRealOccupancy(0);
if (getNorthEdge()) getNorthEdge()->setRealOccupancy(0);
if (getSouthEdge()) getSouthEdge()->setRealOccupancy(0);
}
@ -1688,6 +1837,13 @@ namespace Anabatic {
string s = Super::_getString();
s.insert( s.size()-1, " "+getString(getBoundingBox()) );
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;
}
@ -1702,6 +1858,7 @@ namespace Anabatic {
record->add( getSlot("_northEdges" , &_northEdges) );
record->add( DbU::getValueSlot("_xmin", &_xmin) );
record->add( DbU::getValueSlot("_ymin", &_ymin) );
record->add( getSlot ( "_gcontacts", &_gcontacts ) );
record->add( getSlot ( "_vsegments", &_vsegments ) );
record->add( getSlot ( "_hsegments", &_hsegments ) );
record->add( getSlot ( "_contacts" , &_contacts ) );
@ -1713,7 +1870,7 @@ namespace Anabatic {
ostringstream s;
const Layer* layer = rg->getRoutingLayer(depth)->getBlockageLayer();
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 ) {

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -31,11 +31,287 @@
#include "hurricane/Horizontal.h"
#include "hurricane/Cell.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContact.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoSegment.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 {
using Hurricane::DebugSession;
@ -59,9 +335,55 @@ namespace Anabatic {
cmess1 << " o Desaturate layer "
<< 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 );
if (optimized) {
for ( GCell* gcell : invalidateds ) {
queue.push( gcell->cloneKey(depth) );
}
}
}
}
delete topKey;
}
}
#if OLD_QUEUE_DISABLED
GCellDensitySet queue ( depth, getGCells() );
GCell::Set invalidateds;
GCell::Set invalidateds;
bool optimized = true;
while ( optimized ) {
@ -73,7 +395,7 @@ namespace Anabatic {
size_t i = 0;
for ( ; igcell!=queue.getGCells().end() ; ++igcell, ++i ) {
cdebug_log(149,0) << "_desaturate: [" << depth << "]:"
<< (*igcell)->getDensity(depth) << " " << *igcell << endl;
<< (*igcell)->getDensity(depth) << " " << *igcell << endl;
if (not (*igcell)->isSaturated(depth)) {
cdebug_log(149,0) << "STOP desaturated: @" << i << " " << *igcell << endl;
@ -95,6 +417,7 @@ namespace Anabatic {
}
}
}
#endif
}
@ -117,8 +440,14 @@ namespace Anabatic {
}
global++;
if ((*isegment)->getLayer() == Session::getRoutingLayer(1)) (*isegment)->setLayer( Session::getRoutingLayer(3) );
if ((*isegment)->getLayer() == Session::getRoutingLayer(2)) (*isegment)->setLayer( Session::getRoutingLayer(4) );
if ((*isegment)->getLayer() == Session::getRoutingLayer(1)) {
(*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 +471,7 @@ namespace Anabatic {
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_tabw(145,1);
@ -172,8 +501,14 @@ namespace Anabatic {
netGlobal++;
cdebug_log(145,0) << "Migrate to M4/M5: " << autoSegment << endl;
if (autoSegment->isHorizontal()) autoSegment->setLayer( Session::getRoutingLayer(3) );
if (autoSegment->isVertical ()) autoSegment->setLayer( Session::getRoutingLayer(4) );
if (autoSegment->isHorizontal()) {
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 +534,124 @@ 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<AutoSegment*> perpandiculars;
vector<AutoSegment*> northBounds;
vector<AutoSegment*> southBounds;
DbU::Unit leftBound;
DbU::Unit rightBound;
//bool hasNorth = false;
//bool hasSouth = false;
AutoSegment::getTopologicalInfos( horizontal
, collapseds
, perpandiculars
, leftBound
, rightBound
);
for ( AutoSegment* perpandicular : perpandiculars ) {
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
void AnabaticEngine::moveULeft ( AutoSegment* seed, set<Net*>& globalNets, GCell::Set& invalidateds )
{
Net* net = seed->getNet();
DebugSession::open( net, 140, 150 );
DebugSession::open( net, 145, 150 );
cdebug_log(9000,0) << "Deter| Move left: " << seed << endl;
@ -240,7 +688,7 @@ namespace Anabatic {
void AnabaticEngine::moveURight ( AutoSegment* seed, set<Net*>& globalNets, GCell::Set& invalidateds )
{
Net* net = seed->getNet();
DebugSession::open( net, 140, 150 );
DebugSession::open( net, 145, 150 );
cdebug_log(9000,0) << "Deter| Move right: " << seed << endl;
@ -280,7 +728,7 @@ namespace Anabatic {
Net* net = seed->getNet();
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;
if (not seed->canMoveUp( 1.0, Flags::Propagate|Flags::AllowTerminal|Flags::NoCheckLayer) ) {
@ -306,7 +754,7 @@ namespace Anabatic {
if (not segment->isStrongTerminal()) locals.push_back( segment );
continue;
}
if ( (segment->getLength() < 3*Session::getSliceHeight()) and (segment != seed) ) {
if ( (segment->getAnchoredLength() < 3*Session::getSliceHeight()) and (segment != seed) ) {
locals.push_back( segment );
continue;
}
@ -474,6 +922,8 @@ namespace Anabatic {
void AnabaticEngine::layerAssign ( uint32_t method )
{
//DebugSession::open( 145, 150 );
cdebug_log(9000,0) << "Deter| Layer Assignment" << endl;
set<Net*> globalNets;
@ -486,8 +936,9 @@ namespace Anabatic {
if (Session::getAllowedDepth() >= 3) {
switch ( method ) {
case EngineLayerAssignByLength: _layerAssignByLength( total, global, globalNets ); break;
case EngineLayerAssignByTrunk: _layerAssignByTrunk ( total, global, globalNets ); break;
case EngineLayerAssignByLength: _layerAssignByLength ( total, global, globalNets ); break;
case EngineLayerAssignByTrunk: _layerAssignByTrunk ( total, global, globalNets ); break;
case EngineLayerAssignNoGlobalM2V: _layerAssignNoGlobalM2V ( total, global, globalNets ); break;
case EngineNoNetLayerAssign: break;
default:
stopMeasures();
@ -502,7 +953,8 @@ namespace Anabatic {
globalNets.clear();
Session::revalidate();
if (getConfiguration()->getAllowedDepth() > 2) {
if ( (method != EngineLayerAssignNoGlobalM2V)
and (getConfiguration()->getAllowedDepth() > 2) ) {
for ( size_t depth=1 ; depth <= getConfiguration()->getAllowedDepth()-2; ++depth ) {
_desaturate( depth, globalNets, total, global );
if ( (depth > 1) and ((depth-1)%2 == 1) ) Session::revalidate();
@ -519,6 +971,54 @@ namespace Anabatic {
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() > 8) {
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();
Session::close();
@ -529,6 +1029,8 @@ namespace Anabatic {
// cmess2 << " - Global segments : " << global << endl;
// cmess2 << " - Ratio : "
// << ((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>" -*-
//
// 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 |
@ -78,8 +78,10 @@ namespace Anabatic {
int index = xy2maxIndex(x,y);
cdebug_log(110,0) << "Matrix::getUnder() ("
<< DbU::getValueString(x) << " "
<< DbU::getValueString(y) << ") index:" << index << endl;
<< DbU::getValueString(x) << " "
<< DbU::getValueString(y) << ") index:" << index
<< " " << ((index < 0) ? NULL : _gcells[index]->getUnder(x,y)) << endl;
return (index < 0) ? NULL : _gcells[index]->getUnder(x,y);
}
@ -117,7 +119,7 @@ namespace Anabatic {
DbU::Unit dy = updateArea.getYMin() - _area.getYMin();
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) << "indexMax:" << indexMax << 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
{
cdebug_log(111,0) << this << endl;

2478
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,352 @@
// -*- 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 () { }
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 );
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,676 @@
// -*- 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 () { }
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 );
DbU::Unit gridPosition = 0;
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;
}
}
#if 0
// Quasi-punctual M1 terminal.
if (flags & VSmall) {
Box ab = rp->getCell()->getBoundingBox();
RoutingLayerGauge* gaugeMetal3 = Session::getLayerGauge( 2 );
DbU::Unit metal3axis = gaugeMetal3->getTrackPosition( ab.getYMin()
, ab.getYMax()
, sourcePosition.getY()
, Constant::Nearest );
DbU::Unit viaSideProtect = Session::getViaWidth((size_t)0);
AutoContact* sourceVia12 = AutoContactTerminal::create( sourceGCell
, rp
, Session::getContactLayer(0)
, sourcePosition
, viaSideProtect, viaSideProtect
);
AutoContact* targetVia12 = AutoContactTerminal::create( targetGCell
, rp
, Session::getContactLayer(0)
, targetPosition
, viaSideProtect, viaSideProtect
);
AutoContact* sourceVia23 = AutoContactTurn::create( sourceGCell, net, Session::getContactLayer(1) );
AutoContact* targetVia23 = AutoContactTurn::create( targetGCell, net, Session::getContactLayer(1) );
sourceVia23->setY( metal3axis );
targetVia23->setY( metal3axis );
sourceVia23->setX( sourcePosition.getX() );
targetVia23->setX( targetPosition.getX() );
AutoSegment* segmentS = AutoSegment::create( sourceVia12, sourceVia23, Flags::Vertical );
AutoSegment* segmentT = AutoSegment::create( targetVia12, targetVia23, Flags::Vertical );
AutoSegment* segmentM = AutoSegment::create( sourceVia23, targetVia23, Flags::Horizontal );
sourceVia12->setFlags( CntFixed );
sourceVia23->setFlags( CntFixed );
targetVia12->setFlags( CntFixed );
targetVia23->setFlags( CntFixed );
segmentS->setFlags( AutoSegment::SegFixed );
segmentT->setFlags( AutoSegment::SegFixed );
segmentM->setFlags( AutoSegment::SegFixed );
cdebug_log(145,0) << "Hard protect: " << rp << endl;
cdebug_log(145,0) << "X:" << DbU::getValueString(sourcePosition.getX())
<< " Metal3 Track Y:" << DbU::getValueString(metal3axis) << endl;
}
#endif
// Non-M1 terminal or punctual M1 protections.
if ( (rpDepth != 0) or ((sourcePosition == targetPosition) and (gridPosition == 0)) ) {
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* NetBuilderVH::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
{
cdebug_log(145,1) << getTypeName() << "::doRp_Access() - flags:" << flags << endl;
AutoContact* rpContactSource;
AutoContact* rpContactTarget;
flags |= checkRoutingPadSize( rp );
doRp_AutoContacts( gcell, rp, rpContactSource, rpContactTarget, flags );
if (not (flags & (HAccess|HAccessEW))) {
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoContact* subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpContactSource, subContact1, Flags::Vertical );
AutoSegment::create( subContact1, subContact2, Flags::Horizontal );
rpContactSource = subContact2;
} else {
if (flags & VSmall) {
AutoContact* subContact1 = NULL;
if (flags & HAccessEW)
subContact1 = AutoContactHTee::create( gcell, rp->getNet(), Session::getContactLayer(1) );
else
subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpContactSource, subContact1, Flags::Vertical );
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 )
{
cdebug_log(145,1) << "propagateConstraintFromRp() - " << rp << endl;
cdebug_log(146,1) << "propagateConstraintFromRp() - " << rp << endl;
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) );
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*> horizontalSegments;
for ( AutoSegment* segment : sourceContact->getAutoSegments() ) {
cdebug_log(145,0) << "Examining: " << segment << endl;
cdebug_log(146,0) << "Examining: " << segment << endl;
AutoContact* targetContact = segment->getOppositeAnchor(sourceContact);
if (targetContact) {
if (segment->isHorizontal()) {
cdebug_log(145,0) << "On horizontal stack " << segment << endl;
cdebug_log(146,0) << "On horizontal stack " << segment << endl;
horizontalSegments.insert( segment );
} else {
cdebug_log(145,0) << "On vertical stack " << segment << endl;
cdebug_log(146,0) << "On vertical stack " << segment << endl;
verticalSegments.insert( segment );
}
}
}
Box constraintBox = sourceContact->getConstraintBox();
cdebug_log(145,0) << "Contraint: " << constraintBox << endl;
// 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 ) {
AutoContact* contact = NULL;
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();
cdebug_log(145,0) << "contact: " << contact << endl;
cdebug_log(146,0) << "contact: " << contact << endl;
if (contact) {
cdebug_log(145,0) << "Apply to (target): " << contact << endl;
cdebug_log(146,0) << "Apply to (target): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getYMin()
, constraintBox.getYMax()
, Flags::Horizontal|Flags::WarnOnError );
}
contact = aligned->getAutoSource();
cdebug_log(145,0) << "contact: " << contact << endl;
cdebug_log(146,0) << "contact: " << contact << endl;
if (contact) {
cdebug_log(145,0) << "Apply to (source): " << contact << endl;
cdebug_log(146,0) << "Apply to (source): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getYMin()
, constraintBox.getYMax()
, Flags::Horizontal|Flags::WarnOnError );
@ -118,23 +118,23 @@ namespace {
}
// 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 ) {
AutoContact* contact = NULL;
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();
if (contact) {
cdebug_log(145,0) << "Apply to (target): " << contact << endl;
cdebug_log(146,0) << "Apply to (target): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getXMin()
, constraintBox.getXMax()
, Flags::Vertical|Flags::WarnOnError );
}
contact = aligned->getAutoSource();
if (contact) {
cdebug_log(145,0) << "Apply to (source): " << contact << endl;
cdebug_log(146,0) << "Apply to (source): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getXMin()
, constraintBox.getXMax()
, Flags::Vertical|Flags::WarnOnError );
@ -144,8 +144,8 @@ namespace {
}
}
cdebug_log(145,0) << "propagateConstraintFromRp() - Exit" << endl;
cdebug_tabw(145,-1);
cdebug_log(146,0) << "propagateConstraintFromRp() - Exit" << endl;
cdebug_tabw(146,-1);
}
@ -159,35 +159,128 @@ namespace Anabatic {
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 )
{
DebugSession::open( net, 140, 150);
DebugSession::open( net, 146, 150);
cdebug_log(149,0) << "Anabatic::computeNetConstraints( " << net << " )" << endl;
cdebug_tabw(145,1);
cdebug_tabw(146,1);
vector<RoutingPad*> routingPads;
forEach ( Component*, icomponent, net->getComponents() ) {
Contact* contact = dynamic_cast<Contact*>( *icomponent );
for ( Component* component : net->getComponents() ) {
Contact* contact = dynamic_cast<Contact*>( component );
if (contact) {
AutoContact* autoContact = Session::lookup( contact );
if (autoContact)
autoContact->restoreNativeConstraintBox();
} else {
RoutingPad* routingPad = dynamic_cast<RoutingPad*>( *icomponent );
if (routingPad) routingPads.push_back( routingPad );
Segment* segment = dynamic_cast<Segment*>( component );
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] );
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() ) {
// AutoSegment* autoSegment = Session::lookup( *isegment );
// if (autoSegment) autoSegment->toConstraintAxis();
// }
cdebug_tabw(145,-1);
cdebug_tabw(146,-1);
DebugSession::close();
}

View File

@ -2,7 +2,7 @@
// -*- C++ -*-
//
// 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 |
@ -61,7 +61,7 @@ namespace Anabatic {
void AnabaticEngine::toOptimals ( Net* net )
{
DebugSession::open( net, 140, 150 );
DebugSession::open( net, 145, 150 );
cdebug_log(149,0) << "Anabatic::_toOptimals( " << net << " )" << endl;
cdebug_tabw(145,1);

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -35,6 +35,7 @@ namespace Anabatic {
using Hurricane::RegularLayer;
using Hurricane::Component;
using Hurricane::Pin;
using Hurricane::Plug;
using Hurricane::DeepNet;
using Hurricane::Cell;
using Hurricane::NetRoutingExtension;
@ -66,12 +67,16 @@ namespace Anabatic {
void AnabaticEngine::setupPreRouteds ()
size_t AnabaticEngine::setupPreRouteds ()
{
cmess1 << " o Looking for fixed or manually global routed nets." << endl;
openSession();
size_t toBeRouteds = 0;
Box ab = getCell()->getAbutmentBox();
ab.inflate( -1 );
for ( Net* net : getCell()->getNets() ) {
if (net == _blockageNet) continue;
if (net->getType() == Net::Type::POWER ) continue;
@ -81,13 +86,93 @@ namespace Anabatic {
vector<Segment*> segments;
vector<Contact*> contacts;
bool isPreRouted = false;
bool isFixed = false;
size_t rpCount = 0;
bool isManualGlobalRouted = false;
bool isManualDetailRouted = false;
bool isFixed = false;
size_t rpCount = 0;
if (net->isDeepNet()) {
rpCount = 2;
for( Component* component : net->getComponents() ) {
if (dynamic_cast<Pin *>(component)) continue;
if (dynamic_cast<Plug*>(component)) continue;
const RegularLayer* layer = dynamic_cast<const RegularLayer*>(component->getLayer());
if (layer and (layer->getBasicLayer()->getMaterial() == BasicLayer::Material::blockage))
continue;
if ( not Session::isGaugeLayer(component->getLayer())
and not Session::isGLayer (component->getLayer())) {
const BasicLayer* basicLayer = dynamic_cast<const BasicLayer*>( component->getLayer() );
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()))
isFixed = true;
}
} else {
Vertical* vertical = dynamic_cast<Vertical*>(component);
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 );
if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer()))
isFixed = true;
}
} else {
Contact* contact = dynamic_cast<Contact*>(component);
if (contact) {
if (not ab.contains(contact->getCenter())) continue;
if (Session::isGLayer(component->getLayer())) {
isManualGlobalRouted = 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 {
RoutingPad* rp = dynamic_cast<RoutingPad*>(component);
if (rp) {
++rpCount;
} else {
// Plug* plug = dynamic_cast<Plug*>(component);
// if (plug) {
// cerr << "buildPreRouteds(): " << plug << endl;
// ++rpCount;
// }
}
}
}
}
}
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() ) {
@ -95,84 +180,52 @@ namespace Anabatic {
if (dynamic_cast<Vertical*> (component)) { isFixed = true; break; }
if (dynamic_cast<Contact*> (component)) { isFixed = true; break; }
}
} else {
for( Component* component : net->getComponents() ) {
if (dynamic_cast<Pin*>(component)) continue;
const RegularLayer* layer = dynamic_cast<const RegularLayer*>(component->getLayer());
if (layer and (layer->getBasicLayer()->getMaterial() == BasicLayer::Material::blockage))
continue;
Horizontal* horizontal = dynamic_cast<Horizontal*>(component);
if (horizontal) {
segments.push_back( horizontal );
isPreRouted = true;
if (horizontal->getWidth() != Session::getWireWidth(horizontal->getLayer()))
isFixed = true;
} else {
Vertical* vertical = dynamic_cast<Vertical*>(component);
if (vertical) {
isPreRouted = true;
segments.push_back( vertical );
if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer()))
isFixed = true;
} else {
Contact* contact = dynamic_cast<Contact*>(component);
if (contact) {
isPreRouted = true;
contacts.push_back( contact );
if ( (contact->getWidth () != Session::getViaWidth(contact->getLayer()))
or (contact->getHeight() != Session::getViaWidth(contact->getLayer())) )
isFixed = true;
} else {
RoutingPad* rp = dynamic_cast<RoutingPad*>(component);
if (rp) {
++rpCount;
} else {
// Plug* plug = dynamic_cast<Plug*>(component);
// if (plug) {
// cerr << "buildPreRouteds(): " << plug << endl;
// ++rpCount;
// }
}
}
}
}
}
}
if (isFixed or isPreRouted or (rpCount < 2)) {
if (isFixed or isManualDetailRouted or isManualGlobalRouted or (rpCount < 2)) {
NetData* ndata = getNetData( net, Flags::Create );
NetRoutingState* state = ndata->getNetRoutingState();
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 );
if (rpCount < 2)
state->setFlags ( NetRoutingState::Unconnected );
state->setFlags( NetRoutingState::Unconnected );
if (isFixed) {
cmess2 << " - <" << net->getName() << "> is fixed." << endl;
state->unsetFlags( NetRoutingState::ManualGlobalRoute );
if (rpCount > 1)
cmess2 << " - <" << net->getName() << "> is fixed." << endl;
state->unsetFlags( NetRoutingState::ManualGlobalRoute|NetRoutingState::ManualDetailRoute );
state->setFlags ( NetRoutingState::Fixed );
} else {
} else if (isManualGlobalRouted) {
cmess2 << " - <" << net->getName() << "> is manually global routed." << endl;
} else if (isManualDetailRouted) {
if (rpCount > 1) {
cmess2 << " - <" << net->getName() << "> is manually global routed." << endl;
for ( auto icontact : contacts ) {
AutoContact::createFrom( icontact );
++toBeRouteds;
cmess2 << " - <" << net->getName() << "> is manually detail routed." << endl;
for ( auto contact : contacts ) {
AutoContact::createFrom( contact );
}
for ( auto isegment : segments ) {
AutoContact* source = Session::lookup( dynamic_cast<Contact*>( isegment->getSource() ));
AutoContact* target = Session::lookup( dynamic_cast<Contact*>( isegment->getTarget() ));
AutoSegment* autoSegment = AutoSegment::create( source, target, isegment );
for ( auto segment : segments ) {
AutoContact* source = Session::lookup( dynamic_cast<Contact*>( segment->getSource() ));
AutoContact* target = Session::lookup( dynamic_cast<Contact*>( segment->getTarget() ));
AutoSegment* autoSegment = AutoSegment::create( source, target, segment );
autoSegment->setFlags( AutoSegment::SegUserDefined|AutoSegment::SegAxisSet );
}
}
}
} else {
++toBeRouteds;
}
}
Session::close();
return toBeRouteds;
}

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -71,11 +71,12 @@ extern "C" {
PyObject* dictionnary = PyModule_GetDict(module);
PyObject* constant;
LoadObjectConstant( dictionnary,EngineLoadGrByNet ,"EngineLoadGrByNet" );
LoadObjectConstant( dictionnary,EngineLoadGrByGCell ,"EngineLoadGrByGCell" );
LoadObjectConstant( dictionnary,EngineLayerAssignByLength,"EngineLayerAssignByLength" );
LoadObjectConstant( dictionnary,EngineLayerAssignByTrunk ,"EngineLayerAssignByTrunk" );
LoadObjectConstant( dictionnary,EngineNoNetLayerAssign ,"EngineNoNetLayerAssign" );
LoadObjectConstant( dictionnary,EngineLoadGrByNet ,"EngineLoadGrByNet" );
LoadObjectConstant( dictionnary,EngineLoadGrByGCell ,"EngineLoadGrByGCell" );
LoadObjectConstant( dictionnary,EngineLayerAssignByLength ,"EngineLayerAssignByLength" );
LoadObjectConstant( dictionnary,EngineLayerAssignByTrunk ,"EngineLayerAssignByTrunk" );
LoadObjectConstant( dictionnary,EngineLayerAssignNoGlobalM2V,"EngineLayerAssignNoGlobalM2V" );
LoadObjectConstant( dictionnary,EngineNoNetLayerAssign ,"EngineNoNetLayerAssign" );
}

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Session.cpp<anabatic>" -*-
//
// 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 |
@ -17,6 +17,7 @@
#include <cstdlib>
#include <sstream>
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Cell.h"
@ -47,6 +48,7 @@ namespace Anabatic {
using namespace std;
using Hurricane::tab;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::ForEachIterator;
using Hurricane::UpdateSession;
using Hurricane::Horizontal;
@ -80,7 +82,12 @@ namespace Anabatic {
, _segmentRevalidateds()
, _netInvalidateds ()
, _netRevalidateds ()
{ }
{
_autoContacts .reserve( 1024 );
_doglegs .reserve( 1024 );
_segmentInvalidateds.reserve( 1024 );
_segmentRevalidateds.reserve( 1024 );
}
void Session::_postCreate ()
@ -158,6 +165,7 @@ namespace Anabatic {
canonical->setFlags( AutoSegment::SegCanonical );
cdebug_log(145,0) << "Canonical: " << canonical << endl;
Interval userConstraints = canonical->getUserConstraints();
for ( size_t j=0 ; j<aligneds.size() ; j++ ) {
if (isWeakGlobal and not aligneds[j]->isGlobal()) aligneds[j]->setFlags ( AutoSegment::SegWeakGlobal );
@ -171,14 +179,29 @@ namespace Anabatic {
}
aligneds[j]->unsetFlags( AutoSegment::SegCanonical );
cdebug_log(145,0) << "Secondary: " << aligneds[j] << endl;
userConstraints.intersection( aligneds[j]->getUserConstraints() );
}
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(145,0) << "Combined user constraints: " << userConstraints << endl;
//canonical->setAxis( canonical->getAxis(), Flags::Realignate );
if (canonical->isUnsetAxis()) canonical->toOptimalAxis( Flags::Realignate|Flags::Propagate );
else canonical->setAxis( canonical->getAxis(), Flags::Realignate|Flags::Propagate );
if (canonical->isUnsetAxis() and not canonical->isFixed())
canonical->toOptimalAxis( Flags::Realignate|Flags::Propagate );
else
canonical->setAxis( canonical->getAxis(), Flags::Realignate|Flags::Propagate );
aligneds.clear();
cdebug_tabw(145,-1);
}
@ -192,21 +215,21 @@ namespace Anabatic {
{
cdebug_log(145,1) << "Anabatic::Session::_revalidateTopology()" << endl;
set<Net*>::iterator inet = _netInvalidateds.begin();
for ( ; inet != _netInvalidateds.end() ; inet++ ) {
cdebug_log(145,0) << "Anabatic::Session::_revalidateTopology(Net*)" << *inet << endl;
_anabatic->updateNetTopology ( *inet );
_anabatic->computeNetConstraints( *inet );
_anabatic->_computeNetOptimals ( *inet );
_anabatic->_computeNetTerminals ( *inet );
for ( Net* net : _netInvalidateds ) {
cdebug_log(145,0) << "Anabatic::Session::_revalidateTopology(Net*)" << net << endl;
_anabatic->updateNetTopology ( net );
_anabatic->computeNetConstraints( net );
_anabatic->_computeNetOptimals ( net );
//_anabatic->_computeNetTerminals ( net );
}
_canonize ();
AutoSegment* segment = NULL;
for ( size_t i=0 ; i<_segmentInvalidateds.size() ; ++i ) {
if (_segmentInvalidateds[i]->isCanonical()) {
if (_segmentInvalidateds[i]->isUnsetAxis()) _segmentInvalidateds[i]->toOptimalAxis();
else _segmentInvalidateds[i]->toConstraintAxis();
segment = _segmentInvalidateds[i];
if (segment->isCanonical()) {
if (segment->isUnsetAxis()) segment->toOptimalAxis();
else segment->toConstraintAxis();
}
}
@ -236,6 +259,8 @@ namespace Anabatic {
cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl;
_segmentRevalidateds.clear();
std::sort( _segmentInvalidateds.begin(), _segmentInvalidateds.end()
, AutoSegment::CompareByRevalidate() );
for ( size_t i=0 ; i < _segmentInvalidateds.size() ; ++i, ++count ) {
_segmentInvalidateds[i]->revalidate();
if ( not _destroyedSegments.empty()
@ -337,20 +362,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 )
{
Box ab = _anabatic->getCell()->getAbutmentBox();
RoutingLayerGauge* lg = _routingGauge->getLayerGauge( 1 );
RoutingLayerGauge* lg = _routingGauge->getVerticalGauge();
DbU::Unit x = lg->getTrackPosition( ab.getXMin()
, lg->getTrackIndex( ab.getXMin()
, ab.getXMax()
, p.getX()
, Constant::Nearest ) );
if (x < constraint.getXMin()) x += lg->getPitch();
if (x > constraint.getXMax()) x -= lg->getPitch();
lg = _routingGauge->getLayerGauge( 2 );
lg = _routingGauge->getHorizontalGauge();
DbU::Unit y = lg->getTrackPosition( ab.getYMin()
, lg->getTrackIndex( ab.getYMin()
, ab.getYMax()

646
anabatic/src/anabatic/: Normal file
View File

@ -0,0 +1,646 @@
// -*- 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++ Header : "./anabatic/AutoSegment.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOSEGMENT_H
#define ANABATIC_AUTOSEGMENT_H
#include <set>
#include <iostream>
#include <functional>
#include "hurricane/Interval.h"
#include "hurricane/Segment.h"
#include "hurricane/Components.h"
#include "hurricane/Contact.h"
namespace Hurricane {
class Layer;
class Horizontal;
class Vertical;
class Cell;
}
#include "crlcore/RoutingGauge.h"
#include "anabatic/Constants.h"
#include "anabatic/GCell.h"
#include "anabatic/AutoSegments.h"
#include "anabatic/Session.h"
namespace Anabatic {
using std::array;
using std::set;
using std::cerr;
using std::endl;
using std::binary_function;
using Hurricane::StaticObservable;
using Hurricane::BaseObserver;
using Hurricane::tab;
using Hurricane::Interval;
using Hurricane::Layer;
using Hurricane::Components;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::Cell;
using CRL::RoutingGauge;
class AutoHorizontal;
class AutoVertical;
// -------------------------------------------------------------------
// Class : "AutoSegment".
class AutoSegment {
friend class AutoHorizontal;
friend class AutoVertical;
public:
static const uint64_t SegNoFlags = 0L;
static const uint64_t SegHorizontal = (1L<< 0);
static const uint64_t SegFixed = (1L<< 1);
static const uint64_t SegFixedAxis = (1L<< 2);
static const uint64_t SegGlobal = (1L<< 3);
static const uint64_t SegWeakGlobal = (1L<< 4);
static const uint64_t SegLongLocal = (1L<< 5);
static const uint64_t SegCanonical = (1L<< 6);
static const uint64_t SegBipoint = (1L<< 7);
static const uint64_t SegDogleg = (1L<< 8);
static const uint64_t SegStrap = (1L<< 9);
static const uint64_t SegSourceTop = (1L<<10);
static const uint64_t SegSourceBottom = (1L<<11);
static const uint64_t SegTargetTop = (1L<<12);
static const uint64_t SegTargetBottom = (1L<<13);
static const uint64_t SegIsReduced = (1L<<14);
static const uint64_t SegDrag = (1L<<15);
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 SegWeakTerminal1 = (1L<<19); // Replace TopologicalEnd.
static const uint64_t SegWeakTerminal2 = (1L<<20); // Replace TopologicalEnd.
static const uint64_t SegNotSourceAligned = (1L<<21);
static const uint64_t SegNotTargetAligned = (1L<<22);
static const uint64_t SegUnbound = (1L<<23);
static const uint64_t SegHalfSlackened = (1L<<24);
static const uint64_t SegSlackened = (1L<<25);
static const uint64_t SegAxisSet = (1L<<26);
static const uint64_t SegInvalidated = (1L<<27);
static const uint64_t SegInvalidatedSource = (1L<<28);
static const uint64_t SegInvalidatedTarget = (1L<<29);
static const uint64_t SegInvalidatedLayer = (1L<<30);
static const uint64_t SegCreated = (1L<<31);
static const uint64_t SegUserDefined = (1L<<32);
static const uint64_t SegAnalog = (1L<<33);
static const uint64_t SegWide = (1L<<34);
// Masks.
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
static const uint64_t SegSpinTop = SegSourceTop |SegTargetTop;
static const uint64_t SegSpinBottom = SegSourceBottom |SegTargetBottom;
static const uint64_t SegDepthSpin = SegSpinTop |SegSpinBottom;
public:
class Observable : public StaticObservable<1> {
public:
enum Indexes { TrackSegment = 0
};
public:
inline Observable ();
private:
Observable ( const StaticObservable& );
Observable& operator= ( const StaticObservable& );
};
public:
enum ObserverFlag { Create = (1 << 0)
, Destroy = (1 << 1)
, Invalidate = (1 << 2)
, Revalidate = (1 << 3)
, RevalidatePPitch = (1 << 4)
};
public:
typedef std::function< void(AutoSegment*) > RevalidateCb_t;
public:
static void setAnalogMode ( bool );
static bool getAnalogMode ();
inline static DbU::Unit getViaToTopCap ( size_t depth );
inline static DbU::Unit getViaToBottomCap ( size_t depth );
inline static DbU::Unit getViaToSameCap ( size_t depth );
static AutoSegment* create ( AutoContact* source
, AutoContact* target
, Segment* hurricaneSegment
);
static AutoSegment* create ( AutoContact* source
, AutoContact* target
, Flags dir
, size_t depth=RoutingGauge::nlayerdepth
);
void destroy ();
// Wrapped Segment Functions.
virtual Segment* base () const = 0;
virtual Segment* base () = 0;
virtual Horizontal* getHorizontal () { return NULL; };
virtual Vertical* getVertical () { return NULL; };
inline Cell* getCell () const;
inline Net* getNet () const;
inline const Layer* getLayer () const;
inline Box getBoundingBox () const;
inline Hook* getSourceHook ();
inline Hook* getTargetHook ();
inline Contact* getSource () const;
inline Contact* getTarget () const;
inline Component* getOppositeAnchor ( Component* ) const;
inline Components getAnchors () const;
virtual DbU::Unit getX () const;
virtual DbU::Unit getY () const;
inline DbU::Unit getWidth () const;
inline DbU::Unit getContactWidth () const;
inline DbU::Unit getLength () const;
inline DbU::Unit getSourcePosition () const;
inline DbU::Unit getTargetPosition () const;
inline DbU::Unit getSourceX () const;
inline DbU::Unit getSourceY () const;
inline DbU::Unit getTargetX () const;
inline DbU::Unit getTargetY () const;
inline void invert ();
inline void setLayer ( const Layer* );
// Predicates.
inline bool isHorizontal () const;
inline bool isVertical () const;
inline bool isGlobal () const;
inline bool isWeakGlobal () const;
inline bool isLongLocal () const;
inline bool isLocal () const;
inline bool isFixed () const;
inline bool isFixedAxis () const;
inline bool isBipoint () const;
inline bool isWeakTerminal () const;
inline bool isWeakTerminal1 () const;
inline bool isWeakTerminal2 () const;
inline bool isTerminal () const;
inline bool isDrag () const;
inline bool isNotSourceAligned () const;
inline bool isNotTargetAligned () const;
inline bool isNotAligned () const;
bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const;
inline bool isSourceTerminal () const;
inline bool isTargetTerminal () const;
inline bool isLayerChange () const;
inline bool isSpinTop () const;
inline bool isSpinBottom () const;
inline bool isSpinTopOrBottom () const;
inline bool isReduced () const;
inline bool isStrap () const;
inline bool isDogleg () const;
inline bool isUnbound () const;
inline bool isInvalidated () const;
inline bool isInvalidatedLayer () const;
inline bool isCreated () const;
inline bool isCanonical () const;
inline bool isUnsetAxis () const;
inline bool isSlackened () const;
inline bool isUserDefined () const;
bool isReduceCandidate () const;
bool isUTurn () const;
inline bool isAnalog () const;
inline bool isWide () const;
virtual bool _canSlacken () const = 0;
bool canReduce () 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.
inline unsigned long getId () const;
inline uint64_t getFlags () const;
virtual Flags getDirection () const = 0;
inline GCell* getGCell () const;
virtual bool getGCells ( vector<GCell*>& ) const = 0;
inline AutoContact* getAutoSource () const;
inline AutoContact* getAutoTarget () const;
AutoContact* getOppositeAnchor ( AutoContact* ) const;
size_t getPerpandicularsBound ( set<AutoSegment*>& );
inline AutoSegment* getParent () const;
inline unsigned int getDepth () const;
inline DbU::Unit getPitch () const;
DbU::Unit getPPitch () const;
#if DISABLED
DbU::Unit getExtensionCap () const;
#endif
DbU::Unit getExtensionCap ( Flags ) const;
inline DbU::Unit getAxis () const;
void getEndAxes ( DbU::Unit& sourceAxis, DbU::Unit& targetAxis ) const;
virtual DbU::Unit getSourceU () const = 0;
virtual DbU::Unit getTargetU () const = 0;
virtual DbU::Unit getDuSource () const = 0;
virtual DbU::Unit getDuTarget () const = 0;
inline DbU::Unit getOrigin () const;
inline DbU::Unit getExtremity () const;
virtual Interval getSpanU () const = 0;
Interval getMinSpanU () const;
virtual Interval getSourceConstraints ( Flags flags=Flags::NoFlags ) const = 0;
virtual Interval getTargetConstraints ( Flags flags=Flags::NoFlags ) const = 0;
virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const = 0;
inline bool getConstraints ( Interval& i ) const;
inline const Interval& getUserConstraints () const;
inline const Interval& getNativeConstraints () const;
virtual DbU::Unit getSlack () const;
inline DbU::Unit getOptimalMin () const;
inline DbU::Unit getOptimalMax () const;
inline DbU::Unit getNativeMin () const;
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 );
// Modifiers.
inline void unsetFlags ( uint64_t );
inline void setFlags ( uint64_t );
void setFlagsOnAligneds ( uint64_t );
inline void incReduceds ();
inline void decReduceds ();
virtual void setDuSource ( DbU::Unit du ) = 0;
virtual void setDuTarget ( DbU::Unit du ) = 0;
void computeTerminal ();
virtual void updateOrient () = 0;
virtual void updatePositions () = 0;
virtual void updateNativeConstraints () = 0;
void updateSourceSpin ();
void updateTargetSpin ();
void sourceDetach ();
void targetDetach ();
void sourceAttach ( AutoContact* );
void targetAttach ( AutoContact* );
//inline void mergeUserConstraints ( const Interval& );
void mergeUserConstraints ( const Interval& );
inline void resetUserConstraints ();
inline void setOptimalMin ( DbU::Unit min );
inline void setOptimalMax ( DbU::Unit max );
inline void mergeNativeMin ( DbU::Unit min );
inline void mergeNativeMax ( DbU::Unit max );
inline void resetNativeConstraints ( DbU::Unit min, DbU::Unit max );
bool checkNotInvalidated () const;
inline void setParent ( AutoSegment* );
void revalidate ();
AutoSegment* makeDogleg ( AutoContact* );
Flags makeDogleg ( Interval, Flags flags=Flags::NoFlags );
Flags makeDogleg ( GCell* , Flags flags=Flags::NoFlags );
virtual Flags _makeDogleg ( GCell* , Flags flags ) = 0;
virtual bool moveULeft () = 0;
virtual bool moveURight () = 0;
bool slacken ( 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 );
bool moveDown ( Flags flags=Flags::NoFlags );
bool reduceDoglegLayer ();
bool reduce ();
bool raise ();
// Canonical Modifiers.
AutoSegment* canonize ( Flags flags=Flags::NoFlags );
virtual void invalidate ( Flags flags=Flags::Propagate );
void invalidate ( AutoContact* );
void computeOptimal ( set<AutoSegment*>& processeds );
void setAxis ( DbU::Unit, Flags flags=Flags::NoFlags );
bool toConstraintAxis ( Flags flags=Flags::Realignate );
bool toOptimalAxis ( Flags flags=Flags::Realignate );
// Collections & Filters.
AutoSegments getOnSourceContact ( Flags direction );
AutoSegments getOnTargetContact ( Flags direction );
AutoSegments getCachedOnSourceContact ( Flags direction );
AutoSegments getCachedOnTargetContact ( Flags direction );
AutoSegments getAligneds ( Flags flags=Flags::NoFlags );
AutoSegments getConnecteds ( Flags flags=Flags::NoFlags );
AutoSegments getPerpandiculars ( Flags flags=Flags::NoFlags );
size_t getAlignedContacts ( map<AutoContact*,int>& ) const ;
// Observers.
template< typename OwnerT >
inline OwnerT* getObserver ( size_t slot );
inline void setObserver ( size_t slot, BaseObserver* );
inline void notify ( unsigned int flags );
// Inspector Management.
virtual Record* _getRecord () const = 0;
virtual string _getString () const = 0;
virtual string _getTypeName () const = 0;
// Non-reviewed atomic modifiers.
bool _check () const;
#if THIS_IS_DISABLED
virtual void desalignate ( AutoContact* ) = 0;
bool shearUp ( GCell*
, AutoSegment*& movedUp
, float reserve
, Flags flags );
#endif
protected:
// Internal: Static Attributes.
static size_t _allocateds;
static size_t _globalsCount;
static bool _analogMode;
static bool _initialized;
static vector< array<DbU::Unit*,3> > _extensionCaps;
// Internal: Attributes.
const unsigned long _id;
GCell* _gcell;
uint64_t _flags;
unsigned int _depth : 8;
unsigned int _optimalMin :16;
unsigned int _optimalMax :16;
unsigned int _reduceds : 2;
DbU::Unit _sourcePosition;
DbU::Unit _targetPosition;
Interval _userConstraints;
Interval _nativeConstraints;
AutoSegment* _parent;
Observable _observers;
// Internal: Constructors & Destructors.
protected:
AutoSegment ( Segment* segment );
virtual ~AutoSegment ();
static void _preCreate ( AutoContact* source, AutoContact* target );
virtual void _postCreate ();
virtual void _preDestroy ();
static void _initialize ();
private:
AutoSegment ( const AutoSegment& );
AutoSegment& operator= ( const AutoSegment& );
protected:
void _invalidate ();
inline uint64_t _getFlags () const;
std::string _getStringFlags () const;
virtual void _setAxis ( DbU::Unit ) = 0;
public:
struct CompareId : public binary_function<AutoSegment*,AutoSegment*,bool> {
inline bool operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const;
};
public:
struct CompareByDepthLength : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
struct CompareByDepthAxis : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
typedef std::set<AutoSegment*,CompareId> IdSet;
// Static Utilities.
public:
static inline uint64_t swapSourceTargetFlags ( AutoSegment* );
static inline bool areAlignedsAndDiffLayer ( AutoSegment*, AutoSegment* );
static AutoSegment* getGlobalThroughDogleg ( AutoSegment* dogleg, AutoContact* from );
static bool isTopologicalBound ( AutoSegment* seed, Flags flags );
static inline bool arePerpandiculars ( AutoSegment* a, AutoSegment* b );
static inline bool arePerpandiculars ( bool isHorizontalA, AutoSegment* b );
static inline bool areAligneds ( AutoSegment* a, AutoSegment* b );
static Flags getPerpandicularState ( AutoContact* contact
, AutoSegment* source
, AutoSegment* current
, bool isHorizontalMaster
, const Layer* masterLayer=NULL
);
static inline Flags getPerpandicularState ( AutoContact* contact
, AutoSegment* source
, AutoSegment* current
, AutoSegment* master
);
static void getTopologicalInfos ( AutoSegment* seed
, vector<AutoSegment*>& collapseds
, vector<AutoSegment*>& perpandiculars
, DbU::Unit& leftBound
, DbU::Unit& rightBound
);
static int getTerminalCount ( AutoSegment* seed
, vector<AutoSegment*>& collapseds
);
static inline int getTerminalCount ( AutoSegment* seed );
static inline size_t getGlobalsCount ();
static inline size_t getAllocateds ();
static inline unsigned long getMaxId ();
};
// 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 unsigned long AutoSegment::getId () const { return _id; }
inline Cell* AutoSegment::getCell () const { return base()->getCell(); }
inline Net* AutoSegment::getNet () const { return base()->getNet(); }
inline const Layer* AutoSegment::getLayer () const { return base()->getLayer(); }
inline Box AutoSegment::getBoundingBox () const { return base()->getBoundingBox(); }
inline Hook* AutoSegment::getSourceHook () { return base()->getSourceHook(); }
inline Hook* AutoSegment::getTargetHook () { return base()->getTargetHook(); }
inline Contact* AutoSegment::getSource () const { return static_cast<Contact*>(base()->getSource()); }
inline Contact* AutoSegment::getTarget () const { return static_cast<Contact*>(base()->getTarget()); }
inline Component* AutoSegment::getOppositeAnchor ( Component* anchor ) const { return base()->getOppositeAnchor(anchor); };
inline AutoSegment* AutoSegment::getParent () const { return _parent; }
inline DbU::Unit AutoSegment::getSourcePosition () const { return _sourcePosition; }
inline DbU::Unit AutoSegment::getTargetPosition () const { return _targetPosition; }
inline DbU::Unit AutoSegment::getSourceX () const { return base()->getSourceX(); }
inline DbU::Unit AutoSegment::getSourceY () const { return base()->getSourceY(); }
inline DbU::Unit AutoSegment::getTargetX () const { return base()->getTargetX(); }
inline DbU::Unit AutoSegment::getTargetY () const { return base()->getTargetY(); }
inline DbU::Unit AutoSegment::getWidth () const { return base()->getWidth(); }
inline DbU::Unit AutoSegment::getLength () const { return base()->getLength(); }
inline void AutoSegment::invert () { base()->invert(); }
inline GCell* AutoSegment::getGCell () const { return _gcell; }
inline AutoContact* AutoSegment::getAutoSource () const { return Session::lookup(getSource()); }
inline AutoContact* AutoSegment::getAutoTarget () const { return Session::lookup(getTarget()); }
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 unsigned int AutoSegment::getDepth () const { return _depth; }
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::getOrigin () const { return isHorizontal()?_gcell->getYMin():_gcell->getXMin(); }
inline DbU::Unit AutoSegment::getExtremity () const { return isHorizontal()?_gcell->getYMax():_gcell->getXMax(); }
inline DbU::Unit AutoSegment::getOptimalMin () const { return DbU::lambda(_optimalMin) + getOrigin(); }
inline DbU::Unit AutoSegment::getOptimalMax () const { return DbU::lambda(_optimalMax) + getOrigin(); }
inline DbU::Unit AutoSegment::getNativeMin () const { return _nativeConstraints.getVMin(); }
inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); }
inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; }
inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; }
inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; }
inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); }
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::isWeakGlobal () const { return _flags & SegWeakGlobal; }
inline bool AutoSegment::isLongLocal () const { return _flags & SegLongLocal; }
inline bool AutoSegment::isLocal () const { return not (_flags & SegGlobal); }
inline bool AutoSegment::isBipoint () const { return _flags & SegBipoint; }
inline bool AutoSegment::isWeakTerminal () const { return _flags & SegWeakTerminal; }
inline bool AutoSegment::isWeakTerminal1 () const { return _flags & SegWeakTerminal1; }
inline bool AutoSegment::isWeakTerminal2 () const { return _flags & SegWeakTerminal2; }
inline bool AutoSegment::isSourceTerminal () const { return _flags & SegSourceTerminal; }
inline bool AutoSegment::isTargetTerminal () const { return _flags & SegTargetTerminal; }
inline bool AutoSegment::isTerminal () const { return _flags & SegStrongTerminal; }
inline bool AutoSegment::isDrag () const { return _flags & SegDrag; }
inline bool AutoSegment::isNotSourceAligned () const { return _flags & SegNotSourceAligned; }
inline bool AutoSegment::isNotTargetAligned () const { return _flags & SegNotTargetAligned; }
inline bool AutoSegment::isNotAligned () const { return (_flags & SegNotAligned) == SegNotAligned; }
inline bool AutoSegment::isDogleg () const { return _flags & SegDogleg ; }
inline bool AutoSegment::isUnbound () const { return _flags & SegUnbound ; }
inline bool AutoSegment::isStrap () const { return _flags & SegStrap; }
inline bool AutoSegment::isLayerChange () const { return _flags & SegLayerChange; }
inline bool AutoSegment::isSpinTop () const { return ((_flags & SegSpinTop ) == SegSpinTop); }
inline bool AutoSegment::isSpinBottom () const { return ((_flags & SegSpinBottom) == SegSpinBottom); }
inline bool AutoSegment::isSpinTopOrBottom () const { return isSpinTop() or isSpinBottom(); }
inline bool AutoSegment::isReduced () const { return _flags & SegIsReduced; }
inline bool AutoSegment::isSlackened () const { return _flags & SegSlackened; }
inline bool AutoSegment::isCanonical () const { return _flags & SegCanonical; }
inline bool AutoSegment::isUnsetAxis () const { return not (_flags & SegAxisSet); }
inline bool AutoSegment::isInvalidated () const { return _flags & SegInvalidated; }
inline bool AutoSegment::isInvalidatedLayer () const { return _flags & SegInvalidatedLayer; }
inline bool AutoSegment::isCreated () const { return _flags & SegCreated; }
inline bool AutoSegment::isUserDefined () const { return _flags & SegUserDefined; }
inline bool AutoSegment::isAnalog () const { return _flags & SegAnalog; }
inline bool AutoSegment::isWide () const { return _flags & SegWide; }
inline void AutoSegment::setFlags ( 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 void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; }
inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; }
inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); _flags|=SegInvalidatedLayer; }
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::mergeNativeMin ( DbU::Unit min ) { _nativeConstraints.getVMin() = std::max( min, _nativeConstraints.getVMin() ); }
inline void AutoSegment::mergeNativeMax ( DbU::Unit max ) { _nativeConstraints.getVMax() = std::min( max, _nativeConstraints.getVMax() ); }
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::resetUserConstraints () { _userConstraints = Interval(false); }
inline DbU::Unit AutoSegment::getContactWidth () const
{ return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); }
inline void AutoSegment::setParent ( AutoSegment* parent )
{
if ( parent == this ) {
cerr << "Parentage Looping: " << parent->_getString() << endl;
}
_parent = parent;
}
inline bool AutoSegment::CompareId::operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const
{ return lhs->getId() < rhs->getId(); }
inline uint64_t AutoSegment::swapSourceTargetFlags ( AutoSegment* segment )
{
uint64_t segFlags = segment->getFlags();
uint64_t swapFlags = segment->getFlags() & ~(SegSourceTop |SegTargetTop
|SegSourceBottom |SegTargetBottom
|SegSourceTerminal |SegTargetTerminal
|SegNotSourceAligned |SegNotTargetAligned
|SegInvalidatedSource|SegInvalidatedTarget
);
swapFlags |= (segFlags & SegSourceTop ) ? SegTargetTop : SegNoFlags;
swapFlags |= (segFlags & SegSourceBottom ) ? SegTargetBottom : SegNoFlags;
swapFlags |= (segFlags & SegSourceTerminal ) ? SegTargetTerminal : SegNoFlags;
swapFlags |= (segFlags & SegNotSourceAligned ) ? SegNotTargetAligned : SegNoFlags;
swapFlags |= (segFlags & SegInvalidatedSource) ? SegInvalidatedTarget : SegNoFlags;
swapFlags |= (segFlags & SegTargetTop ) ? SegSourceTop : SegNoFlags;
swapFlags |= (segFlags & SegTargetBottom ) ? SegSourceBottom : SegNoFlags;
swapFlags |= (segFlags & SegTargetTerminal ) ? SegSourceTerminal : SegNoFlags;
swapFlags |= (segFlags & SegNotTargetAligned ) ? SegNotSourceAligned : SegNoFlags;
swapFlags |= (segFlags & SegInvalidatedTarget) ? SegInvalidatedSource : SegNoFlags;
return swapFlags;
}
inline bool AutoSegment::areAlignedsAndDiffLayer ( AutoSegment* s1, AutoSegment* s2 )
{ return s1 and s2
and (s1->isHorizontal() == s2->isHorizontal())
and (s1->getLayer() != s2->getLayer()); }
inline bool AutoSegment::arePerpandiculars ( AutoSegment* a, AutoSegment* b )
{ return a and b and (a->isHorizontal() != b->isHorizontal()); }
inline bool AutoSegment::arePerpandiculars ( bool isHorizontalA, AutoSegment* b )
{ return b and (isHorizontalA != b->isHorizontal()); }
inline bool AutoSegment::areAligneds ( AutoSegment* a, AutoSegment* b )
{ return a and b and (a->isHorizontal() == b->isHorizontal()); }
inline Flags AutoSegment::getPerpandicularState ( AutoContact* contact
, AutoSegment* source
, AutoSegment* current
, AutoSegment* master )
{
return getPerpandicularState ( contact, source, current, master->isHorizontal(), master->getLayer() );
}
inline int AutoSegment::getTerminalCount ( AutoSegment* seed )
{
cdebug_log(145,0) << "getTerminalCount() - " << seed << endl;
vector<AutoSegment*> collapseds;
vector<AutoSegment*> perpandiculars;
DbU::Unit leftBound;
DbU::Unit rightBound;
getTopologicalInfos ( seed
, collapseds
, perpandiculars
, leftBound
, rightBound
);
return getTerminalCount ( seed, collapseds );
}
inline size_t AutoSegment::getGlobalsCount () { return _globalsCount; }
inline size_t AutoSegment::getAllocateds () { return _allocateds; }
inline void AutoSegment::setObserver ( size_t slot, BaseObserver* observer )
{ _observers.setObserver( slot, observer ); }
template<typename OwnerT>
inline OwnerT* AutoSegment::getObserver ( size_t slot )
{ return _observers.getObserver<OwnerT>(slot); }
inline void AutoSegment::notify ( unsigned int flags )
{ _observers.notify( flags ); }
inline AutoSegment::Observable::Observable () : StaticObservable<1>() { }
} // End of Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoSegment);
# endif // ANABATIC_AUTOSEGMENT_H

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -14,20 +14,16 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_ANABATIC_ENGINE_H
#define ANABATIC_ANABATIC_ENGINE_H
#pragma once
#include <memory>
#include <string>
#include <vector>
#include <set>
#include "hurricane/NetRoutingProperty.h"
namespace Hurricane {
class Instance;
class CellViewer;
}
#include "crlcore/ToolEngine.h"
#include "anabatic/Configuration.h"
#include "anabatic/Matrix.h"
@ -68,6 +64,8 @@ namespace Anabatic {
};
public:
RawGCellsUnder ( const AnabaticEngine*, Segment* );
RawGCellsUnder ( const AnabaticEngine*, Point source, Point target );
void commonCtor ( const AnabaticEngine*, Point source, Point target );
inline bool empty () const;
inline size_t size () const;
inline GCell* gcellAt ( size_t ) const;
@ -102,19 +100,26 @@ namespace Anabatic {
class NetData {
public:
NetData ( Net* );
NetData ( Net*, AnabaticEngine* );
inline bool isGlobalEstimated () const;
inline bool isGlobalRouted () const;
inline bool isGlobalFixed () const;
inline bool isMixedPreRoute () const;
inline bool isFixed () const;
inline bool isExcluded () const;
inline Net* getNet () const;
inline NetRoutingState* getNetRoutingState () const;
inline const Box& getSearchArea () const;
inline DbU::Unit getHalfPerimeter () const;
inline size_t getRpCount () const;
inline size_t getDiodeRpCount () const;
inline DbU::Unit getSparsity () const;
inline void setNetRoutingState ( NetRoutingState* );
inline void setSearchArea ( Box );
inline void setGlobalEstimated ( bool );
inline void setGlobalRouted ( bool );
inline void setGlobalFixed ( bool );
inline void setExcluded ( bool );
inline void setRpCount ( size_t );
private:
NetData ( const NetData& );
@ -125,22 +130,30 @@ namespace Anabatic {
NetRoutingState* _state;
Box _searchArea;
size_t _rpCount;
size_t _diodeCount;
DbU::Unit _sparsity;
Flags _flags;
};
inline bool NetData::isGlobalEstimated () const { return _flags & Flags::GlobalEstimated; }
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::isFixed () const { return (_state) ? _state->isFixed () : false; }
inline bool NetData::isExcluded () const { return _flags & Flags::ExcludeRoute; }
inline Net* NetData::getNet () const { return _net; }
inline NetRoutingState* NetData::getNetRoutingState () const { return _state; }
inline const Box& NetData::getSearchArea () const { return _searchArea; }
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::getDiodeRpCount () const { return _diodeCount; }
inline void NetData::setNetRoutingState ( NetRoutingState* state ) { _state=state; }
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(); }
@ -153,7 +166,12 @@ namespace Anabatic {
inline bool operator() ( const NetData* lhs, const NetData* rhs ) const
{
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();
}
};
@ -179,135 +197,157 @@ namespace Anabatic {
public:
typedef ToolEngine Super;
public:
static AnabaticEngine* create ( Cell* );
static AnabaticEngine* get ( const Cell* );
static const Name& staticGetName ();
virtual const Name& getName () const;
virtual Configuration* getConfiguration ();
inline uint64_t getDensityMode () const;
inline CellViewer* getViewer () const;
inline void setViewer ( CellViewer* );
inline EngineState getState () const;
inline const Matrix* getMatrix () const;
inline const vector<GCell*>& getGCells () const;
inline const vector<Edge*>& getOvEdges () const;
inline GCell* getSouthWestGCell () const;
inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const;
inline GCell* getGCellUnder ( Point ) const;
inline GCellsUnder getGCellsUnder ( Segment* ) const;
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 addOv ( Edge* );
inline void removeOv ( Edge* );
inline const NetDatas& getNetDatas () const;
NetData* getNetData ( Net*, Flags flags=Flags::NoFlags );
void setupNetDatas ();
void updateMatrix ();
static AnabaticEngine* create ( Cell* );
static AnabaticEngine* get ( const Cell* );
static const Name& staticGetName ();
virtual const Name& getName () const;
virtual Configuration* getConfiguration ();
virtual const Configuration* getConfiguration () const;
inline uint64_t getDensityMode () const;
inline CellViewer* getViewer () const;
inline void setViewer ( CellViewer* );
inline EngineState getState () const;
inline const Matrix* getMatrix () const;
inline const vector<GCell*>& getGCells () const;
inline const vector<Edge*>& getOvEdges () const;
inline GCell* getSouthWestGCell () const;
inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const;
inline GCell* getGCellUnder ( Point ) const;
inline GCellsUnder getGCellsUnder ( Segment* ) const;
inline GCellsUnder getGCellsUnder ( Point source, Point target ) const;
inline Edges getEdgesUnderPath ( GCell* source, GCell* target, Flags pathFlags=Flags::NorthPath ) const;
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 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.
inline int getStamp () const;
inline int incStamp ();
Contact* breakAt ( Segment*, GCell* );
void ripup ( Segment*, Flags );
bool unify ( Contact* );
inline int getStamp () const;
inline int incStamp ();
Contact* breakAt ( Segment*, GCell* );
void ripup ( Segment*, Flags );
bool unify ( Contact* );
// Global routing related functions.
void globalRoute ();
void cleanupGlobal ();
void globalRoute ();
void cleanupGlobal ();
void relaxOverConstraineds ();
// Detailed routing related functions.
inline bool isInDemoMode () const;
inline bool isChip () const;
inline bool doWarnOnGCellOverload () const;
inline bool doDestroyBaseContact () const;
inline bool doDestroyBaseSegment () const;
inline bool doDestroyTool () const;
inline DbU::Unit getGlobalThreshold () const;
inline float getSaturateRatio () const;
inline size_t getSaturateRp () const;
inline DbU::Unit getExtensionCap () const;
inline Net* getBlockageNet () const;
inline const ChipTools& getChipTools () const;
inline const vector<NetData*>& getNetOrdering () const;
void updateDensity ();
size_t checkGCellDensities ();
inline void setGlobalThreshold ( DbU::Unit );
inline void setSaturateRatio ( float );
inline void setSaturateRp ( size_t );
inline void setBlockageNet ( Net* );
void chipPrep ();
void setupSpecialNets ();
void setupPreRouteds ();
void loadGlobalRouting ( uint32_t method );
void computeNetConstraints ( Net* );
void toOptimals ( Net* );
void updateNetTopology ( Net* );
bool moveUpNetTrunk ( AutoSegment*, set<Net*>& globalNets, GCell::Set& invalidateds );
void layerAssign ( uint32_t method );
void finalizeLayout ();
inline const AutoContactLut& _getAutoContactLut () const;
inline const AutoSegmentLut& _getAutoSegmentLut () const;
void _link ( AutoContact* );
void _link ( AutoSegment* );
void _unlink ( AutoContact* );
void _unlink ( AutoSegment* );
AutoContact* _lookup ( Contact* ) const;
AutoSegment* _lookup ( Segment* ) const;
void _loadGrByNet ();
void _loadNetGlobalRouting ( Net* );
void _computeNetOptimals ( Net* );
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 _saveNet ( Net* );
void _destroyAutoContacts ();
void _destroyAutoSegments ();
void _check ( Net* net ) const;
bool _check ( const char* message ) const;
void printMeasures ( const string& tag ) const;
inline bool isInDemoMode () const;
inline bool isChip () const;
inline bool doWarnOnGCellOverload () const;
inline bool doDestroyBaseContact () const;
inline bool doDestroyBaseSegment () const;
inline bool doDestroyTool () const;
inline DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getAntennaDiodeMaxWL () const;
inline DbU::Unit getGlobalThreshold () const;
inline float getSaturateRatio () const;
inline size_t getSaturateRp () const;
inline DbU::Unit getExtensionCap () const;
inline Cell* getDiodeCell () const;
inline Net* getBlockageNet () const;
inline const ChipTools& getChipTools () const;
inline const vector<NetData*>& getNetOrdering () const;
void invalidateRoutingPads ();
void updateDensity ();
size_t checkGCellDensities ();
inline void setGlobalThreshold ( DbU::Unit );
inline void setSaturateRatio ( float );
inline void setSaturateRp ( size_t );
inline void setBlockageNet ( Net* );
void chipPrep ();
void computeEdgeCapacities ( int maxHCap, int maxVCap, int termSatThreshold, int maxTermSat );
void antennaProtect ( Net*, uint32_t& failed, uint32_t& total );
void antennaProtect ();
void setupSpecialNets ();
size_t setupPreRouteds ();
void loadGlobalRouting ( uint32_t method );
void computeNetConstraints ( Net* );
void toOptimals ( Net* );
void updateNetTopology ( Net* );
bool moveUpNetTrunk ( AutoSegment*, set<Net*>& globalNets, GCell::Set& invalidateds );
void layerAssign ( uint32_t method );
void finalizeLayout ();
void exportExternalNets ();
inline const AutoContactLut& _getAutoContactLut () const;
inline const AutoSegmentLut& _getAutoSegmentLut () const;
void _link ( AutoContact* );
void _link ( AutoSegment* );
void _unlink ( AutoContact* );
void _unlink ( AutoSegment* );
AutoContact* _lookup ( Contact* ) const;
AutoSegment* _lookup ( Segment* ) const;
EdgeCapacity* _createCapacity ( Flags, Interval );
size_t _unrefCapacity ( EdgeCapacity* );
void _loadGrByNet ();
void _computeNetOptimals ( Net* );
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.
inline const Flags& flags () const;
inline Flags& flags ();
void reset ();
inline void _add ( GCell* );
inline void _remove ( GCell* );
inline void _updateLookup ( GCell* );
inline bool _inDestroy () const;
inline const Flags& flags () const;
inline Flags& flags ();
void reset ();
inline void _add ( GCell* );
inline void _remove ( GCell* );
inline void _updateLookup ( GCell* );
inline void _updateGContacts ( Flags flags=Flags::Horizontal|Flags::Vertical );
inline void _resizeMatrix ();
inline bool _inDestroy () const;
// Inspector support.
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
protected:
AnabaticEngine ( Cell* );
virtual ~AnabaticEngine ();
virtual void _postCreate ();
virtual void _preDestroy ();
void _gutAnabatic ();
AnabaticEngine ( Cell* );
virtual ~AnabaticEngine ();
virtual void _postCreate ();
virtual void _preDestroy ();
void _gutAnabatic ();
private:
AnabaticEngine ( const AnabaticEngine& );
AnabaticEngine& operator= ( const AnabaticEngine& );
AnabaticEngine ( const AnabaticEngine& );
AnabaticEngine& operator= ( const AnabaticEngine& );
private:
static Name _toolName;
Configuration* _configuration;
ChipTools _chipTools;
EngineState _state;
Matrix _matrix;
vector<GCell*> _gcells;
vector<Edge*> _ovEdges;
vector<NetData*> _netOrdering;
NetDatas _netDatas;
CellViewer* _viewer;
Flags _flags;
int _stamp;
uint64_t _densityMode;
AutoSegmentLut _autoSegmentLut;
AutoContactLut _autoContactLut;
Net* _blockageNet;
static Name _toolName;
Configuration* _configuration;
ChipTools _chipTools;
EngineState _state;
Matrix _matrix;
vector<GCell*> _gcells;
vector<Edge*> _ovEdges;
vector<NetData*> _netOrdering;
NetDatas _netDatas;
CellViewer* _viewer;
Flags _flags;
int _stamp;
uint64_t _densityMode;
AutoSegmentLut _autoSegmentLut;
AutoContactLut _autoContactLut;
EdgeCapacityLut _edgeCapacitiesLut;
Net* _blockageNet;
Cell* _diodeCell;
};
@ -322,6 +362,8 @@ namespace Anabatic {
inline GCell* AnabaticEngine::getGCellUnder ( DbU::Unit x, DbU::Unit y ) const { return _matrix.getUnder(x,y); }
inline GCell* AnabaticEngine::getGCellUnder ( Point p ) const { return _matrix.getUnder(p); }
inline GCellsUnder AnabaticEngine::getGCellsUnder ( Segment* s ) const { return std::shared_ptr<RawGCellsUnder>( new RawGCellsUnder(this,s) ); }
inline GCellsUnder AnabaticEngine::getGCellsUnder ( Point source, Point target ) const { return std::shared_ptr<RawGCellsUnder>( new RawGCellsUnder(this,source,target) ); }
inline Edges AnabaticEngine::getEdgesUnderPath ( GCell* source, GCell* target, Flags pathFlags ) const { return new Path_Edges(source,target,pathFlags); }
inline uint64_t AnabaticEngine::getDensityMode () const { return _densityMode; }
inline void AnabaticEngine::setDensityMode ( uint64_t mode ) { _densityMode=mode; }
inline void AnabaticEngine::setBlockageNet ( Net* net ) { _blockageNet = net; }
@ -335,17 +377,22 @@ namespace Anabatic {
inline bool AnabaticEngine::doWarnOnGCellOverload () const { return _flags & Flags::WarnOnGCellOverload; }
inline bool AnabaticEngine::isInDemoMode () const { return _flags & Flags::DemoMode; }
inline bool AnabaticEngine::isChip () const { return _chipTools.isChip(); }
inline DbU::Unit AnabaticEngine::getAntennaGateMaxWL () const { return getConfiguration()->getAntennaGateMaxWL(); }
inline DbU::Unit AnabaticEngine::getAntennaDiodeMaxWL () const { return getConfiguration()->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::_add ( GCell* gcell )
@ -367,12 +414,15 @@ namespace Anabatic {
inline int AnabaticEngine::getStamp () const { 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 )
{
for ( auto iedge = _ovEdges.begin() ; iedge != _ovEdges.end() ; ++iedge )
if (*iedge == edge) { _ovEdges.erase(iedge); break; }
for ( auto iedge = _ovEdges.begin() ; iedge != _ovEdges.end() ; ++iedge ) {
if (*iedge == edge) { _ovEdges.erase(iedge); return; }
}
}
@ -382,5 +432,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::AnabaticEngine);
#endif // ANABATIC_ANABATIC_ENGINE_H

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -35,6 +35,7 @@ namespace Anabatic {
using Hurricane::setInBound;
using Hurricane::tab;
using Hurricane::Name;
using Hurricane::Entity;
using Hurricane::Net;
using Hurricane::Component;
using Hurricane::Components;
@ -48,7 +49,7 @@ namespace Anabatic {
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)
, CntWeakTerminal = (1 << 12)
, CntUserNativeConstraints = (1 << 13)
, CntOnVertical = (1 << 14)
, CntOnHorizontal = (1 << 15)
, CntDrag = (1 << 16)
, CntHDogleg = (1 << 17)
, CntVDogleg = (1 << 18)
};
class AutoContact {
@ -97,7 +103,7 @@ namespace Anabatic {
inline void setSizes ( DbU::Unit width, DbU::Unit height );
inline void setX ( 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 setDx ( DbU::Unit );
inline void setDy ( DbU::Unit );
@ -115,15 +121,20 @@ namespace Anabatic {
inline bool isVTee () const;
inline bool isFixed () const;
inline bool isUserNativeConstraints () const;
inline bool isHDogleg () const;
inline bool isVDogleg () const;
virtual bool isOnPin () const;
inline bool hasBadTopology () const;
bool canDestroy ( Flags flags=Flags::NoFlags ) const;
bool canMoveUp ( const AutoSegment* moved ) const;
inline bool canDrag () const;
// Accessors.
inline Contact* base () const;
static size_t getAllocateds ();
static const Name& getStaticName ();
virtual const Name& getName () const;
inline size_t getId () const;
inline Flags getFlags () const;
virtual Box getBoundingBox () const;
inline GCell* getGCell () const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const = 0;
@ -153,6 +164,7 @@ namespace Anabatic {
virtual void cacheDetach ( AutoSegment* ) = 0;
virtual void cacheAttach ( AutoSegment* ) = 0;
virtual void updateCache () = 0;
void updateLayer ();
void updateSize ();
virtual void updateGeometry () = 0;
virtual void updateTopology () = 0;
@ -172,6 +184,7 @@ namespace Anabatic {
, Flags flags=Flags::WarnOnError );
void restoreNativeConstraintBox ();
void migrateConstraintBox ( AutoContact* other );
void setLayerAndWidth ( size_t delta, size_t depth );
void destroy ();
// Inspector Management.
Record* _getRecord () const;
@ -252,8 +265,12 @@ namespace Anabatic {
inline bool AutoContact::isTerminal () const { return _flags&CntTerminal; }
inline bool AutoContact::isHTee () const { return _flags&CntHTee; }
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::canDrag () const { return _flags&CntDrag; }
inline size_t AutoContact::getId () const { return _id; }
inline Flags AutoContact::getFlags () const { return _flags; }
inline Contact* AutoContact::base () const { return _contact; }
inline GCell* AutoContact::getGCell () const { return _gcell; }
inline Box AutoContact::getConstraintBox () const { return Box(getCBXMin(),getCBYMin(),getCBXMax(),getCBYMax()); }

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -60,6 +60,7 @@ namespace Anabatic {
virtual void _invalidate ( Flags flags );
public:
bool isEndPoint () const;
virtual bool isOnPin () const;
virtual Box getNativeConstraintBox () const;
RoutingPad* getRoutingPad () const;
inline AutoSegment* getSegment () const;

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |

View File

@ -49,7 +49,7 @@ namespace Anabatic {
virtual Interval getSourceConstraints ( Flags flags=0 ) const;
virtual Interval getTargetConstraints ( Flags flags=0 ) const;
virtual Flags getDirection () const;
virtual size_t getGCells ( vector<GCell*>& ) const;
virtual bool getGCells ( vector<GCell*>& ) const;
// Modifiers.
virtual void setDuSource ( DbU::Unit );
virtual void setDuTarget ( DbU::Unit );

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -39,6 +39,7 @@ namespace Hurricane {
namespace Anabatic {
using std::array;
using std::set;
using std::cerr;
using std::endl;
@ -57,11 +58,10 @@ namespace Anabatic {
class AutoHorizontal;
class AutoVertical;
// -------------------------------------------------------------------
// Class : "AutoSegment".
class AutoSegment {
friend class AutoHorizontal;
friend class AutoVertical;
@ -70,38 +70,44 @@ namespace Anabatic {
static const uint64_t SegNoFlags = 0L;
static const uint64_t SegHorizontal = (1L<< 0);
static const uint64_t SegFixed = (1L<< 1);
static const uint64_t SegGlobal = (1L<< 2);
static const uint64_t SegWeakGlobal = (1L<< 3);
static const uint64_t SegLongLocal = (1L<< 4);
static const uint64_t SegCanonical = (1L<< 5);
static const uint64_t SegBipoint = (1L<< 6);
static const uint64_t SegDogleg = (1L<< 7);
static const uint64_t SegStrap = (1L<< 8);
static const uint64_t SegSourceTop = (1L<< 9);
static const uint64_t SegSourceBottom = (1L<<10);
static const uint64_t SegTargetTop = (1L<<11);
static const uint64_t SegTargetBottom = (1L<<12);
static const uint64_t SegIsReduced = (1L<<13);
static const uint64_t SegLayerChange = (1L<<14);
static const uint64_t SegSourceTerminal = (1L<<15); // Replace Terminal.
static const uint64_t SegTargetTerminal = (1L<<16); // Replace Terminal.
static const uint64_t SegFixedAxis = (1L<< 2);
static const uint64_t SegGlobal = (1L<< 3);
static const uint64_t SegWeakGlobal = (1L<< 4);
static const uint64_t SegLongLocal = (1L<< 5);
static const uint64_t SegCanonical = (1L<< 6);
static const uint64_t SegBipoint = (1L<< 7);
static const uint64_t SegDogleg = (1L<< 8);
static const uint64_t SegStrap = (1L<< 9);
static const uint64_t SegSourceTop = (1L<<10);
static const uint64_t SegSourceBottom = (1L<<11);
static const uint64_t SegTargetTop = (1L<<12);
static const uint64_t SegTargetBottom = (1L<<13);
static const uint64_t SegIsReduced = (1L<<14);
static const uint64_t SegDrag = (1L<<15);
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 SegWeakTerminal1 = (1L<<17); // Replace TopologicalEnd.
static const uint64_t SegWeakTerminal2 = (1L<<18); // Replace TopologicalEnd.
static const uint64_t SegNotSourceAligned = (1L<<19);
static const uint64_t SegNotTargetAligned = (1L<<20);
static const uint64_t SegUnbound = (1L<<21);
static const uint64_t SegHalfSlackened = (1L<<22);
static const uint64_t SegSlackened = (1L<<23);
static const uint64_t SegAxisSet = (1L<<24);
static const uint64_t SegInvalidated = (1L<<25);
static const uint64_t SegInvalidatedSource = (1L<<26);
static const uint64_t SegInvalidatedTarget = (1L<<27);
static const uint64_t SegInvalidatedLayer = (1L<<28);
static const uint64_t SegCreated = (1L<<29);
static const uint64_t SegUserDefined = (1L<<30);
static const uint64_t SegAnalog = (1L<<31);
static const uint64_t SegWide = (1L<<32);
static const uint64_t SegWeakTerminal1 = (1L<<19); // Replace TopologicalEnd.
static const uint64_t SegWeakTerminal2 = (1L<<20); // Replace TopologicalEnd.
static const uint64_t SegNotSourceAligned = (1L<<21);
static const uint64_t SegNotTargetAligned = (1L<<22);
static const uint64_t SegUnbound = (1L<<23);
static const uint64_t SegHalfSlackened = (1L<<24);
static const uint64_t SegSlackened = (1L<<25);
static const uint64_t SegAxisSet = (1L<<26);
static const uint64_t SegInvalidated = (1L<<27);
static const uint64_t SegInvalidatedSource = (1L<<28);
static const uint64_t SegInvalidatedTarget = (1L<<29);
static const uint64_t SegInvalidatedLayer = (1L<<30);
static const uint64_t SegCreated = (1L<<31);
static const uint64_t SegUserDefined = (1L<<32);
static const uint64_t SegAnalog = (1L<<33);
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);
// Masks.
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
@ -130,252 +136,286 @@ namespace Anabatic {
public:
typedef std::function< void(AutoSegment*) > RevalidateCb_t;
public:
static void setAnalogMode ( bool );
static bool getAnalogMode ();
static AutoSegment* create ( AutoContact* source
, AutoContact* target
, Segment* hurricaneSegment
);
static AutoSegment* create ( AutoContact* source
, AutoContact* target
, Flags dir
, size_t depth=RoutingGauge::nlayerdepth
);
void destroy ();
static void setAnalogMode ( bool );
static bool getAnalogMode ();
static void setShortNetMode ( bool );
inline static DbU::Unit getViaToTopCap ( size_t depth );
inline static DbU::Unit getViaToBottomCap ( size_t depth );
inline static DbU::Unit getViaToSameCap ( size_t depth );
inline static DbU::Unit getMinimalLength ( size_t depth );
static AutoSegment* create ( AutoContact* source
, AutoContact* target
, Segment* hurricaneSegment
);
static AutoSegment* create ( AutoContact* source
, AutoContact* target
, Flags dir
, size_t depth=RoutingGauge::nlayerdepth
);
void destroy ();
// Wrapped Segment Functions.
virtual Segment* base () const = 0;
virtual Segment* base () = 0;
virtual Horizontal* getHorizontal () { return NULL; };
virtual Vertical* getVertical () { return NULL; };
inline Cell* getCell () const;
inline Net* getNet () const;
inline const Layer* getLayer () const;
inline Box getBoundingBox () const;
inline Hook* getSourceHook ();
inline Hook* getTargetHook ();
inline Contact* getSource () const;
inline Contact* getTarget () const;
inline Component* getOppositeAnchor ( Component* ) const;
inline Components getAnchors () const;
virtual DbU::Unit getX () const;
virtual DbU::Unit getY () const;
inline DbU::Unit getWidth () const;
inline DbU::Unit getContactWidth () const;
inline DbU::Unit getLength () const;
inline DbU::Unit getSourcePosition () const;
inline DbU::Unit getTargetPosition () const;
inline DbU::Unit getSourceX () const;
inline DbU::Unit getSourceY () const;
inline DbU::Unit getTargetX () const;
inline DbU::Unit getTargetY () const;
inline void invert ();
inline void setLayer ( const Layer* );
virtual Segment* base () const = 0;
virtual Segment* base () = 0;
virtual Horizontal* getHorizontal () { return NULL; };
virtual Vertical* getVertical () { return NULL; };
inline Cell* getCell () const;
inline Net* getNet () const;
inline const Layer* getLayer () const;
inline Box getBoundingBox () const;
inline Hook* getSourceHook ();
inline Hook* getTargetHook ();
inline Contact* getSource () const;
inline Contact* getTarget () const;
inline Component* getOppositeAnchor ( Component* ) const;
inline Components getAnchors () const;
virtual DbU::Unit getX () const;
virtual DbU::Unit getY () const;
inline DbU::Unit getWidth () const;
inline DbU::Unit getContactWidth () const;
inline DbU::Unit getLength () const;
inline DbU::Unit getSpanLength () const;
inline DbU::Unit getAnchoredLength () const;
inline DbU::Unit getSourcePosition () const;
inline DbU::Unit getTargetPosition () const;
inline DbU::Unit getSourceX () const;
inline DbU::Unit getSourceY () const;
inline DbU::Unit getTargetX () const;
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.
inline bool isHorizontal () const;
inline bool isVertical () const;
inline bool isGlobal () const;
inline bool isWeakGlobal () const;
inline bool isLongLocal () const;
inline bool isLocal () const;
inline bool isFixed () const;
inline bool isBipoint () const;
inline bool isWeakTerminal () const;
inline bool isWeakTerminal1 () const;
inline bool isWeakTerminal2 () const;
inline bool isTerminal () const;
inline bool isNotSourceAligned () const;
inline bool isNotTargetAligned () const;
inline bool isNotAligned () const;
bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const;
inline bool isSourceTerminal () const;
inline bool isTargetTerminal () const;
inline bool isLayerChange () const;
inline bool isSpinTop () const;
inline bool isSpinBottom () const;
inline bool isSpinTopOrBottom () const;
inline bool isReduced () const;
inline bool isStrap () const;
inline bool isDogleg () const;
inline bool isUnbound () const;
inline bool isInvalidated () const;
inline bool isInvalidatedLayer () const;
inline bool isCreated () const;
inline bool isCanonical () const;
inline bool isUnsetAxis () const;
inline bool isSlackened () const;
inline bool isUserDefined () const;
bool isReduceCandidate () const;
bool isUTurn () const;
inline bool isAnalog () const;
inline bool isWide () const;
virtual bool _canSlacken () const = 0;
bool canReduce () 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;
inline bool isHorizontal () const;
inline bool isVertical () const;
inline bool isGlobal () const;
inline bool isWeakGlobal () const;
inline bool isLongLocal () const;
inline bool isLocal () const;
inline bool isFixed () const;
inline bool isFixedAxis () const;
inline bool isBipoint () const;
inline bool isWeakTerminal () const;
inline bool isWeakTerminal1 () const;
inline bool isWeakTerminal2 () const;
inline bool isTerminal () const;
inline bool isUnbreakable () const;
inline bool isNonPref () const;
inline bool isDrag () const;
inline bool isAtMinArea () const;
inline bool isNotSourceAligned () const;
inline bool isNotTargetAligned () const;
inline bool isNotAligned () const;
bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const;
inline bool isSourceTerminal () const;
inline bool isTargetTerminal () const;
inline bool isLayerChange () const;
inline bool isStackedStrap () const;
inline bool isSpinTop () const;
inline bool isSpinBottom () const;
inline bool isSpinTopOrBottom () const;
inline bool isReduced () const;
bool isUnderMinLength () const;
inline bool isStrap () const;
inline bool isDogleg () const;
inline bool isUnbound () const;
inline bool isInvalidated () const;
inline bool isInvalidatedLayer () const;
inline bool isCreated () const;
inline bool isCanonical () const;
inline bool isUnsetAxis () const;
inline bool isSlackened () const;
inline bool isUserDefined () const;
bool isMiddleStack () const;
bool isReduceCandidate () const;
bool isUTurn () const;
inline bool isAnalog () const;
inline bool isWide () const;
inline bool isShortNet () const;
virtual bool _canSlacken () const = 0;
bool canReduce ( Flags flags=Flags::WithPerpands ) 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.
inline unsigned long getId () const;
inline uint64_t getFlags () const;
virtual Flags getDirection () const = 0;
inline GCell* getGCell () const;
virtual size_t getGCells ( vector<GCell*>& ) const = 0;
inline AutoContact* getAutoSource () const;
inline AutoContact* getAutoTarget () const;
AutoContact* getOppositeAnchor ( AutoContact* ) const;
size_t getPerpandicularsBound ( set<AutoSegment*>& );
inline AutoSegment* getParent () const;
inline unsigned int getDepth () const;
inline DbU::Unit getPitch () const;
DbU::Unit getPPitch () const;
DbU::Unit getExtensionCap () const;
inline DbU::Unit getAxis () const;
virtual DbU::Unit getSourceU () const = 0;
virtual DbU::Unit getTargetU () const = 0;
virtual DbU::Unit getDuSource () const = 0;
virtual DbU::Unit getDuTarget () const = 0;
inline DbU::Unit getOrigin () const;
inline DbU::Unit getExtremity () const;
virtual Interval getSpanU () const = 0;
Interval getMinSpanU () const;
virtual Interval getSourceConstraints ( Flags flags=Flags::NoFlags ) const = 0;
virtual Interval getTargetConstraints ( Flags flags=Flags::NoFlags ) const = 0;
virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const = 0;
inline bool getConstraints ( Interval& i ) const;
inline const Interval& getUserConstraints () const;
inline const Interval& getNativeConstraints () const;
virtual DbU::Unit getSlack () const;
inline DbU::Unit getOptimalMin () const;
inline DbU::Unit getOptimalMax () const;
inline DbU::Unit getNativeMin () const;
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 unsigned long getId () const;
inline uint64_t getFlags () const;
virtual Flags getDirection () const = 0;
inline GCell* getGCell () const;
virtual bool getGCells ( vector<GCell*>& ) const = 0;
inline AutoContact* getAutoSource () const;
inline AutoContact* getAutoTarget () const;
AutoContact* getOppositeAnchor ( AutoContact* ) const;
size_t getPerpandicularsBound ( set<AutoSegment*>& );
inline AutoSegment* getParent () const;
inline unsigned int getRpDistance () const;
inline unsigned int getDepth () const;
inline DbU::Unit getPitch () const;
DbU::Unit getPPitch () const;
#if DISABLED
DbU::Unit getExtensionCap () const;
#endif
DbU::Unit getExtensionCap ( Flags ) const;
inline DbU::Unit getAxis () const;
void getEndAxes ( DbU::Unit& sourceAxis, DbU::Unit& targetAxis ) const;
virtual DbU::Unit getSourceU () const = 0;
virtual DbU::Unit getTargetU () const = 0;
virtual DbU::Unit getDuSource () const = 0;
virtual DbU::Unit getDuTarget () const = 0;
inline DbU::Unit getOrigin () const;
inline DbU::Unit getExtremity () const;
virtual Interval getSpanU () const = 0;
Interval getMinSpanU () const;
virtual Interval getSourceConstraints ( Flags flags=Flags::NoFlags ) const = 0;
virtual Interval getTargetConstraints ( Flags flags=Flags::NoFlags ) const = 0;
virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const = 0;
inline bool getConstraints ( Interval& i ) const;
inline const Interval& getUserConstraints () const;
inline const Interval& getNativeConstraints () const;
virtual DbU::Unit getSlack () const;
inline DbU::Unit getOptimalMin () const;
inline DbU::Unit getOptimalMax () const;
inline DbU::Unit getNativeMin () const;
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.
inline void unsetFlags ( uint64_t );
inline void setFlags ( uint64_t );
void setFlagsOnAligneds ( uint64_t );
inline void incReduceds ();
inline void decReduceds ();
virtual void setDuSource ( DbU::Unit du ) = 0;
virtual void setDuTarget ( DbU::Unit du ) = 0;
void computeTerminal ();
virtual void updateOrient () = 0;
virtual void updatePositions () = 0;
virtual void updateNativeConstraints () = 0;
void updateSourceSpin ();
void updateTargetSpin ();
void sourceDetach ();
void targetDetach ();
void sourceAttach ( AutoContact* );
void targetAttach ( AutoContact* );
//inline void mergeUserConstraints ( const Interval& );
void mergeUserConstraints ( const Interval& );
inline void resetUserConstraints ();
inline void setOptimalMin ( DbU::Unit min );
inline void setOptimalMax ( DbU::Unit max );
inline void mergeNativeMin ( DbU::Unit min );
inline void mergeNativeMax ( DbU::Unit max );
inline void resetNativeConstraints ( DbU::Unit min, DbU::Unit max );
bool checkNotInvalidated () const;
inline void setParent ( AutoSegment* );
void revalidate ();
AutoSegment* makeDogleg ( AutoContact* );
Flags makeDogleg ( Interval, Flags flags=Flags::NoFlags );
Flags makeDogleg ( GCell* , Flags flags=Flags::NoFlags );
virtual Flags _makeDogleg ( GCell* , Flags flags ) = 0;
virtual bool moveULeft () = 0;
virtual bool moveURight () = 0;
bool slacken ( 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 );
bool moveDown ( Flags flags=Flags::NoFlags );
bool reduceDoglegLayer ();
bool reduce ();
bool raise ();
inline void unsetFlags ( uint64_t );
inline void setFlags ( uint64_t );
void setFlagsOnAligneds ( uint64_t );
inline void setRpDistance ( unsigned int );
inline void incReduceds ();
inline void decReduceds ();
virtual void setDuSource ( DbU::Unit du ) = 0;
virtual void setDuTarget ( DbU::Unit du ) = 0;
void computeTerminal ();
virtual void updateOrient () = 0;
virtual void updatePositions () = 0;
virtual void updateNativeConstraints () = 0;
void updateSourceSpin ();
void updateTargetSpin ();
void sourceDetach ();
void targetDetach ();
void sourceAttach ( AutoContact* );
void targetAttach ( AutoContact* );
//inline void mergeUserConstraints ( const Interval& );
void mergeUserConstraints ( const Interval& );
inline void resetUserConstraints ();
inline void setOptimalMin ( DbU::Unit min );
inline void setOptimalMax ( DbU::Unit max );
inline void mergeNativeMin ( DbU::Unit min );
inline void mergeNativeMax ( DbU::Unit max );
inline void resetNativeConstraints ( DbU::Unit min, DbU::Unit max );
bool checkNotInvalidated () const;
inline void setParent ( AutoSegment* );
void revalidate ();
AutoSegment* makeDogleg ( AutoContact* );
Flags makeDogleg ( Interval, Flags flags=Flags::NoFlags );
Flags makeDogleg ( GCell* , Flags flags=Flags::NoFlags );
virtual Flags _makeDogleg ( GCell* , Flags flags ) = 0;
virtual bool moveULeft () = 0;
virtual bool moveURight () = 0;
bool slacken ( 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 );
bool moveDown ( Flags flags=Flags::NoFlags );
bool reduceDoglegLayer ();
bool bloatStackedStrap ();
bool reduce ( Flags flags=Flags::WithPerpands );
bool raise ();
bool expandToMinLength ( Interval );
bool unexpandToMinLength ();
// Canonical Modifiers.
AutoSegment* canonize ( Flags flags=Flags::NoFlags );
virtual void invalidate ( Flags flags=Flags::Propagate );
void invalidate ( AutoContact* );
void computeOptimal ( set<AutoSegment*>& processeds );
void setAxis ( DbU::Unit, Flags flags=Flags::NoFlags );
bool toConstraintAxis ( Flags flags=Flags::Realignate );
bool toOptimalAxis ( Flags flags=Flags::Realignate );
AutoSegment* canonize ( Flags flags=Flags::NoFlags );
virtual void invalidate ( Flags flags=Flags::Propagate );
void invalidate ( AutoContact* );
void computeOptimal ( set<AutoSegment*>& processeds );
void setAxis ( DbU::Unit, Flags flags=Flags::NoFlags );
bool toConstraintAxis ( Flags flags=Flags::Realignate );
bool toOptimalAxis ( Flags flags=Flags::Realignate );
// Collections & Filters.
AutoSegments getOnSourceContact ( Flags direction );
AutoSegments getOnTargetContact ( Flags direction );
AutoSegments getCachedOnSourceContact ( Flags direction );
AutoSegments getCachedOnTargetContact ( Flags direction );
AutoSegments getAligneds ( Flags flags=Flags::NoFlags );
AutoSegments getConnecteds ( Flags flags=Flags::NoFlags );
AutoSegments getPerpandiculars ( Flags flags=Flags::NoFlags );
size_t getAlignedContacts ( map<AutoContact*,int>& ) const ;
AutoSegments getOnSourceContact ( Flags direction );
AutoSegments getOnTargetContact ( Flags direction );
AutoSegments getCachedOnSourceContact ( Flags direction );
AutoSegments getCachedOnTargetContact ( Flags direction );
AutoSegments getAligneds ( Flags flags=Flags::NoFlags );
AutoSegments getConnecteds ( Flags flags=Flags::NoFlags );
AutoSegments getPerpandiculars ( Flags flags=Flags::NoFlags );
size_t getAlignedContacts ( map<AutoContact*,int>& ) const ;
// Observers.
template< typename OwnerT >
inline OwnerT* getObserver ( size_t slot );
inline void setObserver ( size_t slot, BaseObserver* );
inline void notify ( unsigned int flags );
inline OwnerT* getObserver ( size_t slot );
inline void setObserver ( size_t slot, BaseObserver* );
inline void notify ( unsigned int flags );
// Inspector Management.
virtual Record* _getRecord () const = 0;
virtual string _getString () const = 0;
virtual string _getTypeName () const = 0;
virtual Record* _getRecord () const = 0;
virtual string _getString () const = 0;
virtual string _getTypeName () const = 0;
// Non-reviewed atomic modifiers.
bool _check () const;
bool _check () const;
#if THIS_IS_DISABLED
virtual void desalignate ( AutoContact* ) = 0;
bool shearUp ( GCell*
, AutoSegment*& movedUp
, float reserve
, Flags flags );
virtual void desalignate ( AutoContact* ) = 0;
bool shearUp ( GCell*
, AutoSegment*& movedUp
, float reserve
, Flags flags );
#endif
protected:
// Internal: Static Attributes.
static size_t _allocateds;
static size_t _globalsCount;
static bool _analogMode;
static size_t _allocateds;
static size_t _globalsCount;
static bool _analogMode;
static bool _shortNetMode;
static bool _initialized;
static vector< array<DbU::Unit*,4> > _extensionCaps;
// Internal: Attributes.
const unsigned long _id;
GCell* _gcell;
uint64_t _flags;
unsigned int _depth : 8;
unsigned int _optimalMin :16;
unsigned int _optimalMax :16;
unsigned int _reduceds : 2;
DbU::Unit _sourcePosition;
DbU::Unit _targetPosition;
Interval _userConstraints;
Interval _nativeConstraints;
AutoSegment* _parent;
Observable _observers;
const unsigned long _id;
GCell* _gcell;
uint64_t _flags;
unsigned int _depth : 8;
unsigned int _optimalMin :16;
unsigned int _optimalMax :16;
unsigned int _reduceds : 2;
unsigned int _rpDistance : 4;
DbU::Unit _sourcePosition;
DbU::Unit _targetPosition;
Interval _userConstraints;
Interval _nativeConstraints;
AutoSegment* _parent;
Observable _observers;
// Internal: Constructors & Destructors.
protected:
AutoSegment ( Segment* segment );
virtual ~AutoSegment ();
static void _preCreate ( AutoContact* source, AutoContact* target );
virtual void _postCreate ();
virtual void _preDestroy ();
AutoSegment ( Segment* segment );
virtual ~AutoSegment ();
static void _preCreate ( AutoContact* source, AutoContact* target );
virtual void _postCreate ();
virtual void _preDestroy ();
static void _initialize ();
private:
AutoSegment ( const AutoSegment& );
AutoSegment& operator= ( const AutoSegment& );
AutoSegment ( const AutoSegment& );
AutoSegment& operator= ( const AutoSegment& );
protected:
void _invalidate ();
inline uint64_t _getFlags () const;
std::string _getStringFlags () const;
virtual void _setAxis ( DbU::Unit ) = 0;
void _invalidate ();
inline uint64_t _getFlags () const;
std::string _getStringFlags () const;
virtual void _setAxis ( DbU::Unit ) = 0;
public:
struct CompareId : public binary_function<AutoSegment*,AutoSegment*,bool> {
@ -389,8 +429,20 @@ namespace Anabatic {
struct CompareByDepthAxis : public binary_function<AutoSegment*,AutoSegment*,bool> {
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:
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
typedef std::set<AutoSegment*,CompareId> IdSet;
// Static Utilities.
public:
@ -429,6 +481,10 @@ namespace Anabatic {
// 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 Cell* AutoSegment::getCell () const { return base()->getCell(); }
inline Net* AutoSegment::getNet () const { return base()->getNet(); }
@ -455,6 +511,7 @@ namespace Anabatic {
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 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::getAxis () const { return isHorizontal()?base()->getY():base()->getX(); }
inline DbU::Unit AutoSegment::getOrigin () const { return isHorizontal()?_gcell->getYMin():_gcell->getXMin(); }
@ -465,21 +522,27 @@ namespace Anabatic {
inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); }
inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; }
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::isVertical () const { return not (_flags & SegHorizontal); }
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::isWeakGlobal () const { return _flags & SegWeakGlobal; }
inline bool AutoSegment::isLongLocal () const { return _flags & SegLongLocal; }
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::isBipoint () const { return _flags & SegBipoint; }
inline bool AutoSegment::isWeakTerminal () const { return _flags & SegWeakTerminal; }
inline bool AutoSegment::isWeakTerminal1 () const { return _flags & SegWeakTerminal1; }
inline bool AutoSegment::isWeakTerminal2 () const { return _flags & SegWeakTerminal2; }
inline bool AutoSegment::isWeakTerminal () const { return (_rpDistance < 2); }
inline bool AutoSegment::isWeakTerminal1 () const { return (_rpDistance == 1); }
inline bool AutoSegment::isWeakTerminal2 () const { return (_rpDistance == 2); }
inline bool AutoSegment::isSourceTerminal () const { return _flags & SegSourceTerminal; }
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::isNotTargetAligned () const { return _flags & SegNotTargetAligned; }
inline bool AutoSegment::isNotAligned () const { return (_flags & SegNotAligned) == SegNotAligned; }
@ -500,14 +563,17 @@ namespace Anabatic {
inline bool AutoSegment::isUserDefined () const { return _flags & SegUserDefined; }
inline bool AutoSegment::isAnalog () const { return _flags & SegAnalog; }
inline bool AutoSegment::isWide () const { return _flags & SegWide; }
inline bool AutoSegment::isShortNet () const { return _flags & SegShortNet; }
inline void AutoSegment::setFlags ( 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 void AutoSegment::setRpDistance ( unsigned int distance ) { _rpDistance=distance; }
inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_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::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() ); }
@ -515,11 +581,25 @@ namespace Anabatic {
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::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
{ 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 )
{
@ -529,7 +609,6 @@ namespace Anabatic {
_parent = parent;
}
inline bool AutoSegment::CompareId::operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const
{ return lhs->getId() < rhs->getId(); }

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -48,6 +48,7 @@ namespace Anabatic {
using Hurricane::DbU;
using Hurricane::Box;
using Hurricane::Hook;
using Hurricane::Entity;
using Hurricane::Component;
using Hurricane::Contact;
using Hurricane::Segment;
@ -70,13 +71,13 @@ namespace Anabatic {
// -------------------------------------------------------------------
// Collections.
typedef Hurricane::Filter<AutoSegment*> AutoSegmentHF;
typedef Hurricane::Locator<AutoSegment*> AutoSegmentHL;
typedef Hurricane::Collection<AutoSegment*> AutoSegmentHC;
typedef GenericCollection<AutoSegment*> AutoSegments;
typedef GenericLocator<AutoSegment*> AutoSegmentLocator;
typedef GenericFilter<AutoSegment*> AutoSegmentFilter;
typedef map<Segment*,AutoSegment*> AutoSegmentLut;
typedef Hurricane::Filter<AutoSegment*> AutoSegmentHF;
typedef Hurricane::Locator<AutoSegment*> AutoSegmentHL;
typedef Hurricane::Collection<AutoSegment*> AutoSegmentHC;
typedef GenericCollection<AutoSegment*> AutoSegments;
typedef GenericLocator<AutoSegment*> AutoSegmentLocator;
typedef GenericFilter<AutoSegment*> AutoSegmentFilter;
typedef map<Segment*,AutoSegment*,Entity::CompareById> AutoSegmentLut;
// -------------------------------------------------------------------

View File

@ -49,7 +49,7 @@ namespace Anabatic {
virtual Interval getSourceConstraints ( Flags flags=0 ) const;
virtual Interval getTargetConstraints ( Flags flags=0 ) const;
virtual Flags getDirection () const;
virtual size_t getGCells ( vector<GCell*>& ) const;
virtual bool getGCells ( vector<GCell*>& ) const;
// Modifiers.
virtual void setDuSource ( DbU::Unit );
virtual void setDuTarget ( DbU::Unit );

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// 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 |
@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_CHIP_TOOLS_H
#define ANABATIC_CHIP_TOOLS_H
#pragma once
#include <string>
#include "hurricane/DbU.h"
#include "hurricane/Torus.h"
@ -113,6 +111,4 @@ namespace Anabatic {
} // Anabatic namespace.
INSPECTOR_PV_SUPPORT(Anabatic::ChipTools);
#endif // ANABATIC_CHIP_TOOLS_H
INSPECTOR_PR_SUPPORT(Anabatic::ChipTools);

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Configuration.h<anabatic>" -*-
//
// 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 |
@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_CONFIGURATION_H
#define ANABATIC_CONFIGURATION_H
#pragma once
#include <string>
#include <vector>
@ -24,6 +22,7 @@
namespace Hurricane {
class Layer;
class Cell;
class RoutingPad;
}
namespace CRL {
@ -43,6 +42,7 @@ namespace Anabatic {
using Hurricane::Name;
using Hurricane::Layer;
using Hurricane::DbU;
using Hurricane::RoutingPad;
using Hurricane::Cell;
using CRL::CellGauge;
using CRL::RoutingGauge;
@ -53,59 +53,99 @@ namespace Anabatic {
// Class : "Anabatic::Configuration".
class Configuration {
public:
static const size_t ndepth = (size_t)-1;
public:
// Constructor & Destructor.
Configuration ( const CellGauge* cg=NULL, const RoutingGauge* rg=NULL );
Configuration ( const Configuration& );
virtual ~Configuration ();
virtual Configuration* clone () const;
Configuration ( const CellGauge* cg=NULL, const RoutingGauge* rg=NULL );
Configuration ( const Configuration& );
virtual ~Configuration ();
virtual Configuration* clone () const;
// Methods.
bool isGMetal ( const Layer* ) const;
bool isGContact ( const Layer* ) const;
const Layer* getGContactLayer () const;
const Layer* getGHorizontalLayer () const;
const Layer* getGVerticalLayer () const;
size_t getDepth () const;
size_t getAllowedDepth () const;
size_t getLayerDepth ( const Layer* ) const;
CellGauge* getCellGauge () const;
RoutingGauge* getRoutingGauge () const;
RoutingLayerGauge* getLayerGauge ( size_t depth ) const;
const Layer* getRoutingLayer ( size_t depth ) const;
Layer* getContactLayer ( size_t depth ) 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 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 getExtensionCap ( const Layer* ) const;
Flags getDirection ( const Layer* ) const;
float getSaturateRatio () const;
size_t getSaturateRp () 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;
virtual void print ( Cell* ) const;
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
inline bool isGLayer ( const Layer* ) const;
bool isGMetal ( const Layer* ) const;
bool isGContact ( const Layer* ) const;
bool isTwoMetals () const;
bool isHV () const;
bool isVH () const;
const Layer* getGContactLayer () const;
const Layer* getGHorizontalLayer () const;
const Layer* getGVerticalLayer () const;
inline size_t getGVerticalDepth () const;
inline DbU::Unit getGVerticalPitch () const;
inline size_t getGHorizontalDepth () const;
inline DbU::Unit getGHorizontalPitch () const;
inline size_t getDVerticalDepth () const;
inline const Layer* getDVerticalLayer () const;
inline DbU::Unit getDVerticalWidth () const;
inline DbU::Unit getDPVerticalWidth () const;
inline DbU::Unit getDVerticalPitch () const;
inline DbU::Unit getDVerticalOffset () const;
inline size_t getDHorizontalDepth () const;
inline const Layer* getDHorizontalLayer () const;
inline DbU::Unit getDHorizontalWidth () const;
inline DbU::Unit getDPHorizontalWidth () const;
inline DbU::Unit getDHorizontalPitch () const;
inline DbU::Unit getDHorizontalOffset () const;
inline size_t getDContactDepth () const;
inline const Layer* getDContactLayer () const;
inline DbU::Unit getDContactWidth () const;
inline DbU::Unit getDContactPitch () const;
size_t getDepth () const;
size_t getAllowedDepth () const;
size_t getLayerDepth ( const Layer* ) const;
CellGauge* getCellGauge () const;
RoutingGauge* getRoutingGauge () const;
RoutingLayerGauge* getLayerGauge ( size_t depth ) const;
const Layer* getRoutingLayer ( size_t depth ) const;
Layer* getContactLayer ( size_t depth ) 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;
virtual void print ( Cell* ) const;
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
protected:
// Attributes.
const Layer* _gmetalh;
const Layer* _gmetalv;
const Layer* _gcontact;
size_t _gdepthv;
size_t _gdepthh;
size_t _ddepthv;
size_t _ddepthh;
size_t _ddepthc;
CellGauge* _cg;
RoutingGauge* _rg;
std::vector<DbU::Unit> _extensionCaps;
@ -118,15 +158,44 @@ namespace Anabatic {
float _edgeCostH;
float _edgeCostK;
float _edgeHInc;
float _edgeHScaling;
int _globalIterations;
std::string _diodeName;
DbU::Unit _antennaGateMaxWL;
DbU::Unit _antennaDiodeMaxWL;
private:
Configuration& operator= ( const Configuration& ) = delete;
void _setTopRoutingLayer ( Name name );
};
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; }
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::Configuration);
#endif // ANABATIC_CONFIGURATION_H

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Constants.h<anabatic>" -*-
//
// 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 |
@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_CONSTANTS_H
#define ANABATIC_CONSTANTS_H
#pragma once
#include "hurricane/Flags.h"
namespace Anabatic {
@ -39,6 +37,14 @@ namespace Anabatic {
static const BaseFlags MatrixGCell ; // = (1 << 9);
static const BaseFlags IoPadGCell ; // = (1 << 10);
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.
static const BaseFlags DemoMode ; // = (1 << 5);
static const BaseFlags WarnOnGCellOverload ; // = (1 << 6);
@ -46,7 +52,11 @@ namespace Anabatic {
static const BaseFlags DestroyBaseContact ; // = (1 << 8);
static const BaseFlags DestroyBaseSegment ; // = (1 << 9);
// 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.
static const BaseFlags WestSide ; // = Horizontal|Target;
static const BaseFlags EastSide ; // = Horizontal|Source;
@ -56,7 +66,10 @@ namespace Anabatic {
static const BaseFlags EndsMask ; // = Source|Target;
static const BaseFlags DirectionMask ; // = Horizontal|Vertical;
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.
static const BaseFlags Create ; // = (1 << 5);
static const BaseFlags WithPerpands ;
@ -86,6 +99,13 @@ namespace Anabatic {
static const BaseFlags CheckLowDensity ;
static const BaseFlags CheckLowUpDensity ;
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 ;
public:
inline Flags ( uint64_t flags = NoFlags );
inline Flags ( const Hurricane::BaseFlags& );
@ -112,11 +132,12 @@ namespace Anabatic {
, EngineGutted = 6
};
enum EngineAlgorithm { EngineLoadGrByNet = (1 << 0)
, EngineLoadGrByGCell = (1 << 1)
, EngineLayerAssignByLength = (1 << 2)
, EngineLayerAssignByTrunk = (1 << 3)
, EngineNoNetLayerAssign = (1 << 4)
enum EngineAlgorithm { EngineLoadGrByNet = (1 << 0)
, EngineLoadGrByGCell = (1 << 1)
, EngineLayerAssignByLength = (1 << 2)
, EngineLayerAssignByTrunk = (1 << 3)
, EngineLayerAssignNoGlobalM2V = (1 << 4)
, EngineNoNetLayerAssign = (1 << 5)
};
@ -131,6 +152,4 @@ namespace Anabatic {
} // Anabatic namespace.
INSPECTOR_PV_SUPPORT(Anabatic::Flags)
#endif // ANABATIC_CONSTANTS_H
INSPECTOR_PR_SUPPORT(Anabatic::Flags);

View File

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

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Edge.h<anabatic>" -*-
//
// 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 |
@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_EDGE_H
#define ANABATIC_EDGE_H
#pragma once
#include <string>
#include "hurricane/Name.h"
#include "hurricane/Interval.h"
@ -26,10 +24,10 @@ namespace Hurricane {
class Segment;
}
#include "anabatic/Constants.h"
#include "anabatic/EdgeCapacity.h"
#include "anabatic/Edges.h"
namespace Anabatic {
using std::string;
@ -60,8 +58,11 @@ namespace Anabatic {
inline bool isHorizontal () const;
inline bool hasNet ( const Net* ) const;
inline unsigned int getCapacity () const;
inline unsigned int getRawCapacity () const;
inline unsigned int getReservedCapacity () const;
inline unsigned int getCapacity ( size_t depth ) const;
inline unsigned int getRealOccupancy () const;
inline unsigned int getEstimateOccupancy () const;
inline float getEstimateOccupancy () const;
inline float getHistoricCost () const;
DbU::Unit getDistance () const;
inline GCell* getSource () const;
@ -73,12 +74,16 @@ namespace Anabatic {
Interval getSide () const;
Segment* getSegment ( const Net* ) const;
inline const vector<Segment*>& getSegments () const;
inline void setCapacity ( int );
inline void incCapacity ( int );
//inline void setCapacity ( int );
//inline void incCapacity ( int );
inline void forceCapacity ( int );
inline void reserveCapacity ( int );
inline void setRealOccupancy ( int );
void incRealOccupancy ( int );
void incRealOccupancy2 ( int );
inline void incEstimateOccupancy ( float );
inline void setHistoricCost ( float );
bool isEnding ( Segment* ) const;
void add ( Segment* );
void remove ( Segment* );
void replace ( Segment* orig, Segment* repl );
@ -86,19 +91,18 @@ namespace Anabatic {
inline const Flags& flags () const;
inline Flags& flags ();
inline void revalidate () const;
bool isMaxCapacity ( Net* net = NULL ) const;
inline Flags& setFlags ( Flags mask );
void _setSource ( GCell* );
void _setTarget ( GCell* );
private:
void _invalidate ();
void _revalidate ();
public:
// ExtensionGo support.
inline const Name& staticGetName ();
virtual const Name& getName () const;
virtual void translate ( const DbU::Unit&, const DbU::Unit& );
virtual Box getBoundingBox () const;
virtual void invalidate ( bool propagateFlag=true );
virtual void materialize ();
public:
// Inspector support.
virtual string _getTypeName () const;
@ -115,7 +119,8 @@ namespace Anabatic {
private:
static Name _extensionName;
Flags _flags;
unsigned int _capacity;
EdgeCapacity* _capacities;
unsigned int _reservedCapacity;
unsigned int _realOccupancy;
float _estimateOccupancy;
float _historicCost;
@ -130,25 +135,34 @@ namespace Anabatic {
inline bool Edge::isVertical () const { return _flags.isset(Flags::Vertical); }
inline bool Edge::isHorizontal () const { return _flags.isset(Flags::Horizontal); }
inline bool Edge::hasNet ( const Net* owner ) const { return getSegment(owner); }
inline unsigned int Edge::getCapacity () const { return _capacity; }
inline unsigned int Edge::getCapacity ( size_t depth ) const { return (_capacities) ? _capacities->getCapacity(depth) : 0; }
inline unsigned int Edge::getRawCapacity () const { return (_capacities) ? _capacities->getCapacity() : 0; }
inline unsigned int Edge::getReservedCapacity () const { return _reservedCapacity; }
inline unsigned int Edge::getRealOccupancy () const { return _realOccupancy; }
inline unsigned int Edge::getEstimateOccupancy () const { return _estimateOccupancy; }
inline float Edge::getEstimateOccupancy () const { return _estimateOccupancy; }
inline float Edge::getHistoricCost () const { return _historicCost; }
inline GCell* Edge::getSource () const { return _source; }
inline GCell* Edge::getTarget () const { return _target; }
inline DbU::Unit Edge::getAxis () const { return _axis; }
inline const vector<Segment*>& Edge::getSegments () const { return _segments; }
inline void Edge::incCapacity ( int delta ) { _capacity = ((int)_capacity+delta > 0) ? _capacity+delta : 0; }
inline void Edge::setCapacity ( int c ) { _capacity = ((int) c > 0) ? c : 0; }
inline void Edge::forceCapacity ( int capacity ) { if (_capacities) _capacities->forceCapacity(capacity); }
//inline void Edge::incCapacity ( int delta ) { _capacity = ((int)_capacity+delta > 0) ? _capacity+delta : 0; }
//inline void Edge::setCapacity ( int c ) { _capacity = ((int) c > 0) ? c : 0; }
inline void Edge::setRealOccupancy ( int c ) { _realOccupancy = ((int) c > 0) ? c : 0; }
inline void Edge::setHistoricCost ( float hcost ) { _historicCost = hcost; }
inline void Edge::incEstimateOccupancy ( float delta ) { _estimateOccupancy += delta; }
inline const Flags& Edge::flags () const { return _flags; }
inline Flags& Edge::flags () { return _flags; }
inline void Edge::revalidate () const { /*if (_flags&Flags::Invalidated)*/ const_cast<Edge*>(this)->_revalidate(); }
inline Flags& Edge::setFlags ( Flags mask ) { _flags |= mask; return _flags; }
inline void Edge::reserveCapacity ( int delta ) { _reservedCapacity = ((int)_reservedCapacity+delta > 0) ? _reservedCapacity+delta : 0; }
inline unsigned int Edge::getCapacity () const
{
if (not _capacities) return 0;
return (_capacities->getCapacity() > (int)_reservedCapacity) ? _capacities->getCapacity()-_reservedCapacity : 0;
}
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::Edge);
#endif // ANABATIC_EDGE_H

View File

@ -0,0 +1,99 @@
// -*- mode: C++; explicit-buffer-name: "EdgeCapacity.h<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++ Header : "./anabatic/EdgeCapacity.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_EDGE_CAPACITY_H
#define ANABATIC_EDGE_CAPACITY_H
#include <string>
#include <set>
#include "hurricane/Interval.h"
#include "anabatic/Constants.h"
namespace Anabatic {
using Hurricane::Record;
using Hurricane::DbU;
using Hurricane::Interval;
class AnabaticEngine;
// -------------------------------------------------------------------
// Class : "EdgeCapacity".
class EdgeCapacity {
public:
class Compare {
public:
inline bool operator() ( const EdgeCapacity*, const EdgeCapacity* ) const;
};
public:
EdgeCapacity ( AnabaticEngine*, Flags, Interval, size_t depth );
inline size_t incref ();
inline size_t decref ();
inline size_t getref () const;
inline AnabaticEngine* getAnabatic () const;
inline const Interval& getSpan () const;
inline int getCapacity () const;
inline int getCapacity ( size_t depth ) const;
void forceCapacity ( unsigned int );
std::string _getString () const;
Record* _getRecord () const;
private:
private:
AnabaticEngine* _anabatic;
size_t _refCount;
Flags _flags;
size_t _depth;
Interval _span;
std::vector<int> _capacities;
};
inline size_t EdgeCapacity::incref () { return ++_refCount; }
inline size_t EdgeCapacity::decref () { if (_refCount < 2) { delete this; return 0; } return --_refCount; }
inline size_t EdgeCapacity::getref () const { return _refCount; }
inline AnabaticEngine* EdgeCapacity::getAnabatic () const { return _anabatic; }
inline const Interval& EdgeCapacity::getSpan () const { return _span; }
inline int EdgeCapacity::getCapacity ( size_t depth ) const { return (depth<_depth) ? _capacities[depth] : 0; }
inline int EdgeCapacity::getCapacity () const
{
int full = 0;
for ( size_t depth=0; depth<_depth ; ++depth ) full += _capacities[depth];
return full;
}
inline bool EdgeCapacity::Compare::operator() ( const EdgeCapacity* lhs, const EdgeCapacity* rhs ) const
{
if ( (lhs->_flags & Flags::Horizontal) and not (rhs->_flags & Flags::Horizontal)) return true;
if (not (lhs->_flags & Flags::Horizontal) and (rhs->_flags & Flags::Horizontal)) return false;
DbU::Unit dmin = lhs->getSpan().getVMin() - rhs->getSpan().getVMin();
if (dmin < 0) return true;
if (dmin > 0) return false;
return lhs->getSpan().getVMax() < rhs->getSpan().getVMax();
}
typedef std::set<EdgeCapacity*,EdgeCapacity::Compare> EdgeCapacityLut;
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::EdgeCapacity);
#endif // ANABATIC_EDGE_CAPACITY_H

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Edges.h<anabatic>" -*-
//
// 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 |
@ -19,6 +19,7 @@
#include <string>
#include <vector>
#include "hurricane/DbU.h"
#include "hurricane/Collection.h"
#include "anabatic/Constants.h"
@ -27,6 +28,7 @@ namespace Anabatic {
using std::string;
using std::vector;
using Hurricane::DbU;
using Hurricane::Record;
using Hurricane::Filter;
using Hurricane::Locator;
@ -110,12 +112,82 @@ namespace Anabatic {
{ }
// -------------------------------------------------------------------
// Class : "Path_Edges".
class Path_Edges : public EdgesHC {
public:
// Sub-Class: Locator.
class Locator : public EdgesHL {
public:
Locator ( const GCell* source, const GCell* target, Flags pathFlags );
inline Locator ( const Locator& );
virtual Edge* getElement () const;
virtual EdgesHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
const GCell* _source;
const GCell* _target;
Flags _stateFlags;
DbU::Unit _uprobe;
Edge* _edge;
};
// GCell_Edges.
public:
inline Path_Edges ( const GCell* source, const GCell* target, Flags pathFlags=Flags::NorthPath );
inline Path_Edges ( const Path_Edges& );
virtual EdgesHC* getClone () const;
virtual EdgesHL* getLocator () const;
virtual string _getString () const;
protected:
const GCell* _source;
const GCell* _target;
Flags _pathFlags;
};
inline Path_Edges::Locator::Locator ( const Locator &locator )
: EdgesHL()
, _source (locator._source)
, _target (locator._target)
, _stateFlags(locator._stateFlags)
, _uprobe (locator._uprobe)
, _edge (locator._edge)
{
// cdebug_log(110,0) << "GCell_Edges::Locator::Locator(const Locator&)" << std::endl;
}
inline Path_Edges::Path_Edges ( const GCell* source, const GCell* target, Flags pathFlags )
: EdgesHC()
, _source (source)
, _target (target)
, _pathFlags(pathFlags)
{ }
inline Path_Edges::Path_Edges ( const Path_Edges& path )
: EdgesHC()
, _source (path._source)
, _target (path._target)
, _pathFlags(path._pathFlags)
{ }
} // Anabatic namespace.
GETSTRING_POINTER_SUPPORT(Anabatic::GCell_Edges);
GETSTRING_POINTER_SUPPORT(Anabatic::GCell_Edges::Locator);
GETSTRING_POINTER_SUPPORT(Anabatic::Path_Edges);
GETSTRING_POINTER_SUPPORT(Anabatic::Path_Edges::Locator);
IOSTREAM_POINTER_SUPPORT(Anabatic::GCell_Edges);
IOSTREAM_POINTER_SUPPORT(Anabatic::GCell_Edges::Locator);
IOSTREAM_POINTER_SUPPORT(Anabatic::Path_Edges);
IOSTREAM_POINTER_SUPPORT(Anabatic::Path_Edges::Locator);
#endif // ANABATIC_EDGES_H

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "GCell.h<anabatic>" -*-
//
// 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 |
@ -14,10 +14,9 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_GCELL_H
#define ANABATIC_GCELL_H
#pragma once
#include <vector>
#include <queue>
#include <string>
#include <set>
#include <functional>
@ -66,6 +65,8 @@ namespace Anabatic {
class GCell;
// -------------------------------------------------------------------
// Class : "GCell".
@ -113,175 +114,211 @@ namespace Anabatic {
public:
class Key {
public:
inline Key ( GCell*, size_t depth );
inline float getDensity () const;
inline GCell* getGCell () const;
inline void update ( size_t depth );
friend bool operator< ( const Key&, const Key& );
inline Key ( const GCell*, size_t depth );
inline ~Key ();
inline float getDensity () const;
inline const GCell* getGCell () const;
inline bool isActive () const;
inline bool isSaturated () const;
inline void update ( size_t depth );
friend bool operator< ( const Key&, const Key& );
public:
class Compare {
public:
inline bool operator() ( const Key*, const Key* );
};
private:
GCell* _gcell;
float _density;
const GCell* _gcell;
float _density;
};
public:
static uint32_t getDisplayMode ();
static void setDisplayMode ( uint32_t );
static Box getBorder ( const GCell*, const GCell* );
static uint32_t getDisplayMode ();
static void setDisplayMode ( uint32_t );
static Box getBorder ( const GCell*, const GCell* );
static inline DbU::Unit getMatrixHSide ();
static inline DbU::Unit getMatrixVSide ();
public:
static GCell* create ( AnabaticEngine* );
static GCell* create ( AnabaticEngine* );
public:
inline bool isSaturated () const;
bool isSaturated ( size_t depth ) const;
inline bool isInvalidated () const;
inline bool isHFlat () const;
inline bool isVFlat () const;
inline bool isFlat () const;
inline bool isDevice () const;
inline bool isHChannel () const;
inline bool isVChannel () const;
inline bool isStrut () const;
inline bool isMatrix () const;
inline bool isIoPad () const;
bool isWest ( GCell* ) const;
bool isEast ( GCell* ) const;
bool isNorth ( GCell* ) const;
bool isSouth ( GCell* ) const;
Contact* hasGContact ( const Contact* ) const;
Contact* hasGContact ( const Net* ) const;
inline AnabaticEngine* getAnabatic () const;
inline Flags getType () const;
inline DbU::Unit getXMin () const;
inline DbU::Unit getYMin () const;
inline DbU::Unit getXMax ( int shrink=0 ) const;
inline DbU::Unit getYMax ( int shrink=0 ) const;
inline DbU::Unit getXCenter () const;
inline DbU::Unit getYCenter () const;
inline DbU::Unit getConstraintXMax ( int shrink=0 ) const;
inline DbU::Unit getConstraintYMax ( int shrink=0 ) const;
inline Interval getSide ( Flags direction, int shrink=0 ) const;
inline Point getCenter () const;
inline Box getConstraintBox () const;
inline const vector<Edge*>& getWestEdges () const;
inline const vector<Edge*>& getEastEdges () const;
inline const vector<Edge*>& getNorthEdges () const;
inline const vector<Edge*>& getSouthEdges () const;
Edge* getEdgeTo ( GCell*, Flags sideHint=Flags::AllSides ) const;
Edge* getEdgeAt ( Flags sideHint, DbU::Unit u ) const;
inline Edges getEdges ( Flags sides=Flags::AllSides ) const;
inline GCell* getWest () const;
inline GCell* getEast () const;
inline GCell* getSouth () const;
inline GCell* getNorth () const;
inline bool isSaturated () const;
bool isSaturated ( size_t depth ) const;
inline bool isInvalidated () const;
inline bool isHFlat () const;
inline bool isVFlat () const;
inline bool isFlat () const;
inline bool isDevice () const;
inline bool isHChannel () const;
inline bool isVChannel () const;
inline bool isStrut () const;
inline bool isAnalog () const;
inline bool isMatrix () const;
inline bool isRow () const;
inline bool isIoPad () const;
inline bool isGoStraight () const;
inline bool isHRail () const;
inline bool isVRail () const;
inline bool isStdCellRow () const;
inline bool isChannelRow () const;
bool isWest ( GCell* ) const;
bool isEast ( GCell* ) const;
bool isNorth ( GCell* ) const;
bool isSouth ( GCell* ) const;
bool hasNet ( const Net* ) const;
Contact* hasGContact ( const Contact* ) const;
Contact* hasGContact ( const Net* ) const;
bool isHorizontalPlane ( size_t depth ) const;
bool isVerticalPlane ( size_t depth ) const;
inline AnabaticEngine* getAnabatic () const;
inline Flags getType () const;
inline DbU::Unit getXMin () const;
inline DbU::Unit getYMin () const;
inline DbU::Unit getXMax ( int shrink=0 ) const;
inline DbU::Unit getYMax ( int shrink=0 ) const;
inline DbU::Unit getXCenter () const;
inline DbU::Unit getYCenter () const;
inline DbU::Unit getConstraintXMax ( int shrink=0 ) const;
inline DbU::Unit getConstraintYMax ( int shrink=0 ) const;
inline Interval getSide ( Flags direction, int shrink=0 ) const;
inline Interval getHSide ( int shrink=0 ) const;
inline Interval getVSide ( int shrink=0 ) const;
inline Point getCenter () const;
inline Box getConstraintBox () const;
inline const vector<Edge*>& getWestEdges () const;
inline const vector<Edge*>& getEastEdges () const;
inline const vector<Edge*>& getNorthEdges () const;
inline const vector<Edge*>& getSouthEdges () const;
Edge* getEdgeTo ( GCell*, Flags sideHint=Flags::AllSides ) const;
Edge* getEdgeAt ( Flags sideHint, DbU::Unit u ) const;
inline Edges getEdges ( Flags sides=Flags::AllSides ) const;
inline GCell* getWest () const;
inline GCell* getEast () const;
inline GCell* getSouth () const;
inline GCell* getNorth () const;
inline Edge* getWestEdge () const;
inline Edge* getEastEdge () const;
inline Edge* getSouthEdge () const;
inline Edge* getNorthEdge () const;
GCell* getEastNMatrix () const;
GCell* getNorthNMatrix () const;
GCell* getWest ( DbU::Unit y ) const;
GCell* getEast ( DbU::Unit y ) const;
GCell* getSouth ( DbU::Unit x ) const;
GCell* getNorth ( DbU::Unit x ) const;
GCell* getNeighborAt ( Flags side, DbU::Unit axis ) const;
GCell* getUnder ( DbU::Unit x, DbU::Unit y ) const;
inline GCell* getUnder ( Point p ) const;
GCell* hcut ( DbU::Unit y );
GCell* vcut ( DbU::Unit x );
bool doGrid ();
Contact* getGContact ( Net* );
inline const vector<Contact*>& getGContacts () const;
Contact* breakGoThrough ( Net* net );
bool unrefContact ( Contact* );
void setXY ( DbU::Unit x, DbU::Unit y );
void updateContactsPosition ();
void cleanupGlobal ();
inline DbU::Unit getWidth () const;
inline DbU::Unit getHeight () const;
inline Edge* getWestEdge () const;
inline Edge* getEastEdge () const;
inline Edge* getSouthEdge () const;
inline Edge* getNorthEdge () const;
GCell* getWest ( DbU::Unit y ) const;
GCell* getEast ( DbU::Unit y ) const;
GCell* getSouth ( DbU::Unit x ) const;
GCell* getNorth ( DbU::Unit x ) const;
GCell* getNeighborAt ( Flags side, DbU::Unit axis ) const;
GCell* getUnder ( DbU::Unit x, DbU::Unit y ) const;
inline GCell* getUnder ( Point p ) const;
GCell* hcut ( DbU::Unit y );
GCell* vcut ( DbU::Unit x );
bool doGrid ();
Contact* getGContact ( Net* );
inline const vector<Contact*>& getGContacts () const;
Segment* hasGoThrough ( Net* ) const;
Contact* breakGoThrough ( Net* );
bool unrefContact ( Contact* );
void setSouthWestCorner ( DbU::Unit x, DbU::Unit y );
void cleanupGlobal ();
inline DbU::Unit getWidth () const;
inline DbU::Unit getHeight () const;
// Detailed routing functions.
bool hasFreeTrack ( size_t depth, float reserve ) const;
inline size_t getDepth () const;
float getHCapacity () const;
float getVCapacity () const;
float getDensity ( Flags flags=Flags::NoFlags ) const;
float getAverageHVDensity () const;
float getMaxHVDensity () const;
inline float getCDensity ( Flags flags=Flags::NoFlags ) const;
inline float getWDensity ( size_t depth, Flags flags=Flags::NoFlags ) const;
inline DbU::Unit getBlockage ( size_t depth ) const;
inline float getFragmentation ( size_t depth ) const;
inline float getFeedthroughs ( size_t depth ) const;
inline float getGlobalsCount ( size_t depth ) const;
inline const vector<AutoSegment*>& getHSegments () const;
inline const vector<AutoSegment*>& getVSegments () const;
inline const vector<AutoContact*>& getContacts () const;
AutoSegments getHStartSegments ();
AutoSegments getVStartSegments ();
AutoSegments getHStopSegments ();
AutoSegments getVStopSegments ();
inline AutoSegments getStartSegments ( Flags direction );
inline AutoSegments getStopSegments ( Flags direction );
size_t getRoutingPads ( set<RoutingPad*>& );
inline const Key& getKey () const;
size_t checkDensity () const;
bool checkEdgeSaturation ( size_t hreserved, size_t vreserved) const;
void setType ( Flags );
void addBlockage ( size_t depth, DbU::Unit );
inline void addHSegment ( AutoSegment* );
inline void addVSegment ( AutoSegment* );
inline void addContact ( AutoContact* );
void removeVSegment ( AutoSegment* );
void removeHSegment ( AutoSegment* );
void removeContact ( AutoContact* );
void updateContacts ();
size_t updateDensity ();
inline void updateKey ( size_t depth );
void truncDensities ();
bool stepBalance ( size_t depth, Set& invalidateds );
void rpDesaturate ( set<Net*>& );
bool stepDesaturate ( size_t depth
, set<Net*>&, AutoSegment*& moved
, Flags flags=Flags::NoFlags );
bool stepNetDesaturate ( size_t depth
, set<Net*>& globalNets
, Set& invalidateds );
void setEdgesOccupancy (unsigned int, unsigned int);
bool hasFreeTrack ( size_t depth, float reserve ) const;
inline size_t getDepth () const;
size_t getNetCount () const;
inline int getRpCount () const;
int getHCapacity () const;
int getVCapacity () const;
int getCapacity ( size_t depth ) const;
float getDensity ( Flags flags=Flags::NoFlags ) const;
float getDensity ( size_t depth ) const;
float getAverageHVDensity () const;
float getMaxHVDensity () const;
inline float getCDensity ( Flags flags=Flags::NoFlags ) const;
inline float getWDensity ( size_t depth, Flags flags=Flags::NoFlags ) const;
inline DbU::Unit getBlockage ( size_t depth ) const;
inline float getFragmentation ( size_t depth ) const;
inline float getFeedthroughs ( size_t depth ) const;
inline float getGlobalsCount ( size_t depth ) const;
inline const vector<AutoSegment*>& getHSegments () const;
inline const vector<AutoSegment*>& getVSegments () const;
inline const vector<AutoContact*>& getContacts () const;
AutoSegments getHStartSegments ();
AutoSegments getVStartSegments ();
AutoSegments getHStopSegments ();
AutoSegments getVStopSegments ();
inline AutoSegments getStartSegments ( Flags direction );
inline AutoSegments getStopSegments ( Flags direction );
size_t getRoutingPads ( set<RoutingPad*>& );
inline const Key& getKey () const;
inline Key* cloneKey ( size_t depth ) const;
inline Key* getLastClonedKey () const;
inline void clearClonedKey () const;
size_t checkDensity () const;
bool checkEdgeSaturation ( size_t hreserved, size_t vreserved) const;
void setType ( Flags );
void addBlockage ( size_t depth, DbU::Unit );
inline void addHSegment ( AutoSegment* );
inline void addVSegment ( AutoSegment* );
inline void addContact ( AutoContact* );
void removeVSegment ( AutoSegment* );
void removeHSegment ( AutoSegment* );
void removeContact ( AutoContact* );
void updateGContacts ( Flags flags );
void updateContacts ();
size_t updateDensity ();
inline void updateKey ( size_t depth );
void truncDensities ();
bool stepBalance ( size_t depth, Set& invalidateds );
void rpDesaturate ( set<Net*>& );
bool stepDesaturate ( size_t depth
, set<Net*>&, AutoSegment*& moved
, Flags flags=Flags::NoFlags );
bool stepNetDesaturate ( size_t depth
, set<Net*>& globalNets
, Set& invalidateds );
inline void incRpCount ( int );
void forceEdgesCapacities ( unsigned int hcapacities, unsigned int vcapacities );
// Misc. functions.
inline const Flags& flags () const;
inline Flags& flags ();
void _add ( Edge* edge, Flags side );
void _remove ( Edge* edge, Flags side=Flags::AllSides );
void _destroyEdges ();
void _revalidate ();
inline const Flags& flags () const;
inline Flags& flags ();
void _add ( Edge* edge, Flags side );
void _remove ( Edge* edge, Flags side=Flags::AllSides );
void _destroyEdges ();
private:
void _moveEdges ( GCell* dest, size_t ibegin, Flags flags );
void _moveEdges ( GCell* dest, size_t ibegin, Flags flags );
public:
// Observers.
template<typename OwnerT>
inline OwnerT* getObserver ( size_t slot );
inline void setObserver ( size_t slot, BaseObserver* );
inline void notify ( unsigned int flags );
inline OwnerT* getObserver ( size_t slot );
inline void setObserver ( size_t slot, BaseObserver* );
inline void notify ( unsigned int flags );
// ExtensionGo support.
inline const Name& staticGetName ();
virtual const Name& getName () const;
virtual void translate ( const DbU::Unit&, const DbU::Unit& );
virtual Box getBoundingBox () const;
inline const Name& staticGetName ();
virtual const Name& getName () const;
virtual void translate ( const DbU::Unit&, const DbU::Unit& );
virtual Box getBoundingBox () const;
virtual void invalidate ( bool propagateFlag=true );
virtual void materialize ();
public:
// Inspector support.
virtual string _getTypeName () const;
virtual string _getString () const;
virtual Record* _getRecord () const;
virtual string _getTypeName () const;
virtual string _getString () const;
virtual Record* _getRecord () const;
protected:
GCell ( AnabaticEngine*, DbU::Unit xmin, DbU::Unit ymin );
virtual ~GCell ();
GCell* _create ( DbU::Unit xmin, DbU::Unit ymin );
virtual void _postCreate ();
virtual void _preDestroy ();
GCell ( AnabaticEngine*, DbU::Unit xmin, DbU::Unit ymin );
virtual ~GCell ();
GCell* _create ( DbU::Unit xmin, DbU::Unit ymin );
virtual void _postCreate ();
virtual void _preDestroy ();
private:
GCell ( const GCell& );
GCell& operator= ( const GCell& );
GCell ( const GCell& );
GCell& operator= ( const GCell& );
private:
static Name _extensionName;
static uint32_t _displayMode;
static DbU::Unit _matrixHSide;
static DbU::Unit _matrixVSide;
Observable _observable;
AnabaticEngine* _anabatic;
Flags _flags;
@ -297,6 +334,7 @@ namespace Anabatic {
vector<AutoContact*> _contacts;
size_t _depth;
size_t _pinDepth;
int _rpCount;
DbU::Unit* _blockages;
float _cDensity;
float* _densities;
@ -304,54 +342,71 @@ namespace Anabatic {
float* _fragmentations;
float* _globalsCount;
Key _key;
mutable Key* _lastClonedKey;
};
inline bool GCell::isHFlat () const { return getYMin() == getYMax(); }
inline bool GCell::isVFlat () const { return getXMin() == getXMax(); }
inline bool GCell::isFlat () const { return isHFlat() or isVFlat(); }
inline bool GCell::isDevice () const { return _flags & Flags::DeviceGCell; }
inline bool GCell::isHChannel () const { return _flags & Flags::HChannelGCell; }
inline bool GCell::isVChannel () const { return _flags & Flags::VChannelGCell; }
inline bool GCell::isStrut () const { return _flags & Flags::StrutGCell; }
inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; }
inline bool GCell::isIoPad () const { return _flags & Flags::IoPadGCell; }
inline bool GCell::isSaturated () const { return _flags & Flags::Saturated; }
inline bool GCell::isInvalidated () const { return _flags & Flags::Invalidated; }
inline Flags GCell::getType () const { return _flags & Flags::GCellTypeMask; }
inline AnabaticEngine* GCell::getAnabatic () const { return _anabatic; }
inline DbU::Unit GCell::getXMin () const { return _xmin; }
inline DbU::Unit GCell::getYMin () const { return _ymin; }
inline Edges GCell::getEdges ( Flags sides ) const { return new GCell_Edges(this,sides); }
inline const vector<Edge*>& GCell::getWestEdges () const { return _westEdges; }
inline const vector<Edge*>& GCell::getEastEdges () const { return _eastEdges; }
inline const vector<Edge*>& GCell::getNorthEdges () const { return _northEdges; }
inline const vector<Edge*>& GCell::getSouthEdges () const { return _southEdges; }
inline GCell* GCell::getWest () const { return _westEdges.empty() ? NULL : _westEdges[0]->getOpposite(this); }
inline GCell* GCell::getEast () const { return _eastEdges.empty() ? NULL : _eastEdges[0]->getOpposite(this); }
inline GCell* GCell::getSouth () const { return _southEdges.empty() ? NULL : _southEdges[0]->getOpposite(this); }
inline GCell* GCell::getNorth () const { return _northEdges.empty() ? NULL : _northEdges[0]->getOpposite(this); }
inline bool GCell::isHFlat () const { return getYMin() == getYMax(); }
inline bool GCell::isVFlat () const { return getXMin() == getXMax(); }
inline bool GCell::isFlat () const { return isHFlat() or isVFlat(); }
inline bool GCell::isDevice () const { return _flags & Flags::DeviceGCell; }
inline bool GCell::isHChannel () const { return _flags & Flags::HChannelGCell; }
inline bool GCell::isVChannel () const { return _flags & Flags::VChannelGCell; }
inline bool GCell::isStrut () const { return _flags & Flags::StrutGCell; }
inline bool GCell::isAnalog () const { return _flags & Flags::AnalogGCellMask; }
inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; }
inline bool GCell::isRow () const { return _flags & Flags::RowGCellMask; }
inline bool GCell::isIoPad () const { return _flags & Flags::IoPadGCell; }
inline bool GCell::isGoStraight () const { return _flags & Flags::GoStraight; }
inline bool GCell::isHRail () const { return _flags & Flags::HRailGCell; }
inline bool GCell::isVRail () const { return _flags & Flags::VRailGCell; }
inline bool GCell::isStdCellRow () const { return _flags & Flags::StdCellRow; }
inline bool GCell::isChannelRow () const { return _flags & Flags::ChannelRow; }
inline bool GCell::isSaturated () const { return _flags & Flags::Saturated; }
inline bool GCell::isInvalidated () const { return _flags & Flags::Invalidated; }
inline DbU::Unit GCell::getMatrixHSide () { return _matrixHSide; }
inline DbU::Unit GCell::getMatrixVSide () { return _matrixVSide; }
inline Flags GCell::getType () const { return _flags & Flags::GCellTypeMask; }
inline AnabaticEngine* GCell::getAnabatic () const { return _anabatic; }
inline DbU::Unit GCell::getXMin () const { return _xmin; }
inline DbU::Unit GCell::getYMin () const { return _ymin; }
inline Interval GCell::getHSide ( int shrink ) const { return getSide(Flags::Horizontal,shrink); }
inline Interval GCell::getVSide ( int shrink ) const { return getSide(Flags::Vertical ,shrink); }
inline Edges GCell::getEdges ( Flags sides ) const { return new GCell_Edges(this,sides); }
inline const vector<Edge*>& GCell::getWestEdges () const { return _westEdges; }
inline const vector<Edge*>& GCell::getEastEdges () const { return _eastEdges; }
inline const vector<Edge*>& GCell::getNorthEdges () const { return _northEdges; }
inline const vector<Edge*>& GCell::getSouthEdges () const { return _southEdges; }
inline GCell* GCell::getWest () const { return _westEdges.empty() ? NULL : _westEdges[0]->getOpposite(this); }
inline GCell* GCell::getEast () const { return _eastEdges.empty() ? NULL : _eastEdges[0]->getOpposite(this); }
inline GCell* GCell::getSouth () const { return _southEdges.empty() ? NULL : _southEdges[0]->getOpposite(this); }
inline GCell* GCell::getNorth () const { return _northEdges.empty() ? NULL : _northEdges[0]->getOpposite(this); }
inline Edge* GCell::getWestEdge () const { return _westEdges.empty() ? NULL : _westEdges[0]; }
inline Edge* GCell::getEastEdge () const { return _eastEdges.empty() ? NULL : _eastEdges[0]; }
inline Edge* GCell::getSouthEdge () const { return _southEdges.empty() ? NULL : _southEdges[0]; }
inline Edge* GCell::getNorthEdge () const { return _northEdges.empty() ? NULL : _northEdges[0]; }
inline Edge* GCell::getWestEdge () const { return _westEdges.empty() ? NULL : _westEdges[0]; }
inline Edge* GCell::getEastEdge () const { return _eastEdges.empty() ? NULL : _eastEdges[0]; }
inline Edge* GCell::getSouthEdge () const { return _southEdges.empty() ? NULL : _southEdges[0]; }
inline Edge* GCell::getNorthEdge () const { return _northEdges.empty() ? NULL : _northEdges[0]; }
inline GCell* GCell::getUnder ( Point p ) const { return getUnder(p.getX(),p.getY()); }
inline const vector<Contact*>& GCell::getGContacts () const { return _gcontacts; }
inline size_t GCell::getDepth () const { return _depth; }
inline const vector<AutoSegment*>& GCell::getVSegments () const { return _vsegments; }
inline const vector<AutoSegment*>& GCell::getHSegments () const { return _hsegments; }
inline const vector<AutoContact*>& GCell::getContacts () const { return _contacts; }
inline GCell* GCell::getUnder ( Point p ) const { return getUnder(p.getX(),p.getY()); }
inline const vector<Contact*>& GCell::getGContacts () const { return _gcontacts; }
inline size_t GCell::getDepth () const { return _depth; }
inline int GCell::getRpCount () const { return _rpCount; }
const vector<AutoSegment*>& GCell::getVSegments () const { return _vsegments; }
inline const vector<AutoSegment*>& GCell::getHSegments () const { return _hsegments; }
inline const vector<AutoContact*>& GCell::getContacts () const { return _contacts; }
inline DbU::Unit GCell::getWidth () const { return (getXMax()-getXMin()); }
inline DbU::Unit GCell::getHeight () const { return (getYMax()-getYMin()); }
inline DbU::Unit GCell::getWidth () const { return (getXMax()-getXMin()); }
inline DbU::Unit GCell::getHeight () const { return (getYMax()-getYMin()); }
inline float GCell::getDensity ( size_t depth ) const { return (depth<_depth) ? _densities[depth] : 0.0; }
inline const GCell::Key& GCell::getKey () const { return _key; }
inline void GCell::setType ( Flags type ) { _flags.reset(Flags::GCellTypeMask); _flags |= (type&Flags::GCellTypeMask); };
inline void GCell::updateKey ( size_t depth ) { _key.update(depth); }
inline const Flags& GCell::flags () const { return _flags; }
inline Flags& GCell::flags () { return _flags; }
inline const GCell::Key& GCell::getKey () const { return _key; }
inline GCell::Key* GCell::cloneKey ( size_t depth ) const { _lastClonedKey = new Key(this,depth); return _lastClonedKey; }
inline void GCell::clearClonedKey () const { _lastClonedKey=NULL; }
inline GCell::Key* GCell::getLastClonedKey () const { return _lastClonedKey; }
inline void GCell::setType ( Flags type ) { _flags.reset(Flags::GCellTypeMask); _flags |= (type&Flags::GCellTypeMask); };
inline void GCell::updateKey ( size_t depth ) { _key.update(depth); }
inline const Flags& GCell::flags () const { return _flags; }
inline Flags& GCell::flags () { return _flags; }
inline DbU::Unit GCell::getXMax ( int shrink ) const
{ return _eastEdges.empty() ? getCell()->getAbutmentBox().getXMax() - shrink
@ -382,6 +437,10 @@ namespace Anabatic {
return Interval( getXMin(), getConstraintXMax(shrink) );
}
inline void GCell::incRpCount ( int delta )
{ _rpCount = (_rpCount + delta > 0) ? (_rpCount + delta) : 0; }
inline void GCell::setObserver ( size_t slot, BaseObserver* observer )
{ _observable.setObserver( slot, observer ); }
@ -418,12 +477,12 @@ namespace Anabatic {
inline DbU::Unit GCell::getBlockage ( size_t depth ) const
{ return (depth<_depth) ? _blockages[depth] : 0; }
inline void GCell::addVSegment ( AutoSegment* segment )
{ _flags |= Flags::Invalidated; _vsegments.push_back(segment); }
inline void GCell::addHSegment ( AutoSegment* segment )
{ _flags |= Flags::Invalidated; _hsegments.push_back(segment); }
inline void GCell::addVSegment ( AutoSegment* segment )
{ _flags |= Flags::Invalidated; _vsegments.push_back(segment); }
inline void GCell::addContact ( AutoContact* contact )
{ _flags |= Flags::Invalidated; _contacts.push_back(contact); }
@ -435,17 +494,25 @@ namespace Anabatic {
return lhs.getId() < rhs.getId();
}
// GCell::CompareByKey Inline Functions.
inline bool GCell::CompareByKey::operator() ( const GCell* lhs, const GCell* rhs )
{ return lhs->getKey() < rhs->getKey(); }
// GCell::Key Inline Functions.
inline GCell::Key::Key ( GCell* owner, size_t depth ) : _gcell(owner), _density(owner->getWDensity(depth,Flags::NoUpdate)) {}
inline float GCell::Key::getDensity () const { return _density; }
inline GCell* GCell::Key::getGCell () const { return _gcell; }
inline void GCell::Key::update ( size_t depth ) { _density=_gcell->getWDensity(depth); }
inline GCell::Key::Key ( const GCell* owner, size_t depth )
: _gcell(owner)
, _density(owner->getWDensity(depth,Flags::NoUpdate))
{ }
inline GCell::Key::~Key ()
{ if (isActive()) _gcell->clearClonedKey(); }
inline float GCell::Key::getDensity () const { return _density; }
inline const GCell* GCell::Key::getGCell () const { return _gcell; }
inline void GCell::Key::update ( size_t depth ) { _density=_gcell->getWDensity(depth); }
inline bool GCell::Key::isActive () const { return (this == _gcell->getLastClonedKey()); }
inline bool GCell::Key::isSaturated () const { return _gcell->isSaturated(); }
inline bool operator< ( const GCell::Key& lhs, const GCell::Key& rhs )
{
@ -455,6 +522,22 @@ namespace Anabatic {
return lhs._gcell->getId() < rhs._gcell->getId();
}
inline bool GCell::Key::Compare::operator() ( const GCell::Key* lhs, const GCell::Key* rhs )
{
//if (lhs->isSaturated() xor rhs->isSaturated()) return lhs->isSaturated();
float difference = lhs->_density - rhs->_density;
if (difference != 0.0) return (difference < 0.0);
return lhs->_gcell->getId() < rhs->_gcell->getId();
}
// -------------------------------------------------------------------
// Class : "GCellKeyQueue".
typedef std::priority_queue< GCell::Key*, std::vector<GCell::Key*>, GCell::Key::Compare > GCellKeyQueue;
// -------------------------------------------------------------------
// Class : "GCellDensitySet".
@ -499,5 +582,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::GCell);
#endif // ANABATIC_GCELL_H

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Matrix.h<anabatic>" -*-
//
// 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 |
@ -94,7 +94,7 @@ namespace Anabatic {
inline GCell* getUnder ( Point ) const;
void setCell ( Cell*, DbU::Unit side );
void updateLookup ( GCell* );
void resize ( Box area, DbU::Unit side );
void resize ( Cell*, const vector<GCell*>& );
void show () const;
// Inspector support.
virtual Record* _getRecord () const;

View File

@ -0,0 +1,422 @@
// -*- 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++ Header : "./anabatic/NetBuilder.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_NET_BUILDER_H
#define ANABATIC_NET_BUILDER_H
#include <vector>
#include <map>
namespace Hurricane {
class Hook;
class Net;
class RoutingPad;
class Component;
}
namespace Anabatic {
using std::string;
using std::vector;
using std::map;
using std::endl;
using Hurricane::Hook;
using Hurricane::Net;
using Hurricane::RoutingPad;
using Hurricane::Component;
class GCell;
class AutoContact;
class AutoSegment;
class AnabaticEngine;
// -------------------------------------------------------------------
// Class : "ForkStack".
class ForkStack {
public:
inline void push ( Hook* from, AutoContact* contact );
inline void pop ();
inline Hook* getFrom () const;
inline AutoContact* getContact () const;
private:
struct Element {
Hook* _from;
AutoContact* _contact;
inline Element ( Hook* from, AutoContact* contact );
};
private:
list<Element> _stack;
};
inline ForkStack::Element::Element ( Hook* from, AutoContact* contact ) : _from(from), _contact(contact) {}
inline void ForkStack::pop () { if (not _stack.empty()) _stack.pop_back(); }
inline Hook* ForkStack::getFrom () const { return _stack.empty() ? NULL : _stack.back()._from; }
inline AutoContact* ForkStack::getContact () const { return _stack.empty() ? NULL : _stack.back()._contact; }
inline void ForkStack::push ( Hook* from, AutoContact* contact )
{
cdebug_log(145,0) << " Stacking " << from << " + " << contact << endl;
_stack.push_back( Element(from,contact) );
}
// -------------------------------------------------------------------
// Class : "NetBuilder".
class NetBuilder {
public:
enum FunctionFlags { NoFlags = (1 << 0)
, SortDecreasing = (1 << 1)
, HAccess = (1 << 2)
, HAccessEW = (1 << 3)
, VSmall = (1 << 4)
, HSmall = (1 << 5)
, Punctual = (1 << 6)
, HCollapse = (1 << 7)
, VCollapse = (1 << 8)
, Terminal = (1 << 9)
, DoSourceContact = (1 << 10)
, DoTargetContact = (1 << 11)
, SouthBound = (1 << 12)
, NorthBound = (1 << 13)
, WestBound = (1 << 14)
, EastBound = (1 << 15)
, Middle = (1 << 16)
, UseNonPref = (1 << 17)
, NoProtect = (1 << 18)
, HBothAccess = HAccess|HAccessEW
, SouthWest = SouthBound|WestBound
, NorthEast = NorthBound|EastBound
};
enum TopologyFlag { Global_Vertical_End = 0x00000001
, Global_Horizontal_End = 0x00000002
, Global_Horizontal = 0x00000004
, Global_Vertical = 0x00000008
, Global_Turn = 0x00000010
, Global_Fork = 0x00000020
, Global_Fixed = 0x00000040
, Global_End = Global_Vertical_End | Global_Horizontal_End
, Global_Split = Global_Horizontal | Global_Vertical | Global_Fork
};
// Connexity Union Type.
enum ConnexityBits { GlobalBSize = 8
, Metal1BSize = 4
, Metal2BSize = 4
, Metal3BSize = 4
, PadsBSize = 4
, PinsBSize = 4
};
union UConnexity {
uint64_t connexity;
struct {
unsigned int globals : GlobalBSize;
unsigned int M1 : Metal1BSize;
unsigned int M2 : Metal2BSize;
unsigned int M3 : Metal3BSize;
unsigned int Pad : PadsBSize;
unsigned int Pin : PinsBSize;
} fields;
};
public:
template< typename BuilderT >
static void load ( AnabaticEngine*, Net* );
static void getPositions ( Component* anchor, Point& source, Point& target );
static uint64_t checkRoutingPadSize ( Component* anchor );
static Hook* getSegmentOppositeHook ( Hook* hook );
static uint64_t getSegmentHookType ( Hook* hook );
static void sortHookByX ( vector<Hook*>& , uint64_t flags=NoFlags );
static void sortHookByY ( vector<Hook*>& , uint64_t flags=NoFlags );
static void sortRpByX ( vector<RoutingPad*>& , uint64_t flags=NoFlags );
static void sortRpByY ( vector<RoutingPad*>& , uint64_t flags=NoFlags );
public:
NetBuilder ();
virtual ~NetBuilder ();
void clear ();
inline bool isTwoMetals () const;
inline AnabaticEngine* getAnabatic () const;
inline unsigned int getDegree () const;
inline void setDegree ( unsigned int degree );
void fixSegments ();
NetBuilder& setStartHook ( AnabaticEngine*
, Hook* fromHook
, AutoContact* sourceContact=NULL );
void construct ();
inline unsigned int getStateG () const;
inline UConnexity getConnexity () const;
inline UConnexity& getConnexity ();
inline Net* getNet () const;
inline GCell* getGCell () const;
inline AutoContact* getSourceContact () const;
inline AutoContact* getSouthWestContact () const;
inline AutoContact*& getSouthWestContact ();
inline AutoContact* getNorthEastContact () const;
inline AutoContact*& getNorthEastContact ();
inline Hook* getFromHook () const;
inline ForkStack& getForks ();
inline vector<RoutingPad*>& getRoutingPads ();
inline map<Component*,AutoSegment*>& getRpLookup ();
inline unsigned int getTopology () const;
inline vector<Hook*>& getNorths ();
inline vector<Hook*>& getSouths ();
inline Hook* north ( size_t i=0 ) const;
inline Hook* south ( size_t i=0 ) const;
inline Hook* east ( size_t i=0 ) const;
inline Hook* west ( size_t i=0 ) const;
inline void addToNorths ( Hook* );
inline void addToSouths ( Hook* );
inline void addToEasts ( Hook* );
inline void addToWests ( Hook* );
inline void clearNorths ();
inline void clearSouths ();
inline void clearEasts ();
inline void clearWests ();
inline void setFromHook ( Hook* );
inline void setSouthWestContact ( AutoContact* );
inline void setNorthEastContact ( AutoContact* );
inline void setBothCornerContacts ( AutoContact* );
inline void swapCornerContacts ();
inline void addToFixSegments ( AutoSegment* );
bool push ( Hook* to, AutoContact* contact, uint64_t flags=0 );
virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags ) = 0;
virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags ) = 0;
virtual AutoContact* doRp_AccessPad ( RoutingPad*, uint64_t flags );
virtual AutoContact* doRp_AccessAnalog ( GCell*, RoutingPad*, uint64_t flags );
void doRp_StairCaseH ( GCell*, Component* rp1, Component* rp2 );
void doRp_StairCaseV ( GCell*, Component* rp1, Component* rp2 );
void _load ( AnabaticEngine*, Net* );
private:
virtual bool _do_xG ();
virtual bool _do_2G ();
virtual bool _do_xG_1Pad ();
virtual bool _do_1G_1PinM1 ();
virtual bool _do_2G_1PinM1 ();
virtual bool _do_1G_1PinM2 ();
virtual bool _do_xG_1PinM2 ();
virtual bool _do_1G_1PinM3 ();
virtual bool _do_xG_1PinM3 ();
virtual bool _do_1G_1M1 ();
virtual bool _do_2G_1M1 ();
virtual bool _do_1G_xM1 ();
virtual bool _do_xG_1M1 ();
virtual bool _do_xG_xM1_xM3 ();
virtual bool _do_xG_1M1_1M2 ();
virtual bool _do_4G_1M2 ();
virtual bool _do_xG_xM2 ();
virtual bool _do_1G_1M3 ();
virtual bool _do_xG_xM3 ();
virtual bool _do_1G_xM1_1PinM2 ();
virtual bool _do_2G_xM1_1PinM2 ();
virtual bool _do_1G_1M1_1PinM3 ();
virtual bool _do_2G_xM1_1PinM3 ();
virtual bool _do_3G_xM1_1PinM3 ();
virtual bool _do_globalSegment ();
virtual void singleGCell ( AnabaticEngine*, Net* );
AutoContact* _doHChannel ();
AutoContact* _doVChannel ();
AutoContact* _doStrut ();
AutoContact* _doDevice ();
AutoContact* _doHRail ();
AutoContact* _doVRail ();
void _doIoPad ();
unsigned int getNumberGlobals ();
unsigned int getDeviceNeighbourBound();
virtual string getTypeName () const;
private:
#define CONNEXITY_VALUE( Gs, M1s, M2s, M3s, pads, pins ) \
Gs + ((M1s ) << GlobalBSize) \
+ ((M2s ) << (GlobalBSize+Metal1BSize)) \
+ ((M3s ) << (GlobalBSize+Metal1BSize+Metal2BSize)) \
+ ((pads) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize)) \
+ ((pins) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize+PadsBSize))
// Connexity Name | G|M1|M2|M3|Pad|Pin|
enum ConnexityFlag { Conn_0G = CONNEXITY_VALUE( 0, 0, 0, 0, 0 , 0 )
, Conn_2G = CONNEXITY_VALUE( 2, 0, 0, 0, 0 , 0 )
, Conn_3G = CONNEXITY_VALUE( 3, 0, 0, 0, 0 , 0 )
, Conn_4G = CONNEXITY_VALUE( 4, 0, 0, 0, 0 , 0 )
, Conn_5G = CONNEXITY_VALUE( 5, 0, 0, 0, 0 , 0 )
, Conn_6G = CONNEXITY_VALUE( 6, 0, 0, 0, 0 , 0 )
, Conn_0G_2M1 = CONNEXITY_VALUE( 0, 2, 0, 0, 0 , 0 )
, Conn_1G_1M1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 0 )
, Conn_1G_2M1 = CONNEXITY_VALUE( 1, 2, 0, 0, 0 , 0 )
, Conn_1G_3M1 = CONNEXITY_VALUE( 1, 3, 0, 0, 0 , 0 )
, Conn_1G_4M1 = CONNEXITY_VALUE( 1, 4, 0, 0, 0 , 0 )
, Conn_1G_5M1 = CONNEXITY_VALUE( 1, 5, 0, 0, 0 , 0 )
, Conn_1G_6M1 = CONNEXITY_VALUE( 1, 6, 0, 0, 0 , 0 )
, Conn_1G_7M1 = CONNEXITY_VALUE( 1, 7, 0, 0, 0 , 0 )
, Conn_1G_8M1 = CONNEXITY_VALUE( 1, 8, 0, 0, 0 , 0 )
, Conn_1G_9M1 = CONNEXITY_VALUE( 1, 9, 0, 0, 0 , 0 )
, Conn_1G_1M2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 0 )
, Conn_1G_2M2 = CONNEXITY_VALUE( 1, 0, 2, 0, 0 , 0 )
, Conn_1G_3M2 = CONNEXITY_VALUE( 1, 0, 3, 0, 0 , 0 )
, Conn_1G_4M2 = CONNEXITY_VALUE( 1, 0, 4, 0, 0 , 0 )
, Conn_1G_1M3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 0 )
, Conn_1G_2M3 = CONNEXITY_VALUE( 1, 0, 0, 2, 0 , 0 )
, Conn_1G_3M3 = CONNEXITY_VALUE( 1, 0, 0, 3, 0 , 0 )
, Conn_1G_4M3 = CONNEXITY_VALUE( 1, 0, 0, 4, 0 , 0 )
, Conn_1G_1M1_1M2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 0 )
, Conn_1G_1M1_1M3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_2G_1M1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 0 )
, Conn_2G_2M1 = CONNEXITY_VALUE( 2, 2, 0, 0, 0 , 0 )
, Conn_2G_3M1 = CONNEXITY_VALUE( 2, 3, 0, 0, 0 , 0 )
, Conn_2G_4M1 = CONNEXITY_VALUE( 2, 4, 0, 0, 0 , 0 )
, Conn_2G_5M1 = CONNEXITY_VALUE( 2, 5, 0, 0, 0 , 0 )
, Conn_2G_6M1 = CONNEXITY_VALUE( 2, 6, 0, 0, 0 , 0 )
, Conn_2G_7M1 = CONNEXITY_VALUE( 2, 7, 0, 0, 0 , 0 )
, Conn_2G_8M1 = CONNEXITY_VALUE( 2, 8, 0, 0, 0 , 0 )
, Conn_2G_9M1 = CONNEXITY_VALUE( 2, 9, 0, 0, 0 , 0 )
, Conn_2G_1M2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 0 )
, Conn_2G_2M2 = CONNEXITY_VALUE( 2, 0, 2, 0, 0 , 0 )
, Conn_2G_3M2 = CONNEXITY_VALUE( 2, 0, 3, 0, 0 , 0 )
, Conn_2G_4M2 = CONNEXITY_VALUE( 2, 0, 4, 0, 0 , 0 )
, Conn_2G_1M3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 0 )
, Conn_2G_2M3 = CONNEXITY_VALUE( 2, 0, 0, 2, 0 , 0 )
, Conn_2G_3M3 = CONNEXITY_VALUE( 2, 0, 0, 3, 0 , 0 )
, Conn_2G_4M3 = CONNEXITY_VALUE( 2, 0, 0, 4, 0 , 0 )
, Conn_2G_1M1_1M2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_3G_1M1 = CONNEXITY_VALUE( 3, 1, 0, 0, 0 , 0 )
, Conn_3G_2M1 = CONNEXITY_VALUE( 3, 2, 0, 0, 0 , 0 )
, Conn_3G_3M1 = CONNEXITY_VALUE( 3, 3, 0, 0, 0 , 0 )
, Conn_3G_4M1 = CONNEXITY_VALUE( 3, 4, 0, 0, 0 , 0 )
, Conn_3G_5M1 = CONNEXITY_VALUE( 3, 5, 0, 0, 0 , 0 )
, Conn_3G_6M1 = CONNEXITY_VALUE( 3, 6, 0, 0, 0 , 0 )
, Conn_3G_7M1 = CONNEXITY_VALUE( 3, 7, 0, 0, 0 , 0 )
, Conn_3G_8M1 = CONNEXITY_VALUE( 3, 8, 0, 0, 0 , 0 )
, Conn_3G_9M1 = CONNEXITY_VALUE( 3, 9, 0, 0, 0 , 0 )
, Conn_3G_1M2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 0 )
, Conn_3G_2M2 = CONNEXITY_VALUE( 3, 0, 2, 0, 0 , 0 )
, Conn_3G_1M3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 0 )
, Conn_3G_2M3 = CONNEXITY_VALUE( 3, 0, 0, 2, 0 , 0 )
, Conn_3G_3M3 = CONNEXITY_VALUE( 3, 0, 0, 3, 0 , 0 )
, Conn_3G_4M3 = CONNEXITY_VALUE( 3, 0, 0, 4, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_4G_1M1 = CONNEXITY_VALUE( 4, 1, 0, 0, 0 , 0 )
, Conn_4G_2M1 = CONNEXITY_VALUE( 4, 2, 0, 0, 0 , 0 )
, Conn_4G_3M1 = CONNEXITY_VALUE( 4, 3, 0, 0, 0 , 0 )
, Conn_4G_4M1 = CONNEXITY_VALUE( 4, 4, 0, 0, 0 , 0 )
, Conn_4G_5M1 = CONNEXITY_VALUE( 4, 5, 0, 0, 0 , 0 )
, Conn_4G_6M1 = CONNEXITY_VALUE( 4, 6, 0, 0, 0 , 0 )
, Conn_4G_7M1 = CONNEXITY_VALUE( 4, 7, 0, 0, 0 , 0 )
, Conn_4G_8M1 = CONNEXITY_VALUE( 4, 8, 0, 0, 0 , 0 )
, Conn_4G_9M1 = CONNEXITY_VALUE( 4, 9, 0, 0, 0 , 0 )
, Conn_4G_1M2 = CONNEXITY_VALUE( 4, 0, 1, 0, 0 , 0 )
, Conn_4G_1M3 = CONNEXITY_VALUE( 4, 0, 0, 1, 0 , 0 )
, Conn_1G_1Pad = CONNEXITY_VALUE( 1, 0, 0, 0, 1 , 0 )
, Conn_2G_1Pad = CONNEXITY_VALUE( 2, 0, 0, 0, 1 , 0 )
, Conn_3G_1Pad = CONNEXITY_VALUE( 3, 0, 0, 0, 1 , 0 )
, Conn_1G_1PinM1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 1 )
, Conn_2G_1PinM1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 1 )
, Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 1 )
, Conn_2G_1PinM2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 1 )
, Conn_3G_1PinM2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 1 )
, Conn_1G_1M1_1PinM2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 1 )
, Conn_1G_2M1_1PinM2 = CONNEXITY_VALUE( 1, 2, 1, 0, 0 , 1 )
, Conn_2G_1M1_1PinM2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 1 )
, Conn_2G_2M1_1PinM2 = CONNEXITY_VALUE( 2, 2, 1, 0, 0 , 1 )
, Conn_1G_1PinM3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 1 )
, Conn_2G_1PinM3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 1 )
, Conn_3G_1PinM3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 1 )
, Conn_1G_1M1_1PinM3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 1 )
, Conn_2G_1M1_1PinM3 = CONNEXITY_VALUE( 2, 1, 0, 1, 0 , 1 )
, Conn_2G_2M1_1PinM3 = CONNEXITY_VALUE( 2, 2, 0, 1, 0 , 1 )
, Conn_2G_3M1_1PinM3 = CONNEXITY_VALUE( 2, 3, 0, 1, 0 , 1 )
, Conn_3G_1M1_1PinM3 = CONNEXITY_VALUE( 3, 1, 0, 1, 0 , 1 )
, Conn_3G_2M1_1PinM3 = CONNEXITY_VALUE( 3, 2, 0, 1, 0 , 1 )
, Conn_3G_3M1_1PinM3 = CONNEXITY_VALUE( 3, 3, 0, 1, 0 , 1 )
};
#undef CONNEXITY_VALUE
// Attributes.
private:
AnabaticEngine* _anabatic;
ForkStack _forks;
UConnexity _connexity;
unsigned int _topology;
Net* _net;
GCell* _gcell;
AutoContact* _sourceContact;
AutoContact* _southWestContact;
AutoContact* _northEastContact;
Hook* _fromHook;
vector<Hook*> _easts;
vector<Hook*> _wests;
vector<Hook*> _norths;
vector<Hook*> _souths;
vector<RoutingPad*> _routingPads;
map<Component*,AutoSegment*> _routingPadAutoSegments;
vector<AutoSegment*> _toFixSegments;
unsigned int _degree;
bool _isTwoMetals;
// Sort classes.
public:
};
inline bool NetBuilder::isTwoMetals () const { return _isTwoMetals; }
inline AnabaticEngine* NetBuilder::getAnabatic () const { return _anabatic; }
inline unsigned int NetBuilder::getDegree () const { return _degree; }
inline NetBuilder::UConnexity NetBuilder::getConnexity () const { return _connexity; }
inline NetBuilder::UConnexity& NetBuilder::getConnexity () { return _connexity; }
inline ForkStack& NetBuilder::getForks () { return _forks; }
inline unsigned int NetBuilder::getStateG () const { return _connexity.fields.globals; }
inline GCell* NetBuilder::getGCell () const { return _gcell; }
inline Net* NetBuilder::getNet () const { return _net; }
inline AutoContact* NetBuilder::getSourceContact () const { return _sourceContact; }
inline AutoContact* NetBuilder::getSouthWestContact () const { return _southWestContact; }
inline AutoContact*& NetBuilder::getSouthWestContact () { return _southWestContact; }
inline AutoContact* NetBuilder::getNorthEastContact () const { return _northEastContact; }
inline AutoContact*& NetBuilder::getNorthEastContact () { return _northEastContact; }
inline Hook* NetBuilder::getFromHook () const { return _fromHook; }
inline unsigned int NetBuilder::getTopology () const { return _topology; }
inline vector<RoutingPad*>& NetBuilder::getRoutingPads () { return _routingPads; }
inline map<Component*,AutoSegment*>& NetBuilder::getRpLookup () { return _routingPadAutoSegments; }
inline vector<Hook*>& NetBuilder::getNorths () { return _norths; }
inline vector<Hook*>& NetBuilder::getSouths () { return _souths; }
inline Hook* NetBuilder::north ( size_t i ) const { return (i<_norths.size()) ? _norths[i] : NULL; }
inline Hook* NetBuilder::south ( size_t i ) const { return (i<_souths.size()) ? _souths[i] : NULL; }
inline Hook* NetBuilder::east ( size_t i ) const { return (i<_easts .size()) ? _easts [i] : NULL; }
inline Hook* NetBuilder::west ( size_t i ) const { return (i<_wests .size()) ? _wests [i] : NULL; }
inline void NetBuilder::setDegree ( unsigned int degree ) { _degree = degree; }
inline void NetBuilder::setFromHook ( Hook* hook ) { _fromHook = hook; }
inline void NetBuilder::setBothCornerContacts ( AutoContact* ac ) { _southWestContact = _northEastContact = ac; }
inline void NetBuilder::setSouthWestContact ( AutoContact* ac ) { _southWestContact = ac; }
inline void NetBuilder::setNorthEastContact ( AutoContact* ac ) { _northEastContact = ac; }
inline void NetBuilder::swapCornerContacts () { std::swap( _southWestContact, _northEastContact ); }
inline void NetBuilder::addToFixSegments ( AutoSegment* as ) { _toFixSegments.push_back(as); }
inline void NetBuilder::addToNorths ( Hook* hook ) { _norths.push_back(hook); }
inline void NetBuilder::addToSouths ( Hook* hook ) { _souths.push_back(hook); }
inline void NetBuilder::addToEasts ( Hook* hook ) { _easts .push_back(hook); }
inline void NetBuilder::addToWests ( Hook* hook ) { _wests .push_back(hook); }
inline void NetBuilder::clearNorths () { _norths.clear(); }
inline void NetBuilder::clearSouths () { _souths.clear(); }
inline void NetBuilder::clearEasts () { _easts .clear(); }
inline void NetBuilder::clearWests () { _wests .clear(); }
template< typename BuilderT >
void NetBuilder::load ( AnabaticEngine* engine, Net* net ) { BuilderT()._load(engine,net); }
}
#endif // ANABATIC_NET_BUILDER_H

View File

@ -0,0 +1,71 @@
// -*- 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++ Header : "./anabatic/NetBuilderHV.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_NET_BUILDER_HV_H
#define ANABATIC_NET_BUILDER_HV_H
#include "anabatic/NetBuilder.h"
namespace Anabatic {
// -----------------------------------------------------------------
// Class : "NetBuilderHV".
class NetBuilderHV : public NetBuilder {
public:
NetBuilderHV ();
virtual ~NetBuilderHV ();
virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags );
virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags );
AutoContact* doRp_AccessNorthPin ( GCell*, RoutingPad* );
AutoContact* doRp_AccessEastWestPin ( GCell*, RoutingPad* );
private:
virtual bool _do_1G_1M1 ();
virtual bool _do_1G_xM1 ();
virtual bool _do_xG ();
virtual bool _do_2G ();
virtual bool _do_2G_1M1 ();
virtual bool _do_xG_1Pad ();
virtual bool _do_1G_1PinM1 ();
virtual bool _do_2G_1PinM1 ();
virtual bool _do_1G_1PinM2 ();
virtual bool _do_xG_1PinM2 ();
virtual bool _do_1G_1PinM3 ();
virtual bool _do_xG_1PinM3 ();
virtual bool _do_xG_1M1 ();
virtual bool _do_xG_1M1_1M2 ();
virtual bool _do_xG_xM1_xM3 ();
virtual bool _do_4G_1M2 ();
virtual bool _do_xG_xM2 ();
virtual bool _do_1G_1M3 ();
virtual bool _do_xG_xM3 ();
virtual bool _do_1G_xM1_1PinM2 ();
virtual bool _do_2G_xM1_1PinM2 ();
virtual bool _do_1G_1M1_1PinM3 ();
virtual bool _do_2G_xM1_1PinM3 ();
virtual bool _do_3G_xM1_1PinM3 ();
virtual bool _do_globalSegment ();
virtual void singleGCell ( AnabaticEngine*, Net* );
public:
virtual string getTypeName () const;
};
} // Anabatic namespace.
#endif // ANABATIC_NET_BUILDER_HV_H

View File

@ -0,0 +1,57 @@
// -*- 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++ Header : "./anabatic/NetBuilderM2.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_NET_BUILDER_M2_H
#define ANABATIC_NET_BUILDER_M2_H
#include "anabatic/NetBuilder.h"
namespace Anabatic {
// -----------------------------------------------------------------
// Class : "NetBuilderM2".
class NetBuilderM2 : public NetBuilder {
public:
NetBuilderM2 ();
virtual ~NetBuilderM2 ();
virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags );
virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags );
private:
virtual bool _do_1G_1M1 ();
virtual bool _do_2G_1M1 ();
virtual bool _do_xG ();
virtual bool _do_globalSegment ();
// Should never occur, so just return false.
virtual bool _do_xG_1Pad ();
virtual bool _do_1G_1PinM2 ();
virtual bool _do_1G_xM1 ();
virtual bool _do_xG_xM2 ();
virtual bool _do_1G_1M3 ();
virtual bool _do_xG_xM3 ();
virtual bool _do_xG_1M1_1M2 ();
virtual bool _do_xG_xM1_xM3 ();
virtual bool _do_4G_1M2 ();
virtual bool _do_2G ();
public:
virtual string getTypeName () const;
};
} // Anabatic namespace.
#endif // ANABATIC_NET_BUILDER_M2_H

View File

@ -0,0 +1,54 @@
// -*- 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 |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/NetBuilderVH.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_NET_BUILDER_VH_H
#define ANABATIC_NET_BUILDER_VH_H
#include "anabatic/NetBuilder.h"
namespace Anabatic {
// -----------------------------------------------------------------
// Class : "NetBuilderVH".
class NetBuilderVH : public NetBuilder {
public:
NetBuilderVH ();
virtual ~NetBuilderVH ();
virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags );
virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags );
private:
virtual bool _do_1G_1PinM2 ();
virtual bool _do_xG_1PinM2 ();
virtual bool _do_1G_1PinM3 ();
virtual bool _do_xG_1PinM3 ();
virtual bool _do_1G_1M1 ();
virtual bool _do_1G_xM1 ();
virtual bool _do_2G_1M1 ();
virtual bool _do_xG_xM1_xM3 ();
virtual bool _do_xG ();
virtual bool _do_2G ();
virtual bool _do_globalSegment ();
virtual void singleGCell ( AnabaticEngine*, Net* );
public:
virtual string getTypeName () const;
};
} // Anabatic namespace.
#endif // ANABATIC_NET_BUILDER_VH_H

View File

@ -1,7 +1,7 @@
// -*- mode: C++; explicit-buffer-name: "Session.h<anabatic>" -*-
//
// 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 |
@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_SESSION_H
#define ANABATIC_SESSION_H
#pragma once
#include <string>
#include <vector>
#include <set>
@ -24,6 +22,7 @@
#include <boost/function.hpp>
#include "hurricane/Commons.h"
#include "hurricane/Box.h"
#include "hurricane/DBo.h"
#include "crlcore/CellGauge.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/Constants.h"
@ -55,6 +54,7 @@ namespace Anabatic {
using Hurricane::DbU;
using Hurricane::Point;
using Hurricane::Box;
using Hurricane::DBo;
using Hurricane::Net;
using Hurricane::Contact;
using Hurricane::Segment;
@ -71,99 +71,128 @@ namespace Anabatic {
class Session {
public:
// Static Methods.
static inline bool doDestroyBaseContact ();
static inline bool doDestroyBaseSegment ();
static inline bool doDestroyTool ();
static bool isInDemoMode ();
static bool doWarnGCellOverload ();
static Session* get ( const char* message=NULL );
static inline Technology* getTechnology ();
static inline AnabaticEngine* getAnabatic ();
static inline const Configuration* getConfiguration ();
static float getSaturateRatio ();
static size_t getSaturateRp ();
static inline size_t getAllowedDepth ();
static DbU::Unit getExtensionCap ();
static inline CellGauge* getCellGauge ();
static inline DbU::Unit getSliceHeight ();
static inline DbU::Unit getSliceStep ();
static inline RoutingGauge* getRoutingGauge ();
static inline RoutingLayerGauge* getLayerGauge ( size_t depth );
static inline size_t getDepth ();
static inline size_t getViaDepth ( const Layer* layer );
static inline size_t getLayerDepth ( const Layer* layer );
static inline const Layer* getRoutingLayer ( size_t );
static inline const Layer* getContactLayer ( size_t );
static Flags getDirection ( size_t depth );
static inline DbU::Unit getPitch ( size_t depth, Flags flags );
static inline DbU::Unit getOffset ( size_t depth );
static inline DbU::Unit getWireWidth ( size_t depth );
static inline DbU::Unit getViaWidth ( size_t depth );
static inline Flags getDirection ( const Layer* );
static inline DbU::Unit getPitch ( const Layer*, Flags flags );
static inline DbU::Unit getOffset ( const Layer* );
static inline DbU::Unit getWireWidth ( const Layer* );
static inline DbU::Unit getViaWidth ( const Layer* );
static inline DbU::Unit getExtensionCap ( const Layer* );
static inline Point getNearestGridPoint ( Point, Box constraints );
static inline size_t getSegmentStackSize ();
static inline size_t getContactStackSize ();
static inline const vector<AutoSegment*>& getInvalidateds ();
static inline const vector<AutoSegment*>& getRevalidateds ();
static inline const set<AutoSegment*>& getDestroyeds ();
static inline const vector<AutoSegment*>& getDoglegs ();
static inline const set<Net*>& getNetsModificateds ();
static void close ();
static void setAnabaticFlags ( Flags );
static inline void dogleg ( AutoSegment* );
static inline void doglegReset ();
static inline void revalidateTopology ();
static inline void setInvalidateMask ( Flags );
static inline void invalidate ( Net* );
static inline void invalidate ( AutoContact* );
static inline void invalidate ( AutoSegment* );
static inline size_t revalidate ();
static void link ( AutoContact* );
static void link ( AutoSegment* );
static void unlink ( AutoContact* );
static void unlink ( AutoSegment* );
static AutoContact* lookup ( Contact* );
static AutoSegment* lookup ( Segment* );
static inline void destroyRequest ( AutoSegment* );
static inline bool isOpen ();
static inline bool doDestroyBaseContact ();
static inline bool doDestroyBaseSegment ();
static inline bool doDestroyTool ();
static bool isInDemoMode ();
static bool doWarnGCellOverload ();
static Session* get ( const char* message=NULL );
static inline Technology* getTechnology ();
static inline AnabaticEngine* getAnabatic ();
static inline const Configuration* getConfiguration ();
static float getSaturateRatio ();
static size_t getSaturateRp ();
static inline size_t getAllowedDepth ();
static DbU::Unit getExtensionCap ();
static inline CellGauge* getCellGauge ();
static inline DbU::Unit getSliceHeight ();
static inline DbU::Unit getSliceStep ();
static inline size_t getGVerticalDepth ();
static inline size_t getGHorizontalDepth ();
static inline DbU::Unit getGHorizontalPitch ();
static inline DbU::Unit getGVerticalPitch ();
static inline size_t getDVerticalDepth ();
static inline const Layer* getDVerticalLayer ();
static inline DbU::Unit getDVerticalWidth ();
static inline DbU::Unit getDPVerticalWidth ();
static inline DbU::Unit getDVerticalPitch ();
static inline DbU::Unit getDVerticalOffset ();
static inline size_t getDHorizontalDepth ();
static inline const Layer* getDHorizontalLayer ();
static inline DbU::Unit getDHorizontalWidth ();
static inline DbU::Unit getDPHorizontalWidth ();
static inline DbU::Unit getDHorizontalPitch ();
static inline DbU::Unit getDHorizontalOffset ();
static inline size_t getDContactDepth ();
static inline const Layer* getDContactLayer ();
static inline DbU::Unit getDContactWidth ();
static inline DbU::Unit getDContactPitch ();
static inline RoutingGauge* getRoutingGauge ();
static inline bool isGLayer ( const Layer* );
static inline bool isGMetal ( const Layer* );
static inline bool isGContact ( const Layer* );
static inline bool isGaugeLayer ( const Layer* );
static inline RoutingLayerGauge* getLayerGauge ( const Layer* );
static inline RoutingLayerGauge* getLayerGauge ( size_t depth );
static inline size_t getDepth ();
static inline size_t getViaDepth ( const Layer* layer );
static inline size_t getLayerDepth ( const Layer* layer );
static inline const Layer* getRoutingLayer ( size_t );
static inline const Layer* getContactLayer ( size_t );
static Flags getDirection ( size_t depth );
static inline DbU::Unit getPitch ( size_t depth, Flags flags );
static inline DbU::Unit getOffset ( size_t depth );
static inline DbU::Unit getWireWidth ( size_t depth );
static inline DbU::Unit getPWireWidth ( size_t depth );
static inline DbU::Unit getViaWidth ( size_t depth );
static inline Flags getDirection ( const Layer* );
static inline DbU::Unit getPitch ( const Layer*, Flags flags );
static inline DbU::Unit getOffset ( const Layer* );
static inline DbU::Unit getWireWidth ( const Layer* );
static inline DbU::Unit getViaWidth ( const Layer* );
static inline DbU::Unit getExtensionCap ( const Layer* );
static inline DbU::Unit getNearestTrackAxis ( const Layer*, DbU::Unit, uint32_t mode );
static inline Point getNearestGridPoint ( Point, Box constraints );
static inline size_t getSegmentStackSize ();
static inline size_t getContactStackSize ();
static inline const vector<AutoSegment*>& getInvalidateds ();
static inline const vector<AutoSegment*>& getRevalidateds ();
static inline const set<AutoSegment*>& getDestroyeds ();
static inline const vector<AutoSegment*>& getDoglegs ();
static inline const set<Net*,DBo::CompareById>& getNetsModificateds ();
static void close ();
static void setAnabaticFlags ( Flags );
static inline void dogleg ( AutoSegment* );
static inline void doglegReset ();
static inline void revalidateTopology ();
static inline void setInvalidateMask ( Flags );
static inline void invalidate ( Net* );
static inline void invalidate ( AutoContact* );
static inline void invalidate ( AutoSegment* );
static inline size_t revalidate ();
static void link ( AutoContact* );
static void link ( AutoSegment* );
static void unlink ( AutoContact* );
static void unlink ( AutoSegment* );
static AutoContact* lookup ( Contact* );
static AutoSegment* lookup ( Segment* );
static inline void destroyRequest ( AutoSegment* );
// Methods.
static Session* _open ( AnabaticEngine* );
bool _doDestroyBaseContact ();
bool _doDestroyBaseSegment ();
bool _doDestroyTool ();
virtual Configuration* _getConfiguration ();
inline void _dogleg ( AutoSegment* );
inline void _doglegReset ();
void _invalidate ( Net* );
inline void _invalidate ( AutoContact* );
inline void _invalidate ( AutoSegment* );
inline void _destroyRequest ( AutoSegment* );
void _canonize ();
void _revalidateTopology ();
virtual size_t _revalidate ();
DbU::Unit _getPitch ( size_t depth, Flags flags ) const;
Point _getNearestGridPoint ( Point, Box constraints );
Record* _getRecord () const;
string _getString () const;
inline string _getTypeName () const;
static Session* _open ( AnabaticEngine* );
bool _doDestroyBaseContact ();
bool _doDestroyBaseSegment ();
bool _doDestroyTool ();
virtual Configuration* _getConfiguration ();
inline void _dogleg ( AutoSegment* );
inline void _doglegReset ();
void _invalidate ( Net* );
inline void _invalidate ( AutoContact* );
inline void _invalidate ( AutoSegment* );
inline void _destroyRequest ( AutoSegment* );
void _canonize ();
void _revalidateTopology ();
virtual size_t _revalidate ();
DbU::Unit _getPitch ( size_t depth, Flags flags ) const;
DbU::Unit _getNearestTrackAxis ( const Layer*, DbU::Unit, uint32_t mode );
Point _getNearestGridPoint ( Point, Box constraints );
Record* _getRecord () const;
string _getString () const;
inline string _getTypeName () const;
protected:
static Session* _session;
AnabaticEngine* _anabatic;
Technology* _technology;
CellGauge* _cellGauge;
RoutingGauge* _routingGauge;
vector<AutoContact*> _autoContacts;
vector<AutoSegment*> _doglegs;
vector<AutoSegment*> _segmentInvalidateds;
vector<AutoSegment*> _segmentRevalidateds;
set<Net*> _netInvalidateds;
set<Net*> _netRevalidateds;
set<AutoSegment*> _destroyedSegments;
static Session* _session;
AnabaticEngine* _anabatic;
Technology* _technology;
CellGauge* _cellGauge;
RoutingGauge* _routingGauge;
vector<AutoContact*> _autoContacts;
vector<AutoSegment*> _doglegs;
vector<AutoSegment*> _segmentInvalidateds;
vector<AutoSegment*> _segmentRevalidateds;
set<Net*,DBo::CompareById> _netInvalidateds;
set<Net*,DBo::CompareById> _netRevalidateds;
set<AutoSegment*> _destroyedSegments;
// Constructors.
protected:
@ -178,64 +207,89 @@ namespace Anabatic {
// Inline Functions.
inline Technology* Session::getTechnology () { return get("getTechnology()")->_technology; }
inline CellGauge* Session::getCellGauge () { return get("getCellGauge()")->_cellGauge; }
inline RoutingGauge* Session::getRoutingGauge () { return get("getRoutingGauge()")->_routingGauge; }
inline bool Session::doDestroyBaseContact () { return get("doDestroyBaseContact()")->_doDestroyBaseContact(); }
inline bool Session::doDestroyBaseSegment () { return get("doDestroyBaseSegment()")->_doDestroyBaseSegment(); }
inline bool Session::doDestroyTool () { return get("doDestroyTool()")->_doDestroyTool(); }
inline const Configuration* Session::getConfiguration () { return get("getConfiguration()")->_getConfiguration(); }
inline AnabaticEngine* Session::getAnabatic () { return get("getAnabatic()")->_anabatic; }
inline void Session::revalidateTopology () { return get("revalidateTopology()")->_revalidateTopology(); }
inline size_t Session::revalidate () { return get("revalidate()")->_revalidate(); }
inline size_t Session::getSegmentStackSize () { return get("getSegmentStackSize()")->_segmentInvalidateds.size(); }
inline size_t Session::getContactStackSize () { return get("getContactStackSize()")->_autoContacts.size(); }
inline const vector<AutoSegment*>& Session::getInvalidateds () { return get("getInvalidateds()")->_segmentInvalidateds; }
inline const vector<AutoSegment*>& Session::getRevalidateds () { return get("getRevalidateds()")->_segmentRevalidateds; }
inline const set<AutoSegment*>& Session::getDestroyeds () { return get("getDestroyeds()")->_destroyedSegments; }
inline const vector<AutoSegment*>& Session::getDoglegs () { return get("getDoglegs()")->_doglegs; }
inline const set<Net*>& Session::getNetsModificateds () { return get("getNetsModificateds()")->_netRevalidateds; }
inline void Session::doglegReset () { return get("doglegReset()")->_doglegReset (); }
inline void Session::invalidate ( Net* net ) { return get("invalidate(Net*)")->_invalidate(net); }
inline void Session::invalidate ( AutoContact* autoContact ) { return get("invalidate(AutoContact*)")->_invalidate(autoContact); }
inline void Session::invalidate ( AutoSegment* autoSegment ) { return get("invalidate(AutoSegment*)")->_invalidate(autoSegment); }
inline void Session::dogleg ( AutoSegment* autoSegment ) { return get("dogleg(AutoSegment*)")->_dogleg(autoSegment); }
inline void Session::destroyRequest ( AutoSegment* autoSegment ) { return get("destroyRequest(AutoSegment*)")->_destroyRequest(autoSegment); }
inline bool Session::isOpen () { return get() != NULL; }
inline Technology* Session::getTechnology () { return get("getTechnology()")->_technology; }
inline CellGauge* Session::getCellGauge () { return get("getCellGauge()")->_cellGauge; }
inline RoutingGauge* Session::getRoutingGauge () { return get("getRoutingGauge()")->_routingGauge; }
inline bool Session::doDestroyBaseContact () { return get("doDestroyBaseContact()")->_doDestroyBaseContact(); }
inline bool Session::doDestroyBaseSegment () { return get("doDestroyBaseSegment()")->_doDestroyBaseSegment(); }
inline bool Session::doDestroyTool () { return get("doDestroyTool()")->_doDestroyTool(); }
inline const Configuration* Session::getConfiguration () { return get("getConfiguration()")->_getConfiguration(); }
inline AnabaticEngine* Session::getAnabatic () { return get("getAnabatic()")->_anabatic; }
inline void Session::revalidateTopology () { return get("revalidateTopology()")->_revalidateTopology(); }
inline size_t Session::revalidate () { return get("revalidate()")->_revalidate(); }
inline size_t Session::getSegmentStackSize () { return get("getSegmentStackSize()")->_segmentInvalidateds.size(); }
inline size_t Session::getContactStackSize () { return get("getContactStackSize()")->_autoContacts.size(); }
inline const vector<AutoSegment*>& Session::getInvalidateds () { return get("getInvalidateds()")->_segmentInvalidateds; }
inline const vector<AutoSegment*>& Session::getRevalidateds () { return get("getRevalidateds()")->_segmentRevalidateds; }
inline const set<AutoSegment*>& Session::getDestroyeds () { return get("getDestroyeds()")->_destroyedSegments; }
inline const vector<AutoSegment*>& Session::getDoglegs () { return get("getDoglegs()")->_doglegs; }
inline const set<Net*,DBo::CompareById>& Session::getNetsModificateds () { return get("getNetsModificateds()")->_netRevalidateds; }
inline void Session::doglegReset () { return get("doglegReset()")->_doglegReset (); }
inline void Session::invalidate ( Net* net ) { return get("invalidate(Net*)")->_invalidate(net); }
inline void Session::invalidate ( AutoContact* autoContact ) { return get("invalidate(AutoContact*)")->_invalidate(autoContact); }
inline void Session::invalidate ( AutoSegment* autoSegment ) { return get("invalidate(AutoSegment*)")->_invalidate(autoSegment); }
inline void Session::dogleg ( AutoSegment* autoSegment ) { return get("dogleg(AutoSegment*)")->_dogleg(autoSegment); }
inline void Session::destroyRequest ( AutoSegment* autoSegment ) { return get("destroyRequest(AutoSegment*)")->_destroyRequest(autoSegment); }
inline size_t Session::getAllowedDepth () { return getConfiguration()->getAllowedDepth(); }
inline size_t Session::getAllowedDepth () { return getConfiguration()->getAllowedDepth(); }
inline DbU::Unit Session::getSliceHeight () { return getCellGauge()->getSliceHeight(); }
inline DbU::Unit Session::getSliceStep () { return getCellGauge()->getSliceStep(); }
inline RoutingLayerGauge* Session::getLayerGauge ( size_t depth ) { return getRoutingGauge()->getLayerGauge(depth); }
inline size_t Session::getDepth () { return getRoutingGauge()->getDepth(); }
inline size_t Session::getViaDepth ( const Layer* layer ) { return getRoutingGauge()->getViaDepth(layer); }
inline size_t Session::getLayerDepth ( const Layer* layer ) { return getRoutingGauge()->getLayerDepth(layer); }
inline const Layer* Session::getRoutingLayer ( size_t depth ) { return getRoutingGauge()->getRoutingLayer(depth); }
inline const Layer* Session::getContactLayer ( size_t depth ) { return getRoutingGauge()->getContactLayer(depth); }
inline DbU::Unit Session::getPitch ( size_t depth, Flags flags=Flags::NoFlags ) { return get("getPitch(depth,flags)")->_getPitch( depth, flags ); }
inline DbU::Unit Session::getOffset ( size_t depth ) { return getRoutingGauge()->getLayerOffset(depth); }
inline DbU::Unit Session::getWireWidth ( size_t depth ) { return getRoutingGauge()->getLayerWireWidth(depth); }
inline DbU::Unit Session::getViaWidth ( size_t depth ) { return getRoutingGauge()->getViaWidth(depth); }
inline DbU::Unit Session::getPitch ( const Layer* layer, Flags flags=Flags::NoFlags ) { return getPitch( getLayerDepth(layer), flags ); }
inline DbU::Unit Session::getOffset ( const Layer* layer ) { return getOffset ( getLayerDepth(layer) ); }
inline DbU::Unit Session::getWireWidth ( const Layer* layer ) { return getWireWidth( getLayerDepth(layer) ); }
inline DbU::Unit Session::getViaWidth ( const Layer* layer ) { return getViaWidth ( getViaDepth(layer) ); }
inline DbU::Unit Session::getExtensionCap ( const Layer* layer ) { return getConfiguration()->getExtensionCap(layer); }
inline Flags Session::getDirection ( const Layer* layer ) { return getDirection( getLayerDepth(layer) ); }
inline Point Session::getNearestGridPoint ( Point p, Box b ) { return get("getNearestGridPoint()")->_getNearestGridPoint(p,b); }
inline DbU::Unit Session::getSliceHeight () { return getCellGauge()->getSliceHeight(); }
inline DbU::Unit Session::getSliceStep () { return getCellGauge()->getSliceStep(); }
inline size_t Session::getGVerticalDepth () { return getConfiguration()->getGVerticalDepth(); }
inline size_t Session::getGHorizontalDepth () { return getConfiguration()->getGHorizontalDepth(); }
inline DbU::Unit Session::getGVerticalPitch () { return getConfiguration()->getGVerticalPitch(); }
inline DbU::Unit Session::getGHorizontalPitch () { return getConfiguration()->getGHorizontalPitch(); }
inline size_t Session::getDVerticalDepth () { return getConfiguration()->getDVerticalDepth(); }
inline const Layer* Session::getDVerticalLayer () { return getConfiguration()->getDVerticalLayer(); }
inline DbU::Unit Session::getDVerticalWidth () { return getConfiguration()->getDVerticalWidth(); }
inline DbU::Unit Session::getDPVerticalWidth () { return getConfiguration()->getDPVerticalWidth(); }
inline DbU::Unit Session::getDVerticalPitch () { return getConfiguration()->getDVerticalPitch(); }
inline DbU::Unit Session::getDVerticalOffset () { return getConfiguration()->getDVerticalOffset(); }
inline size_t Session::getDHorizontalDepth () { return getConfiguration()->getDHorizontalDepth(); }
inline const Layer* Session::getDHorizontalLayer () { return getConfiguration()->getDHorizontalLayer(); }
inline DbU::Unit Session::getDHorizontalWidth () { return getConfiguration()->getDHorizontalWidth(); }
inline DbU::Unit Session::getDPHorizontalWidth () { return getConfiguration()->getDPHorizontalWidth(); }
inline DbU::Unit Session::getDHorizontalPitch () { return getConfiguration()->getDHorizontalPitch(); }
inline DbU::Unit Session::getDHorizontalOffset () { return getConfiguration()->getDHorizontalOffset(); }
inline size_t Session::getDContactDepth () { return getConfiguration()->getDContactDepth(); }
inline const Layer* Session::getDContactLayer () { return getConfiguration()->getDContactLayer(); }
inline DbU::Unit Session::getDContactWidth () { return getConfiguration()->getDContactWidth(); }
inline DbU::Unit Session::getDContactPitch () { return getConfiguration()->getDContactPitch(); }
inline bool Session::isGLayer ( const Layer* layer ) { return getConfiguration()->isGLayer(layer); }
inline bool Session::isGMetal ( const Layer* layer ) { return getConfiguration()->isGMetal(layer); }
inline bool Session::isGContact ( const Layer* layer ) { return getConfiguration()->isGContact(layer); }
inline bool Session::isGaugeLayer ( const Layer* layer ) { return getRoutingGauge()->hasLayer(layer); }
inline RoutingLayerGauge* Session::getLayerGauge ( const Layer* layer ) { return getRoutingGauge()->getLayerGauge(layer); }
inline RoutingLayerGauge* Session::getLayerGauge ( size_t depth ) { return getRoutingGauge()->getLayerGauge(depth); }
inline size_t Session::getDepth () { return getRoutingGauge()->getDepth(); }
inline size_t Session::getViaDepth ( const Layer* layer ) { return getRoutingGauge()->getViaDepth(layer); }
inline size_t Session::getLayerDepth ( const Layer* layer ) { return getRoutingGauge()->getLayerDepth(layer); }
inline const Layer* Session::getRoutingLayer ( size_t depth ) { return getRoutingGauge()->getRoutingLayer(depth); }
inline const Layer* Session::getContactLayer ( size_t depth ) { return getRoutingGauge()->getContactLayer(depth); }
inline DbU::Unit Session::getPitch ( size_t depth, Flags flags=Flags::NoFlags ) { return get("getPitch(depth,flags)")->_getPitch( depth, flags ); }
inline DbU::Unit Session::getOffset ( size_t depth ) { return getRoutingGauge()->getLayerOffset(depth); }
inline DbU::Unit Session::getWireWidth ( size_t depth ) { return getRoutingGauge()->getLayerWireWidth(depth); }
inline DbU::Unit Session::getPWireWidth ( size_t depth ) { return getRoutingGauge()->getLayerPWireWidth(depth); }
inline DbU::Unit Session::getViaWidth ( size_t depth ) { return getRoutingGauge()->getViaWidth(depth); }
inline DbU::Unit Session::getPitch ( const Layer* layer, Flags flags=Flags::NoFlags ) { return getPitch( getLayerDepth(layer), flags ); }
inline DbU::Unit Session::getOffset ( const Layer* layer ) { return getOffset ( getLayerDepth(layer) ); }
inline DbU::Unit Session::getWireWidth ( const Layer* layer ) { return getWireWidth( getLayerDepth(layer) ); }
inline DbU::Unit Session::getViaWidth ( const Layer* layer ) { return getViaWidth ( getViaDepth(layer) ); }
inline DbU::Unit Session::getExtensionCap ( const Layer* layer ) { return getConfiguration()->getExtensionCap(layer); }
inline Flags Session::getDirection ( const Layer* layer ) { return getDirection( getLayerDepth(layer) ); }
inline Point Session::getNearestGridPoint ( Point p, Box b ) { return get("getNearestGridPoint()")->_getNearestGridPoint(p,b); }
inline DbU::Unit Session::getNearestTrackAxis ( const Layer* layer, DbU::Unit axis, uint32_t mode ) { return get("getNearestTrackAxis()")->_getNearestTrackAxis(layer,axis,mode); }
inline void Session::_dogleg ( AutoSegment* segment ) { _doglegs.push_back(segment); }
inline void Session::_doglegReset () { _doglegs.clear(); }
inline void Session::_invalidate ( AutoContact* contact ) { _autoContacts.push_back(contact); }
inline void Session::_invalidate ( AutoSegment* segment ) { _segmentInvalidateds.push_back(segment); }
inline void Session::_destroyRequest ( AutoSegment* segment ) { _destroyedSegments.insert(segment); }
inline string Session::_getTypeName () const { return _TName("Session"); }
inline void Session::_dogleg ( AutoSegment* segment ) { _doglegs.push_back(segment); }
inline void Session::_doglegReset () { _doglegs.clear(); }
inline void Session::_invalidate ( AutoContact* contact ) { _autoContacts.push_back(contact); }
inline void Session::_invalidate ( AutoSegment* segment ) { _segmentInvalidateds.push_back(segment); }
inline void Session::_destroyRequest ( AutoSegment* segment ) { _destroyedSegments.insert(segment); }
inline string Session::_getTypeName () const { return _TName("Session"); }
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::Session);
#endif // ANABATIC_SESSION_H

View File

@ -5,6 +5,8 @@
cmake_minimum_required(VERSION 2.4.0)
set(ignoreVariables "${BUILD_DOC} ${CMAKE_INSTALL_DIR}")
add_subdirectory(cmake_modules)
list(INSERT CMAKE_MODULE_PATH 0 "${Bootstrap_SOURCE_DIR}/cmake_modules/")

View File

@ -38,12 +38,13 @@ build: FORCE
esac; \
case "$${X_SCLS}" in \
*"devtoolset"*) \
cmakeArgs="$${cmakeArgs} -D Boost_NO_SYSTEM_PATHS:STRING=TRUE"; \
BOOST_INCLUDEDIR="/opt/rh/devtoolset-2/root/usr/include"; \
BOOST_LIBRARYDIR="/opt/rh/devtoolset-2/root/usr/lib"; \
export BOOST_INCLUDEDIR BOOST_LIBRARYDIR; \
echo "** Using $${X_SCLS}."; \
;; \
version="`echo $${X_SCLS} | sed 's,devtoolset-,,'`"; \
cmakeArgs="$${cmakeArgs} -D Boost_NO_SYSTEM_PATHS:STRING=TRUE"; \
BOOST_INCLUDEDIR="/opt/rh/devtoolset-$${version}/root/usr/include"; \
BOOST_LIBRARYDIR="/opt/rh/devtoolset-$${version}/root/usr/lib"; \
export BOOST_INCLUDEDIR BOOST_LIBRARYDIR; \
echo "** Using $${X_SCLS}."; \
;; \
esac; \
for tool in $(tools); do \
echo "** Building tool $${tool}"; \

19
bootstrap/allianceInstaller.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/bash
srcDir=${HOME}/coriolis-2.x/src/alliance/alliance/src
commonRoot=${HOME}/coriolis-2.x/Linux.el7_64/Release.Shared
buildDir=${commonRoot}/build
installDir=${commonRoot}/install
export ALLIANCE_TOP=${installDir}
export LD_LIBRARY_PATH=${installDir}/lib:${LD_LIBRARY_PATH}
cd ${srcDir}
# Skip doc generation to avoid pulling TeXLive in docker images.
sed -i 's,dirs="\$newdirs documentation",dirs="$newdirs",' ./autostuff
./autostuff clean
./autostuff
mkdir -p ${buildDir}
cd ${buildDir}
${srcDir}/configure --prefix=${ALLIANCE_TOP} --enable-alc-shared
make -j1 install

View File

@ -13,44 +13,33 @@ projects = [
}
, { 'name' : "coriolis"
, 'tools' : [ "bootstrap"
, "lefdef"
, "coloquinte"
, "vlsisapd"
, "hurricane"
, "crlcore"
#, "nimbus"
#, "metis"
#, "mauka"
, "flute"
, "etesian"
, "anabatic"
, "katana"
, "knik"
, "katabatic"
, "kite"
, "coloquinte"
, "etesian"
, "equinox"
, "solstice"
, "oroshi"
, "bora"
, "karakaze"
, "unicorn"
, "tutorial"
#, "testbench"
#, "ispd"
, "cumulus"
, "stratus1"
, "documentation"
, "unittests"
]
, 'repository': 'ssh://asim-t/users/largo2/git/coriolis.git' }
, { 'name' : "chams"
, 'tools' : [ "hurricaneAMS"
, "amsCore"
, "opSim"
#, "scribe"
, "graph"
, "pharos"
, "isis"
, "horus"
#, "schematic"
, "solver"
, "autoDTR"
]
, 'repository':"ssh://melon-t/users/outil/chams/chams.git" }
]
package = { 'name' : 'coriolis2'

View File

@ -2,7 +2,7 @@
# -*- mode:Python -*-
#
# 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 |

View File

@ -1,7 +1,7 @@
# -*- mode:Python -*-
#
# 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 |
@ -37,7 +37,8 @@ class Builder:
self._clang = False
self._noSystemBoost = False
self._macports = False
self._devtoolset2 = False
self._devtoolset = 0
self._llvmtoolset = 0
self._qt5 = False
self._openmp = False
self._enableShared = "ON"
@ -66,9 +67,11 @@ class Builder:
elif attribute == "macports":
self._macports = value
if value: self._noSystemBoost = True
elif attribute == "devtoolset2":
self._devtoolset2 = value
elif attribute == "devtoolset":
self._devtoolset = value
if value: self._noSystemBoost = True
elif attribute == "llvmtoolset":
self._llvmtoolset = value
elif attribute == "qt5": self._qt5 = value
elif attribute == "openmp": self._openmp = value
elif attribute == "enableDoc": self._enableDoc = value
@ -132,16 +135,24 @@ class Builder:
def _execute ( self, command, error ):
if self._devtoolset2 == True:
print 'Using devtoolset-2 (scl enable devtoolset-2 ...)'
commandAsString = ''
for i in range(len(command)):
if i: commandAsString += ' '
if ' ' in command[i]: commandAsString += '"'+command[i]+'"'
else: commandAsString += command[i]
command = [ 'scl', 'enable', 'devtoolset-2', commandAsString ]
collections = []
if self._devtoolset:
collections.append( 'devtoolset-%d' % self._devtoolset )
print 'Using devtoolset-%(v)d (scl enable devtoolset-%(v)d ...)' % {'v':self._devtoolset}
if self._llvmtoolset:
collections.append( 'llvm-toolset-%d' % self._llvmtoolset )
print 'Using llvm-toolset-%(v)d (scl enable llvm-toolset-%(v)d ...)' % {'v':self._llvmtoolset}
if collections:
commandAsString = ''
for i in range(len(command)):
if i: commandAsString += ' '
if ' ' in command[i]: commandAsString += '"'+command[i]+'"'
else: commandAsString += command[i]
command = [ 'scl', 'enable' ]
command += collections
command.append( commandAsString )
#print command
sys.stdout.flush ()
sys.stderr.flush ()
child = subprocess.Popen ( command, env=self._environment, stdout=None )
@ -174,15 +185,20 @@ class Builder:
command = [ 'cmake' ]
if self._ninja: command += [ "-G", "Ninja" ]
if self._noSystemBoost: command += [ "-D", "Boost_NO_SYSTEM_PATHS:STRING=TRUE" ]
if self._macports: command += [ "-D", "WITH_MACPORTS:STRING=TRUE" ]
if self._noSystemBoost: command += [ "-D", "Boost_NO_SYSTEM_PATHS:STRING=TRUE"
#, "-D", "BOOST_INCLUDEDIR:STRING=/usr/include/boost169"
#, "-D", "BOOST_LIBRARYDIR:STRING=/usr/lib64/boost169"
]
if self._qt5: command += [ "-D", "WITH_QT5:STRING=TRUE" ]
if self._openmp: command += [ "-D", "WITH_OPENMP:STRING=TRUE" ]
command += [ "-D", "CMAKE_BUILD_TYPE:STRING=%s" % self.buildMode
, "-D", "BUILD_SHARED_LIBS:STRING=%s" % self.enableShared
#, "-D", "BUILD_SHARED_LIBS:STRING=%s" % self.enableShared
, "-D", "CMAKE_INSTALL_PREFIX:STRING=%s" % self.installDir
, "-D", "CMAKE_INSTALL_DIR:STRING=%s" % cmakeInstallDir
#, "-D", "CMAKE_MODULE_PATH:STRING=%s" % cmakeModules
#, "-D", "CMAKE_MODULE_PATH:STRING=%s" % cmakeModules
#, "-D", "Boost_DEBUG:STRING=TRUE"
, toolSourceDir ]
if not os.path.isdir(toolBuildDir):
@ -197,14 +213,13 @@ class Builder:
if os.path.isfile ( cmakeCache ): os.unlink ( cmakeCache )
command += [ "-D", "BUILD_DOC:STRING=%s" % self._enableDoc
, "-D", "CHECK_DATABASE:STRING=%s" % self._checkDatabase
, "-D", "CHECK_DETERMINISM:STRING=%s" % self._checkDeterminism
, "-D", "CMAKE_VERBOSE_MAKEFILE:STRING=%s" % self._verboseMakefile
, "-D", "CMAKE_INSTALL_PREFIX:STRING=%s" % self.installDir
, "-D", "CMAKE_INSTALL_DIR:STRING=%s" % cmakeInstallDir
]
if self.libSuffix:
command += [ "-D", "LIB_SUFFIX:STRING=%s" % self.libSuffix ]
if self.libSuffix: command += [ "-D", "LIB_SUFFIX:STRING=%s" % self.libSuffix ]
if self._checkDatabase == 'ON': command += [ "-D", "CHECK_DATABASE:STRING=ON" ]
if self._checkDeterminism == 'ON': command += [ "-D", "CHECK_DETERMINISM:STRING=ON" ]
command += [ toolSourceDir ]
self._execute ( command, "Second CMake failed" )
@ -294,11 +309,11 @@ class Builder:
def _commandTemplate ( self, tools, projects, command ):
if self._clang:
self._environment[ 'CC' ] = '/usr/bin/clang'
self._environment[ 'CXX' ] = '/usr/bin/clang++'
if self._devtoolset2:
self._environment[ 'BOOST_INCLUDEDIR' ] = '/opt/rh/devtoolset-2/root/usr/include'
self._environment[ 'BOOST_LIBRARYDIR' ] = '/opt/rh/devtoolset-2/root/usr/lib'
self._environment[ 'CC' ] = 'clang'
self._environment[ 'CXX' ] = 'clang++'
if self._devtoolset:
self._environment[ 'BOOST_INCLUDEDIR' ] = '/opt/rh/devtoolset-%d/root/usr/include' % self._devtoolset
self._environment[ 'BOOST_LIBRARYDIR' ] = '/opt/rh/devtoolset-%d/root/usr/lib' % self._devtoolset
if self._macports:
self._environment[ 'BOOST_INCLUDEDIR' ] = '/opt/local/include'
self._environment[ 'BOOST_LIBRARYDIR' ] = '/opt/local/lib'
@ -431,8 +446,8 @@ class Builder:
, "--define", "_tmppath %s" % self.tmppathDir
#, "--define", "_enable_debug_packages 0"
, "--with", "binarytar" ]
if self._devtoolset2 == True:
command += [ "--define", "scl devtoolset-2" ]
if self._devtoolset:
command += [ "--define", "scl devtoolset-%d"%self._devtoolset ]
command += [ "-ba", "--clean", rpmSpecFile ]
self._execute ( command, "Rebuild rpm packages" )

View File

@ -2,7 +2,7 @@
# -*- mode:Python -*-
#
# 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 |

View File

@ -2,7 +2,7 @@
# -*- mode:Python -*-
#
# 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 |
@ -139,14 +139,14 @@ class CompileWidget ( QWidget ):
if self.conf.rootDir: command += [ '--root=%s'%self.conf.rootDir ]
#if self.options.svnUpdate: command += [ '--svn-update' ]
#if self.options.svnStatus: command += [ '--svn-update' ]
if self.options.enableDoc: command += [ '--doc' ]
if self.options.devtoolset2: command += [ '--devtoolset-2' ]
if self.options.qt5: command += [ '--qt5' ]
if self.options.noCache: command += [ '--no-cache' ]
if self.options.rmBuild: command += [ '--rm-build' ]
if self.options.verbose: command += [ '--verbose' ]
#if self.options.svnUpdate: command += [ '--svn-update' ]
#if self.options.svnStatus: command += [ '--svn-update' ]
if self.options.enableDoc: command += [ '--doc' ]
if self.options.devtoolset: command += [ '--devtoolset-8' ]
if self.options.qt5: command += [ '--qt5' ]
if self.options.noCache: command += [ '--no-cache' ]
if self.options.rmBuild: command += [ '--rm-build' ]
if self.options.verbose: command += [ '--verbose' ]
if self.options.make:
makeArguments='install '+self.options.threads
command += [ '--make=%s'%makeArguments ]

View File

@ -2,7 +2,7 @@
# -*- mode:Python -*-
#
# 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 |

View File

@ -2,7 +2,7 @@
# -*- mode:Python -*-
#
# 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 |

View File

@ -2,7 +2,7 @@
# -*- mode:Python -*-
#
# 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 |

View File

@ -2,7 +2,7 @@
# -*- mode:Python -*-
#
# 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 |
@ -65,7 +65,7 @@ class OptionsWidget ( QWidget ):
#self._svnStatus = QCheckBox( 'SVN Status' )
self._make = QCheckBox( 'Build' )
self._enableDoc = QCheckBox( 'Build Documentation' )
self._devtoolset2 = QCheckBox( 'Build with devtoolset 2' )
self._devtoolset = QCheckBox( 'Build with devtoolset 8' )
self._qt5 = QCheckBox( 'Build with Qt 5 (Qt 4 default)' )
self._noCache = QCheckBox( 'Remove previous CMake cache' )
self._rmBuild = QCheckBox( 'Cleanup Build Directory' )
@ -91,7 +91,7 @@ class OptionsWidget ( QWidget ):
vLayout = QVBoxLayout()
vLayout.addWidget( self._buildMode )
vLayout.addWidget( self._enableDoc )
vLayout.addWidget( self._devtoolset2 )
vLayout.addWidget( self._devtoolset )
vLayout.addWidget( self._qt5 )
vLayout.addWidget( self._noCache )
vLayout.addWidget( self._rmBuild )
@ -130,7 +130,7 @@ class OptionsWidget ( QWidget ):
#def _getSvnStatus ( self ): return self._svnStatus.isChecked()
def _getMake ( self ): return self._make.isChecked()
def _getEnableDoc ( self ): return self._enableDoc.isChecked()
def _getDevtoolset2 ( self ): return self._devtoolset2.isChecked()
def _getDevtoolset ( self ): return self._devtoolset.isChecked()
def _getQt5 ( self ): return self._qt5.isChecked()
def _getNoCache ( self ): return self._noCache.isChecked()
def _getRmBuild ( self ): return self._rmBuild.isChecked()
@ -143,7 +143,7 @@ class OptionsWidget ( QWidget ):
#svnStatus = property( _getSvnStatus )
make = property( _getMake )
enableDoc = property( _getEnableDoc )
devtoolset2 = property( _getDevtoolset2 )
devtoolset = property( _getDevtoolset )
qt5 = property( _getQt5 )
noCache = property( _getNoCache )
rmBuild = property( _getRmBuild )
@ -156,7 +156,7 @@ class OptionsWidget ( QWidget ):
#self._svnStatus .setChecked( settings.value('builder/svnStatus').toBool() )
self._make .setChecked( settings.value('builder/make' ).toBool() )
self._enableDoc .setChecked( settings.value('builder/enableDoc').toBool() )
self._devtoolset2.setChecked( settings.value('builder/devtoolset2').toBool() )
self._devtoolset .setChecked( settings.value('builder/devtoolset').toBool() )
self._qt5 .setChecked( settings.value('builder/qt5').toBool() )
self._noCache .setChecked( settings.value('builder/noCache' ).toBool() )
self._rmBuild .setChecked( settings.value('builder/rmBuild' ).toBool() )
@ -176,17 +176,17 @@ class OptionsWidget ( QWidget ):
def saveSettings ( self ):
settings = QSettings()
#settings.setValue('builder/svnUpdate' , self._svnUpdate .isChecked() )
#settings.setValue('builder/svnStatus' , self._svnStatus .isChecked() )
settings.setValue('builder/make' , self._make .isChecked() )
settings.setValue('builder/enableDoc' , self._enableDoc .isChecked() )
settings.setValue('builder/devtoolset2', self._devtoolset2.isChecked() )
settings.setValue('builder/qt5' , self._qt5 .isChecked() )
settings.setValue('builder/buildMode' , self._buildMode .currentText() )
settings.setValue('builder/noCache' , self._noCache .isChecked() )
settings.setValue('builder/rmBuild' , self._rmBuild .isChecked() )
settings.setValue('builder/verbose' , self._verbose .isChecked() )
settings.setValue('builder/threads' , self._threads .currentText() )
#settings.setValue('builder/svnUpdate' , self._svnUpdate .isChecked() )
#settings.setValue('builder/svnStatus' , self._svnStatus .isChecked() )
settings.setValue('builder/make' , self._make .isChecked() )
settings.setValue('builder/enableDoc' , self._enableDoc .isChecked() )
settings.setValue('builder/devtoolset', self._devtoolset.isChecked() )
settings.setValue('builder/qt5' , self._qt5 .isChecked() )
settings.setValue('builder/buildMode' , self._buildMode .currentText() )
settings.setValue('builder/noCache' , self._noCache .isChecked() )
settings.setValue('builder/rmBuild' , self._rmBuild .isChecked() )
settings.setValue('builder/verbose' , self._verbose .isChecked() )
settings.setValue('builder/threads' , self._threads .currentText() )
for project in self._projects: project.saveToSettings()
return

View File

@ -2,7 +2,7 @@
# -*- mode:Python -*-
#
# 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 |

View File

@ -2,7 +2,7 @@
# -*- mode:Python -*-
#
# 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 |

View File

@ -2,7 +2,7 @@
# -*- mode:Python -*-
#
# 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 |

View File

@ -3,7 +3,7 @@
# -*- mode:Python -*-
#
# 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 |
@ -159,12 +159,8 @@ def autoLocate ():
locations = [ os.path.abspath(os.path.dirname(sys.argv[0]))
, os.environ['HOME']+'/coriolis-2.x/src/coriolis/bootstrap'
, os.environ['HOME']+'/coriolis/src/coriolis/bootstrap'
, os.environ['HOME']+'/chams-1.x/src/coriolis/bootstrap'
, os.environ['HOME']+'/chams/src/coriolis/bootstrap'
, '/users/outil/coriolis/coriolis-2.x/src/coriolis/bootstrap'
, os.environ['HOME']+'/coriolis-2.x/'+osType+'/Release.Shared/install/'+libDir+'/'+sitePackage
, os.environ['HOME']+'/chams-1.x/'+osType+'/Release.Shared/install/'+libDir+'/'+sitePackage
, os.environ['HOME']+'/chams/'+osType+'/Release.Shared/install/'+libDir+'/'+sitePackage
, '/users/outil/coriolis/coriolis-2.x/'+osType+'/Release.Shared/install/'+libDir+'/'+sitePackage
]
@ -212,7 +208,8 @@ parser.add_option ( "--no-build" , action="store_true" ,
parser.add_option ( "--no-cache" , action="store_true" , dest="noCache" , help="Remove previous CMake cache before building." )
parser.add_option ( "--rm-build" , action="store_true" , dest="rmBuild" , help="Remove previous build directoty before building." )
parser.add_option ( "--macports" , action="store_true" , dest="macports" , help="Build against MacPorts." )
parser.add_option ( "--devtoolset-2" , action="store_true" , dest="devtoolset2" , help="Build against TUV Dev Toolset 2." )
parser.add_option ( "--devtoolset" , action="store" , type="int" , dest="devtoolset" , help="Build against TUV Dev Toolset N." )
parser.add_option ( "--llvm-toolset" , action="store" , type="int" , dest="llvmtoolset" , help="Build against TUV Dev LLVM Toolset N." )
parser.add_option ( "--qt5" , action="store_true" , dest="qt5" , help="Build against Qt 5 (default: Qt 4)." )
parser.add_option ( "--openmp" , action="store_true" , dest="openmp" , help="Enable the use of OpenMP in Gcc." )
parser.add_option ( "--ninja" , action="store_true" , dest="ninja" , help="Use Ninja instead of UNIX Makefile." )
@ -275,27 +272,28 @@ else:
builder.showConfiguration ()
sys.exit(0)
if options.quiet: builder.quiet = True
if options.release: builder.buildMode = "Release"
if options.debug: builder.buildMode = "Debug"
if options.static: builder.enableShared = "OFF"
if options.doc: builder.enableDoc = "ON"
if options.checkDb: builder.checkDatabase = "ON"
if options.checkDeterminism: builder.checkDeterminism = "ON"
if options.verboseMakefile: builder.verboseMakefile = "ON"
if options.rootDir: builder.rootDir = options.rootDir
if options.noBuild: builder.doBuild = False
if options.noCache: builder.noCache = True
if options.rmBuild: builder.rmBuild = True
if options.ninja: builder.ninja = True
if options.clang: builder.clang = True
if options.macports: builder.macports = True
if options.devtoolset2: builder.devtoolset2 = True
if options.qt5: builder.qt5 = True
if options.openmp: builder.openmp = True
if options.makeArguments: builder.makeArguments = options.makeArguments
#if options.svnMethod: builder.svnMethod = options.svnMethod
#if options.svnTag: builder.svnTag = options.svnTag
if options.quiet: builder.quiet = True
if options.release: builder.buildMode = "Release"
if options.debug: builder.buildMode = "Debug"
if options.static: builder.enableShared = "OFF"
if options.doc: builder.enableDoc = "ON"
if options.checkDb: builder.checkDatabase = "ON"
if options.checkDeterminism: builder.checkDeterminism = "ON"
if options.verboseMakefile: builder.verboseMakefile = "ON"
if options.rootDir: builder.rootDir = options.rootDir
if options.noBuild: builder.doBuild = False
if options.noCache: builder.noCache = True
if options.rmBuild: builder.rmBuild = True
if options.ninja: builder.ninja = True
if options.clang or options.llvmtoolset: builder.clang = True
if options.macports: builder.macports = True
if options.devtoolset: builder.devtoolset = options.devtoolset
if options.llvmtoolset: builder.llvmtoolset = options.llvmtoolset
if options.qt5: builder.qt5 = True
if options.openmp: builder.openmp = True
if options.makeArguments: builder.makeArguments = options.makeArguments
#if options.svnMethod: builder.svnMethod = options.svnMethod
#if options.svnTag: builder.svnTag = options.svnTag
#if options.svnStatus: builder.svnStatus ( tools=options.tools, projects=options.projects )
#elif options.svnUpdate: builder.svnUpdate ( tools=options.tools, projects=options.projects )

View File

@ -8,6 +8,7 @@
FindLibbfd.cmake
FindQwt.cmake
FindSphinx.cmake
FindPelican.cmake
GetGitRevisionDescription.cmake
GetGitRevisionDescription.cmake.in
)

View File

@ -39,6 +39,15 @@
message("-- Distribution is ${DISTRIBUTION}")
endmacro(check_distribution)
#
# Specific setup for MacOS X.
#
if(WITH_MACPORTS)
set(Boost_PYVER "27")
else()
set(Boost_PYVER "")
endif()
#
# Get the svn revision version and configure a svn.h.in file based on this version
# The include directory name is passed as argument
@ -75,6 +84,7 @@
#
# Adds -Wall to the C/C++ flags.
#
set(BUILD_SHARED_LIBS "ON")
#set(DEBUG_FLAGS "-g -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC")
set(DEBUG_FLAGS "-g")
if(CYGWIN)
@ -84,10 +94,14 @@
set(ADDTIONAL_FLAGS "")
set(CXX_STANDARD "c++11")
endif()
set(CMAKE_C_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE)
set(CMAKE_C_FLAGS_RELEASE "-std=${CXX_STANDARD} -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C Compiler Release options." FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C++ Compiler Debug options." FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "-std=${CXX_STANDARD} -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C++ Compiler Release options." FORCE)
set(CMAKE_C_FLAGS_DEBUG " -Wall -fsanitize=address ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE)
#set(CMAKE_C_FLAGS_DEBUG " -Wall ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE)
set(CMAKE_C_FLAGS_RELEASE " -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C Compiler Release options." FORCE)
#set(CMAKE_C_FLAGS_RELEASE " -Wall -fsanitize=address ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C Compiler Release options." FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall -fsanitize=address ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C++ Compiler Debug options." FORCE)
#set(CMAKE_CXX_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C++ Compiler Debug options." FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "-std=${CXX_STANDARD} -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C++ Compiler Release options." FORCE)
#set(CMAKE_CXX_FLAGS_RELEASE "-std=${CXX_STANDARD} -Wall -fsanitize=address ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C++ Compiler Release options." FORCE)
#
@ -174,35 +188,22 @@
endmacro(hurricane_check_libraries)
#
# Perform some tweaks on shared/static linking.
#
macro(set_lib_link_mode)
if(NOT BUILD_SHARED_LIBS)
# check for qmake
find_program(QT_QMAKE_EXECUTABLE NAMES qmake-qt4 qmake PATHS
/opt/qt4-static-4.3.2/bin
NO_DEFAULT_PATH
)
message(STATUS "Building static libraries.")
else(NOT BUILD_SHARED_LIBS)
message(STATUS "Building dynamic libraries.")
endif(NOT BUILD_SHARED_LIBS)
endmacro(set_lib_link_mode)
#
# Find Boost, checking different versions.
#
macro(setup_boost)
#set(Boost_USE_STATIC_LIBS ON)
#message(STATUS "Always uses Boost static libraries.")
if(ARGC LESS 1)
find_package(Boost 1.33.1 REQUIRED)
find_package(Boost 1.35.0 REQUIRED)
else(ARGC LESS 1)
find_package(Boost 1.35.0 COMPONENTS ${ARGV} system)
foreach(component ${ARGV})
if(${component} STREQUAL "python")
set(component ${component}${Boost_PYVER})
endif()
set(components ${components} ${component})
endforeach()
find_package(Boost 1.35.0 COMPONENTS ${components} system)
if(NOT Boost_FOUND)
find_package(Boost 1.33.1 COMPONENTS ${ARGV} REQUIRED)
find_package(Boost 1.35.0 COMPONENTS ${components} REQUIRED)
endif(NOT Boost_FOUND)
endif(ARGC LESS 1)
message(STATUS "Found Boost includes ${Boost_LIB_VERSION} in ${Boost_INCLUDE_DIR}")
@ -276,15 +277,20 @@
PATHS /usr/include/qt5
/usr/include
PATH_SUFFIXES qwt )
find_library(QWT_LIBRARY NAMES qwt-qt5
PATHS /usr/lib${LIB_SUFFIX} )
find_library(QWT_LIBRARY NAMES qwt-qt5 qwt
PATHS /usr/lib64
/usr/lib )
else()
find_path(QWT_INCLUDE_DIR NAMES qwt.h
PATHS /usr/include
PATHS /usr/include/qwt-qt4
/opt/local/libexec/qt4/include
/usr/include/qt4
/usr/include
PATH_SUFFIXES qwt )
find_library(QWT_LIBRARY NAMES qwt
PATHS /usr/lib${LIB_SUFFIX} )
find_library(QWT_LIBRARY NAMES qwt-qt4 qwt
PATHS /opt/local/libexec/qt4/lib
/usr/lib64
/usr/lib )
endif()
if( QWT_INCLUDE_DIR AND QWT_LIBRARY)
@ -310,10 +316,10 @@
#
macro(setup_sysconfdir INSTALLDIR)
message("-- Checking installation directory <${INSTALLDIR}>")
string(REGEX MATCH "^/opt/rh/devtoolset-2/root/usr$" IS_OPT_RH ${INSTALLDIR})
string(REGEX MATCH "^/opt/rh/devtoolset-[0-9]+/root" IS_OPT_RH ${INSTALLDIR})
if(IS_OPT_RH)
message("-- Using devtoolset-2 install tree /opt/rh/devtoolset-2/root/etc.")
set(SYS_CONF_DIR "/opt/rh/devtoolset-2/root/etc" CACHE STRING "System configuration directory (/etc)" FORCE)
message("-- Using devtoolset-X install tree ${IS_OPT_RH}/etc.")
set(SYS_CONF_DIR ${IS_OPT_RH} CACHE STRING "System configuration directory (/etc)" FORCE)
else()
string(REGEX MATCH "^/usr$" IS_USR ${INSTALLDIR})
string(REGEX MATCH "^/opt$" IS_OPT ${INSTALLDIR})
@ -413,5 +419,7 @@
target_link_libraries( ${pytarget} ${pyDeplibs} )
install( TARGETS ${pytarget} DESTINATION ${PYTHON_SITE_PACKAGES} )
if( NOT ("${pyIncludes}" STREQUAL "None") )
install( FILES ${pyIncludes} DESTINATION ${inc_install_dir} )
endif()
endmacro( add_python_module )

View File

@ -63,7 +63,7 @@ FIND_PROGRAM(FLEX_EXECUTABLE flex DOC "path to the flex executable")
MARK_AS_ADVANCED(FLEX_EXECUTABLE)
FIND_LIBRARY(FL_LIBRARY NAMES fl
PATHS /usr/lib${LIB_SUFFIX} DOC "path to the fl library")
PATHS /usr/lib64 lib DOC "path to the fl library")
SET(FLEX_LIBRARIES ${FL_LIBRARY})
IF(FLEX_EXECUTABLE)

View File

@ -7,124 +7,121 @@
#
# The DEF C API library: LEFDEF_CDEF_LIBRARY
# LEFDEF_CDEF_LIBRARY_RELEASE
# LEFDEF_CDEF_LIBRARY_DEBUG
#
# The DEF C API library (zlib) : LEFDEF_ZCDEF_LIBRARY
# LEFDEF_ZCDEF_LIBRARY_RELEASE
# LEFDEF_ZCDEF_LIBRARY_DEBUG
#
# The DEF C++ API library: LEFDEF_DEF_LIBRARY
# LEFDEF_DEF_LIBRARY_RELEASE
# LEFDEF_DEF_LIBRARY_DEBUG
#
# The DEF C++ API library (zlib) : LEFDEF_ZDEF_LIBRARY
# LEFDEF_ZDEF_LIBRARY_RELEASE
# LEFDEF_ZDEF_LIBRARY_DEBUG
#
# The LEF C API library: LEFDEF_CLEF_LIBRARY
# LEFDEF_CLEF_LIBRARY_RELEASE
# LEFDEF_CLEF_LIBRARY_DEBUG
#
# The LEF C API library (zlib) : LEFDEF_ZCLEF_LIBRARY
# LEFDEF_ZCLEF_LIBRARY_RELEASE
# LEFDEF_ZCLEF_LIBRARY_DEBUG
#
# The LEF C++ API library: LEFDEF_LEF_LIBRARY
# LEFDEF_LEF_LIBRARY_RELEASE
# LEFDEF_LEF_LIBRARY_DEBUG
#
# The LEF C++ API library (zlib) : LEFDEF_ZLEF_LIBRARY
# LEFDEF_ZLEF_LIBRARY_RELEASE
# LEFDEF_ZLEF_LIBRARY_DEBUG
# Try to find a reasonable CORIOLIS_TOP value.
if( NOT("$ENV{CORIOLIS_USER_TOP}" STREQUAL "") )
set ( CORIOLIS_USER_TOP "$ENV{CORIOLIS_USER_TOP}" )
else( NOT("$ENV{CORIOLIS_USER_TOP}" STREQUAL "") )
if( NOT("$ENV{CORIOLIS_TOP}" STREQUAL "") )
set ( CORIOLIS_TOP "$ENV{CORIOLIS_TOP}" )
endif( NOT("$ENV{CORIOLIS_TOP}" STREQUAL "") )
endif( NOT("$ENV{CORIOLIS_USER_TOP}" STREQUAL "") )
macro( _find_lefdef_lib varname libname )
find_library( LEFDEF_${varname}_LIBRARY_RELEASE NAMES ${libname} PATHS ${LEFDEF_LIBRARY_DIR} )
find_library( LEFDEF_${varname}_LIBRARY_DEBUG NAMES ${libname}_Debug PATHS ${LEFDEF_LIBRARY_DIR} )
macro( _find_lefdef_lib varname libname )
find_library( LEFDEF_${varname}_LIBRARY_RELEASE NAMES ${libname} PATHS ${LEFDEF_LIBRARY_DIR} )
if( LEFDEF_${varname}_LIBRARY_RELEASE AND NOT LEFDEF_${varname}_LIBRARY_DEBUG )
set( LEFDEF_${varname}_LIBRARY_DEBUG ${LEFDEF_${varname}_LIBRARY_RELEASE} CACHE STRING "Path to a library" FORCE )
endif()
if( LEFDEF_${varname}_LIBRARY_RELEASE )
set( LEFDEF_${varname}_LIBRARY_DEBUG ${LEFDEF_${varname}_LIBRARY_RELEASE} CACHE STRING "Path to a library" FORCE )
endif()
if( LEFDEF_${varname}_LIBRARY_DEBUG AND NOT LEFDEF_${varname}_LIBRARY_RELEASE )
set( LEFDEF_${varname}_LIBRARY_RELEASE LEFDEF_${varname}_LIBRARY_DEBUG CACHE STRING "Path to a library" FORCE )
endif()
if( LEFDEF_${varname}_LIBRARY_RELEASE )
list( APPEND LEFDEF_LIBRARIES "optimized" ${LEFDEF_${varname}_LIBRARY_RELEASE}
"debug" ${LEFDEF_${varname}_LIBRARY_DEBUG} )
set( LEFDEF_${varname}_LIBRARY_FOUND 1 )
mark_as_advanced( LEFDEF_${varname}_LIBRARY_RELEASE
LEFDEF_${varname}_LIBRARY_DEBUG )
else()
set ( LEFDEF_FOUND "NO" )
endif()
endmacro()
if( LEFDEF_${varname}_LIBRARY_RELEASE )
list( APPEND LEFDEF_LIBRARIES "optimized" ${LEFDEF_${varname}_LIBRARY_RELEASE}
"debug" ${LEFDEF_${varname}_LIBRARY_DEBUG} )
set( LEFDEF_${varname}_LIBRARY_FOUND 1 )
mark_as_advanced( LEFDEF_${varname}_LIBRARY_RELEASE
LEFDEF_${varname}_LIBRARY_DEBUG )
else()
set ( LEFDEF_FOUND "NO" )
endif()
endmacro()
set( LEFDEF_INCLUDE_DIR_DESCRIPTION "directory containing the LEF/DEF include files. E.g /opt/lefdef-5.6/include" )
set( LEFDEF_LIBRARY_DIR_DESCRIPTION "directory containing the LEF/DEF library files. E.g /opt/lefdef-5.6/lib" )
set( LEFDEF_DIR_MESSAGE "Set the LEFDEF_INCLUDE_DIR cmake cache entry to the ${LEFDEF_INCLUDE_DIR_DESCRIPTION}" )
set( LEFDEF_INCLUDE_DIR_DESCRIPTION "directory containing the LEF/DEF include files. E.g /opt/lefdef-5.6/include" )
set( LEFDEF_LIBRARY_DIR_DESCRIPTION "directory containing the LEF/DEF library files. E.g /opt/lefdef-5.6/lib" )
set( LEFDEF_DIR_MESSAGE "Set the LEFDEF_INCLUDE_DIR cmake cache entry to the ${LEFDEF_INCLUDE_DIR_DESCRIPTION}" )
# Don't even bother under Win32
if ( UNIX )
set ( LEFDEF_FOUND "YES" )
set ( LEFDEF_SEARCH_PATH "$ENV{LEFDEF_TOP}"
if( UNIX )
set( LEFDEF_FOUND "YES" )
set( LEFDEF_SEARCH_PATH "$ENV{CORIOLIS_TOP}"
"$ENV{LEFDEF_TOP}"
"/usr"
"/opt/lefdef-5.6"
"/opt/lefdef-5.8"
"/opt/lefdef-5.7"
"/opt/lefdef-5.6"
"/opt/lefdef"
"$ENV{HOME}/oa/lefdef/5.7-s038"
"/soc/oa"
)
message("-- Components of LEFDEF_DIR_SEARCH:")
foreach(PATH ${LEFDEF_DIR_SEARCH})
message("-- ${PATH}")
endforeach(PATH)
message( "-- Components of LEFDEF_DIR_SEARCH:" )
foreach( PATH ${LEFDEF_SEARCH_PATH} )
message( "-- ${PATH}" )
endforeach()
set ( LEFDEF_LIBRARIES "" )
set ( LEFDEF_LIBRARY_SEARCH_PATH "" )
set( LEFDEF_LIBRARIES "" )
set( LEFDEF_LIBRARY_SEARCH_PATH "" )
find_path ( LEFDEF_INCLUDE_DIR NAMES "defiDefs.h"
find_path( LEFDEF_INCLUDE_DIR NAMES "defiDefs.hpp"
PATHS ${LEFDEF_SEARCH_PATH}
PATH_SUFFIXES "include" "include/lefdef"
PATH_SUFFIXES "include/lefdef" "include"
DOC "The ${LEFDEF_INCLUDE_DIR_DESCRIPTION}" )
message( STATUS "LEFDEF_INCLUDE_DIR: ${LEFDEF_INCLUDE_DIR}" )
message( STATUS "LEFDEF_INCLUDE_DIR: ${LEFDEF_INCLUDE_DIR}" )
find_path ( LEFDEF_LIBRARY_DIR NAMES "libdef.a" "libdef_Debug.a"
find_path( LEFDEF_LIBRARY_DIR NAMES "libdef.so"
PATHS ${LEFDEF_SEARCH_PATH}
PATH_SUFFIXES "lib${LIB_SUFFIX}"
PATH_SUFFIXES "lib64" "lib"
DOC "The ${LEFDEF_LIBRARY_DIR_DESCRIPTION}" )
message( STATUS "LEFDEF_LIBRARY_DIR: ${LEFDEF_LIBRARY_DIR}" )
message( STATUS "LEFDEF_LIBRARY_DIR: ${LEFDEF_LIBRARY_DIR}" )
if ( LEFDEF_INCLUDE_DIR AND LEFDEF_LIBRARY_DIR )
_find_lefdef_lib ( "CDEF" "cdef" )
_find_lefdef_lib ( "ZCDEF" "cdefzlib" )
_find_lefdef_lib ( "DEF" "def" )
_find_lefdef_lib ( "ZDEF" "defzlib" )
_find_lefdef_lib ( "CLEF" "clef" )
_find_lefdef_lib ( "ZCLEF" "clefzlib" )
_find_lefdef_lib ( "LEF" "lef" )
_find_lefdef_lib ( "ZLEF" "lefzlib" )
else ( LEFDEF_INCLUDE_DIR AND LEFDEF_LIBRARY_DIR )
set ( LEFDEF_FOUND "NO" )
endif ( LEFDEF_INCLUDE_DIR AND LEFDEF_LIBRARY_DIR )
if( LEFDEF_INCLUDE_DIR AND LEFDEF_LIBRARY_DIR )
#_find_lefdef_lib( "CDEF" "cdef" )
#_find_lefdef_lib( "ZCDEF" "cdefzlib" )
_find_lefdef_lib( "DEF" "def" )
_find_lefdef_lib( "ZDEF" "defzlib" )
#_find_lefdef_lib( "CLEF" "clef" )
#_find_lefdef_lib( "ZCLEF" "clefzlib" )
_find_lefdef_lib( "LEF" "lef" )
_find_lefdef_lib( "ZLEF" "lefzlib" )
else()
set( LEFDEF_FOUND "NO" )
endif()
if ( LEFDEF_FOUND )
message ( STATUS "Found LEF/DEF" )
add_definitions ( -DHAVE_LEFDEF )
if ( NOT LEFDEF_FIND_QUIETLY )
message ( STATUS "Found LEF/DEF" )
endif ( NOT LEFDEF_FIND_QUIETLY )
else ( LEFDEF_FOUND )
set ( LEFDEF_LIBRARIES "" )
set ( LEFDEF_INCLUDE_DIR "" )
set ( LEFDEF_LIBRARY_DIR "" )
if ( LEFDEF_FIND_REQUIRED )
message ( STATUS "LEF/DEF libraries and/or includes NOT found!" )
endif ( LEFDEF_FIND_REQUIRED )
endif ( LEFDEF_FOUND )
if( LEFDEF_FOUND )
add_definitions( -DHAVE_LEFDEF )
if( NOT LEFDEF_FIND_QUIETLY )
message( STATUS "Found LEF/DEF" )
endif()
else( LEFDEF_FOUND )
set( LEFDEF_LIBRARIES "" )
set( LEFDEF_INCLUDE_DIR "" )
set( LEFDEF_LIBRARY_DIR "" )
if( LEFDEF_FIND_REQUIRED )
message( STATUS "LEF/DEF libraries and/or includes NOT found!" )
endif()
endif( LEFDEF_FOUND )
mark_as_advanced ( LEFDEF_INCLUDE_DIR LEFDEF_LIBRARY_DIR LEFDEF_LIBRARIES )
endif ( UNIX )
mark_as_advanced( LEFDEF_INCLUDE_DIR LEFDEF_LIBRARY_DIR LEFDEF_LIBRARIES )
endif( UNIX )

View File

@ -0,0 +1,10 @@
find_program( PELICAN_EXECUTABLE NAMES pelican
HINTS $ENV{PELICAN_DIR}
PATH_SUFFIXES bin
DOC "Pelican blog generator"
)
include( FindPackageHandleStandardArgs )
find_package_handle_standard_args( Pelican DEFAULT_MSG PELICAN_EXECUTABLE )
mark_as_advanced( PELICAN_EXECUTABLE )

View File

@ -41,7 +41,7 @@ def scrubPath ( pathName ):
def guessOs ():
useDevtoolset2 = False
useDevtoolset = False
osSlsoc7x_64 = re.compile (".*Linux.*el7.*x86_64.*")
osSlsoc6x_64 = re.compile (".*Linux.*el6.*x86_64.*")
osSlsoc6x = re.compile (".*Linux.*(el|slsoc)6.*")
@ -67,77 +67,41 @@ def guessOs ():
uname = subprocess.Popen ( ["uname", "-srm"], stdout=subprocess.PIPE )
lines = uname.stdout.readlines()
libDir="lib"
if osSlsoc7x_64.match(lines[0]):
osType = "Linux.el7_64"
libDir = "lib64"
if osSlsoc7x_64.match(lines[0]): osType = "Linux.el7_64"
elif osSlsoc6x_64.match(lines[0]):
osType = "Linux.slsoc6x_64"
libDir = "lib64"
useDevtoolset2 = True
useDevtoolset = True
elif osSlsoc6x.match(lines[0]):
osType = "Linux.slsoc6x"
useDevtoolset2 = True
elif osSLSoC5x_64.match(lines[0]):
osType = "Linux.SLSoC5x_64"
libDir = "lib64"
elif osSLSoC5x.match(lines[0]):
osType = "Linux.SLSoC5x"
elif osFedora_64.match(lines[0]):
osType = "Linux.fc_64"
libDir = "lib64"
elif osFedora.match(lines[0]):
osType = "Linux.fc"
elif osUbuntu1004.match(lines[0]):
osType = "Linux.Ubuntu1004"
elif osUbuntu1004_64.match(lines[0]):
osType = "Linux.Ubuntu1004_64"
libDir = "lib64"
elif osLinux_64.match(lines[0]):
osType = "Linux.x86_64"
if(os.path.exists("/usr/lib64/")):
libDir = "lib64"
elif osLinux.match(lines[0]):
osType = "Linux.i386"
elif osFreeBSD8x_64.match(lines[0]):
osType = "FreeBSD.8x.x86_64"
libDir = "lib64"
elif osFreeBSD8x_amd64.match(lines[0]):
osType = "FreeBSD.8x.amd64"
libDir = "lib64"
elif osFreeBSD8x.match(lines[0]):
osType = "FreeBSD.8x.i386"
elif osDarwin.match(lines[0]):
osType = "Darwin"
elif osCygwinW7_64.match(lines[0]):
osType = "Cygwin.W7_64"
libDir = "lib64"
elif osCygwinW7.match(lines[0]):
osType = "Cygwin.W7"
elif osCygwinW8_64.match(lines[0]):
osType = "Cygwin.W8_64"
libDir = "lib64"
elif osCygwinW8.match(lines[0]):
osType = "Cygwin.W8"
elif osCygwinW10_64.match(lines[0]):
osType = "Cygwin.W10_64"
libDir = "lib64"
elif osCygwinW10.match(lines[0]):
osType = "Cygwin.W10"
useDevtoolset = True
elif osSLSoC5x_64 .match(lines[0]): osType = "Linux.SLSoC5x_64"
elif osSLSoC5x .match(lines[0]): osType = "Linux.SLSoC5x"
elif osFedora_64 .match(lines[0]): osType = "Linux.fc_64"
elif osFedora .match(lines[0]): osType = "Linux.fc"
elif osUbuntu1004 .match(lines[0]): osType = "Linux.Ubuntu1004"
elif osUbuntu1004_64 .match(lines[0]): osType = "Linux.Ubuntu1004_64"
elif osLinux_64 .match(lines[0]): osType = "Linux.x86_64"
elif osLinux .match(lines[0]): osType = "Linux.i386"
elif osFreeBSD8x_64 .match(lines[0]): osType = "FreeBSD.8x.x86_64"
elif osFreeBSD8x_amd64.match(lines[0]): osType = "FreeBSD.8x.amd64"
elif osFreeBSD8x .match(lines[0]): osType = "FreeBSD.8x.i386"
elif osDarwin .match(lines[0]): osType = "Darwin"
elif osCygwinW7_64 .match(lines[0]): osType = "Cygwin.W7_64"
elif osCygwinW7 .match(lines[0]): osType = "Cygwin.W7"
elif osCygwinW8_64 .match(lines[0]): osType = "Cygwin.W8_64"
elif osCygwinW8 .match(lines[0]): osType = "Cygwin.W8"
elif osCygwinW10_64 .match(lines[0]): osType = "Cygwin.W10_64"
elif osCygwinW10 .match(lines[0]): osType = "Cygwin.W10"
else:
uname = subprocess.Popen ( ["uname", "-sr"], stdout=subprocess.PIPE )
osType = uname.stdout.readlines()[0][:-1]
print "[WARNING] Unrecognized OS: \"%s\"." % lines[0][:-1]
print " (using: \"%s\")" % osType
ldLibraryPath = os.getenv('LD_LIBRARY_PATH')
if ldLibraryPath and 'devtoolset' in ldLibraryPath: useDevtoolset2 = False
if ldLibraryPath and 'devtoolset' in ldLibraryPath: useDevtoolset = False
if libDir == 'lib64' and not os.path.exists('/usr/lib64'):
libDir = 'lib'
return (osType,libDir,useDevtoolset2)
return (osType,useDevtoolset)
def guessShell ():
@ -170,11 +134,11 @@ def guessShell ():
if __name__ == "__main__":
osType,libDir,useDevtoolset2 = guessOs()
buildType = "Release"
linkType = "Shared"
rootDir = None
shellBin, isBourneShell = guessShell()
osType,useDevtoolset = guessOs()
buildType = "Release"
linkType = "Shared"
rootDir = None
shellBin, isBourneShell = guessShell()
parser = optparse.OptionParser ()
# Build relateds.
@ -185,9 +149,9 @@ if __name__ == "__main__":
parser.add_option ( "--devel" , action="store_true" , dest="devel" )
parser.add_option ( "--static" , action="store_true" , dest="static" )
parser.add_option ( "--shared" , action="store_true" , dest="shared" )
parser.add_option ( "--chams" , action="store_true" , dest="chams" )
parser.add_option ( "--no-python" , action="store_true" , dest="nopython" )
parser.add_option ( "--root" , action="store" , type="string", dest="rootDir" )
parser.add_option ( "--remove" , action="store_true" , dest="remove" )
( options, args ) = parser.parse_args ()
if options.release: buildType = "Release"
@ -208,6 +172,32 @@ if __name__ == "__main__":
strippedLibraryPath = scrubPath( "LD_LIBRARY_PATH" )
strippedPythonPath = scrubPath( "PYTHONPATH" )
if options.remove:
shellScript = 'echo "Removing Coriolis environment";'
if osType == "Darwin":
ldVar = 'DYLD_LIBRARY_PATH'
else:
ldVar = 'LD_LIBRARY_PATH'
if isBourneShell:
shellScript += 'export PATH={};hash -r;'.format(strippedPath)
shellScript += 'BOOTSTRAP_TOP="";CORIOLIS_TOP="";export -n BOOTSTRAP_TOP CORIOLIS_TOP;'
if strippedLibraryPath:
shellScript += 'export {}={};'.format(ldVar, strippedLibraryPath)
else:
shellScript += '{0}=""; export -n {0};'.format(ldVar)
else:
shellScript += 'setenv PATH {};rehash;'.format(strippedPath)
shellScript += 'unsetenv BOOTSTRAP_TOP CORIOLIS_TOP;'
if strippedLibraryPath:
shellScript += 'setenv {} {};'.format(ldVar, strippedLibraryPath)
else:
shellScript += 'unsetenv {};'.format(ldVar)
print(shellScript)
sys.exit(0)
shellScriptSh = \
'echo "%(MESSAGE)s";' \
'echo "Switching to Coriolis 2.x (%(buildDir)s)";' \
@ -227,6 +217,8 @@ if __name__ == "__main__":
# 'setenv STRATUS_MAPPING_NAME "%(SYSCONF_DIR)s/stratus2sxlib.xml";' \
reDevtoolset = re.compile( r'/opt/rh/devtoolset-(?P<version>\d+)/root/etc/coriolis2.*' )
buildDir = buildType + "." + linkType
scriptDir = os.path.dirname ( os.path.abspath(__file__) )
#print "echo \"Script Location: %s\";" % scriptDir,
@ -234,57 +226,69 @@ if __name__ == "__main__":
coriolisTop = "/usr"
sysconfDir = scriptDir
shellMessage = "Using system-wide Coriolis 2 (/usr)"
elif scriptDir.startswith("/opt/rh/devtoolset-2/root/etc/coriolis2"):
coriolisTop = "/opt/rh/devtoolset-2/root/usr"
sysconfDir = scriptDir
shellMessage = "Using system-wide devtoolset-2 Coriolis 2 (/opt/rh/devtoolset-2/root/usr)"
elif scriptDir.startswith(os.getenv("HOME")+"/nightly/coriolis-2.x/"):
rootDir = os.getenv("HOME") + "/nightly/coriolis-2.x"
coriolisTop = "%s/%s/%s/install" % ( rootDir, osType, buildDir )
sysconfDir = scriptDir
shellMessage = "Using Nightly build Coriolis 2 (%s)" % coriolisTop
elif scriptDir.startswith("/users/outil/coriolis/coriolis-2.x/") \
or scriptDir.startswith("/soc/coriolis2/"):
coriolisTop = "/soc/coriolis2"
sysconfDir = coriolisTop + "/etc/coriolis2"
shellMessage = "Using SoC network-wide Coriolis 2 (/soc/coriolis2)"
else:
if not rootDir:
rootDir = os.getenv("HOME") + "/coriolis-2.x"
coriolisTop = "%s/%s/%s/install" % ( rootDir, osType, buildDir )
sysconfDir = coriolisTop + "/etc/coriolis2"
shellMessage = "Using user-selected Coriolis 2 (%s)" % rootDir
m = reDevtoolset.match( scriptDir )
if m:
coriolisTop = "/opt/rh/devtoolset-%d/root/usr" % m.group('version')
sysconfDir = scriptDir
shellMessage = "Using system-wide devtoolset-%(v)d Coriolis 2 (/opt/rh/devtoolset-%(v)d/root/usr)" \
% { 'v':m.group('version') }
elif scriptDir.startswith(os.getenv("HOME")+"/nightly/coriolis-2.x/"):
rootDir = os.getenv("HOME") + "/nightly/coriolis-2.x"
coriolisTop = "%s/%s/%s/install" % ( rootDir, osType, buildDir )
sysconfDir = scriptDir
shellMessage = "Using Nightly build Coriolis 2 (%s)" % coriolisTop
elif scriptDir.startswith("/users/outil/coriolis/coriolis-2.x/") \
or scriptDir.startswith("/soc/coriolis2/"):
coriolisTop = "/soc/coriolis2"
sysconfDir = coriolisTop + "/etc/coriolis2"
shellMessage = "Using SoC network-wide Coriolis 2 (/soc/coriolis2)"
else:
if not rootDir:
rootDir = os.getenv("HOME") + "/coriolis-2.x"
coriolisTop = "%s/%s/%s/install" % ( rootDir, osType, buildDir )
sysconfDir = coriolisTop + "/etc/coriolis2"
shellMessage = "Using user-selected Coriolis 2 (%s)" % rootDir
if osType.startswith("Cygwin"):
strippedPath = "%s/%s:%s" % ( coriolisTop, libDir, strippedPath )
absLibDir = "%s/%s" % ( coriolisTop, libDir )
strippedPath = "%s/bin:%s" % ( coriolisTop, strippedPath )
strippedLibraryPath = "%s:%s" % ( absLibDir , strippedLibraryPath )
strippedPath = "%s/lib:%s" % ( coriolisTop, libDir, strippedPath )
if not os.path.exists(coriolisTop):
print 'echo "[ERROR] coriolisEnv.py, top directory <%s> do not exists."' % coriolisTop
sys.exit( 1 )
for lib in [ 'lib64', 'lib' ]:
libDir = lib
absLibDir = '{0}/{1}'.format( coriolisTop, lib )
if os.path.isdir(absLibDir): break
libDir = None
if libDir is None:
print 'echo "[ERROR] coriolisEnv.py, library directory not found."'
sys.exit( 1 )
strippedPath = "%s/bin:%s" % ( coriolisTop, strippedPath )
strippedLibraryPath = "%s:%s" % ( absLibDir , strippedLibraryPath )
if not options.nopython:
pyVersion = sys.version_info
version = "%d.%d" % (pyVersion[0],pyVersion[1])
if osType.startswith("Linux.SL") \
or osType.startswith("Linux.sl") \
or osType.startswith("Linux.el") \
or osType.startswith("Linux.fc") \
or osType.startswith("Cygwin"):
sitePackagesDir = "%s/python%s/site-packages" % (absLibDir,version)
elif osType.startswith("Darwin"):
sitePackagesDir = "%s/%s/site-packages" % (absLibDir,version)
else:
sitePackagesDir = "%s/python%s/dist-packages" % (absLibDir,version)
sitePackagesDir = "sitePackageDir_has_been_not_found"
for pyPackageDir in [ "%s/python%s/site-packages" % (absLibDir,version)
, "%s/python%s/dist-packages" % (absLibDir,version)
, "%s/%s/site-packages" % (absLibDir,version)
]:
if os.path.isdir(pyPackageDir):
sitePackagesDir = pyPackageDir
break
strippedPythonPath = "%s:" % (sitePackagesDir) + strippedPythonPath
strippedPythonPath = "%s/crlcore:" % (sitePackagesDir) + strippedPythonPath
strippedPythonPath = "%s/cumulus:" % (sitePackagesDir) + strippedPythonPath
strippedPythonPath = "%s/cumulus/plugins:" % (sitePackagesDir) + strippedPythonPath
strippedPythonPath = "%s/stratus:" % (sitePackagesDir) + strippedPythonPath
strippedPythonPath = "%s:" % (sysconfDir) + strippedPythonPath
shellScriptSh += 'PYTHONPATH="%(PYTHONPATH)s";' \
'export PYTHONPATH;'
@ -305,10 +309,10 @@ if __name__ == "__main__":
if isBourneShell: shellScript = shellScriptSh
else: shellScript = shellScriptCsh
if useDevtoolset2:
if useDevtoolset:
shellScript += \
' echo "Launching a devtoolset-2 subshell though scl (CTRL+D to exit).";' \
' scl enable devtoolset-2 %(SHELL)s'
' echo "Launching a devtoolset-8 subshell though scl (CTRL+D to exit).";' \
' scl enable devtoolset-8 %(SHELL)s'
evalScript = shellScript % { "PATH" : strippedPath
, "LD_LIBRARY_PATH" : strippedLibraryPath

View File

@ -0,0 +1,6 @@
FROM debian10.coriolis
COPY root/dot.bashrc /root/.bashrc
CMD [ "/bin/bash", "-i" ]

View File

@ -0,0 +1,10 @@
FROM debian10.system
COPY root/socInstaller.py /root/socInstaller.py
RUN mkdir -p coriolis-2.x/src \
&& git clone https://github.com/m-labs/nmigen.git \
&& cd nmigen \
&& python3 setup.py develop \
&& /root/socInstaller.py --docker --profile=Debian10 --do-yosys --do-alliance --do-coriolis

View File

@ -0,0 +1,4 @@
FROM debian10.libresoc
CMD [ "/bin/bash", "-i" ]

View File

@ -0,0 +1,12 @@
FROM debian10.coriolis
# Cannot clone directly from LibreSOC repository as I need my
# ssh key that I cannot forward to the docker build process.
#
# git clone ssh://gitolite3@libre-riscv.org:922/soclayout.git
COPY ./root/soclayout /root/coriolis-2.x/src/soclayout
RUN cd /root/coriolis-2.x/src/soclayout \
&& git checkout 75e03eb

View File

@ -0,0 +1,29 @@
FROM debian:buster-slim
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get -y install build-essential binutils-dev \
git cmake bison flex gcc python-dev \
libboost-all-dev libboost-python-dev \
zlib1g-dev libxml2-dev rapidjson-dev libbz2-dev \
qt4-dev-tools libqwt-dev python-qt4 \
python3-setuptools \
\
autotools-dev automake \
libxt-dev libxpm-dev libmotif-dev \
\
tcl tcl-dev libffi6 libffi-dev libreadline-dev \
\
vim \
&& apt-get clean
# If you want to build Alliance documentation, install those LaTeX
# packages:
# transfig texlive texlive-latex-extra
# texlive-plain-generic texlive-pictures
# imagemagick
#
# The packaged yosys 0.8 is too old to work with nMigen, must be 0.9.
# yosys

View File

@ -0,0 +1,4 @@
systemImage="debian10.system"
coriolisImage="debian10.coriolis"
bashImage="debian10.bash"

View File

@ -0,0 +1,19 @@
#!/bin/bash
srcDir=${HOME}/coriolis-2.x/src/alliance/alliance/src
commonRoot=${HOME}/coriolis-2.x/Linux.el7_64/Release.Shared
buildDir=${commonRoot}/build
installDir=${commonRoot}/install
export ALLIANCE_TOP=${installDir}
export LD_LIBRARY_PATH=${installDir}/lib:${LD_LIBRARY_PATH}
cd ${srcDir}
# Skip doc generation to avoid pulling TeXLive in docker images.
sed -i 's,dirs="\$newdirs documentation",dirs="$newdirs",' ./autostuff
./autostuff clean
./autostuff
mkdir -p ${buildDir}
cd ${buildDir}
${srcDir}/configure --prefix=${ALLIANCE_TOP} --enable-alc-shared
make -j1 install

View File

@ -0,0 +1,14 @@
echo "Running /root/.bashrc"
for archDir in `ls /root/coriolis-2.x/`; do
if [ "$archDir" = "src" ]; then continue; fi
break
done
echo "Found Coriolis architecture directory \"${archDir}\"."
installDir="/root/coriolis-2.x/${archDir}/Release.Shared/install"
. ${installDir}/etc/profile.d/alc_env.sh
eval `${installDir}/etc/coriolis2/coriolisEnv.py`
export QT_X11_NO_MITSHM=1

View File

@ -0,0 +1,650 @@
#!/usr/bin/env python
#
# -*- mode:Python -*-
#
# This file is part of the Coriolis Software.
# Copyright (c) UPMC 2015-2018, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | C o r i o l i s I n s t a l l e r |
# | |
# | Authors : Jean-Paul Chaput |
# | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
# | =============================================================== |
# | Python : "./socInstaller.py" |
# +-----------------------------------------------------------------+
#
# WARNING:
# This script has been designed only for internal use in the
# LIP6/CIAN department. If you want to use it you will need to
# change the hardwired configuration.
showTrace = True
try:
import sys
import os.path
import shutil
import optparse
import time
import traceback
import distutils.sysconfig
import subprocess
import socket
import re
import bz2
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
except ImportError, e:
module = str(e).split()[-1]
class ErrorMessage ( Exception ):
def __init__ ( self, code, *arguments ):
self._code = code
self._errors = [ 'Malformed call to ErrorMessage()', '%s' % str(arguments) ]
text = None
if len(arguments) == 1:
if isinstance(arguments[0],Exception): text = str(arguments[0]).split('\n')
else:
self._errors = arguments[0]
elif len(arguments) > 1:
text = list(arguments)
if text:
self._errors = []
while len(text[0]) == 0: del text[0]
lstrip = 0
if text[0].startswith('[ERROR]'): lstrip = 8
for line in text:
if line[0:lstrip ] == ' '*lstrip or \
line[0:lstrip-1] == '[ERROR]':
self._errors += [ line[lstrip:] ]
else:
self._errors += [ line.lstrip() ]
return
def __str__ ( self ):
if not isinstance(self._errors,list):
return "[ERROR] %s" % self._errors
formatted = "\n"
for i in range(len(self._errors)):
if i == 0: formatted += "[ERROR] %s" % self._errors[i]
else: formatted += " %s" % self._errors[i]
if i+1 < len(self._errors): formatted += "\n"
return formatted
def addMessage ( self, message ):
if not isinstance(self._errors,list):
self._errors = [ self._errors ]
if isinstance(message,list):
for line in message:
self._errors += [ line ]
else:
self._errors += [ message ]
return
def terminate ( self ):
print self
sys.exit(self._code)
@property
def code ( self ): return self._code
class BadBinary ( ErrorMessage ):
def __init__ ( self, binary ):
ErrorMessage.__init__( self, 1, "Binary not found: <%s>." % binary )
return
class BadReturnCode ( ErrorMessage ):
def __init__ ( self, status ):
ErrorMessage.__init__( self, 1, "Command returned status:%d." % status )
return
class Command ( object ):
def __init__ ( self, arguments, fdLog=None ):
self.arguments = arguments
self.fdLog = fdLog
if self.fdLog != None and not isinstance(self.fdLog,file):
print '[WARNING] Command.__init__(): <fdLog> is neither None or a file.'
return
def _argumentsToStr ( self, arguments ):
s = ''
for argument in arguments:
if argument.find(' ') >= 0: s += ' "' + argument + '"'
else: s += ' ' + argument
return s
def log ( self, text ):
print text[:-1]
sys.stdout.flush()
sys.stderr.flush()
if isinstance(self.fdLog,file):
self.fdLog.write( text )
self.fdLog.flush()
return
def execute ( self ):
global conf
sys.stdout.flush()
sys.stderr.flush()
homeDir = os.environ['HOME']
workDir = os.getcwd()
if homeDir.startswith(homeDir):
workDir = '~' + workDir[ len(homeDir) : ]
user = 'root'
if os.environ.has_key('USER'): user = os.environ['USER']
prompt = '%s@%s:%s$' % (user,conf.masterHost,workDir)
try:
self.log( '%s%s\n' % (prompt,self._argumentsToStr(self.arguments)) )
print self.arguments
child = subprocess.Popen( self.arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
while True:
line = child.stdout.readline()
if not line: break
self.log( line )
except OSError, e:
raise BadBinary( self.arguments[0] )
(pid,status) = os.waitpid( child.pid, 0 )
status >>= 8
if status != 0:
raise BadReturnCode( status )
return
class CommandArg ( object ):
def __init__ ( self, command, wd=None, host=None, fdLog=None ):
self.command = command
self.host = host
self.wd = wd
self.fdLog = fdLog
return
def __str__ ( self ):
s = ''
if self.wd: s = 'cd %s && ' % self.wd
for i in range(len(self.command)):
if i: s += ' '
s += self.command[i]
return s
def getArgs ( self ):
if not self.host: return self.command
return [ 'ssh', self.host, str(self) ]
def execute ( self ):
if not self.host and self.wd: os.chdir( self.wd )
Command( self.getArgs(), self.fdLog ).execute()
return
class YosysCommand ( CommandArg ):
def __init__ ( self, yosysBin, fdLog=None ):
CommandArg.__init__ ( self, [ yosysBin ], fdLog=fdLog )
return
class AllianceCommand ( CommandArg ):
def __init__ ( self, alcBin, fdLog=None ):
CommandArg.__init__ ( self, [ alcBin ], fdLog=fdLog )
return
class CoriolisCommand ( CommandArg ):
def __init__ ( self, ccbBin, rootDir, threads=1, otherArgs=[], fdLog=None ):
CommandArg.__init__ ( self, [ ccbBin
, '--root='+rootDir
, '--project=coriolis'
, '--make=-j%d install' % threads
] + otherArgs
, fdLog=fdLog )
return
class BenchsCommand ( CommandArg ):
def __init__ ( self, benchsDir, fdLog=None ):
CommandArg.__init__ ( self, [ '../bin/go.sh' ], wd=benchsDir, fdLog=fdLog )
return
class GitRepository ( object ):
@staticmethod
def getLocalRepository ( url ):
localRepo = url.split( '/' )[-1]
if localRepo.endswith('.git'):
localRepo = localRepo[:-4]
return localRepo
def __init__ ( self, url, cloneDir, fdLog=None ):
self.url = url
self.cloneDir = cloneDir
self.localRepo = GitRepository.getLocalRepository( url )
self.fdLog = fdLog
return
@property
def localRepoDir ( self ): return self.cloneDir+'/'+self.localRepo
def removeLocalRepo ( self ):
if os.path.isdir(self.localRepoDir):
print 'Removing Git local repository: <%s>' % self.localRepoDir
shutil.rmtree( self.localRepoDir )
return
def clone ( self ):
print 'Clone/pull from:', self.url
if not os.path.isdir(self.cloneDir):
os.makedirs( self.cloneDir )
if not os.path.isdir(self.localRepoDir):
os.chdir( self.cloneDir )
Command( [ 'git', 'clone', self.url ], self.fdLog ).execute()
else:
os.chdir( self.localRepoDir )
Command( [ 'git', 'pull' ], self.fdLog ).execute()
return
def checkout ( self, branch ):
os.chdir( self.localRepoDir )
Command( [ 'git', 'checkout', branch ], self.fdLog ).execute()
return
class Configuration ( object ):
PrimaryNames = \
[ 'sender' , 'receivers'
, 'coriolisRepo', 'benchsRepo' , 'supportRepos'
, 'homeDir' , 'masterHost'
, 'debugArg' , 'nightlyMode', 'dockerMode', 'chrootMode'
, 'rmSource' , 'rmBuild'
, 'doGit' , 'doAlliance' , 'doCoriolis', 'doBenchs', 'doSendReport'
, 'success' , 'rcode'
]
SecondaryNames = \
[ 'rootDir', 'srcDir', 'logDir', 'logs', 'fds', 'yosysBin', 'alcBin', 'ccbBin', 'benchsDir'
]
def __init__ ( self ):
self._sender = 'Jean-Paul.Chaput@soc.lip6.fr'
self._receivers = [ 'Jean-Paul.Chaput@lip6.fr', ]
self._supportRepos = [ 'http://github.com/miloyip/rapidjson' ]
self._allianceRepo = 'https://gitlab.lip6.fr/jpc/alliance.git'
self._coriolisRepo = 'https://gitlab.lip6.fr/jpc/coriolis.git'
self._benchsRepo = 'https://gitlab.lip6.fr/jpc/alliance-check-toolkit.git'
self._homeDir = os.environ['HOME']
self._debugArg = ''
self._rmSource = False
self._rmBuild = False
self._doGit = True
self._doYosys = False
self._doAlliance = False
self._doCoriolis = False
self._doBenchs = False
self._doSendReport = False
self._nightlyMode = False
self._dockerMode = False
self._chrootMode = None
self._logs = { 'alliance':None, 'coriolis':None, 'benchs':None }
self._fds = { 'alliance':None, 'coriolis':None, 'benchs':None }
self._ccbBin = None
self._benchsDir = None
self._masterHost = self._detectMasterHost()
self._success = False
self._rcode = 0
self._updateSecondaries()
return
def __setattr__ ( self, attribute, value ):
if attribute in Configuration.SecondaryNames:
print ErrorMessage( 1, 'Attempt to write in read-only attribute <%s> in Configuration.'%attribute )
return
if attribute == 'masterHost' or attribute == '_masterHost':
if value == 'lepka':
print 'Never touch the Git tree when running on <lepka>.'
self._rmSource = False
self._rmBuild = False
self._doGit = False
self._doSendReport = False
if attribute[0] == '_':
self.__dict__[attribute] = value
return
if attribute == 'homeDir': value = os.path.expanduser(value)
self.__dict__['_'+attribute] = value
self._updateSecondaries()
return
def __getattr__ ( self, attribute ):
if attribute[0] != '_': attribute = '_'+attribute
if not self.__dict__.has_key(attribute):
raise ErrorMessage( 1, 'Configuration has no attribute <%s>.'%attribute )
return self.__dict__[attribute]
def _updateSecondaries ( self ):
if self._nightlyMode:
self._rootDir = self._homeDir + '/nightly/coriolis-2.x'
else:
self._rootDir = self._homeDir + '/coriolis-2.x'
self._srcDir = self._rootDir + '/src'
self._logDir = self._srcDir + '/logs'
self._yosysBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/yosysInstaller.sh'
self._alcBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/allianceInstaller.sh'
self._ccbBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/ccb.py'
self._benchsDir = self._srcDir + '/' + GitRepository.getLocalRepository(self._benchsRepo ) + '/benchs'
self._masterHost = self._detectMasterHost()
return
def _detectMasterHost ( self ):
if self._chrootMode is None: return 'unknown'
if self._chrootMode: return 'chrooted-host'
masterHost = 'unknown'
hostname = socket.gethostname()
hostAddr = socket.gethostbyname(hostname)
if hostname == 'lepka' and hostAddr == '127.0.0.1':
masterHost = 'lepka'
else:
masterHost = hostname.split('.')[0]
return masterHost
def openLog ( self, stem ):
if not os.path.isdir(self._logDir):
os.makedirs( self._logDir )
index = 0
timeTag = time.strftime( "%Y.%m.%d" )
while True:
logFile = os.path.join(self._logDir,"%s-%s-%02d.log" % (stem,timeTag,index))
if not os.path.isfile(logFile):
print "Report log: <%s>" % logFile
break
index += 1
fd = open( logFile, "w" )
self._logs[stem] = logFile
self._fds [stem] = fd
return
def closeLogs ( self ):
for fd in self._fds.values():
if fd: fd.close()
return
def compressLogs ( self ):
for log in self._logs.values():
if not log: continue
fd = open( log, 'r' )
bzfd = bz2.BZ2File( log+'.bz2', 'w' )
for line in fd.readlines(): bzfd.write( line )
bzfd.close()
fd.close()
os.unlink( log )
return
def getCommands ( self, target ):
commands = []
if self.doYosys:
if not os.path.isfile( self.yosysBin ):
raise ErrorMessage( 1, [ 'Cannot find <yosysInstaller.sh>, should be here:'
, ' <%s>' % self.yosysBin
] )
commands.append( YosysCommand( self.yosysBin, fdLog=self.fds['yosys'] ) )
if self.doAlliance:
if not os.path.isfile( self.alcBin ):
raise ErrorMessage( 1, [ 'Cannot find <allianceInstaller.sh>, should be here:'
, ' <%s>' % self.alcBin
] )
commands.append( AllianceCommand( self.alcBin, fdLog=self.fds['alliance'] ) )
if self.doCoriolis:
if not os.path.isfile( self.ccbBin ):
raise ErrorMessage( 1, [ 'Cannot find <ccb.py>, should be here:'
, ' <%s>' % self.ccbBin
] )
otherArgs = []
if self.debugArg: otherArgs.append( self.debugArg )
if target == 'SL7_64':
otherArgs.append( '--project=support' )
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 3, otherArgs , fdLog=self.fds['coriolis'] ) )
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 1, otherArgs+['--doc'], fdLog=self.fds['coriolis'] ) )
elif target == 'SL6_64' or target == 'SL6':
otherArgs.append( '--project=support' )
otherArgs.append( '--devtoolset=8' )
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 6, otherArgs , fdLog=self.fds['coriolis'] ) )
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 1, otherArgs+['--doc'], fdLog=self.fds['coriolis'] ) )
elif target == 'Ubuntu18' or target == 'Debian9' or target == 'Debian10':
if target == 'Ubuntu18': otherArgs.append( '--qt5' )
commands.append( CoriolisCommand( self.ccbBin, self.rootDir, 3, otherArgs, fdLog=self.fds['coriolis'] ) )
if self.doBenchs:
commands.append( BenchsCommand( self.benchsDir, fdLog=self.fds['benchs'] ) )
return commands
class Report ( object ):
def __init__ ( self, conf ):
self.conf = conf
commaspace = ', '
date = time.strftime( "%A %d %B %Y" )
stateText = 'FAILED'
modeText = 'SoC installation'
if self.conf.success: stateText = 'SUCCESS'
if self.conf.nightlyMode: modeText = 'Nightly build'
self.message = MIMEMultipart()
self.message['Subject'] = '[%s] Coriolis %s %s' % (stateText,modeText,date)
self.message['From' ] = self.conf.sender
self.message['To' ] = commaspace.join( self.conf.receivers )
self.attachements = []
self.mainText = '\n'
self.mainText += 'Salut le Crevard,\n'
self.mainText += '\n'
if self.conf.nightlyMode:
self.mainText += 'This is the nightly build report of Coriolis.\n'
else:
self.mainText += 'SoC installer report of Coriolis.\n'
self.mainText += '%s\n' % date
self.mainText += '\n'
if self.conf.success:
self.mainText += 'Build was SUCCESSFUL\n'
else:
self.mainText += 'Build has FAILED, please have a look to the attached log file(s).\n'
self.mainText += '\n'
self.mainText += 'Complete log file(s) can be found here:\n'
return
def attachLog ( self, logFile ):
if not logFile: return
fd = open( logFile, 'rb' )
try:
fd.seek( -1024*100, os.SEEK_END )
except IOError, e:
pass
tailLines = ''
for line in fd.readlines()[1:]:
tailLines += line
fd.close()
self.mainText += ' <%s>\n' % logFile
attachement = MIMEApplication(tailLines)
attachement.add_header( 'Content-Disposition', 'attachment', filename=os.path.basename(logFile) )
self.attachements.append( attachement )
return
def send ( self ):
self.message.attach( MIMEText(self.mainText) )
for attachement in self.attachements:
self.message.attach( attachement )
print "Sending mail report to:"
for receiver in self.conf.receivers: print ' <%s>' % receiver
session = smtplib.SMTP( 'localhost' )
session.sendmail( self.conf.sender, self.conf.receivers, self.message.as_string() )
session.quit()
return
# -------------------------------------------------------------------
# <socInstaller> Main Part.
parser = optparse.OptionParser ()
parser.add_option ( "--debug" , action="store_true" , dest="debug" , help="Build a <Debug> aka (-g) version." )
parser.add_option ( "--no-git" , action="store_true" , dest="noGit" , help="Do not pull/update Git repositories before building." )
parser.add_option ( "--do-yosys" , action="store_true" , dest="doYosys" , help="Rebuild Yosys." )
parser.add_option ( "--do-alliance" , action="store_true" , dest="doAlliance" , help="Rebuild the Alliance tools." )
parser.add_option ( "--do-coriolis" , action="store_true" , dest="doCoriolis" , help="Rebuild the Coriolis tools." )
parser.add_option ( "--do-report" , action="store_true" , dest="doReport" , help="Send a final report." )
parser.add_option ( "--nightly" , action="store_true" , dest="nightly" , help="Perform a nighly build." )
parser.add_option ( "--docker" , action="store_true" , dest="docker" , help="Perform a build inside a docker container." )
parser.add_option ( "--chroot" , action="store_true" , dest="chroot" , help="Perform a build inside a chrooted environment." )
parser.add_option ( "--benchs" , action="store_true" , dest="benchs" , help="Run the <alliance-checker-toolkit> sanity benchs." )
parser.add_option ( "--rm-build" , action="store_true" , dest="rmBuild" , help="Remove the build/install directories." )
parser.add_option ( "--rm-source" , action="store_true" , dest="rmSource" , help="Remove the Git source repositories." )
parser.add_option ( "--rm-all" , action="store_true" , dest="rmAll" , help="Remove everything (source+build+install)." )
parser.add_option ( "--root" , action="store" , type="string", dest="rootDir" , help="The root directory (default: <~/coriolis-2.x/>)." )
parser.add_option ( "--profile" , action="store" , type="string", dest="profile" , help="The targeted OS for the build." )
(options, args) = parser.parse_args ()
conf = Configuration()
try:
if options.debug: conf.debugArg = '--debug'
if options.nightly: conf.nightlyMode = True
if options.docker: conf.dockerMode = True
if options.chroot: conf.chrootMode = True
if options.noGit: conf.doGit = False
if options.doYosys: conf.doYosys = True
if options.doAlliance: conf.doAlliance = True
if options.doCoriolis: conf.doCoriolis = True
if options.benchs: conf.doBenchs = True
if options.doReport: conf.doSendReport = True
if options.rmSource or options.rmAll: conf.rmSource = True
if options.rmBuild or options.rmAll: conf.rmBuild = True
if conf.doYosys: conf.openLog( 'yosys' )
if conf.doAlliance: conf.openLog( 'alliance' )
if conf.doCoriolis: conf.openLog( 'coriolis' )
if conf.doBenchs: conf.openLog( 'benchs' )
if conf.dockerMode: os.environ['USER'] = 'root'
gitSupports = []
for supportRepo in conf.supportRepos:
gitSupports.append( GitRepository( supportRepo, conf.srcDir+'/support' ) )
gitCoriolis = GitRepository( conf.coriolisRepo, conf.srcDir, conf.fds['coriolis'] )
gitBenchs = GitRepository( conf.benchsRepo , conf.srcDir, conf.fds['coriolis'] )
if conf.doAlliance:
gitAlliance = GitRepository( conf.allianceRepo, conf.srcDir, conf.fds['alliance'] )
if conf.doGit:
for gitSupport in gitSupports:
if conf.rmSource: gitSupport.removeLocalRepo()
gitSupport.clone()
#if gitSupport.url.endswith('rapidjson'):
# gitSupport.checkout( 'a1c4f32' )
if conf.doAlliance:
if conf.rmSource: gitAlliance.removeLocalRepo()
gitAlliance.clone ()
#gitAlliance.checkout( 'devel' )
if conf.doCoriolis:
if conf.rmSource: gitCoriolis.removeLocalRepo()
gitCoriolis.clone ()
gitCoriolis.checkout( 'devel' )
if conf.rmSource: gitBenchs.removeLocalRepo()
gitBenchs.clone()
if conf.rmBuild:
for entry in os.listdir(conf.rootDir):
if entry.startswith('Linux.'):
buildDir = conf.rootDir+'/'+entry
print 'Removing OS build directory: <%s>' % buildDir
shutil.rmtree( buildDir )
commands = conf.getCommands( options.profile )
for command in commands:
if command.host:
print 'Executing command on remote host <%s>:' % host
else:
print 'Executing command on *local* host:'
print ' %s' % str(command)
command.execute()
conf.closeLogs()
conf.success = True
except ErrorMessage, e:
print e
conf.closeLogs()
conf.success = False
if showTrace:
print '\nPython stack trace:'
traceback.print_tb( sys.exc_info()[2] )
conf.rcode = e.code
if conf.doSendReport:
report = Report( conf )
report.attachLog( conf.logs['coriolis' ] )
report.attachLog( conf.logs['benchs' ] )
report.send()
conf.compressLogs()
sys.exit( conf.rcode )

@ -0,0 +1 @@
Subproject commit bd6b78003c0cc6579fbad73593e69f2714f3a770

View File

@ -0,0 +1,6 @@
FROM sl7.coriolis
COPY root/dot.bashrc /root/.bashrc
CMD [ "/bin/bash", "-i" ]

View File

@ -0,0 +1,6 @@
FROM sl7.system
COPY root/socInstaller.py /root/socInstaller.py
RUN /root/socInstaller.py --docker --profile=SL7_64 --do-alliance --do-coriolis --benchs

View File

@ -0,0 +1,25 @@
FROM scientificlinux/sl:latest
RUN yum -y update \
&& yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \
&& yum -y install git cmake bison flex gcc-c++ libstdc++-devel \
make binutils-devel \
boost-devel boost-python boost-filesystem \
boost-regex boost-wave \
python-devel libxml2-devel bzip2-devel \
qt-devel PyQt4 \
\
autoconf automake libtool \
libX11-devel libXt-devel libXpm-devel \
motif motif-devel \
\
python36-six \
vim-x11 \
&& yum -y install http://ftp.lip6.fr/pub/linux/distributions/slsoc/soc/7/addons/x86_64/RPMS/qwt-6.1.2-4.fc23.x86_64.rpm \
http://ftp.lip6.fr/pub/linux/distributions/slsoc/soc/7/addons/x86_64/RPMS/qwt-devel-6.1.2-4.fc23.x86_64.rpm \
http://ftp.lip6.fr/pub/linux/distributions/slsoc/soc/7/addons/x86_64/RPMS/yosys-0.9-1.el7.soc.x86_64.rpm \
http://ftp.lip6.fr/pub/linux/distributions/slsoc/soc/7/addons/x86_64/RPMS/python3-pyvcd-0.1.7-git2302c99.1.el7.soc.x86_64.rpm \
http://ftp.lip6.fr/pub/linux/distributions/slsoc/soc/7/addons/x86_64/RPMS/python3-nmigen-0.1-git57d95b7.1.el7.soc.x86_64.rpm \
&& yum clean all

View File

@ -0,0 +1,4 @@
systemImage="sl7.system"
coriolisImage="sl7.coriolis"
bashImage="sl7.bash"

View File

@ -0,0 +1,18 @@
#!/bin/bash
srcDir=${HOME}/coriolis-2.x/src/alliance/alliance/src
commonRoot=${HOME}/coriolis-2.x/Linux.el7_64/Release.Shared
buildDir=${commonRoot}/build
installDir=${commonRoot}/install
export ALLIANCE_TOP=${installDir}
export LD_LIBRARY_PATH=${installDir}/lib:${LD_LIBRARY_PATH}
cd ${srcDir}
sed -i 's,dirs="\$newdirs documentation",dirs="$newdirs",' ./autostuff
./autostuff clean
./autostuff
mkdir -p ${buildDir}
cd ${buildDir}
${srcDir}/configure --prefix=${ALLIANCE_TOP} --enable-alc-shared
make -j1 install

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