text: ///////////////////////////////////////////////////////////////////////////////
  // BSD 3-Clause License
  //
  // Copyright (c) 2019, Nefelus Inc
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are met:
  //
  // * Redistributions of source code must retain the above copyright notice, this
  //   list of conditions and the following disclaimer.
  //
  // * Redistributions in binary form must reproduce the above copyright notice,
  //   this list of conditions and the following disclaimer in the documentation
  //   and/or other materials provided with the distribution.
  //
  // * Neither the name of the copyright holder nor the names of its
  //   contributors may be used to endorse or promote products derived from
  //   this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  // POSSIBILITY OF SUCH DAMAGE.
  
  #pragma once
  
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  
  #include "ZInterface.h"
  #include "array1.h"
  #include "atypes.h"
  #include "box.h"
  #include "db.h"
  #include "geom.h"
  #include "gseq.h"
  #include "qtype.h"
  #include "tech.h"
  
  using namespace odb;
  
  enum Ath__overlapAdjust
  {
    Z_noAdjust,
    Z_merge,
    Z_endAdjust
  };
  
  class Ath__net;
  
  class Ath__path
  {
   private:
    Ath__net* _net;
  
    union
    {
      struct
      {
        uint _level : 5;
        uint _trackNum : 12;
        uint _qRow : 5;
        uint _qCol : 5;
      } _from;
  
      uint _fromIterm;
    };
    union
    {
      struct
      {
        uint _level : 5;
        uint _trackNum : 12;
        uint _qRow : 5;
        uint _qCol : 5;
      } _to;
  
      uint _toIterm;
    };
    uint _num;
  
   public:
  };
  
  class Ath__via
  {
   private:
    uint _trackNum : 12;
    uint _xy : 10;
    uint _masterNum : 10;
  
    uint _wire1 : 10;
    uint _wire2 : 10;
    uint _node : 12;  // TODO
  
   public:
  };
  
  class Ath__track;
  
  class Ath__searchBox
  {
   private:
    int  _ll[2];
    int  _ur[2];
    uint _level;
    uint _dir;
    uint _ownId;
    uint _otherId;
    uint _type;
  
   public:
    Ath__searchBox(int x1, int y1, int x2, int y2, uint l, int dir = -1);
    Ath__searchBox(Ath__box* bb, uint l, int dir = -1);
    Ath__searchBox(Ath__searchBox* bb, uint l, int dir = -1);
    Ath__searchBox();
    void set(int x1, int y1, int x2, int y2, uint l, int dir);
    void setMidPointSearch();
    int  loXY(uint d);
    int  loXY(uint d, int loBound);
    int  hiXY(uint d);
    int  hiXY(uint d, int hiBound);
    void setLo(uint d, int xy);
    void setHi(uint d, int xy);
    void setType(uint v);
    uint getType();
  
    uint getDir();
    uint getLevel();
    void setDir(int v = -1);
    void setLevel(uint v);
    void setOwnerId(uint v, uint other = 0);
    uint getOwnerId();
    uint getOtherId();
    uint getLength();
    void printCoords(FILE* fp, char* msg);
    void setMaxBox(Ath__searchBox* bb);
    bool outside(int x1, int y1, int x2, int y2);
  };
  
  class Ath__wire
  {
   private:
    uint _id;
    uint _srcId;  // TODO-OPTIMIZE
    uint _boxId;
    uint _otherId;
  
    Ath__track* _track;
    Ath__wire*  _next;
  
    int _xy;  // TODO offset from track start in large dimension
    int _len;
  
    int _base;
    int _width : 24;
  
    uint _flags : 6;
    // 0=wire, 2=obs, 1=pin, 3=power or SET BY USER
  
    uint _dir : 1;
    uint _ext : 1;
  
   public:
    void reset();
    // void set(int xy1, int xy2);
    void set(uint dir, int* ll, int* ur);
    void search(int xy1, int xy2, uint& cnt, Ath__array1D<uint>* idTable);
    void search1(int xy1, int xy2, uint& cnt, Ath__array1D<uint>* idTable);
  
    void       setNext(Ath__wire* w) { _next = w; };
    Ath__wire* getNext() { return _next; };
    uint       getFlags() { return _flags; };
    uint       getBoxId();
    void       setExt(uint ext) { _ext = ext; };
    uint       getExt() { return _ext; };
    uint       getId() { return _id; };
    void       setOtherId(uint id);
    uint       getOtherId();
    bool       isPower();
    bool       isTilePin();
    bool       isTileBus();
    uint       getOwnerId();
    uint       getSrcId();
    void       getCoords(Ath__searchBox* box);
    int        getXY() { return _xy; }
    void       getCoords(int* x1, int* y1, int* x2, int* y2, uint* dir);
  
    // void makeZuiObject(Ath__zui *zui, Ath__boxType type, int layer);
  
    friend class Ath__track;
    friend class Ath__grid;
    friend class Ath__gridTable;
    friend class dbBlockHandle;
  
    // Extraction
    void       printOneWire(FILE* ptfile);
    void       printWireNeighbor(uint                      met,
                                 Ath__array1D<Ath__wire*>* topNeighbor,
                                 Ath__array1D<Ath__wire*>* botNeighbor);
    int        wireOverlap(Ath__wire* w, int* len1, int* len2, int* len3);
    Ath__wire* getPoolWire(AthPool<Ath__wire>* wirePool);
    Ath__wire* makeWire(AthPool<Ath__wire>* wirePool, int xy1, uint len);
    Ath__wire* makeCoupleWire(AthPool<Ath__wire>* wirePool,
                              int                 targetHighTracks,
                              Ath__wire*          w2,
                              int                 xy1,
                              uint                len,
                              uint                wtype);
    void       setXY(int xy1, uint len);
    dbNet*     getNet();
  };
  
  class Ath__grid;
  
  class Ath__track
  {
   private:
    int _x;  // you need only one
    int _y;
  
    int         _base;
    Ath__track* _hiTrack;
    Ath__track* _lowTrack;
  
    Ath__wire** _marker;
    Ath__wire** _eMarker;
    uint        _markerCnt;
    uint        _searchMarkerIndex;
  
    uint       _targetMarker;
    Ath__wire* _targetWire;
  
    Ath__grid* _grid;
  
    uint _num : 20;
    uint _markerModulo : 12;
  
    // int _width:20; // to be removed
    int        _width : 19;
    uint       _lowest : 1;
    uint       _widthIndex : 4;  // 0 is std width
    uint       _shift : 4;
    uint       _centered : 1;
    uint       _blocked : 1;
    uint       _full : 1;
    Ath__wire* _tmpHead;
    bool       _ordered;
  
   public:
    void set(Ath__grid* g,
             int        x,
             int        y,
             uint       n,
             uint       width,
             uint       markerLen,
             uint       markerCnt,
             int        base);
    void freeWires(AthPool<Ath__wire>* pool);
    bool place(Ath__wire* w, int markIndex1, int markIndex2);
    bool place(Ath__wire* w, int markIndex1);
    uint setExtrusionMarker(int markerCnt, int start, uint markerLen);
    bool placeTrail(Ath__wire* w, uint m1, uint m2);
  
    bool       overlapCheck(Ath__wire* w, int markIndex1, int markIndex2);
    bool       isAscendingOrdered(uint markerCnt, uint* wCnt);
    Ath__grid* getGrid();
    Ath__wire* getWire_Linear(uint markerCnt, uint id);
    Ath__wire* getNextWire(Ath__wire* wire);
    uint       search(int                 xy1,
                      int                 xy2,
                      uint                markIndex1,
                      uint                markIndex2,
                      Ath__array1D<uint>* idtable);
    uint       search1(int                 xy1,
                       int                 xy2,
                       uint                markIndex1,
                       uint                markIndex2,
                       Ath__array1D<uint>* idTable);
  
    bool checkAndplace(Ath__wire* w, int markIndex1);
    bool checkMarker(int markIndex);
    bool checkAndplacerOnMarker(Ath__wire* w, int markIndex);
    uint getAllWires(Ath__array1D<Ath__wire*>* boxTable, uint markerCnt);
    void resetExtFlag(uint markerCnt);
    void linkWire(Ath__wire*& w1, Ath__wire*& w2);
  
    Ath__track* getNextSubTrack(Ath__track* subt, bool tohi);
    int         getBase() { return _base; };
    void        setHiTrack(Ath__track* hitrack);
    void        setLowTrack(Ath__track* lowtrack);
    Ath__track* getHiTrack();
    Ath__track* getLowTrack();
    Ath__track* nextTrackInRange(uint& delt,
                                 uint  trackDist,
                                 uint  srcTrack,
                                 bool  tohi);
    int         nextSubTrackInRange(Ath__track*& tstrack,
                                    uint&        delt,
                                    uint         trackDist,
                                    uint         srcTrack,
                                    bool         tohi);
    void        setLowest(uint lst) { _lowest = lst; };
  
    friend class Ath__gridTable;
    friend class Ath__grid;
    friend class Ath__wire;
  
    uint removeMarkedNetWires();
  
    // EXTRACTION
  
    bool place2(Ath__wire* w, int mark1, int mark2);
    void insertWire(Ath__wire* w, int mark1, int mark2);
    uint initTargetTracks(uint sourceTrack, uint trackDist, bool tohi);
    void findNeighborWire(Ath__wire*, Ath__array1D<Ath__wire*>*, bool);
    uint searchSpread(uint  srcTrack,
                      void* ip,
                      uint  trackDist,
                      uint  met,
                      void (*doSpread)(void*, uint, void*, void*, void*));
    void getTrackWires(std::vector<Ath__wire*>& ctxwire);
    void buildDgContext(Ath__array1D<odb::SEQ*>* dgContext,
                        Ath__wire**&             allWire,
                        int&                     awcnt,
                        int&                     a1wcnt);
    int  getBandWires(Ath__array1D<Ath__wire*>* bandWire);
    uint couplingCaps(Ath__grid*          resGrid,
                      uint                currentTrack,
                      uint                ccTrackDist,
                      uint                ccDomain,
                      ZInterface*         context,
                      Ath__array1D<uint>* ccTable,
                      uint                met,
                      void (*coupleAndCompute)(int*, void*),
                      void* compPtr);
  
    uint findOverlap(Ath__wire*                origWire,
                     uint                      ccDomain,
                     Ath__array1D<Ath__wire*>* wTable,
                     Ath__array1D<Ath__wire*>* nwTable,
                     Ath__grid*                ccGrid,
                     Ath__array1D<Ath__wire*>* ccTable,
                     ZInterface*               context,
                     uint                      met,
                     void (*coupleAndCompute)(int*, void*),
                     void* compPtr);
  
    void       initTargetWire(int noPowerWire);
    Ath__wire* nextTargetWire(int noPowerWire);
    Ath__wire* getTargetWire();
    void       adjustMetalFill();
    void       adjustOverlapMakerEnd(uint markerCnt);
    void       adjustOverlapMakerEnd(uint markerCnt, int start, uint markerLen);
    uint       trackContextOn(int                orig,
                              int                end,
                              int                base,
                              int                width,
                              uint               firstContextTrack,
                              Ath__array1D<int>* context);
  
    void dealloc(AthPool<Ath__wire>* pool);
  };
  class Ath__quadTable;
  class Ath__gridTable;
  
  class Ath__grid
  {
   private:
    Ath__gridTable* _gridtable;
    Ath__track**    _trackTable;
    uint*           _blockedTrackTable;
    uint            _trackFilledCnt;
    float           _emptyTrackCnt;
    uint            _freeTrackCnt;
    uint            _trackCnt;
    uint*           _subTrackCnt;
    int             _base;
    int             _max;
  
    int _start;  // laterraly
    int _end;
  
    int _lo[2];
    int _hi[2];
  
    int  _width;
    int  _pitch;
    uint _level;
    uint _layer;
    uint _dir;
    int  _markerLen;
    uint _markerCnt;
    uint _searchLowTrack;
    uint _searchHiTrack;
    uint _searchLowMarker;
    uint _searchHiMarker;
    uint _placed : 1;
  
    // void (*coupleAndCompute)(int *, void *), void *compPtr;
    void* _coupleAndCompute;
    void* _compPtr;
  
    // AthArray<Ath__wire*> *_wireTable;
    // AthArray<Ath__via*> *_viaTable;
  
    uint                 _widthTable[8];
    uint                 _shiftTable[8];
    AthPool<Ath__track>* _trackPoolPtr;
    AthPool<Ath__wire>*  _wirePoolPtr;
  
    uint _ignoreFlag;
    uint _schema;
    uint _wireType;
  
    uint _currentTrack;
    uint _lastFreeTrack;
  
   public:
    Ath__grid(AthPool<Ath__track>* trackPool,
              AthPool<Ath__wire>*  _wirePool,
              Ath__box*            bb,
              Ath__layer*          layer,
              uint                 markerCnt = 4);
    Ath__grid(Ath__gridTable*      gt,
              AthPool<Ath__track>* trackPool,
              AthPool<Ath__wire>*  wirePool,
              Ath__box*            bb,
              uint                 level,
              uint                 dir,
              uint                 num,
              uint                 width,
              uint                 pitch,
              uint                 markerCnt = 4);
    Ath__grid(Ath__gridTable*      gt,
              AthPool<Ath__track>* trackPool,
              AthPool<Ath__wire>*  wirePool,
              uint                 level,
              uint                 num,
              uint                 markerCnt);
    ~Ath__grid();
  
    Ath__gridTable* getGridTable() { return _gridtable; };
    void            setBoundaries(uint dir, int xlo, int ylo, int xhi, int yhi);
    void            setTracks(uint dir,
                              uint width,
                              uint pitch,
                              int  xlo,
                              int  ylo,
                              int  xhi,
                              int  yhi,
                              uint markerLen = 0);
    void            setPlaced();
    void            setSchema(uint v);
    bool            isPlaced();
  
    uint setFreeTracks();
    bool anyTrackAvailable();
  
    uint        addWireList(Ath__box* box);
    uint        getTrackCnt() { return _trackCnt; };
    Ath__track* getTrackPtr(uint n) { return _trackTable[n]; };
    uint        getTrackNum1(int xy);
    uint        getWidth();
    int         getXYbyWidth(int xy, uint* mark);
    Ath__track* addTrack(uint ii, uint markerCnt, int base);
    Ath__track* addTrack(uint ii, uint markerCnt);
    void        makeTracks(uint space, uint width);
    void        getBbox(Ath__box* bb);
    void        getBbox(Ath__searchBox* bb);
    uint        setExtrusionMarker();
    uint        getBoundaries(Ath__zui* zui, uint dd, uint layer);
    uint        addWire(Ath__box* box, int check);
    uint        addWire(Ath__box* box);
  
    uint       placeWire(Ath__searchBox* bb);
    uint       placeBox(uint id, int x1, int y1, int x2, int y2);
    uint       placeBox(dbBox* box, uint wtype, uint id);
    uint       placeBox(Ath__box* box);
    uint       placeBox(Ath__searchBox* bb);
    uint       getBucketNum(int xy);
    uint       getTrackNum(int* ll, uint d, uint* marker);
    Ath__wire* getWirePtr(uint wireId);
    void getBoxIds(Ath__array1D<uint>* wireIdTable, Ath__array1D<uint>* idtable);
    void getWireIds(Ath__array1D<uint>* wireIdTable, Ath__array1D<uint>* idtable);
  
    int  findEmptyTrack(int ll[2], int ur[2]);
    uint getFirstTrack(uint divider);
    int  getClosestTrackCoord(int xy);
    void makeZuiObjects(Ath__zui* zui);
    uint addWire(uint initTrack, Ath__box* box, int sortedOrder, int* height);
    Ath__wire* getPoolWire();
    Ath__wire* makeWire(Ath__box* box,
                        uint*     id,
                        uint*     m1,
                        uint*     m2,
                        uint      fullTrack);
    Ath__wire* makeWire(Ath__box* box, uint id, uint* m1);
    Ath__wire* makeWire(int* ll, int* ur, uint id, uint* m1);
    // Ath__wire *makeWire(int xy1, int xy2, uint id1, uint id2, uint type=0);
    Ath__wire* makeWire(uint dir,
                        int* ll,
                        int* ur,
                        uint id1,
                        uint id2,
                        uint type = 0);
  
    Ath__wire* makeWire(Ath__wire* w, uint type = 0);
  
    void  makeTrackTable(uint width, uint pitch, uint space = 0);
    uint  blockTracks(Ath__searchBox* box, bool ignoreLevel = true);
    uint  blockTracks(dbBlock* block, Ath__array1D<uint>* idTable);
    uint  blockTracks(Ath__box* box, uint ignoreLevel);
    uint  blockTracks(dbBlock* block, Ath__gridTable* wireSearch);
    float updateFreeTracks(float v);
    void  resetFreeTracks();
  
    void        freeTracksAndTables();
    uint        getAbsTrackNum(int xy);
    uint        getMinMaxTrackNum(int xy);
    bool        addOnTrack(uint track, Ath__wire* w, uint mark1, uint mark2);
    int         getTrackHeight(uint track);
    uint        getTrackNum(Ath__box* box);
    Ath__track* getTrackPtr(int* ll);
    Ath__track* getTrackPtr(int xy);
    Ath__track* getTrackPtr(uint ii, uint markerCnt, int base);
    Ath__track* getTrackPtr(uint ii, uint markerCnt);
    bool        isOrdered(bool ascending, uint* cnt);
    uint        search(Ath__searchBox*     bb,
                       Ath__array1D<uint>* idtable,
                       bool                wireIdFlag = false);
    uint        searchAllMarkers(Ath__searchBox*     bb,
                                 Ath__array1D<uint>* idtable,
                                 bool                wireIdFlag = false);
  
    uint addWireNext(uint initTrack, Ath__box* box, int sortedOrder, int* height);
    // Ath__wire *getNewWire(Ath__box *box, int xy1, int xy2, uint *id);
    Ath__wire* getNewWire(Ath__box* box, int* ll, int* ur, uint* id);
    Ath__wire* makeWireCut(Ath__box* box,
                           uint*     id,
                           uint*     m1,
                           uint*     m2,
                           uint      cutFlag);
    Ath__wire* makeWireExt(Ath__box* box,
                           uint*     id,
                           uint*     m1,
                           uint*     m2,
                           uint      extFlag,
                           int       height);
    uint       placeWire(uint       initTrack,
                         Ath__wire* w,
                         uint       mark1,
                         uint       mark2,
                         int        sortedOrder,
                         int*       height);
    uint       addWireCut(uint      cutFlag,
                          uint      initTrack,
                          Ath__box* box,
                          int       sortedOrder,
                          int*      height);
    uint       addWireExt(uint      cutFlag,
                          uint      initTrack,
                          Ath__box* box,
                          int       sortedOrder,
                          int*      height);
  
    void getBusObs(Ath__zui* zui);
    void getBoxes(Ath__array1D<uint>* table);
    uint getBoxes(uint ii, Ath__array1D<uint>* table);
  
    void       placeAgainSortedThru(uint                 space,
                                    uint                 width,
                                    AthArray<Ath__box*>* obsTable);
    uint       getDir();
    uint       getLevel();
    Ath__wire* getWire_Linear(uint id);
    void       setIgnoreFlag(uint v);
  
    int  placeTileWire(uint            wireType,
                       uint            id,
                       Ath__searchBox* bb,
                       int             loMarker,
                       int             initTrack,
                       bool            skipResetSize);
    void getBuses(Ath__array1D<Ath__box*>* boxtable, uint width);
    uint white(Ath__searchBox* bb, Ath__array1D<uint>* idtable, Ath__grid* g);
    Ath__wire* makeWhite(uint                dir,
                         int*                lo,
                         int*                hi,
                         Ath__array1D<uint>* idtable,
                         Ath__grid*          g);
  
    friend class Ath__quadTable;
    friend class Ath__gridTable;
  
    uint removeMarkedNetWires();
    void setSearchDomain(uint domainAdjust);
    uint searchLowMarker() { return _searchLowMarker; };
    uint searchHiMarker() { return _searchHiMarker; };
  
    // EXTRACTION
    uint                searchSpread(void* ip,
                                     uint  spreadTrackDist,
                                     void (*doSpread)(void*, uint, void*, void*, void*));
    void                buildDgContext(int gridn, int base);
    int                 getBandWires(int                       hiXY,
                                     uint                      couplingDist,
                                     uint&                     wireCnt,
                                     Ath__array1D<Ath__wire*>* bandWire,
                                     int*                      limitArray);
    uint                couplingCaps(Ath__grid*          resGrid,
                                     uint                couplingDist,
                                     ZInterface*         context,
                                     Ath__array1D<uint>* ccTable,
                                     void (*coupleAndCompute)(int*, void*),
                                     void* compPtr);
    AthPool<Ath__wire>* getWirePoolPtr();
    uint                placeWire(Ath__wire* w);
    uint                defaultWireType();
    void                setDefaultWireType(uint v);
    uint                search(Ath__searchBox*     bb,
                               uint*               gxy,
                               Ath__array1D<uint>* idtable,
                               Ath__grid*          g);
    void                adjustMetalFill();
    void                adjustOverlapMakerEnd();
    void                initContextGrids();
    void                initContextTracks();
    void                contextsOn(int orig, int len, int base, int width);
    void                gridContextOn(int orig, int len, int base, int width);
  
    int  initCouplingCapLoops(uint couplingDist,
                              void (*coupleAndCompute)(int*, void*),
                              void* compPtr,
                              bool  startSearchTrack = true,
                              int   startXY          = 0);
    int  couplingCaps(int   hiXY,
                      uint  couplingDist,
                      uint& wireCnt,
                      void (*coupleAndCompute)(int*, void*),
                      void* compPtr,
                      int*  limitArray);
    int  dealloc(int hiXY);
    void dealloc();
  };
  class Ath__gridStack  // DELETE after porting on new DB
  {
   private:
    Ath__grid* _nextGridTable[2];
    Ath__grid* _thruGridTable[2];
    Ath__grid* _cornerGridTable[4][2];
    int        _loDivide[2];
    int        _hiDivide[2];
    uint       _level[2];
    uint       _nextLevel[2];
    Rect       _bb;
  
   public:
    Ath__gridStack(Ath__layer**         met,
                   Ath__layer**         nextMet,
                   uint*                loFlag,
                   uint*                hiFlag,
                   int*                 loLine,
                   int*                 hiLine,
                   int*                 ll,
                   int*                 ur,
                   AthPool<Ath__track>* trackPool,
                   AthPool<Ath__wire>*  wirePool);
    ~Ath__gridStack();
    bool isThruPlaced(uint dir);
    uint getGridOutlines(Ath__zui* zui);
    uint blockTracks(AthArray<Ath__box*>* obsTable);
    uint addWire(Ath__box* box, uint trackRange);
  
    uint        placeSortedThru(uint       dir,
                                Ath__box** boxArray,
                                uint       cnt,
                                uint       width,
                                uint       space);
    uint        blockTracks(Ath__box* boxList, uint dir);
    uint        blockTracks(Ath__box* box);
    Ath__grid** getCornerGrid(uint type,
                              uint space,
                              uint width,
                              uint layer0,
                              uint layer2);
    uint        placeCornerSorted(uint       type,
                                  Ath__box** boxArray,
                                  Ath__box** boxArrayNext,
                                  uint       cnt,
                                  uint       space,
                                  uint       width);
    Ath__grid*  getThruGrid(uint dir, uint layer, uint space, uint width);
    Ath__grid*  getThruGrid(uint dir);
    Ath__grid*  getNextGrid(uint dir);
    Ath__grid*  getNextGrid(uint dir, uint layer, uint space, uint width);
    uint        placeSortedNext(uint       dir,
                                Ath__box** boxArray,
                                int*       heightArray,
                                uint       cnt,
                                uint       space,
                                uint       width);
    void        getBusObs(Ath__zui* zui);
    bool        isPlacedCorner(uint type);
  };
  class Ath__gridTile
  {
   private:
    Ath__grid** _gTable;
    uint        _levelCnt;
    Rect        _bb;
  
    bool                 _poolFlag;
    AthPool<Ath__track>* _trackPool;
    AthPool<Ath__wire>*  _wirePool;
  
   public:
    Ath__gridTile(uint                 levelCnt,
                  int                  x1,
                  int                  y1,
                  int                  x2,
                  int                  y2,
                  AthPool<Ath__track>* trackPoolPtr = NULL,
                  AthPool<Ath__wire>*  wirePoolPtr  = NULL);
    ~Ath__gridTile();
    Ath__grid* addGrid(Ath__box* bb,
                       uint      level,
                       uint      dir,
                       uint      layerNum,
                       uint      width,
                       uint      pitch);
    Ath__grid* addGrid(int  x1,
                       int  y1,
                       int  x2,
                       int  y2,
                       uint level,
                       uint dir,
                       uint layerNum,
                       uint width,
                       uint pitch);
    void       searchWires(Ath__searchBox* bb, Ath__array1D<uint>* idtable);
  
    void       getBounds(int* x1, int* y1, int* x2, int* y2);
    Ath__grid* getGrid(uint level);
    void       addGrid(Ath__grid* g);
  
    void getBuses(Ath__array1D<Ath__box*>* boxTable, dbTech* tech);
  };
  
  class Ath__gridTable
  {
   private:
    Ath__grid***         _gridTable;
    Ath__box             _bbox;
    Ath__box             _maxSearchBox;
    bool                 _setMaxArea;
    Rect                 _rectBB;
    uint                 _rowCnt;
    uint                 _colCnt;
    uint                 _rowSize;
    uint                 _colSize;
    AthPool<Ath__track>* _trackPool;
    AthPool<Ath__wire>*  _wirePool;
    uint                 _schema;
    uint                 _overlapAdjust;
    uint                 _powerMultiTrackWire;
    uint                 _signalMultiTrackWire;
    uint                 _offlineOverlapTouch;
    uint                 _offlineOverlapCnt;
    uint                 _overlapTouchCheck;
    uint                 _noPowerSource;
    uint                 _noPowerTarget;
    uint                 _CCshorts;
    uint                 _CCtargetHighTracks;
    uint                 _CCtargetHighMarkedNet;
    bool                 _targetTrackReversed;
    bool                 _allNet;
    bool                 _handleEmptyOnly;
    bool                 _useDbSdb;
    uint                 _ccFlag;
  
    uint  _ccContextDepth;
    uint* _ccContextLength;
  
    Ath__array1D<int>** _ccContextArray;
  
    AthPool<odb::SEQ>*         _seqPool;
    Ath__array1D<odb::SEQ*>*** _dgContextArray;  // array
  
    uint* _dgContextDepth;      // not array
    uint* _dgContextPlanes;     // not array
    uint* _dgContextTracks;     // not array
    uint* _dgContextBaseLvl;    // not array
    int*  _dgContextLowLvl;     // not array
    int*  _dgContextHiLvl;      // not array
    uint* _dgContextBaseTrack;  // array
    int*  _dgContextLowTrack;   // array
    int*  _dgContextHiTrack;    // array
    int** _dgContextTrackBase;  // array
  
    int _signalPowerNotAlignedOverlap;
    int _powerNotAlignedOverlap;
    int _signalNotAlignedOverlap;
    int _signalOverlap;
    int _powerOverlap;
    int _signalPowerOverlap;
    int _powerSignalOverlap;
  
    dbBlock* _block;
  
    uint _wireCnt;
  
    // void (*coupleAndCompute)(int *, void *), void *compPtr;
    void* _coupleAndCompute;
    void* _compPtr;
  
    Ath__array1D<Ath__wire*>* _bandWire;
  
   public:
    Ath__gridTable(Ath__box* bb,
                   uint      rowSize,
                   uint      colSize,
                   uint      layer,
                   uint      dir,
                   uint      width,
                   uint      pitch);
    Ath__gridTable(dbBox* bb,
                   uint   rowSize,
                   uint   colSize,
                   uint   layer,
                   uint   dir,
                   uint   width,
                   uint   pitch,
                   uint   minWidth);
    Ath__gridTable(Rect* bb,
                   uint  layer,
                   uint  dir,
                   uint  width,
                   uint  pitch,
                   uint  minWidth);
    Ath__gridTable(Rect* bb,
                   uint  rowCnt,
                   uint  colCnt,
                   uint* width,
                   uint* pitch,
                   uint* spacing,
                   int*  X1 = NULL,
                   int*  Y1 = NULL);
    ~Ath__gridTable();
    Ath__grid* getGrid(uint row, uint col);
    void       init1(uint memChunk, uint rowSize, uint colSize, uint dx, uint dy);
    uint       getColCnt();
    uint       getRowCnt();
    Ath__wire* getWirePtr(uint id);
    void       releaseWire(uint wireId);
    Ath__box*  maxSearchBox() { return &_maxSearchBox; };
    int        xMin();
    int        xMax();
    int        yMin();
    int        yMax();
    uint       getRowNum(int x);
    uint       getColNum(int y);
    bool       getRowCol(int x1, int y1, uint* row, uint* col);
    Ath__wire* addBox(Ath__box* bb);
    Ath__wire* addBox(dbBox* bb, uint wtype, uint id);
    bool       addBox(uint row, uint col, dbBox* bb);
    uint       setExtrusionMarker(uint startRow, uint startCol);
  
    uint       getBoxes(Ath__box* bb, Ath__array1D<Ath__box*>* table);
    bool       isOrdered(bool ascending);
    uint       search(Ath__zui* zui, uint row, uint col);
    uint       search(Ath__searchBox*     bb,
                      uint                row,
                      uint                col,
                      Ath__array1D<uint>* idTable,
                      bool                wireIdFlag);
    uint       search(Ath__searchBox* bb, Ath__array1D<uint>* idTable);
    uint       search(Ath__box* bb);
    Ath__wire* getWire_Linear(uint instId);
    uint       white(Ath__searchBox*     bb,
                     uint                row,
                     uint                col,
                     Ath__array1D<uint>* idTable,
                     Ath__grid*          g);
  
    uint addBox(int  x1,
                int  y1,
                int  x2,
                int  y2,
                uint level,
                uint id1,
                uint id2,
                uint wireType);
    uint search(int                 x1,
                int                 y1,
                int                 x2,
                int                 y2,
                uint                row,
                uint                col,
                Ath__array1D<uint>* idTable,
                bool                wireIdFlag);
    void getCoords(Ath__searchBox* bb, uint wireId);
    void setMaxArea(int x1, int y1, int x2, int y2);
    void resetMaxArea();
  
    void removeMarkedNetWires();
  
    // EXTRACTION
  
    void                     setDefaultWireType(uint v);
    uint                     searchSpread(void*                ip,
                                          uint                 spreadTrackDist,
                                          std::vector<dbNet*>& inets,
                                          char*                bbox,
                                          void (*doSpread)(void*, uint, void*, void*, void*));
    void                     buildDgContext(int base, uint level, uint dir);
    Ath__array1D<odb::SEQ*>* renewDgContext(uint gridn, uint trackn);
    uint                     couplingCaps(Ath__gridTable*     resGridTable,
                                          uint                couplingDist,
                                          ZInterface*         context,
                                          Ath__array1D<uint>* ccTable,
                                          void (*coupleAndCompute)(int*, void*),
                                          void* compPtr);
    uint                     couplingCaps(uint        row,
                                          uint        col,
                                          Ath__grid*  resGrid,
                                          uint        couplingDist,
                                          ZInterface* context);
    void                     getBox(uint  wid,
                                    int*  x1,
                                    int*  y1,
                                    int*  x2,
                                    int*  y2,
                                    uint* level,
                                    uint* id1,
                                    uint* id2,
                                    uint* wireType);
    void getCCdist(uint wid, uint* width, uint* level, uint* id1, uint* id2);
    void getIds(uint wid, uint* id1, uint* id2, uint* wtype);
    uint search(Ath__searchBox*     bb,
                uint*               gxy,
                uint                row,
                uint                col,
                Ath__array1D<uint>* idtable,
                Ath__grid*          g);
    uint getOverlapAdjust() { return _overlapAdjust; };
    uint getOverlapTouchCheck() { return _overlapTouchCheck; };
    uint targetHighTracks() { return _CCtargetHighTracks; };
    uint targetHighMarkedNet() { return _CCtargetHighMarkedNet; };
    void setCCFlag(uint ccflag) { _ccFlag = ccflag; };
    uint getCcFlag() { return _ccFlag; };
    uint contextDepth() { return _ccContextDepth; };
    void setContextLength(uint level, uint contextLength)
    {
      _ccContextLength[level] = contextLength;
    };
    Ath__array1D<int>**        contextArray() { return _ccContextArray; };
    AthPool<odb::SEQ>*         seqPool() { return _seqPool; };
    Ath__array1D<odb::SEQ*>*** dgContextArray() { return _dgContextArray; };
    int** dgContextTrackBase() { return _dgContextTrackBase; };
    uint* dgContextBaseTrack() { return _dgContextBaseTrack; };
    int*  dgContextLowTrack() { return _dgContextLowTrack; };
    int*  dgContextHiTrack() { return _dgContextHiTrack; };
    bool  allNet() { return _allNet; };
    void  setAllNet(bool allnet) { _allNet = allnet; };
    bool  handleEmptyOnly() { return _handleEmptyOnly; };
    void  setHandleEmptyOnly(bool handleEmptyOnly)
    {
      _handleEmptyOnly = handleEmptyOnly;
    };
    uint     noPowerSource() { return _noPowerSource; };
    void     setNoPowerSource(uint nps) { _noPowerSource = nps; };
    uint     noPowerTarget() { return _noPowerTarget; };
    void     setNoPowerTarget(uint npt) { _noPowerTarget = npt; };
    void     incrOfflineOverlapCnt() { _offlineOverlapCnt++; };
    void     incrOfflineOverlapTouch() { _offlineOverlapTouch++; };
    void     incrCCshorts() { _CCshorts++; };
    void     setExtControl(dbBlock*                   block,
                           bool                       useDbSdb,
                           uint                       adj,
                           uint                       npsrc,
                           uint                       nptgt,
                           uint                       ccUp,
                           bool                       allNet,
                           uint                       contextDepth,
                           Ath__array1D<int>**        contextArray,
                           uint*                      contextLength,
                           Ath__array1D<odb::SEQ*>*** dgContextArray,
                           uint*                      dgContextDepth,
                           uint*                      dgContextPlanes,
                           uint*                      dgContextTracks,
                           uint*                      dgContextBaseLvl,
                           int*                       dgContextLowLvl,
                           int*                       dgContextHiLvl,
                           uint*                      dgContextBaseTrack,
                           int*                       dgContextLowTrack,
                           int*                       dgContextHiTrack,
                           int**                      dgContextTrackBase,
                           AthPool<odb::SEQ>*         seqPool);
    bool     usingDbSdb() { return _useDbSdb; }
    void     reverseTargetTrack();
    bool     targetTrackReversed() { return _targetTrackReversed; };
    void     adjustMetalFill();
    void     incrNotAlignedOverlap(Ath__wire* w1, Ath__wire* w2);
    void     incrSignalOverlap();
    void     incrPowerOverlap();
    void     incrSignalToPowerOverlap();
    void     incrPowerToSignallOverlap();
    void     incrMultiTrackWireCnt(bool isPower);
    void     adjustOverlapMakerEnd();
    void     dumpTrackCounts(FILE* fp);
    dbBlock* getBlock() { return _block; };
    void     setBlock(dbBlock* block) { _block = block; };
  
    int  couplingCaps(int   hiXY,
                      uint  couplingDist,
                      uint  dir,
                      uint& wireCnt,
                      void (*coupleAndCompute)(int*, void*),
                      void* compPtr,
                      bool  getBandWire,
                      int** limitArray);
    void initCouplingCapLoops(uint dir,
                              uint couplingDist,
                              void (*coupleAndCompute)(int*, void*),
                              void* compPtr,
                              int*  startXY = NULL);
    int  dealloc(uint dir, int hiXY);
    void dealloc();
  
    uint getWireCnt();
  };
  