Compare commits

..

373 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
3360 changed files with 495187 additions and 103872 deletions

View File

@ -5,8 +5,6 @@
Coriolis README
===============
**Tag: Test 5 of LIP6 gitlab**
Coriolis is a free database, placement tool and routing tool for VLSI design.
@ -27,7 +25,7 @@ Documentation
The complete documentation is available here, both in pdf & html:
./documentation/_build/html/index.html
./documentation/output/html
./documentation/UsersGuide/UsersGuide.pdf
The documentation of the latest *stable* version is also

View File

@ -24,6 +24,7 @@
find_package(VLSISAPD REQUIRED)
find_package(HURRICANE REQUIRED)
find_package(CORIOLIS REQUIRED)
find_package(ETESIAN REQUIRED)
find_package(Doxygen)
add_subdirectory(src)

View File

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

View File

@ -20,11 +20,13 @@
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/DataBase.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/Horizontal.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Vertical.h"
#include "hurricane/Cell.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/DebugSession.h"
#include "hurricane/UpdateSession.h"
#include "crlcore/RoutingGauge.h"
@ -120,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.
@ -134,11 +163,13 @@ namespace Anabatic {
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::Breakpoint;
using Hurricane::DataBase;
using Hurricane::RegularLayer;
using Hurricane::Component;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::NetRoutingExtension;
using Hurricane::NetExternalComponents;
using Hurricane::Cell;
using Hurricane::DebugSession;
using Hurricane::UpdateSession;
@ -280,19 +311,27 @@ namespace Anabatic {
// -------------------------------------------------------------------
// Class : "Anabatic::NetData".
NetData::NetData ( Net* net )
NetData::NetData ( Net* net, AnabaticEngine* anabatic )
: _net (net)
, _state (NetRoutingExtension::get(net))
, _searchArea()
, _rpCount (0)
, _diodeCount(0)
, _sparsity (0)
, _flags ()
{
if (_state and _state->isMixedPreRoute()) return;
Cell* diodeCell = anabatic->getDiodeCell();
for ( RoutingPad* rp : _net->getRoutingPads() ) {
_searchArea.merge( rp->getBoundingBox() );
++_rpCount;
if (diodeCell) {
Plug* plug = dynamic_cast<Plug*>( rp->getPlugOccurrence().getEntity() );
if (plug and (plug->getInstance()->getMasterCell() == diodeCell))
++_diodeCount;
}
}
_update();
}
@ -334,11 +373,15 @@ namespace Anabatic {
, _autoContactLut ()
, _edgeCapacitiesLut()
, _blockageNet (cell->getNet("blockagenet"))
, _diodeCell (NULL)
{
_matrix.setCell( cell, _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 );
}
}
@ -346,9 +389,17 @@ namespace Anabatic {
{
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();
GCell::create( this );
UpdateSession::close();
checkPlacement();
}
@ -395,6 +446,7 @@ namespace Anabatic {
void AnabaticEngine::_gutAnabatic ()
{
//DebugSession::open( 159, 160 );
openSession();
_flags.reset( Flags::DestroyBaseContact|Flags::DestroyBaseSegment );
@ -402,19 +454,40 @@ namespace Anabatic {
if (_state == EngineDriving) {
cdebug_log(145,1) << "Saving AutoContacts/AutoSegments." << endl;
vector<NonReducedItem> reduceds;
size_t fixedSegments = 0;
size_t sameLayerDoglegs = 0;
size_t bloatedStraps = 0;
for ( auto isegment : _autoSegmentLut ) {
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 << Dots::asSizet(" - Active AutoSegments",AutoSegment::getAllocateds()-fixedSegments) << endl;
cmess1 << Dots::asSizet(" - Active AutoContacts",AutoContact::getAllocateds()-fixedSegments*2) << endl;
cmess1 << Dots::asSizet(" - AutoSegments" ,AutoSegment::getAllocateds()) << endl;
cmess1 << Dots::asSizet(" - AutoContacts" ,AutoContact::getAllocateds()) << endl;
cmess1 << Dots::asSizet(" - Same Layer doglegs" ,sameLayerDoglegs) << endl;
cmess1 << Dots::asSizet(" - Active AutoSegments" ,AutoSegment::getAllocateds()-fixedSegments) << endl;
cmess1 << Dots::asSizet(" - Active AutoContacts" ,AutoContact::getAllocateds()-fixedSegments*2) << endl;
cmess1 << Dots::asSizet(" - AutoSegments" ,AutoSegment::getAllocateds()) << endl;
cmess1 << Dots::asSizet(" - AutoContacts" ,AutoContact::getAllocateds()) << endl;
cmess1 << Dots::asSizet(" - Same Layer doglegs" ,sameLayerDoglegs) << endl;
cmess1 << Dots::asSizet(" - Bloated straps (< minArea)",bloatedStraps ) << endl;
//for ( Net* net : _cell->getNets() ) _saveNet( net );
@ -437,14 +510,33 @@ namespace Anabatic {
_ovEdges.clear();
}
exportExternalNets();
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 );
}
}
}
Configuration* AnabaticEngine::getConfiguration ()
{ return _configuration; }
const Configuration* AnabaticEngine::getConfiguration () const
{ return _configuration; }
Interval AnabaticEngine::getUSide ( Flags direction ) const
{
Interval side;
@ -492,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 ()
{ Session::_open(this); }
@ -518,10 +709,10 @@ namespace Anabatic {
size_t oindex = _netOrdering.size();
for ( Net* net : _cell->getNets() ) {
if (_netDatas.find(net->getId()) != _netDatas.end()) continue;
NetData* data = new NetData( net );
NetData* data = new NetData( net, this );
_netOrdering.push_back( data );
netHistogram.addSample( (float)data->getRpCount(), 0 );
netHistogram.addSample( (float)(data->getRpCount() - data->getDiodeRpCount()), 0 );
}
for ( ; oindex < _netOrdering.size() ; ++oindex ) {
@ -599,7 +790,7 @@ namespace Anabatic {
NetData* data = NULL;
NetDatas::iterator idata = _netDatas.find( net->getId() );
if (idata == _netDatas.end()) {
data = new NetData( net );
data = new NetData( net, this );
_netDatas.insert( make_pair(net->getId(),data) );
_netOrdering.push_back( data );
// cerr << Bug( "AnabaticEngine::getNetData() - %s is missing in NetDatas table."
@ -883,6 +1074,17 @@ namespace Anabatic {
UpdateSession::open();
for ( GCell* gcell : _gcells ) gcell->cleanupGlobal();
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;
}
}
}
}
@ -894,6 +1096,8 @@ namespace Anabatic {
if (_state > EngineGlobalLoaded)
throw Error ("AnabaticEngine::loadGlobalRouting() : global routing already loaded.");
antennaProtect();
if (method == EngineLoadGrByNet ) { _loadGrByNet(); }
else {
throw Error( badMethod, "Anabatic::loadGlobalRouting()", method, getString(_cell).c_str() );
@ -1037,7 +1241,10 @@ namespace Anabatic {
//AutoSegment::setShortNetMode( true );
++shortNets;
}
if (NetRoutingExtension::isAutomaticGlobalRoute(net)) {
if (NetRoutingExtension::isManualDetailRoute(net))
continue;
if ( NetRoutingExtension::isManualGlobalRoute(net)
or NetRoutingExtension::isAutomaticGlobalRoute(net)) {
DebugSession::open( net, 145, 150 );
AutoSegment::setAnalogMode( NetRoutingExtension::isAnalog(net) );
@ -1208,7 +1415,7 @@ namespace Anabatic {
set<const Layer*> connectedLayers;
forEach ( Segment*, segment, net->getSegments() ) {
if (segment->getLength()) {
if (segment->getAnchoredLength()) {
if (net->isExternal()) {
NetExternalComponents::setExternal( *segment );
}
@ -1481,7 +1688,7 @@ namespace Anabatic {
Edge* edge = neighbor->getWestEdge();
if (not edge) break;
if (edge->getReservedCapacity() < maxTermSat)
if (edge->getReservedCapacity() < (uint32_t)maxTermSat)
edge->reserveCapacity( maxTermSat - edge->getReservedCapacity() );
neighbor = neighbor->getWest();
}
@ -1490,7 +1697,7 @@ namespace Anabatic {
Edge* edge = neighbor->getEastEdge();
if (not edge) break;
if (edge->getReservedCapacity() < maxTermSat)
if (edge->getReservedCapacity() < (uint32_t)maxTermSat)
edge->reserveCapacity( maxTermSat - edge->getReservedCapacity() );
neighbor = neighbor->getEast();
}

File diff suppressed because it is too large Load Diff

View File

@ -178,6 +178,7 @@ namespace Anabatic {
AutoHorizontal* AutoContact::getHorizontal2 () const { return NULL; }
AutoVertical* AutoContact::getVertical1 () const { return NULL; }
AutoVertical* AutoContact::getVertical2 () const { return NULL; }
bool AutoContact::isOnPin () const { return false; }
void AutoContact::getDepthSpan ( size_t& minDepth, size_t& maxDepth ) const
@ -204,10 +205,11 @@ namespace Anabatic {
size_t maxDepth = 0;
getDepthSpan( minDepth, maxDepth );
if (minDepth == maxDepth)
setLayer( Session::getRoutingGauge()->getRoutingLayer(minDepth) );
else
setLayer( Session::getRoutingGauge()->getContactLayer(minDepth) );
setLayerAndWidth( maxDepth-minDepth, minDepth );
// if (minDepth == maxDepth)
// setLayer( Session::getRoutingGauge()->getRoutingLayer(minDepth) );
// else
// setLayer( Session::getRoutingGauge()->getContactLayer(minDepth) );
}
@ -225,14 +227,17 @@ namespace Anabatic {
size_t depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer());
DbU::Unit length;
if (segment->isLocal()) {
length = segment->getLength();
length = segment->getAnchoredLength();
lengths[depth] += length;
DbU::Unit sideLength = (segment->isHorizontal()) ? hSideLength : vSideLength;
if ( not segment->isUnbound() and (abs(length) > sideLength) )
cerr << Error("Suspicious length:%.2f of %s."
,DbU::getValueString(length).c_str()
,getString(segment).c_str()) << endl;
cerr << Error( "AutoContact::getLength(): Suspicious length %s (> %s) of %s.\n"
" (on: %s)"
, DbU::getValueString(length).c_str()
, DbU::getValueString(sideLength).c_str()
, getString(segment).c_str()
, getString(this).c_str()) << endl;
} else {
if (segment->isHorizontal()) {
if (isSourceHook)
@ -469,12 +474,13 @@ namespace Anabatic {
void AutoContact::setConstraintBox ( const Box& box )
{
cdebug_log(149,0) << "setConstraintBox() " << this << " " << getConstraintBox()
<< " from:" << box << endl;
setCBXMin ( box.getXMin() );
setCBXMax ( box.getXMax() );
setCBYMin ( box.getYMin() );
setCBYMax ( box.getYMax() );
cdebug_log(149,0) << "setConstraintBox() - " << this << " " << getConstraintBox()
<< " from:" << box << endl;
cdebug_log(149,0) << "setConstraintBox() " << this << " " << getConstraintBox() << endl;
cdebug_log(149,0) << "* " << _gcell << endl;
}
@ -572,8 +578,13 @@ namespace Anabatic {
if (delta == 0) {
setLayer( Session::getRoutingLayer(depth) );
setSizes( Session::getWireWidth (depth)
, Session::getWireWidth (depth) );
if (Session::getDirection(depth) & Flags::Horizontal) {
setSizes( Session::getPWireWidth(depth)
, Session::getWireWidth (depth) );
} else {
setSizes( Session::getWireWidth (depth)
, Session::getPWireWidth(depth) );
}
} else {
setLayer( Session::getContactLayer(depth) );
setSizes( Session::getViaWidth (depth)

View File

@ -29,6 +29,7 @@
#include "hurricane/RoutingPad.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Pin.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactTerminal.h"
@ -47,6 +48,7 @@ namespace Anabatic {
using Hurricane::Transformation;
using Hurricane::Entity;
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
{ return NULL; }

View File

@ -88,8 +88,17 @@ namespace Anabatic {
AutoSegment* AutoContactTurn::getPerpandicular ( const AutoSegment* reference ) const
{
cdebug_log(149,0) << _getTypeName() << "::getPerpandicular() " << this
<< " to:" << reference << endl;
cdebug_log(149,0) << "| _horizontal1:" << _horizontal1 << endl;
cdebug_log(149,0) << "| _vertical1 :" << _vertical1 << endl;
if (reference == _horizontal1) return _vertical1;
if (reference == _vertical1 ) return _horizontal1;
cdebug_log(149,0) << _getTypeName() << "::getPerpandicular() " << this
<< " to:" << reference << " failed." << endl;
return NULL;
}
@ -117,6 +126,9 @@ namespace Anabatic {
void AutoContactTurn::cacheDetach ( AutoSegment* segment )
{
cdebug_log(149,0) << _getTypeName() << "::cacheDetach() " << this
<< " from:" << segment << endl;
if (segment == _horizontal1) _horizontal1 = NULL;
else if (segment == _vertical1) _vertical1 = NULL;
else return;
@ -127,6 +139,9 @@ namespace Anabatic {
void AutoContactTurn::cacheAttach ( AutoSegment* segment )
{
cdebug_log(149,0) << _getTypeName() << "::cacheAttach() " << this
<< " to:" << segment << endl;
if (segment->getDirection() == Flags::Horizontal) {
if (_horizontal1) {
cerr << Bug( "%s::cacheAttach() On %s,\n"

View File

@ -47,8 +47,8 @@ namespace Anabatic {
Segment* AutoHorizontal::base () { return _horizontal; }
Segment* AutoHorizontal::base () const { return _horizontal; }
Horizontal* AutoHorizontal::getHorizontal () { return _horizontal; }
DbU::Unit AutoHorizontal::getSourceU () const { return _horizontal->getSourceX(); }
DbU::Unit AutoHorizontal::getTargetU () const { return _horizontal->getTargetX(); }
DbU::Unit AutoHorizontal::getSourceU () const { return _horizontal->getSource()->getX(); }
DbU::Unit AutoHorizontal::getTargetU () const { return _horizontal->getTarget()->getX(); }
DbU::Unit AutoHorizontal::getDuSource () const { return _horizontal->getDxSource(); }
DbU::Unit AutoHorizontal::getDuTarget () const { return _horizontal->getDxTarget(); }
Interval AutoHorizontal::getSpanU () const { return Interval(_horizontal->getSourceX(),_horizontal->getTargetX()); }
@ -93,6 +93,14 @@ namespace Anabatic {
mergeNativeMax( gcell->getConstraintYMax() );
}
}
// if (getId() == 1518590) {
// cerr << "AutoHorizontal::_postCreate(): " << this << endl;
// cerr << "| Source contact:" << source << endl;
// cerr << "| Source GCell: " << getGCell() << endl;
// cerr << "| Target contact:" << target << endl;
// cerr << "| Target GCell: " << target->getGCell() << endl;
// }
}
@ -224,13 +232,15 @@ namespace Anabatic {
gcell = gcell->getEast( yprobe );
if (not gcell) {
success = false;
cerr << Error( "AutoHorizontal::getGCells() : NULL GCell under %s\n"
" begin:%s\n"
" end: %s"
, getString(this).c_str()
, getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
if (not isCreated()) {
cerr << Error( "AutoHorizontal::getGCells() : NULL GCell under %s\n"
" begin:%s\n"
" end: %s"
, getString(this).c_str()
, getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
}
break;
}
@ -245,8 +255,9 @@ namespace Anabatic {
{
cdebug_tabw(149,1);
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
if (source->isOnPin() or target->isOnPin()) { cdebug_tabw(149,-1); return false; }
Interval sourceSide = source->getGCell()->getSide( Flags::Vertical );
Interval targetSide = target->getGCell()->getSide( Flags::Vertical );
@ -314,6 +325,9 @@ namespace Anabatic {
isNonPrefSource = true;
slackenSource = true;
}
cdebug_log(149,0) << "target:" << target << endl;
cdebug_log(149,0) << "target->getPerpandicular(this):" << target->getPerpandicular(this) << endl;
if (target->isTurn() and (target->getPerpandicular(this)->getLayer() == getLayer())) {
isNonPrefTarget = true;
slackenTarget = true;
@ -321,11 +335,11 @@ namespace Anabatic {
cdebug_tabw(149,1);
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
cdebug_log(149,0) << "test:" << (getLength() < 5*getPitch()) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl;
cdebug_log(149,0) << "test:" << (getAnchoredLength() < 5*getPitch()) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getAnchoredLength()) << endl;
if (height >= 4*getPitch()) {
if (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < 5*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;
@ -399,7 +413,15 @@ namespace Anabatic {
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
if (targetSlackened and (doglegs.size() >= 2)) {
cdebug_log(149,0) << "AutoHorizontal::_slacken(): Target @" << DbU::getValueString(targetPosition) << endl;
GCell* targetGCell = target->getGCell();
Box constraintBox = target->getConstraintBox();
cdebug_log(149,0) << "slacken from Target @" << DbU::getValueString(targetPosition) << endl;
if (targetPosition >= targetGCell->getXMax()) {
cdebug_log(149,0) << "On the rigthmost track, adjust of one P-pitch to the left." << endl;
targetPosition -= getPPitch();
constraintBox.inflate( getPPitch(), 0, 0, 0 );
}
doglegs[doglegs.size()-2]->setAxis( targetPosition );
success = true;
@ -407,7 +429,7 @@ namespace Anabatic {
cdebug_log(149,0) << "Fixing on target terminal contact: "
<< doglegs[doglegs.size()-2]->getAutoTarget() << endl;
//doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntFixed );
doglegs[doglegs.size()-2]->getAutoTarget()->setConstraintBox( target->getConstraintBox() );
doglegs[doglegs.size()-2]->getAutoTarget()->setConstraintBox( constraintBox );
doglegs[doglegs.size()-2]->getAutoTarget()->setFlags( CntUserNativeConstraints );
}
}
@ -464,9 +486,18 @@ namespace Anabatic {
void AutoHorizontal::updateOrient ()
{
if (_horizontal->getTargetX() < _horizontal->getSourceX()) {
if (_horizontal->getTarget()->getX() < _horizontal->getSource()->getX()) {
cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl;
_horizontal->invert();
if (isAtMinArea()) {
DbU::Unit sourceX = _horizontal->getSourceX();
DbU::Unit targetX = _horizontal->getTargetX();
_horizontal->invert();
setDuSource( sourceX - getSourceU() );
setDuTarget( targetX - getTargetU() );
} else {
_horizontal->invert();
}
cdebug_log(145,0) << "updateOrient() " << this << " (after S/T swap)" << endl;
uint64_t spinFlags = _flags & SegDepthSpin;
unsetFlags( SegDepthSpin );
@ -490,8 +521,8 @@ namespace Anabatic {
void AutoHorizontal::updatePositions ()
{
_sourcePosition = _horizontal->getSourceX() - getExtensionCap(Flags::Source);
_targetPosition = _horizontal->getTargetX() + getExtensionCap(Flags::Target);
_sourcePosition = getSourceU() - getExtensionCap(Flags::Source);
_targetPosition = getTargetU() + getExtensionCap(Flags::Target);
}
@ -511,8 +542,8 @@ namespace Anabatic {
bool AutoHorizontal::checkPositions () const
{
bool coherency = true;
DbU::Unit sourcePosition = _horizontal->getSourceX() - getExtensionCap(Flags::Source);
DbU::Unit targetPosition = _horizontal->getTargetX() + getExtensionCap(Flags::Target);
DbU::Unit sourcePosition = _horizontal->getSource()->getX() - getExtensionCap(Flags::Source);
DbU::Unit targetPosition = _horizontal->getTarget()->getX() + getExtensionCap(Flags::Target);
if ( _sourcePosition != sourcePosition ) {
cerr << "extensionCap: " << DbU::getValueString(getExtensionCap(Flags::Source)) << endl;

View File

@ -14,6 +14,7 @@
// +-----------------------------------------------------------------+
#include <cmath>
#include "hurricane/DebugSession.h"
#include "hurricane/Warning.h"
#include "hurricane/Bug.h"
@ -347,7 +348,7 @@ namespace Anabatic {
if ( deltaUnit < 0 ) return true; // Smallest source first.
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 false;
@ -408,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".
@ -417,7 +444,7 @@ namespace Anabatic {
bool AutoSegment::_analogMode = false;
bool AutoSegment::_shortNetMode = 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; }
@ -430,17 +457,19 @@ namespace Anabatic {
//cerr << "AutoSegment::_initialize()" << endl;
_initialized = true;
DbU::Unit twoGrid = DbU::fromGrid( 2 );
for ( size_t depth=0 ; depth<Session::getDepth() ; ++depth ) {
DbU::Unit* viaToTopCap = new DbU::Unit ( 0 );
DbU::Unit* viaToBottomCap = 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());
uint32_t flags = (isVertical) ? Layer::EnclosureV : Layer::EnclosureH ;
//cerr << depth << ":" << Session::getLayerGauge(depth)->getLayer()->getName()
// << " isVertical:" << Session::getLayerGauge(depth)->isVertical() << endl;
*viaToSameCap = Session::getWireWidth(depth)/2;
*viaToSameCap = Session::getPWireWidth(depth)/2;
// Bottom metal of the VIA going *up*.
const Layer* viaLayer = dynamic_cast<const ViaLayer*>( Session::getContactLayer(depth) );
@ -454,6 +483,15 @@ namespace Anabatic {
*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 << " viaToTopCap: " << DbU::getValueString(*viaToTopCap ) << endl;
//if (depth > 0)
@ -461,7 +499,10 @@ namespace Anabatic {
//cerr << " viaToBottomCap: " << DbU::getValueString(*viaToBottomCap) << 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 }} ) );
}
}
@ -534,6 +575,11 @@ namespace Anabatic {
_observers.notify( Destroy );
AutoContact* contact = getAutoSource();
if (contact) contact->cacheDetach( this );
contact = getAutoTarget();
if (contact) contact->cacheDetach( this );
Session::unlink( this );
cdebug_tabw(145,-1);
}
@ -668,6 +714,10 @@ namespace Anabatic {
incReduceds();
}
Interval oldSpan = Interval( _sourcePosition, _targetPosition );
if (not expandToMinLength(oldSpan)) {
unexpandToMinLength();
}
updatePositions();
unsigned int observerFlags = Revalidate;
@ -720,20 +770,53 @@ namespace Anabatic {
if (getFlags() & SegSourceTop ) cap = getViaToTopCap (depth);
else if (getFlags() & SegSourceBottom) cap = getViaToBottomCap(depth);
else cap = getViaToSameCap (depth);
cdebug_log(145,0) << "getExtensionCap(): flags:" << getFlags()
cdebug_log(150,0) << "getExtensionCap(): (source) flags:" << getFlags()
<< " VIA cap:" << DbU::getValueString(cap)
<< " " << (getFlags() & SegSourceBottom)
<< " t:" << (getFlags() & SegSourceBottom)
<< " b:" << (getFlags() & SegSourceTop)
<< 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 (getFlags() & SegTargetTop ) cap = getViaToTopCap (depth);
else if (getFlags() & SegTargetBottom) cap = getViaToBottomCap(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;
return cap + getLayer()->getMinimalSpacing()/2;;
// if ( not isCreated()
// 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;
}
@ -1305,7 +1388,7 @@ namespace Anabatic {
if (terminalMin != 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;
DbU::Unit perpandMin = autoSegment->getSourceU();
@ -1529,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
{
if (isGlobal()) return false;
@ -1544,14 +1756,18 @@ namespace Anabatic {
}
bool AutoSegment::canReduce () const
bool AutoSegment::canReduce ( Flags flags ) const
{
cdebug_log(159,0) << "AutoSegment::canReduce():" << this << endl;
cdebug_log(159,0) << " _reduceds:" << _reduceds << endl;
if (isGlobal() or isDrag() or isFixed()) return false;
DbU::Unit length = getAnchoredLength();
if (isGlobal() and (length > getPPitch())) return false;
if (isDrag() or isFixed()) 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* target = getAutoTarget();
@ -1565,6 +1781,9 @@ namespace Anabatic {
// 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();
if (isSpinBottom()) {
if (perpandicularDepth > 0) --perpandicularDepth;
@ -1573,17 +1792,18 @@ namespace Anabatic {
if (perpandicularDepth >= Session::getDepth()) return false;
} else
return false;
cdebug_log(159,0) << " length:" << DbU::getValueString(getLength()) << endl;
if (getLength() >= (Session::getPitch(perpandicularDepth) * 2)) return false;
if (getAnchoredLength() >= Session::getPitch(perpandicularDepth) * 2) return false;
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* target = getAutoTarget();
@ -1598,13 +1818,32 @@ namespace Anabatic {
perpandicular->incReduceds();
}
// if (not source->isTerminal()) source->getPerpandicular( this )->incReduceds();
// if (not target->isTerminal()) target->getPerpandicular( this )->incReduceds();
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
{
if (not (_flags & SegIsReduced)) return false;
@ -1614,26 +1853,27 @@ namespace Anabatic {
else if (isSpinTop ()) ++perpandicularDepth;
else return true;
return (getLength() >= (Session::getPitch(perpandicularDepth) * 2));
return (getAnchoredLength() >= (Session::getPitch(perpandicularDepth) * 2));
}
bool AutoSegment::raise ()
{
if (not (_flags & SegIsReduced)) return false;
cdebug_log(159,0) << "AutoSegment::raise():" << this << endl;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
_flags &= ~SegIsReduced;
//if (not source->isTerminal()) source->getPerpandicular( this )->decReduceds();
//if (not target->isTerminal()) target->getPerpandicular( this )->decReduceds();
for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
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();
}
@ -1724,8 +1964,8 @@ namespace Anabatic {
if (_canSlacken()) return true;
if ((flags & Flags::Propagate) and not isNotAligned()) {
forEach ( AutoSegment*, isegment, const_cast<AutoSegment*>(this)->getAligneds() ) {
if (isegment->_canSlacken()) return true;
for ( AutoSegment* segment : const_cast<AutoSegment*>(this)->getAligneds() ) {
if (segment->_canSlacken()) return true;
}
}
@ -1877,6 +2117,12 @@ namespace Anabatic {
{
cdebug_log(159,0) << "AutoSegment::canMoveUp() " << flags
<< " (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 nLowUpDensity = true;
@ -1995,13 +2241,14 @@ namespace Anabatic {
bool AutoSegment::reduceDoglegLayer ()
{
if (not isReduced()) return true;
if (not isReduced()) return false;
DebugSession::open( getNet(), 149, 160 );
cdebug_log(159,1) << "AutoSegment::reduceDoglegLayer(): " << this << endl;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
bool success = false;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
unsigned int minSourceDepth = Session::getAllowedDepth();
unsigned int maxSourceDepth = 0;
@ -2012,9 +2259,11 @@ namespace Anabatic {
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() );
}
@ -2023,9 +2272,11 @@ namespace Anabatic {
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() );
}
@ -2038,20 +2289,26 @@ namespace Anabatic {
and (minTargetDepth == maxTargetDepth)
and (minSourceDepth == minTargetDepth) ) {
const Layer* layer = Session::getRoutingLayer(minSourceDepth);
DbU::Unit side = Session::getWireWidth (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 );
source->setSizes( side, side );
target->setSizes( side, side );
setWidth( hside );
source->setSizes( hside, vside );
target->setSizes( hside, vside );
success = true;
}
cdebug_tabw(159,-1);
DebugSession::close();
return true;
return success;
// if (not source->isTurn() or not target->isTurn()) return true;
@ -2080,6 +2337,55 @@ namespace Anabatic {
}
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;
}
DbU::Unit minLength
= DbU::fromPhysical( minArea / DbU::toPhysical( getWidth(), DbU::UnitPower::Micro )
, DbU::UnitPower::Micro );
cdebug_log(149,0) << "Min length: " << DbU::getValueString(minLength) << " ." << endl;
if ((getSpanLength() >= minLength) or isReduced()) {
cdebug_log(149,-1) << "False, has length or is reduced." << endl;
DebugSession::close();
return false;
}
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;
}
#if THIS_IS_DISABLED
bool AutoSegment::shearUp ( GCell* upGCell, AutoSegment*& movedUp, float reserve, Flags flags )
{
@ -2564,9 +2870,10 @@ namespace Anabatic {
segment->_postCreate();
} else if (vertical) {
if (vertical->getLayer() != verticalLayer) {
if (Session::getAnabatic()->getConfiguration()->isGMetal(vertical->getLayer()) )
vertical->setLayer( verticalLayer );
vertical->setWidth( verticalWidth );
if (Session::getAnabatic()->getConfiguration()->isGMetal(vertical->getLayer()) ) {
vertical->setLayer( verticalLayer );
vertical->setWidth( verticalWidth );
}
} else {
if (vertical->getWidth() != verticalWidth) {
cerr << Warning("Segment %s has non-default width %s."
@ -2607,14 +2914,16 @@ namespace Anabatic {
if (dir & Flags::UseNonPref) {
if (dir & Flags::Vertical) {
cdebug_log(149,0) << "Make vertical in non-preferred direction." << endl;
vLayer = hLayer;
vWidth = hWidth;
vWidth = Session::getDPHorizontalWidth();
cdebug_log(149,0) << "Make vertical in non-preferred direction (ppW:"
<< DbU::getValueString(vWidth).c_str() << ")." << endl;
}
if (dir & Flags::Horizontal) {
cdebug_log(149,0) << "Make horizontal in non-preferred direction." << endl;
hLayer = vLayer;
hWidth = vWidth;
hWidth = Session::getDPVerticalWidth();
cdebug_log(149,0) << "Make horizontal in non-preferred direction (ppW:"
<< DbU::getValueString(hWidth).c_str() << ")." << endl;
}
}
@ -2622,12 +2931,14 @@ namespace Anabatic {
DbU::Unit horizontalWidth = hWidth;
const Layer* verticalLayer = vLayer;
DbU::Unit verticalWidth = vWidth;
cdebug_log(149,0) << "verticalWidth:" << DbU::getValueString(verticalWidth).c_str() << endl;
uint32_t wPitch = NetRoutingExtension::getWPitch( source->getNet() );
if (wPitch > 1) {
horizontalWidth = (wPitch-1) * Session::getDHorizontalPitch() + hWidth;
verticalWidth = (wPitch-1) * Session::getDVerticalPitch () + vWidth;
}
cdebug_log(149,0) << "verticalWidth:" << DbU::getValueString(verticalWidth).c_str() << endl;
if (depth != RoutingGauge::nlayerdepth) {
horizontalLayer = verticalLayer = Session::getRoutingLayer( depth );
@ -2636,9 +2947,23 @@ namespace Anabatic {
horizontalWidth = verticalWidth = (wPitch-1) * Session::getPitch (depth)
+ Session::getWireWidth(depth);
} 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;
AutoContact* reference = source;
@ -2738,7 +3063,7 @@ namespace Anabatic {
exploreds.insert( seed->getAutoSource() );
exploreds.insert( seed->getAutoTarget() );
if (seed->getLength()) {
if (seed->getAnchoredLength()) {
if (flags & Flags::Superior) stack.push_back( seed->getAutoTarget() );
else stack.push_back( seed->getAutoSource() );
} else {
@ -2763,7 +3088,7 @@ namespace Anabatic {
AutoSegment* autoSegment = Session::lookup( segment );
if (not autoSegment) continue;
if (not autoSegment->getLength()) {
if (not autoSegment->getAnchoredLength()) {
AutoContact* contact = autoSegment->getAutoSource();
if (contact and (contact != currentContact)) {
if (exploreds.find(contact) == exploreds.end())

View File

@ -41,8 +41,8 @@ namespace Anabatic {
Segment* AutoVertical::base () { return _vertical; }
Segment* AutoVertical::base () const { return _vertical; }
Vertical* AutoVertical::getVertical () { return _vertical; }
DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSourceY(); }
DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTargetY(); }
DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSource()->getY(); }
DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTarget()->getY(); }
DbU::Unit AutoVertical::getDuSource () const { return _vertical->getDySource(); }
DbU::Unit AutoVertical::getDuTarget () const { return _vertical->getDyTarget(); }
Interval AutoVertical::getSpanU () const { return Interval(_vertical->getSourceY(),_vertical->getTargetY()); }
@ -218,13 +218,15 @@ namespace Anabatic {
if (not gcell) {
success = false;
cerr << Error( "AutoVertical::getGCells() : NULL GCell under %s\n"
" begin:%s\n"
" end: %s"
, getString(this).c_str()
, getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
if (not isCreated()) {
cerr << Error( "AutoVertical::getGCells() : NULL GCell under %s\n"
" begin:%s\n"
" end: %s"
, getString(this).c_str()
, getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
}
break;
}
@ -239,6 +241,8 @@ namespace Anabatic {
{
cdebug_tabw(149,-1);
if (getAutoSource()->isOnPin() or getAutoTarget()->isOnPin()) { cdebug_tabw(149,-1); return false; }
Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Horizontal );
Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Horizontal );
Interval sourceConstraints = Interval(getAutoSource()->getCBXMin(),getAutoSource()->getCBXMax());
@ -264,13 +268,13 @@ namespace Anabatic {
if (not isDrag()) {
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_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
cdebug_log(149,0) << "test:" << (getLength() < getPitch()*5) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl;
cdebug_log(149,0) << "test:" << (getAnchoredLength() < getPitch()*5) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getAnchoredLength()) << endl;
bool success = false;
bool sourceSlackened = false;
@ -378,6 +382,10 @@ namespace Anabatic {
if (_vertical->getTargetY() < _vertical->getSourceY()) {
cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl;
_vertical->invert();
DbU::Unit duSource = getDuSource();
DbU::Unit duTarget = getDuTarget();
setDuSource( -duTarget );
setDuTarget( -duSource );
unsigned int spinFlags = _flags & SegDepthSpin;
unsetFlags( SegDepthSpin );
@ -401,8 +409,8 @@ namespace Anabatic {
void AutoVertical::updatePositions ()
{
_sourcePosition = _vertical->getSourceY() - getExtensionCap(Flags::Source);
_targetPosition = _vertical->getTargetY() + getExtensionCap(Flags::Target);
_sourcePosition = getSourceU() - getExtensionCap(Flags::Source);
_targetPosition = getTargetU() + getExtensionCap(Flags::Target);
}
@ -422,8 +430,8 @@ namespace Anabatic {
bool AutoVertical::checkPositions () const
{
bool coherency = true;
DbU::Unit sourcePosition = _vertical->getSourceY() - getExtensionCap(Flags::Source);
DbU::Unit targetPosition = _vertical->getTargetY() + getExtensionCap(Flags::Target);
DbU::Unit sourcePosition = _vertical->getSource()->getY() - getExtensionCap(Flags::Source);
DbU::Unit targetPosition = _vertical->getTarget()->getY() + getExtensionCap(Flags::Target);
if ( _sourcePosition != sourcePosition ) {
cerr << Error ( "%s\n Source position incoherency: "

View File

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

View File

@ -25,6 +25,7 @@
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Pin.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/Cell.h"
#include "crlcore/Utilities.h"
@ -55,6 +56,7 @@ namespace Anabatic {
using Hurricane::BasicLayer;
using Hurricane::RegularLayer;
using Hurricane::Segment;
using Hurricane::Pin;
using Hurricane::Plug;
using Hurricane::Path;
using Hurricane::Occurrence;
@ -69,25 +71,28 @@ namespace Anabatic {
Configuration::Configuration ( const CellGauge* cg, const RoutingGauge* rg )
: _gdepthv (ndepth)
, _gdepthh (ndepth)
, _ddepthv (ndepth)
, _ddepthh (ndepth)
, _ddepthc (ndepth)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps ()
, _saturateRatio (Cfg::getParamPercentage("anabatic.saturateRatio",80.0)->asDouble())
, _saturateRp (Cfg::getParamInt ("anabatic.saturateRp" ,8 )->asInt())
, _globalThreshold (0)
, _allowedDepth (0)
, _edgeLength (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeLength",24)->asInt()))
, _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt()))
, _edgeCostH (Cfg::getParamDouble("anabatic.edgeCostH" , 9.0)->asDouble())
, _edgeCostK (Cfg::getParamDouble("anabatic.edgeCostK" ,-10.0)->asDouble())
, _edgeHInc (Cfg::getParamDouble("anabatic.edgeHInc" , 1.5)->asDouble())
, _edgeHScaling (Cfg::getParamDouble("anabatic.edgeHScaling" , 1.0)->asDouble())
, _globalIterations(Cfg::getParamInt ("anabatic.globalIterations", 10 )->asInt())
: _gdepthv (ndepth)
, _gdepthh (ndepth)
, _ddepthv (ndepth)
, _ddepthh (ndepth)
, _ddepthc (ndepth)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps ()
, _saturateRatio (Cfg::getParamPercentage("anabatic.saturateRatio",80.0)->asDouble())
, _saturateRp (Cfg::getParamInt ("anabatic.saturateRp" ,8 )->asInt())
, _globalThreshold (0)
, _allowedDepth (0)
, _edgeLength (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeLength",24)->asInt()))
, _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt()))
, _edgeCostH (Cfg::getParamDouble("anabatic.edgeCostH" , 9.0)->asDouble())
, _edgeCostK (Cfg::getParamDouble("anabatic.edgeCostK" , -10.0)->asDouble())
, _edgeHInc (Cfg::getParamDouble("anabatic.edgeHInc" , 1.5)->asDouble())
, _edgeHScaling (Cfg::getParamDouble("anabatic.edgeHScaling" , 1.0)->asDouble())
, _globalIterations (Cfg::getParamInt ("anabatic.globalIterations", 10 )->asInt())
, _diodeName (Cfg::getParamString("etesian.diodeName" , "dio_x0")->asString() )
, _antennaGateMaxWL (Cfg::getParamInt ("etesian.antennaGateMaxWL" , 0 )->asInt())
, _antennaDiodeMaxWL(Cfg::getParamInt ("etesian.antennaDiodeMaxWL", 0 )->asInt())
{
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
@ -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 )
: _gmetalh (other._gmetalh)
, _gmetalv (other._gmetalv)
, _gcontact (other._gcontact)
, _gdepthv (other._gdepthv)
, _gdepthh (other._gdepthh)
, _ddepthv (other._ddepthv)
, _ddepthh (other._ddepthh)
, _ddepthc (other._ddepthc)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps (other._extensionCaps)
, _saturateRatio (other._saturateRatio)
, _globalThreshold (other._globalThreshold)
, _allowedDepth (other._allowedDepth)
, _edgeCostH (other._edgeCostH)
, _edgeCostK (other._edgeCostK)
, _edgeHInc (other._edgeHInc)
, _edgeHScaling (other._edgeHScaling)
, _globalIterations(other._globalIterations)
: _gmetalh (other._gmetalh)
, _gmetalv (other._gmetalv)
, _gcontact (other._gcontact)
, _gdepthv (other._gdepthv)
, _gdepthh (other._gdepthh)
, _ddepthv (other._ddepthv)
, _ddepthh (other._ddepthh)
, _ddepthc (other._ddepthc)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps (other._extensionCaps)
, _saturateRatio (other._saturateRatio)
, _globalThreshold (other._globalThreshold)
, _allowedDepth (other._allowedDepth)
, _edgeCostH (other._edgeCostH)
, _edgeCostK (other._edgeCostK)
, _edgeHInc (other._edgeHInc)
, _edgeHScaling (other._edgeHScaling)
, _globalIterations (other._globalIterations)
, _diodeName (other._diodeName)
, _antennaGateMaxWL (other._antennaGateMaxWL)
, _antennaDiodeMaxWL(other._antennaDiodeMaxWL)
{
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
@ -286,6 +302,10 @@ namespace Anabatic {
{ return getWireWidth( getLayerDepth(layer) ); }
DbU::Unit Configuration::getPWireWidth ( const Layer* layer ) const
{ return getPWireWidth( getLayerDepth(layer) ); }
Flags Configuration::getDirection ( const Layer* layer ) const
{ return getDirection( getLayerDepth(layer) ); }
@ -337,6 +357,9 @@ namespace Anabatic {
{ return _rg->getLayerWireWidth(depth); }
DbU::Unit Configuration::getPWireWidth ( size_t depth ) const
{ return _rg->getLayerPWireWidth(depth); }
DbU::Unit Configuration::getExtensionCap ( size_t depth ) const
{ return _extensionCaps[depth]; }
@ -458,13 +481,24 @@ namespace Anabatic {
cdebug_log(112,0) << "Looking into: " << masterNet->getCell() << endl;
for ( Component* component : masterNet->getComponents() ) {
cdebug_log(112,0) << "@ " << component << endl;
if (not NetExternalComponents::isExternal(component)) continue;
if (not NetExternalComponents::isExternal(component)) {
cdebug_log(112,0) << " Not an external component, skip." << endl;
continue;
}
Segment* segment = dynamic_cast<Segment*>(component);
if (not segment) continue;
if (segment->getLayer()->getMask() != metal1->getMask()) continue;
if (dynamic_cast<Pin*>(component)) {
cdebug_log(112,0) << " Pins are always considered best candidates:" << component << endl;
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 minPos = DbU::Max;
DbU::Unit maxPos = DbU::Min;
@ -497,7 +531,7 @@ namespace Anabatic {
cdebug_log(112,0) << "| " << occurrence.getPath() << 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;
if ( (trackPos >= minPos) and (trackPos <= maxPos) ) {
@ -556,17 +590,22 @@ namespace Anabatic {
Record* Configuration::_getRecord () const
{
Record* record = new Record ( _getString() );
record->add ( getSlot( "_gdepthh" , _gdepthh ) );
record->add ( getSlot( "_gdepthv" , _gdepthv ) );
record->add ( getSlot( "_rg" , _rg ) );
record->add ( getSlot( "_gmetalh" , _gmetalh ) );
record->add ( getSlot( "_gmetalv" , _gmetalv ) );
record->add ( getSlot( "_gcontact" , _gcontact ) );
record->add ( getSlot( "_allowedDepth", _allowedDepth ) );
record->add ( getSlot( "_edgeCostH" , _edgeCostH ) );
record->add ( getSlot( "_edgeCostK" , _edgeCostK ) );
record->add( getSlot( "_gdepthh" , _gdepthh ) );
record->add( getSlot( "_gdepthv" , _gdepthv ) );
record->add( getSlot( "_rg" , _rg ) );
record->add( getSlot( "_gmetalh" , _gmetalh ) );
record->add( getSlot( "_gmetalv" , _gmetalv ) );
record->add( getSlot( "_gcontact" , _gcontact ) );
record->add( getSlot( "_allowedDepth" , _allowedDepth ) );
record->add( getSlot( "_edgeCostH" , _edgeCostH ) );
record->add( getSlot( "_edgeCostK" , _edgeCostK ) );
record->add( getSlot( "_edgeHInc" , _edgeHInc ) );
record->add( getSlot( "_edgeHScaling" , _edgeHScaling ) );
record->add( getSlot( "_globalIterations", _globalIterations ) );
record->add( DbU::getValueSlot( "_antennaGateMaxWL" , &_antennaGateMaxWL ) );
record->add( DbU::getValueSlot( "_antennaDiodeMaxWL", &_antennaDiodeMaxWL ) );
return ( record );
return record;
}

View File

@ -54,9 +54,11 @@ namespace Anabatic {
const BaseFlags Flags::DestroyBaseContact = (1L << 8);
const BaseFlags Flags::DestroyBaseSegment = (1L << 9);
// Flags for NetDatas objects states only.
const BaseFlags Flags::GlobalRouted = (1L << 5);
const BaseFlags Flags::GlobalFixed = (1L << 5);
const BaseFlags Flags::GlobalEstimated = (1L << 6);
const BaseFlags Flags::ExcludeRoute = (1L << 7);
const BaseFlags Flags::GlobalRouted = (1L << 7);
const BaseFlags Flags::DetailRouted = (1L << 8);
const BaseFlags Flags::ExcludeRoute = (1L << 9);
// Masks.
const BaseFlags Flags::WestSide = Horizontal|Target;
const BaseFlags Flags::EastSide = Horizontal|Source;
@ -119,6 +121,10 @@ namespace Anabatic {
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 ()

View File

@ -19,6 +19,7 @@
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Net.h"
#include "hurricane/Pin.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
@ -42,6 +43,7 @@ namespace Anabatic {
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::Component;
using Hurricane::Pin;
using Hurricane::Segment;
using Hurricane::Horizontal;
using Hurricane::Vertical;
@ -298,52 +300,68 @@ namespace Anabatic {
GCell* c2 = v2->getGCell();
// Check from GCell 1
if ( c1->isNorth(c2) ) {
if ( !v1->isNRestricted() ) restricted = false;
} else if ( c1->isSouth(c2) ) {
if ( !v1->isSRestricted() ) restricted = false;
} else if ( c1->isEast (c2) ) {
if ( !v1->isERestricted() ) restricted = false;
} else if ( c1->isWest (c2) ) {
if ( !v1->isWRestricted() ) restricted = false;
} else {
cerr << Error( "GCells are not side by side." ) << endl;
if ( c1->isNorth(c2) and not v1->isNRestricted() ) restricted = false;
else if ( c1->isSouth(c2) and not v1->isSRestricted() ) restricted = false;
else if ( c1->isEast (c2) and not v1->isERestricted() ) restricted = false;
else if ( c1->isWest (c2) and not v1->isWRestricted() ) restricted = false;
// else {
// cerr << Error( "Vertex::isRestricted(): Vertexes/GCells v1 & v2 do not share a side.\n"
// " v1:%s\n"
// " v2:%s"
// , getString(v1).c_str()
// , 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;
}
if ( (c1->getWidth() < hpitch)
||(c1->getHeight() < vpitch)
||(restricted)
) return true;
else {
restricted = true;
// Check from GCell 2
if ( c2->isNorth(c1) ) {
if ( !v2->isNRestricted() ) restricted = false;
} else if ( c2->isSouth(c1) ) {
if ( !v2->isSRestricted() ) restricted = false;
} else if ( c2->isEast (c1) ) {
if ( !v2->isERestricted() ) restricted = false;
} else if ( c2->isWest (c1) ) {
if ( !v2->isWRestricted() ) restricted = false;
} else {
cerr << Error( "GCells are not side by side." ) << 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;
}
restricted = true;
// Check from GCell 2
if ( c2->isNorth(c1) and not v2->isNRestricted() ) restricted = false;
else if ( c2->isSouth(c1) and not v2->isSRestricted() ) restricted = false;
else if ( c2->isEast (c1) and not v2->isERestricted() ) restricted = false;
else if ( c2->isWest (c1) and not v2->isWRestricted() ) restricted = false;
// else {
// cerr << Error( "Vertex::isRestricted(): Vertexes/GCells v1 & v2 do not share a side.\n"
// " v1:%s\n"
// " v2:%s"
// , getString(v1).c_str()
// , getString(v2).c_str()
// ) << endl;
// return true;
// }
if (restricted) {
cdebug_log(112,0) << "v2 -> v1 edge is restricted." << endl;
return true;
}
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
{
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 )
{
_cleanup();
@ -1473,12 +1537,13 @@ namespace Anabatic {
cdebug_log(112,1) << "Dijkstra::load() " << _net << endl;
vector<RoutingPad*> rps;
NetRoutingState* state = NetRoutingExtension::get( _net );
NetRoutingState* state = NetRoutingExtension::get( _net );
if (state) {
if (state->isSelfSym()) {
cdebug_log(112,0) << "Dijkstra::SELF SYMMETRY CASE " << DbU::getValueString(state->getSymAxis()) << endl;
}
state->unsetFlags( NetRoutingState::HasAntenna );
}
for ( Component* component : _net->getComponents() ) {
@ -1488,20 +1553,24 @@ namespace Anabatic {
cdebug_log(112,0) << "@ frp:" << rp << endl;
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 ) {
if (not _anabatic->getConfiguration()->selectRpComponent(rp))
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;
Point center = rp->getBoundingBox().getCenter();
GCell* gcell = _anabatic->getGCellUnder( center );
Box bb = rp->getBoundingBox();
Point center = rp->getBoundingBox().getCenter();
GCell* gcell = _anabatic->getGCellUnder( center );
Box bb = rp->getBoundingBox();
bool isDriver = false;
cdebug_log(112,0) << bb.getXMin() << " " << bb.getXMax() << endl;
cdebug_log(112,0) << "center X:" << center.getX() << " gcell Xmax:" << gcell->getXMax() << endl;
@ -1519,6 +1588,29 @@ namespace Anabatic {
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
cdebug_log(112,0) << "| Merged search area: " << _searchArea << ", gcell: " << gcell << endl;
@ -1543,6 +1635,8 @@ namespace Anabatic {
vertex->setDegree ( 0 );
vertex->setRpCount ( 0 );
vertex->setFrom ( NULL );
if (isDriver)
vertex->setDriver( true );
vertex->setFrom2 ( NULL);
vertex->unsetFlags ( Vertex::UseFromFrom2 );
@ -1568,6 +1662,45 @@ namespace Anabatic {
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 );
cdebug_log(112,0) << "Search halo: " << DbU::getValueString(_searchAreaHalo) << endl;
cdebug_log(112,0) << "Search area: " << _searchArea << endl;
@ -1716,8 +1849,15 @@ namespace Anabatic {
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 (_targets.size() == 2) {
auto ivertex = _targets.begin();
@ -1734,24 +1874,25 @@ namespace Anabatic {
_mode = Mode::Standart;
}
}
#endif
if (not firstSource) {
// Standart routing.
bool hasDevice = false;
for ( Vertex* ivertex : _targets ) {
if (ivertex->getGCell()->isDevice()) hasDevice = true;
for ( Vertex* vertex : drivers ) {
if (vertex->getGCell()->isDevice()) hasDevice = true;
}
Point areaCenter;
if (hasDevice) areaCenter = _getPonderedPoint();
else areaCenter = _searchArea.getCenter();
auto ivertex = _targets.begin();
auto ivertex = drivers.begin();
firstSource = *ivertex++;
DbU::Unit minDistance = areaCenter.manhattanDistance( firstSource->getCenter() );
for ( ; ivertex != _targets.end() ; ++ivertex ) {
for ( ; ivertex != drivers.end() ; ++ivertex ) {
DbU::Unit distance = areaCenter.manhattanDistance( (*ivertex)->getCenter() );
if (distance < minDistance) {
minDistance = distance;
@ -2060,6 +2201,7 @@ namespace Anabatic {
if (_sources.size() < 2) { cdebug_tabw(112,-1); return; }
DbU::Unit gWL = 0;
NetRoutingState* state = NetRoutingExtension::get( _net );
//cerr << "state: " << state << endl;
@ -2090,8 +2232,8 @@ namespace Anabatic {
vector<Edge*> aligneds;
aligneds.push_back( from );
Vertex* target = source->getPredecessor();
Interval constraint = from->getSide();
Vertex* target = source->getPredecessor();
Interval constraint = from->getSide();
source->setFrom( NULL );
cdebug_log(112,0) << "| " << target << endl;
@ -2150,6 +2292,8 @@ namespace Anabatic {
, constraint.getCenter()
, width
);
gWL += segment->getLength();
cdebug_log(112,0) << "| ref: " << segment << endl;
for ( Edge* through : aligneds ) through->add( segment );
if (state) {
@ -2168,6 +2312,8 @@ namespace Anabatic {
, constraint.getCenter()
, width
);
gWL += segment->getLength();
cdebug_log(112,0) << "| ref: " << segment << endl;
for ( Edge* through : aligneds ) through->add( segment );
if (state) {
@ -2184,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);
}
@ -2330,51 +2484,66 @@ namespace Anabatic {
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 );
//cdebug_log(112,0) << "state: " << state << endl;
if ((state != NULL)&&(segment!=NULL)){
if (state and segment) {
Horizontal* h = dynamic_cast<Horizontal*>(segment);
Vertical* v = dynamic_cast<Vertical*>(segment);
Point sp, tp;
DbU::Unit axis;
Component* sourceContact = segment->getSource();
Component* targetContact = segment->getTarget();
if (h){
if (state->isSymHorizontal()){
cdebug_log(112,0) << "H case Horizontal" << endl;
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) << "H case Vertical" << endl;
sp = Point( state->getSymValue(targetContact->getX()), targetContact->getY() );
tp = Point( state->getSymValue(sourceContact->getX()), sourceContact->getY() );
Vertical* v = dynamic_cast<Vertical *>(segment);
Point sp;
Point tp;
DbU::Unit axis;
Component* sourceContact = segment->getSource();
Component* targetContact = segment->getTarget();
cdebug_log(112,0) << "source: " << sourceContact << endl;
cdebug_log(112,0) << "target: " << targetContact << endl;
cdebug_log(112,0) << "sym axis: " << DbU::getValueString(state->getSymAxis()) << endl;
if (h) {
if (state->isSymHorizontal()) {
cdebug_log(112,0) << "Horizontal + Horizontal symmetry." << endl;
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();
} 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;
}
//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* 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* tvertex = tgcell->getObserver<Vertex>(GCell::Observable::Vertex);
Contact* sourceSym = NULL;
Contact* targetSym = NULL;
if (state->isSelfSym()){
cdebug_log(112,0) << "isSelfSym" << endl;
if (state->isSelfSym()) {
cdebug_log(112,0) << "Symmetrical to myself (isSelfSym)." << endl;
sourceSym = svertex->getGContact( _net );
targetSym = tvertex->getGContact( _net );
} 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() );
targetSym = tvertex->getGContact( state->getSymNet() );
} 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;
}
@ -2386,7 +2555,7 @@ namespace Anabatic {
, axis
, 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) {
if (state->isSymVertical()){
//cerr << "V case Vertical" << endl;
@ -2400,6 +2569,7 @@ namespace Anabatic {
axis = segment->getX();
} else {
cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong here. " << endl;
cdebug_tabw(112,-1);
return;
}
GCell* sgcell = _anabatic->getGCellUnder( sp );
@ -2416,6 +2586,7 @@ namespace Anabatic {
targetSym = tvertex->getGContact( state->getSymNet() );
} else {
cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong with the symmetry. " << endl;
cdebug_tabw(112,-1);
return;
}
@ -2430,6 +2601,7 @@ namespace Anabatic {
cdebug_log(112,0) << "|| " << segment2 << endl;
}
}
cdebug_tabw(112,-1);
}

View File

@ -29,16 +29,31 @@ namespace {
using namespace std;
using namespace Hurricane;
using Anabatic::NetData;
using Anabatic::AnabaticEngine;
class SortSegmentByLength {
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 )
{
NetData* lhsNData = _anabatic->getNetData( lhs->getNet() );
NetData* rhsNData = _anabatic->getNetData( rhs->getNet() );
if (lhsNData->isGlobalFixed() and not rhsNData->isGlobalFixed()) return true;
if (rhsNData->isGlobalFixed() and not lhsNData->isGlobalFixed()) return false;
DbU::Unit delta = rhs->getLength() - lhs->getLength();
if (delta > 0) return true;
if (delta < 0) return false;
@ -358,12 +373,13 @@ namespace Anabatic {
AnabaticEngine* anabatic = getAnabatic();
size_t netCount = 0;
sort( _segments.begin(), _segments.end(), SortSegmentByLength() );
sort( _segments.begin(), _segments.end(), SortSegmentByLength(anabatic) );
if (Session::getRoutingGauge()->isTwoMetals()) {
for ( size_t i=0 ; i<_segments.size() ; ) {
if (not isEnding(_segments[i])) {
NetData* netData = anabatic->getNetData( _segments[i]->getNet() );
if (netData->isGlobalFixed ()) break;
if (netData->isGlobalRouted()) ++netCount;
anabatic->ripup( _segments[i], Flags::Propagate );
continue;
@ -374,6 +390,7 @@ namespace Anabatic {
size_t truncate = (size_t)( (getCapacity()*2) / 3 );
while ( _segments.size() > truncate ) {
NetData* netData = anabatic->getNetData( _segments[truncate]->getNet() );
if (netData->isGlobalFixed ()) break;
if (netData->isGlobalRouted()) ++netCount;
anabatic->ripup( _segments[truncate], Flags::Propagate );
}

View File

@ -306,6 +306,7 @@ namespace Anabatic {
, _fragmentations(new float [_depth])
, _globalsCount (new float [_depth])
, _key (this,1)
, _lastClonedKey (NULL)
{
if (not _matrixHSide) {
_matrixVSide = Session::getSliceHeight();
@ -475,6 +476,26 @@ namespace Anabatic {
}
bool GCell::hasNet ( const Net* net ) const
{
if (hasGContact(net)) return true;
for ( Edge* edge : _eastEdges ) {
for ( Segment* segment : edge->getSegments() ) {
if (segment->getNet() == net) return true;
}
}
for ( Edge* edge : _northEdges ) {
for ( Segment* segment : edge->getSegments() ) {
if (segment->getNet() == net) return true;
}
}
return false;
}
Contact* GCell::hasGContact ( const Contact* owned ) const
{
for ( Contact* contact : _gcontacts ) {
@ -507,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
{
for ( Edge* edge : getEdges(sideHint) ) {
@ -1312,7 +1349,7 @@ namespace Anabatic {
_blockages[depth] += length;
_flags |= Flags::Invalidated;
cdebug_log(149,0) << "GCell:addBlockage() " << this << " "
cdebug_log(149,0) << "GCell::addBlockage() " << this << " "
<< depth << ":" << DbU::getValueString(_blockages[depth]) << endl;
}
@ -1490,7 +1527,14 @@ namespace Anabatic {
}
// 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.
if (not processeds.empty()) {
@ -1739,7 +1783,7 @@ namespace Anabatic {
bool GCell::stepNetDesaturate ( size_t depth, set<Net*>& globalNets, GCell::Set& invalidateds )
{
cdebug_log(9000,0) << "Deter| GCell::stepNetDesaturate() depth:" << depth << endl;
cdebug_log(149,0) << "GCell::stepNetDesaturate() depth:" << depth << endl;
cdebug_log(9000,0) << "Deter| " << this << endl;
updateDensity();
@ -1761,7 +1805,7 @@ namespace Anabatic {
if (segmentDepth < depth) continue;
if (segmentDepth > depth) break;
cdebug_log(9000,0) << "Deter| Move up " << (*isegment) << endl;
cdebug_log(149,0) << "Move up " << (*isegment) << endl;
if (getAnabatic()->moveUpNetTrunk(*isegment,globalNets,invalidateds))
return true;
@ -1826,7 +1870,7 @@ namespace Anabatic {
ostringstream s;
const Layer* layer = rg->getRoutingLayer(depth)->getBlockageLayer();
s << "_blockages[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
record->add( getSlot ( s.str(), &_blockages[depth] ) );
record->add( DbU::getValueSlot( s.str(), &_blockages[depth] ) );
}
for ( size_t depth=0 ; depth<_depth ; ++depth ) {

View File

@ -335,9 +335,55 @@ namespace Anabatic {
cmess1 << " o Desaturate layer "
<< Session::getRoutingGauge()->getRoutingLayer(depth)->getName() << endl;
cdebug_log(149,0) << "Session::getSaturateRatio()=" << Session::getSaturateRatio() << endl;
GCellKeyQueue queue;
GCell::Set invalidateds;
for ( GCell* gcell : getGCells() ) queue.push( gcell->cloneKey(depth) );
bool optimized = true;
bool finished = false;
while ( optimized ) {
Session::revalidate ();
optimized = false;
while ( not queue.empty() ) {
GCell::Key* topKey = queue.top();
GCell* gcell = const_cast<GCell*>( topKey->getGCell() );
queue.pop();
if (topKey->isActive()) {
cdebug_log(149,0) << "_desaturate: [" << depth << "]:"
<< gcell->getDensity(depth) << " " << gcell << endl;
if (not gcell->isSaturated(depth)) {
cdebug_log(149,0) << "STOP desaturated: " << gcell << endl;
finished = true;
} else {
if (finished) {
cparanoid << "[ERROR] Still saturated: " << gcell << endl;
}
}
if (not finished) {
optimized = gcell->stepNetDesaturate( depth, globalNets, invalidateds );
if (optimized) {
for ( GCell* gcell : invalidateds ) {
queue.push( gcell->cloneKey(depth) );
}
}
}
}
delete topKey;
}
}
#if OLD_QUEUE_DISABLED
GCellDensitySet queue ( depth, getGCells() );
GCell::Set invalidateds;
GCell::Set invalidateds;
bool optimized = true;
while ( optimized ) {
@ -371,6 +417,7 @@ namespace Anabatic {
}
}
}
#endif
}
@ -707,7 +754,7 @@ namespace Anabatic {
if (not segment->isStrongTerminal()) locals.push_back( segment );
continue;
}
if ( (segment->getLength() < 3*Session::getSliceHeight()) and (segment != seed) ) {
if ( (segment->getAnchoredLength() < 3*Session::getSliceHeight()) and (segment != seed) ) {
locals.push_back( segment );
continue;
}

View File

@ -228,22 +228,44 @@ namespace Anabatic {
void NetBuilder::getPositions ( Component* anchor, Point& source, Point& target )
{
Segment* segment = dynamic_cast<Segment*>( anchor );
Segment* segment = dynamic_cast<Segment*>( anchor );
if (segment) {
source = segment->getSourcePosition();
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 (rp) {
source = rp->getSourcePosition();
target = rp->getTargetPosition();
return;
}
if (source == target) return;
if (source.getX() > target.getX()) swap( source, target );
if (source.getY() > target.getY()) swap( source, target );
source = anchor->getPosition();
target = anchor->getPosition();
if (not Session::getRoutingGauge()->isSymbolic()) {
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() ) {
cdebug_log(145,0) << "Hook: " << hook << 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;
<< "[" << (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;
Segment* toSegment = dynamic_cast<Segment*>( hook->getComponent() );
if (toSegment) {
@ -507,6 +529,16 @@ namespace Anabatic {
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;
}
@ -543,6 +575,15 @@ namespace Anabatic {
void NetBuilder::construct ()
{
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()) {
_southWestContact = NULL;
@ -562,7 +603,11 @@ namespace Anabatic {
case Conn_1G_2M1:
case Conn_1G_3M1:
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.
case Conn_1G_1M2:
@ -582,17 +627,31 @@ namespace Anabatic {
case Conn_2G_3M1:
case Conn_2G_4M1:
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_2M1:
case Conn_3G_3M1:
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_3M3:
case Conn_3G_4M3:
case Conn_4G_1M1: if (_do_xG_1M1()) break;
case Conn_4G_2M1:
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.
case Conn_4G_1M2: if (_do_4G_1M2()) break;
@ -616,17 +675,28 @@ namespace Anabatic {
case Conn_4G: _do_xG(); break;
// End xG cascaded cases.
// Optimized specific cases.
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_3G_1PinM2: _do_xG_1PinM2 (); break;
case Conn_1G_1PinM3: _do_1G_1PinM3 (); break;
case Conn_2G_1PinM3:
case Conn_3G_1PinM3: _do_xG_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;
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_3G_1PinM2: _do_xG_1PinM2 (); break;
case Conn_1G_1PinM3: _do_1G_1PinM3 (); break;
case Conn_2G_1PinM3:
case Conn_3G_1PinM3: _do_xG_1PinM3 (); break;
case Conn_1G_1M1_1PinM3: _do_1G_1M1_1PinM3(); break;
case Conn_1G_1M1_1PinM2:
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:
if (not isTwoMetals())
throw Bug( "Unmanaged Configuration [%d] = [%d+%d+%d+%d,%d+%d] %s in %s\n"
@ -1068,7 +1138,42 @@ namespace Anabatic {
return false;
}
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 ()
{
throw Error ( "%s::_do_globalSegment() method *not* reimplemented from base class.", getTypeName().c_str() );
@ -2261,8 +2366,10 @@ namespace Anabatic {
size_t degree = routingPads.getSize();
if (degree == 0) {
cmess2 << Warning("Net \"%s\" do not have any RoutingPad (ignored)."
,getString(net->getName()).c_str()) << endl;
if (not net->isBlockage()) {
cmess2 << Warning( "Net \"%s\" do not have any RoutingPad (ignored)."
, getString(net->getName()).c_str() ) << endl;
}
cdebug_tabw(145,-1);
return;
}

View File

@ -95,9 +95,6 @@ namespace Anabatic {
getPositions( rp, sourcePosition, targetPosition );
if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition );
if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition );
GCell* sourceGCell = Session::getAnabatic()->getGCellUnder( sourcePosition );
GCell* targetGCell = Session::getAnabatic()->getGCellUnder( targetPosition );
@ -111,6 +108,53 @@ namespace Anabatic {
if ( ((rpDepth != 0) or (sourcePosition == targetPosition)) and not (flags & NoProtect) ) {
map<Component*,AutoSegment*>::iterator irp = getRpLookup().find( rp );
if (irp == getRpLookup().end()) {
Box rpBb = rp->getBoundingBox();
if (rpDepth != 0) {
DbU::Unit hborder = 0;
DbU::Unit vborder = 0;
if (direction.contains(Flags::Horizontal)) {
vborder = Session::getWireWidth(rpDepth) / 2;
rpBb.inflate( hborder, vborder );
if (not rpBb.isEmpty()) {
DbU::Unit trackAxis = Session::getNearestTrackAxis( rp->getLayer()
, sourcePosition.getY()
, Constant::Nearest );
if (trackAxis != sourcePosition.getY()) {
cerr << Warning( "NetBuilderHV::doRp_AutoContacts(): Adjust Y position to nearest H track of %s\n"
" (%s -> %s)"
, getString(rp).c_str()
, DbU::getValueString(sourcePosition.getY()).c_str()
, DbU::getValueString(trackAxis).c_str()
) << endl;
sourcePosition.setY( trackAxis );
targetPosition.setY( trackAxis );
}
} else {
cdebug_log(145,0) << "rpBb is too narrow to adjust: " << rp->getBoundingBox() << endl;
}
} else {
hborder = Session::getWireWidth(rpDepth) / 2;
rpBb.inflate( hborder, vborder );
if (not rpBb.isEmpty()) {
DbU::Unit trackAxis = Session::getNearestTrackAxis( rp->getLayer()
, sourcePosition.getX()
, Constant::Nearest );
if (trackAxis != sourcePosition.getX()) {
cerr << Warning( "NetBuilderHV::doRp_AutoContacts(): Adjust X position to nearest V track of %s\n"
" (%s -> %s)"
, getString(rp).c_str()
, DbU::getValueString(sourcePosition.getX()).c_str()
, DbU::getValueString(trackAxis).c_str()
) << endl;
sourcePosition.setX( trackAxis );
targetPosition.setX( trackAxis );
}
} else {
cdebug_log(145,0) << "rpBb is too narrow to adjust: " << rp->getBoundingBox() << endl;
}
}
}
AutoContact* sourceProtect = AutoContactTerminal::create( sourceGCell
, rp
, rpLayer
@ -168,9 +212,9 @@ namespace Anabatic {
{
cdebug_log(145,1) << getTypeName() << "::doRp_Access() - flags:" << flags << endl;
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
AutoContact* rpSourceContact;
AutoContact* rpContactTarget;
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
Flags useNonPref = Flags::NoFlags;
if (flags & UseNonPref) useNonPref |= Flags::UseNonPref;
@ -239,6 +283,22 @@ namespace Anabatic {
AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical );
} else {
#if OFFGRID_M2_DISABLED
Box cellAb = getAnabatic()->getCell()->getAbutmentBox();
RoutingLayerGauge* lgM2 = Session::getLayerGauge( 1 );
DbU::Unit trackAxis = lgM2->getTrackPosition( cellAb.getYMin()
, cellAb.getYMax()
, rp->getY()
, Constant::Nearest );
bool offGrid = (trackAxis != rp->getY());
if (offGrid) {
cdebug_log(145,0) << "Off grid, Misaligned M2 RoutingPad, add vertical strap" << endl;
subContact1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical );
rpSourceContact = subContact1;
}
#endif
subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, subContact1, Flags::Horizontal );
}
@ -251,6 +311,79 @@ namespace Anabatic {
}
AutoContact* NetBuilderHV::doRp_AccessNorthPin ( GCell* gcell, RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_AccessNorthPin() " << rp << endl;
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
AutoContact* turn = NULL;
doRp_AutoContacts( gcell, rp, rpSourceContact, rpContactTarget, NoProtect );
Net* net = rp->getNet();
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
if (pinDir == Pin::AccessDirection::NORTH) {
turn = AutoContactTurn::create( gcell, net, Session::getRoutingLayer(1) );
AutoSegment* segment = AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
segment->setAxis( rp->getX(), Flags::Force );
segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
rpSourceContact = turn;
turn = AutoContactTurn::create( gcell, net, Session::getContactLayer(1) );
segment = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
rpSourceContact = turn;
DbU::Unit axis = gcell->getYMax() - Session::getDHorizontalPitch();
cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl;
segment->setAxis( axis, Flags::Force );
//segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
cdebug_log(145,0) << segment << endl;
} else {
turn = rpSourceContact;
}
cdebug_tabw(145,-1);
return turn;
}
AutoContact* NetBuilderHV::doRp_AccessEastWestPin ( GCell* gcell, RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_AccessNorthPin() " << rp << endl;
Net* net = rp->getNet();
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
AutoContact* turn = NULL;
AutoSegment* segment = NULL;
doRp_AutoContacts( gcell, rp, rpSourceContact, rpContactTarget, NoProtect );
turn = AutoContactTurn::create( gcell, net, Session::getContactLayer(1) );
segment = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
segment->setAxis( pin->getCenter().getY(), Flags::Force );
rpSourceContact = turn;
turn = AutoContactTurn::create( gcell, net, Session::getContactLayer(1) );
segment = AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
DbU::Unit axis = 0;
if (pinDir == Pin::AccessDirection::EAST)
axis = gcell->getXMax() - Session::getDVerticalPitch();
else
axis = gcell->getXMin() + Session::getDVerticalPitch();
segment->setAxis( axis );
cdebug_tabw(145,-1);
return turn;
}
bool NetBuilderHV::_do_1G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1() [Managed Configuration - Optimized] " << getTopology() << endl;
@ -487,7 +620,7 @@ namespace Anabatic {
doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoFlags );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn1, Flags::Horizontal );
if (east() or west()) {
@ -672,9 +805,17 @@ namespace Anabatic {
AutoSegment* vertical = AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
rpSourceContact = turn;
DbU::Unit axis = getGCell()->getXMax() - Session::getDVerticalPitch();
Box cellAb = getAnabatic()->getCell()->getAbutmentBox();
RoutingLayerGauge* lgM3 = Session::getLayerGauge( 2 );
DbU::Unit axis = lgM3->getTrackPosition( cellAb.getXMin()
, cellAb.getXMax()
, getGCell()->getXMax() - Session::getDVerticalPitch()
, Constant::Superior );
if (pinDir == Pin::AccessDirection::WEST)
axis = getGCell()->getXMin() + Session::getDVerticalPitch();
axis = lgM3->getTrackPosition( cellAb.getXMin()
, cellAb.getXMax()
, getGCell()->getXMin() + Session::getDVerticalPitch()
, Constant::Inferior );
cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl;
vertical->setAxis( axis, Flags::Force );
@ -730,6 +871,9 @@ namespace Anabatic {
AutoContact* htee2 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( htee1, htee2, Flags::Horizontal );
if (pinDir == Pin::AccessDirection::EAST)
std::swap( htee1, htee2 );
setSouthWestContact( htee1 );
setNorthEastContact( htee2 );
}
@ -744,9 +888,8 @@ namespace Anabatic {
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoFlags );
rpSourceContact = doRp_AccessNorthPin( getGCell(), getRoutingPads()[0] );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn1, Flags::Vertical );
@ -804,19 +947,28 @@ namespace Anabatic {
setSouthWestContact( turn1 );
setNorthEastContact( htee1 );
} else {
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, vtee1, Flags::Vertical );
} else if (north() and south()) {
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( vtee1, turn1, Flags::Vertical );
AutoSegment::create( rpSourceContact, turn1, Flags::Vertical );
setSouthWestContact( vtee1 );
setNorthEastContact( turn1 );
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( turn1, vtee1, Flags::Horizontal );
setBothCornerContacts( vtee1 );
} else { // Remaining case is East & West.
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, htee1, Flags::Vertical );
setBothCornerContacts( htee1 );
}
} else {
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn1, Flags::Vertical );
AutoSegment::create( turn1, turn2, Flags::Horizontal );
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, vtee1, Flags::Vertical );
AutoSegment::create( turn2, vtee1, Flags::Vertical );
AutoContact* vtee2 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( vtee1, vtee2, Flags::Vertical );
@ -830,6 +982,258 @@ namespace Anabatic {
}
bool NetBuilderHV::_do_2G_xM1_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_xM1_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
RoutingPad* pinM3 = NULL;
AutoContact* pinContact = NULL;
AutoContact* dummy = NULL;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM3 = rp;
else rpsM1.push_back( rp );
}
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
doRp_AutoContacts( getGCell(), pinM3, pinContact, dummy, NoFlags );
AutoContact* m1contact = doRp_Access( getGCell(), rpsM1.back(), HAccess );
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( m1contact , vtee1, Flags::Horizontal );
AutoSegment::create( pinContact, vtee1, Flags::Vertical );
AutoContact* vtee2 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( vtee1, vtee2, Flags::Vertical );
setBothCornerContacts( vtee2 );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_3G_xM1_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_3G_1M1_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
RoutingPad* pinM3 = NULL;
AutoContact* pinContact = NULL;
AutoContact* dummy = NULL;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM3 = rp;
else rpsM1.push_back( rp );
}
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
doRp_AutoContacts( getGCell(), pinM3, pinContact, dummy, NoFlags );
AutoContact* m1contact = doRp_Access( getGCell(), rpsM1.back(), HAccess );
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( m1contact , vtee1, Flags::Horizontal );
AutoContact* vtee2 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( vtee1, vtee2, Flags::Vertical );
AutoContact* vtee3 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( vtee2, vtee3, Flags::Vertical );
if (not south() or not north()) {
AutoSegment::create( pinContact, vtee1, Flags::Vertical );
}
if (not east() or not west()) {
AutoSegment::create( pinContact, vtee2, Flags::Horizontal );
}
if (not south()) {
setSouthWestContact( vtee2 );
setNorthEastContact( vtee3 );
} else if (not north()) {
setSouthWestContact( vtee3 );
setNorthEastContact( vtee2 );
} else if (not east()) {
setSouthWestContact( vtee3 );
setNorthEastContact( vtee1 );
} else if (not west()) {
setSouthWestContact( vtee1 );
setNorthEastContact( vtee3 );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_1G_xM1_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
RoutingPad* pinM2 = NULL;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM2 = rp;
else rpsM1.push_back( rp );
}
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
AutoContact* turn = NULL;
AutoContact* tee = NULL;
AutoContact* pinM2Contact = NULL;
AutoContact* rpM1Contact = NULL;
doRp_AutoContacts( getGCell(), pinM2, pinM2Contact, rpM1Contact, NoProtect );
rpM1Contact = doRp_Access( getGCell(), rpsM1[0], (north() or south()) ? HAccess : NoFlags );
if (north() or south()) {
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpM1Contact , tee , Flags::Horizontal );
AutoSegment::create( pinM2Contact, turn, Flags::Horizontal );
AutoSegment::create( tee , turn, Flags::Vertical );
setBothCornerContacts( tee );
} else {
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpM1Contact , tee , Flags::Vertical );
AutoSegment::create( pinM2Contact, tee , Flags::Horizontal );
AutoSegment::create( tee , turn, Flags::Vertical );
setBothCornerContacts( turn );
}
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_2G_xM1_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_xM1_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
RoutingPad* pinM2 = NULL;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM2 = rp;
else rpsM1.push_back( rp );
}
AutoContact* pinM2Contact = NULL;
AutoContact* rpM1Contact = NULL;
doRp_AutoContacts( getGCell(), pinM2, pinM2Contact, rpM1Contact, NoFlags );
rpM1Contact = doRp_Access( getGCell(), rpsM1[0], NoFlags );
if (north() and south()) {
cdebug_log(145,0) << "Case north & south." << endl;
AutoContact* htee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* vtee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinM2Contact, htee, Flags::Horizontal );
AutoSegment::create( rpM1Contact , htee, Flags::Vertical );
AutoSegment::create( htee , vtee, Flags::Horizontal );
setBothCornerContacts( vtee );
} else if (east() and west()) {
cdebug_log(145,0) << "Case east & west." << endl;
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* htee2 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinM2Contact, htee1, Flags::Horizontal );
AutoSegment::create( rpM1Contact , htee1, Flags::Vertical );
AutoSegment::create( htee1 , turn , Flags::Horizontal );
AutoSegment::create( htee2 , turn , Flags::Vertical );
setBothCornerContacts( htee2 );
} else {
cdebug_log(145,0) << "Case bend." << endl;
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* htee2 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinM2Contact, vtee1, Flags::Horizontal );
AutoSegment::create( rpM1Contact , vtee1, Flags::Vertical );
AutoSegment::create( vtee1 , turn1, Flags::Vertical );
AutoSegment::create( turn1 , htee2, Flags::Horizontal );
setBothCornerContacts( htee2 );
}
cdebug_log(145,0) << "Wiring all M1 together." << endl;
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_1G_1M1_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpSourceContact = NULL;
RoutingPad* pinM3 = getRoutingPads()[0];
RoutingPad* rpM1 = getRoutingPads()[1];
if (dynamic_cast<Pin*>(rpM1->getOccurrence().getEntity())) std::swap( rpM1, pinM3 );
AutoContact* contact1 = doRp_Access( getGCell(), rpM1, HAccess );
AutoContact* htee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( contact1, htee, Flags::Horizontal );
rpSourceContact = doRp_AccessNorthPin( getGCell(), pinM3 );
if (north() or south()) {
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
AutoSegment::create( turn , htee, Flags::Horizontal );
} else {
AutoSegment::create( rpSourceContact, htee, Flags::Vertical );
}
setBothCornerContacts( htee );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_2G_1M1 ()
{
return _do_xG_1M1();
@ -854,9 +1258,12 @@ namespace Anabatic {
if (getConnexity().fields.globals == 2) {
if (north() and south()) {
AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess );
AutoContact* contact2 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
AutoContact* contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Horizontal );
setBothCornerContacts( contact2 );
contact1 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( contact1, contact2, Flags::Horizontal );
setNorthEastContact( contact1 );
setSouthWestContact( contact2 );
} else if (east() and west()) {
// AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], NoFlags );
// AutoContact* contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
@ -1216,6 +1623,20 @@ namespace Anabatic {
const Layer* viaLayer1 = Session::getContactLayer(1);
Box cellAb = getAnabatic()->getCell()->getAbutmentBox();
RoutingLayerGauge* lgM3 = Session::getLayerGauge( 2 );
DbU::Unit trackAxis = lgM3->getTrackPosition( cellAb.getXMin()
, cellAb.getXMax()
, getRoutingPads()[0]->getX()
, Constant::Nearest );
bool offGrid = (trackAxis != getRoutingPads()[0]->getX());
if (offGrid) {
cdebug_log(145,0) << "Off grid, Misaligned M3, add horizontal strap" << endl;
AutoContactTurn* turn1 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( getSouthWestContact(), turn1, Flags::Horizontal );
setBothCornerContacts( turn1 );
}
if (flags & HAccess) {
// HARDCODED VALUE.
if (getRoutingPads()[0]->getBoundingBox().getHeight() < 3*Session::getPitch(1)) {
@ -1225,14 +1646,15 @@ namespace Anabatic {
setBothCornerContacts( subContact );
}
} else {
if (getSourceContact()) {
if (getSourceContact()->getX() != getSouthWestContact()->getX()) {
AutoContactTurn* turn1 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoContactTurn* turn2 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment::create( getSouthWestContact(), turn1, Flags::Vertical );
AutoSegment::create( turn1 , turn2, Flags::Horizontal );
setBothCornerContacts( turn2 );
}
if (getSourceContact() and (getSourceContact()->getX() != getSouthWestContact()->getX())) {
cdebug_log(145,0) << "On grid, Misaligned M3, add dogleg" << endl;
AutoContactTurn* turn1 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoContactTurn* turn2 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
AutoSegment* v1 = AutoSegment::create( getSouthWestContact(), turn1, Flags::Vertical );
AutoSegment::create( turn1, turn2, Flags::Horizontal );
v1->setAxis( getSouthWestContact()->getX(), Flags::Force );
v1->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
setBothCornerContacts( turn2 );
}
}
cdebug_tabw(145,-1);
@ -1329,7 +1751,7 @@ namespace Anabatic {
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getLength() < 2*Session::getSliceHeight()) )
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
addToFixSegments( globalSegment );
if (getConnexity().fields.globals < 2) {
@ -1349,6 +1771,135 @@ namespace Anabatic {
}
void NetBuilderHV::singleGCell ( AnabaticEngine* anbt, Net* net )
{
cdebug_log(145,1) << "NetBuilderHV::singleGCell() " << net << endl;
vector<RoutingPad*> rpM1s;
Component* rpM2 = NULL;
RoutingPad* rpPin = NULL;
for ( RoutingPad* rp : net->getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) {
rpPin = rp;
continue;
}
if (Session::getRoutingGauge()->getLayerDepth(rp->getLayer()) == 1)
rpM2 = rp;
else
rpM1s.push_back( rp );
}
if ( (rpM1s.size() < 2) and not (rpM2 or rpPin) ) {
cerr << Error( "For %s, less than two Plugs/Pins (%d)."
, getString(net).c_str()
, rpM1s.size() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (rpM1s.empty()) {
cerr << Error( "No METAL1 in Single GCell for Net \"%s\".", getString(net->getName()).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
sortRpByX( rpM1s, NetBuilder::NoFlags ); // increasing X.
GCell* gcell1 = anbt->getGCellUnder( (*rpM1s.begin ())->getCenter() );
GCell* gcell2 = anbt->getGCellUnder( (*rpM1s.rbegin())->getCenter() );
if (not gcell1) {
cerr << Error( "No GCell under %s.", getString(*(rpM1s.begin())).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (gcell1 != gcell2) {
cerr << Error( "Not under a single GCell %s.", getString(*(rpM1s.rbegin())).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
cdebug_log(145,0) << "singleGCell " << gcell1 << endl;
AutoContact* turn1 = NULL;
AutoContact* turn2 = NULL;
AutoContact* source = NULL;
AutoContact* target = NULL;
for ( size_t irp=1 ; irp<rpM1s.size() ; ++irp ) {
doRp_AutoContacts( gcell1, rpM1s[irp-1], source, turn1, DoSourceContact );
doRp_AutoContacts( gcell1, rpM1s[irp ], target, turn1, DoSourceContact );
if (source->getUConstraints(Flags::Vertical).intersect(target->getUConstraints(Flags::Vertical))) {
uint64_t flags = checkRoutingPadSize( rpM1s[irp-1] );
if ((flags & VSmall) or Session::getConfiguration()->isVH()) {
if (Session::getConfiguration()->isHV()) {
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( source, turn1, Flags::Horizontal );
source = turn1;
}
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( source, turn1 , Flags::Vertical );
source = turn1;
}
flags = checkRoutingPadSize( rpM1s[irp] );
if ((flags & VSmall) or Session::getConfiguration()->isVH()) {
if (Session::getConfiguration()->isHV()) {
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( target, turn1, Flags::Horizontal );
target = turn1;
}
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( target, turn1 , Flags::Vertical );
target = turn1;
}
AutoSegment::create( source, target, Flags::Horizontal );
} else {
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
turn2 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( source, turn1 , Flags::Horizontal );
AutoSegment::create( turn1 , turn2 , Flags::Vertical );
AutoSegment::create( turn2 , target, Flags::Horizontal );
}
}
if (rpM2) {
doRp_AutoContacts( gcell1, rpM1s[0], source, turn1, DoSourceContact );
doRp_AutoContacts( gcell1, rpM2 , target, turn1, DoSourceContact );
turn1 = AutoContactTurn::create( gcell1, rpM2->getNet(), Session::getContactLayer(1) );
AutoSegment::create( source, turn1 , Flags::Horizontal );
AutoSegment::create( turn1 , target, Flags::Vertical );
}
if (rpPin) {
Pin* pin = dynamic_cast<Pin*>( rpPin->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
if ( (pinDir == Pin::AccessDirection::NORTH)
or (pinDir == Pin::AccessDirection::SOUTH) ) {
doRp_AutoContacts( gcell1, rpM1s[0], source, turn1, DoSourceContact );
target = doRp_AccessNorthPin( gcell1, rpPin );
turn1 = AutoContactTurn::create( gcell1, rpPin->getNet(), Session::getContactLayer(1) );
AutoSegment::create( source, turn1 , Flags::Horizontal );
AutoSegment::create( turn1 , target, Flags::Vertical );
} else {
RoutingPad* closest = NULL;
if (pinDir == Pin::AccessDirection::EAST) closest = rpM1s.back();
else closest = rpM1s.front();
doRp_AutoContacts( gcell1, closest, source, turn1, DoSourceContact );
target = doRp_AccessEastWestPin( gcell1, rpPin );
AutoSegment::create( source, target , Flags::Horizontal );
}
}
cdebug_tabw(145,-1);
}
string NetBuilderHV::getTypeName () const
{ return "NetBuilderHV"; }

View File

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

View File

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

View File

@ -82,7 +82,12 @@ namespace Anabatic {
, _segmentRevalidateds()
, _netInvalidateds ()
, _netRevalidateds ()
{ }
{
_autoContacts .reserve( 1024 );
_doglegs .reserve( 1024 );
_segmentInvalidateds.reserve( 1024 );
_segmentRevalidateds.reserve( 1024 );
}
void Session::_postCreate ()
@ -219,7 +224,9 @@ namespace Anabatic {
}
_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->isUnsetAxis()) segment->toOptimalAxis();
else segment->toConstraintAxis();
@ -252,6 +259,8 @@ namespace Anabatic {
cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl;
_segmentRevalidateds.clear();
std::sort( _segmentInvalidateds.begin(), _segmentInvalidateds.end()
, AutoSegment::CompareByRevalidate() );
for ( size_t i=0 ; i < _segmentInvalidateds.size() ; ++i, ++count ) {
_segmentInvalidateds[i]->revalidate();
if ( not _destroyedSegments.empty()
@ -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 )
{
Box ab = _anabatic->getCell()->getAbutmentBox();

View File

@ -14,20 +14,16 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_ANABATIC_ENGINE_H
#define ANABATIC_ANABATIC_ENGINE_H
#pragma once
#include <memory>
#include <string>
#include <vector>
#include <set>
#include "hurricane/NetRoutingProperty.h"
namespace Hurricane {
class Instance;
class CellViewer;
}
#include "crlcore/ToolEngine.h"
#include "anabatic/Configuration.h"
#include "anabatic/Matrix.h"
@ -104,9 +100,10 @@ namespace Anabatic {
class NetData {
public:
NetData ( Net* );
NetData ( Net*, AnabaticEngine* );
inline bool isGlobalEstimated () const;
inline bool isGlobalRouted () const;
inline bool isGlobalFixed () const;
inline bool isMixedPreRoute () const;
inline bool isFixed () const;
inline bool isExcluded () const;
@ -115,11 +112,13 @@ namespace Anabatic {
inline const Box& getSearchArea () const;
inline DbU::Unit getHalfPerimeter () const;
inline size_t getRpCount () const;
inline size_t getDiodeRpCount () const;
inline DbU::Unit getSparsity () const;
inline void setNetRoutingState ( NetRoutingState* );
inline void setSearchArea ( Box );
inline void setGlobalEstimated ( bool );
inline void setGlobalRouted ( bool );
inline void setGlobalFixed ( bool );
inline void setExcluded ( bool );
inline void setRpCount ( size_t );
private:
@ -131,6 +130,7 @@ namespace Anabatic {
NetRoutingState* _state;
Box _searchArea;
size_t _rpCount;
size_t _diodeCount;
DbU::Unit _sparsity;
Flags _flags;
};
@ -138,6 +138,7 @@ namespace Anabatic {
inline bool NetData::isGlobalEstimated () const { return _flags & Flags::GlobalEstimated; }
inline bool NetData::isGlobalRouted () const { return _flags & Flags::GlobalRouted; }
inline bool NetData::isGlobalFixed () const { return _flags & Flags::GlobalFixed; }
inline bool NetData::isMixedPreRoute () const { return (_state) ? _state->isMixedPreRoute() : false; }
inline bool NetData::isFixed () const { return (_state) ? _state->isFixed () : false; }
inline bool NetData::isExcluded () const { return _flags & Flags::ExcludeRoute; }
@ -146,10 +147,12 @@ namespace Anabatic {
inline const Box& NetData::getSearchArea () const { return _searchArea; }
inline DbU::Unit NetData::getHalfPerimeter () const { return (_searchArea.isEmpty()) ? 0.0 : (_searchArea.getWidth()+_searchArea.getHeight()); }
inline size_t NetData::getRpCount () const { return _rpCount; }
inline size_t NetData::getDiodeRpCount () const { return _diodeCount; }
inline void NetData::setNetRoutingState ( NetRoutingState* state ) { _state=state; }
inline DbU::Unit NetData::getSparsity () const { return _sparsity; }
inline void NetData::setGlobalEstimated ( bool state ) { _flags.set(Flags::GlobalEstimated,state); }
inline void NetData::setGlobalRouted ( bool state ) { _flags.set(Flags::GlobalRouted ,state); }
inline void NetData::setGlobalFixed ( bool state ) { _flags.set(Flags::GlobalFixed ,state); }
inline void NetData::setExcluded ( bool state ) { _flags.set(Flags::ExcludeRoute ,state); }
inline void NetData::setRpCount ( size_t count ) { _rpCount=count; _update(); }
@ -199,6 +202,7 @@ namespace Anabatic {
static const Name& staticGetName ();
virtual const Name& getName () const;
virtual Configuration* getConfiguration ();
virtual const Configuration* getConfiguration () const;
inline uint64_t getDensityMode () const;
inline CellViewer* getViewer () const;
inline void setViewer ( CellViewer* );
@ -226,6 +230,7 @@ namespace Anabatic {
void exclude ( const Name& netName );
void exclude ( Net* );
void updateMatrix ();
bool checkPlacement () const;
// Dijkstra related functions.
inline int getStamp () const;
inline int incStamp ();
@ -243,10 +248,13 @@ namespace Anabatic {
inline bool doDestroyBaseContact () const;
inline bool doDestroyBaseSegment () const;
inline bool doDestroyTool () const;
inline DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getAntennaDiodeMaxWL () const;
inline DbU::Unit getGlobalThreshold () const;
inline float getSaturateRatio () const;
inline size_t getSaturateRp () const;
inline DbU::Unit getExtensionCap () const;
inline Cell* getDiodeCell () const;
inline Net* getBlockageNet () const;
inline const ChipTools& getChipTools () const;
inline const vector<NetData*>& getNetOrdering () const;
@ -259,6 +267,8 @@ namespace Anabatic {
inline void setBlockageNet ( Net* );
void chipPrep ();
void computeEdgeCapacities ( int maxHCap, int maxVCap, int termSatThreshold, int maxTermSat );
void antennaProtect ( Net*, uint32_t& failed, uint32_t& total );
void antennaProtect ();
void setupSpecialNets ();
size_t setupPreRouteds ();
void loadGlobalRouting ( uint32_t method );
@ -268,6 +278,7 @@ namespace Anabatic {
bool moveUpNetTrunk ( AutoSegment*, set<Net*>& globalNets, GCell::Set& invalidateds );
void layerAssign ( uint32_t method );
void finalizeLayout ();
void exportExternalNets ();
inline const AutoContactLut& _getAutoContactLut () const;
inline const AutoSegmentLut& _getAutoSegmentLut () const;
void _link ( AutoContact* );
@ -336,6 +347,7 @@ namespace Anabatic {
AutoContactLut _autoContactLut;
EdgeCapacityLut _edgeCapacitiesLut;
Net* _blockageNet;
Cell* _diodeCell;
};
@ -365,11 +377,14 @@ namespace Anabatic {
inline bool AnabaticEngine::doWarnOnGCellOverload () const { return _flags & Flags::WarnOnGCellOverload; }
inline bool AnabaticEngine::isInDemoMode () const { return _flags & Flags::DemoMode; }
inline bool AnabaticEngine::isChip () const { return _chipTools.isChip(); }
inline DbU::Unit AnabaticEngine::getAntennaGateMaxWL () const { return getConfiguration()->getAntennaGateMaxWL(); }
inline DbU::Unit AnabaticEngine::getAntennaDiodeMaxWL () const { return getConfiguration()->getAntennaDiodeMaxWL(); }
inline DbU::Unit AnabaticEngine::getGlobalThreshold () const { return _configuration->getGlobalThreshold(); }
inline float AnabaticEngine::getSaturateRatio () const { return _configuration->getSaturateRatio(); }
inline size_t AnabaticEngine::getSaturateRp () const { return _configuration->getSaturateRp(); }
inline void AnabaticEngine::setSaturateRatio ( float ratio ) { _configuration->setSaturateRatio(ratio); }
inline void AnabaticEngine::setSaturateRp ( size_t threshold ) { _configuration->setSaturateRp(threshold); }
inline Cell* AnabaticEngine::getDiodeCell () const { return _diodeCell; }
inline Net* AnabaticEngine::getBlockageNet () const { return _blockageNet; }
inline const ChipTools& AnabaticEngine::getChipTools () const { return _chipTools; }
inline const vector<NetData*>& AnabaticEngine::getNetOrdering () const { return _netOrdering; }
@ -417,5 +432,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::AnabaticEngine);
#endif // ANABATIC_ANABATIC_ENGINE_H

View File

@ -123,6 +123,7 @@ namespace Anabatic {
inline bool isUserNativeConstraints () const;
inline bool isHDogleg () const;
inline bool isVDogleg () const;
virtual bool isOnPin () const;
inline bool hasBadTopology () const;
bool canDestroy ( Flags flags=Flags::NoFlags ) const;
bool canMoveUp ( const AutoSegment* moved ) const;

View File

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

View File

@ -107,6 +107,7 @@ namespace Anabatic {
static const uint64_t SegShortNet = (1L<<35);
static const uint64_t SegUnbreakable = (1L<<36);
static const uint64_t SegNonPref = (1L<<37);
static const uint64_t SegAtMinArea = (1L<<38);
// Masks.
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
@ -141,6 +142,7 @@ namespace Anabatic {
inline static DbU::Unit getViaToTopCap ( size_t depth );
inline static DbU::Unit getViaToBottomCap ( size_t depth );
inline static DbU::Unit getViaToSameCap ( size_t depth );
inline static DbU::Unit getMinimalLength ( size_t depth );
static AutoSegment* create ( AutoContact* source
, AutoContact* target
, Segment* hurricaneSegment
@ -171,6 +173,8 @@ namespace Anabatic {
inline DbU::Unit getWidth () const;
inline DbU::Unit getContactWidth () const;
inline DbU::Unit getLength () const;
inline DbU::Unit getSpanLength () const;
inline DbU::Unit getAnchoredLength () const;
inline DbU::Unit getSourcePosition () const;
inline DbU::Unit getTargetPosition () const;
inline DbU::Unit getSourceX () const;
@ -198,6 +202,7 @@ namespace Anabatic {
inline bool isUnbreakable () const;
inline bool isNonPref () const;
inline bool isDrag () const;
inline bool isAtMinArea () const;
inline bool isNotSourceAligned () const;
inline bool isNotTargetAligned () const;
inline bool isNotAligned () const;
@ -205,10 +210,12 @@ namespace Anabatic {
inline bool isSourceTerminal () const;
inline bool isTargetTerminal () const;
inline bool isLayerChange () const;
inline bool isStackedStrap () const;
inline bool isSpinTop () const;
inline bool isSpinBottom () const;
inline bool isSpinTopOrBottom () const;
inline bool isReduced () const;
bool isUnderMinLength () const;
inline bool isStrap () const;
inline bool isDogleg () const;
inline bool isUnbound () const;
@ -219,13 +226,14 @@ namespace Anabatic {
inline bool isUnsetAxis () const;
inline bool isSlackened () const;
inline bool isUserDefined () const;
bool isMiddleStack () const;
bool isReduceCandidate () const;
bool isUTurn () const;
inline bool isAnalog () const;
inline bool isWide () const;
inline bool isShortNet () const;
virtual bool _canSlacken () const = 0;
bool canReduce () const;
bool canReduce ( Flags flags=Flags::WithPerpands ) const;
bool mustRaise () const;
Flags canDogleg ( Interval );
virtual bool canMoveULeft ( float reserve=0.0 ) const = 0;
@ -282,6 +290,8 @@ namespace Anabatic {
virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max );
inline AutoSegment* getCanonical ( Interval& i );
float getMaxUnderDensity ( Flags flags );
inline uint32_t getReduceds () const;
uint32_t getNonReduceds ( Flags flags=Flags::WithPerpands ) const;
// Modifiers.
inline void unsetFlags ( uint64_t );
inline void setFlags ( uint64_t );
@ -325,8 +335,11 @@ namespace Anabatic {
bool moveUp ( Flags flags=Flags::NoFlags );
bool moveDown ( Flags flags=Flags::NoFlags );
bool reduceDoglegLayer ();
bool reduce ();
bool bloatStackedStrap ();
bool reduce ( Flags flags=Flags::WithPerpands );
bool raise ();
bool expandToMinLength ( Interval );
bool unexpandToMinLength ();
// Canonical Modifiers.
AutoSegment* canonize ( Flags flags=Flags::NoFlags );
virtual void invalidate ( Flags flags=Flags::Propagate );
@ -370,7 +383,7 @@ namespace Anabatic {
static bool _analogMode;
static bool _shortNetMode;
static bool _initialized;
static vector< array<DbU::Unit*,3> > _extensionCaps;
static vector< array<DbU::Unit*,4> > _extensionCaps;
// Internal: Attributes.
const unsigned long _id;
GCell* _gcell;
@ -420,6 +433,13 @@ namespace Anabatic {
struct CompareBySourceU : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
struct CompareByRevalidate : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
struct CompareByReduceds : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
typedef std::set<AutoSegment*,CompareId> IdSet;
@ -464,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::getViaToBottomCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][1]) : 0; }
inline DbU::Unit AutoSegment::getViaToSameCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][2]) : 0; }
inline DbU::Unit AutoSegment::getMinimalLength ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][3]) : 0; }
inline unsigned long AutoSegment::getId () const { return _id; }
inline Cell* AutoSegment::getCell () const { return base()->getCell(); }
inline Net* AutoSegment::getNet () const { return base()->getNet(); }
@ -501,6 +522,7 @@ namespace Anabatic {
inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); }
inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; }
inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; }
inline uint32_t AutoSegment::getReduceds () const { return _reduceds; }
inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; }
inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); }
@ -520,6 +542,7 @@ namespace Anabatic {
inline bool AutoSegment::isTargetTerminal () const { return _flags & SegTargetTerminal; }
inline bool AutoSegment::isTerminal () const { return (_rpDistance == 0); }
inline bool AutoSegment::isDrag () const { return _flags & SegDrag; }
inline bool AutoSegment::isAtMinArea () const { return _flags & SegAtMinArea; }
inline bool AutoSegment::isNotSourceAligned () const { return _flags & SegNotSourceAligned; }
inline bool AutoSegment::isNotTargetAligned () const { return _flags & SegNotTargetAligned; }
inline bool AutoSegment::isNotAligned () const { return (_flags & SegNotAligned) == SegNotAligned; }
@ -558,7 +581,7 @@ namespace Anabatic {
inline void AutoSegment::resetNativeConstraints ( DbU::Unit min, DbU::Unit max ) { _nativeConstraints = Interval( min, max ); }
//inline void AutoSegment::mergeUserConstraints ( const Interval& constraints ) { _userConstraints.intersection(constraints); }
inline void AutoSegment::resetUserConstraints () { _userConstraints = Interval(false); }
inline DbU::Unit AutoSegment::getAnchoredLength () const { return std::abs(getTargetU() - getSourceU()); }
inline void AutoSegment::setLayer ( size_t depth )
{
@ -570,10 +593,13 @@ namespace Anabatic {
_flags|=SegInvalidatedLayer;
}
inline DbU::Unit AutoSegment::getContactWidth () const
{ return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); }
inline DbU::Unit AutoSegment::getSpanLength () const
{ return getAnchoredLength() + getExtensionCap( Flags::Source|Flags::LayerCapOnly|Flags::NoMinLength )
+ getExtensionCap( Flags::Target|Flags::LayerCapOnly|Flags::NoMinLength );
}
inline void AutoSegment::setParent ( AutoSegment* parent )
{

View File

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

View File

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

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_CONSTANTS_H
#define ANABATIC_CONSTANTS_H
#pragma once
#include "hurricane/Flags.h"
namespace Anabatic {
@ -54,9 +52,11 @@ namespace Anabatic {
static const BaseFlags DestroyBaseContact ; // = (1 << 8);
static const BaseFlags DestroyBaseSegment ; // = (1 << 9);
// Flags for NetDatas objects states only.
static const BaseFlags GlobalRouted ; // = (1 << 5);
static const BaseFlags GlobalFixed ; // = (1 << 5);
static const BaseFlags GlobalEstimated ; // = (1 << 6);
static const BaseFlags ExcludeRoute ; // = (1 << 7);
static const BaseFlags GlobalRouted ; // = (1 << 7);
static const BaseFlags DetailRouted ; // = (1 << 8);
static const BaseFlags ExcludeRoute ; // = (1 << 9);
// Masks.
static const BaseFlags WestSide ; // = Horizontal|Target;
static const BaseFlags EastSide ; // = Horizontal|Source;
@ -102,6 +102,10 @@ namespace Anabatic {
static const BaseFlags NorthPath ;
static const BaseFlags UseNonPref ;
static const BaseFlags Force ;
static const BaseFlags LayerCapOnly ;
static const BaseFlags NoMinLength ;
static const BaseFlags NoSegExt ;
static const BaseFlags NullLength ;
public:
inline Flags ( uint64_t flags = NoFlags );
inline Flags ( const Hurricane::BaseFlags& );
@ -148,6 +152,4 @@ namespace Anabatic {
} // Anabatic namespace.
INSPECTOR_PV_SUPPORT(Anabatic::Flags)
#endif // ANABATIC_CONSTANTS_H
INSPECTOR_PR_SUPPORT(Anabatic::Flags);

View File

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

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_EDGE_H
#define ANABATIC_EDGE_H
#pragma once
#include <string>
#include "hurricane/Name.h"
#include "hurricane/Interval.h"
@ -168,5 +166,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::Edge);
#endif // ANABATIC_EDGE_H

View File

@ -14,10 +14,9 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_GCELL_H
#define ANABATIC_GCELL_H
#pragma once
#include <vector>
#include <queue>
#include <string>
#include <set>
#include <functional>
@ -115,14 +114,22 @@ namespace Anabatic {
public:
class Key {
public:
inline Key ( GCell*, size_t depth );
inline float getDensity () const;
inline GCell* getGCell () const;
inline void update ( size_t depth );
friend bool operator< ( const Key&, const Key& );
inline Key ( const GCell*, size_t depth );
inline ~Key ();
inline float getDensity () const;
inline const GCell* getGCell () const;
inline bool isActive () const;
inline bool isSaturated () const;
inline void update ( size_t depth );
friend bool operator< ( const Key&, const Key& );
public:
class Compare {
public:
inline bool operator() ( const Key*, const Key* );
};
private:
GCell* _gcell;
float _density;
const GCell* _gcell;
float _density;
};
public:
static uint32_t getDisplayMode ();
@ -156,6 +163,7 @@ namespace Anabatic {
bool isEast ( GCell* ) const;
bool isNorth ( GCell* ) const;
bool isSouth ( GCell* ) const;
bool hasNet ( const Net* ) const;
Contact* hasGContact ( const Contact* ) const;
Contact* hasGContact ( const Net* ) const;
bool isHorizontalPlane ( size_t depth ) const;
@ -207,7 +215,8 @@ namespace Anabatic {
bool doGrid ();
Contact* getGContact ( Net* );
inline const vector<Contact*>& getGContacts () const;
Contact* breakGoThrough ( Net* net );
Segment* hasGoThrough ( Net* ) const;
Contact* breakGoThrough ( Net* );
bool unrefContact ( Contact* );
void setSouthWestCorner ( DbU::Unit x, DbU::Unit y );
void cleanupGlobal ();
@ -242,6 +251,9 @@ namespace Anabatic {
inline AutoSegments getStopSegments ( Flags direction );
size_t getRoutingPads ( set<RoutingPad*>& );
inline const Key& getKey () const;
inline Key* cloneKey ( size_t depth ) const;
inline Key* getLastClonedKey () const;
inline void clearClonedKey () const;
size_t checkDensity () const;
bool checkEdgeSaturation ( size_t hreserved, size_t vreserved) const;
void setType ( Flags );
@ -330,67 +342,71 @@ namespace Anabatic {
float* _fragmentations;
float* _globalsCount;
Key _key;
mutable Key* _lastClonedKey;
};
inline bool GCell::isHFlat () const { return getYMin() == getYMax(); }
inline bool GCell::isVFlat () const { return getXMin() == getXMax(); }
inline bool GCell::isFlat () const { return isHFlat() or isVFlat(); }
inline bool GCell::isDevice () const { return _flags & Flags::DeviceGCell; }
inline bool GCell::isHChannel () const { return _flags & Flags::HChannelGCell; }
inline bool GCell::isVChannel () const { return _flags & Flags::VChannelGCell; }
inline bool GCell::isStrut () const { return _flags & Flags::StrutGCell; }
inline bool GCell::isAnalog () const { return _flags & Flags::AnalogGCellMask; }
inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; }
inline bool GCell::isRow () const { return _flags & Flags::RowGCellMask; }
inline bool GCell::isIoPad () const { return _flags & Flags::IoPadGCell; }
inline bool GCell::isGoStraight () const { return _flags & Flags::GoStraight; }
inline bool GCell::isHRail () const { return _flags & Flags::HRailGCell; }
inline bool GCell::isVRail () const { return _flags & Flags::VRailGCell; }
inline bool GCell::isStdCellRow () const { return _flags & Flags::StdCellRow; }
inline bool GCell::isChannelRow () const { return _flags & Flags::ChannelRow; }
inline bool GCell::isSaturated () const { return _flags & Flags::Saturated; }
inline bool GCell::isInvalidated () const { return _flags & Flags::Invalidated; }
inline DbU::Unit GCell::getMatrixHSide () { return _matrixHSide; }
inline DbU::Unit GCell::getMatrixVSide () { return _matrixVSide; }
inline Flags GCell::getType () const { return _flags & Flags::GCellTypeMask; }
inline AnabaticEngine* GCell::getAnabatic () const { return _anabatic; }
inline DbU::Unit GCell::getXMin () const { return _xmin; }
inline DbU::Unit GCell::getYMin () const { return _ymin; }
inline Interval GCell::getHSide ( int shrink ) const { return getSide(Flags::Horizontal,shrink); }
inline Interval GCell::getVSide ( int shrink ) const { return getSide(Flags::Vertical ,shrink); }
inline Edges GCell::getEdges ( Flags sides ) const { return new GCell_Edges(this,sides); }
inline const vector<Edge*>& GCell::getWestEdges () const { return _westEdges; }
inline const vector<Edge*>& GCell::getEastEdges () const { return _eastEdges; }
inline const vector<Edge*>& GCell::getNorthEdges () const { return _northEdges; }
inline const vector<Edge*>& GCell::getSouthEdges () const { return _southEdges; }
inline GCell* GCell::getWest () const { return _westEdges.empty() ? NULL : _westEdges[0]->getOpposite(this); }
inline GCell* GCell::getEast () const { return _eastEdges.empty() ? NULL : _eastEdges[0]->getOpposite(this); }
inline GCell* GCell::getSouth () const { return _southEdges.empty() ? NULL : _southEdges[0]->getOpposite(this); }
inline GCell* GCell::getNorth () const { return _northEdges.empty() ? NULL : _northEdges[0]->getOpposite(this); }
inline Edge* GCell::getWestEdge () const { return _westEdges.empty() ? NULL : _westEdges[0]; }
inline Edge* GCell::getEastEdge () const { return _eastEdges.empty() ? NULL : _eastEdges[0]; }
inline Edge* GCell::getSouthEdge () const { return _southEdges.empty() ? NULL : _southEdges[0]; }
inline Edge* GCell::getNorthEdge () const { return _northEdges.empty() ? NULL : _northEdges[0]; }
inline GCell* GCell::getUnder ( Point p ) const { return getUnder(p.getX(),p.getY()); }
inline const vector<Contact*>& GCell::getGContacts () const { return _gcontacts; }
inline size_t GCell::getDepth () const { return _depth; }
inline int GCell::getRpCount () const { return _rpCount; }
const vector<AutoSegment*>& GCell::getVSegments () const { return _vsegments; }
inline const vector<AutoSegment*>& GCell::getHSegments () const { return _hsegments; }
inline const vector<AutoContact*>& GCell::getContacts () const { return _contacts; }
inline DbU::Unit GCell::getWidth () const { return (getXMax()-getXMin()); }
inline DbU::Unit GCell::getHeight () const { return (getYMax()-getYMin()); }
inline float GCell::getDensity ( size_t depth ) const { return (depth<_depth) ? _densities[depth] : 0.0; }
inline const GCell::Key& GCell::getKey () const { return _key; }
inline void GCell::setType ( Flags type ) { _flags.reset(Flags::GCellTypeMask); _flags |= (type&Flags::GCellTypeMask); };
inline void GCell::updateKey ( size_t depth ) { _key.update(depth); }
inline const Flags& GCell::flags () const { return _flags; }
inline Flags& GCell::flags () { return _flags; }
inline bool GCell::isHFlat () const { return getYMin() == getYMax(); }
inline bool GCell::isVFlat () const { return getXMin() == getXMax(); }
inline bool GCell::isFlat () const { return isHFlat() or isVFlat(); }
inline bool GCell::isDevice () const { return _flags & Flags::DeviceGCell; }
inline bool GCell::isHChannel () const { return _flags & Flags::HChannelGCell; }
inline bool GCell::isVChannel () const { return _flags & Flags::VChannelGCell; }
inline bool GCell::isStrut () const { return _flags & Flags::StrutGCell; }
inline bool GCell::isAnalog () const { return _flags & Flags::AnalogGCellMask; }
inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; }
inline bool GCell::isRow () const { return _flags & Flags::RowGCellMask; }
inline bool GCell::isIoPad () const { return _flags & Flags::IoPadGCell; }
inline bool GCell::isGoStraight () const { return _flags & Flags::GoStraight; }
inline bool GCell::isHRail () const { return _flags & Flags::HRailGCell; }
inline bool GCell::isVRail () const { return _flags & Flags::VRailGCell; }
inline bool GCell::isStdCellRow () const { return _flags & Flags::StdCellRow; }
inline bool GCell::isChannelRow () const { return _flags & Flags::ChannelRow; }
inline bool GCell::isSaturated () const { return _flags & Flags::Saturated; }
inline bool GCell::isInvalidated () const { return _flags & Flags::Invalidated; }
inline DbU::Unit GCell::getMatrixHSide () { return _matrixHSide; }
inline DbU::Unit GCell::getMatrixVSide () { return _matrixVSide; }
inline Flags GCell::getType () const { return _flags & Flags::GCellTypeMask; }
inline AnabaticEngine* GCell::getAnabatic () const { return _anabatic; }
inline DbU::Unit GCell::getXMin () const { return _xmin; }
inline DbU::Unit GCell::getYMin () const { return _ymin; }
inline Interval GCell::getHSide ( int shrink ) const { return getSide(Flags::Horizontal,shrink); }
inline Interval GCell::getVSide ( int shrink ) const { return getSide(Flags::Vertical ,shrink); }
inline Edges GCell::getEdges ( Flags sides ) const { return new GCell_Edges(this,sides); }
inline const vector<Edge*>& GCell::getWestEdges () const { return _westEdges; }
inline const vector<Edge*>& GCell::getEastEdges () const { return _eastEdges; }
inline const vector<Edge*>& GCell::getNorthEdges () const { return _northEdges; }
inline const vector<Edge*>& GCell::getSouthEdges () const { return _southEdges; }
inline GCell* GCell::getWest () const { return _westEdges.empty() ? NULL : _westEdges[0]->getOpposite(this); }
inline GCell* GCell::getEast () const { return _eastEdges.empty() ? NULL : _eastEdges[0]->getOpposite(this); }
inline GCell* GCell::getSouth () const { return _southEdges.empty() ? NULL : _southEdges[0]->getOpposite(this); }
inline GCell* GCell::getNorth () const { return _northEdges.empty() ? NULL : _northEdges[0]->getOpposite(this); }
inline Edge* GCell::getWestEdge () const { return _westEdges.empty() ? NULL : _westEdges[0]; }
inline Edge* GCell::getEastEdge () const { return _eastEdges.empty() ? NULL : _eastEdges[0]; }
inline Edge* GCell::getSouthEdge () const { return _southEdges.empty() ? NULL : _southEdges[0]; }
inline Edge* GCell::getNorthEdge () const { return _northEdges.empty() ? NULL : _northEdges[0]; }
inline GCell* GCell::getUnder ( Point p ) const { return getUnder(p.getX(),p.getY()); }
inline const vector<Contact*>& GCell::getGContacts () const { return _gcontacts; }
inline size_t GCell::getDepth () const { return _depth; }
inline int GCell::getRpCount () const { return _rpCount; }
const vector<AutoSegment*>& GCell::getVSegments () const { return _vsegments; }
inline const vector<AutoSegment*>& GCell::getHSegments () const { return _hsegments; }
inline const vector<AutoContact*>& GCell::getContacts () const { return _contacts; }
inline DbU::Unit GCell::getWidth () const { return (getXMax()-getXMin()); }
inline DbU::Unit GCell::getHeight () const { return (getYMax()-getYMin()); }
inline float GCell::getDensity ( size_t depth ) const { return (depth<_depth) ? _densities[depth] : 0.0; }
inline const GCell::Key& GCell::getKey () const { return _key; }
inline GCell::Key* GCell::cloneKey ( size_t depth ) const { _lastClonedKey = new Key(this,depth); return _lastClonedKey; }
inline void GCell::clearClonedKey () const { _lastClonedKey=NULL; }
inline GCell::Key* GCell::getLastClonedKey () const { return _lastClonedKey; }
inline void GCell::setType ( Flags type ) { _flags.reset(Flags::GCellTypeMask); _flags |= (type&Flags::GCellTypeMask); };
inline void GCell::updateKey ( size_t depth ) { _key.update(depth); }
inline const Flags& GCell::flags () const { return _flags; }
inline Flags& GCell::flags () { return _flags; }
inline DbU::Unit GCell::getXMax ( int shrink ) const
{ return _eastEdges.empty() ? getCell()->getAbutmentBox().getXMax() - shrink
@ -478,17 +494,25 @@ namespace Anabatic {
return lhs.getId() < rhs.getId();
}
// GCell::CompareByKey Inline Functions.
inline bool GCell::CompareByKey::operator() ( const GCell* lhs, const GCell* rhs )
{ return lhs->getKey() < rhs->getKey(); }
// GCell::Key Inline Functions.
inline GCell::Key::Key ( GCell* owner, size_t depth ) : _gcell(owner), _density(owner->getWDensity(depth,Flags::NoUpdate)) {}
inline float GCell::Key::getDensity () const { return _density; }
inline GCell* GCell::Key::getGCell () const { return _gcell; }
inline void GCell::Key::update ( size_t depth ) { _density=_gcell->getWDensity(depth); }
inline GCell::Key::Key ( const GCell* owner, size_t depth )
: _gcell(owner)
, _density(owner->getWDensity(depth,Flags::NoUpdate))
{ }
inline GCell::Key::~Key ()
{ if (isActive()) _gcell->clearClonedKey(); }
inline float GCell::Key::getDensity () const { return _density; }
inline const GCell* GCell::Key::getGCell () const { return _gcell; }
inline void GCell::Key::update ( size_t depth ) { _density=_gcell->getWDensity(depth); }
inline bool GCell::Key::isActive () const { return (this == _gcell->getLastClonedKey()); }
inline bool GCell::Key::isSaturated () const { return _gcell->isSaturated(); }
inline bool operator< ( const GCell::Key& lhs, const GCell::Key& rhs )
{
@ -498,6 +522,22 @@ namespace Anabatic {
return lhs._gcell->getId() < rhs._gcell->getId();
}
inline bool GCell::Key::Compare::operator() ( const GCell::Key* lhs, const GCell::Key* rhs )
{
//if (lhs->isSaturated() xor rhs->isSaturated()) return lhs->isSaturated();
float difference = lhs->_density - rhs->_density;
if (difference != 0.0) return (difference < 0.0);
return lhs->_gcell->getId() < rhs->_gcell->getId();
}
// -------------------------------------------------------------------
// Class : "GCellKeyQueue".
typedef std::priority_queue< GCell::Key*, std::vector<GCell::Key*>, GCell::Key::Compare > GCellKeyQueue;
// -------------------------------------------------------------------
// Class : "GCellDensitySet".
@ -542,5 +582,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::GCell);
#endif // ANABATIC_GCELL_H

View File

@ -221,6 +221,11 @@ namespace Anabatic {
virtual bool _do_xG_xM2 ();
virtual bool _do_1G_1M3 ();
virtual bool _do_xG_xM3 ();
virtual bool _do_1G_xM1_1PinM2 ();
virtual bool _do_2G_xM1_1PinM2 ();
virtual bool _do_1G_1M1_1PinM3 ();
virtual bool _do_2G_xM1_1PinM3 ();
virtual bool _do_3G_xM1_1PinM3 ();
virtual bool _do_globalSegment ();
virtual void singleGCell ( AnabaticEngine*, Net* );
AutoContact* _doHChannel ();
@ -242,73 +247,102 @@ namespace Anabatic {
+ ((pads) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize)) \
+ ((pins) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize+PadsBSize))
// Connexity Name | G|M1|M2|M3|Pad|Pin|
enum ConnexityFlag { Conn_0G = CONNEXITY_VALUE( 0, 0, 0, 0, 0 , 0 )
, Conn_2G = CONNEXITY_VALUE( 2, 0, 0, 0, 0 , 0 )
, Conn_3G = CONNEXITY_VALUE( 3, 0, 0, 0, 0 , 0 )
, Conn_4G = CONNEXITY_VALUE( 4, 0, 0, 0, 0 , 0 )
, Conn_5G = CONNEXITY_VALUE( 5, 0, 0, 0, 0 , 0 )
, Conn_6G = CONNEXITY_VALUE( 6, 0, 0, 0, 0 , 0 )
, Conn_0G_2M1 = CONNEXITY_VALUE( 0, 2, 0, 0, 0 , 0 )
, Conn_1G_1M1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 0 )
, Conn_1G_2M1 = CONNEXITY_VALUE( 1, 2, 0, 0, 0 , 0 )
, Conn_1G_3M1 = CONNEXITY_VALUE( 1, 3, 0, 0, 0 , 0 )
, Conn_1G_4M1 = CONNEXITY_VALUE( 1, 4, 0, 0, 0 , 0 )
, Conn_1G_5M1 = CONNEXITY_VALUE( 1, 5, 0, 0, 0 , 0 )
, Conn_1G_1M2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 0 )
, Conn_1G_2M2 = CONNEXITY_VALUE( 1, 0, 2, 0, 0 , 0 )
, Conn_1G_3M2 = CONNEXITY_VALUE( 1, 0, 3, 0, 0 , 0 )
, Conn_1G_4M2 = CONNEXITY_VALUE( 1, 0, 4, 0, 0 , 0 )
, Conn_1G_1M3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 0 )
, Conn_1G_2M3 = CONNEXITY_VALUE( 1, 0, 0, 2, 0 , 0 )
, Conn_1G_3M3 = CONNEXITY_VALUE( 1, 0, 0, 3, 0 , 0 )
, Conn_1G_4M3 = CONNEXITY_VALUE( 1, 0, 0, 4, 0 , 0 )
, Conn_1G_1M1_1M2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 0 )
, Conn_1G_1M1_1M3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_2G_1M1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 0 )
, Conn_2G_2M1 = CONNEXITY_VALUE( 2, 2, 0, 0, 0 , 0 )
, Conn_2G_3M1 = CONNEXITY_VALUE( 2, 3, 0, 0, 0 , 0 )
, Conn_2G_4M1 = CONNEXITY_VALUE( 2, 4, 0, 0, 0 , 0 )
, Conn_2G_5M1 = CONNEXITY_VALUE( 2, 5, 0, 0, 0 , 0 )
, Conn_2G_1M2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 0 )
, Conn_2G_2M2 = CONNEXITY_VALUE( 2, 0, 2, 0, 0 , 0 )
, Conn_2G_3M2 = CONNEXITY_VALUE( 2, 0, 3, 0, 0 , 0 )
, Conn_2G_4M2 = CONNEXITY_VALUE( 2, 0, 4, 0, 0 , 0 )
, Conn_2G_1M3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 0 )
, Conn_2G_2M3 = CONNEXITY_VALUE( 2, 0, 0, 2, 0 , 0 )
, Conn_2G_3M3 = CONNEXITY_VALUE( 2, 0, 0, 3, 0 , 0 )
, Conn_2G_4M3 = CONNEXITY_VALUE( 2, 0, 0, 4, 0 , 0 )
, Conn_2G_1M1_1M2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_3G_1M1 = CONNEXITY_VALUE( 3, 1, 0, 0, 0 , 0 )
, Conn_3G_2M1 = CONNEXITY_VALUE( 3, 2, 0, 0, 0 , 0 )
, Conn_3G_3M1 = CONNEXITY_VALUE( 3, 3, 0, 0, 0 , 0 )
, Conn_3G_4M1 = CONNEXITY_VALUE( 3, 4, 0, 0, 0 , 0 )
, Conn_3G_1M2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 0 )
, Conn_3G_2M2 = CONNEXITY_VALUE( 3, 0, 2, 0, 0 , 0 )
, Conn_3G_1M3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 0 )
, Conn_3G_2M3 = CONNEXITY_VALUE( 3, 0, 0, 2, 0 , 0 )
, Conn_3G_3M3 = CONNEXITY_VALUE( 3, 0, 0, 3, 0 , 0 )
, Conn_3G_4M3 = CONNEXITY_VALUE( 3, 0, 0, 4, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_4G_1M1 = CONNEXITY_VALUE( 4, 1, 0, 0, 0 , 0 )
, Conn_4G_2M1 = CONNEXITY_VALUE( 4, 2, 0, 0, 0 , 0 )
, Conn_4G_3M1 = CONNEXITY_VALUE( 4, 3, 0, 0, 0 , 0 )
, Conn_4G_4M1 = CONNEXITY_VALUE( 4, 4, 0, 0, 0 , 0 )
, Conn_4G_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_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 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
enum ConnexityFlag { Conn_0G = CONNEXITY_VALUE( 0, 0, 0, 0, 0 , 0 )
, Conn_2G = CONNEXITY_VALUE( 2, 0, 0, 0, 0 , 0 )
, Conn_3G = CONNEXITY_VALUE( 3, 0, 0, 0, 0 , 0 )
, Conn_4G = CONNEXITY_VALUE( 4, 0, 0, 0, 0 , 0 )
, Conn_5G = CONNEXITY_VALUE( 5, 0, 0, 0, 0 , 0 )
, Conn_6G = CONNEXITY_VALUE( 6, 0, 0, 0, 0 , 0 )
, Conn_0G_2M1 = CONNEXITY_VALUE( 0, 2, 0, 0, 0 , 0 )
, Conn_1G_1M1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 0 )
, Conn_1G_2M1 = CONNEXITY_VALUE( 1, 2, 0, 0, 0 , 0 )
, Conn_1G_3M1 = CONNEXITY_VALUE( 1, 3, 0, 0, 0 , 0 )
, Conn_1G_4M1 = CONNEXITY_VALUE( 1, 4, 0, 0, 0 , 0 )
, Conn_1G_5M1 = CONNEXITY_VALUE( 1, 5, 0, 0, 0 , 0 )
, Conn_1G_6M1 = CONNEXITY_VALUE( 1, 6, 0, 0, 0 , 0 )
, Conn_1G_7M1 = CONNEXITY_VALUE( 1, 7, 0, 0, 0 , 0 )
, Conn_1G_8M1 = CONNEXITY_VALUE( 1, 8, 0, 0, 0 , 0 )
, Conn_1G_9M1 = CONNEXITY_VALUE( 1, 9, 0, 0, 0 , 0 )
, Conn_1G_1M2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 0 )
, Conn_1G_2M2 = CONNEXITY_VALUE( 1, 0, 2, 0, 0 , 0 )
, Conn_1G_3M2 = CONNEXITY_VALUE( 1, 0, 3, 0, 0 , 0 )
, Conn_1G_4M2 = CONNEXITY_VALUE( 1, 0, 4, 0, 0 , 0 )
, Conn_1G_1M3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 0 )
, Conn_1G_2M3 = CONNEXITY_VALUE( 1, 0, 0, 2, 0 , 0 )
, Conn_1G_3M3 = CONNEXITY_VALUE( 1, 0, 0, 3, 0 , 0 )
, Conn_1G_4M3 = CONNEXITY_VALUE( 1, 0, 0, 4, 0 , 0 )
, Conn_1G_1M1_1M2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 0 )
, Conn_1G_1M1_1M3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_2G_1M1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 0 )
, Conn_2G_2M1 = CONNEXITY_VALUE( 2, 2, 0, 0, 0 , 0 )
, Conn_2G_3M1 = CONNEXITY_VALUE( 2, 3, 0, 0, 0 , 0 )
, Conn_2G_4M1 = CONNEXITY_VALUE( 2, 4, 0, 0, 0 , 0 )
, Conn_2G_5M1 = CONNEXITY_VALUE( 2, 5, 0, 0, 0 , 0 )
, Conn_2G_6M1 = CONNEXITY_VALUE( 2, 6, 0, 0, 0 , 0 )
, Conn_2G_7M1 = CONNEXITY_VALUE( 2, 7, 0, 0, 0 , 0 )
, Conn_2G_8M1 = CONNEXITY_VALUE( 2, 8, 0, 0, 0 , 0 )
, Conn_2G_9M1 = CONNEXITY_VALUE( 2, 9, 0, 0, 0 , 0 )
, Conn_2G_1M2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 0 )
, Conn_2G_2M2 = CONNEXITY_VALUE( 2, 0, 2, 0, 0 , 0 )
, Conn_2G_3M2 = CONNEXITY_VALUE( 2, 0, 3, 0, 0 , 0 )
, Conn_2G_4M2 = CONNEXITY_VALUE( 2, 0, 4, 0, 0 , 0 )
, Conn_2G_1M3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 0 )
, Conn_2G_2M3 = CONNEXITY_VALUE( 2, 0, 0, 2, 0 , 0 )
, Conn_2G_3M3 = CONNEXITY_VALUE( 2, 0, 0, 3, 0 , 0 )
, Conn_2G_4M3 = CONNEXITY_VALUE( 2, 0, 0, 4, 0 , 0 )
, Conn_2G_1M1_1M2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_3G_1M1 = CONNEXITY_VALUE( 3, 1, 0, 0, 0 , 0 )
, Conn_3G_2M1 = CONNEXITY_VALUE( 3, 2, 0, 0, 0 , 0 )
, Conn_3G_3M1 = CONNEXITY_VALUE( 3, 3, 0, 0, 0 , 0 )
, Conn_3G_4M1 = CONNEXITY_VALUE( 3, 4, 0, 0, 0 , 0 )
, Conn_3G_5M1 = CONNEXITY_VALUE( 3, 5, 0, 0, 0 , 0 )
, Conn_3G_6M1 = CONNEXITY_VALUE( 3, 6, 0, 0, 0 , 0 )
, Conn_3G_7M1 = CONNEXITY_VALUE( 3, 7, 0, 0, 0 , 0 )
, Conn_3G_8M1 = CONNEXITY_VALUE( 3, 8, 0, 0, 0 , 0 )
, Conn_3G_9M1 = CONNEXITY_VALUE( 3, 9, 0, 0, 0 , 0 )
, Conn_3G_1M2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 0 )
, Conn_3G_2M2 = CONNEXITY_VALUE( 3, 0, 2, 0, 0 , 0 )
, Conn_3G_1M3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 0 )
, Conn_3G_2M3 = CONNEXITY_VALUE( 3, 0, 0, 2, 0 , 0 )
, Conn_3G_3M3 = CONNEXITY_VALUE( 3, 0, 0, 3, 0 , 0 )
, Conn_3G_4M3 = CONNEXITY_VALUE( 3, 0, 0, 4, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_4G_1M1 = CONNEXITY_VALUE( 4, 1, 0, 0, 0 , 0 )
, Conn_4G_2M1 = CONNEXITY_VALUE( 4, 2, 0, 0, 0 , 0 )
, Conn_4G_3M1 = CONNEXITY_VALUE( 4, 3, 0, 0, 0 , 0 )
, Conn_4G_4M1 = CONNEXITY_VALUE( 4, 4, 0, 0, 0 , 0 )
, Conn_4G_5M1 = CONNEXITY_VALUE( 4, 5, 0, 0, 0 , 0 )
, Conn_4G_6M1 = CONNEXITY_VALUE( 4, 6, 0, 0, 0 , 0 )
, Conn_4G_7M1 = CONNEXITY_VALUE( 4, 7, 0, 0, 0 , 0 )
, Conn_4G_8M1 = CONNEXITY_VALUE( 4, 8, 0, 0, 0 , 0 )
, Conn_4G_9M1 = CONNEXITY_VALUE( 4, 9, 0, 0, 0 , 0 )
, Conn_4G_1M2 = CONNEXITY_VALUE( 4, 0, 1, 0, 0 , 0 )
, Conn_4G_1M3 = CONNEXITY_VALUE( 4, 0, 0, 1, 0 , 0 )
, Conn_1G_1Pad = CONNEXITY_VALUE( 1, 0, 0, 0, 1 , 0 )
, Conn_2G_1Pad = CONNEXITY_VALUE( 2, 0, 0, 0, 1 , 0 )
, Conn_3G_1Pad = CONNEXITY_VALUE( 3, 0, 0, 0, 1 , 0 )
, Conn_1G_1PinM1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 1 )
, Conn_2G_1PinM1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 1 )
, Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 1 )
, Conn_2G_1PinM2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 1 )
, Conn_3G_1PinM2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 1 )
, Conn_1G_1M1_1PinM2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 1 )
, Conn_1G_2M1_1PinM2 = CONNEXITY_VALUE( 1, 2, 1, 0, 0 , 1 )
, Conn_2G_1M1_1PinM2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 1 )
, Conn_2G_2M1_1PinM2 = CONNEXITY_VALUE( 2, 2, 1, 0, 0 , 1 )
, Conn_1G_1PinM3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 1 )
, Conn_2G_1PinM3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 1 )
, Conn_3G_1PinM3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 1 )
, Conn_1G_1M1_1PinM3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 1 )
, Conn_2G_1M1_1PinM3 = CONNEXITY_VALUE( 2, 1, 0, 1, 0 , 1 )
, Conn_2G_2M1_1PinM3 = CONNEXITY_VALUE( 2, 2, 0, 1, 0 , 1 )
, Conn_2G_3M1_1PinM3 = CONNEXITY_VALUE( 2, 3, 0, 1, 0 , 1 )
, Conn_3G_1M1_1PinM3 = CONNEXITY_VALUE( 3, 1, 0, 1, 0 , 1 )
, Conn_3G_2M1_1PinM3 = CONNEXITY_VALUE( 3, 2, 0, 1, 0 , 1 )
, Conn_3G_3M1_1PinM3 = CONNEXITY_VALUE( 3, 3, 0, 1, 0 , 1 )
};
#undef CONNEXITY_VALUE

View File

@ -28,33 +28,41 @@ namespace Anabatic {
class NetBuilderHV : public NetBuilder {
public:
NetBuilderHV ();
virtual ~NetBuilderHV ();
virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags );
virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags );
NetBuilderHV ();
virtual ~NetBuilderHV ();
virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags );
virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags );
AutoContact* doRp_AccessNorthPin ( GCell*, RoutingPad* );
AutoContact* doRp_AccessEastWestPin ( GCell*, RoutingPad* );
private:
virtual bool _do_1G_1M1 ();
virtual bool _do_1G_xM1 ();
virtual bool _do_xG ();
virtual bool _do_2G ();
virtual bool _do_2G_1M1 ();
virtual bool _do_xG_1Pad ();
virtual bool _do_1G_1PinM1 ();
virtual bool _do_2G_1PinM1 ();
virtual bool _do_1G_1PinM2 ();
virtual bool _do_xG_1PinM2 ();
virtual bool _do_1G_1PinM3 ();
virtual bool _do_xG_1PinM3 ();
virtual bool _do_xG_1M1 ();
virtual bool _do_xG_1M1_1M2 ();
virtual bool _do_xG_xM1_xM3 ();
virtual bool _do_4G_1M2 ();
virtual bool _do_xG_xM2 ();
virtual bool _do_1G_1M3 ();
virtual bool _do_xG_xM3 ();
virtual bool _do_globalSegment ();
public:
virtual string getTypeName () const;
virtual bool _do_1G_1M1 ();
virtual bool _do_1G_xM1 ();
virtual bool _do_xG ();
virtual bool _do_2G ();
virtual bool _do_2G_1M1 ();
virtual bool _do_xG_1Pad ();
virtual bool _do_1G_1PinM1 ();
virtual bool _do_2G_1PinM1 ();
virtual bool _do_1G_1PinM2 ();
virtual bool _do_xG_1PinM2 ();
virtual bool _do_1G_1PinM3 ();
virtual bool _do_xG_1PinM3 ();
virtual bool _do_xG_1M1 ();
virtual bool _do_xG_1M1_1M2 ();
virtual bool _do_xG_xM1_xM3 ();
virtual bool _do_4G_1M2 ();
virtual bool _do_xG_xM2 ();
virtual bool _do_1G_1M3 ();
virtual bool _do_xG_xM3 ();
virtual bool _do_1G_xM1_1PinM2 ();
virtual bool _do_2G_xM1_1PinM2 ();
virtual bool _do_1G_1M1_1PinM3 ();
virtual bool _do_2G_xM1_1PinM3 ();
virtual bool _do_3G_xM1_1PinM3 ();
virtual bool _do_globalSegment ();
virtual void singleGCell ( AnabaticEngine*, Net* );
public:
virtual string getTypeName () const;
};

View File

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

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef ANABATIC_SESSION_H
#define ANABATIC_SESSION_H
#pragma once
#include <string>
#include <vector>
#include <set>
@ -97,11 +95,13 @@ namespace Anabatic {
static inline size_t getDVerticalDepth ();
static inline const Layer* getDVerticalLayer ();
static inline DbU::Unit getDVerticalWidth ();
static inline DbU::Unit getDPVerticalWidth ();
static inline DbU::Unit getDVerticalPitch ();
static inline DbU::Unit getDVerticalOffset ();
static inline size_t getDHorizontalDepth ();
static inline const Layer* getDHorizontalLayer ();
static inline DbU::Unit getDHorizontalWidth ();
static inline DbU::Unit getDPHorizontalWidth ();
static inline DbU::Unit getDHorizontalPitch ();
static inline DbU::Unit getDHorizontalOffset ();
static inline size_t getDContactDepth ();
@ -109,6 +109,11 @@ namespace Anabatic {
static inline DbU::Unit getDContactWidth ();
static inline DbU::Unit getDContactPitch ();
static inline RoutingGauge* getRoutingGauge ();
static inline bool isGLayer ( const Layer* );
static inline bool isGMetal ( const Layer* );
static inline bool isGContact ( const Layer* );
static inline bool isGaugeLayer ( const Layer* );
static inline RoutingLayerGauge* getLayerGauge ( const Layer* );
static inline RoutingLayerGauge* getLayerGauge ( size_t depth );
static inline size_t getDepth ();
static inline size_t getViaDepth ( const Layer* layer );
@ -119,6 +124,7 @@ namespace Anabatic {
static inline DbU::Unit getPitch ( size_t depth, Flags flags );
static inline DbU::Unit getOffset ( size_t depth );
static inline DbU::Unit getWireWidth ( size_t depth );
static inline DbU::Unit getPWireWidth ( size_t depth );
static inline DbU::Unit getViaWidth ( size_t depth );
static inline Flags getDirection ( const Layer* );
static inline DbU::Unit getPitch ( const Layer*, Flags flags );
@ -126,6 +132,7 @@ namespace Anabatic {
static inline DbU::Unit getWireWidth ( const Layer* );
static inline DbU::Unit getViaWidth ( const Layer* );
static inline DbU::Unit getExtensionCap ( const Layer* );
static inline DbU::Unit getNearestTrackAxis ( const Layer*, DbU::Unit, uint32_t mode );
static inline Point getNearestGridPoint ( Point, Box constraints );
static inline size_t getSegmentStackSize ();
static inline size_t getContactStackSize ();
@ -167,6 +174,7 @@ namespace Anabatic {
void _revalidateTopology ();
virtual size_t _revalidate ();
DbU::Unit _getPitch ( size_t depth, Flags flags ) const;
DbU::Unit _getNearestTrackAxis ( const Layer*, DbU::Unit, uint32_t mode );
Point _getNearestGridPoint ( Point, Box constraints );
Record* _getRecord () const;
string _getString () const;
@ -235,17 +243,24 @@ namespace Anabatic {
inline size_t Session::getDVerticalDepth () { return getConfiguration()->getDVerticalDepth(); }
inline const Layer* Session::getDVerticalLayer () { return getConfiguration()->getDVerticalLayer(); }
inline DbU::Unit Session::getDVerticalWidth () { return getConfiguration()->getDVerticalWidth(); }
inline DbU::Unit Session::getDPVerticalWidth () { return getConfiguration()->getDPVerticalWidth(); }
inline DbU::Unit Session::getDVerticalPitch () { return getConfiguration()->getDVerticalPitch(); }
inline DbU::Unit Session::getDVerticalOffset () { return getConfiguration()->getDVerticalOffset(); }
inline size_t Session::getDHorizontalDepth () { return getConfiguration()->getDHorizontalDepth(); }
inline const Layer* Session::getDHorizontalLayer () { return getConfiguration()->getDHorizontalLayer(); }
inline DbU::Unit Session::getDHorizontalWidth () { return getConfiguration()->getDHorizontalWidth(); }
inline DbU::Unit Session::getDPHorizontalWidth () { return getConfiguration()->getDPHorizontalWidth(); }
inline DbU::Unit Session::getDHorizontalPitch () { return getConfiguration()->getDHorizontalPitch(); }
inline DbU::Unit Session::getDHorizontalOffset () { return getConfiguration()->getDHorizontalOffset(); }
inline size_t Session::getDContactDepth () { return getConfiguration()->getDContactDepth(); }
inline const Layer* Session::getDContactLayer () { return getConfiguration()->getDContactLayer(); }
inline DbU::Unit Session::getDContactWidth () { return getConfiguration()->getDContactWidth(); }
inline DbU::Unit Session::getDContactPitch () { return getConfiguration()->getDContactPitch(); }
inline bool Session::isGLayer ( const Layer* layer ) { return getConfiguration()->isGLayer(layer); }
inline bool Session::isGMetal ( const Layer* layer ) { return getConfiguration()->isGMetal(layer); }
inline bool Session::isGContact ( const Layer* layer ) { return getConfiguration()->isGContact(layer); }
inline bool Session::isGaugeLayer ( const Layer* layer ) { return getRoutingGauge()->hasLayer(layer); }
inline RoutingLayerGauge* Session::getLayerGauge ( const Layer* layer ) { return getRoutingGauge()->getLayerGauge(layer); }
inline RoutingLayerGauge* Session::getLayerGauge ( size_t depth ) { return getRoutingGauge()->getLayerGauge(depth); }
inline size_t Session::getDepth () { return getRoutingGauge()->getDepth(); }
inline size_t Session::getViaDepth ( const Layer* layer ) { return getRoutingGauge()->getViaDepth(layer); }
@ -255,6 +270,7 @@ namespace Anabatic {
inline DbU::Unit Session::getPitch ( size_t depth, Flags flags=Flags::NoFlags ) { return get("getPitch(depth,flags)")->_getPitch( depth, flags ); }
inline DbU::Unit Session::getOffset ( size_t depth ) { return getRoutingGauge()->getLayerOffset(depth); }
inline DbU::Unit Session::getWireWidth ( size_t depth ) { return getRoutingGauge()->getLayerWireWidth(depth); }
inline DbU::Unit Session::getPWireWidth ( size_t depth ) { return getRoutingGauge()->getLayerPWireWidth(depth); }
inline DbU::Unit Session::getViaWidth ( size_t depth ) { return getRoutingGauge()->getViaWidth(depth); }
inline DbU::Unit Session::getPitch ( const Layer* layer, Flags flags=Flags::NoFlags ) { return getPitch( getLayerDepth(layer), flags ); }
inline DbU::Unit Session::getOffset ( const Layer* layer ) { return getOffset ( getLayerDepth(layer) ); }
@ -263,6 +279,7 @@ namespace Anabatic {
inline DbU::Unit Session::getExtensionCap ( const Layer* layer ) { return getConfiguration()->getExtensionCap(layer); }
inline Flags Session::getDirection ( const Layer* layer ) { return getDirection( getLayerDepth(layer) ); }
inline Point Session::getNearestGridPoint ( Point p, Box b ) { return get("getNearestGridPoint()")->_getNearestGridPoint(p,b); }
inline DbU::Unit Session::getNearestTrackAxis ( const Layer* layer, DbU::Unit axis, uint32_t mode ) { return get("getNearestTrackAxis()")->_getNearestTrackAxis(layer,axis,mode); }
inline void Session::_dogleg ( AutoSegment* segment ) { _doglegs.push_back(segment); }
inline void Session::_doglegReset () { _doglegs.clear(); }
@ -276,6 +293,3 @@ namespace Anabatic {
INSPECTOR_P_SUPPORT(Anabatic::Session);
#endif // ANABATIC_SESSION_H

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,11 +14,11 @@ projects = [
, { 'name' : "coriolis"
, 'tools' : [ "bootstrap"
, "lefdef"
, "flute"
, "coloquinte"
, "vlsisapd"
, "hurricane"
, "crlcore"
, "flute"
, "etesian"
, "anabatic"
, "katana"

View File

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

View File

@ -95,9 +95,13 @@
set(CXX_STANDARD "c++11")
endif()
set(CMAKE_C_FLAGS_DEBUG " -Wall -fsanitize=address ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE)
#set(CMAKE_C_FLAGS_DEBUG " -Wall ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE)
set(CMAKE_C_FLAGS_RELEASE " -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C Compiler Release options." FORCE)
#set(CMAKE_C_FLAGS_RELEASE " -Wall -fsanitize=address ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C Compiler Release options." FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall -fsanitize=address ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C++ Compiler Debug options." FORCE)
#set(CMAKE_CXX_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C++ Compiler Debug options." FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "-std=${CXX_STANDARD} -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C++ Compiler Release options." FORCE)
#set(CMAKE_CXX_FLAGS_RELEASE "-std=${CXX_STANDARD} -Wall -fsanitize=address ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C++ Compiler Release options." FORCE)
#
@ -274,7 +278,8 @@
/usr/include
PATH_SUFFIXES qwt )
find_library(QWT_LIBRARY NAMES qwt-qt5 qwt
PATHS /usr/lib${LIB_SUFFIX} )
PATHS /usr/lib64
/usr/lib )
else()
find_path(QWT_INCLUDE_DIR NAMES qwt.h
PATHS /usr/include/qwt-qt4
@ -284,7 +289,8 @@
PATH_SUFFIXES qwt )
find_library(QWT_LIBRARY NAMES qwt-qt4 qwt
PATHS /opt/local/libexec/qt4/lib
/usr/lib${LIB_SUFFIX} )
/usr/lib64
/usr/lib )
endif()
if( QWT_INCLUDE_DIR AND QWT_LIBRARY)
@ -413,5 +419,7 @@
target_link_libraries( ${pytarget} ${pyDeplibs} )
install( TARGETS ${pytarget} DESTINATION ${PYTHON_SITE_PACKAGES} )
if( NOT ("${pyIncludes}" STREQUAL "None") )
install( FILES ${pyIncludes} DESTINATION ${inc_install_dir} )
endif()
endmacro( add_python_module )

View File

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

View File

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

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

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 ):
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:] ]
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 += [ line.lstrip() ]
return
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):
@ -104,321 +104,433 @@ class ErrorMessage ( Exception ):
class BadBinary ( ErrorMessage ):
def __init__ ( self, binary ):
ErrorMessage.__init__( self, 1, "Binary not found: <%s>." % binary )
return
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
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
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
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
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()
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
homeDir = os.environ['HOME']
workDir = os.getcwd()
if homeDir.startswith(homeDir):
workDir = '~' + workDir[ len(homeDir) : ]
prompt = '%s@%s:%s$' % (os.environ['USER'],conf.masterHost,workDir)
try:
self.log( '%s%s\n' % (prompt,self._argumentsToStr(self.arguments)) )
child = subprocess.Popen( self.arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
class CommandArg ( object ):
while True:
line = child.stdout.readline()
if not line: break
def __init__ ( self, command, wd=None, host=None, fdLog=None ):
self.command = command
self.host = host
self.wd = wd
self.fdLog = fdLog
return
self.log( line )
except OSError, e:
raise BadBinary( self.arguments[0] )
def __str__ ( self ):
s = ''
if self.wd: s = 'cd %s && ' % self.wd
(pid,status) = os.waitpid( child.pid, 0 )
status >>= 8
if status != 0:
raise BadReturnCode( status )
for i in range(len(self.command)):
if i: s += ' '
s += self.command[i]
return s
return
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
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
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
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
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
os.chdir( self.localRepoDir )
Command( [ 'git', 'checkout', branch ], self.fdLog ).execute()
return
class Configuration ( object ):
PrimaryNames = \
[ 'sender' , 'receivers'
, 'coriolisRepo', 'benchsRepo', 'supportRepos'
, 'coriolisRepo', 'benchsRepo' , 'supportRepos'
, 'homeDir' , 'masterHost'
, 'debugArg' , 'nightlyMode'
, 'rmSource' , 'rmBuild', 'doGit', 'doBuild', 'doBenchs', 'doSendReport'
, 'debugArg' , 'nightlyMode', 'dockerMode', 'chrootMode'
, 'rmSource' , 'rmBuild'
, 'doGit' , 'doAlliance' , 'doCoriolis', 'doBenchs', 'doSendReport'
, 'success' , 'rcode'
]
SecondaryNames = \
[ 'rootDir', 'srcDir', 'logDir', 'logs', 'fds'
[ '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._coriolisRepo = 'https://www-soc.lip6.fr/git/coriolis.git'
self._benchsRepo = 'https://www-soc.lip6.fr/git/alliance-check-toolkit.git'
self._homeDir = os.environ['HOME']
self._debugArg = ''
self._rmSource = False
self._rmBuild = False
self._doGit = True
self._doBuild = True
self._doBenchs = False
self._doSendReport = True
self._nightlyMode = False
self._logs = { 'build':None, 'benchs':None }
self._fds = { 'build':None, 'benchs':None }
self._masterHost = self._detectMasterHost()
self._success = False
self._rcode = 0
self._updateSecondaries()
return
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 )
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
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 ):
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]
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._targets['SL6'] = None
self._rootDir = self._homeDir + '/nightly/coriolis-2.x'
else:
if self._masterHost != 'lepka':
self._targets['SL6'] = None
self._rootDir = self._homeDir + '/coriolis-2.x'
self._srcDir = self._rootDir + '/src'
self._logDir = self._srcDir + '/logs'
return
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 ):
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
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
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
for fd in self._fds.values():
if fd: fd.close()
return
def compressLogs ( self ):
for log in self._logs.values():
if not log: continue
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
fd = open( log, 'r' )
bzfd = bz2.BZ2File( log+'.bz2', 'w' )
def getCommands ( self, target ):
commands = []
for line in fd.readlines(): bzfd.write( line )
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'] ) )
bzfd.close()
fd.close()
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'] ) )
os.unlink( log )
return
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
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
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
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
# -------------------------------------------------------------------
@ -428,105 +540,110 @@ class Report ( object ):
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 ( "--no-build" , action="store_true" , dest="noBuild" , help="Do not rebuild the tools, must have already be done." )
parser.add_option ( "--no-report" , action="store_true" , dest="noReport" , help="Do not send a final report." )
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.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.noReport: conf.doSendReport = False
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.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 = []
for supportRepo in conf.supportRepos:
gitSupports.append( GitRepository( supportRepo, conf.srcDir+'/support' ) )
gitCoriolis = GitRepository( conf.coriolisRepo, conf.srcDir, conf.fds['build'] )
gitBenchs = GitRepository( conf.benchsRepo , conf.srcDir, conf.fds['build'] )
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.rmSource: gitCoriolis.removeLocalRepo()
gitCoriolis.clone ()
gitCoriolis.checkout( 'devel_anabatic' )
if conf.rmSource: gitBenchs.removeLocalRepo()
gitBenchs.clone()
for gitSupport in gitSupports:
if conf.rmSource: gitSupport.removeLocalRepo()
gitSupport.clone()
if gitSupport.url.endswith('rapidjson'):
gitSupport.checkout( 'b1a4d91' )
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 )
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 )
ccbBin = gitCoriolis.localRepoDir+'/bootstrap/ccb.py'
if not os.path.isfile( ccbBin ):
raise ErrorMessage( 1, [ 'Cannot find <ccb.py>, should be here:'
, ' <%s>' % ccbBin
] )
buildCommand = '%s --root=%s --project=support --project=coriolis --make="-j%%d install" %%s' \
% (ccbBin,conf.rootDir)
benchsCommand = 'cd %s/benchs && ../bin/go.sh' % (gitBenchs.localRepoDir)
commands = \
[ ( conf.targets['SL7_64'], buildCommand % (3,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()
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
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['build' ] )
report.attachLog( conf.logs['benchs'] )
report.send()
report = Report( conf )
report.attachLog( conf.logs['coriolis' ] )
report.attachLog( conf.logs['benchs' ] )
report.send()
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

@ -267,7 +267,7 @@ namespace Bora {
slicingtree->expandRoutingChannel();
slicingtree->replace();
slicingtree->updateSymNetAxis();
katana->updateMatrix();
katana->analogInit();
Katana::Session::close();

View File

@ -189,7 +189,10 @@ namespace Bora {
{
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 (getNbChild() == 1) {

View File

@ -377,10 +377,14 @@ namespace Bora {
if (getType() == HorizontalSNode) symmetryType = HSymmetry;
if (getType() == VerticalSNode ) symmetryType = VSymmetry;
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."
, childIndex, copyIndex ) << endl;
cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Children %d and %d are not the same, symmetry is ignored.\n"
" child %d: %s\n"
" child %d: %s"
, childIndex, copyIndex
, childIndex, getString(getChild(childIndex)).c_str()
, copyIndex , getString(getChild( copyIndex)).c_str()
) << endl;
return;
}
@ -1128,6 +1132,9 @@ namespace Bora {
void HVSlicingNode::addSymmetryNet ( unsigned int type, Net* net1, Net* net2 )
{
cerr << "HVSlicingNode::addSymmetryNet(): " << this << endl;
cerr << "* " << net1 << endl;
if (checkSymmetryNet(type,net1,net2)) {
cerr << Warning( "HVSlicingNode::addSymmetryNet(): Net symmetry already set." ) << endl;
return;
@ -1201,6 +1208,13 @@ namespace Bora {
}
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* n2 = getChild( _symmetries.front().second );
DbU::Unit xCenter = (n1->getX() + n2->getX() + n2->getWidth())/2;
@ -1248,11 +1262,11 @@ namespace Bora {
}
}
}
}
for ( SlicingNode* child : _children ) {
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) )
child->updateSymNetAxis();
}
for ( SlicingNode* child : _children ) {
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) )
child->updateSymNetAxis();
}
}

View File

@ -70,7 +70,8 @@ namespace Bora {
TransistorFamily* device = dynamic_cast<TransistorFamily *>( cell );
StepParameterRange* stepRange = dynamic_cast<StepParameterRange*>( nodeset->getRange() );
if (device) {
//cdebug_log(536,0) << "createNodeSets for an Analog Device" << endl;
cdebug_log(535,0) << "NodeSets:create(): for a Transistor 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()
@ -94,30 +95,34 @@ namespace Bora {
MatrixParameterRange* matrixRange = dynamic_cast<MatrixParameterRange*>( nodeset->getRange() );
if (mcapacitor) {
cdebug_log(535,0) << "NodeSets::create(): for a Capacitor Analog Device" << endl;
if (not matrixRange) {
throw Error( "NodeSets::create(): Device \"%s\" must be associated with a MatrixParameterRange argument instead of %s."
, getString(mcapacitor->getName()).c_str()
, getString(stepRange).c_str()
);
matrixRange->reset();
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() );
}
matrixRange->reset();
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 {
ResistorFamily* device = dynamic_cast<ResistorFamily *>( cell );
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()
@ -334,7 +339,6 @@ namespace Bora {
if (find(boxSet) == NULL) _boxSets.push_back( boxSet );
else {
find( boxSet )->incrementCpt();
cerr << "NodeSets::push_back(): do not add current BoxSet, already exists." << endl;
boxSet->destroy();
}
}

View File

@ -18,6 +18,7 @@
#include "crlcore/PyRoutingGauge.h"
#include "bora/PyDSlicingNode.h"
#include "bora/PyStepParameterRange.h"
#include "bora/PyMatrixParameterRange.h"
namespace Bora {
@ -73,8 +74,10 @@ extern "C" {
PyErr_SetString( ConstructorError, "DSlicingNode.create(): Second argument *must* be of type Cell." );
return NULL;
}
if (not IsPyStepParameterRange(pyParameterRange)) {
PyErr_SetString( ConstructorError, "DSlicingNode.create(): Third argument *must* be of type StepParameterRange." );
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;
}
if (pyRoutingGauge and not IsPyRoutingGauge(pyRoutingGauge)) {
@ -82,10 +85,18 @@ extern "C" {
return NULL;
}
Cell* cell = PYCELL_O( pyCell );
Instance* instance = cell->getInstance( PyString_AsString(pyInstance) );
ParameterRange* range = ParameterRangeCast( pyParameterRange );
RoutingGauge* rg = (pyRoutingGauge) ? PYROUTINGGAUGE_O(pyRoutingGauge) : NULL;
Cell* cell = PYCELL_O( pyCell );
Instance* instance = cell->getInstance( PyString_AsString(pyInstance) );
if (not instance) {
ostringstream message;
message << "DSlicingNode.create(): Cell \"" << cell->getName()
<< "\" has no instance named \"" << PyString_AsString(pyInstance) << "\".";
PyErr_SetString( ConstructorError, message.str().c_str() );
return NULL;
}
ParameterRange* range = ParameterRangeCast( pyParameterRange );
RoutingGauge* rg = (pyRoutingGauge) ? PYROUTINGGAUGE_O(pyRoutingGauge) : NULL;
node = DSlicingNode::create( NodeSets::create( instance->getMasterCell(), range, rg )
, UnknownAlignment

View File

@ -16,6 +16,7 @@
#include "bora/PyParameterRange.h"
#include "bora/PyStepParameterRange.h"
#include "bora/PyMatrixParameterRange.h"
namespace Bora {
@ -112,7 +113,9 @@ extern "C" {
# if !defined(__PYTHON_MODULE__)
ParameterRange* ParameterRangeCast ( PyObject* derivedObject ) {
if (IsPyStepParameterRange(derivedObject)) return PYSTEPPARAMETERRANGE_O(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;
}

View File

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

View File

@ -698,6 +698,9 @@ namespace Bora {
for ( RoutingPad* rp : net->getRoutingPads() ) rps.push_back( rp );
for ( RoutingPad* rp : rps ) rp->destroy();
}
_cell->getFlags().reset( Cell::Flags::FlattenedNets|Cell::Flags::Routed );
_cell->setTerminalNetlist( false );
}

View File

@ -399,9 +399,11 @@ namespace Bora {
if (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++;
}
}

View File

@ -86,6 +86,7 @@ namespace Bora {
DbU::Unit addedDistance = 0;
if (Vertex::isRestricted(vcurr, vnext, e, _hpitch, _vpitch, _net)) {
cdebug_log(112,1) << "Unreachable, restricted "<< e << std::endl;
distance = Vertex::unreachable;
} else {
if ( (vcurr->getGCell()->isMatrix()) and (vnext->getGCell()->isMatrix()) ) {

View File

@ -87,7 +87,7 @@ namespace Bora {
inline DbU::Unit BoxSet::getWidth () const { return _width; }
inline unsigned int BoxSet::getCpt () const { return _cpt; }
inline void BoxSet::incrementCpt () { _cpt++; }
inline double BoxSet::getRatio () { return _width/_height; }
inline double BoxSet::getRatio () { return (double)_width/(double)_height; }
inline double BoxSet::getArea () { return _width*_height; }
inline unsigned int BoxSet::getType () const { return UnknownType; }
inline double BoxSet::getOccupationArea () const { return 100; }

View File

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

View File

@ -159,6 +159,13 @@ class netlist{
index_t get_cell_ind(index_t external_ind) const{ return cell_internal_mapping_[external_ind]; }
index_t get_net_ind(index_t external_ind) const{ return net_internal_mapping_[external_ind]; }
point<int_t> get_cell_size(index_t external_ind){
return cell_sizes_[ cell_internal_mapping_[external_ind] ];
}
void set_cell_size(index_t external_ind,point<int_t> cell_size){
cell_sizes_[cell_internal_mapping_[external_ind]] = cell_size;
}
};
inline netlist::netlist(std::vector<temporary_cell> cells, std::vector<temporary_net> nets, std::vector<temporary_pin> all_pins){

View File

@ -3,6 +3,7 @@
#include "coloquinte/optimization_subproblems.hxx"
#include <iostream>
#include <sstream>
#include <algorithm>
#include <cmath>
#include <queue>
@ -397,7 +398,6 @@ detailed_placement legalize(netlist const & circuit, placement_t const & pl, box
int_t rnd_hgh_y_pos = std::min(surface.y_max, hgh_y_pos);
int_t rnd_low_x_pos = std::max(surface.x_min, low_x_pos);
int_t rnd_low_y_pos = std::max(surface.y_min, low_y_pos);
index_t first_row = (rnd_low_y_pos - surface.y_min) / row_height;
index_t last_row = (index_t) (rnd_hgh_y_pos - surface.y_min + row_height - 1) / row_height; // Exclusive: if the cell spans the next row, i.e. pos % row_height >= 0, include it too
assert(last_row <= nbr_rows);
@ -415,8 +415,12 @@ detailed_placement legalize(netlist const & circuit, placement_t const & pl, box
std::sort(L.begin(), L.end()); // Sorts from last to first, so that we may use pop_back()
// Doesn't collapse them yet, which may make for bigger complexities
for(index_t i=0; i+1<L.size(); ++i){
if(L[i].min_x < L[i+1].max_x)
throw std::runtime_error("Sorry, I don't handle overlapping fixed cells yet\n");
if(L[i].min_x < L[i+1].max_x) {
std::ostringstream message;
message << "Coloquinte::dp::legalize(): Sorry, I don't handle overlapping fixed cells yet ";
message << " i:" << i << " max_x: " << L[i].max_x << " > min_x:" << L[i+1].min_x << "\n";
throw std::runtime_error(message.str());
}
}
}

View File

@ -88,7 +88,7 @@ box<int_t> region_distribution::get_box(index_t x, index_t y, index_t x_cnt, ind
placement_area_.y_min + ( ((std::int64_t) (placement_area_.y_max - placement_area_.y_min)) * y ) / y_cnt,
placement_area_.y_min + ( ((std::int64_t) (placement_area_.y_max - placement_area_.y_min)) * (y+1) ) / y_cnt
);
assert(not ret.empty());
//assert(not ret.empty());
return ret;
}
@ -1008,7 +1008,7 @@ std::vector<region_distribution::movable_cell> region_distribution::export_sprea
index_t n = R.cell_references_.size();
float_t total_capacity = static_cast<float_t>(R.capacity());
box<float_t> surface = static_cast<box<float_t> >(get_box(x, y, x_regions_cnt(), y_regions_cnt()));
assert(surface.x_max > surface.x_min and surface.y_max > surface.y_min);
//assert(surface.x_max > surface.x_min and surface.y_max > surface.y_min);
std::vector<legalizable_task<float_t> > x_cells, y_cells;

View File

@ -26,7 +26,7 @@ IF(UNIX)
FIND_LIBRARY(CRLCORE_LIBRARY_PATH
NAMES crlcore
PATHS ${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES lib${LIB_SUFFIX}
PATH_SUFFIXES lib64 lib
# Help the user find it if we cannot.
DOC "The ${CORIOLIS_INCLUDE_PATH_DESCRIPTION}"
)
@ -34,7 +34,7 @@ IF(UNIX)
FIND_LIBRARY(LIBMANAGER_LIBRARY_PATH
NAMES libmanager
PATHS ${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES lib${LIB_SUFFIX}
PATH_SUFFIXES lib64 lib
# Help the user find it if we cannot.
DOC "The ${CORIOLIS_INCLUDE_PATH_DESCRIPTION}"
)
@ -50,7 +50,7 @@ IF(UNIX)
FIND_LIBRARY(CORIOLIS_PYTHON_LIBRARY_PATH
NAMES pycrlcore
PATHS ${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES lib${LIB_SUFFIX}
PATH_SUFFIXES lib64 lib
# Help the user find it if we cannot.
DOC "${CORIOLIS_LIBRARY_PATH_DESCRIPTION}"
)

View File

@ -1,6 +1,6 @@
# -*- mode: CMAKE; explicit-buffer-name: # "CMakeLists.txt<crlcore/doc/crlcore>" -*-
set ( htmlInstallDir share/doc/coriolis2/en/html/crlcore )
set ( htmlInstallDir share/doc/coriolis2/en/html/doc/crlcore )
set ( latexInstallDir share/doc/coriolis2/en/latex/crlcore )
set ( doxExtras closed.png
open.png

View File

@ -9,7 +9,7 @@
html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 {
font-size: 11pt;
/* The Open Sans font family is supplied by TexLive. */
font-family: "Open Sans", Verdana, sans-serif;;
font-family: "Roboto", "Open Sans", Verdana, sans-serif;;
}
html {
@ -598,7 +598,7 @@
*/
div.fragment {
font-family: "Monospace";
font-family: "Roboto Mono", "Monospace";
font-size: 80%;
border: none;
/*border-width: thin; */
@ -610,6 +610,16 @@
margin-right: 5%
}
div.fragment a.code:link,
div.fragment a.code:visited,
div.fragment a.codeRef:link,
div.fragment a.codeRef:visited {
text-decoration: none;
font-weight: bold;
color: black;
border: none;
}
div.line {
white-space: pre;
padding: 0pt;
@ -631,7 +641,7 @@
*/
a.el, a.elRef {
font-family: Courier;
font-family: "Roboto Mono", Courier;
font-weight: bold;
font-size: 110%;
color: black;
@ -698,7 +708,7 @@
}
table.memname * {
font-family: "Monospace";
font-family: "Roboto Mono", "Monospace";
}
@ -744,7 +754,7 @@
/*background-color: #eeeeff;*/
/*background-color: #EEEEEE;*/
/*background-color: #CCE6CA;*/
font-family: "Monospace";
font-family: "Roboto Mono", "Monospace";
}
.memTemplItemLeft, .memTemplItemRight {
@ -753,7 +763,7 @@
font-weight: bold;
}
.memItemLeft { font-size: 11px; width: 35%; }
.memItemLeft { font-size: 11px; width: 100pt; }
.memItemRight { font-size: 12px; }
.memTemplItemLeft { font-size: 11px; }
.memTemplItemRight { font-size: 12px; }

View File

@ -9,7 +9,7 @@
<table class="footer2">
<tr>
<td class="LFooter">Coriolis Core (CRL)</td>
<td class="RFooter"><small>Copyright &#169; 2008-2016 UPMC All rights reserved</small></td>
<td class="RFooter"><small>Copyright &#169; 2008-2020 Sorbonne Universite, All rights reserved</small></td>
</tr>
</table>
</body>

View File

@ -48,20 +48,20 @@ $(function() {
<div class="ttc" id="classCRL_1_1AcmSigda_html_a5e61fb60049f5a2dca1f2ca05fd5857a"><div class="ttname"><a href="classCRL_1_1AcmSigda.html#a5e61fb60049f5a2dca1f2ca05fd5857a">CRL::AcmSigda::load</a></div><div class="ttdeci">static Cell * load(std::string benchmark)</div></div>
<div class="ttc" id="classCRL_1_1AcmSigda_html"><div class="ttname"><a href="classCRL_1_1AcmSigda.html">CRL::AcmSigda</a></div><div class="ttdoc">A Parser of ACM/Sigda 89&amp;#39; benchmarks. </div><div class="ttdef"><b>Definition:</b> AcmSigda.h:33</div></div>
<div class="ttc" id="namespaceHurricane_html"><div class="ttname"><a href="namespaceHurricane.html">Hurricane</a></div></div>
<div class="ttc" id="namespaceCRL_html"><div class="ttname"><a href="namespaceCRL.html">CRL</a></div><div class="ttdoc">The namespace of Coriolis Core. </div><div class="ttdef"><b>Definition:</b> Environment.h:26</div></div>
<div class="ttc" id="namespaceCRL_html"><div class="ttname"><a href="namespaceCRL.html">CRL</a></div><div class="ttdoc">The namespace of Coriolis Core. </div><div class="ttdef"><b>Definition:</b> Environment.h:24</div></div>
</div><!-- fragment --></div><!-- contents -->
<br>
<hr>
<table class="footer1">
<tr>
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Thu Nov 12 2020</small></td>
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
</tr>
</table>
<table class="footer2">
<tr>
<td class="LFooter">Coriolis Core (CRL)</td>
<td class="RFooter"><small>Copyright &#169; 2008-2016 UPMC All rights reserved</small></td>
<td class="RFooter"><small>Copyright &#169; 2008-2020 Sorbonne Universite, All rights reserved</small></td>
</tr>
</table>
</body>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -59,21 +59,21 @@ $(function() {
<div class="ttc" id="classCRL_1_1Banner_html_aa61a32222853ae9f4298302ca53788bc"><div class="ttname"><a href="classCRL_1_1Banner.html#aa61a32222853ae9f4298302ca53788bc">CRL::Banner::getAuthors</a></div><div class="ttdeci">const string &amp; getAuthors() const</div><div class="ttdef"><b>Definition:</b> Banner.h:177</div></div>
<div class="ttc" id="classCRL_1_1Banner_html"><div class="ttname"><a href="classCRL_1_1Banner.html">CRL::Banner</a></div><div class="ttdoc">Print Formatted Banners (on ttys). </div><div class="ttdef"><b>Definition:</b> Banner.h:114</div></div>
<div class="ttc" id="classCRL_1_1Banner_html_a240b3f305516b17eff31f684d0a5c643"><div class="ttname"><a href="classCRL_1_1Banner.html#a240b3f305516b17eff31f684d0a5c643">CRL::Banner::getName</a></div><div class="ttdeci">const string &amp; getName() const</div><div class="ttdef"><b>Definition:</b> Banner.h:173</div></div>
<div class="ttc" id="namespaceCRL_html"><div class="ttname"><a href="namespaceCRL.html">CRL</a></div><div class="ttdoc">The namespace of Coriolis Core. </div><div class="ttdef"><b>Definition:</b> Environment.h:26</div></div>
<div class="ttc" id="namespaceCRL_html"><div class="ttname"><a href="namespaceCRL.html">CRL</a></div><div class="ttdoc">The namespace of Coriolis Core. </div><div class="ttdef"><b>Definition:</b> Environment.h:24</div></div>
<div class="ttc" id="classCRL_1_1Banner_html_a9c6bee971231044f417aaac312abcb61"><div class="ttname"><a href="classCRL_1_1Banner.html#a9c6bee971231044f417aaac312abcb61">CRL::Banner::setPurpose</a></div><div class="ttdeci">void setPurpose(string purpose)</div></div>
</div><!-- fragment --></div><!-- contents -->
<br>
<hr>
<table class="footer1">
<tr>
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Mon Oct 28 2019</small></td>
<td class="LFooter"><small>Generated by doxygen 1.8.14 on Thu Nov 12 2020</small></td>
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
</tr>
</table>
<table class="footer2">
<tr>
<td class="LFooter">Coriolis Core (CRL)</td>
<td class="RFooter"><small>Copyright &#169; 2008-2016 UPMC All rights reserved</small></td>
<td class="RFooter"><small>Copyright &#169; 2008-2020 Sorbonne Universite, All rights reserved</small></td>
</tr>
</table>
</body>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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