Compare commits

..

437 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
3587 changed files with 516473 additions and 107651 deletions

View File

@ -5,20 +5,19 @@
Coriolis README Coriolis README
=============== ===============
Coriolis is a free database, placement tool and routing tool for VLSI design.
Coriolis is a free database, placement tool and routing tool for VLSI designs.
Purpose Purpose
======= =======
Coriolis provides several tools to perform the layout of VLSI circuits. Its Coriolis provides several tools to perform the layout of VLSI circuits. Its
main components are the Hurricane database, the Etesian placer and the Kite main components are the Hurricane database, the Etesian placer and the Katana
router, but other tools can use the Hurricane database and the parsers router, but other tools can use the Hurricane database and the parsers
provided. provided.
The user interface <cgt> is the prefered way to use Coriolis, but all The user interface <cgt> is the prefered way to use Coriolis, but all
Coriolis tools are Python modules and thus scriptables. Coriolis tools are Python modules and thus scriptable.
Documentation Documentation
@ -26,14 +25,14 @@ Documentation
The complete documentation is available here, both in pdf & html: The complete documentation is available here, both in pdf & html:
./documentation/_build/html/index.html ./documentation/output/html
./documentation/UsersGuide/UsersGuide.pdf ./documentation/UsersGuide/UsersGuide.pdf
The documentation of the latest *stable* version is also The documentation of the latest *stable* version is also
available online. It may be quite outdated from the *devel* available online. It may be quite outdated from the *devel*
version. version.
https://soc-extras.lip6.fr/en/coriolis/coriolis2-users-guide/ https://www-soc.lip6.fr/sesi-docs/coriolis2-docs/coriolis2/en/latex/users-guide/UsersGuide.pdf
Building Coriolis Building Coriolis
@ -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 ego@home:~: ~/coriolis-2.x/<OS>.<DISTRIB>/Release.Shared/install/bin/coriolis
The ``coriolis`` script is tasked to guess it's location and setup appropriatly The ``coriolis`` script detects its location and setups the UNIX
the UNIX environment, then lauch ``cgt`` (or *any* command, with the environment appropriately, then lauches ``cgt`` (or *any* command, with the
``--run=<COMMAND>`` option). ``--run=<COMMAND>`` option).
Conversely, you can setup the current shell environement for Coriolis by Conversely, you can setup the current shell environement for Coriolis by

View File

@ -3,7 +3,7 @@
set(CMAKE_LEGACY_CYGWIN_WIN32 0) set(CMAKE_LEGACY_CYGWIN_WIN32 0)
project(ANABATIC) project(ANABATIC)
set(ignoreVariables "${BUILD_DOC}") set(ignoreVariables "${BUILD_DOC} ${CMAKE_INSTALL_DIR}")
option(BUILD_DOC "Build the documentation (doxygen)" OFF) option(BUILD_DOC "Build the documentation (doxygen)" OFF)
option(CHECK_DATABASE "Run database in full check mode (very slow)" OFF) option(CHECK_DATABASE "Run database in full check mode (very slow)" OFF)
@ -24,6 +24,7 @@
find_package(VLSISAPD REQUIRED) find_package(VLSISAPD REQUIRED)
find_package(HURRICANE REQUIRED) find_package(HURRICANE REQUIRED)
find_package(CORIOLIS REQUIRED) find_package(CORIOLIS REQUIRED)
find_package(ETESIAN REQUIRED)
find_package(Doxygen) find_package(Doxygen)
add_subdirectory(src) add_subdirectory(src)

View File

@ -26,7 +26,7 @@ IF(UNIX)
FIND_LIBRARY(ANABATIC_LIBRARY_PATH FIND_LIBRARY(ANABATIC_LIBRARY_PATH
NAMES anabatic NAMES anabatic
PATHS ${CORIOLIS_DIR_SEARCH} PATHS ${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES lib${LIB_SUFFIX} PATH_SUFFIXES lib64 lib
# Help the user find it if we cannot. # Help the user find it if we cannot.
DOC "The ${ANABATIC_INCLUDE_PATH_DESCRIPTION}" DOC "The ${ANABATIC_INCLUDE_PATH_DESCRIPTION}"
) )

View File

@ -20,15 +20,18 @@
#include "hurricane/Error.h" #include "hurricane/Error.h"
#include "hurricane/Warning.h" #include "hurricane/Warning.h"
#include "hurricane/Breakpoint.h" #include "hurricane/Breakpoint.h"
#include "hurricane/DataBase.h"
#include "hurricane/RegularLayer.h" #include "hurricane/RegularLayer.h"
#include "hurricane/Horizontal.h" #include "hurricane/Horizontal.h"
#include "hurricane/RoutingPad.h" #include "hurricane/RoutingPad.h"
#include "hurricane/Vertical.h" #include "hurricane/Vertical.h"
#include "hurricane/Cell.h" #include "hurricane/Cell.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/DebugSession.h" #include "hurricane/DebugSession.h"
#include "hurricane/UpdateSession.h" #include "hurricane/UpdateSession.h"
#include "crlcore/RoutingGauge.h" #include "crlcore/RoutingGauge.h"
#include "crlcore/Measures.h" #include "crlcore/Measures.h"
#include "crlcore/Histogram.h"
#include "anabatic/GCell.h" #include "anabatic/GCell.h"
#include "anabatic/AutoContactTerminal.h" #include "anabatic/AutoContactTerminal.h"
#include "anabatic/NetBuilderM2.h" #include "anabatic/NetBuilderM2.h"
@ -119,6 +122,33 @@ namespace {
} }
class NonReducedItem {
public:
inline NonReducedItem ( AutoSegment* segment=NULL, uint32_t nonReduceds=0 );
inline AutoSegment* segment () const;
inline uint32_t nonReduceds () const;
private:
AutoSegment* _segment;
uint32_t _nonReduceds;
};
inline NonReducedItem::NonReducedItem ( AutoSegment* segment, uint32_t nonReduceds )
: _segment (segment)
, _nonReduceds(nonReduceds)
{ }
inline AutoSegment* NonReducedItem::segment () const { return _segment; }
inline uint32_t NonReducedItem::nonReduceds () const { return _nonReduceds; }
bool operator< ( const NonReducedItem& lhs, const NonReducedItem& rhs )
{
int32_t deltaReduceds = (int32_t)lhs.nonReduceds() - (int32_t)rhs.nonReduceds();
if (deltaReduceds > 0) return true; // Most connected first.
if (deltaReduceds < 0) return false;
return lhs.segment()->getId() < rhs.segment()->getId(); // Smallest Id first.
}
} // Anonymous namespace. } // Anonymous namespace.
@ -133,11 +163,13 @@ namespace Anabatic {
using Hurricane::Error; using Hurricane::Error;
using Hurricane::Warning; using Hurricane::Warning;
using Hurricane::Breakpoint; using Hurricane::Breakpoint;
using Hurricane::DataBase;
using Hurricane::RegularLayer; using Hurricane::RegularLayer;
using Hurricane::Component; using Hurricane::Component;
using Hurricane::Horizontal; using Hurricane::Horizontal;
using Hurricane::Vertical; using Hurricane::Vertical;
using Hurricane::NetRoutingExtension; using Hurricane::NetRoutingExtension;
using Hurricane::NetExternalComponents;
using Hurricane::Cell; using Hurricane::Cell;
using Hurricane::DebugSession; using Hurricane::DebugSession;
using Hurricane::UpdateSession; using Hurricane::UpdateSession;
@ -145,6 +177,7 @@ namespace Anabatic {
using CRL::RoutingLayerGauge; using CRL::RoutingLayerGauge;
using CRL::addMeasure; using CRL::addMeasure;
using CRL::getMeasure; using CRL::getMeasure;
using CRL::Histogram;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -168,28 +201,67 @@ namespace Anabatic {
RawGCellsUnder::RawGCellsUnder ( const AnabaticEngine* engine, Segment* segment ) RawGCellsUnder::RawGCellsUnder ( const AnabaticEngine* engine, Segment* segment )
{ {
cdebug_log(112,1) << "RawGCellsUnder::RawGCellsUnder(): " << segment << endl; cdebug_log(112,1) << "RawGCellsUnder::RawGCellsUnder(Segment*): " << segment << endl;
Box gcellsArea = engine->getCell()->getAbutmentBox(); commonCtor( engine, segment->getSourcePosition(), segment->getTargetPosition() );
Point sourcePosition = segment->getSourcePosition();
Point targetPosition = segment->getTargetPosition();
if ( (sourcePosition.getX() > gcellsArea.getXMax()) cdebug_tabw(112,-1);
or (sourcePosition.getY() > gcellsArea.getYMax()) }
or (targetPosition.getX() <= gcellsArea.getXMin())
or (targetPosition.getY() <= gcellsArea.getYMin()) ) {
cerr << Error( "RawGCellsUnder::RawGCellsUnder(): %s is completly outside the GCells area (ignored)." RawGCellsUnder::RawGCellsUnder ( const AnabaticEngine* engine, Point source, Point target )
, getString(segment).c_str() {
cdebug_log(112,1) << "RawGCellsUnder::RawGCellsUnder(Point,Point): s:"
<< source << " t:" << target << endl;
commonCtor( engine, source, target );
cdebug_tabw(112,-1);
}
void RawGCellsUnder::commonCtor ( const AnabaticEngine* engine, Point source, Point target )
{
cdebug_log(112,1) << "RawGCellsUnder::commontCtor(): s:" << source << " t:" << target << endl;
Box gcellsArea = engine->getCell()->getAbutmentBox();
DbU::Unit axis = 0;
Flags side = Flags::NoFlags;
if (source.getY() == target.getY()) {
side = Flags::EastSide;
axis = source.getY();
if (source.getX() > target.getX()) std::swap( source, target );
}
if (source.getX() == target.getX()) {
side = Flags::NorthSide;
axis = source.getX();
if (source.getY() > target.getY()) std::swap( source, target );
}
if (side == Flags::NoFlags) {
cerr << Error( "RawGCellsUnder::commonCtor(): Points are neither horizontally nor vertically aligneds (ignored)."
) << endl; ) << endl;
cdebug_tabw(112,-1); cdebug_tabw(112,-1);
DebugSession::close(); DebugSession::close();
return; return;
} }
DbU::Unit xsource = std::max( sourcePosition.getX(), gcellsArea.getXMin() ); if ( (source.getX() > gcellsArea.getXMax())
DbU::Unit ysource = std::max( sourcePosition.getY(), gcellsArea.getYMin() ); or (source.getY() > gcellsArea.getYMax())
DbU::Unit xtarget = std::min( targetPosition.getX(), gcellsArea.getXMax() ); or (target.getX() <= gcellsArea.getXMin())
DbU::Unit ytarget = std::min( targetPosition.getY(), gcellsArea.getYMax() ); or (target.getY() <= gcellsArea.getYMin()) ) {
cerr << Error( "RawGCellsUnder::commonCtor(): Area is completly outside the GCells area (ignored)."
) << endl;
cdebug_tabw(112,-1);
DebugSession::close();
return;
}
DbU::Unit xsource = std::max( source.getX(), gcellsArea.getXMin() );
DbU::Unit ysource = std::max( source.getY(), gcellsArea.getYMin() );
DbU::Unit xtarget = std::min( target.getX(), gcellsArea.getXMax() );
DbU::Unit ytarget = std::min( target.getY(), gcellsArea.getYMax() );
if (xtarget == gcellsArea.getXMax()) --xtarget; if (xtarget == gcellsArea.getXMax()) --xtarget;
if (ytarget == gcellsArea.getYMax()) --ytarget; if (ytarget == gcellsArea.getYMax()) --ytarget;
@ -198,16 +270,14 @@ namespace Anabatic {
GCell* gtarget = engine->getGCellUnder( xtarget, ytarget ); GCell* gtarget = engine->getGCellUnder( xtarget, ytarget );
if (not gsource) { if (not gsource) {
cerr << Bug( "RawGCellsUnder::RawGCellsUnder(): %s source not under a GCell (ignored)." cerr << Bug( "RawGCellsUnder::RawGCellsUnder(): Source not under a GCell (ignored)."
, getString(segment).c_str()
) << endl; ) << endl;
cdebug_tabw(112,-1); cdebug_tabw(112,-1);
DebugSession::close(); DebugSession::close();
return; return;
} }
if (not gtarget) { if (not gtarget) {
cerr << Bug( "RawGCellsUnder::RawGCellsUnder(): %s target not under a GCell (ignored)." cerr << Bug( "RawGCellsUnder::RawGCellsUnder(): Target not under a GCell (ignored)."
, getString(segment).c_str()
) << endl; ) << endl;
cdebug_tabw(112,-1); cdebug_tabw(112,-1);
DebugSession::close(); DebugSession::close();
@ -221,24 +291,6 @@ namespace Anabatic {
return; return;
} }
Flags side = Flags::NoFlags;
DbU::Unit axis = 0;
Horizontal* horizontal = dynamic_cast<Horizontal*>( segment );
if (horizontal) {
side = Flags::EastSide;
axis = horizontal->getY();
if (horizontal->getSourceX() > horizontal->getTargetX())
std::swap( gsource, gtarget );
} else {
Vertical* vertical = dynamic_cast<Vertical*>( segment );
side = Flags::NorthSide;
axis = vertical->getX();
if (vertical->getSourceY() > vertical->getTargetY())
std::swap( gsource, gtarget );
}
cdebug_log(112,0) << "flags:" << side << " axis:" << DbU::getValueString(axis) << endl; cdebug_log(112,0) << "flags:" << side << " axis:" << DbU::getValueString(axis) << endl;
Edge* edge = gsource->getEdgeAt( side, axis ); Edge* edge = gsource->getEdgeAt( side, axis );
@ -259,19 +311,27 @@ namespace Anabatic {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Anabatic::NetData". // Class : "Anabatic::NetData".
NetData::NetData ( Net* net ) NetData::NetData ( Net* net, AnabaticEngine* anabatic )
: _net (net) : _net (net)
, _state (NetRoutingExtension::get(net)) , _state (NetRoutingExtension::get(net))
, _searchArea() , _searchArea()
, _rpCount (0) , _rpCount (0)
, _diodeCount(0)
, _sparsity (0) , _sparsity (0)
, _flags () , _flags ()
{ {
if (_state and _state->isMixedPreRoute()) return; if (_state and _state->isMixedPreRoute()) return;
Cell* diodeCell = anabatic->getDiodeCell();
for ( RoutingPad* rp : _net->getRoutingPads() ) { for ( RoutingPad* rp : _net->getRoutingPads() ) {
_searchArea.merge( rp->getBoundingBox() ); _searchArea.merge( rp->getBoundingBox() );
++_rpCount; ++_rpCount;
if (diodeCell) {
Plug* plug = dynamic_cast<Plug*>( rp->getPlugOccurrence().getEntity() );
if (plug and (plug->getInstance()->getMasterCell() == diodeCell))
++_diodeCount;
}
} }
_update(); _update();
} }
@ -313,11 +373,15 @@ namespace Anabatic {
, _autoContactLut () , _autoContactLut ()
, _edgeCapacitiesLut() , _edgeCapacitiesLut()
, _blockageNet (cell->getNet("blockagenet")) , _blockageNet (cell->getNet("blockagenet"))
, _diodeCell (NULL)
{ {
_matrix.setCell( cell, _configuration->getSliceHeight() ); _matrix.setCell( cell, _configuration->getSliceHeight() );
Edge::unity = _configuration->getSliceHeight(); Edge::unity = _configuration->getSliceHeight();
if (not _blockageNet) _blockageNet = Net::create( cell, "blockagenet" ); if (not _blockageNet) {
_blockageNet = Net::create( cell, "blockagenet" );
_blockageNet->setType( Net::Type::BLOCKAGE );
}
} }
@ -325,9 +389,17 @@ namespace Anabatic {
{ {
Super::_postCreate(); Super::_postCreate();
_diodeCell = DataBase::getDB()->getCell( getConfiguration()->getDiodeName() );;
if (not _diodeCell) {
cerr << Warning( "AnabaticEngine::_postCreate() Unable to find \"%s\" diode cell."
, getConfiguration()->getDiodeName().c_str()
) << endl;
}
UpdateSession::open(); UpdateSession::open();
GCell::create( this ); GCell::create( this );
UpdateSession::close(); UpdateSession::close();
checkPlacement();
} }
@ -374,6 +446,7 @@ namespace Anabatic {
void AnabaticEngine::_gutAnabatic () void AnabaticEngine::_gutAnabatic ()
{ {
//DebugSession::open( 159, 160 );
openSession(); openSession();
_flags.reset( Flags::DestroyBaseContact|Flags::DestroyBaseSegment ); _flags.reset( Flags::DestroyBaseContact|Flags::DestroyBaseSegment );
@ -381,19 +454,40 @@ namespace Anabatic {
if (_state == EngineDriving) { if (_state == EngineDriving) {
cdebug_log(145,1) << "Saving AutoContacts/AutoSegments." << endl; cdebug_log(145,1) << "Saving AutoContacts/AutoSegments." << endl;
vector<NonReducedItem> reduceds;
size_t fixedSegments = 0; size_t fixedSegments = 0;
size_t sameLayerDoglegs = 0; size_t sameLayerDoglegs = 0;
size_t bloatedStraps = 0;
for ( auto isegment : _autoSegmentLut ) { for ( auto isegment : _autoSegmentLut ) {
if (isegment.second->isFixed()) ++fixedSegments; if (isegment.second->isFixed()) ++fixedSegments;
if (isegment.second->reduceDoglegLayer()) ++sameLayerDoglegs; if (isegment.second->canReduce( Flags::NullLength )) {
//cerr << "push_back() " << (void*)isegment.second << ":" << isegment.second << endl;
reduceds.push_back( NonReducedItem( isegment.second
, isegment.second->getNonReduceds( Flags::NoFlags ) ));
} else {
if (isegment.second->reduceDoglegLayer()) ++sameLayerDoglegs;
}
//if (isegment.second->bloatStackedStrap()) ++bloatedStraps;
}
sort( reduceds.begin(), reduceds.end() );
// cerr << "Reduced segment queue:" << endl;
// for ( size_t i=0 ; i<reduceds.size() ; ++i ) {
// cerr << "| " << setw(3) << i
// << " " << reduceds[i].nonReduceds()
// << " " << reduceds[i].segment() << endl;
// }
for ( auto& item : reduceds ) {
item.segment()->reduce( Flags::NoFlags );
if (item.segment()->reduceDoglegLayer()) ++sameLayerDoglegs;
} }
cmess1 << " o Driving Hurricane data-base." << endl; cmess1 << " o Driving Hurricane data-base." << endl;
cmess1 << Dots::asSizet(" - Active AutoSegments",AutoSegment::getAllocateds()-fixedSegments) << endl; cmess1 << Dots::asSizet(" - Active AutoSegments" ,AutoSegment::getAllocateds()-fixedSegments) << endl;
cmess1 << Dots::asSizet(" - Active AutoContacts",AutoContact::getAllocateds()-fixedSegments*2) << endl; cmess1 << Dots::asSizet(" - Active AutoContacts" ,AutoContact::getAllocateds()-fixedSegments*2) << endl;
cmess1 << Dots::asSizet(" - AutoSegments" ,AutoSegment::getAllocateds()) << endl; cmess1 << Dots::asSizet(" - AutoSegments" ,AutoSegment::getAllocateds()) << endl;
cmess1 << Dots::asSizet(" - AutoContacts" ,AutoContact::getAllocateds()) << endl; cmess1 << Dots::asSizet(" - AutoContacts" ,AutoContact::getAllocateds()) << endl;
cmess1 << Dots::asSizet(" - Same Layer doglegs" ,sameLayerDoglegs) << endl; cmess1 << Dots::asSizet(" - Same Layer doglegs" ,sameLayerDoglegs) << endl;
cmess1 << Dots::asSizet(" - Bloated straps (< minArea)",bloatedStraps ) << endl;
//for ( Net* net : _cell->getNets() ) _saveNet( net ); //for ( Net* net : _cell->getNets() ) _saveNet( net );
@ -416,7 +510,22 @@ namespace Anabatic {
_ovEdges.clear(); _ovEdges.clear();
} }
exportExternalNets();
Session::close(); Session::close();
//DebugSession::close();
}
void AnabaticEngine::exportExternalNets ()
{
for ( Net* net : getCell()->getNets() ) {
if (not net->isExternal()) continue;
if (net->isSupply()) continue;
for ( Segment* segment : net->getSegments() ) {
NetExternalComponents::setExternal( segment );
}
}
} }
@ -424,6 +533,10 @@ namespace Anabatic {
{ return _configuration; } { return _configuration; }
const Configuration* AnabaticEngine::getConfiguration () const
{ return _configuration; }
Interval AnabaticEngine::getUSide ( Flags direction ) const Interval AnabaticEngine::getUSide ( Flags direction ) const
{ {
Interval side; Interval side;
@ -471,6 +584,105 @@ namespace Anabatic {
} }
bool AnabaticEngine::checkPlacement () const
{
bool valid = true;
Box cellAb = getCell()->getAbutmentBox();
for ( Occurrence occurrence : getCell()->getTerminalNetlistInstanceOccurrences() ) {
Instance* instance = static_cast<Instance*>(occurrence.getEntity());
Cell* masterCell = instance->getMasterCell();
string instanceName = occurrence.getCompactString();
instanceName.erase( 0, 1 );
instanceName.erase( instanceName.size()-1 );
Box instanceAb = masterCell->getAbutmentBox();
Transformation instanceTransf = instance->getTransformation();
occurrence.getPath().getTransformation().applyOn( instanceTransf );
instanceTransf.applyOn( instanceAb );
if (not cellAb.contains(instanceAb)) {
valid = false;
cerr << Error( "AnabaticEngine::checkPlacement(): Instance %s is outside top cell abutment box, routing will be incomplete.\n"
" (cell:%s vs instance:%s)"
, instanceName.c_str()
, getString(cellAb ).c_str()
, getString(instanceAb).c_str()
) << endl;
}
}
size_t errorCount = 0;
ostringstream errors;
errors << "AnabaticEngine::checkPlacement():\n";
for ( Net* net: getCell()->getNets() ) {
for ( RoutingPad* rp : net->getRoutingPads() ) {
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
if (not pin) continue;
ostringstream pinError;
Point pinCenter = rp->getCenter();
if ( (pin->getAccessDirection() == Pin::AccessDirection::NORTH)
or (pin->getAccessDirection() == Pin::AccessDirection::SOUTH) ) {
if (pin->getLayer() != getConfiguration()->getDVerticalLayer()) {
pinError << " Should be in vertical routing layer, "
<< "pin:" << pin->getLayer()->getName()
<< " vs gauge:" << getConfiguration()->getDVerticalLayer()->getName()
<< "\n";
valid = false;
++errorCount;
}
if ((pinCenter.getX() - getCell()->getAbutmentBox().getXMin()
- getConfiguration()->getDVerticalOffset())
% getConfiguration()->getDVerticalPitch()) {
pinError << " Misaligned, "
<< "pin:" << DbU::getValueString(pinCenter.getX())
<< " vs gauge, pitch:" << DbU::getValueString(getConfiguration()->getDVerticalPitch ())
<< ", offset:" << DbU::getValueString(getConfiguration()->getDVerticalOffset())
<< "\n";
valid = false;
++errorCount;
}
}
if ( (pin->getAccessDirection() == Pin::AccessDirection::EAST)
or (pin->getAccessDirection() == Pin::AccessDirection::WEST) ) {
if (pin->getLayer() != getConfiguration()->getDHorizontalLayer()) {
pinError << " Should be in horizontal routing layer, "
<< "pin:" << pin->getLayer()->getName()
<< " vs gauge:" << getConfiguration()->getDHorizontalLayer()->getName()
<< "\n";
valid = false;
++errorCount;
}
if ((pinCenter.getY() - getCell()->getAbutmentBox().getYMin()
- getConfiguration()->getDHorizontalOffset())
% getConfiguration()->getDHorizontalPitch()) {
pinError << " Misaligned, "
<< "pin:" << DbU::getValueString(pinCenter.getY())
<< " vs gauge, pitch:" << DbU::getValueString(getConfiguration()->getDHorizontalPitch ())
<< ", offset:" << DbU::getValueString(getConfiguration()->getDHorizontalOffset())
<< "\n";
valid = false;
++errorCount;
}
}
if (not pinError.str().empty()) {
errors << "On " << pin << "\n" << pinError.str();
}
}
}
if (errorCount) throw Error( errors.str() );
return valid;
}
void AnabaticEngine::openSession () void AnabaticEngine::openSession ()
{ Session::_open(this); } { Session::_open(this); }
@ -489,10 +701,18 @@ namespace Anabatic {
void AnabaticEngine::setupNetDatas () void AnabaticEngine::setupNetDatas ()
{ {
Histogram netHistogram ( 0.0, 1.0, 1 );
netHistogram.setTitle ( "RoutingPads", 0 );
netHistogram.setColor ( "green" , 0 );
netHistogram.setIndent( " " , 0 );
size_t oindex = _netOrdering.size(); size_t oindex = _netOrdering.size();
for ( Net* net : _cell->getNets() ) { for ( Net* net : _cell->getNets() ) {
if (_netDatas.find(net->getId()) != _netDatas.end()) continue; if (_netDatas.find(net->getId()) != _netDatas.end()) continue;
_netOrdering.push_back( new NetData(net) ); NetData* data = new NetData( net, this );
_netOrdering.push_back( data );
netHistogram.addSample( (float)(data->getRpCount() - data->getDiodeRpCount()), 0 );
} }
for ( ; oindex < _netOrdering.size() ; ++oindex ) { for ( ; oindex < _netOrdering.size() ; ++oindex ) {
@ -501,6 +721,9 @@ namespace Anabatic {
} }
sort( _netOrdering.begin(), _netOrdering.end(), SparsityOrder() ); sort( _netOrdering.begin(), _netOrdering.end(), SparsityOrder() );
cmess2 << " o Nets Histogram." << endl;
cmess2 << netHistogram.toString(0) << endl;
} }
@ -567,7 +790,7 @@ namespace Anabatic {
NetData* data = NULL; NetData* data = NULL;
NetDatas::iterator idata = _netDatas.find( net->getId() ); NetDatas::iterator idata = _netDatas.find( net->getId() );
if (idata == _netDatas.end()) { if (idata == _netDatas.end()) {
data = new NetData( net ); data = new NetData( net, this );
_netDatas.insert( make_pair(net->getId(),data) ); _netDatas.insert( make_pair(net->getId(),data) );
_netOrdering.push_back( data ); _netOrdering.push_back( data );
// cerr << Bug( "AnabaticEngine::getNetData() - %s is missing in NetDatas table." // cerr << Bug( "AnabaticEngine::getNetData() - %s is missing in NetDatas table."
@ -851,6 +1074,17 @@ namespace Anabatic {
UpdateSession::open(); UpdateSession::open();
for ( GCell* gcell : _gcells ) gcell->cleanupGlobal(); for ( GCell* gcell : _gcells ) gcell->cleanupGlobal();
UpdateSession::close(); UpdateSession::close();
for ( Net* net : getCell()->getNets() ) {
for ( Component* component : net->getComponents() ) {
if (getConfiguration()->isGLayer(component->getLayer())) {
cerr << Error( "AnabaticEngine::cleanupGlobal(): Remaining global routing,\n"
" %s"
, getString(component).c_str()
) << endl;
}
}
}
} }
@ -862,6 +1096,8 @@ namespace Anabatic {
if (_state > EngineGlobalLoaded) if (_state > EngineGlobalLoaded)
throw Error ("AnabaticEngine::loadGlobalRouting() : global routing already loaded."); throw Error ("AnabaticEngine::loadGlobalRouting() : global routing already loaded.");
antennaProtect();
if (method == EngineLoadGrByNet ) { _loadGrByNet(); } if (method == EngineLoadGrByNet ) { _loadGrByNet(); }
else { else {
throw Error( badMethod, "Anabatic::loadGlobalRouting()", method, getString(_cell).c_str() ); throw Error( badMethod, "Anabatic::loadGlobalRouting()", method, getString(_cell).c_str() );
@ -878,7 +1114,7 @@ namespace Anabatic {
{ {
openSession(); openSession();
DbU::Unit pitch3 = Session::getPitch( 2 ); //DbU::Unit pitch3 = Session::getPitch( 2 );
AutoSegment::IdSet constraineds; AutoSegment::IdSet constraineds;
AutoSegment::IdSet processeds; AutoSegment::IdSet processeds;
@ -1005,7 +1241,10 @@ namespace Anabatic {
//AutoSegment::setShortNetMode( true ); //AutoSegment::setShortNetMode( true );
++shortNets; ++shortNets;
} }
if (NetRoutingExtension::isAutomaticGlobalRoute(net)) { if (NetRoutingExtension::isManualDetailRoute(net))
continue;
if ( NetRoutingExtension::isManualGlobalRoute(net)
or NetRoutingExtension::isAutomaticGlobalRoute(net)) {
DebugSession::open( net, 145, 150 ); DebugSession::open( net, 145, 150 );
AutoSegment::setAnalogMode( NetRoutingExtension::isAnalog(net) ); AutoSegment::setAnalogMode( NetRoutingExtension::isAnalog(net) );
@ -1039,8 +1278,8 @@ namespace Anabatic {
printMeasures( "load" ); printMeasures( "load" );
addMeasure<size_t>( getCell(), "Globals", AutoSegment::getGlobalsCount() ); addMeasure<size_t>( "Globals", AutoSegment::getGlobalsCount() );
addMeasure<size_t>( getCell(), "Edges" , AutoSegment::getAllocateds() ); addMeasure<size_t>( "Edges" , AutoSegment::getAllocateds() );
} }
@ -1176,7 +1415,7 @@ namespace Anabatic {
set<const Layer*> connectedLayers; set<const Layer*> connectedLayers;
forEach ( Segment*, segment, net->getSegments() ) { forEach ( Segment*, segment, net->getSegments() ) {
if (segment->getLength()) { if (segment->getAnchoredLength()) {
if (net->isExternal()) { if (net->isExternal()) {
NetExternalComponents::setExternal( *segment ); NetExternalComponents::setExternal( *segment );
} }
@ -1393,6 +1632,83 @@ namespace Anabatic {
} }
void AnabaticEngine::computeEdgeCapacities ( int maxHCap, int maxVCap, int termSatThreshold, int maxTermSat )
{
vector<RoutingPad*> rps;
vector<GCell*> saturateds;
const vector<NetData*>& netDatas = getNetOrdering();
for ( NetData* netData : netDatas ) {
for ( Component* component : netData->getNet()->getComponents() ) {
RoutingPad* rp = dynamic_cast<RoutingPad*>( component );
if (rp) rps.push_back( rp );
}
}
UpdateSession::open();
for ( auto rp : rps ) {
if (not getConfiguration()->selectRpComponent(rp))
cerr << Warning( "AnabaticEngine::computeEdgeCapacities(): %s has no components on grid.", getString(rp).c_str() ) << endl;
Point center = rp->getBoundingBox().getCenter();
GCell* gcell = getGCellUnder( center );
if (not gcell) {
cerr << Error( "AnabaticEngine::computeEdgeCapacities(): %s\n"
" @%s of %s is not under any GCell.\n"
" It will be ignored so the edge capacity estimate may be wrong."
, getString(rp).c_str()
, getString(center).c_str()
, getString(rp->getNet()).c_str()
) << endl;
continue;
}
gcell->incRpCount( 1 );
if (gcell->getRpCount() == termSatThreshold) saturateds.push_back( gcell );
}
for ( GCell* gcell : getGCells() ) {
if (not gcell->isMatrix()) continue;
for ( Edge* edge : gcell->getEdges(Flags::EastSide|Flags::NorthSide) ) {
GCell* opposite = edge->getOpposite( gcell );
int maxReserved = maxHCap;
int reserved = std::max( gcell->getRpCount(), opposite->getRpCount() );
if (edge->isVertical()) maxReserved = maxVCap;
edge->reserveCapacity( std::min( maxReserved, reserved ) );
}
}
for ( GCell* gcell : saturateds ) {
GCell* neighbor = gcell;
for ( size_t i=0 ; i<2; ++i ) {
Edge* edge = neighbor->getWestEdge();
if (not edge) break;
if (edge->getReservedCapacity() < (uint32_t)maxTermSat)
edge->reserveCapacity( maxTermSat - edge->getReservedCapacity() );
neighbor = neighbor->getWest();
}
neighbor = gcell;
for ( size_t i=0 ; i<2; ++i ) {
Edge* edge = neighbor->getEastEdge();
if (not edge) break;
if (edge->getReservedCapacity() < (uint32_t)maxTermSat)
edge->reserveCapacity( maxTermSat - edge->getReservedCapacity() );
neighbor = neighbor->getEast();
}
}
UpdateSession::close();
//Breakpoint::stop( 1, "Edge capacities computeds." );
}
void AnabaticEngine::_check ( Net* net ) const void AnabaticEngine::_check ( Net* net ) const
{ {
cdebug_log(149,1) << "Checking " << net << endl; cdebug_log(149,1) << "Checking " << net << endl;

File diff suppressed because it is too large Load Diff

View File

@ -178,6 +178,7 @@ namespace Anabatic {
AutoHorizontal* AutoContact::getHorizontal2 () const { return NULL; } AutoHorizontal* AutoContact::getHorizontal2 () const { return NULL; }
AutoVertical* AutoContact::getVertical1 () const { return NULL; } AutoVertical* AutoContact::getVertical1 () const { return NULL; }
AutoVertical* AutoContact::getVertical2 () const { return NULL; } AutoVertical* AutoContact::getVertical2 () const { return NULL; }
bool AutoContact::isOnPin () const { return false; }
void AutoContact::getDepthSpan ( size_t& minDepth, size_t& maxDepth ) const void AutoContact::getDepthSpan ( size_t& minDepth, size_t& maxDepth ) const
@ -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 ) void AutoContact::getLengths ( DbU::Unit* lengths, AutoSegment::DepthLengthSet& processeds )
{ {
DbU::Unit hSideLength = getGCell()->getSide( Flags::Horizontal ).getSize(); DbU::Unit hSideLength = getGCell()->getSide( Flags::Horizontal ).getSize();
@ -212,14 +227,17 @@ namespace Anabatic {
size_t depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer()); size_t depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer());
DbU::Unit length; DbU::Unit length;
if (segment->isLocal()) { if (segment->isLocal()) {
length = segment->getLength(); length = segment->getAnchoredLength();
lengths[depth] += length; lengths[depth] += length;
DbU::Unit sideLength = (segment->isHorizontal()) ? hSideLength : vSideLength; DbU::Unit sideLength = (segment->isHorizontal()) ? hSideLength : vSideLength;
if ( not segment->isUnbound() and (abs(length) > sideLength) ) if ( not segment->isUnbound() and (abs(length) > sideLength) )
cerr << Error("Suspicious length:%.2f of %s." cerr << Error( "AutoContact::getLength(): Suspicious length %s (> %s) of %s.\n"
,DbU::getValueString(length).c_str() " (on: %s)"
,getString(segment).c_str()) << endl; , DbU::getValueString(length).c_str()
, DbU::getValueString(sideLength).c_str()
, getString(segment).c_str()
, getString(this).c_str()) << endl;
} else { } else {
if (segment->isHorizontal()) { if (segment->isHorizontal()) {
if (isSourceHook) if (isSourceHook)
@ -274,11 +292,11 @@ namespace Anabatic {
void AutoContact::invalidate ( Flags flags ) void AutoContact::invalidate ( Flags flags )
{ {
if (flags & Flags::Topology ) setFlags( CntInvalidatedCache );
if (not isInvalidated()) { if (not isInvalidated()) {
cdebug_log(145,1) << "AutoContact::invalidate() - " << this << endl; cdebug_log(145,1) << "AutoContact::invalidate() - " << this << endl;
cdebug_log(145,0) << "flags:" << flags.asString(FlagsFunction) << endl; cdebug_log(145,0) << "flags:" << flags.asString(FlagsFunction) << endl;
setFlags( CntInvalidated ); setFlags( CntInvalidated );
if (flags & Flags::Topology ) setFlags( CntInvalidatedCache );
Session::invalidate( this ); Session::invalidate( this );
_invalidate( flags ); _invalidate( flags );
@ -456,12 +474,13 @@ namespace Anabatic {
void AutoContact::setConstraintBox ( const Box& box ) void AutoContact::setConstraintBox ( const Box& box )
{ {
cdebug_log(149,0) << "setConstraintBox() " << this << " " << getConstraintBox()
<< " from:" << box << endl;
setCBXMin ( box.getXMin() ); setCBXMin ( box.getXMin() );
setCBXMax ( box.getXMax() ); setCBXMax ( box.getXMax() );
setCBYMin ( box.getYMin() ); setCBYMin ( box.getYMin() );
setCBYMax ( box.getYMax() ); setCBYMax ( box.getYMax() );
cdebug_log(149,0) << "setConstraintBox() - " << this << " " << getConstraintBox() cdebug_log(149,0) << "setConstraintBox() " << this << " " << getConstraintBox() << endl;
<< " from:" << box << endl;
cdebug_log(149,0) << "* " << _gcell << endl; cdebug_log(149,0) << "* " << _gcell << endl;
} }
@ -554,15 +573,25 @@ namespace Anabatic {
void AutoContact::setLayerAndWidth ( size_t delta, size_t depth ) 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) { if (delta == 0) {
setLayer( Session::getRoutingLayer(depth) ); setLayer( Session::getRoutingLayer(depth) );
setSizes( Session::getWireWidth (depth) if (Session::getDirection(depth) & Flags::Horizontal) {
, Session::getWireWidth (depth) ); setSizes( Session::getPWireWidth(depth)
, Session::getWireWidth (depth) );
} else {
setSizes( Session::getWireWidth (depth)
, Session::getPWireWidth(depth) );
}
} else { } else {
setLayer( Session::getContactLayer(depth) ); setLayer( Session::getContactLayer(depth) );
setSizes( Session::getViaWidth (depth) setSizes( Session::getViaWidth (depth)
, Session::getViaWidth (depth) ); , Session::getViaWidth (depth) );
} }
cdebug_tabw(145,-1);
} }

View File

@ -29,6 +29,7 @@
#include "hurricane/RoutingPad.h" #include "hurricane/RoutingPad.h"
#include "hurricane/Vertical.h" #include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h" #include "hurricane/Horizontal.h"
#include "hurricane/Pin.h"
#include "hurricane/DebugSession.h" #include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h" #include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactTerminal.h" #include "anabatic/AutoContactTerminal.h"
@ -47,6 +48,7 @@ namespace Anabatic {
using Hurricane::Transformation; using Hurricane::Transformation;
using Hurricane::Entity; using Hurricane::Entity;
using Hurricane::Occurrence; using Hurricane::Occurrence;
using Hurricane::Pin;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -129,6 +131,13 @@ namespace Anabatic {
} }
bool AutoContactTerminal::isOnPin () const
{
RoutingPad* rp = dynamic_cast<RoutingPad*>( getAnchor() );
return (dynamic_cast<Pin*>(rp->getOccurrence().getEntity()) != NULL);
}
AutoSegment* AutoContactTerminal::getOpposite ( const AutoSegment* ) const AutoSegment* AutoContactTerminal::getOpposite ( const AutoSegment* ) const
{ return NULL; } { return NULL; }
@ -194,7 +203,7 @@ namespace Anabatic {
// SxLib bug: METAL1 terminal segments are 0.5 lambdas too shorts on // SxLib bug: METAL1 terminal segments are 0.5 lambdas too shorts on
// their extremities. Should modificate all the standard cells layout... // their extremities. Should modificate all the standard cells layout...
// HARDCODED. // HARDCODED.
if (Session::getRoutingGauge()->getName() == "msxlib") if (getString(Session::getRoutingGauge()->getName()).substr(0,6) == "msxlib")
yborder -= DbU::fromLambda( 1.0 ); yborder -= DbU::fromLambda( 1.0 );
else else
yborder -= DbU::fromLambda( 0.5 ); yborder -= DbU::fromLambda( 0.5 );
@ -337,7 +346,7 @@ namespace Anabatic {
void AutoContactTerminal::cacheDetach ( AutoSegment* segment ) void AutoContactTerminal::cacheDetach ( AutoSegment* segment )
{ {
if (_segment == segment) { if (_segment == segment) {
_segment->unsetFlags( AutoSegment::SegAxisSet ); //_segment->unsetFlags( AutoSegment::SegAxisSet );
_segment = NULL; _segment = NULL;
setFlags( CntInvalidatedCache ); setFlags( CntInvalidatedCache );
unsetFlags( CntDrag ); unsetFlags( CntDrag );
@ -497,8 +506,11 @@ namespace Anabatic {
DbU::Unit y = perpandicular->getAxis(); DbU::Unit y = perpandicular->getAxis();
y = std::min( y, getCBYMax() ); y = std::min( y, getCBYMax() );
y = std::max( y, getCBYMin() ); y = std::max( y, getCBYMin() );
setY( y ); Point onGrid = Session::getNearestGridPoint( Point(getX(),y), getConstraintBox() );
cdebug_log(145,0) << "Draging to Y @" << DbU::getValueString(y) << endl; setY( onGrid.getY() );
cdebug_log(145,0) << "Draging to Y @" << DbU::getValueString(y)
<< " pitched:" << DbU::getValueString(onGrid.getY())
<< " " << getConstraintBox() << endl;
} }
} }

View File

@ -88,8 +88,17 @@ namespace Anabatic {
AutoSegment* AutoContactTurn::getPerpandicular ( const AutoSegment* reference ) const AutoSegment* AutoContactTurn::getPerpandicular ( const AutoSegment* reference ) const
{ {
cdebug_log(149,0) << _getTypeName() << "::getPerpandicular() " << this
<< " to:" << reference << endl;
cdebug_log(149,0) << "| _horizontal1:" << _horizontal1 << endl;
cdebug_log(149,0) << "| _vertical1 :" << _vertical1 << endl;
if (reference == _horizontal1) return _vertical1; if (reference == _horizontal1) return _vertical1;
if (reference == _vertical1 ) return _horizontal1; if (reference == _vertical1 ) return _horizontal1;
cdebug_log(149,0) << _getTypeName() << "::getPerpandicular() " << this
<< " to:" << reference << " failed." << endl;
return NULL; return NULL;
} }
@ -117,6 +126,9 @@ namespace Anabatic {
void AutoContactTurn::cacheDetach ( AutoSegment* segment ) void AutoContactTurn::cacheDetach ( AutoSegment* segment )
{ {
cdebug_log(149,0) << _getTypeName() << "::cacheDetach() " << this
<< " from:" << segment << endl;
if (segment == _horizontal1) _horizontal1 = NULL; if (segment == _horizontal1) _horizontal1 = NULL;
else if (segment == _vertical1) _vertical1 = NULL; else if (segment == _vertical1) _vertical1 = NULL;
else return; else return;
@ -127,6 +139,9 @@ namespace Anabatic {
void AutoContactTurn::cacheAttach ( AutoSegment* segment ) void AutoContactTurn::cacheAttach ( AutoSegment* segment )
{ {
cdebug_log(149,0) << _getTypeName() << "::cacheAttach() " << this
<< " to:" << segment << endl;
if (segment->getDirection() == Flags::Horizontal) { if (segment->getDirection() == Flags::Horizontal) {
if (_horizontal1) { if (_horizontal1) {
cerr << Bug( "%s::cacheAttach() On %s,\n" cerr << Bug( "%s::cacheAttach() On %s,\n"
@ -239,7 +254,7 @@ namespace Anabatic {
RoutingGauge* rg = Session::getRoutingGauge(); RoutingGauge* rg = Session::getRoutingGauge();
size_t depthH1 = rg->getLayerDepth( getHorizontal1()->getLayer() ); size_t depthH1 = rg->getLayerDepth( getHorizontal1()->getLayer() );
size_t depthV1 = rg->getLayerDepth( getVertical1 ()->getLayer() ); size_t depthV1 = rg->getLayerDepth( getVertical1 ()->getLayer() );
size_t depthContact = (depthH1 < depthV1) ? depthH1 : depthH1-1; size_t depthContact = (depthH1 <= depthV1) ? depthH1 : depthH1-1;
size_t delta = abssub ( depthH1, depthV1 ); size_t delta = abssub ( depthH1, depthV1 );
unsetFlags( CntWeakTerminal ); unsetFlags( CntWeakTerminal );
@ -247,7 +262,7 @@ namespace Anabatic {
showTopologyError( "Sheared Turn, layer delta exceed 3." ); showTopologyError( "Sheared Turn, layer delta exceed 3." );
setFlags( CntBadTopology ); setFlags( CntBadTopology );
} else { } else {
if (delta == 3) { if (delta > 1) {
if (_horizontal1->isInvalidatedLayer()) { if (_horizontal1->isInvalidatedLayer()) {
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) ); //_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
_horizontal1->makeDogleg(this); _horizontal1->makeDogleg(this);
@ -259,7 +274,7 @@ namespace Anabatic {
} }
depthH1 = rg->getLayerDepth( _horizontal1->getLayer() ); depthH1 = rg->getLayerDepth( _horizontal1->getLayer() );
depthV1 = rg->getLayerDepth( _vertical1->getLayer() ); depthV1 = rg->getLayerDepth( _vertical1->getLayer() );
depthContact = (depthH1 < depthV1) ? depthH1 : depthH1-1; depthContact = (depthH1 <= depthV1) ? depthH1 : depthH1-1;
delta = abssub ( depthH1, depthV1 ); delta = abssub ( depthH1, depthV1 );
} }

View File

@ -47,8 +47,8 @@ namespace Anabatic {
Segment* AutoHorizontal::base () { return _horizontal; } Segment* AutoHorizontal::base () { return _horizontal; }
Segment* AutoHorizontal::base () const { return _horizontal; } Segment* AutoHorizontal::base () const { return _horizontal; }
Horizontal* AutoHorizontal::getHorizontal () { return _horizontal; } Horizontal* AutoHorizontal::getHorizontal () { return _horizontal; }
DbU::Unit AutoHorizontal::getSourceU () const { return _horizontal->getSourceX(); } DbU::Unit AutoHorizontal::getSourceU () const { return _horizontal->getSource()->getX(); }
DbU::Unit AutoHorizontal::getTargetU () const { return _horizontal->getTargetX(); } DbU::Unit AutoHorizontal::getTargetU () const { return _horizontal->getTarget()->getX(); }
DbU::Unit AutoHorizontal::getDuSource () const { return _horizontal->getDxSource(); } DbU::Unit AutoHorizontal::getDuSource () const { return _horizontal->getDxSource(); }
DbU::Unit AutoHorizontal::getDuTarget () const { return _horizontal->getDxTarget(); } DbU::Unit AutoHorizontal::getDuTarget () const { return _horizontal->getDxTarget(); }
Interval AutoHorizontal::getSpanU () const { return Interval(_horizontal->getSourceX(),_horizontal->getTargetX()); } Interval AutoHorizontal::getSpanU () const { return Interval(_horizontal->getSourceX(),_horizontal->getTargetX()); }
@ -93,6 +93,14 @@ namespace Anabatic {
mergeNativeMax( gcell->getConstraintYMax() ); mergeNativeMax( gcell->getConstraintYMax() );
} }
} }
// if (getId() == 1518590) {
// cerr << "AutoHorizontal::_postCreate(): " << this << endl;
// cerr << "| Source contact:" << source << endl;
// cerr << "| Source GCell: " << getGCell() << endl;
// cerr << "| Target contact:" << target << endl;
// cerr << "| Target GCell: " << target->getGCell() << endl;
// }
} }
@ -224,13 +232,15 @@ namespace Anabatic {
gcell = gcell->getEast( yprobe ); gcell = gcell->getEast( yprobe );
if (not gcell) { if (not gcell) {
success = false; success = false;
cerr << Error( "AutoHorizontal::getGCells() : NULL GCell under %s\n" if (not isCreated()) {
" begin:%s\n" cerr << Error( "AutoHorizontal::getGCells() : NULL GCell under %s\n"
" end: %s" " begin:%s\n"
, getString(this).c_str() " end: %s"
, getString(getAutoSource()->getGCell()).c_str() , getString(this).c_str()
, getString(getAutoTarget()->getGCell()).c_str() , getString(getAutoSource()->getGCell()).c_str()
) << endl; , getString(getAutoTarget()->getGCell()).c_str()
) << endl;
}
break; break;
} }
@ -245,24 +255,35 @@ namespace Anabatic {
{ {
cdebug_tabw(149,1); cdebug_tabw(149,1);
Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Vertical ); AutoContact* source = getAutoSource();
Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Vertical ); AutoContact* target = getAutoTarget();
Interval sourceConstraints = Interval(getAutoSource()->getCBYMin(),getAutoSource()->getCBYMax()); if (source->isOnPin() or target->isOnPin()) { cdebug_tabw(149,-1); return false; }
Interval targetConstraints = Interval(getAutoTarget()->getCBYMin(),getAutoTarget()->getCBYMax());
Interval sourceSide = source->getGCell()->getSide( Flags::Vertical );
Interval targetSide = target->getGCell()->getSide( Flags::Vertical );
Interval sourceConstraints = Interval(source->getCBYMin(),source->getCBYMax());
Interval targetConstraints = Interval(target->getCBYMin(),target->getCBYMax());
bool sourceGoStraight = source->getGCell()->isGoStraight();
bool targetGoStraight = target->getGCell()->isGoStraight();
// Expand by a tiny amount for the "contains" to work for sure. // Expand by a tiny amount for the "contains" to work for sure.
sourceConstraints.inflate( 1 ); sourceConstraints.inflate( 1 );
targetConstraints.inflate( 1 ); targetConstraints.inflate( 1 );
cdebug_log(149,0) << "source " << getAutoSource() << endl; cdebug_log(149,0) << "source " << source << endl;
cdebug_log(149,0) << "source constraints: " << sourceConstraints cdebug_log(149,0) << "source constraints: " << sourceConstraints
<< " " << DbU::getValueString(sourceConstraints.getSize()) << endl; << " " << DbU::getValueString(sourceConstraints.getSize()) << endl;
cdebug_log(149,0) << "target " << getAutoTarget() << endl; cdebug_log(149,0) << "target " << target << endl;
cdebug_log(149,0) << "target constraints: " << targetConstraints cdebug_log(149,0) << "target constraints: " << targetConstraints
<< " " << DbU::getValueString(targetConstraints.getSize()) << endl; << " " << DbU::getValueString(targetConstraints.getSize()) << endl;
if (not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; } if (not sourceGoStraight and not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; }
if (not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; } if (not targetGoStraight and not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; }
if (not isUnbreakable()) {
if (source->isTurn() and (source->getPerpandicular(this)->getLayer() == getLayer())) { cdebug_tabw(149,-1); return true; }
if (target->isTurn() and (target->getPerpandicular(this)->getLayer() == getLayer())) { cdebug_tabw(149,-1); return true; }
}
cdebug_tabw(149,-1); cdebug_tabw(149,-1);
return false; return false;
@ -278,30 +299,52 @@ namespace Anabatic {
const Configuration* configuration = Session::getConfiguration(); const Configuration* configuration = Session::getConfiguration();
const Layer* metal2 = configuration->getRoutingLayer( 1 ); const Layer* metal2 = configuration->getRoutingLayer( 1 );
bool success = false; bool success = false;
bool isMetal2Source = false; bool isMetal2Source = false;
bool isMetal2Target = false; bool isMetal2Target = false;
DbU::Unit height = 0; bool isNonPrefSource = false;
AutoContact* source = getAutoSource(); bool isNonPrefTarget = false;
AutoContact* target = getAutoTarget(); DbU::Unit height = 0;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
bool slackenSource = false;
bool slackenTarget = false;
if (source->isTerminal()) { if (source->isTerminal()) {
height = (static_cast<RoutingPad*>(source->getAnchor()))->getBoundingBox().getHeight(); height = (static_cast<RoutingPad*>(source->getAnchor()))->getBoundingBox().getHeight();
isMetal2Source = (source->getLayer() == metal2); isMetal2Source = (source->getLayer() == metal2);
slackenSource = true;
} }
if (target->isTerminal()) { if (target->isTerminal()) {
height = std::min( height, (static_cast<RoutingPad*>(target->getAnchor()))->getBoundingBox().getHeight() ); height = std::min( height, (static_cast<RoutingPad*>(target->getAnchor()))->getBoundingBox().getHeight() );
isMetal2Target = (target->getLayer() == metal2); isMetal2Target = (target->getLayer() == metal2);
slackenTarget = true;
}
if (source->isTurn() and (source->getPerpandicular(this)->getLayer() == getLayer())) {
isNonPrefSource = true;
slackenSource = true;
} }
if (height >= 4*getPitch()) { cdebug_log(149,0) << "target:" << target << endl;
if (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < 5*getPitch())) cdebug_log(149,0) << "target->getPerpandicular(this):" << target->getPerpandicular(this) << endl;
return false; if (target->isTurn() and (target->getPerpandicular(this)->getLayer() == getLayer())) {
isNonPrefTarget = true;
slackenTarget = true;
} }
cdebug_tabw(149,1); cdebug_tabw(149,1);
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl; cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
cdebug_log(149,0) << "test:" << (getLength() < 5*getPitch()) << endl; cdebug_log(149,0) << "test:" << (getAnchoredLength() < 5*getPitch()) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl; cdebug_log(149,0) << "length:" << DbU::getValueString(getAnchoredLength()) << endl;
if (height >= 4*getPitch()) {
if (not (_flags & (SegGlobal|SegWeakGlobal)) and (getAnchoredLength() < 5*getPitch())) {
cdebug_log(149,0) << "Too short terminal segment to slacken." << endl;
cdebug_tabw(149,-1);
return false;
}
}
int lowSlack = (flags & Flags::HalfSlacken) ? 3 : 10; int lowSlack = (flags & Flags::HalfSlacken) ? 3 : 10;
bool sourceSlackened = false; bool sourceSlackened = false;
@ -310,7 +353,7 @@ namespace Anabatic {
DbU::Unit targetPosition = getTargetPosition(); DbU::Unit targetPosition = getTargetPosition();
AutoSegment* parallel = this; AutoSegment* parallel = this;
if (source->isTerminal()) { if (slackenSource) {
Interval perpandConstraints = getAutoTarget()->getUConstraints(Flags::Horizontal); Interval perpandConstraints = getAutoTarget()->getUConstraints(Flags::Horizontal);
Interval constraints = source->getUConstraints (Flags::Vertical|Flags::NoGCellShrink); Interval constraints = source->getUConstraints (Flags::Vertical|Flags::NoGCellShrink);
Interval nativeConstraints = source->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink); Interval nativeConstraints = source->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink);
@ -322,7 +365,7 @@ namespace Anabatic {
<< " native slack:" << nativeSlack << endl; << " native slack:" << nativeSlack << endl;
cdebug_log(149,0) << "Perpand constraints on target: " << perpandConstraints << endl; cdebug_log(149,0) << "Perpand constraints on target: " << perpandConstraints << endl;
// Ugly: GCell's track number is hardwired. // Ugly: GCell's track number is hardwired.
if ((nativeSlack < lowSlack) or (nativeSlack - slack < 3)) { if (isNonPrefSource or (nativeSlack < lowSlack) or (nativeSlack - slack < 3)) {
cdebug_log(149,0) << "Slackening from Source: " << source << endl; cdebug_log(149,0) << "Slackening from Source: " << source << endl;
_makeDogleg( source->getGCell(), Flags::NoFlags ); _makeDogleg( source->getGCell(), Flags::NoFlags );
sourceSlackened = true; sourceSlackened = true;
@ -350,7 +393,7 @@ namespace Anabatic {
if (parallel) target = parallel->getAutoTarget(); if (parallel) target = parallel->getAutoTarget();
if (target->isTerminal()) { if (slackenTarget) {
Interval constraints = target->getUConstraints (Flags::Vertical|Flags::NoGCellShrink); Interval constraints = target->getUConstraints (Flags::Vertical|Flags::NoGCellShrink);
Interval nativeConstraints = target->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink); Interval nativeConstraints = target->getNativeUConstraints(Flags::Vertical|Flags::NoGCellShrink);
int slack = constraints.getSize() / getPitch(); int slack = constraints.getSize() / getPitch();
@ -360,7 +403,7 @@ namespace Anabatic {
cdebug_log(149,0) << "Target constraint: " << constraints cdebug_log(149,0) << "Target constraint: " << constraints
<< " slack:" << slack << " slack:" << slack
<< " native slack:" << nativeSlack << endl; << " native slack:" << nativeSlack << endl;
if ((nativeSlack < lowSlack) or (nativeSlack - slack < 3)) { if (isNonPrefTarget or (nativeSlack < lowSlack) or (nativeSlack - slack < 3)) {
cdebug_log(149,0) << "Slackening from Target: " << target << endl; cdebug_log(149,0) << "Slackening from Target: " << target << endl;
parallel->_makeDogleg( target->getGCell(), Flags::NoFlags ); parallel->_makeDogleg( target->getGCell(), Flags::NoFlags );
targetSlackened = true; targetSlackened = true;
@ -370,7 +413,15 @@ namespace Anabatic {
const vector<AutoSegment*>& doglegs = Session::getDoglegs(); const vector<AutoSegment*>& doglegs = Session::getDoglegs();
if (targetSlackened and (doglegs.size() >= 2)) { if (targetSlackened and (doglegs.size() >= 2)) {
cdebug_log(149,0) << "AutoHorizontal::_slacken(): Target @" << DbU::getValueString(targetPosition) << endl; GCell* targetGCell = target->getGCell();
Box constraintBox = target->getConstraintBox();
cdebug_log(149,0) << "slacken from Target @" << DbU::getValueString(targetPosition) << endl;
if (targetPosition >= targetGCell->getXMax()) {
cdebug_log(149,0) << "On the rigthmost track, adjust of one P-pitch to the left." << endl;
targetPosition -= getPPitch();
constraintBox.inflate( getPPitch(), 0, 0, 0 );
}
doglegs[doglegs.size()-2]->setAxis( targetPosition ); doglegs[doglegs.size()-2]->setAxis( targetPosition );
success = true; success = true;
@ -378,7 +429,7 @@ namespace Anabatic {
cdebug_log(149,0) << "Fixing on target terminal contact: " cdebug_log(149,0) << "Fixing on target terminal contact: "
<< doglegs[doglegs.size()-2]->getAutoTarget() << endl; << doglegs[doglegs.size()-2]->getAutoTarget() << endl;
//doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntFixed ); //doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntFixed );
doglegs[doglegs.size()-2]->getAutoTarget()->setConstraintBox( target->getConstraintBox() ); doglegs[doglegs.size()-2]->getAutoTarget()->setConstraintBox( constraintBox );
doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntUserNativeConstraints ); doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntUserNativeConstraints );
} }
} }
@ -435,9 +486,18 @@ namespace Anabatic {
void AutoHorizontal::updateOrient () void AutoHorizontal::updateOrient ()
{ {
if (_horizontal->getTargetX() < _horizontal->getSourceX()) { if (_horizontal->getTarget()->getX() < _horizontal->getSource()->getX()) {
cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl; cdebug_log(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; uint64_t spinFlags = _flags & SegDepthSpin;
unsetFlags( SegDepthSpin ); unsetFlags( SegDepthSpin );
@ -461,8 +521,8 @@ namespace Anabatic {
void AutoHorizontal::updatePositions () void AutoHorizontal::updatePositions ()
{ {
_sourcePosition = _horizontal->getSourceX() - getExtensionCap(Flags::Source); _sourcePosition = getSourceU() - getExtensionCap(Flags::Source);
_targetPosition = _horizontal->getTargetX() + getExtensionCap(Flags::Target); _targetPosition = getTargetU() + getExtensionCap(Flags::Target);
} }
@ -482,8 +542,8 @@ namespace Anabatic {
bool AutoHorizontal::checkPositions () const bool AutoHorizontal::checkPositions () const
{ {
bool coherency = true; bool coherency = true;
DbU::Unit sourcePosition = _horizontal->getSourceX() - getExtensionCap(Flags::Source); DbU::Unit sourcePosition = _horizontal->getSource()->getX() - getExtensionCap(Flags::Source);
DbU::Unit targetPosition = _horizontal->getTargetX() + getExtensionCap(Flags::Target); DbU::Unit targetPosition = _horizontal->getTarget()->getX() + getExtensionCap(Flags::Target);
if ( _sourcePosition != sourcePosition ) { if ( _sourcePosition != sourcePosition ) {
cerr << "extensionCap: " << DbU::getValueString(getExtensionCap(Flags::Source)) << endl; cerr << "extensionCap: " << DbU::getValueString(getExtensionCap(Flags::Source)) << endl;
@ -804,9 +864,8 @@ namespace Anabatic {
upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
} }
size_t doglegDepth = depth + ((upLayer)?1:-1); size_t doglegDepth = depth + ((upLayer)?1:-1);
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer( depth + ((upLayer)?0:-1) ); Layer* contactLayer = Session::getRoutingGauge()->getContactLayer( depth + ((upLayer)?0:-1) );
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer( doglegDepth );
Session::dogleg( this ); Session::dogleg( this );
targetDetach(); targetDetach();
@ -831,27 +890,48 @@ namespace Anabatic {
segment2->setFlags( (isSlackened()?SegSlackened:0) ); segment2->setFlags( (isSlackened()?SegSlackened:0) );
Session::dogleg( segment2 ); Session::dogleg( segment2 );
if (autoSource->isTerminal()) { if (autoSource->isTerminal() and autoTarget->isTerminal()) {
segment1->setFlags( SegWeakTerminal1 ); dlContact1->setFlags ( CntWeakTerminal );
segment2->setFlags( SegWeakTerminal1 ); dlContact2->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
} else if (autoSource->isTerminal()) {
autoTarget->unsetFlags( CntWeakTerminal ); autoTarget->unsetFlags( CntWeakTerminal );
dlContact1->setFlags ( CntWeakTerminal ); dlContact1->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
dlContact1->migrateConstraintBox( autoTarget );
} else if (autoTarget->isTerminal()) { } else if (autoTarget->isTerminal()) {
unsetFlags( SegTargetTerminal ); unsetFlags( SegTargetTerminal );
setFlags( SegWeakTerminal1 ); setFlags( SegWeakTerminal1 );
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegTargetTerminal );
autoSource->unsetFlags( CntWeakTerminal ); autoSource->unsetFlags( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal ); dlContact2->setFlags ( CntWeakTerminal );
if (autoSource->getGCell() == doglegGCell) if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
dlContact2->migrateConstraintBox( autoSource ); } else if (isWeakTerminal()) {
} else if (isWeakTerminal()) {
segment1->setFlags( SegWeakTerminal1 ); segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 ); segment2->setFlags( SegWeakTerminal1 );
} }
// if (autoSource->isTerminal()) {
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegWeakTerminal1 );
// autoTarget->unsetFlags( CntWeakTerminal );
// dlContact1->setFlags ( CntWeakTerminal );
// if (autoTarget->getGCell() == doglegGCell)
// dlContact1->migrateConstraintBox( autoTarget );
// } else if (autoTarget->isTerminal()) {
// unsetFlags( SegTargetTerminal );
// setFlags( SegWeakTerminal1 );
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegTargetTerminal );
// autoSource->unsetFlags( CntWeakTerminal );
// dlContact2->setFlags ( CntWeakTerminal );
// if (autoSource->getGCell() == doglegGCell)
// dlContact2->migrateConstraintBox( autoSource );
// } else if (isWeakTerminal()) {
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegWeakTerminal1 );
// }
if (isAnalog()) { if (isAnalog()) {
segment1->setFlags( SegAnalog ); segment1->setFlags( SegAnalog );
segment2->setFlags( SegAnalog ); segment2->setFlags( SegAnalog );
@ -871,12 +951,15 @@ namespace Anabatic {
updateNativeConstraints(); updateNativeConstraints();
segment2->updateNativeConstraints(); segment2->updateNativeConstraints();
if ( isLocal()) autoSource->setFlags( AutoContactFlag::CntVDogleg );
if (segment2->isLocal()) autoTarget->setFlags( AutoContactFlag::CntVDogleg );
if (autoTarget->canDrag() and not autoSource->canDrag()) { if (autoTarget->canDrag() and not autoSource->canDrag()) {
if (not autoTarget->getGCell()->isDevice()) { if (not autoTarget->getGCell()->isDevice() and (segment1->getGCell() == autoTarget->getGCell())) {
Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Horizontal); Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Horizontal);
segment1->mergeUserConstraints( dragConstraints ); segment1->mergeUserConstraints( dragConstraints );
cdebug_log(149,0) << "Perpandical has drag constraints: " << dragConstraints << endl; cdebug_log(149,0) << "Perpandicular has drag constraints: " << dragConstraints << endl;
} }
} }

View File

@ -14,6 +14,7 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#include <cmath>
#include "hurricane/DebugSession.h" #include "hurricane/DebugSession.h"
#include "hurricane/Warning.h" #include "hurricane/Warning.h"
#include "hurricane/Bug.h" #include "hurricane/Bug.h"
@ -347,23 +348,25 @@ namespace Anabatic {
if ( deltaUnit < 0 ) return true; // Smallest source first. if ( deltaUnit < 0 ) return true; // Smallest source first.
if ( deltaUnit > 0 ) return false; if ( deltaUnit > 0 ) return false;
deltaUnit = lhs->getLength() - rhs->getLength(); deltaUnit = lhs->getAnchoredLength() - rhs->getAnchoredLength();
if ( deltaUnit > 0 ) return true; // Longest first. if ( deltaUnit > 0 ) return true; // Longest first.
if ( deltaUnit < 0 ) return true; if ( deltaUnit < 0 ) return false;
deltaUnit = lhs->getAxis() - rhs->getAxis(); deltaUnit = lhs->getAxis() - rhs->getAxis();
if ( deltaUnit < 0 ) return true; // Smallest axis first. if ( deltaUnit < 0 ) return true; // Smallest axis first.
if ( deltaUnit > 0 ) return false; if ( deltaUnit > 0 ) return false;
// if ( lhs->isCanonical () xor rhs->isCanonical () ) return lhs->isCanonical(); #if THIS_IS_DISABLED
// if ( lhs->isCollapsed () xor rhs->isCollapsed () ) return rhs->isCollapsed(); if ( lhs->isCanonical () xor rhs->isCanonical () ) return lhs->isCanonical();
// if ( lhs->isSlackenStrap() xor rhs->isSlackenStrap() ) return lhs->isSlackenStrap(); if ( lhs->isCollapsed () xor rhs->isCollapsed () ) return rhs->isCollapsed();
if ( lhs->isSlackenStrap() xor rhs->isSlackenStrap() ) return lhs->isSlackenStrap();
// if ( lhs->isGlobal () xor rhs->isGlobal () ) return lhs->isGlobal(); if ( lhs->isGlobal () xor rhs->isGlobal () ) return lhs->isGlobal();
// if ( lhs->isTerminal () xor rhs->isTerminal () ) return rhs->isTerminal(); if ( lhs->isTerminal () xor rhs->isTerminal () ) return rhs->isTerminal();
// if ( lhs->isHorizontal() xor rhs->isHorizontal() ) return lhs->isHorizontal(); if ( lhs->isHorizontal() xor rhs->isHorizontal() ) return lhs->isHorizontal();
// if ( lhs->isFixed() xor rhs->isFixed() ) return lhs->isFixed(); if ( lhs->isFixed() xor rhs->isFixed() ) return lhs->isFixed();
#endif
return lhs->getId() < rhs->getId(); return lhs->getId() < rhs->getId();
} }
@ -406,6 +409,32 @@ namespace Anabatic {
} }
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegment::CompareByRevalidate".
bool AutoSegment::CompareByRevalidate::operator() ( AutoSegment* lhs, AutoSegment* rhs ) const
{
if (lhs->isNonPref() xor rhs->isNonPref() ) return lhs->isNonPref();
DbU::Unit deltaLength = lhs->getAnchoredLength() - rhs->getAnchoredLength();
if (deltaLength > 0) return true; // Longest length first.
if (deltaLength < 0) return false;
return lhs->getId() < rhs->getId(); // Smallest Id first.
}
bool AutoSegment::CompareByReduceds::operator() ( AutoSegment* lhs, AutoSegment* rhs ) const
{
uint32_t deltaReduceds = lhs->getReduceds() - rhs->getReduceds();
if (deltaReduceds < 0) return true; // Smallest source first.
if (deltaReduceds > 0) return false;
return lhs->getId() < rhs->getId(); // Smallest Id first.
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Anabatic::AutoSegment". // Class : "Anabatic::AutoSegment".
@ -415,7 +444,7 @@ namespace Anabatic {
bool AutoSegment::_analogMode = false; bool AutoSegment::_analogMode = false;
bool AutoSegment::_shortNetMode = false; bool AutoSegment::_shortNetMode = false;
bool AutoSegment::_initialized = false; bool AutoSegment::_initialized = false;
vector< array<DbU::Unit*,3> > AutoSegment::_extensionCaps; vector< array<DbU::Unit*,4> > AutoSegment::_extensionCaps;
void AutoSegment::setAnalogMode ( bool state ) { _analogMode = state; } void AutoSegment::setAnalogMode ( bool state ) { _analogMode = state; }
@ -428,17 +457,19 @@ namespace Anabatic {
//cerr << "AutoSegment::_initialize()" << endl; //cerr << "AutoSegment::_initialize()" << endl;
_initialized = true; _initialized = true;
DbU::Unit twoGrid = DbU::fromGrid( 2 );
for ( size_t depth=0 ; depth<Session::getDepth() ; ++depth ) { for ( size_t depth=0 ; depth<Session::getDepth() ; ++depth ) {
DbU::Unit* viaToTopCap = new DbU::Unit ( 0 ); DbU::Unit* viaToTopCap = new DbU::Unit ( 0 );
DbU::Unit* viaToBottomCap = new DbU::Unit ( 0 ); DbU::Unit* viaToBottomCap = new DbU::Unit ( 0 );
DbU::Unit* viaToSameCap = new DbU::Unit ( 0 ); DbU::Unit* viaToSameCap = new DbU::Unit ( 0 );
DbU::Unit* minimalLength = new DbU::Unit ( 0 );
bool isVertical = (depth == 0) or (Session::getLayerGauge(depth)->isVertical()); bool isVertical = (depth == 0) or (Session::getLayerGauge(depth)->isVertical());
uint32_t flags = (isVertical) ? Layer::EnclosureV : Layer::EnclosureH ; uint32_t flags = (isVertical) ? Layer::EnclosureV : Layer::EnclosureH ;
//cerr << depth << ":" << Session::getLayerGauge(depth)->getLayer()->getName() //cerr << depth << ":" << Session::getLayerGauge(depth)->getLayer()->getName()
// << " isVertical:" << Session::getLayerGauge(depth)->isVertical() << endl; // << " isVertical:" << Session::getLayerGauge(depth)->isVertical() << endl;
*viaToSameCap = Session::getWireWidth(depth)/2; *viaToSameCap = Session::getPWireWidth(depth)/2;
// Bottom metal of the VIA going *up*. // Bottom metal of the VIA going *up*.
const Layer* viaLayer = dynamic_cast<const ViaLayer*>( Session::getContactLayer(depth) ); const Layer* viaLayer = dynamic_cast<const ViaLayer*>( Session::getContactLayer(depth) );
@ -452,6 +483,15 @@ namespace Anabatic {
*viaToBottomCap = Session::getViaWidth(depth-1)/2 + viaLayer->getTopEnclosure( flags ); *viaToBottomCap = Session::getViaWidth(depth-1)/2 + viaLayer->getTopEnclosure( flags );
} }
const Layer* routingLayer = Session::getRoutingLayer( depth );
double minimalArea = routingLayer->getMinimalArea();
if (minimalArea != 0.0) {
*minimalLength = DbU::fromMicrons( minimalArea / DbU::toMicrons( Session::getWireWidth(depth) ) );
DbU::Unit modulo = *minimalLength % twoGrid;
if (modulo)
*minimalLength += twoGrid - modulo;
}
//cerr << " viaToTop width: " << DbU::getValueString( Session::getViaWidth(depth) ) << endl; //cerr << " viaToTop width: " << DbU::getValueString( Session::getViaWidth(depth) ) << endl;
//cerr << " viaToTopCap: " << DbU::getValueString(*viaToTopCap ) << endl; //cerr << " viaToTopCap: " << DbU::getValueString(*viaToTopCap ) << endl;
//if (depth > 0) //if (depth > 0)
@ -459,7 +499,10 @@ namespace Anabatic {
//cerr << " viaToBottomCap: " << DbU::getValueString(*viaToBottomCap) << endl; //cerr << " viaToBottomCap: " << DbU::getValueString(*viaToBottomCap) << endl;
//cerr << " viaToSameCap: " << DbU::getValueString(*viaToSameCap ) << endl; //cerr << " viaToSameCap: " << DbU::getValueString(*viaToSameCap ) << endl;
_extensionCaps.push_back( std::array<DbU::Unit*,3>( { viaToTopCap, viaToBottomCap, viaToSameCap } ) ); _extensionCaps.push_back( std::array<DbU::Unit*,4>( {{ viaToTopCap
, viaToBottomCap
, viaToSameCap
, minimalLength }} ) );
} }
} }
@ -472,6 +515,7 @@ namespace Anabatic {
, _optimalMin (0) , _optimalMin (0)
, _optimalMax (0) , _optimalMax (0)
, _reduceds (0) , _reduceds (0)
, _rpDistance (15)
, _sourcePosition (0) , _sourcePosition (0)
, _targetPosition (0) , _targetPosition (0)
, _userConstraints (false) , _userConstraints (false)
@ -531,6 +575,11 @@ namespace Anabatic {
_observers.notify( Destroy ); _observers.notify( Destroy );
AutoContact* contact = getAutoSource();
if (contact) contact->cacheDetach( this );
contact = getAutoTarget();
if (contact) contact->cacheDetach( this );
Session::unlink( this ); Session::unlink( this );
cdebug_tabw(145,-1); cdebug_tabw(145,-1);
} }
@ -665,6 +714,10 @@ namespace Anabatic {
incReduceds(); incReduceds();
} }
Interval oldSpan = Interval( _sourcePosition, _targetPosition );
if (not expandToMinLength(oldSpan)) {
unexpandToMinLength();
}
updatePositions(); updatePositions();
unsigned int observerFlags = Revalidate; unsigned int observerFlags = Revalidate;
@ -687,11 +740,11 @@ namespace Anabatic {
bool AutoSegment::isStrongTerminal ( Flags flags ) const bool AutoSegment::isStrongTerminal ( Flags flags ) const
{ {
if (_flags & SegStrongTerminal) return true; if (isTerminal()) return true;
if ((flags & Flags::Propagate) and not isNotAligned()) { if ((flags & Flags::Propagate) and not isNotAligned()) {
for ( AutoSegment* segment : const_cast<AutoSegment*>(this)->getAligneds() ) { for ( AutoSegment* segment : const_cast<AutoSegment*>(this)->getAligneds() ) {
if (segment->_flags & SegStrongTerminal) return true; if (segment->isTerminal()) return true;
} }
} }
return false; return false;
@ -717,20 +770,53 @@ namespace Anabatic {
if (getFlags() & SegSourceTop ) cap = getViaToTopCap (depth); if (getFlags() & SegSourceTop ) cap = getViaToTopCap (depth);
else if (getFlags() & SegSourceBottom) cap = getViaToBottomCap(depth); else if (getFlags() & SegSourceBottom) cap = getViaToBottomCap(depth);
else cap = getViaToSameCap (depth); else cap = getViaToSameCap (depth);
cdebug_log(159,0) << "getExtensionCap(): flags:" << getFlags() cdebug_log(150,0) << "getExtensionCap(): (source) flags:" << getFlags()
<< " VIA cap:" << DbU::getValueString(cap) << " VIA cap:" << DbU::getValueString(cap)
<< " " << (getFlags() & SegSourceBottom) << " t:" << (getFlags() & SegSourceBottom)
<< " b:" << (getFlags() & SegSourceTop)
<< endl; << endl;
if (not (flags & Flags::NoSegExt)) {
cdebug_log(150,0) << "duSource=" << DbU::getValueString(getDuSource()) << endl;
if (-getDuSource() > cap) {
cap = -getDuSource();
cdebug_log(150,0) << "-> Custom cap (-duSource):" << DbU::getValueString(cap) << endl;
}
}
} }
if (flags & Flags::Target) { if (flags & Flags::Target) {
if (getFlags() & SegTargetTop ) cap = getViaToTopCap (depth); if (getFlags() & SegTargetTop ) cap = getViaToTopCap (depth);
else if (getFlags() & SegTargetBottom) cap = getViaToBottomCap(depth); else if (getFlags() & SegTargetBottom) cap = getViaToBottomCap(depth);
else cap = getViaToSameCap (depth); else cap = getViaToSameCap (depth);
cdebug_log(150,0) << "getExtensionCap(): (target) flags:" << getFlags()
<< " VIA cap:" << DbU::getValueString(cap)
<< " t:" << (getFlags() & SegSourceBottom)
<< " b:" << (getFlags() & SegSourceTop)
<< endl;
if (not (flags & Flags::NoSegExt)) {
cdebug_log(150,0) << "duTarget=" << DbU::getValueString(getDuTarget()) << endl;
if (getDuTarget() > cap) {
cap = getDuTarget();
cdebug_log(150,0) << "-> Custom cap (+duTarget):" << DbU::getValueString(cap) << endl;
}
}
} }
if (cap < getWidth()/2) cap = getWidth()/2; // if ( not isCreated()
return cap + getLayer()->getMinimalSpacing()/2;; // and not (flags & Flags::NoMinLength)
// and (flags & Flags::Target)
// and (getMinimalLength(depth) != 0.0)
// and isMiddleStack() ) {
// DbU::Unit realLength = getExtensionCap( Flags::Source|Flags::LayerCapOnly|Flags::NoMinLength )
// + getAnchoredLength();
// if (realLength + cap < getMinimalLength(depth)) {
// cap = getMinimalLength(depth) - realLength;
// }
// }
if (getLayer()->isSymbolic() and (cap < getWidth()/2)) cap = getWidth()/2;
if (not (flags & Flags::LayerCapOnly)) cap += getLayer()->getMinimalSpacing()/2;
return cap;
} }
@ -761,8 +847,8 @@ namespace Anabatic {
{ {
cdebug_log(145,0) << "AutoSegment::getCanonical() - " << this << endl; cdebug_log(145,0) << "AutoSegment::getCanonical() - " << this << endl;
min = getSourcePosition (); min = getSourcePosition();
max = getTargetPosition (); max = getTargetPosition();
if (max < min) swap( min, max ); if (max < min) swap( min, max );
@ -775,14 +861,14 @@ namespace Anabatic {
DbU::Unit collapsedMax; DbU::Unit collapsedMax;
if (not isNotAligned()) { if (not isNotAligned()) {
forEach( AutoSegment*, isegment, getAligneds() ) { for ( AutoSegment* segment : getAligneds() ) {
if (isegment->isCanonical()) { if (segment->isCanonical()) {
canonical = *isegment; canonical = segment;
canonicals++; canonicals++;
} }
collapsedMin = isegment->getSourcePosition(); collapsedMin = segment->getSourcePosition();
collapsedMax = isegment->getTargetPosition(); collapsedMax = segment->getTargetPosition();
if (collapsedMax < collapsedMin) swap( collapsedMin, collapsedMax ); if (collapsedMax < collapsedMin) swap( collapsedMin, collapsedMax );
if (collapsedMin < min) min = collapsedMin; if (collapsedMin < min) min = collapsedMin;
if (collapsedMax > max) max = collapsedMax; if (collapsedMax > max) max = collapsedMax;
@ -799,8 +885,8 @@ namespace Anabatic {
int count = 0; int count = 0;
cerr << " " << count++ << ": " << this << endl; cerr << " " << count++ << ": " << this << endl;
forEach( AutoSegment*, isegment, getAligneds() ) for ( AutoSegment* segment : getAligneds() )
cerr << " " << count++ << ": " << *isegment << endl; cerr << " " << count++ << ": " << segment << endl;
} }
} }
@ -1036,6 +1122,10 @@ namespace Anabatic {
cdebug_log(149,1) << "toOptimalAxis() " << this << endl; cdebug_log(149,1) << "toOptimalAxis() " << this << endl;
if (not isCanonical()) { cdebug_tabw(149,-1); return false; } if (not isCanonical()) { cdebug_tabw(149,-1); return false; }
if (not isUnsetAxis()) {
cdebug_tabw(149,-1);
return toConstraintAxis( flags );
}
DbU::Unit constraintMin; DbU::Unit constraintMin;
DbU::Unit constraintMax; DbU::Unit constraintMax;
@ -1071,7 +1161,7 @@ namespace Anabatic {
void AutoSegment::setAxis ( DbU::Unit axis, Flags flags ) void AutoSegment::setAxis ( DbU::Unit axis, Flags flags )
{ {
if (not isCanonical()) return; if (not isCanonical() and not (flags & Flags::Force)) return;
if ( (axis == getAxis()) and not (flags & Flags::Realignate) ) return; if ( (axis == getAxis()) and not (flags & Flags::Realignate) ) return;
@ -1298,7 +1388,7 @@ namespace Anabatic {
if (terminalMin != terminalMax) if (terminalMin != terminalMax)
attractors.addAttractor( terminalMax ); attractors.addAttractor( terminalMax );
} }
} else if (autoSegment->isLongLocal() or (autoSegment->getLength() > getPPitch()*20)) { } else if (autoSegment->isLongLocal() or (autoSegment->getAnchoredLength() > getPPitch()*20)) {
cdebug_log(145,0) << "Used as long global attractor." << endl; cdebug_log(145,0) << "Used as long global attractor." << endl;
DbU::Unit perpandMin = autoSegment->getSourceU(); DbU::Unit perpandMin = autoSegment->getSourceU();
@ -1522,6 +1612,135 @@ namespace Anabatic {
} }
bool AutoSegment::isMiddleStack () const
{
cdebug_log(149,0) << "AutoSegment::isMiddleStack() - " << this << endl;
if (not isCanonical()) return false;
if (isNonPref()) return false;
if (isGlobal()) {
if (getLength() > getPPitch()) return false;
cdebug_log(149,0) << "| Considering this global anyway because it is too short. " << endl;
}
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
if (not source or not target) {
cdebug_log(149,0) << "| false, missing source or target (in creation?). " << endl;
return false;
}
if (isSpinTopOrBottom()) {
cdebug_log(149,0) << "| false, neither spin top nor bottom. " << endl;
return false;
}
if (not (source->isTerminal() xor target->isTerminal())) {
if (source->isTerminal() and target->isTerminal()) {
cdebug_log(149,0) << "| false, source & target are terminals. " << endl;
return false;
}
if (source->isTurn()) {
AutoSegment* perpandicular = source->getPerpandicular( this );
if (perpandicular->isNonPref() and (perpandicular->getAnchoredLength() != 0)) {
cdebug_log(149,0) << "| false, perpandicular is non-pref and non-zero. " << this << endl;
return false;
}
} else if (target->isTurn()) {
AutoSegment* perpandicular = target->getPerpandicular( this );
if (perpandicular->isNonPref() and (perpandicular->getAnchoredLength() != 0)) {
cdebug_log(149,0) << "| false, perpandicular is non-pref and non-zero. " << this << endl;
return false;
}
} else if ((source->isHTee() or target->isHTee()) and isHorizontal()) {
cdebug_log(149,0) << "| false, S/T HTee+Terminal and horizontal. " << this << endl;
return false;
} else if ((source->isVTee() or target->isVTee()) and isVertical()) {
cdebug_log(149,0) << "| false, S/T VTee+Terminal and vertical. " << this << endl;
return false;
}
}
DbU::Unit sourceAxis = 0;
DbU::Unit targetAxis = 0;
getEndAxes( sourceAxis, targetAxis );
if ((targetAxis - sourceAxis) >= getPPitch()) {
cdebug_log(149,0) << "| Canonical axis length superior to P-Pitch " << this << endl;
return false;
}
cdebug_log(149,0) << " Middle stack or terminal bound." << endl;
return true;
}
bool AutoSegment::isUnderMinLength () const
{
return false;
// cdebug_log(149,0) << "AutoSegment::isUnderMinLength() - " << this << endl;
// if (not isMiddleStack()) return false;
// DbU::Unit spanLength = getSpanLength();
// DbU::Unit minimalLength = getMinimalLength( Session::getLayerDepth( getLayer() ));
// cdebug_log(149,0) << " span=" << DbU::getValueString(spanLength)
// << " < min=" << DbU::getValueString(minimalLength)<< endl;
// return spanLength < minimalLength;
}
bool AutoSegment::expandToMinLength ( Interval span )
{
if (not isMiddleStack()) return false;
cdebug_log(149,1) << "AutoSegment::expandToMinLength() " << this << endl;
cdebug_log(149,0) << "In span=" << span << endl;
cdebug_log(149,0) << "Before: [" << DbU::getValueString(getSourceU() - getExtensionCap( Flags::Source|Flags::LayerCapOnly ))
<< " " << DbU::getValueString(getTargetU() + getExtensionCap( Flags::Target|Flags::LayerCapOnly ))
<< "]" << endl;
DbU::Unit sourceCap = getExtensionCap( Flags::Source|Flags::NoSegExt|Flags::LayerCapOnly );
DbU::Unit targetCap = getExtensionCap( Flags::Target|Flags::NoSegExt|Flags::LayerCapOnly );
DbU::Unit segMinLength = getAnchoredLength() + sourceCap + targetCap;
DbU::Unit techMinLength = getMinimalLength( Session::getLayerDepth( getLayer() ));
if (techMinLength <= segMinLength) {
cdebug_log(149,0) << "Above minimal length (" << DbU::getValueString(segMinLength)
<< " >= " << DbU::getValueString(techMinLength) << ")" << endl;
cdebug_tabw(149,-1);
return false;
}
DbU::Unit oneGrid = DbU::fromGrid( 1 );
DbU::Unit targetExpand = (techMinLength - segMinLength) / 2 + targetCap;
DbU::Unit sourceExpand = - (techMinLength - segMinLength) / 2 - sourceCap;
if (targetExpand % oneGrid)
targetExpand += oneGrid - targetExpand % oneGrid;
if (sourceExpand % oneGrid)
sourceExpand -= oneGrid + sourceExpand % oneGrid;
if (not span.isEmpty()) {
DbU::Unit shiftLeft = span.getVMax() - (getTargetU() + targetExpand);
if (shiftLeft < 0) {
targetExpand += shiftLeft;
sourceExpand += shiftLeft;
}
}
setDuSource( sourceExpand );
setDuTarget( targetExpand );
cdebug_log(149,0) << "sourceExpand=" << DbU::getValueString(sourceExpand)
<< " targetExpand=" << DbU::getValueString(targetExpand) << endl;
cdebug_log(149,0) << "After: [" << DbU::getValueString(getSourceU() - getExtensionCap( Flags::Source|Flags::LayerCapOnly ))
<< " " << DbU::getValueString(getTargetU() + getExtensionCap( Flags::Target|Flags::LayerCapOnly ))
<< "] expand:" << DbU::getValueString(techMinLength - segMinLength)<< endl;
setFlags( SegAtMinArea );
cdebug_tabw(149,-1);
return true;
}
bool AutoSegment::unexpandToMinLength ()
{
if (not isAtMinArea()) return false;
cdebug_log(149,0) << "AutoSegment::unexpandToMinLength() " << this << endl;
setDuSource( 0 );
setDuTarget( 0 );
unsetFlags( SegAtMinArea );
return true;
}
bool AutoSegment::isReduceCandidate () const bool AutoSegment::isReduceCandidate () const
{ {
if (isGlobal()) return false; if (isGlobal()) return false;
@ -1537,46 +1756,94 @@ namespace Anabatic {
} }
bool AutoSegment::canReduce () const bool AutoSegment::canReduce ( Flags flags ) const
{ {
if (isGlobal() or isDrag()) return false; cdebug_log(159,0) << "AutoSegment::canReduce():" << this << endl;
cdebug_log(159,0) << " _reduceds:" << _reduceds << endl;
DbU::Unit length = getAnchoredLength();
if (isGlobal() and (length > getPPitch())) return false;
if (isDrag() or isFixed()) return false;
if (not isSpinTopOrBottom()) return false; if (not isSpinTopOrBottom()) return false;
if (_reduceds) return false; if ((getDepth() == 1) and isSpinBottom()) return false;
if ((flags & Flags::WithPerpands) and _reduceds) return false;
AutoContact* source = getAutoSource(); AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget(); AutoContact* target = getAutoTarget();
if (not source->isTurn() or not target->isTurn()) return false; cdebug_log(159,0) << " source:" << source->isHTee() << "+" << source->isVTee() << endl;
cdebug_log(159,0) << " target:" << target->isHTee() << "+" << target->isVTee() << endl;
if ( ((source->isHTee() or target->isHTee()) and isHorizontal())
or ((source->isVTee() or target->isVTee()) and isVertical ()) ) return false;
// if ( source->isHTee() or source->isVTee()
// or target->isHTee() or target->isVTee() ) return false;
cdebug_log(159,0) << " length:" << DbU::getValueString(length) << endl;
if (flags & Flags::NullLength) return (length == 0);
unsigned int perpandicularDepth = getDepth(); unsigned int perpandicularDepth = getDepth();
if (isSpinBottom()) --perpandicularDepth; if (isSpinBottom()) {
else if (isSpinTop()) { if (perpandicularDepth > 0) --perpandicularDepth;
} else if (isSpinTop()) {
++perpandicularDepth; ++perpandicularDepth;
if (perpandicularDepth >= Session::getDepth()) return false; if (perpandicularDepth >= Session::getDepth()) return false;
} else } else
return false; return false;
if (getLength() >= (Session::getPitch(perpandicularDepth) * 2)) return false; if (getAnchoredLength() >= Session::getPitch(perpandicularDepth) * 2) return false;
return true; return true;
} }
bool AutoSegment::reduce () bool AutoSegment::reduce ( Flags flags )
{ {
if (not canReduce()) return false; if (isReduced()) return false;
if (not canReduce(flags)) return false;
cdebug_log(159,0) << "AutoSegment::reduce():" << this << endl;
AutoContact* source = getAutoSource(); AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget(); AutoContact* target = getAutoTarget();
_flags |= SegIsReduced; _flags |= SegIsReduced;
source->getPerpandicular( this )->incReduceds(); for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
target->getPerpandicular( this )->incReduceds(); if (perpandicular == this) continue;
perpandicular->incReduceds();
}
for ( AutoSegment* perpandicular : target->getAutoSegments() ) {
if (perpandicular == this) continue;
perpandicular->incReduceds();
}
return true; return true;
} }
uint32_t AutoSegment::getNonReduceds ( Flags flags ) const
{
if (not canReduce(flags)) return false;
cdebug_log(159,0) << "AutoSegment::getNonReduceds():" << this << endl;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
uint32_t nonReduceds = 0;
for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
if (perpandicular == this) continue;
if (perpandicular->getAnchoredLength()) ++nonReduceds;
}
for ( AutoSegment* perpandicular : target->getAutoSegments() ) {
if (perpandicular == this) continue;
if (perpandicular->getAnchoredLength()) ++nonReduceds;
}
return nonReduceds;
}
bool AutoSegment::mustRaise () const bool AutoSegment::mustRaise () const
{ {
if (not (_flags & SegIsReduced)) return false; if (not (_flags & SegIsReduced)) return false;
@ -1586,20 +1853,29 @@ namespace Anabatic {
else if (isSpinTop ()) ++perpandicularDepth; else if (isSpinTop ()) ++perpandicularDepth;
else return true; else return true;
return (getLength() >= (Session::getPitch(perpandicularDepth) * 2)); return (getAnchoredLength() >= (Session::getPitch(perpandicularDepth) * 2));
} }
bool AutoSegment::raise () bool AutoSegment::raise ()
{ {
if (not (_flags & SegIsReduced)) return false; if (not (_flags & SegIsReduced)) return false;
cdebug_log(159,0) << "AutoSegment::raise():" << this << endl;
AutoContact* source = getAutoSource(); AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget(); AutoContact* target = getAutoTarget();
_flags &= ~SegIsReduced; _flags &= ~SegIsReduced;
source->getPerpandicular( this )->decReduceds(); for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
target->getPerpandicular( this )->decReduceds(); if (perpandicular == this) continue;
cdebug_log(159,0) << "dec PP:" << perpandicular << endl;
perpandicular->decReduceds();
}
for ( AutoSegment* perpandicular : target->getAutoSegments() ) {
if (perpandicular == this) continue;
cdebug_log(159,0) << "dec PP:" << perpandicular << endl;
perpandicular->decReduceds();
}
return true; return true;
} }
@ -1607,6 +1883,8 @@ namespace Anabatic {
void AutoSegment::changeDepth ( unsigned int depth, Flags flags ) void AutoSegment::changeDepth ( unsigned int depth, Flags flags )
{ {
DebugSession::open( getNet(), 145, 150 );
cdebug_log(149,1) << "changeDepth() " << depth << " - " << this << endl; cdebug_log(149,1) << "changeDepth() " << depth << " - " << this << endl;
Session::invalidate( getNet() ); Session::invalidate( getNet() );
@ -1620,6 +1898,8 @@ namespace Anabatic {
} }
cdebug_tabw(149,-1); cdebug_tabw(149,-1);
DebugSession::close();
} }
@ -1632,6 +1912,7 @@ namespace Anabatic {
const Layer* newLayer = Session::getRoutingGauge()->getRoutingLayer(depth); const Layer* newLayer = Session::getRoutingGauge()->getRoutingLayer(depth);
if (getLayer() != newLayer) { if (getLayer() != newLayer) {
cdebug_log(149,0) << "Effective layer change to " << depth << "/" << newLayer << endl;
setLayer( depth ); setLayer( depth );
getAutoSource()->invalidate( Flags::Topology|Flags::NoCheckLayer ); getAutoSource()->invalidate( Flags::Topology|Flags::NoCheckLayer );
getAutoTarget()->invalidate( Flags::Topology|Flags::NoCheckLayer ); getAutoTarget()->invalidate( Flags::Topology|Flags::NoCheckLayer );
@ -1683,8 +1964,8 @@ namespace Anabatic {
if (_canSlacken()) return true; if (_canSlacken()) return true;
if ((flags & Flags::Propagate) and not isNotAligned()) { if ((flags & Flags::Propagate) and not isNotAligned()) {
forEach ( AutoSegment*, isegment, const_cast<AutoSegment*>(this)->getAligneds() ) { for ( AutoSegment* segment : const_cast<AutoSegment*>(this)->getAligneds() ) {
if (isegment->_canSlacken()) return true; if (segment->_canSlacken()) return true;
} }
} }
@ -1741,7 +2022,7 @@ namespace Anabatic {
cdebug_log(149,0) << "AutoSegment::canPivotUp() - " << flags cdebug_log(149,0) << "AutoSegment::canPivotUp() - " << flags
<< " (reserve:" << reserve << ")" << endl; << " (reserve:" << reserve << ")" << endl;
if ( isLayerChange() or isFixed() ) return false; if ( isLayerChange() or isFixed() or isUnbreakable() ) return false;
if ( isStrongTerminal() and (not (flags & Flags::AllowTerminal)) ) return false; if ( isStrongTerminal() and (not (flags & Flags::AllowTerminal)) ) return false;
if ( isLocal() and (not (flags & Flags::AllowLocal )) ) return false; if ( isLocal() and (not (flags & Flags::AllowLocal )) ) return false;
@ -1790,7 +2071,7 @@ namespace Anabatic {
cdebug_log(149,0) << "AutoSegment::canPivotDown()" cdebug_log(149,0) << "AutoSegment::canPivotDown()"
<< " (reserve:" << reserve << ")" << endl; << " (reserve:" << reserve << ")" << endl;
if ( isLayerChange() or isFixed() ) return false; if ( isLayerChange() or isFixed() or isUnbreakable() ) return false;
if ( isStrongTerminal() or isLocal() ) return false; if ( isStrongTerminal() or isLocal() ) return false;
size_t depth = Session::getRoutingGauge()->getLayerDepth( getLayer() ); size_t depth = Session::getRoutingGauge()->getLayerDepth( getLayer() );
@ -1836,11 +2117,17 @@ namespace Anabatic {
{ {
cdebug_log(159,0) << "AutoSegment::canMoveUp() " << flags cdebug_log(159,0) << "AutoSegment::canMoveUp() " << flags
<< " (reserve:" << reserve << ") " << this << endl; << " (reserve:" << reserve << ") " << this << endl;
if (Session::getRoutingGauge()->getName() == "FlexLib")
reserve += 2.0;
// ls180 hard-coded hack.
//if (getId() == 10023986) return false;
if (getId() == 6378409) return false;
bool nLowDensity = true; bool nLowDensity = true;
bool nLowUpDensity = true; bool nLowUpDensity = true;
if ( isLayerChange() or isFixed() ) return false; if ( isLayerChange() or isFixed() or isUnbreakable() ) return false;
if ( isStrongTerminal() and (not (flags & Flags::AllowTerminal)) ) return false; if ( isStrongTerminal() and (not (flags & Flags::AllowTerminal)) ) return false;
if ( isLocal() and (not (flags & Flags::AllowLocal )) ) return false; if ( isLocal() and (not (flags & Flags::AllowLocal )) ) return false;
@ -1871,6 +2158,10 @@ namespace Anabatic {
if (not getAutoTarget()->canMoveUp(this)) return false; if (not getAutoTarget()->canMoveUp(this)) return false;
return true; return true;
} }
// if (getAutoSource()->isTurn() and (getAutoSource()->getPerpandicular(this)->getLayer() == getLayer())) return false;
// if (getAutoTarget()->isTurn() and (getAutoTarget()->getPerpandicular(this)->getLayer() == getLayer())) return false;
cdebug_log(159,0) << "Both source & target Contacts can move up." << endl; cdebug_log(159,0) << "Both source & target Contacts can move up." << endl;
//bool hasGlobalSegment = false; //bool hasGlobalSegment = false;
@ -1950,38 +2241,152 @@ namespace Anabatic {
bool AutoSegment::reduceDoglegLayer () bool AutoSegment::reduceDoglegLayer ()
{ {
if (not isReduced()) return true; if (not isReduced()) return false;
AutoContact* source = getAutoSource(); DebugSession::open( getNet(), 149, 160 );
AutoContact* target = getAutoTarget(); cdebug_log(159,1) << "AutoSegment::reduceDoglegLayer(): " << this << endl;
unsigned int perpandicularDepth = getDepth(); bool success = false;
if (isSpinBottom()) --perpandicularDepth; AutoContact* source = getAutoSource();
if (isSpinTop ()) ++perpandicularDepth; AutoContact* target = getAutoTarget();
if (perpandicularDepth == getDepth()) { unsigned int minSourceDepth = Session::getAllowedDepth();
cerr << Bug( "AutoSegment::reduceDoglegLayer(): Reduced segment spin is neither top (TT) nor bottom (BB).\n" unsigned int maxSourceDepth = 0;
" %s" unsigned int minTargetDepth = Session::getAllowedDepth();
, getString(this).c_str() ) << endl; unsigned int maxTargetDepth = 0;
if (source->isTerminal()) {
unsigned int anchorDepth = Session::getLayerDepth( source->base()->getAnchor()->getLayer() );
minSourceDepth = std::min( minSourceDepth, anchorDepth );
maxSourceDepth = std::max( maxSourceDepth, anchorDepth );
cdebug_log(151,0) << " source:" << source << endl;
} else {
for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
if (perpandicular == this) continue;
cdebug_log(151,0) << " connected:" << perpandicular << endl;
minSourceDepth = std::min( minSourceDepth, perpandicular->getDepth() );
maxSourceDepth = std::max( maxSourceDepth, perpandicular->getDepth() );
}
}
if (target->isTerminal()) {
unsigned int anchorDepth = Session::getLayerDepth( target->base()->getAnchor()->getLayer() );
minTargetDepth = std::min( minTargetDepth, anchorDepth );
maxTargetDepth = std::max( maxTargetDepth, anchorDepth );
cdebug_log(151,0) << " target:" << target << endl;
} else {
for ( AutoSegment* perpandicular : target->getAutoSegments() ) {
if (perpandicular == this) continue;
cdebug_log(151,0) << " connected:" << perpandicular << endl;
minTargetDepth = std::min( minTargetDepth, perpandicular->getDepth() );
maxTargetDepth = std::max( maxTargetDepth, perpandicular->getDepth() );
}
}
cdebug_log(159,0) << "Source span: [" << minSourceDepth << " " << maxSourceDepth << "]" << endl;
cdebug_log(159,0) << "Target span: [" << minTargetDepth << " " << maxTargetDepth << "]" << endl;
if ( (minSourceDepth == maxSourceDepth)
and (minTargetDepth == maxTargetDepth)
and (minSourceDepth == minTargetDepth) ) {
const Layer* layer = Session::getRoutingLayer(minSourceDepth);
DbU::Unit vside = Session::getWireWidth (minSourceDepth);
DbU::Unit hside = Session::getPWireWidth (minSourceDepth);
if (Session::getDirection(minSourceDepth) & Flags::Vertical)
std::swap( hside, vside );
cdebug_log(159,0) << "Reducing to " << minSourceDepth << " " << layer << endl;
source->setLayer( layer );
target->setLayer( layer );
setLayer( layer );
setWidth( hside );
source->setSizes( hside, vside );
target->setSizes( hside, vside );
success = true;
}
cdebug_tabw(159,-1);
DebugSession::close();
return success;
// if (not source->isTurn() or not target->isTurn()) return true;
// unsigned int perpandicularDepth = getDepth();
// if (isSpinBottom()) --perpandicularDepth;
// if (isSpinTop ()) ++perpandicularDepth;
// if (perpandicularDepth == getDepth()) {
// cerr << Bug( "AutoSegment::reduceDoglegLayer(): Reduced segment spin is neither top (TT) nor bottom (BB).\n"
// " %s"
// , getString(this).c_str() ) << endl;
// return false;
// }
// const Layer* layer = Session::getRoutingLayer(perpandicularDepth);
// DbU::Unit side = Session::getWireWidth (perpandicularDepth);
// source->setLayer( layer );
// target->setLayer( layer );
// setLayer( layer );
// source->setSizes( side, side );
// target->setSizes( side, side );
// return true;
}
bool AutoSegment::bloatStackedStrap ()
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(149,1) << "AutoSegment::bloatStackedStrap() " << this << endl;
double minArea = getLayer()->getMinimalArea();
if (minArea == 0.0) {
cdebug_log(149,-1) << "False, NO minimal area." << endl;
DebugSession::close();
return false; return false;
} }
const Layer* layer = Session::getRoutingLayer(perpandicularDepth); DbU::Unit minLength
DbU::Unit side = Session::getWireWidth (perpandicularDepth); = DbU::fromPhysical( minArea / DbU::toPhysical( getWidth(), DbU::UnitPower::Micro )
, DbU::UnitPower::Micro );
cdebug_log(149,0) << "Min length: " << DbU::getValueString(minLength) << " ." << endl;
source->setLayer( layer ); if ((getSpanLength() >= minLength) or isReduced()) {
target->setLayer( layer ); cdebug_log(149,-1) << "False, has length or is reduced." << endl;
setLayer( layer ); DebugSession::close();
source->setSizes( side, side ); return false;
target->setSizes( side, side ); }
if (isDrag()) {
for ( AutoSegment* perpandicular : getPerpandiculars() ) {
if (perpandicular->getSpanLength() > minLength) {
cdebug_log(149,-1) << "False (drag), has length or PP has length." << endl;
DebugSession::close();
return false;
}
}
} else {
if ( ((_flags & (SegSourceBottom|SegTargetTop)) != (SegSourceBottom|SegTargetTop))
and ((_flags & (SegTargetBottom|SegSourceTop)) != (SegTargetBottom|SegSourceTop)) ) {
cdebug_log(149,-1) << "False, not part of a stacked VIA." << endl;
DebugSession::close();
return false;
}
}
DbU::Unit side = DbU::fromPhysical( std::sqrt(minArea) , DbU::UnitPower::Micro );
setWidth( side );
setDuSource( -side/2 );
setDuTarget( side/2 );
cdebug_log(149,-1) << "True, add area." << endl;
DebugSession::close();
return true; return true;
} }
#if THIS_IS_DISABLED #if THIS_IS_DISABLED
bool AutoSegment::shearUp ( GCell* upGCell, AutoSegment*& movedUp, float reserve, Flags flags ) bool AutoSegment::shearUp ( GCell* upGCell, AutoSegment*& movedUp, float reserve, Flags flags )
{ {
cdebug_log(149,0) << "AutoSegment::shearUp() " << this << endl; cdebug_log(149,0) << "AutoSegment::shearUp() " << this << endl;
@ -2065,11 +2470,11 @@ namespace Anabatic {
if (not isNotAligned()) { if (not isNotAligned()) {
for ( AutoSegment* segment : getAligneds() ) { for ( AutoSegment* segment : getAligneds() ) {
if (segment->getSpanU().contains(interval.getVMin())) { if (segment->getSpanU().contains(interval.getVMin())) {
if (segment->isFixed()) return false; if (segment->isFixed()) return Flags::NoFlags;
leftDogleg++; leftDogleg++;
} }
if (segment->getSpanU().contains(interval.getVMax())) { if (segment->getSpanU().contains(interval.getVMax())) {
if (segment->isFixed()) return 0; if (segment->isFixed()) return Flags::NoFlags;
rightDogleg++; rightDogleg++;
} }
} }
@ -2114,16 +2519,12 @@ namespace Anabatic {
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1] << endl; cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1] << endl;
if (isSource) { if (isSource) {
doglegs[ index + 0 ]->setLayer( segmentDepth-2 ); doglegs[ index + 0 ]->setLayer( std::max((size_t)1,segmentDepth-2) );
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth-2) );
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth-1) );
cdebug_log(149,0) << "doglegs[i+0]: " << doglegs[index+0] << endl; cdebug_log(149,0) << "doglegs[i+0]: " << doglegs[index+0] << endl;
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl; cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl; cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
} else { } else {
doglegs[ index + 2 ]->setLayer( segmentDepth-2 ); doglegs[ index + 2 ]->setLayer( std::max((size_t)1,segmentDepth-2) );
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth-2) );
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth-1) );
cdebug_log(149,0) << "doglegs[i+2]: " << doglegs[index+2] << endl; cdebug_log(149,0) << "doglegs[i+2]: " << doglegs[index+2] << endl;
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl; cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl; cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
@ -2136,20 +2537,18 @@ namespace Anabatic {
if (isSource) { if (isSource) {
doglegs[ index + 0 ]->setLayer( segmentDepth+2 ); doglegs[ index + 0 ]->setLayer( segmentDepth+2 );
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth+1) );
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth ) );
cdebug_log(149,0) << "doglegs[i+0]: " << doglegs[index+0] << endl; cdebug_log(149,0) << "doglegs[i+0]: " << doglegs[index+0] << endl;
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl; cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl; cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
} else { } else {
doglegs[ index + 2 ]->setLayer( segmentDepth+2 ); doglegs[ index + 2 ]->setLayer( segmentDepth+2 );
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth+1) );
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth ) );
cdebug_log(149,0) << "doglegs[i+2]: " << doglegs[index+2] << endl; cdebug_log(149,0) << "doglegs[i+2]: " << doglegs[index+2] << endl;
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl; cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl; cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
} }
} }
doglegs[ index + 1 ]->getAutoSource()->updateLayer();
doglegs[ index + 1 ]->getAutoTarget()->updateLayer();
} }
cdebug_tabw(149,-1); cdebug_tabw(149,-1);
@ -2262,10 +2661,10 @@ namespace Anabatic {
} else { } else {
cdebug_log(149,0) << "Looking in aligneds." << endl; cdebug_log(149,0) << "Looking in aligneds." << endl;
if (not isNotAligned()) { if (not isNotAligned()) {
forEach ( AutoSegment*, aligned, getAligneds(flags) ) { for ( AutoSegment* aligned : getAligneds(flags) ) {
cdebug_log(149,0) << "| Try in " << *aligned << endl; cdebug_log(149,0) << "| Try in " << aligned << endl;
if (doglegGCell->getSide(getDirection()).intersect(aligned->getSpanU())) { if (doglegGCell->getSide(getDirection()).intersect(aligned->getSpanU())) {
cdebug_log(149,0) << "Dogleg in " << *aligned << endl; cdebug_log(149,0) << "Dogleg in " << aligned << endl;
rflags = aligned->_makeDogleg( doglegGCell, flags ); rflags = aligned->_makeDogleg( doglegGCell, flags );
cdebug_tabw(149,-1); cdebug_tabw(149,-1);
return 0; return 0;
@ -2312,6 +2711,7 @@ namespace Anabatic {
state += isFixedAxis () ? "X": "-"; state += isFixedAxis () ? "X": "-";
state += isUnsetAxis () ? "u": "-"; state += isUnsetAxis () ? "u": "-";
state += isStrap () ? "S": "-"; state += isStrap () ? "S": "-";
state += isUnbreakable () ? "U": "-";
state += isCanonical () ? "C": "-"; state += isCanonical () ? "C": "-";
state += isGlobal () ? "G": "-"; state += isGlobal () ? "G": "-";
state += isWeakGlobal () ? "g": "-"; state += isWeakGlobal () ? "g": "-";
@ -2341,9 +2741,9 @@ namespace Anabatic {
string AutoSegment::_getString () const string AutoSegment::_getString () const
{ {
string s = base()->_getString(); string sdistance = " rpD:" + getString(_rpDistance);
//s.insert ( 1, "id: " ); string s = base()->_getString();
//s.insert ( 4, getString(_id) ); s.insert ( s.size()-1, sdistance );
s.insert ( s.size()-1, _getStringFlags() ); s.insert ( s.size()-1, _getStringFlags() );
return s; return s;
} }
@ -2470,9 +2870,10 @@ namespace Anabatic {
segment->_postCreate(); segment->_postCreate();
} else if (vertical) { } else if (vertical) {
if (vertical->getLayer() != verticalLayer) { if (vertical->getLayer() != verticalLayer) {
if (Session::getAnabatic()->getConfiguration()->isGMetal(vertical->getLayer()) ) if (Session::getAnabatic()->getConfiguration()->isGMetal(vertical->getLayer()) ) {
vertical->setLayer( verticalLayer ); vertical->setLayer( verticalLayer );
vertical->setWidth( verticalWidth ); vertical->setWidth( verticalWidth );
}
} else { } else {
if (vertical->getWidth() != verticalWidth) { if (vertical->getWidth() != verticalWidth) {
cerr << Warning("Segment %s has non-default width %s." cerr << Warning("Segment %s has non-default width %s."
@ -2511,16 +2912,33 @@ namespace Anabatic {
const Layer* vLayer = Session::getDVerticalLayer(); const Layer* vLayer = Session::getDVerticalLayer();
DbU::Unit vWidth = Session::getDVerticalWidth(); DbU::Unit vWidth = Session::getDVerticalWidth();
if (dir & Flags::UseNonPref) {
if (dir & Flags::Vertical) {
vLayer = hLayer;
vWidth = Session::getDPHorizontalWidth();
cdebug_log(149,0) << "Make vertical in non-preferred direction (ppW:"
<< DbU::getValueString(vWidth).c_str() << ")." << endl;
}
if (dir & Flags::Horizontal) {
hLayer = vLayer;
hWidth = Session::getDPVerticalWidth();
cdebug_log(149,0) << "Make horizontal in non-preferred direction (ppW:"
<< DbU::getValueString(hWidth).c_str() << ")." << endl;
}
}
const Layer* horizontalLayer = hLayer; const Layer* horizontalLayer = hLayer;
DbU::Unit horizontalWidth = hWidth; DbU::Unit horizontalWidth = hWidth;
const Layer* verticalLayer = vLayer; const Layer* verticalLayer = vLayer;
DbU::Unit verticalWidth = vWidth; DbU::Unit verticalWidth = vWidth;
cdebug_log(149,0) << "verticalWidth:" << DbU::getValueString(verticalWidth).c_str() << endl;
uint32_t wPitch = NetRoutingExtension::getWPitch( source->getNet() ); uint32_t wPitch = NetRoutingExtension::getWPitch( source->getNet() );
if (wPitch > 1) { if (wPitch > 1) {
horizontalWidth = (wPitch-1) * Session::getDHorizontalPitch() + hWidth; horizontalWidth = (wPitch-1) * Session::getDHorizontalPitch() + hWidth;
verticalWidth = (wPitch-1) * Session::getDVerticalPitch () + vWidth; verticalWidth = (wPitch-1) * Session::getDVerticalPitch () + vWidth;
} }
cdebug_log(149,0) << "verticalWidth:" << DbU::getValueString(verticalWidth).c_str() << endl;
if (depth != RoutingGauge::nlayerdepth) { if (depth != RoutingGauge::nlayerdepth) {
horizontalLayer = verticalLayer = Session::getRoutingLayer( depth ); horizontalLayer = verticalLayer = Session::getRoutingLayer( depth );
@ -2529,9 +2947,23 @@ namespace Anabatic {
horizontalWidth = verticalWidth = (wPitch-1) * Session::getPitch (depth) horizontalWidth = verticalWidth = (wPitch-1) * Session::getPitch (depth)
+ Session::getWireWidth(depth); + Session::getWireWidth(depth);
} else { } else {
horizontalWidth = verticalWidth = Session::getWireWidth( depth ); if (dir & Flags::Horizontal) {
horizontalWidth = Session::getWireWidth ( depth );
verticalWidth = Session::getPWireWidth( depth );
} else {
verticalWidth = Session::getWireWidth ( depth );
horizontalWidth = Session::getPWireWidth( depth );
}
cdebug_log(149,0) << "hW:" << DbU::getValueString(horizontalWidth).c_str()
<< "vW:" << DbU::getValueString( verticalWidth).c_str()
<< endl;
if (dir & Flags::UseNonPref) {
cdebug_log(149,0) << "swap H/W width." << endl;
std::swap( horizontalWidth, verticalWidth );
}
} }
} }
cdebug_log(149,0) << "verticalWidth:" << DbU::getValueString(verticalWidth).c_str() << endl;
AutoSegment* segment; AutoSegment* segment;
AutoContact* reference = source; AutoContact* reference = source;
@ -2581,6 +3013,7 @@ namespace Anabatic {
if (wPitch > 1) segment->setFlags( SegWide ); if (wPitch > 1) segment->setFlags( SegWide );
if (source->canDrag() or target->canDrag()) segment->setFlags( SegDrag ); if (source->canDrag() or target->canDrag()) segment->setFlags( SegDrag );
if (dir & Flags::UseNonPref) segment->setFlags( SegNonPref );
return segment; return segment;
} }
@ -2630,7 +3063,7 @@ namespace Anabatic {
exploreds.insert( seed->getAutoSource() ); exploreds.insert( seed->getAutoSource() );
exploreds.insert( seed->getAutoTarget() ); exploreds.insert( seed->getAutoTarget() );
if (seed->getLength()) { if (seed->getAnchoredLength()) {
if (flags & Flags::Superior) stack.push_back( seed->getAutoTarget() ); if (flags & Flags::Superior) stack.push_back( seed->getAutoTarget() );
else stack.push_back( seed->getAutoSource() ); else stack.push_back( seed->getAutoSource() );
} else { } else {
@ -2655,7 +3088,7 @@ namespace Anabatic {
AutoSegment* autoSegment = Session::lookup( segment ); AutoSegment* autoSegment = Session::lookup( segment );
if (not autoSegment) continue; if (not autoSegment) continue;
if (not autoSegment->getLength()) { if (not autoSegment->getAnchoredLength()) {
AutoContact* contact = autoSegment->getAutoSource(); AutoContact* contact = autoSegment->getAutoSource();
if (contact and (contact != currentContact)) { if (contact and (contact != currentContact)) {
if (exploreds.find(contact) == exploreds.end()) if (exploreds.find(contact) == exploreds.end())

View File

@ -41,8 +41,8 @@ namespace Anabatic {
Segment* AutoVertical::base () { return _vertical; } Segment* AutoVertical::base () { return _vertical; }
Segment* AutoVertical::base () const { return _vertical; } Segment* AutoVertical::base () const { return _vertical; }
Vertical* AutoVertical::getVertical () { return _vertical; } Vertical* AutoVertical::getVertical () { return _vertical; }
DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSourceY(); } DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSource()->getY(); }
DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTargetY(); } DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTarget()->getY(); }
DbU::Unit AutoVertical::getDuSource () const { return _vertical->getDySource(); } DbU::Unit AutoVertical::getDuSource () const { return _vertical->getDySource(); }
DbU::Unit AutoVertical::getDuTarget () const { return _vertical->getDyTarget(); } DbU::Unit AutoVertical::getDuTarget () const { return _vertical->getDyTarget(); }
Interval AutoVertical::getSpanU () const { return Interval(_vertical->getSourceY(),_vertical->getTargetY()); } Interval AutoVertical::getSpanU () const { return Interval(_vertical->getSourceY(),_vertical->getTargetY()); }
@ -218,13 +218,15 @@ namespace Anabatic {
if (not gcell) { if (not gcell) {
success = false; success = false;
cerr << Error( "AutoVertical::getGCells() : NULL GCell under %s\n" if (not isCreated()) {
" begin:%s\n" cerr << Error( "AutoVertical::getGCells() : NULL GCell under %s\n"
" end: %s" " begin:%s\n"
, getString(this).c_str() " end: %s"
, getString(getAutoSource()->getGCell()).c_str() , getString(this).c_str()
, getString(getAutoTarget()->getGCell()).c_str() , getString(getAutoSource()->getGCell()).c_str()
) << endl; , getString(getAutoTarget()->getGCell()).c_str()
) << endl;
}
break; break;
} }
@ -239,17 +241,21 @@ namespace Anabatic {
{ {
cdebug_tabw(149,-1); cdebug_tabw(149,-1);
if (getAutoSource()->isOnPin() or getAutoTarget()->isOnPin()) { cdebug_tabw(149,-1); return false; }
Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Horizontal ); Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Horizontal );
Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Horizontal ); Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Horizontal );
Interval sourceConstraints = Interval(getAutoSource()->getCBXMin(),getAutoSource()->getCBXMax()); Interval sourceConstraints = Interval(getAutoSource()->getCBXMin(),getAutoSource()->getCBXMax());
Interval targetConstraints = Interval(getAutoTarget()->getCBXMin(),getAutoTarget()->getCBXMax()); Interval targetConstraints = Interval(getAutoTarget()->getCBXMin(),getAutoTarget()->getCBXMax());
bool sourceGoStraight = getAutoSource()->getGCell()->isGoStraight();
bool targetGoStraight = getAutoTarget()->getGCell()->isGoStraight();
// Expand by a tiny amount for the "contains" to work for sure. // Expand by a tiny amount for the "contains" to work for sure.
sourceConstraints.inflate( 1 ); sourceConstraints.inflate( 1 );
targetConstraints.inflate( 1 ); targetConstraints.inflate( 1 );
if (not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; } if (not sourceGoStraight and not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; }
if (not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; } if (not targetGoStraight and not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; }
cdebug_tabw(149,-1); cdebug_tabw(149,-1);
return false; return false;
@ -262,13 +268,13 @@ namespace Anabatic {
if (not isDrag()) { if (not isDrag()) {
if ( not isStrongTerminal() if ( not isStrongTerminal()
or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < getPitch()*5)) ) or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getAnchoredLength() < getPitch()*5)) )
{ cdebug_tabw(149,-1); return false; } { cdebug_tabw(149,-1); return false; }
} }
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl; cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
cdebug_log(149,0) << "test:" << (getLength() < getPitch()*5) << endl; cdebug_log(149,0) << "test:" << (getAnchoredLength() < getPitch()*5) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl; cdebug_log(149,0) << "length:" << DbU::getValueString(getAnchoredLength()) << endl;
bool success = false; bool success = false;
bool sourceSlackened = false; bool sourceSlackened = false;
@ -376,6 +382,10 @@ namespace Anabatic {
if (_vertical->getTargetY() < _vertical->getSourceY()) { if (_vertical->getTargetY() < _vertical->getSourceY()) {
cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl; cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl;
_vertical->invert(); _vertical->invert();
DbU::Unit duSource = getDuSource();
DbU::Unit duTarget = getDuTarget();
setDuSource( -duTarget );
setDuTarget( -duSource );
unsigned int spinFlags = _flags & SegDepthSpin; unsigned int spinFlags = _flags & SegDepthSpin;
unsetFlags( SegDepthSpin ); unsetFlags( SegDepthSpin );
@ -399,8 +409,8 @@ namespace Anabatic {
void AutoVertical::updatePositions () void AutoVertical::updatePositions ()
{ {
_sourcePosition = _vertical->getSourceY() - getExtensionCap(Flags::Source); _sourcePosition = getSourceU() - getExtensionCap(Flags::Source);
_targetPosition = _vertical->getTargetY() + getExtensionCap(Flags::Target); _targetPosition = getTargetU() + getExtensionCap(Flags::Target);
} }
@ -420,8 +430,8 @@ namespace Anabatic {
bool AutoVertical::checkPositions () const bool AutoVertical::checkPositions () const
{ {
bool coherency = true; bool coherency = true;
DbU::Unit sourcePosition = _vertical->getSourceY() - getExtensionCap(Flags::Source); DbU::Unit sourcePosition = _vertical->getSource()->getY() - getExtensionCap(Flags::Source);
DbU::Unit targetPosition = _vertical->getTargetY() + getExtensionCap(Flags::Target); DbU::Unit targetPosition = _vertical->getTarget()->getY() + getExtensionCap(Flags::Target);
if ( _sourcePosition != sourcePosition ) { if ( _sourcePosition != sourcePosition ) {
cerr << Error ( "%s\n Source position incoherency: " cerr << Error ( "%s\n Source position incoherency: "
@ -712,9 +722,8 @@ namespace Anabatic {
upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
} }
size_t doglegDepth = depth + ((upLayer)?1:-1); size_t doglegDepth = depth + ((upLayer)?1:-1);
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer ( depth + ((upLayer)?0:-1) ); Layer* contactLayer = Session::getRoutingGauge()->getContactLayer ( depth + ((upLayer)?0:-1) );
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer ( doglegDepth );
Session::dogleg( this ); Session::dogleg( this );
targetDetach(); targetDetach();
@ -741,27 +750,48 @@ namespace Anabatic {
segment2->setFlags( (isSlackened()?SegSlackened:0) ); segment2->setFlags( (isSlackened()?SegSlackened:0) );
Session::dogleg( segment2 ); Session::dogleg( segment2 );
if (isSourceTerminal()) { if (autoSource->isTerminal() and autoTarget->isTerminal()) {
segment1->setFlags( SegWeakTerminal1 ); dlContact1->setFlags ( CntWeakTerminal );
segment2->setFlags( SegWeakTerminal1 ); dlContact2->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
} else if (autoSource->isTerminal()) {
autoTarget->unsetFlags( CntWeakTerminal ); autoTarget->unsetFlags( CntWeakTerminal );
dlContact1->setFlags ( CntWeakTerminal ); dlContact1->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
dlContact1->migrateConstraintBox( autoTarget ); } else if (autoTarget->isTerminal()) {
} else if (isTargetTerminal()) {
unsetFlags( SegTargetTerminal ); unsetFlags( SegTargetTerminal );
setFlags( SegWeakTerminal1 ); setFlags( SegWeakTerminal1 );
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegTargetTerminal );
autoSource->unsetFlags( CntWeakTerminal ); autoSource->unsetFlags( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal ); dlContact2->setFlags ( CntWeakTerminal );
if (autoSource->getGCell() == doglegGCell) if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
dlContact2->migrateConstraintBox( autoSource ); } else if (isWeakTerminal()) {
} else if (isWeakTerminal()) {
segment1->setFlags( SegWeakTerminal1 ); segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 ); segment2->setFlags( SegWeakTerminal1 );
} }
// if (isSourceTerminal()) {
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegWeakTerminal1 );
// autoTarget->unsetFlags( CntWeakTerminal );
// dlContact1->setFlags ( CntWeakTerminal );
// if (autoTarget->getGCell() == doglegGCell)
// dlContact1->migrateConstraintBox( autoTarget );
// } else if (isTargetTerminal()) {
// unsetFlags( SegTargetTerminal );
// setFlags( SegWeakTerminal1 );
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegTargetTerminal );
// autoSource->unsetFlags( CntWeakTerminal );
// dlContact2->setFlags ( CntWeakTerminal );
// if (autoSource->getGCell() == doglegGCell)
// dlContact2->migrateConstraintBox( autoSource );
// } else if (isWeakTerminal()) {
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegWeakTerminal1 );
// }
if (isAnalog()) { if (isAnalog()) {
segment1->setFlags( SegAnalog ); segment1->setFlags( SegAnalog );
segment2->setFlags( SegAnalog ); segment2->setFlags( SegAnalog );
@ -781,12 +811,15 @@ namespace Anabatic {
updateNativeConstraints(); updateNativeConstraints();
segment2->updateNativeConstraints(); segment2->updateNativeConstraints();
if ( isLocal()) autoSource->setFlags( AutoContactFlag::CntHDogleg );
if (segment2->isLocal()) autoTarget->setFlags( AutoContactFlag::CntHDogleg );
if (autoTarget->canDrag() and not autoSource->canDrag()) { if (autoTarget->canDrag() and not autoSource->canDrag()) {
if (not autoTarget->getGCell()->isDevice()) { if (not autoTarget->getGCell()->isDevice() and (segment1->getGCell() == autoTarget->getGCell())) {
Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Vertical); Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Vertical);
segment1->mergeUserConstraints( dragConstraints ); segment1->mergeUserConstraints( dragConstraints );
cdebug_log(149,0) << "Perpandical has drag constraints: " << dragConstraints << endl; cdebug_log(149,0) << "Perpandicular has drag constraints: " << dragConstraints << endl;
} }
} }

View File

@ -63,13 +63,15 @@ endif ( CHECK_DETERMINISM )
NetBuilderVH.cpp NetBuilderVH.cpp
ChipTools.cpp ChipTools.cpp
LayerAssign.cpp LayerAssign.cpp
AntennaProtect.cpp
PreRouteds.cpp PreRouteds.cpp
AnabaticEngine.cpp AnabaticEngine.cpp
) )
set( pyCpps PyAnabatic.cpp set( pyCpps PyAnabatic.cpp
) )
set( depLibs ${CORIOLIS_PYTHON_LIBRARIES} set( depLibs ${ETESIAN_LIBRARIES}
${CORIOLIS_PYTHON_LIBRARIES}
${CORIOLIS_LIBRARIES} ${CORIOLIS_LIBRARIES}
${HURRICANE_PYTHON_LIBRARIES} ${HURRICANE_PYTHON_LIBRARIES}
${HURRICANE_GRAPHICAL_LIBRARIES} ${HURRICANE_GRAPHICAL_LIBRARIES}

View File

@ -25,6 +25,7 @@
#include "hurricane/BasicLayer.h" #include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h" #include "hurricane/RegularLayer.h"
#include "hurricane/RoutingPad.h" #include "hurricane/RoutingPad.h"
#include "hurricane/Pin.h"
#include "hurricane/NetExternalComponents.h" #include "hurricane/NetExternalComponents.h"
#include "hurricane/Cell.h" #include "hurricane/Cell.h"
#include "crlcore/Utilities.h" #include "crlcore/Utilities.h"
@ -55,6 +56,7 @@ namespace Anabatic {
using Hurricane::BasicLayer; using Hurricane::BasicLayer;
using Hurricane::RegularLayer; using Hurricane::RegularLayer;
using Hurricane::Segment; using Hurricane::Segment;
using Hurricane::Pin;
using Hurricane::Plug; using Hurricane::Plug;
using Hurricane::Path; using Hurricane::Path;
using Hurricane::Occurrence; using Hurricane::Occurrence;
@ -69,25 +71,28 @@ namespace Anabatic {
Configuration::Configuration ( const CellGauge* cg, const RoutingGauge* rg ) Configuration::Configuration ( const CellGauge* cg, const RoutingGauge* rg )
: _gdepthv (ndepth) : _gdepthv (ndepth)
, _gdepthh (ndepth) , _gdepthh (ndepth)
, _ddepthv (ndepth) , _ddepthv (ndepth)
, _ddepthh (ndepth) , _ddepthh (ndepth)
, _ddepthc (ndepth) , _ddepthc (ndepth)
, _cg (NULL) , _cg (NULL)
, _rg (NULL) , _rg (NULL)
, _extensionCaps () , _extensionCaps ()
, _saturateRatio (Cfg::getParamPercentage("katabatic.saturateRatio",80.0)->asDouble()) , _saturateRatio (Cfg::getParamPercentage("anabatic.saturateRatio",80.0)->asDouble())
, _saturateRp (Cfg::getParamInt ("katabatic.saturateRp" ,8 )->asInt()) , _saturateRp (Cfg::getParamInt ("anabatic.saturateRp" ,8 )->asInt())
, _globalThreshold (0) , _globalThreshold (0)
, _allowedDepth (0) , _allowedDepth (0)
, _edgeLength (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeLength",24)->asInt())) , _edgeLength (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeLength",24)->asInt()))
, _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt())) , _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt()))
, _edgeCostH (Cfg::getParamDouble("anabatic.edgeCostH" , 9.0)->asDouble()) , _edgeCostH (Cfg::getParamDouble("anabatic.edgeCostH" , 9.0)->asDouble())
, _edgeCostK (Cfg::getParamDouble("anabatic.edgeCostK" ,-10.0)->asDouble()) , _edgeCostK (Cfg::getParamDouble("anabatic.edgeCostK" , -10.0)->asDouble())
, _edgeHInc (Cfg::getParamDouble("anabatic.edgeHInc" , 1.5)->asDouble()) , _edgeHInc (Cfg::getParamDouble("anabatic.edgeHInc" , 1.5)->asDouble())
, _edgeHScaling (Cfg::getParamDouble("anabatic.edgeHScaling" , 1.0)->asDouble()) , _edgeHScaling (Cfg::getParamDouble("anabatic.edgeHScaling" , 1.0)->asDouble())
, _globalIterations(Cfg::getParamInt ("anabatic.globalIterations", 10 )->asInt()) , _globalIterations (Cfg::getParamInt ("anabatic.globalIterations", 10 )->asInt())
, _diodeName (Cfg::getParamString("etesian.diodeName" , "dio_x0")->asString() )
, _antennaGateMaxWL (Cfg::getParamInt ("etesian.antennaGateMaxWL" , 0 )->asInt())
, _antennaDiodeMaxWL(Cfg::getParamInt ("etesian.antennaDiodeMaxWL", 0 )->asInt())
{ {
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() ); GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
@ -155,29 +160,40 @@ namespace Anabatic {
} }
} }
} }
if (_antennaGateMaxWL and not _antennaDiodeMaxWL) {
_antennaDiodeMaxWL = _antennaGateMaxWL;
cerr << Warning( "Anabatic::Configuration(): \"etesian.antennaGateMaxWL\" is defined but not \"etesian.antennaDiodeMaxWL\".\n"
" Setting both to %s"
, DbU::getValueString(_antennaGateMaxWL).c_str()
) << endl;
}
} }
Configuration::Configuration ( const Configuration& other ) Configuration::Configuration ( const Configuration& other )
: _gmetalh (other._gmetalh) : _gmetalh (other._gmetalh)
, _gmetalv (other._gmetalv) , _gmetalv (other._gmetalv)
, _gcontact (other._gcontact) , _gcontact (other._gcontact)
, _gdepthv (other._gdepthv) , _gdepthv (other._gdepthv)
, _gdepthh (other._gdepthh) , _gdepthh (other._gdepthh)
, _ddepthv (other._ddepthv) , _ddepthv (other._ddepthv)
, _ddepthh (other._ddepthh) , _ddepthh (other._ddepthh)
, _ddepthc (other._ddepthc) , _ddepthc (other._ddepthc)
, _cg (NULL) , _cg (NULL)
, _rg (NULL) , _rg (NULL)
, _extensionCaps (other._extensionCaps) , _extensionCaps (other._extensionCaps)
, _saturateRatio (other._saturateRatio) , _saturateRatio (other._saturateRatio)
, _globalThreshold (other._globalThreshold) , _globalThreshold (other._globalThreshold)
, _allowedDepth (other._allowedDepth) , _allowedDepth (other._allowedDepth)
, _edgeCostH (other._edgeCostH) , _edgeCostH (other._edgeCostH)
, _edgeCostK (other._edgeCostK) , _edgeCostK (other._edgeCostK)
, _edgeHInc (other._edgeHInc) , _edgeHInc (other._edgeHInc)
, _edgeHScaling (other._edgeHScaling) , _edgeHScaling (other._edgeHScaling)
, _globalIterations(other._globalIterations) , _globalIterations (other._globalIterations)
, _diodeName (other._diodeName)
, _antennaGateMaxWL (other._antennaGateMaxWL)
, _antennaDiodeMaxWL(other._antennaDiodeMaxWL)
{ {
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() ); GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
@ -286,6 +302,10 @@ namespace Anabatic {
{ return getWireWidth( getLayerDepth(layer) ); } { return getWireWidth( getLayerDepth(layer) ); }
DbU::Unit Configuration::getPWireWidth ( const Layer* layer ) const
{ return getPWireWidth( getLayerDepth(layer) ); }
Flags Configuration::getDirection ( const Layer* layer ) const Flags Configuration::getDirection ( const Layer* layer ) const
{ return getDirection( getLayerDepth(layer) ); } { return getDirection( getLayerDepth(layer) ); }
@ -337,6 +357,9 @@ namespace Anabatic {
{ return _rg->getLayerWireWidth(depth); } { return _rg->getLayerWireWidth(depth); }
DbU::Unit Configuration::getPWireWidth ( size_t depth ) const
{ return _rg->getLayerPWireWidth(depth); }
DbU::Unit Configuration::getExtensionCap ( size_t depth ) const DbU::Unit Configuration::getExtensionCap ( size_t depth ) const
{ return _extensionCaps[depth]; } { return _extensionCaps[depth]; }
@ -458,13 +481,24 @@ namespace Anabatic {
cdebug_log(112,0) << "Looking into: " << masterNet->getCell() << endl; cdebug_log(112,0) << "Looking into: " << masterNet->getCell() << endl;
for ( Component* component : masterNet->getComponents() ) { for ( Component* component : masterNet->getComponents() ) {
cdebug_log(112,0) << "@ " << component << endl; cdebug_log(112,0) << "@ " << component << endl;
if (not NetExternalComponents::isExternal(component)) continue; if (not NetExternalComponents::isExternal(component)) {
cdebug_log(112,0) << " Not an external component, skip." << endl;
continue;
}
Segment* segment = dynamic_cast<Segment*>(component); if (dynamic_cast<Pin*>(component)) {
if (not segment) continue; cdebug_log(112,0) << " Pins are always considered best candidates:" << component << endl;
if (segment->getLayer()->getMask() != metal1->getMask()) continue; bestComponent = component;
break;
}
Box bb = transformation.getBox( component->getBoundingBox() ); 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 trackPos = 0;
DbU::Unit minPos = DbU::Max; DbU::Unit minPos = DbU::Max;
DbU::Unit maxPos = DbU::Min; DbU::Unit maxPos = DbU::Min;
@ -478,8 +512,8 @@ namespace Anabatic {
maxPos = bb.getXMax(); maxPos = bb.getXMax();
cdebug_log(112,0) << "Vertical gauge: " << gauge << endl; cdebug_log(112,0) << "Vertical gauge: " << gauge << endl;
cdebug_log(112,0) << "ab.getXMin(): " << DbU::getValueString(ab.getXMin()) << endl; cdebug_log(112,0) << "ab.getXMin(): " << DbU::getValueString(bb.getXMin()) << endl;
cdebug_log(112,0) << "ab.getXMax(): " << DbU::getValueString(ab.getXMax()) << endl; cdebug_log(112,0) << "ab.getXMax(): " << DbU::getValueString(bb.getXMax()) << endl;
cdebug_log(112,0) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getX()) << endl; cdebug_log(112,0) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getX()) << endl;
} else { } else {
trackPos = gauge->getTrackPosition( ab.getYMin() trackPos = gauge->getTrackPosition( ab.getYMin()
@ -490,18 +524,18 @@ namespace Anabatic {
maxPos = bb.getYMax(); maxPos = bb.getYMax();
cdebug_log(112,0) << "Horizontal gauge: " << gauge << endl; cdebug_log(112,0) << "Horizontal gauge: " << gauge << endl;
cdebug_log(112,0) << "ab.getYMin(): " << DbU::getValueString(ab.getYMin()) << endl; cdebug_log(112,0) << "ab.getYMin(): " << DbU::getValueString(bb.getYMin()) << endl;
cdebug_log(112,0) << "ab.getYMax(): " << DbU::getValueString(ab.getYMax()) << 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) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getY()) << endl;
} }
cdebug_log(112,0) << "| " << occurrence.getPath() << endl; cdebug_log(112,0) << "| " << occurrence.getPath() << endl;
cdebug_log(112,0) << "| " << transformation << endl; cdebug_log(112,0) << "| " << transformation << endl;
cdebug_log(112,0) << "| " << bb << " of:" << segment << endl; cdebug_log(112,0) << "| " << bb << " of:" << candidate << endl;
cdebug_log(112,0) << "| Nearest Pos: " << DbU::getValueString(trackPos) << endl; cdebug_log(112,0) << "| Nearest Pos: " << DbU::getValueString(trackPos) << endl;
if ( (trackPos >= minPos) and (trackPos <= maxPos) ) { if ( (trackPos >= minPos) and (trackPos <= maxPos) ) {
if (not bestComponent or (bestSpan > maxPos-minPos)) { if (not bestComponent or (bestSpan < maxPos-minPos)) {
bestComponent = component; bestComponent = component;
bestSpan = maxPos - minPos; bestSpan = maxPos - minPos;
} }
@ -533,6 +567,7 @@ namespace Anabatic {
cout << " o Configuration of ToolEngine<Anabatic> for Cell <" << cell->getName() << ">" << endl; cout << " o Configuration of ToolEngine<Anabatic> for Cell <" << cell->getName() << ">" << endl;
cout << Dots::asIdentifier(" - Routing Gauge" ,getString(_rg->getName())) << endl; cout << Dots::asIdentifier(" - Routing Gauge" ,getString(_rg->getName())) << endl;
cout << Dots::asString (" - Top routing layer" ,topLayerName) << endl; cout << Dots::asString (" - Top routing layer" ,topLayerName) << endl;
cout << Dots::asUInt (" - Maximum GR iterations" ,_globalIterations) << endl;
} }
@ -555,17 +590,22 @@ namespace Anabatic {
Record* Configuration::_getRecord () const Record* Configuration::_getRecord () const
{ {
Record* record = new Record ( _getString() ); Record* record = new Record ( _getString() );
record->add ( getSlot( "_gdepthh" , _gdepthh ) ); record->add( getSlot( "_gdepthh" , _gdepthh ) );
record->add ( getSlot( "_gdepthv" , _gdepthv ) ); record->add( getSlot( "_gdepthv" , _gdepthv ) );
record->add ( getSlot( "_rg" , _rg ) ); record->add( getSlot( "_rg" , _rg ) );
record->add ( getSlot( "_gmetalh" , _gmetalh ) ); record->add( getSlot( "_gmetalh" , _gmetalh ) );
record->add ( getSlot( "_gmetalv" , _gmetalv ) ); record->add( getSlot( "_gmetalv" , _gmetalv ) );
record->add ( getSlot( "_gcontact" , _gcontact ) ); record->add( getSlot( "_gcontact" , _gcontact ) );
record->add ( getSlot( "_allowedDepth", _allowedDepth ) ); record->add( getSlot( "_allowedDepth" , _allowedDepth ) );
record->add ( getSlot( "_edgeCostH" , _edgeCostH ) ); record->add( getSlot( "_edgeCostH" , _edgeCostH ) );
record->add ( getSlot( "_edgeCostK" , _edgeCostK ) ); 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

@ -43,6 +43,7 @@ namespace Anabatic {
const BaseFlags Flags::ChannelRow = (1L << 13); const BaseFlags Flags::ChannelRow = (1L << 13);
const BaseFlags Flags::HRailGCell = (1L << 14); const BaseFlags Flags::HRailGCell = (1L << 14);
const BaseFlags Flags::VRailGCell = (1L << 15); const BaseFlags Flags::VRailGCell = (1L << 15);
const BaseFlags Flags::GoStraight = (1L << 16);
// Flags for Edge objects states only. // Flags for Edge objects states only.
const BaseFlags Flags::NullCapacity = (1L << 5); const BaseFlags Flags::NullCapacity = (1L << 5);
const BaseFlags Flags::InfiniteCapacity = (1L << 6); const BaseFlags Flags::InfiniteCapacity = (1L << 6);
@ -53,9 +54,11 @@ namespace Anabatic {
const BaseFlags Flags::DestroyBaseContact = (1L << 8); const BaseFlags Flags::DestroyBaseContact = (1L << 8);
const BaseFlags Flags::DestroyBaseSegment = (1L << 9); const BaseFlags Flags::DestroyBaseSegment = (1L << 9);
// Flags for NetDatas objects states only. // Flags for NetDatas objects states only.
const BaseFlags Flags::GlobalRouted = (1L << 5); const BaseFlags Flags::GlobalFixed = (1L << 5);
const BaseFlags Flags::GlobalEstimated = (1L << 6); const BaseFlags Flags::GlobalEstimated = (1L << 6);
const BaseFlags Flags::ExcludeRoute = (1L << 7); const BaseFlags Flags::GlobalRouted = (1L << 7);
const BaseFlags Flags::DetailRouted = (1L << 8);
const BaseFlags Flags::ExcludeRoute = (1L << 9);
// Masks. // Masks.
const BaseFlags Flags::WestSide = Horizontal|Target; const BaseFlags Flags::WestSide = Horizontal|Target;
const BaseFlags Flags::EastSide = Horizontal|Source; const BaseFlags Flags::EastSide = Horizontal|Source;
@ -116,6 +119,12 @@ namespace Anabatic {
const BaseFlags Flags::CheckLowUpDensity = (1L << 31); const BaseFlags Flags::CheckLowUpDensity = (1L << 31);
const BaseFlags Flags::NoUpdate = (1L << 32); const BaseFlags Flags::NoUpdate = (1L << 32);
const BaseFlags Flags::NorthPath = (1L << 33); const BaseFlags Flags::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 () Flags::~Flags ()
@ -169,6 +178,7 @@ namespace Anabatic {
return s.str(); return s.str();
} }
string Flags::_getTypeName () const string Flags::_getTypeName () const
{ return "Anabatic::Flags"; } { return "Anabatic::Flags"; }
@ -183,12 +193,13 @@ namespace Anabatic {
s += (_flags & (uint64_t)DeviceGCell ) ? 'd' : '-'; s += (_flags & (uint64_t)DeviceGCell ) ? 'd' : '-';
s += (_flags & (uint64_t)HChannelGCell) ? 'c' : '-'; s += (_flags & (uint64_t)HChannelGCell) ? 'c' : '-';
s += (_flags & (uint64_t)VChannelGCell) ? 'c' : '-'; s += (_flags & (uint64_t)VChannelGCell) ? 'c' : '-';
s += (_flags & (uint64_t)HRailGCell ) ? 'r' : '-'; s += (_flags & (uint64_t)HRailGCell ) ? 'H' : '-';
s += (_flags & (uint64_t)VRailGCell ) ? 'r' : '-'; s += (_flags & (uint64_t)VRailGCell ) ? 'V' : '-';
s += (_flags & (uint64_t)StrutGCell ) ? 's' : '-'; s += (_flags & (uint64_t)StrutGCell ) ? 'S' : '-';
s += (_flags & (uint64_t)MatrixGCell ) ? 'm' : '-'; s += (_flags & (uint64_t)MatrixGCell ) ? 'M' : '-';
s += (_flags & (uint64_t)StdCellRow ) ? 'S' : '-'; s += (_flags & (uint64_t)StdCellRow ) ? 'R' : '-';
s += (_flags & (uint64_t)ChannelRow ) ? 'C' : '-'; s += (_flags & (uint64_t)ChannelRow ) ? 'C' : '-';
s += (_flags & (uint64_t)GoStraight ) ? 'g' : '-';
s += ","; s += ",";
s += (_flags & (uint64_t)Invalidated ) ? 'i' : '-'; s += (_flags & (uint64_t)Invalidated ) ? 'i' : '-';
s += (_flags & (uint64_t)DestroyGCell ) ? 'D' : '-'; s += (_flags & (uint64_t)DestroyGCell ) ? 'D' : '-';

View File

@ -19,6 +19,7 @@
#include "hurricane/Error.h" #include "hurricane/Error.h"
#include "hurricane/Warning.h" #include "hurricane/Warning.h"
#include "hurricane/Net.h" #include "hurricane/Net.h"
#include "hurricane/Pin.h"
#include "hurricane/RoutingPad.h" #include "hurricane/RoutingPad.h"
#include "hurricane/Horizontal.h" #include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h" #include "hurricane/Vertical.h"
@ -42,6 +43,7 @@ namespace Anabatic {
using Hurricane::Error; using Hurricane::Error;
using Hurricane::Warning; using Hurricane::Warning;
using Hurricane::Component; using Hurricane::Component;
using Hurricane::Pin;
using Hurricane::Segment; using Hurricane::Segment;
using Hurricane::Horizontal; using Hurricane::Horizontal;
using Hurricane::Vertical; using Hurricane::Vertical;
@ -298,52 +300,68 @@ namespace Anabatic {
GCell* c2 = v2->getGCell(); GCell* c2 = v2->getGCell();
// Check from GCell 1 // Check from GCell 1
if ( c1->isNorth(c2) ) { if ( c1->isNorth(c2) and not v1->isNRestricted() ) restricted = false;
if ( !v1->isNRestricted() ) restricted = false; else if ( c1->isSouth(c2) and not v1->isSRestricted() ) restricted = false;
} else if ( c1->isSouth(c2) ) { else if ( c1->isEast (c2) and not v1->isERestricted() ) restricted = false;
if ( !v1->isSRestricted() ) restricted = false; else if ( c1->isWest (c2) and not v1->isWRestricted() ) restricted = false;
} else if ( c1->isEast (c2) ) { // else {
if ( !v1->isERestricted() ) restricted = false; // cerr << Error( "Vertex::isRestricted(): Vertexes/GCells v1 & v2 do not share a side.\n"
} else if ( c1->isWest (c2) ) { // " v1:%s\n"
if ( !v1->isWRestricted() ) restricted = false; // " v2:%s"
} else { // , getString(v1).c_str()
cerr << Error( "GCells are not side by side." ) << endl; // , getString(v2).c_str()
// ) << endl;
// return true;
// }
if (restricted) {
cdebug_log(112,0) << "v1 -> v2 edge is restricted." << endl;
return true;
}
if ( e->isVertical() and (c1->getWidth() < hpitch) ) {
cdebug_log(112,0) << "GCell 1 is too narrow for V edges." << endl;
return true;
}
if ( e->isHorizontal() and (c1->getHeight() < vpitch) ) {
cdebug_log(112,0) << "GCell 1 is too narrow for H edges." << endl;
return true; return true;
} }
if ( (c1->getWidth() < hpitch) restricted = true;
||(c1->getHeight() < vpitch) // Check from GCell 2
||(restricted) if ( c2->isNorth(c1) and not v2->isNRestricted() ) restricted = false;
) return true; else if ( c2->isSouth(c1) and not v2->isSRestricted() ) restricted = false;
else { else if ( c2->isEast (c1) and not v2->isERestricted() ) restricted = false;
restricted = true; else if ( c2->isWest (c1) and not v2->isWRestricted() ) restricted = false;
// Check from GCell 2 // else {
if ( c2->isNorth(c1) ) { // cerr << Error( "Vertex::isRestricted(): Vertexes/GCells v1 & v2 do not share a side.\n"
if ( !v2->isNRestricted() ) restricted = false; // " v1:%s\n"
} else if ( c2->isSouth(c1) ) { // " v2:%s"
if ( !v2->isSRestricted() ) restricted = false; // , getString(v1).c_str()
} else if ( c2->isEast (c1) ) { // , getString(v2).c_str()
if ( !v2->isERestricted() ) restricted = false; // ) << endl;
} else if ( c2->isWest (c1) ) { // return true;
if ( !v2->isWRestricted() ) restricted = false; // }
} else {
cerr << Error( "GCells are not side by side." ) << endl; if (restricted) {
return true; cdebug_log(112,0) << "v2 -> v1 edge is restricted." << endl;
} return true;
if ( (c2->getWidth() < hpitch)
||(c2->getHeight() < vpitch)
||(restricted)
) return true;
else {
if ((v2->getGCell()->isStrut())){
if (e->isMaxCapacity(net)) {
cdebug_log(112,0) << "Overcapacity:" << e << endl;
return true;
}
else return false;
} else return false;
}
} }
if ( e->isVertical() and (c2->getWidth() < hpitch) ) {
cdebug_log(112,0) << "GCell 2 is too narrow for V edges." << endl;
return true;
}
if ( e->isHorizontal() and (c2->getHeight() < vpitch) ) {
cdebug_log(112,0) << "GCell 2 is too narrow for H edges." << endl;
return true;
}
if ( v2->getGCell()->isStrut() and e->isMaxCapacity(net) ) {
cdebug_log(112,0) << "Overcapacity:" << e << endl;
return true;
}
return false;
} }
@ -1441,6 +1459,10 @@ namespace Anabatic {
} }
DbU::Unit Dijkstra::getAntennaGateMaxWL () const
{ return _anabatic->getAntennaGateMaxWL(); }
Point Dijkstra::_getPonderedPoint() const Point Dijkstra::_getPonderedPoint() const
{ {
vector<RoutingPad*> rps; vector<RoutingPad*> rps;
@ -1462,6 +1484,48 @@ namespace Anabatic {
} }
void Dijkstra::loadFixedGlobal ( Net* net )
{
NetData* netData = _anabatic->getNetData( net );
netData->setGlobalRouted( true );
netData->setGlobalFixed ( true );
for ( Component* component : net->getComponents() ) {
Horizontal* horizontal = dynamic_cast<Horizontal*>( component );
if (horizontal) {
if (not Session::isGLayer(horizontal->getLayer())) {
cerr << Error( "Dijsktra::loadFixedGlobal(): A component of \"%s\" has not a global layer.\n"
" (%s)"
, getString(net->getName()).c_str()
, getString(component).c_str()
) << endl;
continue;
}
GCell* begin = _anabatic->getGCellUnder( horizontal->getSource()->getPosition() );
GCell* end = _anabatic->getGCellUnder( horizontal->getTarget()->getPosition() );
for ( Edge* edge : _anabatic->getEdgesUnderPath(begin,end) )
edge->add( horizontal );
}
Vertical* vertical = dynamic_cast<Vertical*>( component );
if (vertical) {
if (not Session::isGLayer(vertical->getLayer())) {
cerr << Error( "Dijsktra::loadFixedGlobal(): A component of \"%s\" has not a global layer.\n"
" (%s)"
, getString(net->getName()).c_str()
, getString(component).c_str()
) << endl;
continue;
}
GCell* begin = _anabatic->getGCellUnder( vertical->getSource()->getPosition() );
GCell* end = _anabatic->getGCellUnder( vertical->getTarget()->getPosition() );
for ( Edge* edge : _anabatic->getEdgesUnderPath(begin,end,Flags::NorthPath) )
edge->add( vertical );
}
}
}
void Dijkstra::load ( Net* net ) void Dijkstra::load ( Net* net )
{ {
_cleanup(); _cleanup();
@ -1473,12 +1537,13 @@ namespace Anabatic {
cdebug_log(112,1) << "Dijkstra::load() " << _net << endl; cdebug_log(112,1) << "Dijkstra::load() " << _net << endl;
vector<RoutingPad*> rps; vector<RoutingPad*> rps;
NetRoutingState* state = NetRoutingExtension::get( _net ); NetRoutingState* state = NetRoutingExtension::get( _net );
if (state) { if (state) {
if (state->isSelfSym()) { if (state->isSelfSym()) {
cdebug_log(112,0) << "Dijkstra::SELF SYMMETRY CASE " << DbU::getValueString(state->getSymAxis()) << endl; cdebug_log(112,0) << "Dijkstra::SELF SYMMETRY CASE " << DbU::getValueString(state->getSymAxis()) << endl;
} }
state->unsetFlags( NetRoutingState::HasAntenna );
} }
for ( Component* component : _net->getComponents() ) { for ( Component* component : _net->getComponents() ) {
@ -1488,25 +1553,29 @@ namespace Anabatic {
cdebug_log(112,0) << "@ frp:" << rp << endl; cdebug_log(112,0) << "@ frp:" << rp << endl;
rps.push_back( rp ); rps.push_back( rp );
continue;
} }
} }
if (rps.size() < 2) return; if (rps.size() < 2) {
cdebug_tabw(112,-1);
return;
}
uint32_t driverCount = 0;
for ( auto rp : rps ) { for ( auto rp : rps ) {
if (not _anabatic->getConfiguration()->selectRpComponent(rp)) if (not _anabatic->getConfiguration()->selectRpComponent(rp))
cerr << Warning( "Dijktra::load(): %s has no components on grid.", getString(rp).c_str() ) << endl; cerr << Warning( "Dijktra::load(): %s has no components on grid.", getString(rp).c_str() ) << endl;
cdebug_log(112,0) << "@ rp: " << rp << ", getCenter(): " << rp->getBoundingBox().getCenter() << endl; cdebug_log(112,0) << "@ rp: " << rp << ", getCenter(): " << rp->getBoundingBox().getCenter() << endl;
Point center = rp->getBoundingBox().getCenter(); Point center = rp->getBoundingBox().getCenter();
GCell* gcell = _anabatic->getGCellUnder( center ); GCell* gcell = _anabatic->getGCellUnder( center );
Box bb = rp->getBoundingBox(); Box bb = rp->getBoundingBox();
bool isDriver = false;
cdebug_log(112,0) << bb.getXMin() << " " << bb.getXMax() << endl; cdebug_log(112,0) << bb.getXMin() << " " << bb.getXMax() << endl;
cdebug_log(112,0) << "center X:" << center.getX() << " gcell Xmax:" << gcell->getXMax() << endl; cdebug_log(112,0) << "center X:" << center.getX() << " gcell Xmax:" << gcell->getXMax() << endl;
_limitSymSearchArea(rp); // ANALOG if (state and state->isSymmetric()) _limitSymSearchArea( rp );
if (not gcell) { if (not gcell) {
cerr << Error( "Dijkstra::load(): %s\n" cerr << Error( "Dijkstra::load(): %s\n"
@ -1519,6 +1588,29 @@ namespace Anabatic {
continue; continue;
} }
Net* rpNet = NULL;
Plug* plug = dynamic_cast<Plug*>( rp->getPlugOccurrence().getEntity() );
if (plug) {
rpNet = plug->getMasterNet();
if (rpNet->getDirection() & Net::Direction::DirOut) {
cdebug_log(112,0) << "Driver/cell: " << rp << endl;
cdebug_log(112,0) << "masterNet: " << rpNet << endl;
++driverCount;
isDriver = true;
}
} else {
Pin* pin = dynamic_cast<Pin*>( rp->getPlugOccurrence().getEntity() );
if (pin) {
rpNet = pin->getNet();
if (rpNet->getDirection() & Net::Direction::DirIn) {
cdebug_log(112,0) << "Driver/pin: " << rp << endl;
cdebug_log(112,0) << "masterNet: " << rpNet << endl;
++driverCount;
isDriver = true;
}
}
}
_searchArea.merge( gcell->getBoundingBox() ); // TO CHANGE _searchArea.merge( gcell->getBoundingBox() ); // TO CHANGE
cdebug_log(112,0) << "| Merged search area: " << _searchArea << ", gcell: " << gcell << endl; cdebug_log(112,0) << "| Merged search area: " << _searchArea << ", gcell: " << gcell << endl;
@ -1535,6 +1627,7 @@ namespace Anabatic {
++_connectedsId; ++_connectedsId;
for ( Vertex* vertex : connecteds ) { for ( Vertex* vertex : connecteds ) {
vertex->getGCell()->flags().reset( Flags::GoStraight );
vertex->setDistance ( Vertex::unreached ); vertex->setDistance ( Vertex::unreached );
vertex->setStamp ( _stamp ); vertex->setStamp ( _stamp );
vertex->setConnexId ( _connectedsId ); vertex->setConnexId ( _connectedsId );
@ -1542,6 +1635,8 @@ namespace Anabatic {
vertex->setDegree ( 0 ); vertex->setDegree ( 0 );
vertex->setRpCount ( 0 ); vertex->setRpCount ( 0 );
vertex->setFrom ( NULL ); vertex->setFrom ( NULL );
if (isDriver)
vertex->setDriver( true );
vertex->setFrom2 ( NULL); vertex->setFrom2 ( NULL);
vertex->unsetFlags ( Vertex::UseFromFrom2 ); vertex->unsetFlags ( Vertex::UseFromFrom2 );
@ -1567,6 +1662,45 @@ namespace Anabatic {
rp->getBodyHook()->attach( vcontact->getBodyHook() ); rp->getBodyHook()->attach( vcontact->getBodyHook() );
} }
if (driverCount == 0) {
cerr << Error( "Diskstra::load(): Net \"%s\" do not have a driver.\n"
, getString(_net->getName()).c_str()
) << endl;
}
if (driverCount > 1) {
cerr << Error( "Diskstra::load(): Net \"%s\" have multiple drivers (%u).\n"
, getString(_net->getName()).c_str(), driverCount
) << endl;
}
if (state and state->isSymmetric() and not state->isSelfSym() and state->isSymMaster()) {
if (state->isSymVertical()) {
if ( (_searchArea.getXMin() < state->getSymAxis())
and (_searchArea.getXMax() > state->getSymAxis()) ) {
cerr << Error( "Diskstra::load(): For net \"%s\" (paired with \"%s\"),\n"
" Vertical symmetry axis @%s is inside the net area %s."
, getString(_net->getName()).c_str()
, getString(state->getSymNet()->getName()).c_str()
, DbU::getValueString(state->getSymAxis()).c_str()
, getString(_searchArea).c_str()
) << endl;
}
}
if (state->isSymHorizontal()) {
if ( (_searchArea.getYMin() < state->getSymAxis())
and (_searchArea.getYMax() > state->getSymAxis()) ) {
cerr << Error( "Diskstra::load(): For net \"%s\" (paired with \"%s\"),\n"
" Horizontal symmetry axis @%s is inside the net area %s."
, getString(_net->getName()).c_str()
, getString(state->getSymNet()->getName()).c_str()
, DbU::getValueString(state->getSymAxis()).c_str()
, getString(_searchArea).c_str()
) << endl;
}
}
}
_searchArea.inflate( _searchAreaHalo ); _searchArea.inflate( _searchAreaHalo );
cdebug_log(112,0) << "Search halo: " << DbU::getValueString(_searchAreaHalo) << endl; cdebug_log(112,0) << "Search halo: " << DbU::getValueString(_searchAreaHalo) << endl;
cdebug_log(112,0) << "Search area: " << _searchArea << endl; cdebug_log(112,0) << "Search area: " << _searchArea << endl;
@ -1715,8 +1849,15 @@ namespace Anabatic {
return; return;
} }
Vertex* firstSource = NULL; Vertex* firstSource = NULL;
VertexSet drivers;
for ( Vertex* vertex : _targets ) {
if (vertex->isDriver()) drivers.insert( vertex );
}
if (drivers.empty()) drivers = _targets;
#if THIS_IS_DISABLED
if (_mode & Mode::Monotonic) { if (_mode & Mode::Monotonic) {
if (_targets.size() == 2) { if (_targets.size() == 2) {
auto ivertex = _targets.begin(); auto ivertex = _targets.begin();
@ -1733,24 +1874,25 @@ namespace Anabatic {
_mode = Mode::Standart; _mode = Mode::Standart;
} }
} }
#endif
if (not firstSource) { if (not firstSource) {
// Standart routing. // Standart routing.
bool hasDevice = false; bool hasDevice = false;
for ( Vertex* ivertex : _targets ) { for ( Vertex* vertex : drivers ) {
if (ivertex->getGCell()->isDevice()) hasDevice = true; if (vertex->getGCell()->isDevice()) hasDevice = true;
} }
Point areaCenter; Point areaCenter;
if (hasDevice) areaCenter = _getPonderedPoint(); if (hasDevice) areaCenter = _getPonderedPoint();
else areaCenter = _searchArea.getCenter(); else areaCenter = _searchArea.getCenter();
auto ivertex = _targets.begin(); auto ivertex = drivers.begin();
firstSource = *ivertex++; firstSource = *ivertex++;
DbU::Unit minDistance = areaCenter.manhattanDistance( firstSource->getCenter() ); DbU::Unit minDistance = areaCenter.manhattanDistance( firstSource->getCenter() );
for ( ; ivertex != _targets.end() ; ++ivertex ) { for ( ; ivertex != drivers.end() ; ++ivertex ) {
DbU::Unit distance = areaCenter.manhattanDistance( (*ivertex)->getCenter() ); DbU::Unit distance = areaCenter.manhattanDistance( (*ivertex)->getCenter() );
if (distance < minDistance) { if (distance < minDistance) {
minDistance = distance; minDistance = distance;
@ -2059,6 +2201,7 @@ namespace Anabatic {
if (_sources.size() < 2) { cdebug_tabw(112,-1); return; } if (_sources.size() < 2) { cdebug_tabw(112,-1); return; }
DbU::Unit gWL = 0;
NetRoutingState* state = NetRoutingExtension::get( _net ); NetRoutingState* state = NetRoutingExtension::get( _net );
//cerr << "state: " << state << endl; //cerr << "state: " << state << endl;
@ -2089,8 +2232,8 @@ namespace Anabatic {
vector<Edge*> aligneds; vector<Edge*> aligneds;
aligneds.push_back( from ); aligneds.push_back( from );
Vertex* target = source->getPredecessor(); Vertex* target = source->getPredecessor();
Interval constraint = from->getSide(); Interval constraint = from->getSide();
source->setFrom( NULL ); source->setFrom( NULL );
cdebug_log(112,0) << "| " << target << endl; cdebug_log(112,0) << "| " << target << endl;
@ -2149,6 +2292,8 @@ namespace Anabatic {
, constraint.getCenter() , constraint.getCenter()
, width , width
); );
gWL += segment->getLength();
cdebug_log(112,0) << "| ref: " << segment << endl;
for ( Edge* through : aligneds ) through->add( segment ); for ( Edge* through : aligneds ) through->add( segment );
if (state) { if (state) {
@ -2167,6 +2312,8 @@ namespace Anabatic {
, constraint.getCenter() , constraint.getCenter()
, width , width
); );
gWL += segment->getLength();
cdebug_log(112,0) << "| ref: " << segment << endl;
for ( Edge* through : aligneds ) through->add( segment ); for ( Edge* through : aligneds ) through->add( segment );
if (state) { if (state) {
@ -2183,6 +2330,14 @@ namespace Anabatic {
} }
} }
if (gWL > getAntennaGateMaxWL()) {
cdebug_log(113,0) << "| \"" << _net->getName() << "\" may have antenna effect, "
<< DbU::getValueString(gWL)
<< endl;
if (state)
state->setFlags( NetRoutingState::HasAntenna );
}
cdebug_tabw(112,-1); cdebug_tabw(112,-1);
} }
@ -2329,51 +2484,66 @@ namespace Anabatic {
void Dijkstra::_createSelfSymSeg ( Segment* segment ) void Dijkstra::_createSelfSymSeg ( Segment* segment )
{ {
cdebug_log(112,0) << "void Dijkstra::_createSelfSymSeg ( Segment* segment ): " << _net << ", seg: " << segment << endl; cdebug_log(112,1) << "Dijkstra::_createSelfSymSeg(): " << segment << endl;
NetRoutingState* state = NetRoutingExtension::get( _net ); NetRoutingState* state = NetRoutingExtension::get( _net );
//cdebug_log(112,0) << "state: " << state << endl; if (state and segment) {
if ((state != NULL)&&(segment!=NULL)){
Horizontal* h = dynamic_cast<Horizontal*>(segment); Horizontal* h = dynamic_cast<Horizontal*>(segment);
Vertical* v = dynamic_cast<Vertical*>(segment); Vertical* v = dynamic_cast<Vertical *>(segment);
Point sp, tp; Point sp;
DbU::Unit axis; Point tp;
Component* sourceContact = segment->getSource(); DbU::Unit axis;
Component* targetContact = segment->getTarget(); Component* sourceContact = segment->getSource();
if (h){ Component* targetContact = segment->getTarget();
if (state->isSymHorizontal()){
cdebug_log(112,0) << "H case Horizontal" << endl; cdebug_log(112,0) << "source: " << sourceContact << endl;
sp = Point(sourceContact->getX(), state->getSymValue(sourceContact->getY()) ); cdebug_log(112,0) << "target: " << targetContact << endl;
tp = Point(targetContact->getX(), state->getSymValue(targetContact->getY()) ); cdebug_log(112,0) << "sym axis: " << DbU::getValueString(state->getSymAxis()) << endl;
axis = state->getSymValue(segment->getY());
} else if (state->isSymVertical()){ if (h) {
cdebug_log(112,0) << "H case Vertical" << endl; if (state->isSymHorizontal()) {
sp = Point( state->getSymValue(targetContact->getX()), targetContact->getY() ); cdebug_log(112,0) << "Horizontal + Horizontal symmetry." << endl;
tp = Point( state->getSymValue(sourceContact->getX()), sourceContact->getY() );
sp = Point( sourceContact->getX(), state->getSymValue(sourceContact->getY()) );
tp = Point( targetContact->getX(), state->getSymValue(targetContact->getY()) );
axis = state->getSymValue( segment->getY() );
} else if (state->isSymVertical()) {
cdebug_log(112,0) << "Horizontal + Vertical symmetry." << endl;
sp = Point( state->getSymValue(targetContact->getX()), targetContact->getY() );
tp = Point( state->getSymValue(sourceContact->getX()), sourceContact->getY() );
axis = segment->getY(); axis = segment->getY();
} else { } else {
cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong here. " << endl; cdebug_log(112,0) << "Dijkstra::_materialize(): Horizontal + Unknown symmetry. " << endl;
cdebug_tabw(112,-1);
return; return;
} }
//cerr << "sp: " << sp << endl;
//cerr << "tp: " << tp << endl; cdebug_log(112,0) << "sp: " << sp << endl;
cdebug_log(112,0) << "tp: " << tp << endl;
GCell* sgcell = _anabatic->getGCellUnder( sp ); GCell* sgcell = _anabatic->getGCellUnder( sp );
GCell* tgcell = _anabatic->getGCellUnder( tp ); GCell* tgcell = _anabatic->getGCellUnder( tp );
//cerr << "Gcell: " << sgcell << endl;
//cerr << "Gcell: " << tgcell << endl; cdebug_log(112,0) << "GCell: " << sgcell << endl;
cdebug_log(112,0) << "GCell: " << tgcell << endl;
Vertex* svertex = sgcell->getObserver<Vertex>(GCell::Observable::Vertex); Vertex* svertex = sgcell->getObserver<Vertex>(GCell::Observable::Vertex);
Vertex* tvertex = tgcell->getObserver<Vertex>(GCell::Observable::Vertex); Vertex* tvertex = tgcell->getObserver<Vertex>(GCell::Observable::Vertex);
Contact* sourceSym = NULL; Contact* sourceSym = NULL;
Contact* targetSym = NULL; Contact* targetSym = NULL;
if (state->isSelfSym()){ if (state->isSelfSym()) {
cdebug_log(112,0) << "isSelfSym" << endl; cdebug_log(112,0) << "Symmetrical to myself (isSelfSym)." << endl;
sourceSym = svertex->getGContact( _net ); sourceSym = svertex->getGContact( _net );
targetSym = tvertex->getGContact( _net ); targetSym = tvertex->getGContact( _net );
} else if (state->isSymMaster()){ } else if (state->isSymMaster()){
cdebug_log(112,0) << "isSymPair: " << state->getSymNet() << endl; cdebug_log(112,0) << "Symmetrical to (isSymPair): " << state->getSymNet() << endl;
sourceSym = svertex->getGContact( state->getSymNet() ); sourceSym = svertex->getGContact( state->getSymNet() );
targetSym = tvertex->getGContact( state->getSymNet() ); targetSym = tvertex->getGContact( state->getSymNet() );
} else { } else {
cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong with the symmetry. " << endl; cdebug_log(112,0) << "Dijkstra::_materialize(): Unknown Net pairing symmetry. " << endl;
cdebug_tabw(112,-1);
return; return;
} }
@ -2385,7 +2555,7 @@ namespace Anabatic {
, axis , axis
, state->getWPitch()*Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL2")) , state->getWPitch()*Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL2"))
); );
cdebug_log(112,0) << "|| " << segment2 << endl; cdebug_log(112,0) << "| dup:" << segment2 << endl;
} else if (v) { } else if (v) {
if (state->isSymVertical()){ if (state->isSymVertical()){
//cerr << "V case Vertical" << endl; //cerr << "V case Vertical" << endl;
@ -2399,6 +2569,7 @@ namespace Anabatic {
axis = segment->getX(); axis = segment->getX();
} else { } else {
cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong here. " << endl; cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong here. " << endl;
cdebug_tabw(112,-1);
return; return;
} }
GCell* sgcell = _anabatic->getGCellUnder( sp ); GCell* sgcell = _anabatic->getGCellUnder( sp );
@ -2415,6 +2586,7 @@ namespace Anabatic {
targetSym = tvertex->getGContact( state->getSymNet() ); targetSym = tvertex->getGContact( state->getSymNet() );
} else { } else {
cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong with the symmetry. " << endl; cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong with the symmetry. " << endl;
cdebug_tabw(112,-1);
return; return;
} }
@ -2429,6 +2601,7 @@ namespace Anabatic {
cdebug_log(112,0) << "|| " << segment2 << endl; cdebug_log(112,0) << "|| " << segment2 << endl;
} }
} }
cdebug_tabw(112,-1);
} }

View File

@ -29,16 +29,31 @@ namespace {
using namespace std; using namespace std;
using namespace Hurricane; using namespace Hurricane;
using Anabatic::NetData;
using Anabatic::AnabaticEngine;
class SortSegmentByLength { class SortSegmentByLength {
public: public:
inline bool operator() ( const Segment*, const Segment* ); 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 ) 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(); DbU::Unit delta = rhs->getLength() - lhs->getLength();
if (delta > 0) return true; if (delta > 0) return true;
if (delta < 0) return false; if (delta < 0) return false;
@ -355,16 +370,16 @@ namespace Anabatic {
size_t Edge::ripup () size_t Edge::ripup ()
{ {
AnabaticEngine* anabatic = getAnabatic(); AnabaticEngine* anabatic = getAnabatic();
DbU::Unit globalThreshold = Session::getSliceHeight()*3; size_t netCount = 0;
size_t netCount = 0;
sort( _segments.begin(), _segments.end(), SortSegmentByLength() ); sort( _segments.begin(), _segments.end(), SortSegmentByLength(anabatic) );
if (Session::getRoutingGauge()->isTwoMetals()) { if (Session::getRoutingGauge()->isTwoMetals()) {
for ( size_t i=0 ; i<_segments.size() ; ) { for ( size_t i=0 ; i<_segments.size() ; ) {
if (not isEnding(_segments[i])) { if (not isEnding(_segments[i])) {
NetData* netData = anabatic->getNetData( _segments[i]->getNet() ); NetData* netData = anabatic->getNetData( _segments[i]->getNet() );
if (netData->isGlobalFixed ()) break;
if (netData->isGlobalRouted()) ++netCount; if (netData->isGlobalRouted()) ++netCount;
anabatic->ripup( _segments[i], Flags::Propagate ); anabatic->ripup( _segments[i], Flags::Propagate );
continue; continue;
@ -375,10 +390,12 @@ namespace Anabatic {
size_t truncate = (size_t)( (getCapacity()*2) / 3 ); size_t truncate = (size_t)( (getCapacity()*2) / 3 );
while ( _segments.size() > truncate ) { while ( _segments.size() > truncate ) {
NetData* netData = anabatic->getNetData( _segments[truncate]->getNet() ); NetData* netData = anabatic->getNetData( _segments[truncate]->getNet() );
if (netData->isGlobalFixed ()) break;
if (netData->isGlobalRouted()) ++netCount; if (netData->isGlobalRouted()) ++netCount;
anabatic->ripup( _segments[truncate], Flags::Propagate ); anabatic->ripup( _segments[truncate], Flags::Propagate );
} }
// DbU::Unit globalThreshold = Session::getSliceHeight()*3;
// for ( size_t i=0 ; i<_segments.size() ; ) { // for ( size_t i=0 ; i<_segments.size() ; ) {
// if (_segments[i]->getLength() >= globalThreshold) { // if (_segments[i]->getLength() >= globalThreshold) {
// NetData* netData = anabatic->getNetData( _segments[i]->getNet() ); // NetData* netData = anabatic->getNetData( _segments[i]->getNet() );

View File

@ -298,6 +298,7 @@ namespace Anabatic {
, _contacts () , _contacts ()
, _depth (Session::getRoutingGauge()->getDepth()) , _depth (Session::getRoutingGauge()->getDepth())
, _pinDepth (0) , _pinDepth (0)
, _rpCount (0)
, _blockages (new DbU::Unit [_depth]) , _blockages (new DbU::Unit [_depth])
, _cDensity (0.0) , _cDensity (0.0)
, _densities (new float [_depth]) , _densities (new float [_depth])
@ -305,6 +306,7 @@ namespace Anabatic {
, _fragmentations(new float [_depth]) , _fragmentations(new float [_depth])
, _globalsCount (new float [_depth]) , _globalsCount (new float [_depth])
, _key (this,1) , _key (this,1)
, _lastClonedKey (NULL)
{ {
if (not _matrixHSide) { if (not _matrixHSide) {
_matrixVSide = Session::getSliceHeight(); _matrixVSide = Session::getSliceHeight();
@ -474,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 Contact* GCell::hasGContact ( const Contact* owned ) const
{ {
for ( Contact* contact : _gcontacts ) { for ( Contact* contact : _gcontacts ) {
@ -506,6 +528,22 @@ namespace Anabatic {
} }
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;
}
Edge* GCell::getEdgeTo ( GCell* neighbor, Flags sideHint ) const Edge* GCell::getEdgeTo ( GCell* neighbor, Flags sideHint ) const
{ {
for ( Edge* edge : getEdges(sideHint) ) { for ( Edge* edge : getEdges(sideHint) ) {
@ -1215,7 +1253,7 @@ namespace Anabatic {
int GCell::getCapacity ( size_t depth ) const int GCell::getCapacity ( size_t depth ) const
{ {
const vector<Edge*>* edges = NULL; const vector<Edge*>* edges = NULL;
if (isHorizontalPlane(depth)) edges = (_eastEdges .empty()) ? &_westEdges : &_westEdges; if (isHorizontalPlane(depth)) edges = (_eastEdges .empty()) ? &_westEdges : &_eastEdges;
else edges = (_northEdges.empty()) ? &_southEdges : &_northEdges; else edges = (_northEdges.empty()) ? &_southEdges : &_northEdges;
int capacity = 0; int capacity = 0;
@ -1311,7 +1349,7 @@ namespace Anabatic {
_blockages[depth] += length; _blockages[depth] += length;
_flags |= Flags::Invalidated; _flags |= Flags::Invalidated;
cdebug_log(149,0) << "GCell:addBlockage() " << this << " " cdebug_log(149,0) << "GCell::addBlockage() " << this << " "
<< depth << ":" << DbU::getValueString(_blockages[depth]) << endl; << depth << ":" << DbU::getValueString(_blockages[depth]) << endl;
} }
@ -1345,11 +1383,17 @@ namespace Anabatic {
size_t begin = 0; size_t begin = 0;
for ( ; begin < end ; begin++ ) { for ( ; begin < end ; begin++ ) {
if (not _hsegments[begin])
cerr << Bug( "GCell::removeHSegment(): In %s, NULL segment at [%u/%u]."
, _getString().c_str(), begin, _hsegments.size() ) << endl;
if (_hsegments[begin] == segment) std::swap( _hsegments[begin], _hsegments[--end] ); if (_hsegments[begin] == segment) std::swap( _hsegments[begin], _hsegments[--end] );
cdebug_log(9000,0) << "GCell::removeHSegment() " << this << endl;
cdebug_log(9000,0) << " " << segment << endl;
} }
if (_hsegments.size() == end) { if (_hsegments.size() == end) {
cerr << Bug( "%s do not go through %s." cerr << Bug( "GCell::removeHSegment(): %s do not go through %s."
, getString(segment).c_str(), _getString().c_str() ) << endl; , getString(segment).c_str(), _getString().c_str() ) << endl;
return; return;
} }
@ -1397,11 +1441,6 @@ namespace Anabatic {
_flags.reset( Flags::Saturated ); _flags.reset( Flags::Saturated );
for ( size_t i=0 ; i<_vsegments.size() ; i++ ) {
if ( _vsegments[i] == NULL )
cerr << "NULL Autosegment at index " << i << endl;
}
sort( _hsegments.begin(), _hsegments.end(), AutoSegment::CompareByDepthLength() ); sort( _hsegments.begin(), _hsegments.end(), AutoSegment::CompareByDepthLength() );
sort( _vsegments.begin(), _vsegments.end(), AutoSegment::CompareByDepthLength() ); sort( _vsegments.begin(), _vsegments.end(), AutoSegment::CompareByDepthLength() );
@ -1488,7 +1527,14 @@ namespace Anabatic {
} }
// Add the blockages. // Add the blockages.
for ( size_t i=0 ; i<_depth ; i++ ) uLengths2[i] += _blockages[i]; 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. // Compute the number of non pass-through tracks.
if (not processeds.empty()) { if (not processeds.empty()) {
@ -1498,7 +1544,8 @@ namespace Anabatic {
size_t depth = Session::getRoutingGauge()->getLayerDepth(layer); size_t depth = Session::getRoutingGauge()->getLayerDepth(layer);
size_t count = 0; size_t count = 0;
for ( ; isegment != processeds.end(); ++isegment ) { for ( ; isegment != processeds.end(); ++isegment ) {
_feedthroughs[depth] += ((*isegment)->isGlobal()) ? 0.50 : 0.33; //_feedthroughs[depth] += ((*isegment)->isGlobal()) ? 0.50 : 0.33;
_feedthroughs[depth] += 0.50;
localCounts [depth] += 1.0; localCounts [depth] += 1.0;
if ( (*isegment)->isGlobal() ) _globalsCount[depth] += 1.0; if ( (*isegment)->isGlobal() ) _globalsCount[depth] += 1.0;
@ -1736,7 +1783,7 @@ namespace Anabatic {
bool GCell::stepNetDesaturate ( size_t depth, set<Net*>& globalNets, GCell::Set& invalidateds ) bool GCell::stepNetDesaturate ( size_t depth, set<Net*>& globalNets, GCell::Set& invalidateds )
{ {
cdebug_log(9000,0) << "Deter| GCell::stepNetDesaturate() depth:" << depth << endl; cdebug_log(149,0) << "GCell::stepNetDesaturate() depth:" << depth << endl;
cdebug_log(9000,0) << "Deter| " << this << endl; cdebug_log(9000,0) << "Deter| " << this << endl;
updateDensity(); updateDensity();
@ -1758,7 +1805,7 @@ namespace Anabatic {
if (segmentDepth < depth) continue; if (segmentDepth < depth) continue;
if (segmentDepth > depth) break; if (segmentDepth > depth) break;
cdebug_log(9000,0) << "Deter| Move up " << (*isegment) << endl; cdebug_log(149,0) << "Move up " << (*isegment) << endl;
if (getAnabatic()->moveUpNetTrunk(*isegment,globalNets,invalidateds)) if (getAnabatic()->moveUpNetTrunk(*isegment,globalNets,invalidateds))
return true; return true;
@ -1790,6 +1837,7 @@ namespace Anabatic {
string s = Super::_getString(); string s = Super::_getString();
s.insert( s.size()-1, " "+getString(getBoundingBox()) ); s.insert( s.size()-1, " "+getString(getBoundingBox()) );
s.insert( s.size()-1, " "+getString(_flags) ); s.insert( s.size()-1, " "+getString(_flags) );
s.insert( s.size()-1, " "+getString(_rpCount) );
/* string s = "<GCell at(" + DbU::getValueString(getXMin()) /* string s = "<GCell at(" + DbU::getValueString(getXMin())
+ "-" + DbU::getValueString(getYMin()) + "-" + DbU::getValueString(getYMin())
+ "-" + DbU::getValueString(getXMax()) + "-" + DbU::getValueString(getXMax())
@ -1822,7 +1870,7 @@ namespace Anabatic {
ostringstream s; ostringstream s;
const Layer* layer = rg->getRoutingLayer(depth)->getBlockageLayer(); const Layer* layer = rg->getRoutingLayer(depth)->getBlockageLayer();
s << "_blockages[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]"; s << "_blockages[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
record->add( getSlot ( s.str(), &_blockages[depth] ) ); record->add( DbU::getValueSlot( s.str(), &_blockages[depth] ) );
} }
for ( size_t depth=0 ; depth<_depth ; ++depth ) { for ( size_t depth=0 ; depth<_depth ; ++depth ) {

View File

@ -31,11 +31,287 @@
#include "hurricane/Horizontal.h" #include "hurricane/Horizontal.h"
#include "hurricane/Cell.h" #include "hurricane/Cell.h"
#include "crlcore/RoutingGauge.h" #include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContact.h" #include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoSegment.h" #include "anabatic/AutoSegment.h"
#include "anabatic/AnabaticEngine.h" #include "anabatic/AnabaticEngine.h"
namespace {
using namespace std;
using namespace CRL;
using namespace Hurricane;
using namespace Anabatic;
class SortRpByX {
public:
inline SortRpByX ();
inline bool operator() ( RoutingPad* rp1, RoutingPad* rp2 );
};
inline SortRpByX::SortRpByX ()
{ }
inline bool SortRpByX::operator() ( RoutingPad* rp1, RoutingPad* rp2 )
{
DbU::Unit x1 = rp1->getCenter().getX();
DbU::Unit x2 = rp2->getCenter().getX();
if (x1 == x2) return false;
return (x1 < x2);
}
// -----------------------------------------------------------------
// Class : "RpsInRow".
class RpsInRow {
public:
class Compare {
public:
bool operator() ( const RpsInRow* lhs, const RpsInRow* rhs ) const;
};
public:
inline RpsInRow ( RoutingPad*, AnabaticEngine* );
inline const vector<RoutingPad*>& getRps () const;
inline size_t getSouth () const;
inline size_t getNorth () const;
inline const Interval& getRpsHSpan () const;
inline const Interval& getRpsVSpan () const;
void slacken ();
private:
void _findTopology ();
inline void _merge ( RoutingPad* );
private:
AnabaticEngine* _anabatic;
vector<RoutingPad*> _rps;
size_t _north;
size_t _south;
Interval _hSpan;
Interval _vSpan;
};
inline RpsInRow::RpsInRow ( RoutingPad* seed, AnabaticEngine* anabatic )
: _anabatic(anabatic)
, _rps ()
, _north (0)
, _south (0)
, _hSpan ()
, _vSpan ( false )
{
_rps.push_back( seed );
_findTopology();
}
inline const vector<RoutingPad*>& RpsInRow::getRps () const { return _rps; }
inline size_t RpsInRow::getSouth () const { return _south; }
inline size_t RpsInRow::getNorth () const { return _north; }
inline const Interval& RpsInRow::getRpsHSpan () const { return _hSpan; }
inline const Interval& RpsInRow::getRpsVSpan () const { return _vSpan; }
bool RpsInRow::Compare::operator() ( const RpsInRow* lhs, const RpsInRow* rhs ) const
{
if ( (lhs->_rps.size() == 2) and (rhs->_rps.size() != 2) ) return true;
if ( (lhs->_rps.size() != 2) and (rhs->_rps.size() == 2) ) return false;
if ( lhs->_rps.size() != rhs->_rps.size() ) return lhs->_rps.size() < rhs->_rps.size();
size_t lhsNs = lhs->_south + lhs->_north;
size_t rhsNs = rhs->_south + rhs->_north;
if (lhsNs != rhsNs) return lhsNs < rhsNs;
if (lhs->_vSpan != rhs->_vSpan) return lhs->_vSpan.getSize() < rhs->_vSpan.getSize();
if (lhs->_hSpan != rhs->_hSpan) return lhs->_hSpan.getSize() < rhs->_hSpan.getSize();
return lhs->_rps[0]->getId() < rhs->_rps[0]->getId();
}
inline void RpsInRow::_merge ( RoutingPad* rp )
{
if (rp != _rps[0]) _rps.push_back( rp );
Box bb ( _rps.back()->getBoundingBox() );
_hSpan.merge( bb.getCenter().getX() );
_vSpan.intersection( bb.getYMin(), bb.getYMax() );
}
void RpsInRow::_findTopology ()
{
cdebug_log(146,1) << "RpsInRow::findTopology() - " << _rps[0] << endl;
_merge( _rps[0] );
AutoSegmentStack stack;
for ( Component* component : _rps[0]->getSlaveComponents() ) {
cdebug_log(146,0) << "slave component: " << component << endl;
AutoContact* rpContact = Session::lookup( dynamic_cast<Contact*>(component) );
if (rpContact) {
cdebug_log(146,0) << "Start rp: " << rpContact << endl;
for ( AutoSegment* segment : rpContact->getAutoSegments() ) {
cdebug_log(146,0) << "Examining: " << segment << endl;
AutoContact* target = segment->getOppositeAnchor(rpContact);
if (target) {
if (segment->isHorizontal()) {
stack.push( target, segment );
} else {
if (segment->isLocal()) {
stack.push( target, segment );
} else {
if (segment->getAutoSource() == rpContact) ++_north;
else ++_south;
}
}
}
}
// Find Rps in same horizontal GCell range.
cdebug_log(146,0) << "Find Rps in same horizontal GCell range" << endl;
while ( not stack.isEmpty() ) {
AutoSegment* from = stack.getAutoSegment();
AutoContact* contact = stack.getAutoContact();
stack.pop();
for ( AutoSegment* segment : contact->getAutoSegments() ) {
if (segment == from) continue;
if (segment->isVertical() and not segment->isLocal()) {
if (segment->getAutoSource() == contact) ++_north;
else ++_south;
continue;
}
AutoContact* target = segment->getOppositeAnchor( contact );
AutoContactTerminal* terminal = dynamic_cast<AutoContactTerminal*>( target );
if (terminal) {
_merge( terminal->getRoutingPad() );
}
stack.push( target, segment );
}
}
}
}
sort( _rps.begin(), _rps.end(), SortRpByX() );
cdebug_log(146,0) << "findHAlignedsRps() - Exit" << endl;
cdebug_tabw(146,-1);
}
void RpsInRow::slacken ()
{
cdebug_log(149,1) << "RpsInRow::slacken()" << endl;
for ( RoutingPad* rp : _rps ) {
cdebug_log(149,0) << "Slacken from: " << rp << endl;
if (rp->getLayer()) {
if (_anabatic->getConfiguration()->getLayerDepth(rp->getLayer()) == 1)
cdebug_log(149,0) << "In METAL2, skiping" << endl;
continue;
}
for ( Component* component : rp->getSlaveComponents() ) {
AutoContact* rpContact = Session::lookup( dynamic_cast<Contact*>(component) );
if (rpContact) {
cdebug_log(149,0) << "+ " << rpContact << endl;
for ( AutoSegment* segment : rpContact->getAutoSegments() ) {
cdebug_log(149,0) << "| " << segment << endl;
if (segment->isVertical()) {
if (segment->getDepth() == 1) {
cdebug_log(149,0) << "| Slacken: " << segment << endl;
segment->changeDepth( 2, Flags::NoFlags );
cdebug_log(149,0) << "| After Slacken: " << segment << endl;
}
} else {
segment->makeDogleg( rpContact->getGCell() );
cdebug_log(149,0) << "| Make dogleg: " << segment << endl;
}
}
}
}
}
cdebug_tabw(149,-1);
}
// -----------------------------------------------------------------
// Class : "GCellRps".
class GCellRps {
public:
class Compare {
public:
bool operator() ( const GCellRps* lhs, const GCellRps* rhs ) const;
};
public:
GCellRps ( GCell*, AnabaticEngine* );
~GCellRps ();
inline GCell* getGCell () const;
inline size_t add ( RoutingPad* );
inline void consolidate ();
inline RpsInRow* getRpsInRow ( size_t i );
inline const vector<RpsInRow*>& getRpsInRows () const;
private:
AnabaticEngine* _anabatic;
GCell* _gcell;
vector<RpsInRow*> _rpsInRows;
};
GCellRps::GCellRps ( GCell* gcell, AnabaticEngine* anabatic )
: _anabatic (anabatic)
, _gcell (gcell)
, _rpsInRows()
{ }
GCellRps::~GCellRps ()
{
for ( RpsInRow* elem : _rpsInRows ) delete elem;
}
inline GCell* GCellRps::getGCell () const { return _gcell; }
inline size_t GCellRps::add ( RoutingPad* rp )
{
_rpsInRows.push_back( new RpsInRow(rp,_anabatic) );
return _rpsInRows.size() - 1;
}
inline void GCellRps::consolidate ()
{
sort( _rpsInRows.begin(), _rpsInRows.end(), RpsInRow::Compare() );
}
inline RpsInRow* GCellRps::getRpsInRow ( size_t i ) { return _rpsInRows[i]; }
inline const vector<RpsInRow*>& GCellRps::getRpsInRows () const { return _rpsInRows; }
bool GCellRps::Compare::operator() ( const GCellRps* lhs, const GCellRps* rhs ) const
{ return lhs->getGCell()->getId() < rhs->getGCell()->getId(); }
} // Anonymous namespace.
namespace Anabatic { namespace Anabatic {
using Hurricane::DebugSession; using Hurricane::DebugSession;
@ -59,9 +335,55 @@ namespace Anabatic {
cmess1 << " o Desaturate layer " cmess1 << " o Desaturate layer "
<< Session::getRoutingGauge()->getRoutingLayer(depth)->getName() << endl; << Session::getRoutingGauge()->getRoutingLayer(depth)->getName() << endl;
cdebug_log(149,0) << "Session::getSaturateRatio()=" << Session::getSaturateRatio() << endl;
GCellKeyQueue queue;
GCell::Set invalidateds;
for ( GCell* gcell : getGCells() ) queue.push( gcell->cloneKey(depth) );
bool optimized = true;
bool finished = false;
while ( optimized ) {
Session::revalidate ();
optimized = false;
while ( not queue.empty() ) {
GCell::Key* topKey = queue.top();
GCell* gcell = const_cast<GCell*>( topKey->getGCell() );
queue.pop();
if (topKey->isActive()) {
cdebug_log(149,0) << "_desaturate: [" << depth << "]:"
<< gcell->getDensity(depth) << " " << gcell << endl;
if (not gcell->isSaturated(depth)) {
cdebug_log(149,0) << "STOP desaturated: " << gcell << endl;
finished = true;
} else {
if (finished) {
cparanoid << "[ERROR] Still saturated: " << gcell << endl;
}
}
if (not finished) {
optimized = gcell->stepNetDesaturate( depth, globalNets, invalidateds );
if (optimized) {
for ( GCell* gcell : invalidateds ) {
queue.push( gcell->cloneKey(depth) );
}
}
}
}
delete topKey;
}
}
#if OLD_QUEUE_DISABLED
GCellDensitySet queue ( depth, getGCells() ); GCellDensitySet queue ( depth, getGCells() );
GCell::Set invalidateds; GCell::Set invalidateds;
bool optimized = true; bool optimized = true;
while ( optimized ) { while ( optimized ) {
@ -73,7 +395,7 @@ namespace Anabatic {
size_t i = 0; size_t i = 0;
for ( ; igcell!=queue.getGCells().end() ; ++igcell, ++i ) { for ( ; igcell!=queue.getGCells().end() ; ++igcell, ++i ) {
cdebug_log(149,0) << "_desaturate: [" << depth << "]:" cdebug_log(149,0) << "_desaturate: [" << depth << "]:"
<< (*igcell)->getDensity(depth) << " " << *igcell << endl; << (*igcell)->getDensity(depth) << " " << *igcell << endl;
if (not (*igcell)->isSaturated(depth)) { if (not (*igcell)->isSaturated(depth)) {
cdebug_log(149,0) << "STOP desaturated: @" << i << " " << *igcell << endl; cdebug_log(149,0) << "STOP desaturated: @" << i << " " << *igcell << endl;
@ -95,6 +417,7 @@ namespace Anabatic {
} }
} }
} }
#endif
} }
@ -251,8 +574,8 @@ namespace Anabatic {
vector<AutoSegment*> southBounds; vector<AutoSegment*> southBounds;
DbU::Unit leftBound; DbU::Unit leftBound;
DbU::Unit rightBound; DbU::Unit rightBound;
bool hasNorth = false; //bool hasNorth = false;
bool hasSouth = false; //bool hasSouth = false;
AutoSegment::getTopologicalInfos( horizontal AutoSegment::getTopologicalInfos( horizontal
, collapseds , collapseds
@ -431,7 +754,7 @@ namespace Anabatic {
if (not segment->isStrongTerminal()) locals.push_back( segment ); if (not segment->isStrongTerminal()) locals.push_back( segment );
continue; continue;
} }
if ( (segment->getLength() < 3*Session::getSliceHeight()) and (segment != seed) ) { if ( (segment->getAnchoredLength() < 3*Session::getSliceHeight()) and (segment != seed) ) {
locals.push_back( segment ); locals.push_back( segment );
continue; continue;
} }
@ -599,6 +922,8 @@ namespace Anabatic {
void AnabaticEngine::layerAssign ( uint32_t method ) void AnabaticEngine::layerAssign ( uint32_t method )
{ {
//DebugSession::open( 145, 150 );
cdebug_log(9000,0) << "Deter| Layer Assignment" << endl; cdebug_log(9000,0) << "Deter| Layer Assignment" << endl;
set<Net*> globalNets; set<Net*> globalNets;
@ -646,6 +971,54 @@ namespace Anabatic {
Session::setAnabaticFlags( Flags::WarnOnGCellOverload ); Session::setAnabaticFlags( Flags::WarnOnGCellOverload );
} }
set<GCellRps*,GCellRps::Compare> gcellRpss;
for ( GCell* gcell : getGCells() ) {
set<RoutingPad*,Entity::CompareById> rps;
const vector<AutoContact*> contacts = gcell->getContacts();
for ( AutoContact* contact : contacts ) {
AutoContactTerminal* terminal = dynamic_cast<AutoContactTerminal*>( contact );
if (terminal) {
rps.insert( terminal->getRoutingPad() );
}
}
if (rps.size() > 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(); checkGCellDensities();
Session::close(); Session::close();
@ -656,6 +1029,8 @@ namespace Anabatic {
// cmess2 << " - Global segments : " << global << endl; // cmess2 << " - Global segments : " << global << endl;
// cmess2 << " - Ratio : " // cmess2 << " - Ratio : "
// << ((float)global/(float)total)*100.0 << "%." << endl; // << ((float)global/(float)total)*100.0 << "%." << endl;
//DebugSession::close();
} }

View File

@ -228,22 +228,44 @@ namespace Anabatic {
void NetBuilder::getPositions ( Component* anchor, Point& source, Point& target ) void NetBuilder::getPositions ( Component* anchor, Point& source, Point& target )
{ {
Segment* segment = dynamic_cast<Segment*>( anchor ); Segment* segment = dynamic_cast<Segment*>( anchor );
if (segment) { if (segment) {
source = segment->getSourcePosition(); source = segment->getSourcePosition();
target = segment->getTargetPosition(); target = segment->getTargetPosition();
return; } else {
RoutingPad* rp = dynamic_cast<RoutingPad*>( anchor );
if (rp) {
source = rp->getSourcePosition();
target = rp->getTargetPosition();
} else {
source = anchor->getPosition();
target = anchor->getPosition();
return;
}
} }
RoutingPad* rp = dynamic_cast<RoutingPad*>( anchor ); if (source == target) return;
if (rp) { if (source.getX() > target.getX()) swap( source, target );
source = rp->getSourcePosition(); if (source.getY() > target.getY()) swap( source, target );
target = rp->getTargetPosition();
return;
}
source = anchor->getPosition(); if (not Session::getRoutingGauge()->isSymbolic()) {
target = anchor->getPosition(); size_t rpDepth = Session::getLayerDepth( anchor->getLayer() );
Flags direction = Session::getDirection ( rpDepth );
DbU::Unit wwidth = Session::getWireWidth (rpDepth) / 2;
cdebug_log(145,0) << "Not a symbolic gauge, shrink positions of " << DbU::getValueString(wwidth) << endl;
if (rpDepth == 0) return;
if (direction.contains(Flags::Horizontal)) {
cdebug_log(145,0) << "H shrink" << endl;
source.translate( wwidth, 0 );
target.translate( -wwidth, 0 );
} else {
cdebug_log(145,0) << "V shrink" << endl;
source.translate( 0, wwidth );
target.translate( 0, -wwidth );
}
} else {
cdebug_log(145,0) << "Symbolic gauge, no shrink" << endl;
}
} }
@ -401,14 +423,14 @@ namespace Anabatic {
for ( Hook* hook : fromHook->getHooks() ) { for ( Hook* hook : fromHook->getHooks() ) {
cdebug_log(145,0) << "Hook: " << hook << endl; cdebug_log(145,0) << "Hook: " << hook << endl;
cdebug_log(145,0) << "Topology [" << _connexity.connexity << "] = " cdebug_log(145,0) << "Topology [" << _connexity.connexity << "] = "
<< "[" << (int)_connexity.fields.globals << "[" << (int)_connexity.fields.globals
<< "+" << (int)_connexity.fields.M1 << "+" << (int)_connexity.fields.M1
<< "+" << (int)_connexity.fields.M2 << "+" << (int)_connexity.fields.M2
<< "+" << (int)_connexity.fields.M3 << "+" << (int)_connexity.fields.M3
<< "+" << (int)_connexity.fields.Pin << "+" << (int)_connexity.fields.Pin
<< "+" << (int)_connexity.fields.Pad << "+" << (int)_connexity.fields.Pad
<< "] " << _gcell << "] " << _gcell
<< endl; << endl;
Segment* toSegment = dynamic_cast<Segment*>( hook->getComponent() ); Segment* toSegment = dynamic_cast<Segment*>( hook->getComponent() );
if (toSegment) { if (toSegment) {
@ -507,6 +529,16 @@ namespace Anabatic {
if (_gcell == NULL) throw Error( missingGCell ); if (_gcell == NULL) throw Error( missingGCell );
cdebug_log(145,0) << "Topology [" << _connexity.connexity << "] = "
<< "[" << (int)_connexity.fields.globals
<< "+" << (int)_connexity.fields.M1
<< "+" << (int)_connexity.fields.M2
<< "+" << (int)_connexity.fields.M3
<< "+" << (int)_connexity.fields.Pin
<< "+" << (int)_connexity.fields.Pad
<< "] " << _gcell
<< endl;
return *this; return *this;
} }
@ -543,6 +575,15 @@ namespace Anabatic {
void NetBuilder::construct () void NetBuilder::construct ()
{ {
cdebug_log(145,1) << "NetBuilder::construct() [" << _connexity.connexity << "] in " << _gcell << endl; cdebug_log(145,1) << "NetBuilder::construct() [" << _connexity.connexity << "] in " << _gcell << endl;
cdebug_log(145,0) << "Topology [" << _connexity.connexity << "] = "
<< "[" << (int)_connexity.fields.globals
<< "+" << (int)_connexity.fields.M1
<< "+" << (int)_connexity.fields.M2
<< "+" << (int)_connexity.fields.M3
<< "+" << (int)_connexity.fields.Pin
<< "+" << (int)_connexity.fields.Pad
<< "] " << _gcell
<< endl;
if (not isTwoMetals()) { if (not isTwoMetals()) {
_southWestContact = NULL; _southWestContact = NULL;
@ -562,7 +603,11 @@ namespace Anabatic {
case Conn_1G_2M1: case Conn_1G_2M1:
case Conn_1G_3M1: case Conn_1G_3M1:
case Conn_1G_4M1: case Conn_1G_4M1:
case Conn_1G_5M1: _do_1G_xM1(); break; case Conn_1G_5M1:
case Conn_1G_6M1:
case Conn_1G_7M1:
case Conn_1G_8M1:
case Conn_1G_9M1: _do_1G_xM1(); break;
// End 1G_xM1 cascaded cases. // End 1G_xM1 cascaded cases.
case Conn_1G_1M2: case Conn_1G_1M2:
@ -582,17 +627,31 @@ namespace Anabatic {
case Conn_2G_3M1: case Conn_2G_3M1:
case Conn_2G_4M1: case Conn_2G_4M1:
case Conn_2G_5M1: case Conn_2G_5M1:
case Conn_2G_6M1:
case Conn_2G_7M1:
case Conn_2G_8M1:
case Conn_2G_9M1:
case Conn_3G_1M1: if (_do_xG_1M1()) break; case Conn_3G_1M1: if (_do_xG_1M1()) break;
case Conn_3G_2M1: case Conn_3G_2M1:
case Conn_3G_3M1: case Conn_3G_3M1:
case Conn_3G_4M1: case Conn_3G_4M1:
case Conn_3G_5M1:
case Conn_3G_6M1:
case Conn_3G_7M1:
case Conn_3G_8M1:
case Conn_3G_9M1:
case Conn_3G_2M3: case Conn_3G_2M3:
case Conn_3G_3M3: case Conn_3G_3M3:
case Conn_3G_4M3: case Conn_3G_4M3:
case Conn_4G_1M1: if (_do_xG_1M1()) break; case Conn_4G_1M1: if (_do_xG_1M1()) break;
case Conn_4G_2M1: case Conn_4G_2M1:
case Conn_4G_3M1: case Conn_4G_3M1:
case Conn_4G_4M1: _do_xG_xM1_xM3(); break; case Conn_4G_4M1:
case Conn_4G_5M1:
case Conn_4G_6M1:
case Conn_4G_7M1:
case Conn_4G_8M1:
case Conn_4G_9M1: _do_xG_xM1_xM3(); break;
// End xG_xM1_xM3 cascaded cases. // End xG_xM1_xM3 cascaded cases.
case Conn_4G_1M2: if (_do_4G_1M2()) break; case Conn_4G_1M2: if (_do_4G_1M2()) break;
@ -616,19 +675,32 @@ namespace Anabatic {
case Conn_4G: _do_xG(); break; case Conn_4G: _do_xG(); break;
// End xG cascaded cases. // End xG cascaded cases.
// Optimized specific cases. // Optimized specific cases.
case Conn_1G_1PinM2: _do_1G_1PinM2 (); break; case Conn_1G_1PinM1: _do_1G_1PinM1 (); break;
case Conn_2G_1PinM1: _do_2G_1PinM1 (); break;
case Conn_1G_1PinM2: _do_1G_1PinM2 (); break;
case Conn_2G_1PinM2: case Conn_2G_1PinM2:
case Conn_3G_1PinM2: _do_xG_1PinM2 (); break; case Conn_3G_1PinM2: _do_xG_1PinM2 (); break;
case Conn_1G_1PinM3: _do_1G_1PinM3 (); break; case Conn_1G_1PinM3: _do_1G_1PinM3 (); break;
case Conn_2G_1PinM3: case Conn_2G_1PinM3:
case Conn_3G_1PinM3: _do_xG_1PinM3 (); break; case Conn_3G_1PinM3: _do_xG_1PinM3 (); break;
case Conn_1G_1M1_1M2: _do_xG_1M1_1M2(); break; case Conn_1G_1M1_1PinM3: _do_1G_1M1_1PinM3(); break;
case Conn_1G_1M1_1M3: _do_1G_xM1 (); break; case Conn_1G_1M1_1PinM2:
case Conn_2G_1M1_1M2: _do_xG_1M1_1M2(); break; case Conn_1G_2M1_1PinM2: _do_1G_xM1_1PinM2(); break;
case Conn_2G_1M1_1PinM2:
case Conn_2G_2M1_1PinM2: _do_2G_xM1_1PinM2(); break;
case Conn_2G_1M1_1PinM3:
case Conn_2G_2M1_1PinM3:
case Conn_2G_3M1_1PinM3: _do_2G_xM1_1PinM3(); break;
case Conn_3G_1M1_1PinM3:
case Conn_3G_2M1_1PinM3:
case Conn_3G_3M1_1PinM3: _do_3G_xM1_1PinM3(); break;
case Conn_1G_1M1_1M2: _do_xG_1M1_1M2 (); break;
case Conn_1G_1M1_1M3: _do_1G_xM1 (); break;
case Conn_2G_1M1_1M2: _do_xG_1M1_1M2 (); break;
default: default:
if (not isTwoMetals()) if (not isTwoMetals())
throw Bug( "Unmanaged Configuration [%d] = [%d+%d+%d+%d,%d+%d] %s in %s\n" throw Bug( "Unmanaged Configuration [%d] = [%d+%d+%d+%d,%d+%d] %s in %s\n"
" The global routing seems to be defective." " The global routing seems to be defective."
, _connexity.connexity , _connexity.connexity
, _connexity.fields.globals , _connexity.fields.globals
, _connexity.fields.M1 , _connexity.fields.M1
@ -962,6 +1034,20 @@ namespace Anabatic {
} }
bool NetBuilder::_do_1G_1PinM1 ()
{
throw Error ( "%s::_do_1G_1PinM1() method *not* reimplemented from base class.", getTypeName().c_str() );
return false;
}
bool NetBuilder::_do_2G_1PinM1 ()
{
throw Error ( "%s::_do_2G_1PinM1() method *not* reimplemented from base class.", getTypeName().c_str() );
return false;
}
bool NetBuilder::_do_xG_1PinM2 () bool NetBuilder::_do_xG_1PinM2 ()
{ {
throw Error ( "%s::_do_xG_1PinM2() method *not* reimplemented from base class.", getTypeName().c_str() ); throw Error ( "%s::_do_xG_1PinM2() method *not* reimplemented from base class.", getTypeName().c_str() );
@ -1053,6 +1139,41 @@ namespace Anabatic {
} }
bool NetBuilder::_do_1G_1M1_1PinM3 ()
{
throw Error ( "%s::_do_1G_1M1_1PinM3() method *not* reimplemented from base class.", getTypeName().c_str() );
return false;
}
bool NetBuilder::_do_1G_xM1_1PinM2 ()
{
throw Error ( "%s::_do_1G_xM1_1PinM2() method *not* reimplemented from base class.", getTypeName().c_str() );
return false;
}
bool NetBuilder::_do_2G_xM1_1PinM2 ()
{
throw Error ( "%s::_do_2G_xM1_1PinM2() method *not* reimplemented from base class.", getTypeName().c_str() );
return false;
}
bool NetBuilder::_do_2G_xM1_1PinM3 ()
{
throw Error ( "%s::_do_2G_xM1_1PinM3() method *not* reimplemented from base class.", getTypeName().c_str() );
return false;
}
bool NetBuilder::_do_3G_xM1_1PinM3 ()
{
throw Error ( "%s::_do_3G_xM1_1PinM3() method *not* reimplemented from base class.", getTypeName().c_str() );
return false;
}
bool NetBuilder::_do_globalSegment () bool NetBuilder::_do_globalSegment ()
{ {
throw Error ( "%s::_do_globalSegment() method *not* reimplemented from base class.", getTypeName().c_str() ); throw Error ( "%s::_do_globalSegment() method *not* reimplemented from base class.", getTypeName().c_str() );
@ -2245,8 +2366,10 @@ namespace Anabatic {
size_t degree = routingPads.getSize(); size_t degree = routingPads.getSize();
if (degree == 0) { if (degree == 0) {
cmess2 << Warning("Net \"%s\" do not have any RoutingPad (ignored)." if (not net->isBlockage()) {
,getString(net->getName()).c_str()) << endl; cmess2 << Warning( "Net \"%s\" do not have any RoutingPad (ignored)."
, getString(net->getName()).c_str() ) << endl;
}
cdebug_tabw(145,-1); cdebug_tabw(145,-1);
return; return;
} }

File diff suppressed because it is too large Load Diff

View File

@ -318,7 +318,7 @@ namespace Anabatic {
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl; cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE. // HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getLength() < 2*Session::getSliceHeight()) ) if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
addToFixSegments( globalSegment ); addToFixSegments( globalSegment );
if (getConnexity().fields.globals < 2) { if (getConnexity().fields.globals < 2) {

View File

@ -521,6 +521,12 @@ namespace Anabatic {
} }
bool NetBuilderVH::_do_2G ()
{
cdebug_log(145,0) << getTypeName() << "::_do_2G()" << endl;
return _do_xG();
}
bool NetBuilderVH::_do_xG () bool NetBuilderVH::_do_xG ()
{ {
cdebug_log(145,1) << getTypeName() << "::_do_xG()" << endl; cdebug_log(145,1) << getTypeName() << "::_do_xG()" << endl;
@ -571,7 +577,7 @@ namespace Anabatic {
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl; cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE. // HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getLength() < 2*Session::getSliceHeight()) ) if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
addToFixSegments( globalSegment ); addToFixSegments( globalSegment );
if (getConnexity().fields.globals < 2) { if (getConnexity().fields.globals < 2) {

View File

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

View File

@ -35,6 +35,7 @@ namespace Anabatic {
using Hurricane::RegularLayer; using Hurricane::RegularLayer;
using Hurricane::Component; using Hurricane::Component;
using Hurricane::Pin; using Hurricane::Pin;
using Hurricane::Plug;
using Hurricane::DeepNet; using Hurricane::DeepNet;
using Hurricane::Cell; using Hurricane::Cell;
using Hurricane::NetRoutingExtension; using Hurricane::NetRoutingExtension;
@ -85,16 +86,30 @@ namespace Anabatic {
vector<Segment*> segments; vector<Segment*> segments;
vector<Contact*> contacts; vector<Contact*> contacts;
bool isPreRouted = false; bool isManualGlobalRouted = false;
bool isFixed = false; bool isManualDetailRouted = false;
size_t rpCount = 0; bool isFixed = false;
size_t rpCount = 0;
for( Component* component : net->getComponents() ) { for( Component* component : net->getComponents() ) {
if (dynamic_cast<Pin*>(component)) continue; if (dynamic_cast<Pin *>(component)) continue;
if (dynamic_cast<Plug*>(component)) continue;
const RegularLayer* layer = dynamic_cast<const RegularLayer*>(component->getLayer()); const RegularLayer* layer = dynamic_cast<const RegularLayer*>(component->getLayer());
if (layer and (layer->getBasicLayer()->getMaterial() == BasicLayer::Material::blockage)) if (layer and (layer->getBasicLayer()->getMaterial() == BasicLayer::Material::blockage))
continue; continue;
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); Horizontal* horizontal = dynamic_cast<Horizontal*>(component);
if (horizontal) { if (horizontal) {
@ -102,30 +117,42 @@ namespace Anabatic {
and not ab.contains(horizontal->getTargetPosition()) ) continue; and not ab.contains(horizontal->getTargetPosition()) ) continue;
segments.push_back( horizontal ); segments.push_back( horizontal );
isPreRouted = true; if (Session::isGLayer(component->getLayer())) {
if (horizontal->getWidth() != Session::getWireWidth(horizontal->getLayer())) isManualGlobalRouted = true;
isFixed = true; } else {
isManualDetailRouted = true;
if (horizontal->getWidth() != Session::getWireWidth(horizontal->getLayer()))
isFixed = true;
}
} else { } else {
Vertical* vertical = dynamic_cast<Vertical*>(component); Vertical* vertical = dynamic_cast<Vertical*>(component);
if (vertical) { if (vertical) {
if ( not ab.contains(vertical->getSourcePosition()) if ( not ab.contains(vertical->getSourcePosition())
and not ab.contains(vertical->getTargetPosition()) ) continue; and not ab.contains(vertical->getTargetPosition()) ) continue;
isPreRouted = true; if (Session::isGLayer(component->getLayer())) {
segments.push_back( vertical ); isManualGlobalRouted = true;
if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer())) } else {
isFixed = true; isManualDetailRouted = true;
segments.push_back( vertical );
if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer()))
isFixed = true;
}
} else { } else {
Contact* contact = dynamic_cast<Contact*>(component); Contact* contact = dynamic_cast<Contact*>(component);
if (contact) { if (contact) {
if (not ab.contains(contact->getCenter())) continue; if (not ab.contains(contact->getCenter())) continue;
isPreRouted = true; if (Session::isGLayer(component->getLayer())) {
contacts.push_back( contact ); isManualGlobalRouted = true;
if ( (contact->getWidth () != Session::getViaWidth(contact->getLayer())) } else {
or (contact->getHeight() != Session::getViaWidth(contact->getLayer())) isManualGlobalRouted = true;
or (contact->getLayer () == Session::getContactLayer(0)) ) contacts.push_back( contact );
isFixed = true; if ( (contact->getWidth () != Session::getViaWidth(contact->getLayer()))
or (contact->getHeight() != Session::getViaWidth(contact->getLayer()))
or (contact->getLayer () == Session::getContactLayer(0)) )
isFixed = true;
}
} else { } else {
RoutingPad* rp = dynamic_cast<RoutingPad*>(component); RoutingPad* rp = dynamic_cast<RoutingPad*>(component);
if (rp) { if (rp) {
@ -142,7 +169,10 @@ namespace Anabatic {
} }
} }
if ((not isFixed and not isPreRouted) and net->isDeepNet()) { if ( (not isFixed)
and (not isManualGlobalRouted)
and (not isManualDetailRouted)
and net->isDeepNet()) {
Net* rootNet = dynamic_cast<Net*>( Net* rootNet = dynamic_cast<Net*>(
dynamic_cast<DeepNet*>(net)->getRootNetOccurrence().getEntity() ); dynamic_cast<DeepNet*>(net)->getRootNetOccurrence().getEntity() );
for( Component* component : rootNet->getComponents() ) { for( Component* component : rootNet->getComponents() ) {
@ -152,29 +182,34 @@ namespace Anabatic {
} }
} }
if (isFixed or isPreRouted or (rpCount < 2)) { if (isFixed or isManualDetailRouted or isManualGlobalRouted or (rpCount < 2)) {
NetData* ndata = getNetData( net, Flags::Create ); NetData* ndata = getNetData( net, Flags::Create );
NetRoutingState* state = ndata->getNetRoutingState(); NetRoutingState* state = ndata->getNetRoutingState();
state->unsetFlags( NetRoutingState::AutomaticGlobalRoute ); state->unsetFlags( NetRoutingState::AutomaticGlobalRoute );
state->setFlags ( NetRoutingState::ManualGlobalRoute ); if (isManualGlobalRouted) {
state->setFlags( NetRoutingState::ManualGlobalRoute );
ndata->setGlobalFixed( true );
}
if (isManualDetailRouted)
state->setFlags( NetRoutingState::ManualDetailRoute );
ndata->setGlobalRouted( true ); ndata->setGlobalRouted( true );
if (rpCount < 2) if (rpCount < 2)
state->setFlags ( NetRoutingState::Unconnected ); state->setFlags( NetRoutingState::Unconnected );
if (isFixed) { if (isFixed) {
if (rpCount > 1) if (rpCount > 1)
cmess2 << " - <" << net->getName() << "> is fixed." << endl; cmess2 << " - <" << net->getName() << "> is fixed." << endl;
state->unsetFlags( NetRoutingState::ManualGlobalRoute ); state->unsetFlags( NetRoutingState::ManualGlobalRoute|NetRoutingState::ManualDetailRoute );
state->setFlags ( NetRoutingState::Fixed ); state->setFlags ( NetRoutingState::Fixed );
} else { } else if (isManualGlobalRouted) {
cmess2 << " - <" << net->getName() << "> is manually global routed." << endl;
} else if (isManualDetailRouted) {
if (rpCount > 1) { if (rpCount > 1) {
++toBeRouteds; ++toBeRouteds;
cmess2 << " - <" << net->getName() << "> is manually detail routed." << endl;
cmess2 << " - <" << net->getName() << "> is manually global routed." << endl; for ( auto contact : contacts ) {
for ( auto icontact : contacts ) { AutoContact::createFrom( contact );
AutoContact::createFrom( icontact );
} }
for ( auto segment : segments ) { for ( auto segment : segments ) {
AutoContact* source = Session::lookup( dynamic_cast<Contact*>( segment->getSource() )); AutoContact* source = Session::lookup( dynamic_cast<Contact*>( segment->getSource() ));
AutoContact* target = Session::lookup( dynamic_cast<Contact*>( segment->getTarget() )); AutoContact* target = Session::lookup( dynamic_cast<Contact*>( segment->getTarget() ));

View File

@ -82,7 +82,12 @@ namespace Anabatic {
, _segmentRevalidateds() , _segmentRevalidateds()
, _netInvalidateds () , _netInvalidateds ()
, _netRevalidateds () , _netRevalidateds ()
{ } {
_autoContacts .reserve( 1024 );
_doglegs .reserve( 1024 );
_segmentInvalidateds.reserve( 1024 );
_segmentRevalidateds.reserve( 1024 );
}
void Session::_postCreate () void Session::_postCreate ()
@ -215,11 +220,13 @@ namespace Anabatic {
_anabatic->updateNetTopology ( net ); _anabatic->updateNetTopology ( net );
_anabatic->computeNetConstraints( net ); _anabatic->computeNetConstraints( net );
_anabatic->_computeNetOptimals ( net ); _anabatic->_computeNetOptimals ( net );
_anabatic->_computeNetTerminals ( net ); //_anabatic->_computeNetTerminals ( net );
} }
_canonize (); _canonize ();
for ( AutoSegment* segment : _segmentInvalidateds ) { AutoSegment* segment = NULL;
for ( size_t i=0 ; i<_segmentInvalidateds.size() ; ++i ) {
segment = _segmentInvalidateds[i];
if (segment->isCanonical()) { if (segment->isCanonical()) {
if (segment->isUnsetAxis()) segment->toOptimalAxis(); if (segment->isUnsetAxis()) segment->toOptimalAxis();
else segment->toConstraintAxis(); else segment->toConstraintAxis();
@ -252,6 +259,8 @@ namespace Anabatic {
cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl; cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl;
_segmentRevalidateds.clear(); _segmentRevalidateds.clear();
std::sort( _segmentInvalidateds.begin(), _segmentInvalidateds.end()
, AutoSegment::CompareByRevalidate() );
for ( size_t i=0 ; i < _segmentInvalidateds.size() ; ++i, ++count ) { for ( size_t i=0 ; i < _segmentInvalidateds.size() ; ++i, ++count ) {
_segmentInvalidateds[i]->revalidate(); _segmentInvalidateds[i]->revalidate();
if ( not _destroyedSegments.empty() if ( not _destroyedSegments.empty()
@ -353,6 +362,31 @@ namespace Anabatic {
} }
DbU::Unit Session::_getNearestTrackAxis ( const Layer* layer, DbU::Unit axis, uint32_t mode )
{
Box ab = _anabatic->getCell()->getAbutmentBox();
RoutingLayerGauge* lg = _routingGauge->getLayerGauge( layer );
if (not lg) return axis;
DbU::Unit minAxis = 0;
DbU::Unit maxAxis = 0;
if (lg->getDirection() == Constant::Horizontal) {
minAxis = ab.getYMin();
maxAxis = ab.getYMax();
} else {
minAxis = ab.getXMin();
maxAxis = ab.getXMax();
}
DbU::Unit trackAxis = lg->getTrackPosition( minAxis
, lg->getTrackIndex( minAxis
, maxAxis
, axis
, mode ) );
return trackAxis;
}
Point Session::_getNearestGridPoint ( Point p, Box constraint ) Point Session::_getNearestGridPoint ( Point p, Box constraint )
{ {
Box ab = _anabatic->getCell()->getAbutmentBox(); Box ab = _anabatic->getCell()->getAbutmentBox();

View File

@ -14,20 +14,16 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_ANABATIC_ENGINE_H #pragma once
#define ANABATIC_ANABATIC_ENGINE_H
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include <set> #include <set>
#include "hurricane/NetRoutingProperty.h" #include "hurricane/NetRoutingProperty.h"
namespace Hurricane { namespace Hurricane {
class Instance; class Instance;
class CellViewer; class CellViewer;
} }
#include "crlcore/ToolEngine.h" #include "crlcore/ToolEngine.h"
#include "anabatic/Configuration.h" #include "anabatic/Configuration.h"
#include "anabatic/Matrix.h" #include "anabatic/Matrix.h"
@ -68,6 +64,8 @@ namespace Anabatic {
}; };
public: public:
RawGCellsUnder ( const AnabaticEngine*, Segment* ); RawGCellsUnder ( const AnabaticEngine*, Segment* );
RawGCellsUnder ( const AnabaticEngine*, Point source, Point target );
void commonCtor ( const AnabaticEngine*, Point source, Point target );
inline bool empty () const; inline bool empty () const;
inline size_t size () const; inline size_t size () const;
inline GCell* gcellAt ( size_t ) const; inline GCell* gcellAt ( size_t ) const;
@ -102,9 +100,10 @@ namespace Anabatic {
class NetData { class NetData {
public: public:
NetData ( Net* ); NetData ( Net*, AnabaticEngine* );
inline bool isGlobalEstimated () const; inline bool isGlobalEstimated () const;
inline bool isGlobalRouted () const; inline bool isGlobalRouted () const;
inline bool isGlobalFixed () const;
inline bool isMixedPreRoute () const; inline bool isMixedPreRoute () const;
inline bool isFixed () const; inline bool isFixed () const;
inline bool isExcluded () const; inline bool isExcluded () const;
@ -113,11 +112,13 @@ namespace Anabatic {
inline const Box& getSearchArea () const; inline const Box& getSearchArea () const;
inline DbU::Unit getHalfPerimeter () const; inline DbU::Unit getHalfPerimeter () const;
inline size_t getRpCount () const; inline size_t getRpCount () const;
inline size_t getDiodeRpCount () const;
inline DbU::Unit getSparsity () const; inline DbU::Unit getSparsity () const;
inline void setNetRoutingState ( NetRoutingState* ); inline void setNetRoutingState ( NetRoutingState* );
inline void setSearchArea ( Box ); inline void setSearchArea ( Box );
inline void setGlobalEstimated ( bool ); inline void setGlobalEstimated ( bool );
inline void setGlobalRouted ( bool ); inline void setGlobalRouted ( bool );
inline void setGlobalFixed ( bool );
inline void setExcluded ( bool ); inline void setExcluded ( bool );
inline void setRpCount ( size_t ); inline void setRpCount ( size_t );
private: private:
@ -129,6 +130,7 @@ namespace Anabatic {
NetRoutingState* _state; NetRoutingState* _state;
Box _searchArea; Box _searchArea;
size_t _rpCount; size_t _rpCount;
size_t _diodeCount;
DbU::Unit _sparsity; DbU::Unit _sparsity;
Flags _flags; Flags _flags;
}; };
@ -136,6 +138,7 @@ namespace Anabatic {
inline bool NetData::isGlobalEstimated () const { return _flags & Flags::GlobalEstimated; } inline bool NetData::isGlobalEstimated () const { return _flags & Flags::GlobalEstimated; }
inline bool NetData::isGlobalRouted () const { return _flags & Flags::GlobalRouted; } inline bool NetData::isGlobalRouted () const { return _flags & Flags::GlobalRouted; }
inline bool NetData::isGlobalFixed () const { return _flags & Flags::GlobalFixed; }
inline bool NetData::isMixedPreRoute () const { return (_state) ? _state->isMixedPreRoute() : false; } inline bool NetData::isMixedPreRoute () const { return (_state) ? _state->isMixedPreRoute() : false; }
inline bool NetData::isFixed () const { return (_state) ? _state->isFixed () : false; } inline bool NetData::isFixed () const { return (_state) ? _state->isFixed () : false; }
inline bool NetData::isExcluded () const { return _flags & Flags::ExcludeRoute; } inline bool NetData::isExcluded () const { return _flags & Flags::ExcludeRoute; }
@ -144,10 +147,12 @@ namespace Anabatic {
inline const Box& NetData::getSearchArea () const { return _searchArea; } inline const Box& NetData::getSearchArea () const { return _searchArea; }
inline DbU::Unit NetData::getHalfPerimeter () const { return (_searchArea.isEmpty()) ? 0.0 : (_searchArea.getWidth()+_searchArea.getHeight()); } inline DbU::Unit NetData::getHalfPerimeter () const { return (_searchArea.isEmpty()) ? 0.0 : (_searchArea.getWidth()+_searchArea.getHeight()); }
inline size_t NetData::getRpCount () const { return _rpCount; } inline size_t NetData::getRpCount () const { return _rpCount; }
inline size_t NetData::getDiodeRpCount () const { return _diodeCount; }
inline void NetData::setNetRoutingState ( NetRoutingState* state ) { _state=state; } inline void NetData::setNetRoutingState ( NetRoutingState* state ) { _state=state; }
inline DbU::Unit NetData::getSparsity () const { return _sparsity; } inline DbU::Unit NetData::getSparsity () const { return _sparsity; }
inline void NetData::setGlobalEstimated ( bool state ) { _flags.set(Flags::GlobalEstimated,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::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::setExcluded ( bool state ) { _flags.set(Flags::ExcludeRoute ,state); }
inline void NetData::setRpCount ( size_t count ) { _rpCount=count; _update(); } inline void NetData::setRpCount ( size_t count ) { _rpCount=count; _update(); }
@ -161,7 +166,12 @@ namespace Anabatic {
inline bool operator() ( const NetData* lhs, const NetData* rhs ) const inline bool operator() ( const NetData* lhs, const NetData* rhs ) const
{ {
if (lhs->isMixedPreRoute() != rhs->isMixedPreRoute()) return lhs->isMixedPreRoute(); if (lhs->isMixedPreRoute() != rhs->isMixedPreRoute()) return lhs->isMixedPreRoute();
if (lhs->getSparsity() != rhs->getSparsity() ) return lhs->getSparsity() < rhs->getSparsity(); if ((lhs->getRpCount() > 10) or (rhs->getRpCount() > 10)) {
if (lhs->getRpCount() != rhs->getRpCount())
return lhs->getRpCount() > rhs->getRpCount();
}
if (lhs->getSparsity() != rhs->getSparsity()) return lhs->getSparsity() < rhs->getSparsity();
return lhs->getNet()->getId() < rhs->getNet()->getId(); return lhs->getNet()->getId() < rhs->getNet()->getId();
} }
}; };
@ -192,6 +202,7 @@ namespace Anabatic {
static const Name& staticGetName (); static const Name& staticGetName ();
virtual const Name& getName () const; virtual const Name& getName () const;
virtual Configuration* getConfiguration (); virtual Configuration* getConfiguration ();
virtual const Configuration* getConfiguration () const;
inline uint64_t getDensityMode () const; inline uint64_t getDensityMode () const;
inline CellViewer* getViewer () const; inline CellViewer* getViewer () const;
inline void setViewer ( CellViewer* ); inline void setViewer ( CellViewer* );
@ -203,6 +214,7 @@ namespace Anabatic {
inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const; inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const;
inline GCell* getGCellUnder ( Point ) const; inline GCell* getGCellUnder ( Point ) const;
inline GCellsUnder getGCellsUnder ( Segment* ) 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; inline Edges getEdgesUnderPath ( GCell* source, GCell* target, Flags pathFlags=Flags::NorthPath ) const;
Interval getUSide ( Flags direction ) const; Interval getUSide ( Flags direction ) const;
int getCapacity ( Interval, Flags ) const; int getCapacity ( Interval, Flags ) const;
@ -218,6 +230,7 @@ namespace Anabatic {
void exclude ( const Name& netName ); void exclude ( const Name& netName );
void exclude ( Net* ); void exclude ( Net* );
void updateMatrix (); void updateMatrix ();
bool checkPlacement () const;
// Dijkstra related functions. // Dijkstra related functions.
inline int getStamp () const; inline int getStamp () const;
inline int incStamp (); inline int incStamp ();
@ -235,10 +248,13 @@ namespace Anabatic {
inline bool doDestroyBaseContact () const; inline bool doDestroyBaseContact () const;
inline bool doDestroyBaseSegment () const; inline bool doDestroyBaseSegment () const;
inline bool doDestroyTool () const; inline bool doDestroyTool () const;
inline DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getAntennaDiodeMaxWL () const;
inline DbU::Unit getGlobalThreshold () const; inline DbU::Unit getGlobalThreshold () const;
inline float getSaturateRatio () const; inline float getSaturateRatio () const;
inline size_t getSaturateRp () const; inline size_t getSaturateRp () const;
inline DbU::Unit getExtensionCap () const; inline DbU::Unit getExtensionCap () const;
inline Cell* getDiodeCell () const;
inline Net* getBlockageNet () const; inline Net* getBlockageNet () const;
inline const ChipTools& getChipTools () const; inline const ChipTools& getChipTools () const;
inline const vector<NetData*>& getNetOrdering () const; inline const vector<NetData*>& getNetOrdering () const;
@ -250,6 +266,9 @@ namespace Anabatic {
inline void setSaturateRp ( size_t ); inline void setSaturateRp ( size_t );
inline void setBlockageNet ( Net* ); inline void setBlockageNet ( Net* );
void chipPrep (); 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 (); void setupSpecialNets ();
size_t setupPreRouteds (); size_t setupPreRouteds ();
void loadGlobalRouting ( uint32_t method ); void loadGlobalRouting ( uint32_t method );
@ -259,6 +278,7 @@ namespace Anabatic {
bool moveUpNetTrunk ( AutoSegment*, set<Net*>& globalNets, GCell::Set& invalidateds ); bool moveUpNetTrunk ( AutoSegment*, set<Net*>& globalNets, GCell::Set& invalidateds );
void layerAssign ( uint32_t method ); void layerAssign ( uint32_t method );
void finalizeLayout (); void finalizeLayout ();
void exportExternalNets ();
inline const AutoContactLut& _getAutoContactLut () const; inline const AutoContactLut& _getAutoContactLut () const;
inline const AutoSegmentLut& _getAutoSegmentLut () const; inline const AutoSegmentLut& _getAutoSegmentLut () const;
void _link ( AutoContact* ); void _link ( AutoContact* );
@ -327,6 +347,7 @@ namespace Anabatic {
AutoContactLut _autoContactLut; AutoContactLut _autoContactLut;
EdgeCapacityLut _edgeCapacitiesLut; EdgeCapacityLut _edgeCapacitiesLut;
Net* _blockageNet; Net* _blockageNet;
Cell* _diodeCell;
}; };
@ -341,6 +362,7 @@ namespace Anabatic {
inline GCell* AnabaticEngine::getGCellUnder ( DbU::Unit x, DbU::Unit y ) const { return _matrix.getUnder(x,y); } 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 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 ( 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 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 uint64_t AnabaticEngine::getDensityMode () const { return _densityMode; }
inline void AnabaticEngine::setDensityMode ( uint64_t mode ) { _densityMode=mode; } inline void AnabaticEngine::setDensityMode ( uint64_t mode ) { _densityMode=mode; }
@ -355,11 +377,14 @@ namespace Anabatic {
inline bool AnabaticEngine::doWarnOnGCellOverload () const { return _flags & Flags::WarnOnGCellOverload; } inline bool AnabaticEngine::doWarnOnGCellOverload () const { return _flags & Flags::WarnOnGCellOverload; }
inline bool AnabaticEngine::isInDemoMode () const { return _flags & Flags::DemoMode; } inline bool AnabaticEngine::isInDemoMode () const { return _flags & Flags::DemoMode; }
inline bool AnabaticEngine::isChip () const { return _chipTools.isChip(); } 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 DbU::Unit AnabaticEngine::getGlobalThreshold () const { return _configuration->getGlobalThreshold(); }
inline float AnabaticEngine::getSaturateRatio () const { return _configuration->getSaturateRatio(); } inline float AnabaticEngine::getSaturateRatio () const { return _configuration->getSaturateRatio(); }
inline size_t AnabaticEngine::getSaturateRp () const { return _configuration->getSaturateRp(); } inline size_t AnabaticEngine::getSaturateRp () const { return _configuration->getSaturateRp(); }
inline void AnabaticEngine::setSaturateRatio ( float ratio ) { _configuration->setSaturateRatio(ratio); } inline void AnabaticEngine::setSaturateRatio ( float ratio ) { _configuration->setSaturateRatio(ratio); }
inline void AnabaticEngine::setSaturateRp ( size_t threshold ) { _configuration->setSaturateRp(threshold); } 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 Net* AnabaticEngine::getBlockageNet () const { return _blockageNet; }
inline const ChipTools& AnabaticEngine::getChipTools () const { return _chipTools; } inline const ChipTools& AnabaticEngine::getChipTools () const { return _chipTools; }
inline const vector<NetData*>& AnabaticEngine::getNetOrdering () const { return _netOrdering; } inline const vector<NetData*>& AnabaticEngine::getNetOrdering () const { return _netOrdering; }
@ -407,5 +432,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::AnabaticEngine); INSPECTOR_P_SUPPORT(Anabatic::AnabaticEngine);
#endif // ANABATIC_ANABATIC_ENGINE_H

View File

@ -71,6 +71,8 @@ namespace Anabatic {
, CntOnVertical = (1 << 14) , CntOnVertical = (1 << 14)
, CntOnHorizontal = (1 << 15) , CntOnHorizontal = (1 << 15)
, CntDrag = (1 << 16) , CntDrag = (1 << 16)
, CntHDogleg = (1 << 17)
, CntVDogleg = (1 << 18)
}; };
class AutoContact { class AutoContact {
@ -119,6 +121,9 @@ namespace Anabatic {
inline bool isVTee () const; inline bool isVTee () const;
inline bool isFixed () const; inline bool isFixed () const;
inline bool isUserNativeConstraints () const; inline bool isUserNativeConstraints () const;
inline bool isHDogleg () const;
inline bool isVDogleg () const;
virtual bool isOnPin () const;
inline bool hasBadTopology () const; inline bool hasBadTopology () const;
bool canDestroy ( Flags flags=Flags::NoFlags ) const; bool canDestroy ( Flags flags=Flags::NoFlags ) const;
bool canMoveUp ( const AutoSegment* moved ) const; bool canMoveUp ( const AutoSegment* moved ) const;
@ -159,6 +164,7 @@ namespace Anabatic {
virtual void cacheDetach ( AutoSegment* ) = 0; virtual void cacheDetach ( AutoSegment* ) = 0;
virtual void cacheAttach ( AutoSegment* ) = 0; virtual void cacheAttach ( AutoSegment* ) = 0;
virtual void updateCache () = 0; virtual void updateCache () = 0;
void updateLayer ();
void updateSize (); void updateSize ();
virtual void updateGeometry () = 0; virtual void updateGeometry () = 0;
virtual void updateTopology () = 0; virtual void updateTopology () = 0;
@ -259,6 +265,8 @@ namespace Anabatic {
inline bool AutoContact::isTerminal () const { return _flags&CntTerminal; } inline bool AutoContact::isTerminal () const { return _flags&CntTerminal; }
inline bool AutoContact::isHTee () const { return _flags&CntHTee; } inline bool AutoContact::isHTee () const { return _flags&CntHTee; }
inline bool AutoContact::isVTee () const { return _flags&CntVTee; } inline bool AutoContact::isVTee () const { return _flags&CntVTee; }
inline bool AutoContact::isHDogleg () const { return _flags&CntHDogleg; }
inline bool AutoContact::isVDogleg () const { return _flags&CntVDogleg; }
inline bool AutoContact::hasBadTopology () const { return _flags&CntBadTopology; } inline bool AutoContact::hasBadTopology () const { return _flags&CntBadTopology; }
inline bool AutoContact::canDrag () const { return _flags&CntDrag; } inline bool AutoContact::canDrag () const { return _flags&CntDrag; }
inline size_t AutoContact::getId () const { return _id; } inline size_t AutoContact::getId () const { return _id; }

View File

@ -60,6 +60,7 @@ namespace Anabatic {
virtual void _invalidate ( Flags flags ); virtual void _invalidate ( Flags flags );
public: public:
bool isEndPoint () const; bool isEndPoint () const;
virtual bool isOnPin () const;
virtual Box getNativeConstraintBox () const; virtual Box getNativeConstraintBox () const;
RoutingPad* getRoutingPad () const; RoutingPad* getRoutingPad () const;
inline AutoSegment* getSegment () const; inline AutoSegment* getSegment () const;

View File

@ -58,11 +58,10 @@ namespace Anabatic {
class AutoHorizontal; class AutoHorizontal;
class AutoVertical; class AutoVertical;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "AutoSegment". // Class : "AutoSegment".
class AutoSegment { class AutoSegment {
friend class AutoHorizontal; friend class AutoHorizontal;
friend class AutoVertical; friend class AutoVertical;
@ -106,6 +105,9 @@ namespace Anabatic {
static const uint64_t SegAnalog = (1L<<33); static const uint64_t SegAnalog = (1L<<33);
static const uint64_t SegWide = (1L<<34); static const uint64_t SegWide = (1L<<34);
static const uint64_t SegShortNet = (1L<<35); 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. // Masks.
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2; static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned; static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
@ -140,6 +142,7 @@ namespace Anabatic {
inline static DbU::Unit getViaToTopCap ( size_t depth ); inline static DbU::Unit getViaToTopCap ( size_t depth );
inline static DbU::Unit getViaToBottomCap ( size_t depth ); inline static DbU::Unit getViaToBottomCap ( size_t depth );
inline static DbU::Unit getViaToSameCap ( size_t depth ); inline static DbU::Unit getViaToSameCap ( size_t depth );
inline static DbU::Unit getMinimalLength ( size_t depth );
static AutoSegment* create ( AutoContact* source static AutoSegment* create ( AutoContact* source
, AutoContact* target , AutoContact* target
, Segment* hurricaneSegment , Segment* hurricaneSegment
@ -170,6 +173,8 @@ namespace Anabatic {
inline DbU::Unit getWidth () const; inline DbU::Unit getWidth () const;
inline DbU::Unit getContactWidth () const; inline DbU::Unit getContactWidth () const;
inline DbU::Unit getLength () const; inline DbU::Unit getLength () const;
inline DbU::Unit getSpanLength () const;
inline DbU::Unit getAnchoredLength () const;
inline DbU::Unit getSourcePosition () const; inline DbU::Unit getSourcePosition () const;
inline DbU::Unit getTargetPosition () const; inline DbU::Unit getTargetPosition () const;
inline DbU::Unit getSourceX () const; inline DbU::Unit getSourceX () const;
@ -194,7 +199,10 @@ namespace Anabatic {
inline bool isWeakTerminal1 () const; inline bool isWeakTerminal1 () const;
inline bool isWeakTerminal2 () const; inline bool isWeakTerminal2 () const;
inline bool isTerminal () const; inline bool isTerminal () const;
inline bool isUnbreakable () const;
inline bool isNonPref () const;
inline bool isDrag () const; inline bool isDrag () const;
inline bool isAtMinArea () const;
inline bool isNotSourceAligned () const; inline bool isNotSourceAligned () const;
inline bool isNotTargetAligned () const; inline bool isNotTargetAligned () const;
inline bool isNotAligned () const; inline bool isNotAligned () const;
@ -202,10 +210,12 @@ namespace Anabatic {
inline bool isSourceTerminal () const; inline bool isSourceTerminal () const;
inline bool isTargetTerminal () const; inline bool isTargetTerminal () const;
inline bool isLayerChange () const; inline bool isLayerChange () const;
inline bool isStackedStrap () const;
inline bool isSpinTop () const; inline bool isSpinTop () const;
inline bool isSpinBottom () const; inline bool isSpinBottom () const;
inline bool isSpinTopOrBottom () const; inline bool isSpinTopOrBottom () const;
inline bool isReduced () const; inline bool isReduced () const;
bool isUnderMinLength () const;
inline bool isStrap () const; inline bool isStrap () const;
inline bool isDogleg () const; inline bool isDogleg () const;
inline bool isUnbound () const; inline bool isUnbound () const;
@ -216,13 +226,14 @@ namespace Anabatic {
inline bool isUnsetAxis () const; inline bool isUnsetAxis () const;
inline bool isSlackened () const; inline bool isSlackened () const;
inline bool isUserDefined () const; inline bool isUserDefined () const;
bool isMiddleStack () const;
bool isReduceCandidate () const; bool isReduceCandidate () const;
bool isUTurn () const; bool isUTurn () const;
inline bool isAnalog () const; inline bool isAnalog () const;
inline bool isWide () const; inline bool isWide () const;
inline bool isShortNet () const; inline bool isShortNet () const;
virtual bool _canSlacken () const = 0; virtual bool _canSlacken () const = 0;
bool canReduce () const; bool canReduce ( Flags flags=Flags::WithPerpands ) const;
bool mustRaise () const; bool mustRaise () const;
Flags canDogleg ( Interval ); Flags canDogleg ( Interval );
virtual bool canMoveULeft ( float reserve=0.0 ) const = 0; virtual bool canMoveULeft ( float reserve=0.0 ) const = 0;
@ -245,6 +256,7 @@ namespace Anabatic {
AutoContact* getOppositeAnchor ( AutoContact* ) const; AutoContact* getOppositeAnchor ( AutoContact* ) const;
size_t getPerpandicularsBound ( set<AutoSegment*>& ); size_t getPerpandicularsBound ( set<AutoSegment*>& );
inline AutoSegment* getParent () const; inline AutoSegment* getParent () const;
inline unsigned int getRpDistance () const;
inline unsigned int getDepth () const; inline unsigned int getDepth () const;
inline DbU::Unit getPitch () const; inline DbU::Unit getPitch () const;
DbU::Unit getPPitch () const; DbU::Unit getPPitch () const;
@ -278,10 +290,13 @@ namespace Anabatic {
virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max ); virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max );
inline AutoSegment* getCanonical ( Interval& i ); inline AutoSegment* getCanonical ( Interval& i );
float getMaxUnderDensity ( Flags flags ); float getMaxUnderDensity ( Flags flags );
inline uint32_t getReduceds () const;
uint32_t getNonReduceds ( Flags flags=Flags::WithPerpands ) const;
// Modifiers. // Modifiers.
inline void unsetFlags ( uint64_t ); inline void unsetFlags ( uint64_t );
inline void setFlags ( uint64_t ); inline void setFlags ( uint64_t );
void setFlagsOnAligneds ( uint64_t ); void setFlagsOnAligneds ( uint64_t );
inline void setRpDistance ( unsigned int );
inline void incReduceds (); inline void incReduceds ();
inline void decReduceds (); inline void decReduceds ();
virtual void setDuSource ( DbU::Unit du ) = 0; virtual void setDuSource ( DbU::Unit du ) = 0;
@ -320,8 +335,11 @@ namespace Anabatic {
bool moveUp ( Flags flags=Flags::NoFlags ); bool moveUp ( Flags flags=Flags::NoFlags );
bool moveDown ( Flags flags=Flags::NoFlags ); bool moveDown ( Flags flags=Flags::NoFlags );
bool reduceDoglegLayer (); bool reduceDoglegLayer ();
bool reduce (); bool bloatStackedStrap ();
bool reduce ( Flags flags=Flags::WithPerpands );
bool raise (); bool raise ();
bool expandToMinLength ( Interval );
bool unexpandToMinLength ();
// Canonical Modifiers. // Canonical Modifiers.
AutoSegment* canonize ( Flags flags=Flags::NoFlags ); AutoSegment* canonize ( Flags flags=Flags::NoFlags );
virtual void invalidate ( Flags flags=Flags::Propagate ); virtual void invalidate ( Flags flags=Flags::Propagate );
@ -365,15 +383,16 @@ namespace Anabatic {
static bool _analogMode; static bool _analogMode;
static bool _shortNetMode; static bool _shortNetMode;
static bool _initialized; static bool _initialized;
static vector< array<DbU::Unit*,3> > _extensionCaps; static vector< array<DbU::Unit*,4> > _extensionCaps;
// Internal: Attributes. // Internal: Attributes.
const unsigned long _id; const unsigned long _id;
GCell* _gcell; GCell* _gcell;
uint64_t _flags; uint64_t _flags;
unsigned int _depth : 8; unsigned int _depth : 8;
unsigned int _optimalMin :16; unsigned int _optimalMin :16;
unsigned int _optimalMax :16; unsigned int _optimalMax :16;
unsigned int _reduceds : 2; unsigned int _reduceds : 2;
unsigned int _rpDistance : 4;
DbU::Unit _sourcePosition; DbU::Unit _sourcePosition;
DbU::Unit _targetPosition; DbU::Unit _targetPosition;
Interval _userConstraints; Interval _userConstraints;
@ -414,6 +433,13 @@ namespace Anabatic {
struct CompareBySourceU : public binary_function<AutoSegment*,AutoSegment*,bool> { struct CompareBySourceU : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const; bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
}; };
public:
struct CompareByRevalidate : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
struct CompareByReduceds : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public: public:
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet; typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
typedef std::set<AutoSegment*,CompareId> IdSet; typedef std::set<AutoSegment*,CompareId> IdSet;
@ -458,6 +484,7 @@ namespace Anabatic {
inline DbU::Unit AutoSegment::getViaToTopCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][0]) : 0; } 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::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::getViaToSameCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][2]) : 0; }
inline DbU::Unit AutoSegment::getMinimalLength ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][3]) : 0; }
inline unsigned long AutoSegment::getId () const { return _id; } inline unsigned long AutoSegment::getId () const { return _id; }
inline Cell* AutoSegment::getCell () const { return base()->getCell(); } inline Cell* AutoSegment::getCell () const { return base()->getCell(); }
inline Net* AutoSegment::getNet () const { return base()->getNet(); } inline Net* AutoSegment::getNet () const { return base()->getNet(); }
@ -484,6 +511,7 @@ namespace Anabatic {
inline bool AutoSegment::getConstraints ( Interval& i ) const { return getConstraints(i.getVMin(),i.getVMax()); } inline bool AutoSegment::getConstraints ( Interval& i ) const { return getConstraints(i.getVMin(),i.getVMax()); }
inline AutoSegment* AutoSegment::getCanonical ( Interval& i ) { return getCanonical(i.getVMin(),i.getVMax()); } inline AutoSegment* AutoSegment::getCanonical ( Interval& i ) { return getCanonical(i.getVMin(),i.getVMax()); }
inline unsigned int AutoSegment::getDepth () const { return _depth; } inline unsigned int AutoSegment::getDepth () const { return _depth; }
inline unsigned int AutoSegment::getRpDistance () const { return _rpDistance; }
inline DbU::Unit AutoSegment::getPitch () const { return Session::getPitch(getDepth(),Flags::NoFlags); } inline DbU::Unit AutoSegment::getPitch () const { return Session::getPitch(getDepth(),Flags::NoFlags); }
inline DbU::Unit AutoSegment::getAxis () const { return isHorizontal()?base()->getY():base()->getX(); } inline DbU::Unit AutoSegment::getAxis () const { return isHorizontal()?base()->getY():base()->getX(); }
inline DbU::Unit AutoSegment::getOrigin () const { return isHorizontal()?_gcell->getYMin():_gcell->getXMin(); } inline DbU::Unit AutoSegment::getOrigin () const { return isHorizontal()?_gcell->getYMin():_gcell->getXMin(); }
@ -494,6 +522,7 @@ namespace Anabatic {
inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); } inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); }
inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; } inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; }
inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; } inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; }
inline uint32_t AutoSegment::getReduceds () const { return _reduceds; }
inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; } inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; }
inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); } inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); }
@ -503,14 +532,17 @@ namespace Anabatic {
inline bool AutoSegment::isWeakGlobal () const { return _flags & SegWeakGlobal; } inline bool AutoSegment::isWeakGlobal () const { return _flags & SegWeakGlobal; }
inline bool AutoSegment::isLongLocal () const { return _flags & SegLongLocal; } inline bool AutoSegment::isLongLocal () const { return _flags & SegLongLocal; }
inline bool AutoSegment::isLocal () const { return not (_flags & SegGlobal); } inline bool AutoSegment::isLocal () const { return not (_flags & SegGlobal); }
inline bool AutoSegment::isUnbreakable () const { return _flags & SegUnbreakable; }
inline bool AutoSegment::isNonPref () const { return _flags & SegNonPref; }
inline bool AutoSegment::isBipoint () const { return _flags & SegBipoint; } inline bool AutoSegment::isBipoint () const { return _flags & SegBipoint; }
inline bool AutoSegment::isWeakTerminal () const { return _flags & SegWeakTerminal; } inline bool AutoSegment::isWeakTerminal () const { return (_rpDistance < 2); }
inline bool AutoSegment::isWeakTerminal1 () const { return _flags & SegWeakTerminal1; } inline bool AutoSegment::isWeakTerminal1 () const { return (_rpDistance == 1); }
inline bool AutoSegment::isWeakTerminal2 () const { return _flags & SegWeakTerminal2; } inline bool AutoSegment::isWeakTerminal2 () const { return (_rpDistance == 2); }
inline bool AutoSegment::isSourceTerminal () const { return _flags & SegSourceTerminal; } inline bool AutoSegment::isSourceTerminal () const { return _flags & SegSourceTerminal; }
inline bool AutoSegment::isTargetTerminal () const { return _flags & SegTargetTerminal; } inline bool AutoSegment::isTargetTerminal () const { return _flags & SegTargetTerminal; }
inline bool AutoSegment::isTerminal () const { return _flags & SegStrongTerminal; } inline bool AutoSegment::isTerminal () const { return (_rpDistance == 0); }
inline bool AutoSegment::isDrag () const { return _flags & SegDrag; } inline bool AutoSegment::isDrag () const { return _flags & SegDrag; }
inline bool AutoSegment::isAtMinArea () const { return _flags & SegAtMinArea; }
inline bool AutoSegment::isNotSourceAligned () const { return _flags & SegNotSourceAligned; } inline bool AutoSegment::isNotSourceAligned () const { return _flags & SegNotSourceAligned; }
inline bool AutoSegment::isNotTargetAligned () const { return _flags & SegNotTargetAligned; } inline bool AutoSegment::isNotTargetAligned () const { return _flags & SegNotTargetAligned; }
inline bool AutoSegment::isNotAligned () const { return (_flags & SegNotAligned) == SegNotAligned; } inline bool AutoSegment::isNotAligned () const { return (_flags & SegNotAligned) == SegNotAligned; }
@ -537,6 +569,7 @@ namespace Anabatic {
inline uint64_t AutoSegment::getFlags () const { return _flags; } inline uint64_t AutoSegment::getFlags () const { return _flags; }
inline uint64_t AutoSegment::_getFlags () const { return _flags; } inline uint64_t AutoSegment::_getFlags () const { return _flags; }
inline void AutoSegment::setRpDistance ( unsigned int distance ) { _rpDistance=distance; }
inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; } inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; }
inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; } inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; }
inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); _flags|=SegInvalidatedLayer; } inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); _flags|=SegInvalidatedLayer; }
@ -548,7 +581,7 @@ namespace Anabatic {
inline void AutoSegment::resetNativeConstraints ( DbU::Unit min, DbU::Unit max ) { _nativeConstraints = Interval( min, max ); } inline void AutoSegment::resetNativeConstraints ( DbU::Unit min, DbU::Unit max ) { _nativeConstraints = Interval( min, max ); }
//inline void AutoSegment::mergeUserConstraints ( const Interval& constraints ) { _userConstraints.intersection(constraints); } //inline void AutoSegment::mergeUserConstraints ( const Interval& constraints ) { _userConstraints.intersection(constraints); }
inline void AutoSegment::resetUserConstraints () { _userConstraints = Interval(false); } inline void AutoSegment::resetUserConstraints () { _userConstraints = Interval(false); }
inline DbU::Unit AutoSegment::getAnchoredLength () const { return std::abs(getTargetU() - getSourceU()); }
inline void AutoSegment::setLayer ( size_t depth ) inline void AutoSegment::setLayer ( size_t depth )
{ {
@ -560,10 +593,13 @@ namespace Anabatic {
_flags|=SegInvalidatedLayer; _flags|=SegInvalidatedLayer;
} }
inline DbU::Unit AutoSegment::getContactWidth () const inline DbU::Unit AutoSegment::getContactWidth () const
{ return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); } { return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); }
inline DbU::Unit AutoSegment::getSpanLength () const
{ return getAnchoredLength() + getExtensionCap( Flags::Source|Flags::LayerCapOnly|Flags::NoMinLength )
+ getExtensionCap( Flags::Target|Flags::LayerCapOnly|Flags::NoMinLength );
}
inline void AutoSegment::setParent ( AutoSegment* parent ) inline void AutoSegment::setParent ( AutoSegment* parent )
{ {

View File

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

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_CONFIGURATION_H #pragma once
#define ANABATIC_CONFIGURATION_H
#include <string> #include <string>
#include <vector> #include <vector>
@ -64,6 +62,7 @@ namespace Anabatic {
virtual ~Configuration (); virtual ~Configuration ();
virtual Configuration* clone () const; virtual Configuration* clone () const;
// Methods. // Methods.
inline bool isGLayer ( const Layer* ) const;
bool isGMetal ( const Layer* ) const; bool isGMetal ( const Layer* ) const;
bool isGContact ( const Layer* ) const; bool isGContact ( const Layer* ) const;
bool isTwoMetals () const; bool isTwoMetals () const;
@ -79,11 +78,13 @@ namespace Anabatic {
inline size_t getDVerticalDepth () const; inline size_t getDVerticalDepth () const;
inline const Layer* getDVerticalLayer () const; inline const Layer* getDVerticalLayer () const;
inline DbU::Unit getDVerticalWidth () const; inline DbU::Unit getDVerticalWidth () const;
inline DbU::Unit getDPVerticalWidth () const;
inline DbU::Unit getDVerticalPitch () const; inline DbU::Unit getDVerticalPitch () const;
inline DbU::Unit getDVerticalOffset () const; inline DbU::Unit getDVerticalOffset () const;
inline size_t getDHorizontalDepth () const; inline size_t getDHorizontalDepth () const;
inline const Layer* getDHorizontalLayer () const; inline const Layer* getDHorizontalLayer () const;
inline DbU::Unit getDHorizontalWidth () const; inline DbU::Unit getDHorizontalWidth () const;
inline DbU::Unit getDPHorizontalWidth () const;
inline DbU::Unit getDHorizontalPitch () const; inline DbU::Unit getDHorizontalPitch () const;
inline DbU::Unit getDHorizontalOffset () const; inline DbU::Unit getDHorizontalOffset () const;
inline size_t getDContactDepth () const; inline size_t getDContactDepth () const;
@ -103,15 +104,20 @@ namespace Anabatic {
DbU::Unit getPitch ( size_t depth, Flags flags ) const; DbU::Unit getPitch ( size_t depth, Flags flags ) const;
DbU::Unit getOffset ( size_t depth ) const; DbU::Unit getOffset ( size_t depth ) const;
DbU::Unit getWireWidth ( 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; DbU::Unit getExtensionCap ( size_t depth ) const;
Flags getDirection ( size_t depth ) const; Flags getDirection ( size_t depth ) const;
DbU::Unit getPitch ( const Layer*, Flags flags ) const; DbU::Unit getPitch ( const Layer*, Flags flags ) const;
DbU::Unit getOffset ( const Layer* ) const; DbU::Unit getOffset ( const Layer* ) const;
DbU::Unit getWireWidth ( const Layer* ) const; DbU::Unit getWireWidth ( const Layer* ) const;
DbU::Unit getPWireWidth ( const Layer* ) const;
DbU::Unit getExtensionCap ( const Layer* ) const; DbU::Unit getExtensionCap ( const Layer* ) const;
Flags getDirection ( const Layer* ) const; Flags getDirection ( const Layer* ) const;
float getSaturateRatio () const; float getSaturateRatio () const;
size_t getSaturateRp () const; size_t getSaturateRp () const;
inline std::string getDiodeName () const;
inline DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getAntennaDiodeMaxWL () const;
DbU::Unit getGlobalThreshold () const; DbU::Unit getGlobalThreshold () const;
void setAllowedDepth ( size_t ); void setAllowedDepth ( size_t );
void setSaturateRatio ( float ); void setSaturateRatio ( float );
@ -154,12 +160,16 @@ namespace Anabatic {
float _edgeHInc; float _edgeHInc;
float _edgeHScaling; float _edgeHScaling;
int _globalIterations; int _globalIterations;
std::string _diodeName;
DbU::Unit _antennaGateMaxWL;
DbU::Unit _antennaDiodeMaxWL;
private: private:
Configuration& operator= ( const Configuration& ) = delete; Configuration& operator= ( const Configuration& ) = delete;
void _setTopRoutingLayer ( Name name ); void _setTopRoutingLayer ( Name name );
}; };
inline 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::getGHorizontalDepth () const { return _gdepthh; }
inline size_t Configuration::getGVerticalDepth () const { return _gdepthv; } inline size_t Configuration::getGVerticalDepth () const { return _gdepthv; }
inline DbU::Unit Configuration::getGHorizontalPitch () const { return getPitch( getGHorizontalDepth(), Flags::NoFlags ); } inline DbU::Unit Configuration::getGHorizontalPitch () const { return getPitch( getGHorizontalDepth(), Flags::NoFlags ); }
@ -167,22 +177,25 @@ namespace Anabatic {
inline size_t Configuration::getDVerticalDepth () const { return _ddepthv; } inline size_t Configuration::getDVerticalDepth () const { return _ddepthv; }
inline const Layer* Configuration::getDVerticalLayer () const { return getRoutingLayer( getDVerticalDepth() ); } inline const Layer* Configuration::getDVerticalLayer () const { return getRoutingLayer( getDVerticalDepth() ); }
inline DbU::Unit Configuration::getDVerticalWidth () const { return getWireWidth ( 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::getDVerticalPitch () const { return getPitch ( getDVerticalDepth(), Flags::NoFlags ); }
inline DbU::Unit Configuration::getDVerticalOffset () const { return getOffset ( getDVerticalDepth() ); } inline DbU::Unit Configuration::getDVerticalOffset () const { return getOffset ( getDVerticalDepth() ); }
inline size_t Configuration::getDHorizontalDepth () const { return _ddepthh; } inline size_t Configuration::getDHorizontalDepth () const { return _ddepthh; }
inline const Layer* Configuration::getDHorizontalLayer () const { return getRoutingLayer( getDHorizontalDepth() ); } inline const Layer* Configuration::getDHorizontalLayer () const { return getRoutingLayer( getDHorizontalDepth() ); }
inline DbU::Unit Configuration::getDHorizontalWidth () const { return getWireWidth ( 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::getDHorizontalPitch () const { return getPitch ( getDHorizontalDepth(), Flags::NoFlags ); }
inline DbU::Unit Configuration::getDHorizontalOffset () const { return getOffset ( getDHorizontalDepth() ); } inline DbU::Unit Configuration::getDHorizontalOffset () const { return getOffset ( getDHorizontalDepth() ); }
inline size_t Configuration::getDContactDepth () const { return _ddepthc; } inline size_t Configuration::getDContactDepth () const { return _ddepthc; }
inline const Layer* Configuration::getDContactLayer () const { return getContactLayer( getDContactDepth() ); } inline const Layer* Configuration::getDContactLayer () const { return getContactLayer( getDContactDepth() ); }
inline DbU::Unit Configuration::getDContactWidth () const { return getWireWidth ( getDContactDepth() ); } inline DbU::Unit Configuration::getDContactWidth () const { return getWireWidth ( getDContactDepth() ); }
inline DbU::Unit Configuration::getDContactPitch () const { return getPitch ( getDContactDepth(), Flags::NoFlags ); } 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. } // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::Configuration); INSPECTOR_P_SUPPORT(Anabatic::Configuration);
#endif // ANABATIC_CONFIGURATION_H

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_CONSTANTS_H #pragma once
#define ANABATIC_CONSTANTS_H
#include "hurricane/Flags.h" #include "hurricane/Flags.h"
namespace Anabatic { namespace Anabatic {
@ -43,6 +41,7 @@ namespace Anabatic {
static const BaseFlags ChannelRow ; // = (1 << 13); static const BaseFlags ChannelRow ; // = (1 << 13);
static const BaseFlags HRailGCell ; // = (1 << 14); static const BaseFlags HRailGCell ; // = (1 << 14);
static const BaseFlags VRailGCell ; // = (1 << 15); static const BaseFlags VRailGCell ; // = (1 << 15);
static const BaseFlags GoStraight ; // = (1 << 16);
// Flags for Edge objects states only. // Flags for Edge objects states only.
static const BaseFlags NullCapacity ; // = (1 << 5); static const BaseFlags NullCapacity ; // = (1 << 5);
static const BaseFlags InfiniteCapacity ; // = (1 << 6); static const BaseFlags InfiniteCapacity ; // = (1 << 6);
@ -53,9 +52,11 @@ namespace Anabatic {
static const BaseFlags DestroyBaseContact ; // = (1 << 8); static const BaseFlags DestroyBaseContact ; // = (1 << 8);
static const BaseFlags DestroyBaseSegment ; // = (1 << 9); static const BaseFlags DestroyBaseSegment ; // = (1 << 9);
// Flags for NetDatas objects states only. // Flags for NetDatas objects states only.
static const BaseFlags GlobalRouted ; // = (1 << 5); static const BaseFlags GlobalFixed ; // = (1 << 5);
static const BaseFlags GlobalEstimated ; // = (1 << 6); static const BaseFlags GlobalEstimated ; // = (1 << 6);
static const BaseFlags ExcludeRoute ; // = (1 << 7); static const BaseFlags GlobalRouted ; // = (1 << 7);
static const BaseFlags DetailRouted ; // = (1 << 8);
static const BaseFlags ExcludeRoute ; // = (1 << 9);
// Masks. // Masks.
static const BaseFlags WestSide ; // = Horizontal|Target; static const BaseFlags WestSide ; // = Horizontal|Target;
static const BaseFlags EastSide ; // = Horizontal|Source; static const BaseFlags EastSide ; // = Horizontal|Source;
@ -99,6 +100,12 @@ namespace Anabatic {
static const BaseFlags CheckLowUpDensity ; static const BaseFlags CheckLowUpDensity ;
static const BaseFlags NoUpdate ; static const BaseFlags NoUpdate ;
static const BaseFlags NorthPath ; 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: public:
inline Flags ( uint64_t flags = NoFlags ); inline Flags ( uint64_t flags = NoFlags );
inline Flags ( const Hurricane::BaseFlags& ); inline Flags ( const Hurricane::BaseFlags& );
@ -145,6 +152,4 @@ namespace Anabatic {
} // Anabatic namespace. } // Anabatic namespace.
INSPECTOR_PV_SUPPORT(Anabatic::Flags) INSPECTOR_PR_SUPPORT(Anabatic::Flags);
#endif // ANABATIC_CONSTANTS_H

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_DIJKSTRA_H #pragma once
#define ANABATIC_DIJKSTRA_H
#include <set> #include <set>
#include <iomanip> #include <iomanip>
#include "hurricane/Observer.h" #include "hurricane/Observer.h"
@ -189,6 +187,7 @@ namespace Anabatic {
, iHorizontal = (1<<7) , iHorizontal = (1<<7)
, iVertical = (1<<8) , iVertical = (1<<8)
, iSet = (1<<9) , iSet = (1<<9)
, Driver = (1<<10)
}; };
public: public:
static DbU::Unit unreached; static DbU::Unit unreached;
@ -200,6 +199,7 @@ namespace Anabatic {
inline Vertex ( GCell* ); inline Vertex ( GCell* );
//inline Vertex ( size_t id ); //inline Vertex ( size_t id );
inline ~Vertex (); inline ~Vertex ();
inline bool isDriver () const;
inline bool isAnalog () const; inline bool isAnalog () const;
inline bool hasDoneAllRps () const; inline bool hasDoneAllRps () const;
inline Contact* hasGContact ( Net* ) const; inline Contact* hasGContact ( Net* ) const;
@ -220,6 +220,7 @@ namespace Anabatic {
Edge* getFrom () const; Edge* getFrom () const;
inline Vertex* getPredecessor () const; inline Vertex* getPredecessor () const;
inline Vertex* getNeighbor ( Edge* ) const; inline Vertex* getNeighbor ( Edge* ) const;
inline void setDriver ( bool state );
inline void setDistance ( DbU::Unit ); inline void setDistance ( DbU::Unit );
inline void setStamp ( int ); inline void setStamp ( int );
inline void setConnexId ( int ); inline void setConnexId ( int );
@ -333,6 +334,7 @@ namespace Anabatic {
inline Vertex* Vertex::lookup ( GCell* gcell ) { return gcell->getObserver<Vertex>(GCell::Observable::Vertex); } inline Vertex* Vertex::lookup ( GCell* gcell ) { return gcell->getObserver<Vertex>(GCell::Observable::Vertex); }
inline Vertex::~Vertex () { _gcell->setObserver( GCell::Observable::Vertex, NULL ); } inline Vertex::~Vertex () { _gcell->setObserver( GCell::Observable::Vertex, NULL ); }
inline bool Vertex::isDriver () const { return _flags & Driver; }
inline bool Vertex::isAnalog () const { return _gcell->isAnalog(); } inline bool Vertex::isAnalog () const { return _gcell->isAnalog(); }
inline Box Vertex::getBoundingBox () const { return _gcell->getBoundingBox(); } inline Box Vertex::getBoundingBox () const { return _gcell->getBoundingBox(); }
inline Edges Vertex::getEdges ( Flags sides ) const { return _gcell->getEdges(sides); } inline Edges Vertex::getEdges ( Flags sides ) const { return _gcell->getEdges(sides); }
@ -369,6 +371,12 @@ namespace Anabatic {
return (gcell) ? gcell->getObserver<Vertex>(GCell::Observable::Vertex) : NULL; return (gcell) ? gcell->getObserver<Vertex>(GCell::Observable::Vertex) : NULL;
} }
inline void Vertex::setDriver ( bool state )
{
if (state) _flags |= Driver;
else _flags &= ~Driver;
}
inline bool Vertex::CompareById::operator() ( const Vertex* lhs, const Vertex* rhs ) const inline bool Vertex::CompareById::operator() ( const Vertex* lhs, const Vertex* rhs ) const
{ return lhs->getId() < rhs->getId(); } { return lhs->getId() < rhs->getId(); }
@ -514,11 +522,13 @@ namespace Anabatic {
inline bool isSourceVertex ( Vertex* ) const; inline bool isSourceVertex ( Vertex* ) const;
inline Net* getNet () const; inline Net* getNet () const;
inline bool isTargetVertex ( Vertex* ) const; inline bool isTargetVertex ( Vertex* ) const;
DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getSearchAreaHalo () const; inline DbU::Unit getSearchAreaHalo () const;
template<typename DistanceT> template<typename DistanceT>
inline DistanceT* setDistance ( DistanceT ); inline DistanceT* setDistance ( DistanceT );
inline void setSearchAreaHalo ( DbU::Unit ); inline void setSearchAreaHalo ( DbU::Unit );
void load ( Net* net ); void load ( Net* net );
void loadFixedGlobal ( Net* net );
void run ( Mode mode=Mode::Standart ); void run ( Mode mode=Mode::Standart );
inline const VertexSet& getSources () const; inline const VertexSet& getSources () const;
private: private:
@ -593,6 +603,4 @@ namespace Anabatic {
GETSTRING_POINTER_SUPPORT(Anabatic::Vertex); GETSTRING_POINTER_SUPPORT(Anabatic::Vertex);
IOSTREAM_POINTER_SUPPORT(Anabatic::Vertex); IOSTREAM_POINTER_SUPPORT(Anabatic::Vertex);
INSPECTOR_PV_SUPPORT(Anabatic::Dijkstra::Mode); INSPECTOR_PR_SUPPORT(Anabatic::Dijkstra::Mode);
#endif // ANABATIC_DIJKSTRA_H

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_EDGE_H #pragma once
#define ANABATIC_EDGE_H
#include <string> #include <string>
#include "hurricane/Name.h" #include "hurricane/Name.h"
#include "hurricane/Interval.h" #include "hurricane/Interval.h"
@ -60,6 +58,7 @@ namespace Anabatic {
inline bool isHorizontal () const; inline bool isHorizontal () const;
inline bool hasNet ( const Net* ) const; inline bool hasNet ( const Net* ) const;
inline unsigned int getCapacity () const; inline unsigned int getCapacity () const;
inline unsigned int getRawCapacity () const;
inline unsigned int getReservedCapacity () const; inline unsigned int getReservedCapacity () const;
inline unsigned int getCapacity ( size_t depth ) const; inline unsigned int getCapacity ( size_t depth ) const;
inline unsigned int getRealOccupancy () const; inline unsigned int getRealOccupancy () const;
@ -136,8 +135,8 @@ namespace Anabatic {
inline bool Edge::isVertical () const { return _flags.isset(Flags::Vertical); } inline bool Edge::isVertical () const { return _flags.isset(Flags::Vertical); }
inline bool Edge::isHorizontal () const { return _flags.isset(Flags::Horizontal); } inline bool Edge::isHorizontal () const { return _flags.isset(Flags::Horizontal); }
inline bool Edge::hasNet ( const Net* owner ) const { return getSegment(owner); } inline bool Edge::hasNet ( const Net* owner ) const { return getSegment(owner); }
inline unsigned int Edge::getCapacity () const { return (_capacities) ? _capacities->getCapacity()-_reservedCapacity : 0; }
inline unsigned int Edge::getCapacity ( size_t depth ) const { return (_capacities) ? _capacities->getCapacity(depth) : 0; } 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::getReservedCapacity () const { return _reservedCapacity; }
inline unsigned int Edge::getRealOccupancy () const { return _realOccupancy; } inline unsigned int Edge::getRealOccupancy () const { return _realOccupancy; }
inline float Edge::getEstimateOccupancy () const { return _estimateOccupancy; } inline float Edge::getEstimateOccupancy () const { return _estimateOccupancy; }
@ -157,9 +156,13 @@ namespace Anabatic {
inline Flags& Edge::setFlags ( Flags mask ) { _flags |= mask; return _flags; } 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 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. } // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::Edge); INSPECTOR_P_SUPPORT(Anabatic::Edge);
#endif // ANABATIC_EDGE_H

View File

@ -14,10 +14,9 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef ANABATIC_GCELL_H #pragma once
#define ANABATIC_GCELL_H
#include <vector> #include <vector>
#include <queue>
#include <string> #include <string>
#include <set> #include <set>
#include <functional> #include <functional>
@ -115,14 +114,22 @@ namespace Anabatic {
public: public:
class Key { class Key {
public: public:
inline Key ( GCell*, size_t depth ); inline Key ( const GCell*, size_t depth );
inline float getDensity () const; inline ~Key ();
inline GCell* getGCell () const; inline float getDensity () const;
inline void update ( size_t depth ); inline const GCell* getGCell () const;
friend bool operator< ( const Key&, const Key& ); 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: private:
GCell* _gcell; const GCell* _gcell;
float _density; float _density;
}; };
public: public:
static uint32_t getDisplayMode (); static uint32_t getDisplayMode ();
@ -147,6 +154,7 @@ namespace Anabatic {
inline bool isMatrix () const; inline bool isMatrix () const;
inline bool isRow () const; inline bool isRow () const;
inline bool isIoPad () const; inline bool isIoPad () const;
inline bool isGoStraight () const;
inline bool isHRail () const; inline bool isHRail () const;
inline bool isVRail () const; inline bool isVRail () const;
inline bool isStdCellRow () const; inline bool isStdCellRow () const;
@ -155,6 +163,7 @@ namespace Anabatic {
bool isEast ( GCell* ) const; bool isEast ( GCell* ) const;
bool isNorth ( GCell* ) const; bool isNorth ( GCell* ) const;
bool isSouth ( GCell* ) const; bool isSouth ( GCell* ) const;
bool hasNet ( const Net* ) const;
Contact* hasGContact ( const Contact* ) const; Contact* hasGContact ( const Contact* ) const;
Contact* hasGContact ( const Net* ) const; Contact* hasGContact ( const Net* ) const;
bool isHorizontalPlane ( size_t depth ) const; bool isHorizontalPlane ( size_t depth ) const;
@ -206,7 +215,8 @@ namespace Anabatic {
bool doGrid (); bool doGrid ();
Contact* getGContact ( Net* ); Contact* getGContact ( Net* );
inline const vector<Contact*>& getGContacts () const; inline const vector<Contact*>& getGContacts () const;
Contact* breakGoThrough ( Net* net ); Segment* hasGoThrough ( Net* ) const;
Contact* breakGoThrough ( Net* );
bool unrefContact ( Contact* ); bool unrefContact ( Contact* );
void setSouthWestCorner ( DbU::Unit x, DbU::Unit y ); void setSouthWestCorner ( DbU::Unit x, DbU::Unit y );
void cleanupGlobal (); void cleanupGlobal ();
@ -216,6 +226,7 @@ namespace Anabatic {
bool hasFreeTrack ( size_t depth, float reserve ) const; bool hasFreeTrack ( size_t depth, float reserve ) const;
inline size_t getDepth () const; inline size_t getDepth () const;
size_t getNetCount () const; size_t getNetCount () const;
inline int getRpCount () const;
int getHCapacity () const; int getHCapacity () const;
int getVCapacity () const; int getVCapacity () const;
int getCapacity ( size_t depth ) const; int getCapacity ( size_t depth ) const;
@ -240,6 +251,9 @@ namespace Anabatic {
inline AutoSegments getStopSegments ( Flags direction ); inline AutoSegments getStopSegments ( Flags direction );
size_t getRoutingPads ( set<RoutingPad*>& ); size_t getRoutingPads ( set<RoutingPad*>& );
inline const Key& getKey () const; inline const Key& getKey () const;
inline Key* cloneKey ( size_t depth ) const;
inline Key* getLastClonedKey () const;
inline void clearClonedKey () const;
size_t checkDensity () const; size_t checkDensity () const;
bool checkEdgeSaturation ( size_t hreserved, size_t vreserved) const; bool checkEdgeSaturation ( size_t hreserved, size_t vreserved) const;
void setType ( Flags ); void setType ( Flags );
@ -263,7 +277,7 @@ namespace Anabatic {
bool stepNetDesaturate ( size_t depth bool stepNetDesaturate ( size_t depth
, set<Net*>& globalNets , set<Net*>& globalNets
, Set& invalidateds ); , Set& invalidateds );
inline void incRpCount ( int );
void forceEdgesCapacities ( unsigned int hcapacities, unsigned int vcapacities ); void forceEdgesCapacities ( unsigned int hcapacities, unsigned int vcapacities );
// Misc. functions. // Misc. functions.
inline const Flags& flags () const; inline const Flags& flags () const;
@ -320,6 +334,7 @@ namespace Anabatic {
vector<AutoContact*> _contacts; vector<AutoContact*> _contacts;
size_t _depth; size_t _depth;
size_t _pinDepth; size_t _pinDepth;
int _rpCount;
DbU::Unit* _blockages; DbU::Unit* _blockages;
float _cDensity; float _cDensity;
float* _densities; float* _densities;
@ -327,65 +342,71 @@ namespace Anabatic {
float* _fragmentations; float* _fragmentations;
float* _globalsCount; float* _globalsCount;
Key _key; Key _key;
mutable Key* _lastClonedKey;
}; };
inline bool GCell::isHFlat () const { return getYMin() == getYMax(); } inline bool GCell::isHFlat () const { return getYMin() == getYMax(); }
inline bool GCell::isVFlat () const { return getXMin() == getXMax(); } inline bool GCell::isVFlat () const { return getXMin() == getXMax(); }
inline bool GCell::isFlat () const { return isHFlat() or isVFlat(); } inline bool GCell::isFlat () const { return isHFlat() or isVFlat(); }
inline bool GCell::isDevice () const { return _flags & Flags::DeviceGCell; } inline bool GCell::isDevice () const { return _flags & Flags::DeviceGCell; }
inline bool GCell::isHChannel () const { return _flags & Flags::HChannelGCell; } inline bool GCell::isHChannel () const { return _flags & Flags::HChannelGCell; }
inline bool GCell::isVChannel () const { return _flags & Flags::VChannelGCell; } inline bool GCell::isVChannel () const { return _flags & Flags::VChannelGCell; }
inline bool GCell::isStrut () const { return _flags & Flags::StrutGCell; } inline bool GCell::isStrut () const { return _flags & Flags::StrutGCell; }
inline bool GCell::isAnalog () const { return _flags & Flags::AnalogGCellMask; } inline bool GCell::isAnalog () const { return _flags & Flags::AnalogGCellMask; }
inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; } inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; }
inline bool GCell::isRow () const { return _flags & Flags::RowGCellMask; } inline bool GCell::isRow () const { return _flags & Flags::RowGCellMask; }
inline bool GCell::isIoPad () const { return _flags & Flags::IoPadGCell; } inline bool GCell::isIoPad () const { return _flags & Flags::IoPadGCell; }
inline bool GCell::isHRail () const { return _flags & Flags::HRailGCell; } inline bool GCell::isGoStraight () const { return _flags & Flags::GoStraight; }
inline bool GCell::isVRail () const { return _flags & Flags::VRailGCell; } inline bool GCell::isHRail () const { return _flags & Flags::HRailGCell; }
inline bool GCell::isStdCellRow () const { return _flags & Flags::StdCellRow; } inline bool GCell::isVRail () const { return _flags & Flags::VRailGCell; }
inline bool GCell::isChannelRow () const { return _flags & Flags::ChannelRow; } inline bool GCell::isStdCellRow () const { return _flags & Flags::StdCellRow; }
inline bool GCell::isSaturated () const { return _flags & Flags::Saturated; } inline bool GCell::isChannelRow () const { return _flags & Flags::ChannelRow; }
inline bool GCell::isInvalidated () const { return _flags & Flags::Invalidated; } inline bool GCell::isSaturated () const { return _flags & Flags::Saturated; }
inline DbU::Unit GCell::getMatrixHSide () { return _matrixHSide; } inline bool GCell::isInvalidated () const { return _flags & Flags::Invalidated; }
inline DbU::Unit GCell::getMatrixVSide () { return _matrixVSide; } inline DbU::Unit GCell::getMatrixHSide () { return _matrixHSide; }
inline Flags GCell::getType () const { return _flags & Flags::GCellTypeMask; } inline DbU::Unit GCell::getMatrixVSide () { return _matrixVSide; }
inline AnabaticEngine* GCell::getAnabatic () const { return _anabatic; } inline Flags GCell::getType () const { return _flags & Flags::GCellTypeMask; }
inline DbU::Unit GCell::getXMin () const { return _xmin; } inline AnabaticEngine* GCell::getAnabatic () const { return _anabatic; }
inline DbU::Unit GCell::getYMin () const { return _ymin; } inline DbU::Unit GCell::getXMin () const { return _xmin; }
inline Interval GCell::getHSide ( int shrink ) const { return getSide(Flags::Horizontal,shrink); } inline DbU::Unit GCell::getYMin () const { return _ymin; }
inline Interval GCell::getVSide ( int shrink ) const { return getSide(Flags::Vertical ,shrink); } inline Interval GCell::getHSide ( int shrink ) const { return getSide(Flags::Horizontal,shrink); }
inline Edges GCell::getEdges ( Flags sides ) const { return new GCell_Edges(this,sides); } inline Interval GCell::getVSide ( int shrink ) const { return getSide(Flags::Vertical ,shrink); }
inline const vector<Edge*>& GCell::getWestEdges () const { return _westEdges; } inline Edges GCell::getEdges ( Flags sides ) const { return new GCell_Edges(this,sides); }
inline const vector<Edge*>& GCell::getEastEdges () const { return _eastEdges; } inline const vector<Edge*>& GCell::getWestEdges () const { return _westEdges; }
inline const vector<Edge*>& GCell::getNorthEdges () const { return _northEdges; } inline const vector<Edge*>& GCell::getEastEdges () const { return _eastEdges; }
inline const vector<Edge*>& GCell::getSouthEdges () const { return _southEdges; } inline const vector<Edge*>& GCell::getNorthEdges () const { return _northEdges; }
inline GCell* GCell::getWest () const { return _westEdges.empty() ? NULL : _westEdges[0]->getOpposite(this); } inline const vector<Edge*>& GCell::getSouthEdges () const { return _southEdges; }
inline GCell* GCell::getEast () const { return _eastEdges.empty() ? NULL : _eastEdges[0]->getOpposite(this); } inline GCell* GCell::getWest () const { return _westEdges.empty() ? NULL : _westEdges[0]->getOpposite(this); }
inline GCell* GCell::getSouth () const { return _southEdges.empty() ? NULL : _southEdges[0]->getOpposite(this); } inline GCell* GCell::getEast () const { return _eastEdges.empty() ? NULL : _eastEdges[0]->getOpposite(this); }
inline GCell* GCell::getNorth () const { return _northEdges.empty() ? NULL : _northEdges[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::getWestEdge () const { return _westEdges.empty() ? NULL : _westEdges[0]; }
inline Edge* GCell::getEastEdge () const { return _eastEdges.empty() ? NULL : _eastEdges[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::getSouthEdge () const { return _southEdges.empty() ? NULL : _southEdges[0]; }
inline Edge* GCell::getNorthEdge () const { return _northEdges.empty() ? NULL : _northEdges[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 GCell* GCell::getUnder ( Point p ) const { return getUnder(p.getX(),p.getY()); }
inline const vector<Contact*>& GCell::getGContacts () const { return _gcontacts; } inline const vector<Contact*>& GCell::getGContacts () const { return _gcontacts; }
inline size_t GCell::getDepth () const { return _depth; } inline size_t GCell::getDepth () const { return _depth; }
const vector<AutoSegment*>& GCell::getVSegments () const { return _vsegments; } inline int GCell::getRpCount () const { return _rpCount; }
inline const vector<AutoSegment*>& GCell::getHSegments () const { return _hsegments; } const vector<AutoSegment*>& GCell::getVSegments () const { return _vsegments; }
inline const vector<AutoContact*>& GCell::getContacts () const { return _contacts; } 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::getWidth () const { return (getXMax()-getXMin()); }
inline DbU::Unit GCell::getHeight () const { return (getYMax()-getYMin()); } 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 float GCell::getDensity ( size_t depth ) const { return (depth<_depth) ? _densities[depth] : 0.0; }
inline const GCell::Key& GCell::getKey () const { return _key; } inline const GCell::Key& GCell::getKey () const { return _key; }
inline void GCell::setType ( Flags type ) { _flags.reset(Flags::GCellTypeMask); _flags |= (type&Flags::GCellTypeMask); }; inline GCell::Key* GCell::cloneKey ( size_t depth ) const { _lastClonedKey = new Key(this,depth); return _lastClonedKey; }
inline void GCell::updateKey ( size_t depth ) { _key.update(depth); } inline void GCell::clearClonedKey () const { _lastClonedKey=NULL; }
inline const Flags& GCell::flags () const { return _flags; } inline GCell::Key* GCell::getLastClonedKey () const { return _lastClonedKey; }
inline Flags& GCell::flags () { return _flags; } 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 inline DbU::Unit GCell::getXMax ( int shrink ) const
{ return _eastEdges.empty() ? getCell()->getAbutmentBox().getXMax() - shrink { return _eastEdges.empty() ? getCell()->getAbutmentBox().getXMax() - shrink
@ -416,6 +437,10 @@ namespace Anabatic {
return Interval( getXMin(), getConstraintXMax(shrink) ); 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 ) inline void GCell::setObserver ( size_t slot, BaseObserver* observer )
{ _observable.setObserver( slot, observer ); } { _observable.setObserver( slot, observer ); }
@ -469,17 +494,25 @@ namespace Anabatic {
return lhs.getId() < rhs.getId(); return lhs.getId() < rhs.getId();
} }
// GCell::CompareByKey Inline Functions. // GCell::CompareByKey Inline Functions.
inline bool GCell::CompareByKey::operator() ( const GCell* lhs, const GCell* rhs ) inline bool GCell::CompareByKey::operator() ( const GCell* lhs, const GCell* rhs )
{ return lhs->getKey() < rhs->getKey(); } { return lhs->getKey() < rhs->getKey(); }
// GCell::Key Inline Functions. // GCell::Key Inline Functions.
inline GCell::Key::Key ( GCell* owner, size_t depth ) : _gcell(owner), _density(owner->getWDensity(depth,Flags::NoUpdate)) {} inline GCell::Key::Key ( const GCell* owner, size_t depth )
inline float GCell::Key::getDensity () const { return _density; } : _gcell(owner)
inline GCell* GCell::Key::getGCell () const { return _gcell; } , _density(owner->getWDensity(depth,Flags::NoUpdate))
inline void GCell::Key::update ( size_t depth ) { _density=_gcell->getWDensity(depth); } { }
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 ) inline bool operator< ( const GCell::Key& lhs, const GCell::Key& rhs )
{ {
@ -489,6 +522,22 @@ namespace Anabatic {
return lhs._gcell->getId() < rhs._gcell->getId(); 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". // Class : "GCellDensitySet".
@ -533,5 +582,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::GCell); INSPECTOR_P_SUPPORT(Anabatic::GCell);
#endif // ANABATIC_GCELL_H

View File

@ -98,6 +98,9 @@ namespace Anabatic {
, WestBound = (1 << 14) , WestBound = (1 << 14)
, EastBound = (1 << 15) , EastBound = (1 << 15)
, Middle = (1 << 16) , Middle = (1 << 16)
, UseNonPref = (1 << 17)
, NoProtect = (1 << 18)
, HBothAccess = HAccess|HAccessEW
, SouthWest = SouthBound|WestBound , SouthWest = SouthBound|WestBound
, NorthEast = NorthBound|EastBound , NorthEast = NorthBound|EastBound
}; };
@ -202,6 +205,8 @@ namespace Anabatic {
virtual bool _do_xG (); virtual bool _do_xG ();
virtual bool _do_2G (); virtual bool _do_2G ();
virtual bool _do_xG_1Pad (); virtual bool _do_xG_1Pad ();
virtual bool _do_1G_1PinM1 ();
virtual bool _do_2G_1PinM1 ();
virtual bool _do_1G_1PinM2 (); virtual bool _do_1G_1PinM2 ();
virtual bool _do_xG_1PinM2 (); virtual bool _do_xG_1PinM2 ();
virtual bool _do_1G_1PinM3 (); virtual bool _do_1G_1PinM3 ();
@ -216,6 +221,11 @@ namespace Anabatic {
virtual bool _do_xG_xM2 (); virtual bool _do_xG_xM2 ();
virtual bool _do_1G_1M3 (); virtual bool _do_1G_1M3 ();
virtual bool _do_xG_xM3 (); 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 bool _do_globalSegment ();
virtual void singleGCell ( AnabaticEngine*, Net* ); virtual void singleGCell ( AnabaticEngine*, Net* );
AutoContact* _doHChannel (); AutoContact* _doHChannel ();
@ -237,71 +247,102 @@ namespace Anabatic {
+ ((pads) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize)) \ + ((pads) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize)) \
+ ((pins) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize+PadsBSize)) + ((pins) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize+PadsBSize))
// Connexity Name | G|M1|M2|M3|Pad|Pin| // Connexity Name | G|M1|M2|M3|Pad|Pin|
enum ConnexityFlag { Conn_0G = CONNEXITY_VALUE( 0, 0, 0, 0, 0 , 0 ) enum ConnexityFlag { Conn_0G = CONNEXITY_VALUE( 0, 0, 0, 0, 0 , 0 )
, Conn_2G = CONNEXITY_VALUE( 2, 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_3G = CONNEXITY_VALUE( 3, 0, 0, 0, 0 , 0 )
, Conn_4G = CONNEXITY_VALUE( 4, 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_5G = CONNEXITY_VALUE( 5, 0, 0, 0, 0 , 0 )
, Conn_6G = CONNEXITY_VALUE( 6, 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_0G_2M1 = CONNEXITY_VALUE( 0, 2, 0, 0, 0 , 0 )
, Conn_1G_1M1 = CONNEXITY_VALUE( 1, 1, 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_2M1 = CONNEXITY_VALUE( 1, 2, 0, 0, 0 , 0 )
, Conn_1G_3M1 = CONNEXITY_VALUE( 1, 3, 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_4M1 = CONNEXITY_VALUE( 1, 4, 0, 0, 0 , 0 )
, Conn_1G_5M1 = CONNEXITY_VALUE( 1, 5, 0, 0, 0 , 0 ) , Conn_1G_5M1 = CONNEXITY_VALUE( 1, 5, 0, 0, 0 , 0 )
, Conn_1G_1M2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 0 ) , Conn_1G_6M1 = CONNEXITY_VALUE( 1, 6, 0, 0, 0 , 0 )
, Conn_1G_2M2 = CONNEXITY_VALUE( 1, 0, 2, 0, 0 , 0 ) , Conn_1G_7M1 = CONNEXITY_VALUE( 1, 7, 0, 0, 0 , 0 )
, Conn_1G_3M2 = CONNEXITY_VALUE( 1, 0, 3, 0, 0 , 0 ) , Conn_1G_8M1 = CONNEXITY_VALUE( 1, 8, 0, 0, 0 , 0 )
, Conn_1G_4M2 = CONNEXITY_VALUE( 1, 0, 4, 0, 0 , 0 ) , Conn_1G_9M1 = CONNEXITY_VALUE( 1, 9, 0, 0, 0 , 0 )
, Conn_1G_1M3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 0 ) , Conn_1G_1M2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 0 )
, Conn_1G_2M3 = CONNEXITY_VALUE( 1, 0, 0, 2, 0 , 0 ) , Conn_1G_2M2 = CONNEXITY_VALUE( 1, 0, 2, 0, 0 , 0 )
, Conn_1G_3M3 = CONNEXITY_VALUE( 1, 0, 0, 3, 0 , 0 ) , Conn_1G_3M2 = CONNEXITY_VALUE( 1, 0, 3, 0, 0 , 0 )
, Conn_1G_4M3 = CONNEXITY_VALUE( 1, 0, 0, 4, 0 , 0 ) , Conn_1G_4M2 = CONNEXITY_VALUE( 1, 0, 4, 0, 0 , 0 )
, Conn_1G_1M1_1M2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 0 ) , Conn_1G_1M3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 0 )
, Conn_1G_1M1_1M3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 0 ) , Conn_1G_2M3 = CONNEXITY_VALUE( 1, 0, 0, 2, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin| , Conn_1G_3M3 = CONNEXITY_VALUE( 1, 0, 0, 3, 0 , 0 )
, Conn_2G_1M1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 0 ) , Conn_1G_4M3 = CONNEXITY_VALUE( 1, 0, 0, 4, 0 , 0 )
, Conn_2G_2M1 = CONNEXITY_VALUE( 2, 2, 0, 0, 0 , 0 ) , Conn_1G_1M1_1M2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 0 )
, Conn_2G_3M1 = CONNEXITY_VALUE( 2, 3, 0, 0, 0 , 0 ) , Conn_1G_1M1_1M3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 0 )
, Conn_2G_4M1 = CONNEXITY_VALUE( 2, 4, 0, 0, 0 , 0 ) // Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_2G_5M1 = CONNEXITY_VALUE( 2, 5, 0, 0, 0 , 0 ) , Conn_2G_1M1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 0 )
, Conn_2G_1M2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 0 ) , Conn_2G_2M1 = CONNEXITY_VALUE( 2, 2, 0, 0, 0 , 0 )
, Conn_2G_2M2 = CONNEXITY_VALUE( 2, 0, 2, 0, 0 , 0 ) , Conn_2G_3M1 = CONNEXITY_VALUE( 2, 3, 0, 0, 0 , 0 )
, Conn_2G_3M2 = CONNEXITY_VALUE( 2, 0, 3, 0, 0 , 0 ) , Conn_2G_4M1 = CONNEXITY_VALUE( 2, 4, 0, 0, 0 , 0 )
, Conn_2G_4M2 = CONNEXITY_VALUE( 2, 0, 4, 0, 0 , 0 ) , Conn_2G_5M1 = CONNEXITY_VALUE( 2, 5, 0, 0, 0 , 0 )
, Conn_2G_1M3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 0 ) , Conn_2G_6M1 = CONNEXITY_VALUE( 2, 6, 0, 0, 0 , 0 )
, Conn_2G_2M3 = CONNEXITY_VALUE( 2, 0, 0, 2, 0 , 0 ) , Conn_2G_7M1 = CONNEXITY_VALUE( 2, 7, 0, 0, 0 , 0 )
, Conn_2G_3M3 = CONNEXITY_VALUE( 2, 0, 0, 3, 0 , 0 ) , Conn_2G_8M1 = CONNEXITY_VALUE( 2, 8, 0, 0, 0 , 0 )
, Conn_2G_4M3 = CONNEXITY_VALUE( 2, 0, 0, 4, 0 , 0 ) , Conn_2G_9M1 = CONNEXITY_VALUE( 2, 9, 0, 0, 0 , 0 )
, Conn_2G_1M1_1M2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 0 ) , Conn_2G_1M2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin| , Conn_2G_2M2 = CONNEXITY_VALUE( 2, 0, 2, 0, 0 , 0 )
, Conn_3G_1M1 = CONNEXITY_VALUE( 3, 1, 0, 0, 0 , 0 ) , Conn_2G_3M2 = CONNEXITY_VALUE( 2, 0, 3, 0, 0 , 0 )
, Conn_3G_2M1 = CONNEXITY_VALUE( 3, 2, 0, 0, 0 , 0 ) , Conn_2G_4M2 = CONNEXITY_VALUE( 2, 0, 4, 0, 0 , 0 )
, Conn_3G_3M1 = CONNEXITY_VALUE( 3, 3, 0, 0, 0 , 0 ) , Conn_2G_1M3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 0 )
, Conn_3G_4M1 = CONNEXITY_VALUE( 3, 4, 0, 0, 0 , 0 ) , Conn_2G_2M3 = CONNEXITY_VALUE( 2, 0, 0, 2, 0 , 0 )
, Conn_3G_1M2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 0 ) , Conn_2G_3M3 = CONNEXITY_VALUE( 2, 0, 0, 3, 0 , 0 )
, Conn_3G_2M2 = CONNEXITY_VALUE( 3, 0, 2, 0, 0 , 0 ) , Conn_2G_4M3 = CONNEXITY_VALUE( 2, 0, 0, 4, 0 , 0 )
, Conn_3G_1M3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 0 ) , Conn_2G_1M1_1M2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 0 )
, Conn_3G_2M3 = CONNEXITY_VALUE( 3, 0, 0, 2, 0 , 0 ) // Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_3G_3M3 = CONNEXITY_VALUE( 3, 0, 0, 3, 0 , 0 ) , Conn_3G_1M1 = CONNEXITY_VALUE( 3, 1, 0, 0, 0 , 0 )
, Conn_3G_4M3 = CONNEXITY_VALUE( 3, 0, 0, 4, 0 , 0 ) , Conn_3G_2M1 = CONNEXITY_VALUE( 3, 2, 0, 0, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin| , Conn_3G_3M1 = CONNEXITY_VALUE( 3, 3, 0, 0, 0 , 0 )
, Conn_4G_1M1 = CONNEXITY_VALUE( 4, 1, 0, 0, 0 , 0 ) , Conn_3G_4M1 = CONNEXITY_VALUE( 3, 4, 0, 0, 0 , 0 )
, Conn_4G_2M1 = CONNEXITY_VALUE( 4, 2, 0, 0, 0 , 0 ) , Conn_3G_5M1 = CONNEXITY_VALUE( 3, 5, 0, 0, 0 , 0 )
, Conn_4G_3M1 = CONNEXITY_VALUE( 4, 3, 0, 0, 0 , 0 ) , Conn_3G_6M1 = CONNEXITY_VALUE( 3, 6, 0, 0, 0 , 0 )
, Conn_4G_4M1 = CONNEXITY_VALUE( 4, 4, 0, 0, 0 , 0 ) , Conn_3G_7M1 = CONNEXITY_VALUE( 3, 7, 0, 0, 0 , 0 )
, Conn_4G_1M2 = CONNEXITY_VALUE( 4, 0, 1, 0, 0 , 0 ) , Conn_3G_8M1 = CONNEXITY_VALUE( 3, 8, 0, 0, 0 , 0 )
, Conn_4G_1M3 = CONNEXITY_VALUE( 4, 0, 0, 1, 0 , 0 ) , Conn_3G_9M1 = CONNEXITY_VALUE( 3, 9, 0, 0, 0 , 0 )
, Conn_1G_1Pad = CONNEXITY_VALUE( 1, 0, 0, 0, 1 , 0 ) , Conn_3G_1M2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 0 )
, Conn_2G_1Pad = CONNEXITY_VALUE( 2, 0, 0, 0, 1 , 0 ) , Conn_3G_2M2 = CONNEXITY_VALUE( 3, 0, 2, 0, 0 , 0 )
, Conn_3G_1Pad = CONNEXITY_VALUE( 3, 0, 0, 0, 1 , 0 ) , Conn_3G_1M3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 0 )
, Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 1 ) , Conn_3G_2M3 = CONNEXITY_VALUE( 3, 0, 0, 2, 0 , 0 )
, Conn_2G_1PinM2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 1 ) , Conn_3G_3M3 = CONNEXITY_VALUE( 3, 0, 0, 3, 0 , 0 )
, Conn_3G_1PinM2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 1 ) , Conn_3G_4M3 = CONNEXITY_VALUE( 3, 0, 0, 4, 0 , 0 )
, Conn_1G_1PinM3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 1 ) // Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_2G_1PinM3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 1 ) , Conn_4G_1M1 = CONNEXITY_VALUE( 4, 1, 0, 0, 0 , 0 )
, Conn_3G_1PinM3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 1 ) , 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 #undef CONNEXITY_VALUE

View File

@ -25,33 +25,44 @@ namespace Anabatic {
// ----------------------------------------------------------------- // -----------------------------------------------------------------
// Class : "NetBuilderHV". // Class : "NetBuilderHV".
class NetBuilderHV : public NetBuilder { class NetBuilderHV : public NetBuilder {
public: public:
NetBuilderHV (); NetBuilderHV ();
virtual ~NetBuilderHV (); virtual ~NetBuilderHV ();
virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags ); virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags );
virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags ); virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags );
AutoContact* doRp_AccessNorthPin ( GCell*, RoutingPad* );
AutoContact* doRp_AccessEastWestPin ( GCell*, RoutingPad* );
private: private:
virtual bool _do_1G_1M1 (); virtual bool _do_1G_1M1 ();
virtual bool _do_1G_xM1 (); virtual bool _do_1G_xM1 ();
virtual bool _do_xG (); virtual bool _do_xG ();
virtual bool _do_2G (); virtual bool _do_2G ();
virtual bool _do_2G_1M1 (); virtual bool _do_2G_1M1 ();
virtual bool _do_xG_1Pad (); virtual bool _do_xG_1Pad ();
virtual bool _do_1G_1PinM2 (); virtual bool _do_1G_1PinM1 ();
virtual bool _do_xG_1PinM2 (); virtual bool _do_2G_1PinM1 ();
virtual bool _do_1G_1PinM3 (); virtual bool _do_1G_1PinM2 ();
virtual bool _do_xG_1PinM3 (); virtual bool _do_xG_1PinM2 ();
virtual bool _do_xG_1M1 (); virtual bool _do_1G_1PinM3 ();
virtual bool _do_xG_1M1_1M2 (); virtual bool _do_xG_1PinM3 ();
virtual bool _do_xG_xM1_xM3 (); virtual bool _do_xG_1M1 ();
virtual bool _do_4G_1M2 (); virtual bool _do_xG_1M1_1M2 ();
virtual bool _do_xG_xM2 (); virtual bool _do_xG_xM1_xM3 ();
virtual bool _do_1G_1M3 (); virtual bool _do_4G_1M2 ();
virtual bool _do_xG_xM3 (); virtual bool _do_xG_xM2 ();
virtual bool _do_globalSegment (); 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: public:
virtual string getTypeName () const; virtual string getTypeName () const;
}; };

View File

@ -41,6 +41,7 @@ namespace Anabatic {
virtual bool _do_2G_1M1 (); virtual bool _do_2G_1M1 ();
virtual bool _do_xG_xM1_xM3 (); virtual bool _do_xG_xM1_xM3 ();
virtual bool _do_xG (); virtual bool _do_xG ();
virtual bool _do_2G ();
virtual bool _do_globalSegment (); virtual bool _do_globalSegment ();
virtual void singleGCell ( AnabaticEngine*, Net* ); virtual void singleGCell ( AnabaticEngine*, Net* );
public: public:

View File

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

View File

@ -5,7 +5,7 @@
cmake_minimum_required(VERSION 2.4.0) cmake_minimum_required(VERSION 2.4.0)
set(ignoreVariables "${BUILD_DOC}") set(ignoreVariables "${BUILD_DOC} ${CMAKE_INSTALL_DIR}")
add_subdirectory(cmake_modules) add_subdirectory(cmake_modules)

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

@ -14,17 +14,17 @@ projects = [
, { 'name' : "coriolis" , { 'name' : "coriolis"
, 'tools' : [ "bootstrap" , 'tools' : [ "bootstrap"
, "lefdef" , "lefdef"
, "flute" , "coloquinte"
, "vlsisapd" , "vlsisapd"
, "hurricane" , "hurricane"
, "crlcore" , "crlcore"
, "flute"
, "etesian"
, "anabatic" , "anabatic"
, "katana" , "katana"
, "knik" , "knik"
, "katabatic" , "katabatic"
, "kite" , "kite"
, "coloquinte"
, "etesian"
, "equinox" , "equinox"
, "solstice" , "solstice"
, "oroshi" , "oroshi"

View File

@ -38,6 +38,7 @@ class Builder:
self._noSystemBoost = False self._noSystemBoost = False
self._macports = False self._macports = False
self._devtoolset = 0 self._devtoolset = 0
self._llvmtoolset = 0
self._qt5 = False self._qt5 = False
self._openmp = False self._openmp = False
self._enableShared = "ON" self._enableShared = "ON"
@ -69,6 +70,8 @@ class Builder:
elif attribute == "devtoolset": elif attribute == "devtoolset":
self._devtoolset = value self._devtoolset = value
if value: self._noSystemBoost = True if value: self._noSystemBoost = True
elif attribute == "llvmtoolset":
self._llvmtoolset = value
elif attribute == "qt5": self._qt5 = value elif attribute == "qt5": self._qt5 = value
elif attribute == "openmp": self._openmp = value elif attribute == "openmp": self._openmp = value
elif attribute == "enableDoc": self._enableDoc = value elif attribute == "enableDoc": self._enableDoc = value
@ -132,17 +135,24 @@ class Builder:
def _execute ( self, command, error ): def _execute ( self, command, error ):
collections = []
if self._devtoolset: if self._devtoolset:
print 'Using devtoolset-%(v)d (scl enable devtoolset-%(v)d ...)' % {'v':self._devtoolset} collections.append( 'devtoolset-%d' % self._devtoolset )
commandAsString = '' print 'Using devtoolset-%(v)d (scl enable devtoolset-%(v)d ...)' % {'v':self._devtoolset}
for i in range(len(command)): if self._llvmtoolset:
if i: commandAsString += ' ' collections.append( 'llvm-toolset-%d' % self._llvmtoolset )
if ' ' in command[i]: commandAsString += '"'+command[i]+'"' print 'Using llvm-toolset-%(v)d (scl enable llvm-toolset-%(v)d ...)' % {'v':self._llvmtoolset}
else: commandAsString += command[i]
command = [ 'scl', 'enable', 'devtoolset-%d' % self._devtoolset if collections:
, commandAsString ] 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.stdout.flush ()
sys.stderr.flush () sys.stderr.flush ()
child = subprocess.Popen ( command, env=self._environment, stdout=None ) child = subprocess.Popen ( command, env=self._environment, stdout=None )
@ -175,9 +185,10 @@ class Builder:
command = [ 'cmake' ] command = [ 'cmake' ]
if self._ninja: command += [ "-G", "Ninja" ] if self._ninja: command += [ "-G", "Ninja" ]
if self._macports: command += [ "-D", "WITH_MACPORTS:STRING=TRUE" ]
if self._noSystemBoost: command += [ "-D", "Boost_NO_SYSTEM_PATHS:STRING=TRUE" if self._noSystemBoost: command += [ "-D", "Boost_NO_SYSTEM_PATHS:STRING=TRUE"
, "-D", "BOOST_INCLUDEDIR:STRING=/usr/include/boost157" #, "-D", "BOOST_INCLUDEDIR:STRING=/usr/include/boost169"
, "-D", "BOOST_LIBRARYDIR:STRING=/usr/lib/boost157" #, "-D", "BOOST_LIBRARYDIR:STRING=/usr/lib64/boost169"
] ]
if self._qt5: command += [ "-D", "WITH_QT5:STRING=TRUE" ] if self._qt5: command += [ "-D", "WITH_QT5:STRING=TRUE" ]
if self._openmp: command += [ "-D", "WITH_OPENMP:STRING=TRUE" ] if self._openmp: command += [ "-D", "WITH_OPENMP:STRING=TRUE" ]
@ -187,6 +198,7 @@ class Builder:
, "-D", "CMAKE_INSTALL_PREFIX:STRING=%s" % self.installDir , "-D", "CMAKE_INSTALL_PREFIX:STRING=%s" % self.installDir
, "-D", "CMAKE_INSTALL_DIR:STRING=%s" % cmakeInstallDir , "-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 ] , toolSourceDir ]
if not os.path.isdir(toolBuildDir): if not os.path.isdir(toolBuildDir):
@ -210,8 +222,6 @@ class Builder:
if self._checkDeterminism == 'ON': command += [ "-D", "CHECK_DETERMINISM:STRING=ON" ] if self._checkDeterminism == 'ON': command += [ "-D", "CHECK_DETERMINISM:STRING=ON" ]
command += [ toolSourceDir ] command += [ toolSourceDir ]
print self._noSystemBoost
print command
self._execute ( command, "Second CMake failed" ) self._execute ( command, "Second CMake failed" )
if self._doBuild: if self._doBuild:
@ -299,8 +309,8 @@ class Builder:
def _commandTemplate ( self, tools, projects, command ): def _commandTemplate ( self, tools, projects, command ):
if self._clang: if self._clang:
self._environment[ 'CC' ] = '/usr/bin/clang' self._environment[ 'CC' ] = 'clang'
self._environment[ 'CXX' ] = '/usr/bin/clang++' self._environment[ 'CXX' ] = 'clang++'
if self._devtoolset: if self._devtoolset:
self._environment[ 'BOOST_INCLUDEDIR' ] = '/opt/rh/devtoolset-%d/root/usr/include' % 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 self._environment[ 'BOOST_LIBRARYDIR' ] = '/opt/rh/devtoolset-%d/root/usr/lib' % self._devtoolset

View File

@ -208,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 ( "--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 ( "--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 ( "--macports" , action="store_true" , dest="macports" , help="Build against MacPorts." )
parser.add_option ( "--devtoolset" , action="store" , type="int" , dest="devtoolset" , help="Build against TUV Dev Toolset 8." ) 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 ( "--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 ( "--openmp" , action="store_true" , dest="openmp" , help="Enable the use of OpenMP in Gcc." )
parser.add_option ( "--ninja" , action="store_true" , dest="ninja" , help="Use Ninja instead of UNIX Makefile." ) parser.add_option ( "--ninja" , action="store_true" , dest="ninja" , help="Use Ninja instead of UNIX Makefile." )
@ -271,27 +272,28 @@ else:
builder.showConfiguration () builder.showConfiguration ()
sys.exit(0) sys.exit(0)
if options.quiet: builder.quiet = True if options.quiet: builder.quiet = True
if options.release: builder.buildMode = "Release" if options.release: builder.buildMode = "Release"
if options.debug: builder.buildMode = "Debug" if options.debug: builder.buildMode = "Debug"
if options.static: builder.enableShared = "OFF" if options.static: builder.enableShared = "OFF"
if options.doc: builder.enableDoc = "ON" if options.doc: builder.enableDoc = "ON"
if options.checkDb: builder.checkDatabase = "ON" if options.checkDb: builder.checkDatabase = "ON"
if options.checkDeterminism: builder.checkDeterminism = "ON" if options.checkDeterminism: builder.checkDeterminism = "ON"
if options.verboseMakefile: builder.verboseMakefile = "ON" if options.verboseMakefile: builder.verboseMakefile = "ON"
if options.rootDir: builder.rootDir = options.rootDir if options.rootDir: builder.rootDir = options.rootDir
if options.noBuild: builder.doBuild = False if options.noBuild: builder.doBuild = False
if options.noCache: builder.noCache = True if options.noCache: builder.noCache = True
if options.rmBuild: builder.rmBuild = True if options.rmBuild: builder.rmBuild = True
if options.ninja: builder.ninja = True if options.ninja: builder.ninja = True
if options.clang: builder.clang = True if options.clang or options.llvmtoolset: builder.clang = True
if options.macports: builder.macports = True if options.macports: builder.macports = True
if options.devtoolset: builder.devtoolset = options.devtoolset if options.devtoolset: builder.devtoolset = options.devtoolset
if options.qt5: builder.qt5 = True if options.llvmtoolset: builder.llvmtoolset = options.llvmtoolset
if options.openmp: builder.openmp = True if options.qt5: builder.qt5 = True
if options.makeArguments: builder.makeArguments = options.makeArguments if options.openmp: builder.openmp = True
#if options.svnMethod: builder.svnMethod = options.svnMethod if options.makeArguments: builder.makeArguments = options.makeArguments
#if options.svnTag: builder.svnTag = options.svnTag #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 ) #if options.svnStatus: builder.svnStatus ( tools=options.tools, projects=options.projects )
#elif options.svnUpdate: builder.svnUpdate ( 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 FindLibbfd.cmake
FindQwt.cmake FindQwt.cmake
FindSphinx.cmake FindSphinx.cmake
FindPelican.cmake
GetGitRevisionDescription.cmake GetGitRevisionDescription.cmake
GetGitRevisionDescription.cmake.in GetGitRevisionDescription.cmake.in
) )

View File

@ -39,6 +39,15 @@
message("-- Distribution is ${DISTRIBUTION}") message("-- Distribution is ${DISTRIBUTION}")
endmacro(check_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 # Get the svn revision version and configure a svn.h.in file based on this version
# The include directory name is passed as argument # The include directory name is passed as argument
@ -85,10 +94,14 @@
set(ADDTIONAL_FLAGS "") set(ADDTIONAL_FLAGS "")
set(CXX_STANDARD "c++11") set(CXX_STANDARD "c++11")
endif() endif()
set(CMAKE_C_FLAGS_DEBUG " -Wall ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug 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_RELEASE " -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C Compiler Release options." FORCE) #set(CMAKE_C_FLAGS_DEBUG " -Wall ${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_C_FLAGS_RELEASE " -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C Compiler Release 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_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)
# #
@ -175,18 +188,22 @@
endmacro(hurricane_check_libraries) endmacro(hurricane_check_libraries)
#
# Find Boost, checking different versions.
#
macro(setup_boost) macro(setup_boost)
#set(Boost_USE_STATIC_LIBS ON) #set(Boost_USE_STATIC_LIBS ON)
#message(STATUS "Always uses Boost static libraries.") #message(STATUS "Always uses Boost static libraries.")
if(ARGC LESS 1) if(ARGC LESS 1)
find_package(Boost 1.33.1 REQUIRED) find_package(Boost 1.35.0 REQUIRED)
else(ARGC LESS 1) 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) 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(NOT Boost_FOUND)
endif(ARGC LESS 1) endif(ARGC LESS 1)
message(STATUS "Found Boost includes ${Boost_LIB_VERSION} in ${Boost_INCLUDE_DIR}") message(STATUS "Found Boost includes ${Boost_LIB_VERSION} in ${Boost_INCLUDE_DIR}")
@ -261,15 +278,19 @@
/usr/include /usr/include
PATH_SUFFIXES qwt ) PATH_SUFFIXES qwt )
find_library(QWT_LIBRARY NAMES qwt-qt5 qwt find_library(QWT_LIBRARY NAMES qwt-qt5 qwt
PATHS /usr/lib${LIB_SUFFIX} ) PATHS /usr/lib64
/usr/lib )
else() else()
find_path(QWT_INCLUDE_DIR NAMES qwt.h find_path(QWT_INCLUDE_DIR NAMES qwt.h
PATHS /usr/include/qwt-qt4 PATHS /usr/include/qwt-qt4
/opt/local/libexec/qt4/include
/usr/include/qt4 /usr/include/qt4
/usr/include /usr/include
PATH_SUFFIXES qwt ) PATH_SUFFIXES qwt )
find_library(QWT_LIBRARY NAMES qwt-qt4 qwt find_library(QWT_LIBRARY NAMES qwt-qt4 qwt
PATHS /usr/lib${LIB_SUFFIX} ) PATHS /opt/local/libexec/qt4/lib
/usr/lib64
/usr/lib )
endif() endif()
if( QWT_INCLUDE_DIR AND QWT_LIBRARY) if( QWT_INCLUDE_DIR AND QWT_LIBRARY)
@ -398,5 +419,7 @@
target_link_libraries( ${pytarget} ${pyDeplibs} ) target_link_libraries( ${pytarget} ${pyDeplibs} )
install( TARGETS ${pytarget} DESTINATION ${PYTHON_SITE_PACKAGES} ) install( TARGETS ${pytarget} DESTINATION ${PYTHON_SITE_PACKAGES} )
if( NOT ("${pyIncludes}" STREQUAL "None") )
install( FILES ${pyIncludes} DESTINATION ${inc_install_dir} ) install( FILES ${pyIncludes} DESTINATION ${inc_install_dir} )
endif()
endmacro( add_python_module ) 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) MARK_AS_ADVANCED(FLEX_EXECUTABLE)
FIND_LIBRARY(FL_LIBRARY NAMES fl 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}) SET(FLEX_LIBRARIES ${FL_LIBRARY})
IF(FLEX_EXECUTABLE) IF(FLEX_EXECUTABLE)

View File

@ -92,7 +92,7 @@
find_path( LEFDEF_LIBRARY_DIR NAMES "libdef.so" find_path( LEFDEF_LIBRARY_DIR NAMES "libdef.so"
PATHS ${LEFDEF_SEARCH_PATH} PATHS ${LEFDEF_SEARCH_PATH}
PATH_SUFFIXES "lib${LIB_SUFFIX}" PATH_SUFFIXES "lib64" "lib"
DOC "The ${LEFDEF_LIBRARY_DIR_DESCRIPTION}" ) DOC "The ${LEFDEF_LIBRARY_DIR_DESCRIPTION}" )
message( STATUS "LEFDEF_LIBRARY_DIR: ${LEFDEF_LIBRARY_DIR}" ) message( STATUS "LEFDEF_LIBRARY_DIR: ${LEFDEF_LIBRARY_DIR}" )

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

@ -67,77 +67,41 @@ def guessOs ():
uname = subprocess.Popen ( ["uname", "-srm"], stdout=subprocess.PIPE ) uname = subprocess.Popen ( ["uname", "-srm"], stdout=subprocess.PIPE )
lines = uname.stdout.readlines() lines = uname.stdout.readlines()
libDir="lib" if osSlsoc7x_64.match(lines[0]): osType = "Linux.el7_64"
if osSlsoc7x_64.match(lines[0]):
osType = "Linux.el7_64"
libDir = "lib64"
elif osSlsoc6x_64.match(lines[0]): elif osSlsoc6x_64.match(lines[0]):
osType = "Linux.slsoc6x_64" osType = "Linux.slsoc6x_64"
libDir = "lib64"
useDevtoolset = True useDevtoolset = True
elif osSlsoc6x.match(lines[0]): elif osSlsoc6x.match(lines[0]):
osType = "Linux.slsoc6x" osType = "Linux.slsoc6x"
useDevtoolset = True useDevtoolset = True
elif osSLSoC5x_64.match(lines[0]): elif osSLSoC5x_64 .match(lines[0]): osType = "Linux.SLSoC5x_64"
osType = "Linux.SLSoC5x_64" elif osSLSoC5x .match(lines[0]): osType = "Linux.SLSoC5x"
libDir = "lib64" elif osFedora_64 .match(lines[0]): osType = "Linux.fc_64"
elif osSLSoC5x.match(lines[0]): elif osFedora .match(lines[0]): osType = "Linux.fc"
osType = "Linux.SLSoC5x" elif osUbuntu1004 .match(lines[0]): osType = "Linux.Ubuntu1004"
elif osFedora_64.match(lines[0]): elif osUbuntu1004_64 .match(lines[0]): osType = "Linux.Ubuntu1004_64"
osType = "Linux.fc_64" elif osLinux_64 .match(lines[0]): osType = "Linux.x86_64"
libDir = "lib64" elif osLinux .match(lines[0]): osType = "Linux.i386"
elif osFedora.match(lines[0]): elif osFreeBSD8x_64 .match(lines[0]): osType = "FreeBSD.8x.x86_64"
osType = "Linux.fc" elif osFreeBSD8x_amd64.match(lines[0]): osType = "FreeBSD.8x.amd64"
elif osUbuntu1004.match(lines[0]): elif osFreeBSD8x .match(lines[0]): osType = "FreeBSD.8x.i386"
osType = "Linux.Ubuntu1004" elif osDarwin .match(lines[0]): osType = "Darwin"
elif osUbuntu1004_64.match(lines[0]): elif osCygwinW7_64 .match(lines[0]): osType = "Cygwin.W7_64"
osType = "Linux.Ubuntu1004_64" elif osCygwinW7 .match(lines[0]): osType = "Cygwin.W7"
libDir = "lib64" elif osCygwinW8_64 .match(lines[0]): osType = "Cygwin.W8_64"
elif osLinux_64.match(lines[0]): elif osCygwinW8 .match(lines[0]): osType = "Cygwin.W8"
osType = "Linux.x86_64" elif osCygwinW10_64 .match(lines[0]): osType = "Cygwin.W10_64"
if(os.path.exists("/usr/lib64/")): elif osCygwinW10 .match(lines[0]): osType = "Cygwin.W10"
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"
else: else:
uname = subprocess.Popen ( ["uname", "-sr"], stdout=subprocess.PIPE ) uname = subprocess.Popen ( ["uname", "-sr"], stdout=subprocess.PIPE )
osType = uname.stdout.readlines()[0][:-1] osType = uname.stdout.readlines()[0][:-1]
print "[WARNING] Unrecognized OS: \"%s\"." % lines[0][:-1] print "[WARNING] Unrecognized OS: \"%s\"." % lines[0][:-1]
print " (using: \"%s\")" % osType print " (using: \"%s\")" % osType
ldLibraryPath = os.getenv('LD_LIBRARY_PATH') ldLibraryPath = os.getenv('LD_LIBRARY_PATH')
if ldLibraryPath and 'devtoolset' in ldLibraryPath: useDevtoolset = False if ldLibraryPath and 'devtoolset' in ldLibraryPath: useDevtoolset = False
if libDir == 'lib64' and not os.path.exists('/usr/lib64'): return (osType,useDevtoolset)
libDir = 'lib'
return (osType,libDir,useDevtoolset)
def guessShell (): def guessShell ():
@ -170,11 +134,11 @@ def guessShell ():
if __name__ == "__main__": if __name__ == "__main__":
osType,libDir,useDevtoolset = guessOs() osType,useDevtoolset = guessOs()
buildType = "Release" buildType = "Release"
linkType = "Shared" linkType = "Shared"
rootDir = None rootDir = None
shellBin, isBourneShell = guessShell() shellBin, isBourneShell = guessShell()
parser = optparse.OptionParser () parser = optparse.OptionParser ()
# Build relateds. # Build relateds.
@ -187,6 +151,7 @@ if __name__ == "__main__":
parser.add_option ( "--shared" , action="store_true" , dest="shared" ) parser.add_option ( "--shared" , action="store_true" , dest="shared" )
parser.add_option ( "--no-python" , action="store_true" , dest="nopython" ) parser.add_option ( "--no-python" , action="store_true" , dest="nopython" )
parser.add_option ( "--root" , action="store" , type="string", dest="rootDir" ) parser.add_option ( "--root" , action="store" , type="string", dest="rootDir" )
parser.add_option ( "--remove" , action="store_true" , dest="remove" )
( options, args ) = parser.parse_args () ( options, args ) = parser.parse_args ()
if options.release: buildType = "Release" if options.release: buildType = "Release"
@ -207,6 +172,32 @@ if __name__ == "__main__":
strippedLibraryPath = scrubPath( "LD_LIBRARY_PATH" ) strippedLibraryPath = scrubPath( "LD_LIBRARY_PATH" )
strippedPythonPath = scrubPath( "PYTHONPATH" ) 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 = \ shellScriptSh = \
'echo "%(MESSAGE)s";' \ 'echo "%(MESSAGE)s";' \
'echo "Switching to Coriolis 2.x (%(buildDir)s)";' \ 'echo "Switching to Coriolis 2.x (%(buildDir)s)";' \
@ -260,35 +251,44 @@ if __name__ == "__main__":
shellMessage = "Using user-selected Coriolis 2 (%s)" % rootDir shellMessage = "Using user-selected Coriolis 2 (%s)" % rootDir
if osType.startswith("Cygwin"): if osType.startswith("Cygwin"):
strippedPath = "%s/%s:%s" % ( coriolisTop, libDir, strippedPath ) strippedPath = "%s/lib:%s" % ( coriolisTop, libDir, strippedPath )
absLibDir = "%s/%s" % ( coriolisTop, libDir )
strippedPath = "%s/bin:%s" % ( coriolisTop, strippedPath )
strippedLibraryPath = "%s:%s" % ( absLibDir , strippedLibraryPath )
if not os.path.exists(coriolisTop): if not os.path.exists(coriolisTop):
print 'echo "[ERROR] coriolisEnv.py, top directory <%s> do not exists."' % coriolisTop print 'echo "[ERROR] coriolisEnv.py, top directory <%s> do not exists."' % coriolisTop
sys.exit( 1 ) 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: if not options.nopython:
pyVersion = sys.version_info pyVersion = sys.version_info
version = "%d.%d" % (pyVersion[0],pyVersion[1]) version = "%d.%d" % (pyVersion[0],pyVersion[1])
if osType.startswith("Linux.SL") \
or osType.startswith("Linux.sl") \ sitePackagesDir = "sitePackageDir_has_been_not_found"
or osType.startswith("Linux.el") \ for pyPackageDir in [ "%s/python%s/site-packages" % (absLibDir,version)
or osType.startswith("Linux.fc") \ , "%s/python%s/dist-packages" % (absLibDir,version)
or osType.startswith("Cygwin"): , "%s/%s/site-packages" % (absLibDir,version)
sitePackagesDir = "%s/python%s/site-packages" % (absLibDir,version) ]:
elif osType.startswith("Darwin"): if os.path.isdir(pyPackageDir):
sitePackagesDir = "%s/%s/site-packages" % (absLibDir,version) sitePackagesDir = pyPackageDir
else: break
sitePackagesDir = "%s/python%s/dist-packages" % (absLibDir,version)
strippedPythonPath = "%s:" % (sitePackagesDir) + strippedPythonPath strippedPythonPath = "%s:" % (sitePackagesDir) + strippedPythonPath
strippedPythonPath = "%s/crlcore:" % (sitePackagesDir) + strippedPythonPath strippedPythonPath = "%s/crlcore:" % (sitePackagesDir) + strippedPythonPath
strippedPythonPath = "%s/cumulus:" % (sitePackagesDir) + strippedPythonPath strippedPythonPath = "%s/cumulus:" % (sitePackagesDir) + strippedPythonPath
strippedPythonPath = "%s/cumulus/plugins:" % (sitePackagesDir) + strippedPythonPath strippedPythonPath = "%s/cumulus/plugins:" % (sitePackagesDir) + strippedPythonPath
strippedPythonPath = "%s/stratus:" % (sitePackagesDir) + strippedPythonPath strippedPythonPath = "%s/stratus:" % (sitePackagesDir) + strippedPythonPath
strippedPythonPath = "%s:" % (sysconfDir) + strippedPythonPath
shellScriptSh += 'PYTHONPATH="%(PYTHONPATH)s";' \ shellScriptSh += 'PYTHONPATH="%(PYTHONPATH)s";' \
'export PYTHONPATH;' 'export PYTHONPATH;'

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

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,631 @@
#!/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 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', '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._doCoriolis = False
self._doAlliance = 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._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.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-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.doCoriolis: conf.doCoriolis = True
if options.doAlliance: conf.doAlliance = 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.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.doCoriolis:
if conf.rmSource: gitCoriolis.removeLocalRepo()
gitCoriolis.clone ()
gitCoriolis.checkout( 'devel' )
if conf.doAlliance:
if conf.rmSource: gitAlliance.removeLocalRepo()
gitAlliance.clone ()
#gitAlliance.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 )

View File

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

View File

@ -0,0 +1,10 @@
FROM ubuntu18.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=Ubuntu18 --do-alliance --do-coriolis

View File

@ -0,0 +1,26 @@
FROM ubuntu:bionic
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 \
qtbase5-dev libqt5svg5-dev libqwt-qt5-dev \
python-pyqt5 \
\
autotools-dev automake \
libxt-dev libxpm-dev libmotif-dev \
\
yosys \
python3-setuptools python3-pip python3-six \
python3-wheel \
\
vim \
&& apt-get clean \
&& pip3 install git+https://github.com/m-labs/nmigen.git
# For building with Qt 4 instead of Qt 5.
# qt4-dev-tools libqwt-dev python-qt4 \

View File

@ -0,0 +1,4 @@
systemImage="ubuntu18.system"
coriolisImage="ubuntu18.coriolis"
bashImage="ubuntu18.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 )

133
bootstrap/dockerManager.sh Executable file
View File

@ -0,0 +1,133 @@
#!/bin/bash
showHelp=0
showError=0
doBuildSystem=0
doBuildCoriolis=0
doBuildBash=0
doBuild=0
doRun=0
doRemove=0
if [ ! -f "./docker-conf.sh" ]; then
echo "[ERROR] Missing \"./docker-conf.sh\"."
echo " (wd:\"`pwd`\")"
exit 1
fi
. "./docker-conf.sh"
dockerImages="${systemImage},${coriolisImage},${bashImage}"
while [ $# -gt 0 ]; do
case $1 in
--help) showHelp=1;;
--build-system) doBuildSystem=1;;
--build-coriolis) doBuildCoriolis=1;;
--build-bash) doBuildBash=1;;
--run) doRun=1;;
--remove) doRemove=1;;
-*) NB=2; CH=`echo $1 | cut -c$NB`
while [ "$CH" != "" ]; do
case $CH in
h) showHelp=1;;
s) doBuildSystem=1;;
c) doBuildCoriolis=1;;
b) doBuildBash=1;;
r) doRun=1;;
*) showError=1; badOption="$1";;
esac
NB=`expr $NB + 1`
CH=`echo $1 | cut -c$NB`
done;;
*) showError=1; badOption="$1";;
esac
shift
done
if [ ${showError} -ne 0 ]; then
echo "[ERROR] Unknown argument \"${badOption}\"."
exit 1
fi
if [ ${showHelp} -ne 0 ]; then
echo "Usage: ./manager.sh [options]"
echo "Options:"
echo " * [-h|--help]: Print this help."
echo " * [-s|--build-system]: Rebuild the whole OS image."
echo " * [-c|--build-coriolis]: Rebuild the Coriolis image. It will remove the previous"
echo " images (${dockerImages})."
echo " * [-b|--build-bash]: Rebuild the Bash (shell) image. It will remove the previous"
echo " image (${bashImage})."
echo " * [-r|--run]: Recompile Alliance, Coriolis & perform benchs."
echo " * [--remove]: Remove container(s) & image(s)."
exit 0
fi
if [ ${doBuildSystem} -ne 0 ]; then
doBuildBash=1
doBuildCoriolis=1
doBuild=1
doRemove=1
fi
if [ ${doBuildCoriolis} -ne 0 ]; then
doBuildBash=1
doBuild=1
doRemove=1
fi
if [ ${doBuildBash} -ne 0 ]; then
doBuild=1
doRemove=1
fi
if [ ${doRemove} -ne 0 ]; then
if [ ${doBuildBash} -ne 0 ]; then
echo "Removing \"${bashImage}\" docker container."
docker rm ${bashImage}
docker rmi ${bashImage}
fi
if [ ${doBuildCoriolis} -ne 0 ]; then
echo "Removing \"${coriolisImage}\" docker image."
docker rm ${coriolisImage}
docker rmi ${coriolisImage}
fi
if [ ${doBuildSystem} -ne 0 ]; then
echo "Removing \"${systemImage}\" docker image."
docker rm ${systemImage}
docker rmi ${systemImage}
fi
fi
if [ ${doBuild} -ne 0 ]; then
echo "Synching Alliance & Coriolis builder scripts."
cp ../../socInstaller.py ./root
cp ../../dot.bashrc ./root
if [ ${doBuildSystem} -ne 0 ]; then
echo "Build \"${systemImage}\" docker image."
docker build -f Dockerfile.system -t ${systemImage} .
fi
if [ ${doBuildCoriolis} -ne 0 ]; then
echo "Build \"${coriolisImage}\" docker image."
docker build -f Dockerfile.coriolis -t ${coriolisImage} .
fi
if [ ${doBuildBash} -ne 0 ]; then
echo "Build \"${bashImage}\" docker image."
docker build -f Dockerfile.bash -t ${bashImage} .
fi
fi
if [ ${doRun} -ne 0 ]; then
docker run --rm --net=host -e DISPLAY=:0 -ti --name ${bashImage} ${bashImage}
fi

14
bootstrap/dot.bashrc Normal file
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

31
bootstrap/resetDoc.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/bash
docDirs=""
docDirs="${docDirs} hurricane/doc/analog"
docDirs="${docDirs} hurricane/doc/hurricane"
docDirs="${docDirs} hurricane/doc/viewer"
docDirs="${docDirs} crlcore/doc/crlcore"
docDirs="${docDirs} katabatic/doc"
docDirs="${docDirs} kite/doc"
docDirs="${docDirs} oroshi/doc"
docDirs="${docDirs} unicorn/doc/unicorn"
docDirs="${docDirs} vlsisapd/doc"
docDirs="${docDirs} vlsisapd/doc"
resetDir ()
{
directory="$1"
echo "Resetting \"${directory} ..."
if [ -d "${directory}" ]; then
rm -rf "${directory}"
git checkout "${directory}"
fi
}
for docDir in ${docDirs}; do
resetDir "${docDir}/html"
resetDir "${docDir}/latex"
resetDir "${docDir}/man"
resetDir "${docDir}/rtf"
done
resetDir "documentation/output/pdfs"

View File

@ -46,31 +46,31 @@ except ImportError, e:
class ErrorMessage ( Exception ): class ErrorMessage ( Exception ):
def __init__ ( self, code, *arguments ): def __init__ ( self, code, *arguments ):
self._code = code self._code = code
self._errors = [ 'Malformed call to ErrorMessage()', '%s' % str(arguments) ] self._errors = [ 'Malformed call to ErrorMessage()', '%s' % str(arguments) ]
text = None text = None
if len(arguments) == 1: if len(arguments) == 1:
if isinstance(arguments[0],Exception): text = str(arguments[0]).split('\n') 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: else:
self._errors += [ line.lstrip() ] self._errors = arguments[0]
return 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 ): def __str__ ( self ):
if not isinstance(self._errors,list): if not isinstance(self._errors,list):
@ -104,321 +104,433 @@ class ErrorMessage ( Exception ):
class BadBinary ( ErrorMessage ): class BadBinary ( ErrorMessage ):
def __init__ ( self, binary ): def __init__ ( self, binary ):
ErrorMessage.__init__( self, 1, "Binary not found: <%s>." % binary ) ErrorMessage.__init__( self, 1, "Binary not found: <%s>." % binary )
return return
class BadReturnCode ( ErrorMessage ): class BadReturnCode ( ErrorMessage ):
def __init__ ( self, status ): def __init__ ( self, status ):
ErrorMessage.__init__( self, 1, "Command returned status:%d." % status ) ErrorMessage.__init__( self, 1, "Command returned status:%d." % status )
return return
class Command ( object ): class Command ( object ):
def __init__ ( self, arguments, fdLog=None ): def __init__ ( self, arguments, fdLog=None ):
self.arguments = arguments self.arguments = arguments
self.fdLog = fdLog self.fdLog = fdLog
if self.fdLog != None and not isinstance(self.fdLog,file): if self.fdLog != None and not isinstance(self.fdLog,file):
print '[WARNING] Command.__init__(): <fdLog> is neither None or a file.' print '[WARNING] Command.__init__(): <fdLog> is neither None or a file.'
return return
def _argumentsToStr ( self, arguments ): def _argumentsToStr ( self, arguments ):
s = '' s = ''
for argument in arguments: for argument in arguments:
if argument.find(' ') >= 0: s += ' "' + argument + '"' if argument.find(' ') >= 0: s += ' "' + argument + '"'
else: s += ' ' + argument else: s += ' ' + argument
return s return s
def log ( self, text ): def log ( self, text ):
print text[:-1] print text[:-1]
sys.stdout.flush() sys.stdout.flush()
sys.stderr.flush() sys.stderr.flush()
if isinstance(self.fdLog,file): if isinstance(self.fdLog,file):
self.fdLog.write( text ) self.fdLog.write( text )
self.fdLog.flush() self.fdLog.flush()
return return
def execute ( self ): def execute ( self ):
global conf global conf
sys.stdout.flush() sys.stdout.flush()
sys.stderr.flush() sys.stderr.flush()
homeDir = os.environ['HOME'] homeDir = os.environ['HOME']
workDir = os.getcwd() workDir = os.getcwd()
if homeDir.startswith(homeDir): if homeDir.startswith(homeDir):
workDir = '~' + workDir[ len(homeDir) : ] workDir = '~' + workDir[ len(homeDir) : ]
prompt = '%s@%s:%s$' % (os.environ['USER'],conf.masterHost,workDir) user = 'root'
if os.environ.has_key('USER'): user = os.environ['USER']
prompt = '%s@%s:%s$' % (user,conf.masterHost,workDir)
try: try:
self.log( '%s%s\n' % (prompt,self._argumentsToStr(self.arguments)) ) self.log( '%s%s\n' % (prompt,self._argumentsToStr(self.arguments)) )
child = subprocess.Popen( self.arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) print self.arguments
child = subprocess.Popen( self.arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
while True: while True:
line = child.stdout.readline() line = child.stdout.readline()
if not line: break if not line: break
self.log( line ) self.log( line )
except OSError, e: except OSError, e:
raise BadBinary( self.arguments[0] ) raise BadBinary( self.arguments[0] )
(pid,status) = os.waitpid( child.pid, 0 ) (pid,status) = os.waitpid( child.pid, 0 )
status >>= 8 status >>= 8
if status != 0: if status != 0:
raise BadReturnCode( status ) 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
return
class GitRepository ( object ): class GitRepository ( object ):
@staticmethod @staticmethod
def getLocalRepository ( url ): def getLocalRepository ( url ):
localRepo = url.split( '/' )[-1] localRepo = url.split( '/' )[-1]
if localRepo.endswith('.git'): if localRepo.endswith('.git'):
localRepo = localRepo[:-4] localRepo = localRepo[:-4]
return localRepo return localRepo
def __init__ ( self, url, cloneDir, fdLog=None ): def __init__ ( self, url, cloneDir, fdLog=None ):
self.url = url self.url = url
self.cloneDir = cloneDir self.cloneDir = cloneDir
self.localRepo = GitRepository.getLocalRepository( url ) self.localRepo = GitRepository.getLocalRepository( url )
self.fdLog = fdLog self.fdLog = fdLog
return return
@property @property
def localRepoDir ( self ): return self.cloneDir+'/'+self.localRepo def localRepoDir ( self ): return self.cloneDir+'/'+self.localRepo
def removeLocalRepo ( self ): def removeLocalRepo ( self ):
if os.path.isdir(self.localRepoDir): if os.path.isdir(self.localRepoDir):
print 'Removing Git local repository: <%s>' % self.localRepoDir print 'Removing Git local repository: <%s>' % self.localRepoDir
shutil.rmtree( self.localRepoDir ) shutil.rmtree( self.localRepoDir )
return return
def clone ( self ): def clone ( self ):
print 'Clone/pull from:', self.url print 'Clone/pull from:', self.url
if not os.path.isdir(self.cloneDir): if not os.path.isdir(self.cloneDir):
os.makedirs( self.cloneDir ) os.makedirs( self.cloneDir )
if not os.path.isdir(self.localRepoDir): if not os.path.isdir(self.localRepoDir):
os.chdir( self.cloneDir ) os.chdir( self.cloneDir )
Command( [ 'git', 'clone', self.url ], self.fdLog ).execute() Command( [ 'git', 'clone', self.url ], self.fdLog ).execute()
else: else:
os.chdir( self.localRepoDir ) os.chdir( self.localRepoDir )
Command( [ 'git', 'pull' ], self.fdLog ).execute() Command( [ 'git', 'pull' ], self.fdLog ).execute()
return return
def checkout ( self, branch ): def checkout ( self, branch ):
os.chdir( self.localRepoDir ) os.chdir( self.localRepoDir )
Command( [ 'git', 'checkout', branch ], self.fdLog ).execute() Command( [ 'git', 'checkout', branch ], self.fdLog ).execute()
return return
class Configuration ( object ): class Configuration ( object ):
PrimaryNames = \ PrimaryNames = \
[ 'sender' , 'receivers' [ 'sender' , 'receivers'
, 'coriolisRepo', 'benchsRepo', 'supportRepos' , 'coriolisRepo', 'benchsRepo' , 'supportRepos'
, 'homeDir' , 'masterHost' , 'homeDir' , 'masterHost'
, 'debugArg' , 'nightlyMode' , 'debugArg' , 'nightlyMode', 'dockerMode', 'chrootMode'
, 'rmSource' , 'rmBuild', 'doGit', 'doBuild', 'doBenchs', 'doSendReport' , 'rmSource' , 'rmBuild'
, 'doGit' , 'doAlliance' , 'doCoriolis', 'doBenchs', 'doSendReport'
, 'success' , 'rcode' , 'success' , 'rcode'
] ]
SecondaryNames = \ SecondaryNames = \
[ 'rootDir', 'srcDir', 'logDir', 'logs', 'fds' [ 'rootDir', 'srcDir', 'logDir', 'logs', 'fds', 'yosysBin', 'alcBin', 'ccbBin', 'benchsDir'
] ]
def __init__ ( self ): def __init__ ( self ):
self._sender = 'Jean-Paul.Chaput@soc.lip6.fr' self._sender = 'Jean-Paul.Chaput@soc.lip6.fr'
self._receivers = [ 'Jean-Paul.Chaput@lip6.fr', ] self._receivers = [ 'Jean-Paul.Chaput@lip6.fr', ]
self._supportRepos = [ 'http://github.com/miloyip/rapidjson' ] self._supportRepos = [ 'http://github.com/miloyip/rapidjson' ]
self._coriolisRepo = 'https://www-soc.lip6.fr/git/coriolis.git' self._allianceRepo = 'https://gitlab.lip6.fr/jpc/alliance.git'
self._benchsRepo = 'https://www-soc.lip6.fr/git/alliance-check-toolkit.git' self._coriolisRepo = 'https://gitlab.lip6.fr/jpc/coriolis.git'
self._homeDir = os.environ['HOME'] self._benchsRepo = 'https://gitlab.lip6.fr/jpc/alliance-check-toolkit.git'
self._debugArg = '' self._homeDir = os.environ['HOME']
self._rmSource = False self._debugArg = ''
self._rmBuild = False self._rmSource = False
self._doGit = True self._rmBuild = False
self._doBuild = True self._doGit = True
self._doBenchs = False self._doYosys = False
self._doSendReport = True self._doAlliance = False
self._nightlyMode = False self._doCoriolis = False
self._logs = { 'build':None, 'benchs':None } self._doBenchs = False
self._fds = { 'build':None, 'benchs':None } self._doSendReport = False
self._masterHost = self._detectMasterHost() self._nightlyMode = False
self._success = False self._dockerMode = False
self._rcode = 0 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() self._updateSecondaries()
return return
def __setattr__ ( self, attribute, value ): def __setattr__ ( self, attribute, value ):
if attribute in Configuration.SecondaryNames: if attribute in Configuration.SecondaryNames:
print ErrorMessage( 1, 'Attempt to write in read-only attribute <%s> in Configuration.'%attribute ) 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 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
self._targets = { 'SL6' :None
, 'SL6_64':None
, 'SL7_64':'lepka'
}
else:
self._targets = { 'SL6' :None
, 'SL6_64':None
, 'SL7_64':'bop'
}
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 ): def __getattr__ ( self, attribute ):
if attribute[0] != '_': attribute = '_'+attribute if attribute[0] != '_': attribute = '_'+attribute
if not self.__dict__.has_key(attribute): if not self.__dict__.has_key(attribute):
raise ErrorMessage( 1, 'Configuration has no attribute <%s>.'%attribute ) raise ErrorMessage( 1, 'Configuration has no attribute <%s>.'%attribute )
return self.__dict__[attribute] return self.__dict__[attribute]
def _updateSecondaries ( self ): def _updateSecondaries ( self ):
if self._nightlyMode: if self._nightlyMode:
self._targets['SL6'] = None self._rootDir = self._homeDir + '/nightly/coriolis-2.x'
self._rootDir = self._homeDir + '/nightly/coriolis-2.x' else:
else: self._rootDir = self._homeDir + '/coriolis-2.x'
if self._masterHost != 'lepka': self._srcDir = self._rootDir + '/src'
self._targets['SL6'] = None self._logDir = self._srcDir + '/logs'
self._rootDir = self._homeDir + '/coriolis-2.x' self._yosysBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/yosysInstaller.sh'
self._srcDir = self._rootDir + '/src' self._alcBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/allianceInstaller.sh'
self._logDir = self._srcDir + '/logs' self._ccbBin = self._srcDir + '/' + GitRepository.getLocalRepository(self._coriolisRepo) + '/bootstrap/ccb.py'
return self._benchsDir = self._srcDir + '/' + GitRepository.getLocalRepository(self._benchsRepo ) + '/benchs'
self._masterHost = self._detectMasterHost()
return
def _detectMasterHost ( self ): def _detectMasterHost ( self ):
masterHost = 'unknown' if self._chrootMode is None: return 'unknown'
hostname = socket.gethostname() if self._chrootMode: return 'chrooted-host'
hostAddr = socket.gethostbyname(hostname)
if hostname == 'lepka' and hostAddr == '127.0.0.1': masterHost = 'unknown'
masterHost = 'lepka' hostname = socket.gethostname()
else: hostAddr = socket.gethostbyname(hostname)
masterHost = hostname.split('.')[0]
return masterHost if hostname == 'lepka' and hostAddr == '127.0.0.1':
masterHost = 'lepka'
else:
masterHost = hostname.split('.')[0]
return masterHost
def openLog ( self, stem ): def openLog ( self, stem ):
if not os.path.isdir(self._logDir): if not os.path.isdir(self._logDir):
os.makedirs( self._logDir ) os.makedirs( self._logDir )
index = 0 index = 0
timeTag = time.strftime( "%Y.%m.%d" ) timeTag = time.strftime( "%Y.%m.%d" )
while True: while True:
logFile = os.path.join(self._logDir,"%s-%s-%02d.log" % (stem,timeTag,index)) logFile = os.path.join(self._logDir,"%s-%s-%02d.log" % (stem,timeTag,index))
if not os.path.isfile(logFile): if not os.path.isfile(logFile):
print "Report log: <%s>" % logFile print "Report log: <%s>" % logFile
break break
index += 1 index += 1
fd = open( logFile, "w" ) fd = open( logFile, "w" )
self._logs[stem] = logFile self._logs[stem] = logFile
self._fds [stem] = fd self._fds [stem] = fd
return return
def closeLogs ( self ): def closeLogs ( self ):
for fd in self._fds.values(): for fd in self._fds.values():
if fd: fd.close() if fd: fd.close()
return return
def compressLogs ( self ): def compressLogs ( self ):
for log in self._logs.values(): for log in self._logs.values():
if not log: continue if not log: continue
fd = open( log, 'r' ) fd = open( log, 'r' )
bzfd = bz2.BZ2File( log+'.bz2', 'w' ) bzfd = bz2.BZ2File( log+'.bz2', 'w' )
for line in fd.readlines(): bzfd.write( line ) for line in fd.readlines(): bzfd.write( line )
bzfd.close() bzfd.close()
fd.close() fd.close()
os.unlink( log ) os.unlink( log )
return 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 ): class Report ( object ):
def __init__ ( self, conf ): def __init__ ( self, conf ):
self.conf = conf self.conf = conf
commaspace = ', ' commaspace = ', '
date = time.strftime( "%A %d %B %Y" ) date = time.strftime( "%A %d %B %Y" )
stateText = 'FAILED' stateText = 'FAILED'
modeText = 'SoC installation' modeText = 'SoC installation'
if self.conf.success: stateText = 'SUCCESS' if self.conf.success: stateText = 'SUCCESS'
if self.conf.nightlyMode: modeText = 'Nightly build' if self.conf.nightlyMode: modeText = 'Nightly build'
self.message = MIMEMultipart() self.message = MIMEMultipart()
self.message['Subject'] = '[%s] Coriolis %s %s' % (stateText,modeText,date) self.message['Subject'] = '[%s] Coriolis %s %s' % (stateText,modeText,date)
self.message['From' ] = self.conf.sender self.message['From' ] = self.conf.sender
self.message['To' ] = commaspace.join( self.conf.receivers ) self.message['To' ] = commaspace.join( self.conf.receivers )
self.attachements = [] self.attachements = []
self.mainText = '\n' self.mainText = '\n'
self.mainText += 'Salut le Crevard,\n' self.mainText += 'Salut le Crevard,\n'
self.mainText += '\n' self.mainText += '\n'
if self.conf.nightlyMode: if self.conf.nightlyMode:
self.mainText += 'This is the nightly build report of Coriolis.\n' self.mainText += 'This is the nightly build report of Coriolis.\n'
else: else:
self.mainText += 'SoC installer report of Coriolis.\n' self.mainText += 'SoC installer report of Coriolis.\n'
self.mainText += '%s\n' % date self.mainText += '%s\n' % date
self.mainText += '\n' self.mainText += '\n'
if self.conf.success: if self.conf.success:
self.mainText += 'Build was SUCCESSFUL\n' self.mainText += 'Build was SUCCESSFUL\n'
else: else:
self.mainText += 'Build has FAILED, please have a look to the attached log file(s).\n' self.mainText += 'Build has FAILED, please have a look to the attached log file(s).\n'
self.mainText += '\n' self.mainText += '\n'
self.mainText += 'Complete log file(s) can be found here:\n' self.mainText += 'Complete log file(s) can be found here:\n'
return return
def attachLog ( self, logFile ): def attachLog ( self, logFile ):
if not logFile: return if not logFile: return
fd = open( logFile, 'rb' ) fd = open( logFile, 'rb' )
try: try:
fd.seek( -1024*100, os.SEEK_END ) fd.seek( -1024*100, os.SEEK_END )
except IOError, e: except IOError, e:
pass pass
tailLines = '' tailLines = ''
for line in fd.readlines()[1:]: for line in fd.readlines()[1:]:
tailLines += line tailLines += line
fd.close() fd.close()
self.mainText += ' <%s>\n' % logFile self.mainText += ' <%s>\n' % logFile
attachement = MIMEApplication(tailLines) attachement = MIMEApplication(tailLines)
attachement.add_header( 'Content-Disposition', 'attachment', filename=os.path.basename(logFile) ) attachement.add_header( 'Content-Disposition', 'attachment', filename=os.path.basename(logFile) )
self.attachements.append( attachement ) self.attachements.append( attachement )
return return
def send ( self ): def send ( self ):
self.message.attach( MIMEText(self.mainText) ) self.message.attach( MIMEText(self.mainText) )
for attachement in self.attachements: for attachement in self.attachements:
self.message.attach( attachement ) self.message.attach( attachement )
print "Sending mail report to:" print "Sending mail report to:"
for receiver in self.conf.receivers: print ' <%s>' % receiver for receiver in self.conf.receivers: print ' <%s>' % receiver
session = smtplib.SMTP( 'localhost' ) session = smtplib.SMTP( 'localhost' )
session.sendmail( self.conf.sender, self.conf.receivers, self.message.as_string() ) session.sendmail( self.conf.sender, self.conf.receivers, self.message.as_string() )
session.quit() session.quit()
return return
# ------------------------------------------------------------------- # -------------------------------------------------------------------
@ -428,105 +540,110 @@ class Report ( object ):
parser = optparse.OptionParser () parser = optparse.OptionParser ()
parser.add_option ( "--debug" , action="store_true" , dest="debug" , help="Build a <Debug> aka (-g) version." ) 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 ( "--no-git" , action="store_true" , dest="noGit" , help="Do not pull/update Git repositories before building." )
parser.add_option ( "--no-build" , action="store_true" , dest="noBuild" , help="Do not rebuild the tools, must have already be done." ) parser.add_option ( "--do-yosys" , action="store_true" , dest="doYosys" , help="Rebuild Yosys." )
parser.add_option ( "--no-report" , action="store_true" , dest="noReport" , help="Do not send a final report." ) 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 ( "--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 ( "--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-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-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 ( "--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 ( "--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 () (options, args) = parser.parse_args ()
conf = Configuration() conf = Configuration()
try: try:
if options.debug: conf.debugArg = '--debug' if options.debug: conf.debugArg = '--debug'
if options.nightly: conf.nightlyMode = True 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.noGit: conf.doGit = False
if options.noBuild: conf.doBuild = 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.benchs: conf.doBenchs = True
if options.noReport: conf.doSendReport = False if options.doReport: conf.doSendReport = True
if options.rmSource or options.rmAll: conf.rmSource = True if options.rmSource or options.rmAll: conf.rmSource = True
if options.rmBuild or options.rmAll: conf.rmBuild = True if options.rmBuild or options.rmAll: conf.rmBuild = True
if conf.doBuild: conf.openLog( 'build' )
if conf.doBenchs: conf.openLog( 'benchs' ) 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 = [] gitSupports = []
for supportRepo in conf.supportRepos: for supportRepo in conf.supportRepos:
gitSupports.append( GitRepository( supportRepo, conf.srcDir+'/support' ) ) gitSupports.append( GitRepository( supportRepo, conf.srcDir+'/support' ) )
gitCoriolis = GitRepository( conf.coriolisRepo, conf.srcDir, conf.fds['build'] ) gitCoriolis = GitRepository( conf.coriolisRepo, conf.srcDir, conf.fds['coriolis'] )
gitBenchs = GitRepository( conf.benchsRepo , conf.srcDir, conf.fds['build'] ) gitBenchs = GitRepository( conf.benchsRepo , conf.srcDir, conf.fds['coriolis'] )
if conf.doAlliance:
gitAlliance = GitRepository( conf.allianceRepo, conf.srcDir, conf.fds['alliance'] )
if conf.doGit: if conf.doGit:
for gitSupport in gitSupports: for gitSupport in gitSupports:
if conf.rmSource: gitSupport.removeLocalRepo() if conf.rmSource: gitSupport.removeLocalRepo()
gitSupport.clone() gitSupport.clone()
#if gitSupport.url.endswith('rapidjson'): if gitSupport.url.endswith('rapidjson'):
# gitSupport.checkout( 'a1c4f32' ) gitSupport.checkout( 'b1a4d91' )
if conf.rmSource: gitCoriolis.removeLocalRepo() if conf.doAlliance:
gitCoriolis.clone () if conf.rmSource: gitAlliance.removeLocalRepo()
gitCoriolis.checkout( 'devel' ) gitAlliance.clone ()
#gitAlliance.checkout( 'devel' )
if conf.rmSource: gitBenchs.removeLocalRepo() if conf.doCoriolis:
gitBenchs.clone() if conf.rmSource: gitCoriolis.removeLocalRepo()
gitCoriolis.clone ()
gitCoriolis.checkout( 'devel' )
if conf.rmSource: gitBenchs.removeLocalRepo()
gitBenchs.clone()
if conf.rmBuild: if conf.rmBuild:
for entry in os.listdir(conf.rootDir): for entry in os.listdir(conf.rootDir):
if entry.startswith('Linux.'): if entry.startswith('Linux.'):
buildDir = conf.rootDir+'/'+entry buildDir = conf.rootDir+'/'+entry
print 'Removing OS build directory: <%s>' % buildDir print 'Removing OS build directory: <%s>' % buildDir
shutil.rmtree( buildDir ) shutil.rmtree( buildDir )
ccbBin = gitCoriolis.localRepoDir+'/bootstrap/ccb.py' commands = conf.getCommands( options.profile )
if not os.path.isfile( ccbBin ): for command in commands:
raise ErrorMessage( 1, [ 'Cannot find <ccb.py>, should be here:' if command.host:
, ' <%s>' % ccbBin print 'Executing command on remote host <%s>:' % host
] ) else:
print 'Executing command on *local* host:'
buildCommand = '%s --root=%s --project=support --project=coriolis --make="-j%%d install" %%s' \ print ' %s' % str(command)
% (ccbBin,conf.rootDir) command.execute()
benchsCommand = 'cd %s/benchs && ../bin/go.sh' % (gitBenchs.localRepoDir)
commands = \
[ ( conf.targets['SL7_64'], buildCommand % (6,conf.debugArg) , conf.fds['build' ] )
, ( conf.targets['SL7_64'], buildCommand % (1,conf.debugArg+' --doc') , conf.fds['build' ] )
, ( conf.targets['SL7_64'], benchsCommand , conf.fds['benchs'] )
#, ( conf.targets['SL6_64'], buildCommand % (6,conf.debugArg+' --devtoolset=8') , conf.fds['build' ] )
#, ( conf.targets['SL6_64'], buildCommand % (1,conf.debugArg+' --devtoolset=8 --doc'), conf.fds['build' ] )
#, ( conf.targets['SL6_64'], benchsCommand , conf.fds['benchs'] )
#, ( conf.targets['SL6'] , buildCommand % (2,conf.debugArg+' --devtoolset=8') , conf.fds['build' ] )
#, ( conf.targets['SL6'] , buildCommand % (1,conf.debugArg+' --devtoolset=8 --doc'), conf.fds['build' ] )
#, ( conf.targets['SL6'] , benchsCommand , conf.fds['benchs'] )
]
for host,command,fd in commands:
if host and fd:
print 'Executing command on <%s>:' % host
print ' %s' % command
Command( [ 'ssh', host, command ], fd ).execute()
conf.closeLogs() conf.closeLogs()
conf.success = True conf.success = True
except ErrorMessage, e: except ErrorMessage, e:
print e print e
conf.closeLogs() conf.closeLogs()
conf.success = False conf.success = False
if showTrace: if showTrace:
print '\nPython stack trace:' print '\nPython stack trace:'
traceback.print_tb( sys.exc_info()[2] ) traceback.print_tb( sys.exc_info()[2] )
conf.rcode = e.code conf.rcode = e.code
if conf.doSendReport: if conf.doSendReport:
report = Report( conf ) report = Report( conf )
report.attachLog( conf.logs['build' ] ) report.attachLog( conf.logs['coriolis' ] )
report.attachLog( conf.logs['benchs'] ) report.attachLog( conf.logs['benchs' ] )
report.send() report.send()
conf.compressLogs() conf.compressLogs()

12
bootstrap/yosysInstaller.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
srcDir=${HOME}
gitHash="6edca05"
cd ${srcDir}
git clone https://github.com/cliffordwolf/yosys.git
cd yosys
git checkout ${gitHash}
make config-gcc
make GIT_REV=${gitHash} -j4
make GIT_REV=${gitHash} install

View File

@ -7,7 +7,7 @@
cmake_minimum_required(VERSION 2.8.9) cmake_minimum_required(VERSION 2.8.9)
set(ignoreVariables "${BUILD_DOC}") set(ignoreVariables "${BUILD_DOC} ${CMAKE_INSTALL_DIR}")
list(INSERT CMAKE_MODULE_PATH 0 "${DESTDIR}$ENV{CORIOLIS_TOP}/share/cmake/Modules/") list(INSERT CMAKE_MODULE_PATH 0 "${DESTDIR}$ENV{CORIOLIS_TOP}/share/cmake/Modules/")
find_package(Bootstrap REQUIRED) find_package(Bootstrap REQUIRED)
@ -31,5 +31,6 @@
find_package(Doxygen) find_package(Doxygen)
add_subdirectory(src) add_subdirectory(src)
add_subdirectory(python)
#add_subdirectory(cmake_modules) #add_subdirectory(cmake_modules)
#add_subdirectory(doc) #add_subdirectory(doc)

View File

@ -0,0 +1,2 @@
install ( FILES boraInit.py DESTINATION ${PYTHON_SITE_PACKAGES}/bora )

29
bora/python/boraInit.py Normal file
View File

@ -0,0 +1,29 @@
#!/usr/bin/env python
try:
import sys
import os.path
import helpers.io
from helpers.io import ErrorMessage
from helpers.io import WarningMessage
import Viewer
except Exception, e:
helpers.io.catch( e )
sys.exit( 1 )
def boraHook ( **kw ):
bora = None
if kw.has_key('bora'):
bora = kw['bora']
else:
print ErrorMessage( 3, 'boraHook(): Must be run from a BoraEngine.' )
return
try:
userInit = os.path.join( os.getcwd(), 'coriolis2/bora.py' )
if (os.path.exists(userInit)):
execfile( userInit )
except Exception, e:
helpers.io.catch( e )
return

View File

@ -14,6 +14,7 @@
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#include <Python.h>
#include <sstream> #include <sstream>
#include <QAction> #include <QAction>
#include <QMenu> #include <QMenu>
@ -30,6 +31,7 @@
#include "hurricane/Library.h" #include "hurricane/Library.h"
#include "hurricane/viewer/HApplication.h" #include "hurricane/viewer/HApplication.h"
#include "hurricane/viewer/ExceptionWidget.h" #include "hurricane/viewer/ExceptionWidget.h"
#include "hurricane/viewer/Script.h"
#include "hurricane/UpdateSession.h" #include "hurricane/UpdateSession.h"
#include "hurricane/analog/AnalogCellExtension.h" #include "hurricane/analog/AnalogCellExtension.h"
#include "hurricane/analog/LayoutGenerator.h" #include "hurricane/analog/LayoutGenerator.h"
@ -42,12 +44,16 @@
#include "bora/SlicingDataWidget.h" #include "bora/SlicingDataWidget.h"
#include "bora/AnalogDistance.h" #include "bora/AnalogDistance.h"
#include "bora/BoraEngine.h" #include "bora/BoraEngine.h"
#include "bora/PyBoraEngine.h"
namespace Bora { namespace Bora {
using namespace std; using namespace std;
using Hurricane::dbo_ptr;
using Hurricane::Error; using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::Breakpoint;
using Hurricane::DebugSession; using Hurricane::DebugSession;
using Hurricane::NetRoutingState; using Hurricane::NetRoutingState;
using Hurricane::NetRoutingExtension; using Hurricane::NetRoutingExtension;
@ -58,6 +64,7 @@ namespace Bora {
using Hurricane::UpdateSession; using Hurricane::UpdateSession;
using Analog::AnalogCellExtension; using Analog::AnalogCellExtension;
using Analog::Device; using Analog::Device;
using CRL::System;
using CRL::GdsDriver; using CRL::GdsDriver;
@ -87,6 +94,7 @@ namespace Bora {
void BoraEngine::_postCreate () void BoraEngine::_postCreate ()
{ {
Super::_postCreate(); Super::_postCreate();
_runBoraInit();
} }
@ -100,6 +108,27 @@ namespace Bora {
} }
void BoraEngine::_runBoraInit ()
{
Utilities::Path pythonSitePackages = System::getPath("pythonSitePackages");
Utilities::Path systemConfDir = pythonSitePackages / "bora";
Utilities::Path systemConfFile = systemConfDir / "boraInit.py";
if (systemConfFile.exists()) {
Isobar::Script::addPath( systemConfDir.toString() );
dbo_ptr<Isobar::Script> script = Isobar::Script::create( systemConfFile.stem().toString() );
script->addKwArgument( "bora" , (PyObject*)PyBoraEngine_Link(this) );
script->runFunction ( "boraHook", getCell() );
Isobar::Script::removePath( systemConfDir.toString() );
} else {
cerr << Warning( "Bora system configuration file:\n <%s> not found."
, systemConfFile.toString().c_str() ) << endl;
}
}
BoraEngine::~BoraEngine () BoraEngine::~BoraEngine ()
{ } { }
@ -220,7 +249,8 @@ namespace Bora {
Anabatic::Dijkstra* dijkstra = new Anabatic::Dijkstra( katana ); Anabatic::Dijkstra* dijkstra = new Anabatic::Dijkstra( katana );
AnalogDistance distance = AnalogDistance( cell, hpitch, vpitch ); AnalogDistance distance = AnalogDistance( cell, hpitch, vpitch );
dijkstra->setDistance( distance ); dijkstra->setDistance ( distance );
dijkstra->setSearchAreaHalo( std::max(hpitch,vpitch) );
for ( Net* net : cell->getNets() ) { for ( Net* net : cell->getNets() ) {
distance.setNet( net ); distance.setNet( net );

View File

@ -16,6 +16,8 @@
#include "hurricane/Error.h" #include "hurricane/Error.h"
#include "hurricane/Warning.h" #include "hurricane/Warning.h"
#include "hurricane/Cell.h"
#include "crlcore/RoutingGauge.h"
#include "bora/BoxSet.h" #include "bora/BoxSet.h"
@ -84,8 +86,18 @@ namespace Bora {
} }
size_t BoxSet::getIndex () const
{
cerr << Warning( "BoxSet::getIndex(): Only DBoxSet has parameter range indexes." ) << endl;
return 0;
}
void BoxSet::destroy() void BoxSet::destroy()
{ delete this; } {
if (_cpt < 2) delete this;
else --_cpt;
}
void BoxSet::setWidth ( DbU::Unit ) void BoxSet::setWidth ( DbU::Unit )
@ -96,6 +108,21 @@ namespace Bora {
{ cerr << Warning( "BoxSet::setWidth(): Must never be called." ) << endl; } { cerr << Warning( "BoxSet::setWidth(): Must never be called." ) << endl; }
string BoxSet::_getTypeName () const
{ return "BoxSet"; }
string BoxSet::_getString () const
{
string s = "<" + _getTypeName()
+ " refs:" + getString(_cpt)
+ " w:" + DbU::getValueString(getWidth ())
+ " h:" + DbU::getValueString(getHeight())
+ ">";
return s;
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Bora::HVBoxSet". // Class : "Bora::HVBoxSet".
@ -103,13 +130,17 @@ namespace Bora {
HVBoxSet::HVBoxSet ( const vector<BoxSet*>& dimensionSet, DbU::Unit height, DbU::Unit width ) HVBoxSet::HVBoxSet ( const vector<BoxSet*>& dimensionSet, DbU::Unit height, DbU::Unit width )
: BoxSet(height,width) : BoxSet(height,width)
,_dimensionSet(dimensionSet) ,_dimensionSet(dimensionSet)
{ } {
for ( BoxSet* bs : _dimensionSet ) bs->incrementCpt();
}
HVBoxSet::HVBoxSet ( HVBoxSet* boxSet ) HVBoxSet::HVBoxSet ( HVBoxSet* boxSet )
: BoxSet( boxSet ) : BoxSet( boxSet )
, _dimensionSet( boxSet->getSet() ) , _dimensionSet( boxSet->getSet() )
{ } {
for ( BoxSet* bs : _dimensionSet ) bs->incrementCpt();
}
HVBoxSet::~HVBoxSet () HVBoxSet::~HVBoxSet ()
@ -124,6 +155,10 @@ namespace Bora {
} }
string HVBoxSet::_getTypeName () const
{ return "HVBoxSet"; }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Bora::HBoxSet". // Class : "Bora::HBoxSet".
@ -190,6 +225,10 @@ namespace Bora {
} }
string HBoxSet::_getTypeName () const
{ return "HBoxSet"; }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Bora::VBoxSet". // Class : "Bora::VBoxSet".
@ -257,6 +296,10 @@ namespace Bora {
} }
string VBoxSet::_getTypeName () const
{ return "VBoxSet"; }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Bora::DBoxSet". // Class : "Bora::DBoxSet".
@ -265,9 +308,9 @@ namespace Bora {
int DBoxSet::_countAll = 0; int DBoxSet::_countAll = 0;
DBoxSet::DBoxSet ( DbU::Unit height, DbU::Unit width, int nfing ) DBoxSet::DBoxSet ( DbU::Unit height, DbU::Unit width, size_t index )
: BoxSet( height, width ) : BoxSet( height, width )
, _nfing(nfing) , _index(index)
{ {
++_count; ++_count;
++_countAll; ++_countAll;
@ -276,7 +319,7 @@ namespace Bora {
DBoxSet::DBoxSet ( DBoxSet* boxSet ) DBoxSet::DBoxSet ( DBoxSet* boxSet )
: BoxSet( boxSet ) : BoxSet( boxSet )
, _nfing( boxSet->getNFing() ) , _index( boxSet->getIndex() )
{ } { }
@ -286,15 +329,40 @@ namespace Bora {
} }
DBoxSet* DBoxSet::create ( DbU::Unit height, DbU::Unit width, int nfing ) DBoxSet* DBoxSet::create ( Cell* cell, int index, CRL::RoutingGauge* rg )
{ {
return new DBoxSet( height, width, nfing ); DbU::Unit abHeight = cell->getAbutmentBox().getHeight();
DbU::Unit abWidth = cell->getAbutmentBox().getWidth();
if (rg) {
DbU::Unit h2pitch = rg->getHorizontalPitch()*2;
DbU::Unit v2pitch = rg->getVerticalPitch ()*2;
if (abHeight % h2pitch) {
cerr << Warning( "DBoxSet::create(): The height of device \"%s\" (%s) is not pitched on 2*%s (adjusted)."
, getString(cell->getName()).c_str()
, DbU::getValueString(abHeight ).c_str()
, DbU::getValueString(h2pitch/2).c_str()
) << endl;
abHeight += h2pitch - (abHeight % h2pitch);
}
if (abWidth % v2pitch) {
cerr << Warning( "DBoxSet::create(): The width of device \"%s\" (%s) is not pitched on 2*%s (adjusted)."
, getString(cell->getName()).c_str()
, DbU::getValueString(abWidth ).c_str()
, DbU::getValueString(v2pitch/2).c_str()
) << endl;
abWidth += v2pitch - (abWidth % v2pitch);
}
}
return new DBoxSet( abHeight, abWidth, index );
} }
DBoxSet* DBoxSet::clone () DBoxSet* DBoxSet::clone ()
{ {
return DBoxSet::create( getHeight(), getWidth(), getNFing() ); return new DBoxSet( getHeight(), getWidth(), getNFing() );
} }
@ -304,6 +372,10 @@ namespace Bora {
} }
string DBoxSet::_getTypeName () const
{ return "DBoxSet"; }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Bora::RHVBoxSet". // Class : "Bora::RHVBoxSet".
@ -345,6 +417,10 @@ namespace Bora {
} }
string RHVBoxSet::_getTypeName () const
{ return "RHVBoxSet"; }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Bora::RHBoxSet". // Class : "Bora::RHBoxSet".
@ -378,6 +454,10 @@ namespace Bora {
} }
string RHBoxSet::_getTypeName () const
{ return "RHBoxSet"; }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Bora::RVBoxSet". // Class : "Bora::RVBoxSet".
@ -411,4 +491,8 @@ namespace Bora {
} }
string RVBoxSet::_getTypeName () const
{ return "RVBoxSet"; }
} // Bora namespace. } // Bora namespace.

View File

@ -10,6 +10,7 @@
${PYTHON_INCLUDE_PATH} ${PYTHON_INCLUDE_PATH}
) )
set( includes bora/Constants.h set( includes bora/Constants.h
bora/ParameterRange.h
bora/BoxSet.h bora/BoxSet.h
bora/NodeSets.h bora/NodeSets.h
bora/HVSetState.h bora/HVSetState.h
@ -27,7 +28,10 @@
bora/BoraEngine.h bora/BoraEngine.h
) )
set( pyIncludes bora/PySlicingNode.h set( pyIncludes bora/PyParameterRange.h
bora/PyStepParameterRange.h
bora/PyMatrixParameterRange.h
bora/PySlicingNode.h
bora/PyDSlicingNode.h bora/PyDSlicingNode.h
bora/PyHSlicingNode.h bora/PyHSlicingNode.h
bora/PyVSlicingNode.h bora/PyVSlicingNode.h
@ -44,6 +48,7 @@
) )
set( cpps BoxSet.cpp set( cpps BoxSet.cpp
NodeSets.cpp NodeSets.cpp
ParameterRange.cpp
HVSetState.cpp HVSetState.cpp
SlicingNode.cpp SlicingNode.cpp
HVSlicingNode.cpp HVSlicingNode.cpp
@ -62,7 +67,10 @@
SlicingWidget.cpp SlicingWidget.cpp
GraphicBoraEngine.cpp GraphicBoraEngine.cpp
) )
set( pyCpps PySlicingNode.cpp set( pyCpps PyParameterRange.cpp
PyStepParameterRange.cpp
PyMatrixParameterRange.cpp
PySlicingNode.cpp
PyDSlicingNode.cpp PyDSlicingNode.cpp
PyHSlicingNode.cpp PyHSlicingNode.cpp
PyRHSlicingNode.cpp PyRHSlicingNode.cpp
@ -94,7 +102,7 @@
${PYTHON_LIBRARIES} -lutil ${PYTHON_LIBRARIES} -lutil
) )
add_library( bora ${cpps} ${mocCpps} ) add_library( bora ${cpps} ${mocCpps} ${pyCpps} )
set_target_properties( bora PROPERTIES VERSION 1.0 SOVERSION 1 ) set_target_properties( bora PROPERTIES VERSION 1.0 SOVERSION 1 )
target_link_libraries( bora ${depLibs} ) target_link_libraries( bora ${depLibs} )

View File

@ -23,6 +23,7 @@
#include "hurricane/analog/CommonSourcePair.h" #include "hurricane/analog/CommonSourcePair.h"
#include "hurricane/analog/DifferentialPair.h" #include "hurricane/analog/DifferentialPair.h"
#include "hurricane/analog/LayoutGenerator.h" #include "hurricane/analog/LayoutGenerator.h"
#include "hurricane/analog/MultiCapacitor.h"
#include "anabatic/Session.h" #include "anabatic/Session.h"
#include "bora/DSlicingNode.h" #include "bora/DSlicingNode.h"
@ -35,10 +36,12 @@ namespace Bora {
using Hurricane::Transformation; using Hurricane::Transformation;
using Analog::Device; using Analog::Device;
using Analog::FormFactorParameter; using Analog::FormFactorParameter;
using Analog::MatrixParameter;
using Analog::TransistorFamily; using Analog::TransistorFamily;
using Analog::Transistor; using Analog::Transistor;
using Analog::CommonSourcePair; using Analog::CommonSourcePair;
using Analog::DifferentialPair; using Analog::DifferentialPair;
using Analog::MultiCapacitor;
using Analog::LayoutGenerator; using Analog::LayoutGenerator;
using Anabatic::Session; using Anabatic::Session;
@ -88,7 +91,7 @@ namespace Bora {
else if (isAlignTop ()) cerr << "Alignment : Top" << endl; else if (isAlignTop ()) cerr << "Alignment : Top" << endl;
else if (isAlignBottom()) cerr << "Alignment : Bottom" << endl; else if (isAlignBottom()) cerr << "Alignment : Bottom" << endl;
else cerr << "Alignment : Unknown" << endl; else cerr << "Alignment : Unknown" << endl;
cerr << "NFingers : " << getNFing() << endl; cerr << "BoxSetIndex : " << getBoxSetIndex() << endl;
if (_instance) cerr << "Instance : " << _instance << endl; if (_instance) cerr << "Instance : " << _instance << endl;
else cerr << "Instance : None" << endl; else cerr << "Instance : None" << endl;
SlicingNode::print(); SlicingNode::print();
@ -109,31 +112,19 @@ namespace Bora {
} }
void DSlicingNode::setNFing ( int nfing ) void DSlicingNode::setBoxSetIndex ( size_t index )
{ _boxSet = _nodeSets->find( nfing ); } { _boxSet = _nodeSets->find( index ); }
int DSlicingNode::getNFing () const size_t DSlicingNode::getBoxSetIndex () const
{ return (_boxSet) ? _boxSet->getNFing() : 1 ; } { return (_boxSet) ? _boxSet->getIndex() : 0 ; }
double DSlicingNode::getStartParameter () const
{ return _nodeSets->getStartParameter(); }
double DSlicingNode::getStepParameter () const
{ return _nodeSets->getStepParameter(); }
double DSlicingNode::getCountParameter () const
{ return _nodeSets->getCountParameter(); }
void DSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace ) void DSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )
{ {
cdebug_log(536,1) << "DSlicingNode::_place(DbU::Unit,DbU::Unit,bool replace)" << endl; cdebug_log(536,1) << "DSlicingNode::_place(DbU::Unit,DbU::Unit,bool replace)" << endl;
if (replace){ if (replace) {
SlicingNode::place( x, y ); SlicingNode::place( x, y );
if (_instance) { if (_instance) {
Cell* model = _instance->getMasterCell(); Cell* model = _instance->getMasterCell();
@ -150,16 +141,43 @@ namespace Bora {
Device* device = dynamic_cast<Device*>( model ); Device* device = dynamic_cast<Device*>( model );
if (device) { if (device) {
unique_ptr<LayoutGenerator> layoutGenerator ( new LayoutGenerator() );
TransistorFamily* tf = dynamic_cast<TransistorFamily*>( device ); TransistorFamily* tf = dynamic_cast<TransistorFamily*>( device );
if (tf) { if (tf) {
tf->setNfing( getNFing() ); StepParameterRange* stepRange = dynamic_cast<StepParameterRange*>( getNodeSets()->getRange() );
FormFactorParameter* pff = NULL; if (not stepRange) {
if ((pff = dynamic_cast<FormFactorParameter*>(tf->getParameter("M"))) != NULL) throw Error( "DSlicingNode::_place(): Device \"%s\" must be associated with a StepParameterRange argument instead of %s."
pff->setValue( tf->getNfing() ); , getString(device->getName()).c_str()
, getString(stepRange).c_str()
);
}
stepRange->setIndex( getBoxSet()->getIndex() );
int nfingers = stepRange->getValue();
shared_ptr<LayoutGenerator> layoutGenerator ( new LayoutGenerator() ); tf->setNfing( nfingers );
layoutGenerator->setDevice (device); layoutGenerator->setDevice ( device );
layoutGenerator->drawLayout(); layoutGenerator->drawLayout();
} else {
MultiCapacitor* mcapacitor = dynamic_cast<MultiCapacitor *>( device );
MatrixParameterRange* matrixRange = dynamic_cast<MatrixParameterRange*>( getNodeSets()->getRange() );
if (mcapacitor) {
if (not matrixRange) {
throw Error( "DSlicingNode::create(): Device \"%s\" must be associated with a MatrixParameterRange argument instead of %s."
, getString(mcapacitor->getName()).c_str()
, getString(matrixRange).c_str()
);
}
matrixRange->setIndex( getBoxSet()->getIndex() );
MatrixParameter* mp = NULL;
if ( (mp = dynamic_cast<MatrixParameter*>(mcapacitor->getParameter("Matrix"))) != NULL )
mp->setMatrix( &matrixRange->getValue() );
layoutGenerator->setDevice( mcapacitor );
layoutGenerator->drawLayout();
}
} }
} }
_instance->setTransformation ( Transformation( _x - model->getAbutmentBox().getXMin() _instance->setTransformation ( Transformation( _x - model->getAbutmentBox().getXMin()

View File

@ -189,7 +189,10 @@ namespace Bora {
{ {
cdebug_log(535,1) << "HSlicingNode::updateGlobalsize() - " << this << endl; cdebug_log(535,1) << "HSlicingNode::updateGlobalsize() - " << this << endl;
for ( SlicingNode* child : _children ) child->updateGlobalSize(); for ( SlicingNode* child : _children ) {
cdebug_log(535,0) << "child: " << child << endl;
child->updateGlobalSize();
}
if (not getMaster()) { if (not getMaster()) {
if (getNbChild() == 1) { if (getNbChild() == 1) {

View File

@ -153,8 +153,7 @@ namespace Bora {
// Notes: Set the next combination. See notes above. // Notes: Set the next combination. See notes above.
cdebug_log(535,0) << "HVSetState::next(): counter_:" << _counter << endl; cdebug_log(535,0) << "HVSetState::next(): counter_:" << _counter << endl;
Symmetry symmetry; Symmetry symmetry;
vector<size_t>::iterator itpair = _nextSet.begin();
const VSlicingNodes& children = _HVSnode->getChildren(); const VSlicingNodes& children = _HVSnode->getChildren();
for ( size_t ichild=0 ; ichild<children.size() ; ++ichild ) { for ( size_t ichild=0 ; ichild<children.size() ; ++ichild ) {

View File

@ -377,10 +377,14 @@ namespace Bora {
if (getType() == HorizontalSNode) symmetryType = HSymmetry; if (getType() == HorizontalSNode) symmetryType = HSymmetry;
if (getType() == VerticalSNode ) symmetryType = VSymmetry; if (getType() == VerticalSNode ) symmetryType = VSymmetry;
if (not getChild(childIndex)->isSymmetric(getChild(copyIndex), symmetryType, ShowDiff)) { if (not getChild(childIndex)->isSymmetric(getChild(copyIndex), symmetryType, ShowDiff)) {
cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Children %d and %d are not the same, symmetry is ignored." cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Children %d and %d are not the same, symmetry is ignored.\n"
, childIndex, copyIndex ) << endl; " child %d: %s\n"
" child %d: %s"
, childIndex, copyIndex
, childIndex, getString(getChild(childIndex)).c_str()
, copyIndex , getString(getChild( copyIndex)).c_str()
) << endl;
return; return;
} }
@ -699,7 +703,7 @@ namespace Bora {
} else { } else {
vector<BoxSet*>::const_iterator ibs = boxSet->getSet().begin(); vector<BoxSet*>::const_iterator ibs = boxSet->getSet().begin();
for ( VSlicingNodes::iterator ichild = _children.begin() for ( VSlicingNodes::iterator ichild = _children.begin()
; ichild != _children.end(); ichild++){ ; ichild != _children.end(); ichild++) {
(*ichild)->_setGlobalSize( *ibs ); (*ichild)->_setGlobalSize( *ibs );
ibs++; ibs++;
} }
@ -1128,6 +1132,9 @@ namespace Bora {
void HVSlicingNode::addSymmetryNet ( unsigned int type, Net* net1, Net* net2 ) void HVSlicingNode::addSymmetryNet ( unsigned int type, Net* net1, Net* net2 )
{ {
cerr << "HVSlicingNode::addSymmetryNet(): " << this << endl;
cerr << "* " << net1 << endl;
if (checkSymmetryNet(type,net1,net2)) { if (checkSymmetryNet(type,net1,net2)) {
cerr << Warning( "HVSlicingNode::addSymmetryNet(): Net symmetry already set." ) << endl; cerr << Warning( "HVSlicingNode::addSymmetryNet(): Net symmetry already set." ) << endl;
return; return;
@ -1201,6 +1208,13 @@ namespace Bora {
} }
for ( const NetSymmetry& symNet : _netSymmetries ) { for ( const NetSymmetry& symNet : _netSymmetries ) {
if (_symmetries.empty())
throw Error( "HVSlicingNode::updateSymNetAxis(): \n"
" Symmetry request for \"%s\" in non-symmetrical node \"%s\"."
, getString(get<1>(symNet)->getName()).c_str()
, getString(this).c_str()
);
SlicingNode* n1 = getChild( _symmetries.front().first ); SlicingNode* n1 = getChild( _symmetries.front().first );
SlicingNode* n2 = getChild( _symmetries.front().second ); SlicingNode* n2 = getChild( _symmetries.front().second );
DbU::Unit xCenter = (n1->getX() + n2->getX() + n2->getWidth())/2; DbU::Unit xCenter = (n1->getX() + n2->getX() + n2->getWidth())/2;
@ -1248,11 +1262,11 @@ namespace Bora {
} }
} }
} }
}
for ( SlicingNode* child : _children ) { for ( SlicingNode* child : _children ) {
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) ) if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) )
child->updateSymNetAxis(); child->updateSymNetAxis();
}
} }
} }

View File

@ -18,6 +18,8 @@
#include "hurricane/Warning.h" #include "hurricane/Warning.h"
#include "hurricane/analog/Device.h" #include "hurricane/analog/Device.h"
#include "hurricane/analog/TransistorFamily.h" #include "hurricane/analog/TransistorFamily.h"
#include "hurricane/analog/MultiCapacitor.h"
#include "hurricane/analog/Resistor.h"
#include "hurricane/analog/LayoutGenerator.h" #include "hurricane/analog/LayoutGenerator.h"
#include "crlcore/RoutingGauge.h" #include "crlcore/RoutingGauge.h"
@ -28,115 +30,120 @@ namespace Bora {
using namespace Analog; using namespace Analog;
NodeSets::NodeSets ( double start, double step, double count ) NodeSets::NodeSets ( ParameterRange* range )
: _boxSets() : _boxSets()
, _start ( start ) , _range (NULL)
, _step ( step ) {
, _count ( count ) if (range) {
{ } _range = range->clone();
_range->setNested();
}
}
NodeSets::NodeSets ( const NodeSets* other ) NodeSets::NodeSets ( const NodeSets* from )
: _boxSets( other->getBoxSets() ) : _boxSets( from->getBoxSets() )
, _start ( other->getStartParameter() ) , _range (NULL)
, _step ( other->getStepParameter() ) {
, _count ( other->getCountParameter() ) if (from->_range) {
{ } _range = from->_range->clone();
_range->setNested();
}
}
NodeSets::~NodeSets () NodeSets::~NodeSets ()
{ } {
if (_range) delete _range;
}
NodeSets* NodeSets::create ( Cell* cell NodeSets* NodeSets::create ( Cell* cell
, double start , ParameterRange* range
, double step
, double count
, CRL::RoutingGauge* rg ) , CRL::RoutingGauge* rg )
{ {
NodeSets* nodeset = new NodeSets( start, step, count ); NodeSets* nodeset = new NodeSets( range );
if (not cell) return nodeset; if (not cell) return nodeset;
Device* dev = dynamic_cast<Device*>( cell ); unique_ptr<LayoutGenerator> layoutGenerator ( new LayoutGenerator() );
if (dev) {
//cdebug_log(536,0) << "createNodeSets for an Analog Device" << endl;
TransistorFamily* tf = dynamic_cast<TransistorFamily*>(dev);
for ( int i = 0; i < count; ++i ) { TransistorFamily* device = dynamic_cast<TransistorFamily *>( cell );
tf->setNfing( start + i*step ); StepParameterRange* stepRange = dynamic_cast<StepParameterRange*>( nodeset->getRange() );
if (device) {
cdebug_log(535,0) << "NodeSets:create(): for a Transistor Analog Device" << endl;
FormFactorParameter* pff = NULL; if (not stepRange) {
if ( (pff = dynamic_cast<FormFactorParameter*>(tf->getParameter("M"))) != NULL ) throw Error( "NodeSets::create(): Device \"%s\" must be associated with a StepParameterRange argument instead of %s."
pff->setValue( tf->getNfing() ); , getString(device->getName()).c_str()
, getString(stepRange).c_str()
);
}
auto_ptr<LayoutGenerator> layoutGenerator ( new LayoutGenerator() ); stepRange->reset();
layoutGenerator->setDevice( dev ); do {
device->setNfing( stepRange->getValue() );
layoutGenerator->setDevice( device );
layoutGenerator->drawLayout(); layoutGenerator->drawLayout();
if (rg) { nodeset->push_back( DBoxSet::create( device, stepRange->getIndex(), rg ) );
float h2pitch = rg->getHorizontalPitch()*2;
float v2pitch = rg->getVerticalPitch ()*2;
float h = dev->getAbutmentBox().getHeight(); stepRange->progress();
float w = dev->getAbutmentBox().getWidth(); } while ( stepRange->isValid() );
if (fmod(h,h2pitch) > 1e-06) {
cerr << Warning( "NodeSets::create(): The height of device \"%s\" (%s) is not pitched on 2*%s (adjusted)."
, getString(dev->getName()).c_str()
, DbU::getValueString(dev->getAbutmentBox().getWidth()).c_str()
, DbU::getValueString(rg->getHorizontalPitch()*2).c_str()
) << endl;
}
if (fmod(w,v2pitch) > 1e-06) {
cerr << Warning( "NodeSets::create(): The width of device \"%s\" (%s) is not pitched on 2*%s (adjusted)."
, getString(dev->getName()).c_str()
, DbU::getValueString(dev->getAbutmentBox().getWidth()).c_str()
, DbU::getValueString(rg->getVerticalPitch()*2).c_str()
) << endl;
}
nodeset->push_back( DBoxSet::create( ceil(h/h2pitch)*h2pitch
, ceil(w/v2pitch)*v2pitch
, start + i*step
) );
} else {
nodeset->push_back( DBoxSet::create( dev->getAbutmentBox().getHeight()
, dev->getAbutmentBox().getWidth()
, start + i*step
) );
}
}
} else { } else {
//cdebug_log(536,0) << "createNodeSets for a Digital Device: " << cell << endl; MultiCapacitor* mcapacitor = dynamic_cast<MultiCapacitor *>( cell );
if (rg) { MatrixParameterRange* matrixRange = dynamic_cast<MatrixParameterRange*>( nodeset->getRange() );
DbU::Unit h2pitch = rg->getHorizontalPitch()*2;
DbU::Unit v2pitch = rg->getVerticalPitch ()*2;
DbU::Unit h = cell->getAbutmentBox().getHeight();
DbU::Unit w = cell->getAbutmentBox().getWidth();
if (h % h2pitch) { if (mcapacitor) {
cerr << Warning( "NodeSets::create(): The height of device \"%s\" (%s) is not pitched on %s*2 (adjusted)." cdebug_log(535,0) << "NodeSets::create(): for a Capacitor Analog Device" << endl;
, getString(cell->getName()).c_str()
, DbU::getValueString(cell->getAbutmentBox().getHeight()).c_str() if (not matrixRange) {
, DbU::getValueString(rg->getHorizontalPitch()).c_str() throw Error( "NodeSets::create(): Device \"%s\" must be associated with a MatrixParameterRange argument instead of %s."
) << endl; , getString(mcapacitor->getName()).c_str()
} , getString(stepRange).c_str()
if (w % v2pitch) { );
cerr << Warning( "NodeSets::create(): The width of device \"%s\" (%s) is not pitched on %s*2 (adjusted)."
, getString(cell->getName()).c_str()
, DbU::getValueString(cell->getAbutmentBox().getWidth()).c_str()
, DbU::getValueString(rg->getVerticalPitch()).c_str()
) << endl;
} }
nodeset->push_back( DBoxSet::create( ceil(h/h2pitch)*h2pitch matrixRange->reset();
, ceil(w/v2pitch)*v2pitch do {
) ); MatrixParameter* mp = NULL;
if ( (mp = dynamic_cast<MatrixParameter*>(mcapacitor->getParameter("matrix"))) != NULL )
mp->setMatrix( &matrixRange->getValue() );
layoutGenerator->setDevice( mcapacitor );
layoutGenerator->drawLayout();
nodeset->push_back( DBoxSet::create( mcapacitor, matrixRange->getIndex(), rg ) );
matrixRange->progress();
} while ( matrixRange->isValid() );
} else { } else {
nodeset->push_back( DBoxSet::create( cell->getAbutmentBox().getHeight() ResistorFamily* device = dynamic_cast<ResistorFamily *>( cell );
, cell->getAbutmentBox().getWidth() StepParameterRange* stepRange = dynamic_cast<StepParameterRange*>( nodeset->getRange() );
) ); if (device) {
cdebug_log(535,0) << "NodeSets::create(): for a Resistor Analog Device" << endl;
if (not stepRange) {
throw Error( "NodeSets::create(): Device \"%s\" must be associated with a StepParameterRange argument instead of %s."
, getString(device->getName()).c_str()
, getString(stepRange).c_str()
);
}
stepRange->reset();
do {
device->setBends( stepRange->getValue() );
layoutGenerator->setDevice( device );
layoutGenerator->drawLayout();
nodeset->push_back( DBoxSet::create( device, stepRange->getIndex(), rg ) );
stepRange->progress();
} while ( stepRange->isValid() );
} else {
nodeset->push_back( DBoxSet::create( cell, 0, rg ) );
}
} }
} }
@ -273,11 +280,11 @@ namespace Bora {
} }
BoxSet* NodeSets::find ( int nfing ) BoxSet* NodeSets::find ( size_t index )
{ {
size_t i = 0; size_t i = 0;
for ( ; i<_boxSets.size() ; ++i ) { for ( ; i<_boxSets.size() ; ++i ) {
if (_boxSets[i]->getNFing() == nfing) if (_boxSets[i]->getIndex() == index)
return _boxSets[i]; return _boxSets[i];
} }
@ -355,7 +362,7 @@ namespace Bora {
NodeSets* NodeSets::clone() NodeSets* NodeSets::clone()
{ {
NodeSets* nodesets = new NodeSets( _start, _step, _count ); NodeSets* nodesets = new NodeSets( _range );
for ( BoxSet* bs : _boxSets ) _boxSets.push_back( bs->clone() ); for ( BoxSet* bs : _boxSets ) _boxSets.push_back( bs->clone() );
return nodesets; return nodesets;
} }

158
bora/src/ParameterRange.cpp Normal file
View File

@ -0,0 +1,158 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2019, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | B o r a - A n a l o g S l i c i n g T r e e |
// | |
// | Author : Jean-Paul Chaput |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./arameterRange.cpp" |
// +-----------------------------------------------------------------+
#include "bora/ParameterRange.h"
namespace Bora {
using namespace std;
// -------------------------------------------------------------------
// Class : "ParameterRange"
ParameterRange::ParameterRange ()
: _flags(0), _index(0)
{ }
ParameterRange::~ParameterRange ()
{ }
string ParameterRange::_getString () const
{ return "<" + _getTypeName() + ">"; }
Record* ParameterRange::_getRecord () const
{
Record* record = new Record( getString(this) );
record->add( getSlot("_index", _index) );
return record;
}
// -------------------------------------------------------------------
// Class : "StepParameterRange"
StepParameterRange::StepParameterRange ( double start, double step, double count )
: Super()
, _start(start)
, _step (step )
, _count(count)
{ }
StepParameterRange::~StepParameterRange ()
{ }
StepParameterRange* StepParameterRange::clone () const
{
return new StepParameterRange( _start, _step, _count );
}
size_t StepParameterRange::getSize () const
{ return size_t(_count); }
double StepParameterRange::getValue () const
{ return _start + getIndex() * _step; }
string StepParameterRange::_getTypeName () const
{ return "StepParameterRange"; }
string StepParameterRange::_getString () const
{
string s = Super::_getString();
s.insert( s.length() - 1, " [" + getString(_start));
s.insert( s.length() - 1, " +" + getString(_step ));
s.insert( s.length() - 1, " ," + getString(_count) + "]");
return s;
}
Record* StepParameterRange::_getRecord () const
{
Record* record = Super::_getRecord();
if (record) {
record->add( getSlot("_start", _start) );
record->add( getSlot("_step" , _step ) );
record->add( getSlot("_count", _count) );
}
return record;
}
// -------------------------------------------------------------------
// Class : "MatrixParameterRange"
MatrixParameterRange::MatrixParameterRange ()
: Super()
, _matrixes()
{ }
MatrixParameterRange::~MatrixParameterRange ()
{ }
MatrixParameterRange* MatrixParameterRange::clone () const
{
MatrixParameterRange* param = new MatrixParameterRange();
param->copy( this );
return param;
}
size_t MatrixParameterRange::getSize () const
{ return _matrixes.size(); }
const Matrix& MatrixParameterRange::getValue () const
{ return _matrixes[ getIndex() ]; }
string MatrixParameterRange::_getTypeName () const
{ return "MatrixParameterRange"; }
string MatrixParameterRange::_getString () const
{
string s = Super::_getString();
s.insert( s.length() - 1, " [" + getString(getSize()) + "]");
return s;
}
Record* MatrixParameterRange::_getRecord () const
{
Record* record = Super::_getRecord();
if (record) {
record->add( getSlot("_matrixes", &_matrixes) );
}
return record;
}
} // Bora namespace.

View File

@ -16,6 +16,9 @@
#include "hurricane/isobar/PyHurricane.h" #include "hurricane/isobar/PyHurricane.h"
#include "hurricane/isobar/PyCell.h" #include "hurricane/isobar/PyCell.h"
#include "bora/PyParameterRange.h"
#include "bora/PyStepParameterRange.h"
#include "bora/PyMatrixParameterRange.h"
#include "bora/PySlicingNode.h" #include "bora/PySlicingNode.h"
#include "bora/PyHSlicingNode.h" #include "bora/PyHSlicingNode.h"
#include "bora/PyVSlicingNode.h" #include "bora/PyVSlicingNode.h"
@ -31,6 +34,7 @@ namespace Bora {
using std::cerr; using std::cerr;
using std::endl; using std::endl;
using Hurricane::tab; using Hurricane::tab;
using Isobar::getPyHash;
using Isobar::__cs; using Isobar::__cs;
using CRL::PyTypeToolEngine; using CRL::PyTypeToolEngine;
using CRL::PyTypeGraphicTool; using CRL::PyTypeGraphicTool;
@ -66,6 +70,9 @@ extern "C" {
{ {
cdebug.log(61) << "initBora()" << endl; cdebug.log(61) << "initBora()" << endl;
PyParameterRange_LinkPyType();
PyStepParameterRange_LinkPyType();
PyMatrixParameterRange_LinkPyType();
PySlicingNode_LinkPyType(); PySlicingNode_LinkPyType();
PyHSlicingNode_LinkPyType(); PyHSlicingNode_LinkPyType();
PyVSlicingNode_LinkPyType(); PyVSlicingNode_LinkPyType();
@ -75,15 +82,18 @@ extern "C" {
PyBoraEngine_LinkPyType(); PyBoraEngine_LinkPyType();
PyGraphicBoraEngine_LinkPyType(); PyGraphicBoraEngine_LinkPyType();
PYTYPE_READY( ParameterRange )
PYTYPE_READY( SlicingNode ) PYTYPE_READY( SlicingNode )
PYTYPE_READY_SUB( HSlicingNode , SlicingNode ) PYTYPE_READY_SUB( StepParameterRange , ParameterRange );
PYTYPE_READY_SUB( VSlicingNode , SlicingNode ) PYTYPE_READY_SUB( MatrixParameterRange, ParameterRange );
PYTYPE_READY_SUB( DSlicingNode , SlicingNode ) PYTYPE_READY_SUB( HSlicingNode , SlicingNode );
PYTYPE_READY_SUB( RHSlicingNode , SlicingNode ) PYTYPE_READY_SUB( VSlicingNode , SlicingNode );
PYTYPE_READY_SUB( RVSlicingNode , SlicingNode ) PYTYPE_READY_SUB( DSlicingNode , SlicingNode );
PYTYPE_READY_SUB( BoraEngine , ToolEngine ); PYTYPE_READY_SUB( RHSlicingNode , SlicingNode );
PYTYPE_READY_SUB( GraphicBoraEngine, GraphicTool ); PYTYPE_READY_SUB( RVSlicingNode , SlicingNode );
PYTYPE_READY_SUB( BoraEngine , ToolEngine );
PYTYPE_READY_SUB( GraphicBoraEngine , GraphicTool );
PyObject* module = Py_InitModule( "Bora", PyBora_Methods ); PyObject* module = Py_InitModule( "Bora", PyBora_Methods );
@ -93,22 +103,28 @@ extern "C" {
return; return;
} }
Py_INCREF( &PyTypeParameterRange );
PyModule_AddObject( module, "ParameterRange" , (PyObject*)&PyTypeParameterRange );
Py_INCREF( &PyTypeStepParameterRange );
PyModule_AddObject( module, "StepParameterRange" , (PyObject*)&PyTypeStepParameterRange );
Py_INCREF( &PyTypeMatrixParameterRange );
PyModule_AddObject( module, "MatrixParameterRange", (PyObject*)&PyTypeMatrixParameterRange );
Py_INCREF( &PyTypeSlicingNode ); Py_INCREF( &PyTypeSlicingNode );
PyModule_AddObject( module, "SlicingNode" , (PyObject*)&PyTypeSlicingNode ); PyModule_AddObject( module, "SlicingNode" , (PyObject*)&PyTypeSlicingNode );
Py_INCREF( &PyTypeHSlicingNode ); Py_INCREF( &PyTypeHSlicingNode );
PyModule_AddObject( module, "HSlicingNode" , (PyObject*)&PyTypeHSlicingNode ); PyModule_AddObject( module, "HSlicingNode" , (PyObject*)&PyTypeHSlicingNode );
Py_INCREF( &PyTypeVSlicingNode ); Py_INCREF( &PyTypeVSlicingNode );
PyModule_AddObject( module, "VSlicingNode" , (PyObject*)&PyTypeVSlicingNode ); PyModule_AddObject( module, "VSlicingNode" , (PyObject*)&PyTypeVSlicingNode );
Py_INCREF( &PyTypeDSlicingNode ); Py_INCREF( &PyTypeDSlicingNode );
PyModule_AddObject( module, "DSlicingNode" , (PyObject*)&PyTypeDSlicingNode ); PyModule_AddObject( module, "DSlicingNode" , (PyObject*)&PyTypeDSlicingNode );
Py_INCREF( &PyTypeRHSlicingNode ); Py_INCREF( &PyTypeRHSlicingNode );
PyModule_AddObject( module, "RHSlicingNode" , (PyObject*)&PyTypeRHSlicingNode ); PyModule_AddObject( module, "RHSlicingNode" , (PyObject*)&PyTypeRHSlicingNode );
Py_INCREF( &PyTypeRVSlicingNode ); Py_INCREF( &PyTypeRVSlicingNode );
PyModule_AddObject( module, "RVSlicingNode" , (PyObject*)&PyTypeRVSlicingNode ); PyModule_AddObject( module, "RVSlicingNode" , (PyObject*)&PyTypeRVSlicingNode );
Py_INCREF( &PyTypeBoraEngine ); Py_INCREF( &PyTypeBoraEngine );
PyModule_AddObject( module, "BoraEngine" , (PyObject*)&PyTypeBoraEngine ); PyModule_AddObject( module, "BoraEngine" , (PyObject*)&PyTypeBoraEngine );
Py_INCREF( &PyTypeGraphicBoraEngine ); Py_INCREF( &PyTypeGraphicBoraEngine );
PyModule_AddObject( module, "GraphicBoraEngine", (PyObject*)&PyTypeGraphicBoraEngine ); PyModule_AddObject( module, "GraphicBoraEngine" , (PyObject*)&PyTypeGraphicBoraEngine );
PySlicingNode_postModuleInit(); PySlicingNode_postModuleInit();
PyBoraEngine_postModuleInit(); PyBoraEngine_postModuleInit();

View File

@ -39,6 +39,7 @@ namespace Bora {
using Isobar::ConstructorError; using Isobar::ConstructorError;
using Isobar::HurricaneError; using Isobar::HurricaneError;
using Isobar::HurricaneWarning; using Isobar::HurricaneWarning;
using Isobar::getPyHash;
using Isobar::ParseOneArg; using Isobar::ParseOneArg;
using Isobar::ParseTwoArg; using Isobar::ParseTwoArg;
using Isobar::PyCell; using Isobar::PyCell;
@ -103,8 +104,6 @@ extern "C" {
static PyObject* PyBoraEngine_updatePlacement ( PyBoraEngine* self, PyObject* args ) static PyObject* PyBoraEngine_updatePlacement ( PyBoraEngine* self, PyObject* args )
{ {
unsigned int bsIndex = 0;
METHOD_HEAD( "BoraEngine.updatePlacement()" ) METHOD_HEAD( "BoraEngine.updatePlacement()" )
HTRY HTRY
PyObject* arg0; PyObject* arg0;

View File

@ -17,6 +17,8 @@
#include "hurricane/analog/PyDevice.h" #include "hurricane/analog/PyDevice.h"
#include "crlcore/PyRoutingGauge.h" #include "crlcore/PyRoutingGauge.h"
#include "bora/PyDSlicingNode.h" #include "bora/PyDSlicingNode.h"
#include "bora/PyStepParameterRange.h"
#include "bora/PyMatrixParameterRange.h"
namespace Bora { namespace Bora {
@ -53,40 +55,50 @@ extern "C" {
static PyObject* PyDSlicingNode_create ( PyObject* , PyObject* args ) static PyObject* PyDSlicingNode_create ( PyObject* , PyObject* args )
{ {
PyObject* pyInstance = NULL; PyObject* pyInstance = NULL;
PyObject* pyCell = NULL; PyObject* pyCell = NULL;
PyObject* pyRoutingGauge = NULL; PyObject* pyRoutingGauge = NULL;
double start = 0.0; PyObject* pyParameterRange = NULL;
double step = 0.0; DSlicingNode* node = NULL;
double count = 0.0;
DSlicingNode* node = NULL;
HTRY HTRY
if (not PyArg_ParseTuple( args,"SOddd|O:DSlicingNode.create" if (not PyArg_ParseTuple( args,"SOO|O:DSlicingNode.create"
, &pyInstance , &pyInstance
, &pyCell , &pyCell
, &start , &pyParameterRange
, &step
, &count
, &pyRoutingGauge ) ) { , &pyRoutingGauge ) ) {
PyErr_SetString ( ConstructorError, "DSlicingNode.create(): Invalid/bad number of parameters ." ); PyErr_SetString ( ConstructorError, "DSlicingNode.create(): Invalid/bad number of parameters ." );
return NULL; return NULL;
} }
if (not IsPyCell(pyCell)) { if (not IsPyCell(pyCell)) {
PyErr_SetString( ConstructorError, "DSlicingNode.create(): First argument *must* be of type Cell." ); PyErr_SetString( ConstructorError, "DSlicingNode.create(): Second argument *must* be of type Cell." );
return NULL;
}
if ( (pyParameterRange != Py_None)
and not IsPyStepParameterRange(pyParameterRange)
and not IsPyMatrixParameterRange(pyParameterRange)) {
PyErr_SetString( ConstructorError, "DSlicingNode.create(): Third argument *must* be of type StepParameterRange or MatrixParameterRange." );
return NULL; return NULL;
} }
if (pyRoutingGauge and not IsPyRoutingGauge(pyRoutingGauge)) { if (pyRoutingGauge and not IsPyRoutingGauge(pyRoutingGauge)) {
PyErr_SetString( ConstructorError, "DSlicingNode.create(): Fifth argument *must* be of type RoutingGauge." ); PyErr_SetString( ConstructorError, "DSlicingNode.create(): Fourth argument *must* be of type RoutingGauge." );
return NULL; return NULL;
} }
Cell* cell = PYCELL_O( pyCell ); Cell* cell = PYCELL_O( pyCell );
Instance* instance = cell->getInstance( PyString_AsString(pyInstance) ); Instance* instance = cell->getInstance( PyString_AsString(pyInstance) );
//Device* device = dynamic_cast<Device*>( instance->getMasterCell() ); if (not instance) {
RoutingGauge* rg = (pyRoutingGauge) ? PYROUTINGGAUGE_O(pyRoutingGauge) : NULL; ostringstream message;
message << "DSlicingNode.create(): Cell \"" << cell->getName()
<< "\" has no instance named \"" << PyString_AsString(pyInstance) << "\".";
PyErr_SetString( ConstructorError, message.str().c_str() );
return NULL;
}
node = DSlicingNode::create( NodeSets::create( instance->getMasterCell(), start, step, count, rg ) ParameterRange* range = ParameterRangeCast( pyParameterRange );
RoutingGauge* rg = (pyRoutingGauge) ? PYROUTINGGAUGE_O(pyRoutingGauge) : NULL;
node = DSlicingNode::create( NodeSets::create( instance->getMasterCell(), range, rg )
, UnknownAlignment , UnknownAlignment
, instance ); , instance );
HCATCH HCATCH
@ -95,8 +107,8 @@ extern "C" {
} }
DirectGetIntAttribute(PyDSlicingNode_getNFing,getNFing,PyDSlicingNode,DSlicingNode) DirectGetIntAttribute(PyDSlicingNode_getBoxSetIndex,getBoxSetIndex,PyDSlicingNode,DSlicingNode)
DirectSetIntAttribute(PyDSlicingNode_setNFing,setNFing,PyDSlicingNode,DSlicingNode) DirectSetIntAttribute(PyDSlicingNode_setBoxSetIndex,setBoxSetIndex,PyDSlicingNode,DSlicingNode)
// Standart Destroy (Attribute). // Standart Destroy (Attribute).
@ -104,10 +116,10 @@ extern "C" {
// PyDSlicingNode Attribute Method table. // PyDSlicingNode Attribute Method table.
PyMethodDef PyDSlicingNode_Methods[] = PyMethodDef PyDSlicingNode_Methods[] =
{ { "create" , (PyCFunction)PyDSlicingNode_create , METH_VARARGS|METH_STATIC { { "create" , (PyCFunction)PyDSlicingNode_create , METH_VARARGS|METH_STATIC
, "Create a new DSlicingNode." } , "Create a new DSlicingNode." }
, { "getNFing" , (PyCFunction)PyDSlicingNode_getNFing , METH_NOARGS , "To be documented." } , { "getBoxSetIndex" , (PyCFunction)PyDSlicingNode_getBoxSetIndex, METH_NOARGS , "To be documented." }
, { "setNFing" , (PyCFunction)PyDSlicingNode_setNFing , METH_VARARGS, "To be documented." } , { "setBoxSetIndex" , (PyCFunction)PyDSlicingNode_setBoxSetIndex, METH_VARARGS, "To be documented." }
, { NULL, NULL, 0, NULL } /* sentinel */ , { NULL, NULL, 0, NULL } /* sentinel */
}; };

View File

@ -0,0 +1,146 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2019-2019, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | B o r a - A n a l o g S l i c i n g T r e e |
// | |
// | Author : Jean-Paul Chaput |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./bora/PyMatrixParameterRange.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/analog/PyMatrix.h"
#include "bora/PyMatrixParameterRange.h"
namespace Bora {
using namespace Hurricane;
using namespace Isobar;
extern "C" {
#undef ACCESS_OBJECT
#undef ACCESS_CLASS
#define ACCESS_OBJECT _baseObject._object
#define ACCESS_CLASS(_pyObject) &(_pyObject->_baseObject)
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(MatrixParameterRange,range,function)
// +=================================================================+
// | "PyMatrixParameterRange" Python Module Code Part |
// +=================================================================+
#if defined(__PYTHON_MODULE__)
static PyObject* PyMatrixParameterRange_NEW ( PyObject* , PyObject* args )
{
MatrixParameterRange* range = NULL;
HTRY
range = new MatrixParameterRange();
HCATCH
return PyMatrixParameterRange_Link(range);
}
static int PyMatrixParameterRange_Init ( PyMatrixParameterRange* self, PyObject* args, PyObject* kwargs )
{
cdebug_log(20,0) << "PyMatrixParameterRange_Init(): " << (void*)self << endl;
return 0;
}
static PyObject* PyMatrixParameterRange_addValue ( PyMatrixParameterRange* self, PyObject* args )
{
PyObject* pyMatrix = NULL;
METHOD_HEAD( "MatrixParameterRange.addValue()" );
HTRY
if (not PyArg_ParseTuple( args,"O:MatrixParameterRange.addValue", &pyMatrix ) ) {
PyErr_SetString ( ConstructorError, "MatrixParameterRange.addValue(): Invalid/bad number of parameters ." );
return NULL;
}
if (not IsPyMatrix(pyMatrix)) {
if (not PyList_Check(pyMatrix)) {
PyErr_SetString( ConstructorError, "MatrixParameterRange.addValue(): Argument is neither of type Matrix not list of list." );
return NULL;
}
Matrix m = Matrix_FromListOfList( pyMatrix );
if (m.empty()) return NULL;
range->addValue( &m );
} else {
range->addValue( PYMATRIX_O(pyMatrix) );
}
HCATCH
Py_RETURN_NONE;
}
static PyObject* PyMatrixParameterRange_getValue ( PyMatrixParameterRange* self, PyObject* args )
{
PyMatrix* pyMatrix = NULL;
METHOD_HEAD( "MatrixParameterRange.getValue()" );
HTRY
pyMatrix = PyObject_NEW( PyMatrix, &PyTypeMatrix );
if (pyMatrix == NULL) { return NULL; }
pyMatrix->_object = new Matrix( range->getValue() );
HCATCH
return (PyObject*)pyMatrix;
}
DirectDeleteMethod(PyMatrixParameterRange_DeAlloc,PyMatrixParameterRange)
// ---------------------------------------------------------------
// PyMatrixParameterRange Attribute Method table.
PyMethodDef PyMatrixParameterRange_Methods[] =
{ { "getValue" , (PyCFunction)PyMatrixParameterRange_getValue , METH_NOARGS , "To be documented." }
, { "addValue" , (PyCFunction)PyMatrixParameterRange_addValue , METH_VARARGS, "To be documented." }
, { NULL, NULL, 0, NULL } /* sentinel */
};
// +-------------------------------------------------------------+
// | "PyMatrixParameterRange" Object Methods |
// +-------------------------------------------------------------+
PyTypeObjectLinkPyTypeNewInit(MatrixParameterRange)
#else // End of Python Module Code Part.
// +=================================================================+
// | "PyMatrixParameterRange" Shared Library Code Part |
// +=================================================================+
extern LinkCreateMethod(MatrixParameterRange);
PyTypeInheritedObjectDefinitions(MatrixParameterRange, ParameterRange)
#endif // End of Shared Library Code Part.
} // extern "C".
} // Bora namespace.

View File

@ -0,0 +1,125 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | B o r a - A n a l o g S l i c i n g T r e e |
// | |
// | Author : Jean-Paul Chaput |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./bora/PyParameterRange.cpp" |
// +-----------------------------------------------------------------+
#include "bora/PyParameterRange.h"
#include "bora/PyStepParameterRange.h"
#include "bora/PyMatrixParameterRange.h"
namespace Bora {
using namespace Hurricane;
using namespace Isobar;
extern "C" {
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(ParameterRange,range,function)
// +=================================================================+
// | "PyParameterRange" Python Module Code Part |
// +=================================================================+
#if defined(__PYTHON_MODULE__)
// Standart destroy (Attribute).
//DBoDestroyAttribute(PyParameterRange_destroy ,PyParameterRange)
// Standart Accessors (Attributes).
DirectGetBoolAttribute(PyParameterRange_isValid ,isValid ,PyParameterRange,ParameterRange)
DirectGetBoolAttribute(PyParameterRange_progress,progress,PyParameterRange,ParameterRange)
DirectGetUIntAttribute(PyParameterRange_getIndex,getIndex,PyParameterRange,ParameterRange)
DirectGetUIntAttribute(PyParameterRange_getSize ,getSize ,PyParameterRange,ParameterRange)
DirectSetIntAttribute (PyParameterRange_setIndex,setIndex,PyParameterRange,ParameterRange)
DirectVoidMethod(ParameterRange,range,reset)
// ---------------------------------------------------------------
// PyParameterRange Attribute Method table.
PyMethodDef PyParameterRange_Methods[] =
{ { "isValid" , (PyCFunction)PyParameterRange_isValid , METH_NOARGS , "To be documented." }
, { "getIndex" , (PyCFunction)PyParameterRange_getIndex , METH_NOARGS , "To be documented." }
, { "getSize" , (PyCFunction)PyParameterRange_getSize , METH_NOARGS , "To be documented." }
, { "progress" , (PyCFunction)PyParameterRange_progress , METH_NOARGS , "To be documented." }
, { "setIndex" , (PyCFunction)PyParameterRange_setIndex , METH_VARARGS, "To be documented." }
, { "reset" , (PyCFunction)PyParameterRange_reset , METH_NOARGS , "To be documented." }
//, { "destroy" , (PyCFunction)PyParameterRange_destroy , METH_NOARGS
// , "Destroy associated hurricane object, the python object remains." }
, {NULL, NULL, 0, NULL} /* sentinel */
};
PythonOnlyDeleteMethod(ParameterRange)
PyTypeObjectLinkPyType(ParameterRange)
#else // End of Python Module Code Part.
// +=================================================================+
// | "PyParameterRange" Shared Library Code Part |
// +=================================================================+
// ---------------------------------------------------------------
// Allocator Method : "PyParameterRange_NEW ()"
//
// No PyParameterRange should ever be created, it's not a terminal object
// of the class hierarchy. Instead create the real underlying PyObject.
PyObject* PyParameterRange_NEW ( ParameterRange* range ) {
if (not range) {
PyErr_SetString ( HurricaneError, "PyParameterRange_NEW(): NULL range argument." );
return NULL;
}
StepParameterRange* stepRange = dynamic_cast<StepParameterRange*>(range);
if (stepRange) return PyStepParameterRange_Link( stepRange );
Py_RETURN_NONE;
}
PyTypeRootObjectDefinitions(ParameterRange)
#endif // Shared Library Code Part.
} // extern "C".
// +=================================================================+
// | "PyParameterRange" Shared Library Code Part |
// +=================================================================+
# if !defined(__PYTHON_MODULE__)
ParameterRange* ParameterRangeCast ( PyObject* derivedObject ) {
if (not derivedObject or (derivedObject == Py_None)) return NULL;
if (IsPyStepParameterRange (derivedObject)) return PYSTEPPARAMETERRANGE_O (derivedObject);
if (IsPyMatrixParameterRange(derivedObject)) return PYMATRIXPARAMETERRANGE_O(derivedObject);
return NULL;
}
#endif
} // Bora namespace.

View File

@ -0,0 +1,123 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | B o r a - A n a l o g S l i c i n g T r e e |
// | |
// | Author : Jean-Paul Chaput |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./bora/PyStepParameterRange.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/analog/PyDevice.h"
#include "crlcore/PyRoutingGauge.h"
#include "bora/PyStepParameterRange.h"
namespace Bora {
using namespace Hurricane;
using namespace Isobar;
extern "C" {
#undef ACCESS_OBJECT
#undef ACCESS_CLASS
#define ACCESS_OBJECT _baseObject._object
#define ACCESS_CLASS(_pyObject) &(_pyObject->_baseObject)
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(StepParameterRange,node,function)
// +=================================================================+
// | "PyStepParameterRange" Python Module Code Part |
// +=================================================================+
#if defined(__PYTHON_MODULE__)
static PyObject* PyStepParameterRange_NEW ( PyObject* , PyObject* args )
{
double start = 0.0;
double step = 0.0;
double count = 0.0;
StepParameterRange* range = NULL;
HTRY
if (not PyArg_ParseTuple( args, "ddd:StepParameterRange_NEW", &start, &step, &count ) ) {
PyErr_SetString ( ConstructorError, "StepParameterRange.create(): Invalid/bad number of parameters ." );
return NULL;
}
range = new StepParameterRange( start, step, count );
HCATCH
return PyStepParameterRange_Link(range);
}
static int PyStepParameterRange_Init ( PyStepParameterRange* self, PyObject* args, PyObject* kwargs )
{
cdebug_log(20,0) << "PyStepParameterRange_Init(): " << (void*)self << endl;
return 0;
}
static void PyStepParameterRange_DeAlloc ( PyStepParameterRange* self )
{
cdebug_log(20,0) << "PyStepParameterRange_DeAlloc(" << (void*)self << ") "
<< (void*)(self->ACCESS_OBJECT) << ":" << self->ACCESS_OBJECT << endl;
if (self->ACCESS_OBJECT and not self->ACCESS_OBJECT->isNested()) {
cdebug_log(20,0) << "C++ object := " << &(self->ACCESS_OBJECT) << endl;
delete self->ACCESS_OBJECT;
}
PyObject_DEL( self );
}
DirectGetDoubleAttribute(PyStepParameterRange_getValue,getValue,PyStepParameterRange,StepParameterRange)
// Standart Destroy (Attribute).
// ---------------------------------------------------------------
// PyStepParameterRange Attribute Method table.
PyMethodDef PyStepParameterRange_Methods[] =
{ { "getValue" , (PyCFunction)PyStepParameterRange_getValue , METH_NOARGS , "To be documented." }
, { NULL, NULL, 0, NULL } /* sentinel */
};
// +-------------------------------------------------------------+
// | "PyStepParameterRange" Object Methods |
// +-------------------------------------------------------------+
PyTypeObjectLinkPyTypeNewInit(StepParameterRange)
#else // End of Python Module Code Part.
// +=================================================================+
// | "PyStepParameterRange" Shared Library Code Part |
// +=================================================================+
extern LinkCreateMethod(StepParameterRange);
PyTypeInheritedObjectDefinitions(StepParameterRange, ParameterRange)
#endif // End of Shared Library Code Part.
} // extern "C".
} // Bora namespace.

View File

@ -77,12 +77,11 @@ namespace Bora {
NodeSets nodeSets = slicingtree->getNodeSets(); NodeSets nodeSets = slicingtree->getNodeSets();
switch ( index.column() ) { switch ( index.column() ) {
case 0: return QVariant( row ); case 0: return QVariant( row );
case 1: return QVariant( DbU::toPhysical(nodeSets[row]->getHeight() , DbU::Micro) ); case 1: return QVariant( DbU::toPhysical(nodeSets[row]->getHeight(), DbU::Micro) );
case 2: return QVariant( DbU::toPhysical(nodeSets[row]->getWidth() , DbU::Micro) ); case 2: return QVariant( DbU::toPhysical(nodeSets[row]->getWidth (), DbU::Micro) );
case 3: return QVariant( nodeSets[row]->getOccupationArea() ); case 3: return QVariant( nodeSets[row]->getOccupationArea() );
case 4: return QVariant( nodeSets[row]->getCpt() ); case 4: return QVariant( nodeSets[row]->getCpt() );
case 5: return QVariant( (double) ( nodeSets[row]->getWidth() case 5: return QVariant( nodeSets[row]->getRatio() );
/ nodeSets[row]->getHeight()) );
case 6: return QVariant( DbU::getPhysical( nodeSets[row]->getWidth() ,DbU::Micro) case 6: return QVariant( DbU::getPhysical( nodeSets[row]->getWidth() ,DbU::Micro)
* DbU::getPhysical( nodeSets[row]->getHeight(),DbU::Micro) ); * DbU::getPhysical( nodeSets[row]->getHeight(),DbU::Micro) );
default: default:

View File

@ -80,7 +80,7 @@ namespace Bora {
: Super() : Super()
, _parent (NULL) , _parent (NULL)
, _flags (0) , _flags (0)
, _nodeSets(NodeSets::create( NULL, 0.0, 0.0, 0.0 )) , _nodeSets(NodeSets::create( NULL, NULL))
, _x (0) , _x (0)
, _y (0) , _y (0)
, _boxSet (NULL) , _boxSet (NULL)
@ -489,6 +489,12 @@ namespace Bora {
} }
void SlicingNode::_setGlobalSize ( DbU::Unit, DbU::Unit )
{
cerr << Error( "SlicingNode::_setGlobalSize(): Must not be called on \"%s\"." , _getTypeName().c_str() ) << endl;
}
void SlicingNode::preDestroy () void SlicingNode::preDestroy ()
{ {
if (_parent) _parent->removeNode(this); if (_parent) _parent->removeNode(this);
@ -692,6 +698,9 @@ namespace Bora {
for ( RoutingPad* rp : net->getRoutingPads() ) rps.push_back( rp ); for ( RoutingPad* rp : net->getRoutingPads() ) rps.push_back( rp );
for ( RoutingPad* rp : rps ) rp->destroy(); for ( RoutingPad* rp : rps ) rp->destroy();
} }
_cell->getFlags().reset( Cell::Flags::FlattenedNets|Cell::Flags::Routed );
_cell->setTerminalNetlist( false );
} }
@ -812,38 +821,17 @@ namespace Bora {
} }
void SlicingNode::setNFing ( int ) void SlicingNode::setBoxSetIndex ( size_t )
{ cerr << Error( "SlicingNode::setNFing(): Base class method must never be called." ) << endl; } { cerr << Error( "SlicingNode::setBoxSetIndex(): Base class method must never be called." ) << endl; }
int SlicingNode::getNFing () const size_t SlicingNode::getBoxSetIndex () const
{ {
cerr << Error( "SlicingNode::getNFing(): Base class method must never be called." ) << endl; cerr << Error( "SlicingNode::getBoxSetIndex(): Base class method must never be called." ) << endl;
return 0; return 0;
} }
double SlicingNode::getStartParameter () const
{
cerr << Error( "SlicingNode::getStartParameter(): Base class method must never be called." ) << endl;
return 0.0;
}
double SlicingNode::getStepParameter () const
{
cerr << Error( "SlicingNode::getStepParameter(): Base class method must never be called." ) << endl;
return 0.0;
}
double SlicingNode::getCountParameter () const
{
cerr << Error( "SlicingNode::getCountParameter(): Base class method must never be called." ) << endl;
return 0.0;
}
Instance* SlicingNode::getInstance () const Instance* SlicingNode::getInstance () const
{ {
cerr << Error( "SlicingNode::getInstance(): Base class method must never be called." ) << endl; cerr << Error( "SlicingNode::getInstance(): Base class method must never be called." ) << endl;

View File

@ -399,9 +399,11 @@ namespace Bora {
if (device) { if (device) {
TransistorFamily* tf = dynamic_cast<TransistorFamily*>( device ); TransistorFamily* tf = dynamic_cast<TransistorFamily*>( device );
if (tf) _gridLabel[i+5]->setDynamicText ( QString("%1" ).arg( tf->getNfing() ) ); if (tf) {
_gridLabel[i+5]->setDynamicText ( QString("%1" ).arg( tf->getNfing() ) );
i++;
}
} }
i++;
} }
} }

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