text:
///////////////////////////////////////////////////////////////////////////////
// Authors: Ilgweon Kang and Lutong Wang
//          (respective Ph.D. advisors: Chung-Kuan Cheng, Andrew B. Kahng),
//          based on Dr. Jingwei Lu with ePlace and ePlace-MS
//
//          Many subsequent improvements were made by Mingyu Woo
//          leading up to the initial release.
//
// BSD 3-Clause License
//
// Copyright (c) 2018, The Regents of the University of California
// 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.
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////
//
//  This code was implemented by mgwoo at 18.01.17
//
//          http://mgwoo.github.io/
//
///////////////////////////////////////////////////////

#include "replace_private.h"
#include "lefdefIO.h"
#include "bookShelfIO.h"

#include "timing.h"
#include "timingSta.h"
#include <iostream>
#include <boost/functional/hash.hpp>

using namespace std;
using Replace::NetInfo;
using Replace::Circuit;

Replace::Circuit::Circuit() : lefManufacturingGrid(DBL_MIN) {
#ifdef USE_GOOGLE_HASH
  lefMacroMap.set_empty_key(INIT_STR);
  lefViaMap.set_empty_key(INIT_STR);
  lefLayerMap.set_empty_key(INIT_STR);
  lefSiteMap.set_empty_key(INIT_STR);

  defComponentMap.set_empty_key(INIT_STR);
  defPinMap.set_empty_key(INIT_STR);
  defRowY2OrientMap.set_empty_key(INT_MAX);
#endif
};

Replace::Circuit::Circuit(vector< string >& lefStor, string defFilename, bool isVerbose)
      : lefManufacturingGrid(DBL_MIN) {
#ifdef USE_GOOGLE_HASH
    lefMacroMap.set_empty_key(INIT_STR);
    lefViaMap.set_empty_key(INIT_STR);
    lefLayerMap.set_empty_key(INIT_STR);
    lefSiteMap.set_empty_key(INIT_STR);

    defComponentMap.set_empty_key(INIT_STR);
    defPinMap.set_empty_key(INIT_STR);
    defRowY2OrientMap.set_empty_key(INT_MAX);
#endif

    Init(lefStor, defFilename, isVerbose);
  }

void Replace::Circuit::Init(vector< string >& lefStor, string defFilename,
    bool isVerbose) {
  PrintProcBegin("LefParsing");
  ParseLef(lefStor, isVerbose);
  PrintProcEnd("LefParsing");
  PrintProcBegin("DefParsing");
  ParseDef(defFilename, isVerbose);
  PrintProcEnd("DefParsing");
}

//
// The below global variable is updated.
//
//
// terminalInstance // terminalCNT
// moduleInstance // moduleCNT
// netInstnace // netCNT
// pinInstance // pinCNT
// row_st // row_cnt
//
// shapeMap // (Fixed cell can have rectilinear polygon)

//
// numNonRectangularNodes // required bookshelf writing - *.shape aware
// totalShapeCount // required bookshelf writing - *.shape aware
//
// terminal_pmin
// terminal_pmax
//
// grow_pmin
// grow_pmax
//
// rowHeight
//
//

// global variable.. to write output as DEF
namespace Replace {
  Circuit __ckt;
}

using Replace::__ckt;

// lef 2 def unit convert
static prec l2d = 0.0f;

//
// To support book-shelf based tools, scale down all values..
//
// Set unitX as siteWidth
// Set unitY as Vertical routing pitch (in lowest metal)
//
static prec unitX = 0.0f;
static prec unitY = 0.0f;

//
// To prevent mis-matching in ROW offset.
//
static prec offsetX = PREC_MAX;
static prec offsetY = PREC_MAX;

// module & terminal Makp
//
// first : nodeName
// second, first : isModule (true -> moduleInst // false -> termInst)
// second, second : corresponding index
//
static HASH_MAP< string, pair< bool, int > > moduleTermMap;

//
// Metal1 Name.
// It usually depends on the lef files
//
static string metal1Name;

// helper function for LEF/DEF in siteorient
static const char*
orientStr(int orient) {
  switch(orient) {
    case 0:
      return ((const char*)"N");
    case 1:
      return ((const char*)"W");
    case 2:
      return ((const char*)"S");
    case 3:
      return ((const char*)"E");
    case 4:
      return ((const char*)"FN");
    case 5:
      return ((const char*)"FW");
    case 6:
      return ((const char*)"FS");
    case 7:
      return ((const char*)"FE");
  };
  return ((const char*)"BOGUS");
}

// orient coordinate shift
inline static std::pair<float, float>
GetOrientPoint( float x, float y, float w, float h, int orient ) {
  switch(orient) {
    case 0: // North
      return std::make_pair(x, y);
    case 1: // West
      return std::make_pair(h-y, x);
    case 2: // South
      return std::make_pair(w-x, h-y); // x-flip, y-flip
    case 3: // East
      return std::make_pair(y, w-x);
    case 4: // Flipped North
      return std::make_pair(w-x, y); // x-flip
    case 5: // Flipped West
      return std::make_pair(y, x); // x-flip from West
    case 6: // Flipped South
      return std::make_pair(x, h-y); // y-flip
    case 7: // Flipped East
      return std::make_pair(h-y, w-x); // y-flip from West
  }

  cout << "Warning: Weird Orientation: Set North... " << endl;
  return std::make_pair(x, y); // default
}

// Get Lower-left coordinates from rectangle's definition
inline static std::pair<float, float>
GetOrientLowerLeftPoint( float lx, float ly, float ux, float uy,
   float w, float h, int orient ) {
  switch(orient) {
    case 0: // North
      return std::make_pair(lx, ly); // verified
    case 1: // West
      return GetOrientPoint(lx, uy, w, h, orient);
    case 2: // South
      return GetOrientPoint(ux, uy, w, h, orient);
    case 3: // East
      return GetOrientPoint(ux, ly, w, h, orient);
    case 4: // Flipped North
      return GetOrientPoint(ux, ly, w, h, orient); // x-flip
    case 5: // Flipped West
      return GetOrientPoint(lx, ly, w, h, orient); // x-flip from west
    case 6: // Flipped South
      return GetOrientPoint(lx, uy, w, h, orient); // y-flip
    case 7: // Flipped East
      return GetOrientPoint(ux, uy, w, h, orient); // y-flip from west
  }

  cout << "Warning: Weird Orientation: Set North... " << endl;
  return std::make_pair(lx, ly); // default
}

// orient coordinate shift
inline static std::pair<float, float>
GetOrientSize( float w, float h, int orient ) {
  switch(orient) {
    // East, West, FlipEast, FlipWest
    case 1:
    case 3:
    case 5:
    case 7:
      return std::make_pair(h, w);
    // otherwise
    case 0:
    case 2:
    case 4:
    case 6:
      return std::make_pair(w, h);
  }

  cout << "Warning: Weird Orientation: Set North... " << endl;
  return std::make_pair(w, h);
}

// for Saving verilog information
// declaired here to send verilog -> timing inst..
static HASH_MAP< string, vector< NetInfo >, boost::hash< std::string > >
    netMap;

// save clockNets' index
// for DEF parsing
static vector< int > clockNetsDef;

// for Verilog parsing
static vector< string > clockNetsVerilog;

// from main.cpp
void ParseInput() {
  if(auxCMD == "" && lefStor.size() != 0 && defName != "") {
    inputMode = InputMode::lefdef;
    ParseLefDef();
  }
  else if(auxCMD != "" && lefStor.size() == 0 && defName == "") {
    inputMode = InputMode::bookshelf;
    ParseBookShelf();
  }

  if(verilogName != "") {
    SetVerilogTopModule();
  }
}

inline static bool IsPrecEqual(prec a, prec b) {
  return std::fabs(a - b) < std::numeric_limits< float >::epsilon();
}

//
// this will set below (global) parameter, needed to parse LEF/DEF file
//
// l2d,                 - lef to def scale difference
// metal1Name,          - metal1 Layer Name
// unitX, unitY         - scale down parameter for bookshelf porting
// offsetX, offsetY     - offset parameter to exactly fit on 'ROW' structure
//
void SetParameter() {
  // lef 2 def unit info setting
  SetDefDbu( __ckt.defUnit );
  PrintInfoInt("DefUnit", GetDefDbu());

  if(__ckt.lefLayerStor.size() == 0) {
    cout << "\n** ERROR : LAYER statements not exists in lef file!" << endl;
    exit(1);
  }

  metal1Name = "";
  // Metal1 Name extract
  for(auto& curLayer : __ckt.lefLayerStor) {
    if(!curLayer.hasType()) {
      continue;
    }
    if(strcmp(curLayer.type(), "ROUTING") == 0) {
      if( metal1Name == "" ) {
        metal1Name = string(curLayer.name());
        break;
      }
    }
  }
  PrintInfoString("LefMetal1Name", metal1Name);

#ifdef USE_GOOGLE_HASH
  // required for FIXED components(DEF) -> *.shape bookshelf
  shapeMap.set_empty_key(INIT_STR);

  // required for net(DEF) -> module fast access
  moduleTermMap.set_empty_key(INIT_STR);
#endif

  // unitX, unitY setting : RowHeight / 9 --> Converted Height: 9
  // RePlAce's Nesterov iteration parameter is optimized when cell height is around 9.
  PrintInfoString("DefSiteName", __ckt.defRowStor[0].macro());

  auto sitePtr = __ckt.lefSiteMap.find(string(__ckt.defRowStor[0].macro()));
  if( sitePtr == __ckt.lefSiteMap.end() ) {
    cout << "ERROR:  CANNOT find SITE: "
      << __ckt.defRowStor[0].macro() << " IN DEF" << endl;
    exit(1);
  }

  int siteSizeY = INT_CONVERT( GetDefDbu() * __ckt.lefSiteStor[sitePtr->second].sizeY() );

  SetUnitY(1.0 * siteSizeY / 9.0f);
  SetUnitX(GetUnitY());

  PrintInfoPrec( "ScaleDownUnit", GetUnitX() );

  // offsetX & offsetY : Minimum coordinate of ROW's x/y
  if(IsPrecEqual(offsetX, PREC_MAX)) {
    int rowMin = INT_MAX;
    for(auto& curRow : __ckt.defRowStor) {
      rowMin = (rowMin > curRow.x()) ? curRow.x() : rowMin;
    }

    // Note that OffsetX should follow siteSizeY, because unitX = unitY
    // and unitY comes from siteSizeY
    SetOffsetX( (rowMin % siteSizeY == 0)?
              0 : siteSizeY - (rowMin % siteSizeY) );
  }

  if(IsPrecEqual(offsetY, PREC_MAX)) {
    int rowMin = INT_MAX;
    for(auto& curRow : __ckt.defRowStor) {
      rowMin = (rowMin > curRow.y()) ? curRow.y() : rowMin;
    }

    SetOffsetY( (rowMin % siteSizeY == 0)?
              0 : siteSizeY - (rowMin % siteSizeY) );
  }

  PrintInfoPrecPair( "OffsetCoordi", GetOffsetX(), GetOffsetY());

  // init for local global vars
  l2d = GetDefDbu();
  unitX = GetUnitX();
  unitY = GetUnitY();
  offsetX = GetOffsetX();
  offsetY = GetOffsetY();
}

void SetVerilogTopModule() {
  verilogTopModule = __ckt.defDesignName;
}

void ParseLefDef() {
  // for input parse only
  //
  // Replace::Circuit __ckt(lefStor, defName, "");
  //
  __ckt.Init(lefStor, defName, ( gVerbose >= 1 ));

  SetParameter();

  GenerateRow(__ckt);
  GenerateModuleTerminal(__ckt);

  GenerateDummyCell(__ckt);
  GenerateFullRow(__ckt);

  if(__ckt.defNetStor.size() > 0) {
    GenerateNetDefOnly(__ckt);
  }
  else {
    cout << "** ERROR:  Cannot Find any Net information "
      << "(Check NETS statement in DEF) " << endl;
      exit(1);
  }

  PrintProc("LEF/DEF Parsing Success!");

  // do weird things..
  FPOS tier_min, tier_max;
  int tier_row_cnt = 0;

  get_mms_3d_dim(&tier_min, &tier_max, &tier_row_cnt);
  transform_3d(&tier_min, &tier_max, tier_row_cnt);
  post_read_3d();
}

void WriteDef(const char* defOutput) {
  MODULE* curModule = NULL;

  // moduleInstnace -> defComponentStor
  for(int i = 0; i < moduleCNT; i++) {
    curModule = &moduleInstance[i];
    auto cmpPtr = __ckt.defComponentMap.find(string(curModule->Name()));
    if(cmpPtr == __ckt.defComponentMap.end()) {
      cout << "** ERROR:  Module Instance ( " << curModule->Name()
           << " ) does not exist in COMPONENT statement (defComponentMap) "
           << endl;
      exit(1);
    }

    // update into PLACED status
    if(!__ckt.defComponentStor[cmpPtr->second].isPlaced()) {
      __ckt.defComponentStor[cmpPtr->second].setPlacementStatus(
          DEFI_COMPONENT_PLACED);
    }

    // update into corresponding coordinate
    //
    // unitX & unitY is used to recover scaling

    int x = INT_CONVERT(curModule->pmin.x * unitX) - offsetX;
    int y = INT_CONVERT(curModule->pmin.y * unitY) - offsetY;

    // x-coordinate, y-coordinate, cell-orient
    auto orientPtr = __ckt.defRowY2OrientMap.find(y);

    __ckt.defComponentStor[cmpPtr->second].setPlacementLocation(
        x, y,
        (orientPtr != __ckt.defRowY2OrientMap.end()) ? orientPtr->second : 0);

    // cout << curModule->name << ": " << curModule->pmin.x << " " <<
    // curModule->pmin.y << endl;
  }

  FILE* fp = fopen(defOutput, "w");
  if(!fp) {
    cout << "** ERROR:  Cannot open " << defOutput << " (DEF WRITING)" << endl;
    exit(1);
  }

  __ckt.WriteDef(fp);
}

////////
//
// Generate Module&Terminal Instance
//
// helper function for FIXED cells(in DEF Components), which can have multiple
// rectangles,
// i.e. it is corresponded to *.shape
//
// The shapeMap & shapeStor is updated in here.
// numNonRectangularNodes, totalShapeCount also updated in here
//
// COMPONENTS -> MACRO(TYPE: BLOCK) -> OBS -> LAYER -> RECT
//
// return type :
// true -- the sub-rectangular has been found and added
// false -- the sub-rectangular has not been found.
bool AddShape(int defCompIdx, int lx, int ly,
    float w, float h, int orient) {
  string compName = string(__ckt.defComponentStor[defCompIdx].id());
  string macroName = string(__ckt.defComponentStor[defCompIdx].name());

  // reference MACRO in lef
  auto mcPtr = __ckt.lefMacroMap.find(macroName);
  if(mcPtr == __ckt.lefMacroMap.end()) {
    cout << "** ERROR:  Macro Instance ( " << macroName
         << " ) does not exist in COMPONENT statement (lefMacroMap) " << endl;
    exit(1);
  }

  // Check whether MACRO have CLASS statement
  int macroIdx = mcPtr->second;
  if(!__ckt.lefMacroStor[macroIdx].hasClass()) {
    cout << "** ERROR: Macro Instance ( " << __ckt.lefMacroStor[macroIdx].name()
         << " ) does not have Class! (lefMacroStor) " << endl;
    exit(1);
  }

  //
  // only for MACRO TYPE == BLOCK cases
  // & OBS command must exist in LEF
  //
  if(strcmp(__ckt.lefMacroStor[macroIdx].macroClass(), "BLOCK") != 0 ||
     __ckt.lefObsStor[macroIdx].size() == 0) {
    return false;
  }

  // already updated into shapeMap, then skip
  //    if( shapeMap.find( compName ) != shapeMap.end() ) {
  //        cout << "already updated: " << compName << endl;
  //        return ;
  //    }
  //    cout << "compName: " << compName << endl;

  bool isMetal1 = false;
  int shapeCnt = 0;

  for(auto& curObs : __ckt.lefObsStor[macroIdx]) {
    lefiGeometries* curGeom = curObs.geometries();

    // LAYER Metal1 <-- lefiGeomLayerE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //
    //
    // LAYER VIA1 <-- Skip for this
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE

    for(int j = 0; j < curGeom->numItems(); j++) {
      // Meets 'Metal1' Layer
      if(curGeom->itemType(j) == lefiGeomLayerE &&
         string(curGeom->getLayer(j)) == metal1Name) {
        //                cout << j << " " << curGeom->getLayer(j) << endl;
        isMetal1 = true;

        continue;
      }

      // calculate BBox
      if(isMetal1 && curGeom->itemType(j) == lefiGeomRectE) {
        lefiGeomRect* rect = curGeom->getRect(j);

        // shape Name -> bunch of shapeStor's index
        if(shapeMap.find(compName) == shapeMap.end()) {
          vector< int > tmpStor;
          tmpStor.push_back(shapeStor.size());
          shapeMap[compName] = tmpStor;
        }
        else {
          shapeMap[compName].push_back(shapeStor.size());
        }
        totalShapeCount++;

        std::pair<float, float> rectLxLy =
          GetOrientLowerLeftPoint( rect->xl, rect->yl, rect->xh, rect->yh,
                                    w, h, orient );

        std::pair<float, float> rectSize =
          GetOrientSize( rect->xh - rect->xl, rect->yh - rect->yl, orient );

        // finally pushed into shapeStor
        /*
        shapeStor.push_back(SHAPE(
            string("shape_") + to_string(shapeCnt), compName,
            shapeStor.size(),
            (l2d * rect->xl + lx + offsetX) / unitX,  // lx
            (l2d * rect->yl + ly + offsetY) / unitY,  // ly
            l2d * (rect->xh - rect->xl) / unitX,      // xWidth
            l2d * (rect->yh - rect->yl) / unitY));    // yWidth
        */

        // finally pushed into shapeStor
        shapeStor.push_back(SHAPE(
            string("shape_") + to_string(shapeCnt), compName,
            shapeStor.size(),
            (l2d * rectLxLy.first + lx + offsetX) / unitX,  // lx
            (l2d * rectLxLy.second + ly + offsetY) / unitY,  // ly
            l2d * rectSize.first / unitX,      // xWidth
            l2d * rectSize.second / unitY));    // yWidth

        shapeCnt++;
      }
      // now, meets another Layer
      else if(isMetal1 && curGeom->itemType(j) == lefiGeomLayerE) {
        break;
      }
    }
    // firstMetal was visited
    if(isMetal1) {
      break;
    }
  }

  if(isMetal1) {
    numNonRectangularNodes++;
  }

  return (isMetal1) ? true : false;
}

void SetSizeForObsMacro(int macroIdx, MODULE* curModule, int orient) {
  bool isMetal1 = false;

  prec llx = PREC_MAX, lly = PREC_MAX;
  prec urx = PREC_MIN, ury = PREC_MIN;

  // original macro size info to handle orientation
  float w = __ckt.lefMacroStor[macroIdx].sizeX();
  float h = __ckt.lefMacroStor[macroIdx].sizeY();

  for(auto& curObs : __ckt.lefObsStor[macroIdx]) {
    lefiGeometries* curGeom = curObs.geometries();

    // LAYER Metal1 <-- lefiGeomLayerE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //
    //
    // LAYER VIA1 <-- Skip for this
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE

    for(int j = 0; j < curGeom->numItems(); j++) {
      // Meets 'Metal1' Layer
      if(curGeom->itemType(j) == lefiGeomLayerE &&
         string(curGeom->getLayer(j)) == metal1Name) {
        //                cout << j << " " << curGeom->getLayer(j) << endl;
        isMetal1 = true;
        continue;
      }

      // calculate BBox
      if(isMetal1 && curGeom->itemType(j) == lefiGeomRectE) {
        lefiGeomRect* rect = curGeom->getRect(j);

        // Orientation handling
        std::pair<float, float> rectLxLy =
          GetOrientLowerLeftPoint( rect->xl, rect->yl, rect->xh, rect->yh,
                                    w, h, orient );

        std::pair<float, float> rectSize =
          GetOrientSize( rect->xh - rect->xl, rect->yh - rect->yl, orient );

        // Extract BBox information
        llx = ( llx > rectLxLy.first )?   rectLxLy.first : llx;
        lly = ( lly > rectLxLy.second )?  rectLxLy.second : lly;

        urx = ( urx < rectLxLy.first + rectSize.first )?
                  rectLxLy.first + rectSize.first : urx;
        ury = ( ury < rectLxLy.second + rectSize.second )?
                  rectLxLy.second + rectSize.second : ury;

//        cout << rect->xl << " " << rect->yl << endl;
//        cout << rect->xh << " " << rect->yh << endl;
      }
      // now, meets another Layer
      else if(isMetal1 && curGeom->itemType(j) == lefiGeomLayerE) {
        break;
      }
    }
    // firstMetal was visited
    if(isMetal1) {
      break;
    }
  }

  if( !isMetal1 || llx == PREC_MAX ) {
    cout << "ERROR: LEF's OBS statements don't have metal1 statements!!" << endl;
    exit(1);
  }

  // finalize modules' Size
  curModule->size.Set(
      (l2d * (urx - llx)) / unitX,
      (l2d * (ury - lly)) / unitY );
}

//
// defComponentStor(non FIXED cell) -> moduleInstance
// defComponentStor(FIXED cell), defPinStor -> terminalInstnace
//
// terminal_pmin & terminal_pmax must be updated...
void GenerateModuleTerminal(Replace::Circuit& __ckt) {
  moduleInstance =
      (MODULE*)malloc(sizeof(MODULE) * __ckt.defComponentStor.size());

  // to fast traverse when building TerminalInstance
  vector< int > fixedComponent;

  MODULE* curModule = NULL;
  defiComponent* curComp = NULL;
  lefiMacro* curMacro = NULL;

  moduleCNT = 0;

  // not 1-to-1 mapping (into moduleInstnace), so traverse by index
  for(size_t i = 0; i < __ckt.defComponentStor.size(); i++) {
    curComp = &(__ckt.defComponentStor[i]);

    curModule = &moduleInstance[moduleCNT];
    new(curModule) MODULE();

    if(curComp->isFixed()) {
      fixedComponent.push_back(i);
      continue;
    }

    // pmin info update
    if(curComp->isPlaced()) {
      // only when is already placed
      curModule->pmin.Set(((prec)curComp->placementX() + offsetX) / unitX,
                          ((prec)curComp->placementY() + offsetY) / unitY);
    }
    else {
      curModule->pmin.SetZero();
    }

    auto macroPtr = __ckt.lefMacroMap.find(string(curComp->name()));
    if(macroPtr == __ckt.lefMacroMap.end()) {
      cout << "\n** ERROR : Cannot find MACRO cell in lef files: "
           << curComp->name() << endl;
      exit(1);
    }

    curMacro = &__ckt.lefMacroStor[macroPtr->second];

    if(!curMacro->hasSize()) {
      cout << "\n** ERROR : Cannot find MACRO SIZE in lef files: "
           << curComp->name() << endl;
      exit(1);
    }

    if(strcmp(curMacro->macroClass(), "BLOCK") == 0 &&
       __ckt.lefObsStor[macroPtr->second].size() != 0) {
      // cout << "BLOCK/OBS: " << curMacro->name() << endl;

      // Orient handling for MS-Placement
      SetSizeForObsMacro(macroPtr->second, curModule,
          curComp->isUnplaced()?
          0 : curComp->placementOrient());
    }
    else {
      // size info update from LEF Macro
      curModule->size.Set(l2d * curMacro->sizeX() / unitX,
                          l2d * curMacro->sizeY() / unitY);
    }

    if(fabs(curModule->size.y - rowHeight) > PREC_EPSILON) {
      defMacroCnt++;
//      cout << "MACRO: " << curComp->id() << " " << curModule->size.y << endl;
    }

    // set half_size
    curModule->half_size.Set(curModule->size.x / 2, curModule->size.y / 2);

    // set center coordi
    curModule->center.SetAdd(curModule->pmin, curModule->half_size);

    // set pinMax coordi
    curModule->pmax.SetAdd(curModule->pmin, curModule->size);

    // set area
    curModule->area = curModule->size.GetProduct();

    // set which tier
    curModule->tier = 0;

    string moduleName = curComp->id();

    // set Name
//    strcpy(curModule->name, moduleName.c_str());
    moduleNameStor.push_back( moduleName );

    // set Index
    curModule->idx = moduleCNT;

    moduleTermMap[moduleName] = make_pair(true, moduleCNT);

    // check
    //        curModule->Dump(string("Macro ") + to_string(moduleCNT));
    moduleCNT++;
  }
  //    cout << moduleCNT << endl;

  // memory cutting
//  moduleInstance =
//      (MODULE*)realloc(moduleInstance, sizeof(MODULE) * moduleCNT);

  //
  // Terminal Update
  //

  // Check the Blockage
  vector< int > blockageIdxStor;
  for(auto& curBlockage : __ckt.defBlockageStor) {
    int idx = &curBlockage - &__ckt.defBlockageStor[0];
    if(curBlockage.hasPlacement()) {
      blockageIdxStor.push_back(idx);
    }
  }

  TERM* curTerm = NULL;
  terminalCNT = 0;
  terminalInstance = (TERM*)malloc(
      sizeof(TERM) * (blockageIdxStor.size() + fixedComponent.size() +
                      __ckt.defPinStor.size()));

  // for fixed cells.
  for(auto& curIdx : fixedComponent) {
    curTerm = &terminalInstance[terminalCNT];
    new(curTerm) TERM();

    curComp = &(__ckt.defComponentStor[curIdx]);

    curTerm->idx = terminalCNT;

    // pmin info update
    curTerm->pmin.Set(((prec)curComp->placementX() + offsetX) / unitX,
                      ((prec)curComp->placementY() + offsetY) / unitY);

    //        cout << "Fixed: " << curComp->name() << endl;
    auto macroPtr = __ckt.lefMacroMap.find(string(curComp->name()));
    if(macroPtr == __ckt.lefMacroMap.end()) {
      cout << "\n** ERROR : Cannot find MACRO cell in lef files: "
           << curComp->name() << endl;
      exit(1);
    }

    int macroIdx = macroPtr->second;
    curMacro = &__ckt.lefMacroStor[macroIdx];

    if(!curMacro->hasSize()) {
      cout << "\n** ERROR : Cannot find MACRO SIZE in lef files: "
           << curComp->name() << endl;
      exit(1);
    }

    // check whether this nodes contains sub-rectangular sets
    // Note that unplaced cells is regarded as North orientation (default)
    AddShape(curIdx, curComp->placementX(), curComp->placementY(),
                  curMacro->sizeX(), curMacro->sizeY(), // for orient
                  curComp->isUnplaced()?
                  0 : curComp->placementOrient());          // for orient

    // Orient consideration
    // Note that unplaced cells is regarded as North orientation (default)
    std::pair<float, float> macroSize =
      GetOrientSize(curMacro->sizeX(), curMacro->sizeY(),
          curComp->isUnplaced()?
          0 : curComp->placementOrient());

    curTerm->size.Set(l2d * macroSize.first   / unitX,
                      l2d * macroSize.second  / unitY);

    // Always visible blockage: terminal
    curTerm->isTerminalNI = false;

    // set center coordi
    curTerm->center.x = curTerm->pmin.x + curTerm->size.x / 2;
    curTerm->center.y = curTerm->pmin.y + curTerm->size.y / 2;

    // set pinMax coordi
    curTerm->pmax.SetAdd(curTerm->pmin, curTerm->size);

    // set area
    curTerm->area = curTerm->size.GetProduct();

    string termName = curComp->id();

    // set Name
    terminalNameStor.push_back(termName);

    // set tier
    moduleTermMap[termName] = make_pair(false, terminalCNT);

    terminalCNT++;
  }

  // for pin
  for(auto& curPin : __ckt.defPinStor) {
    curTerm = &terminalInstance[terminalCNT];
    new(curTerm) TERM();

//    strcpy(curTerm->name, curPin.pinName());
    terminalNameStor.push_back(curPin.pinName());

    curTerm->idx = terminalCNT;
    curTerm->IO = (strcmp(curPin.direction(), "INPUT") == 0) ? 0 : 1;
    curTerm->pmin.Set((curPin.placementX() + offsetX) / unitX,
                      (curPin.placementY() + offsetY) / unitY);
    curTerm->isTerminalNI = true;

    // since size == 0, pmin == center == pmax;
    curTerm->pmax.Set(curTerm->pmin);
    curTerm->center.Set(curTerm->pmin);

    moduleTermMap[string(curTerm->Name())] = make_pair(false, terminalCNT);

    //        curTerm->Dump();
    terminalCNT++;
  }

  int blockageCnt = 0;
  for(auto& curBlockIdx : blockageIdxStor) {
    string blockName = "replace_blockage_" + to_string(blockageCnt++);
    curTerm = &terminalInstance[terminalCNT];
    new(curTerm) TERM();

//    strcpy(curTerm->name, blockName.c_str());
    terminalNameStor.push_back(blockName);

    curTerm->idx = terminalCNT;
    curTerm->IO = 2;

    defiBlockage* curBlockage = &__ckt.defBlockageStor[curBlockIdx];
    if(curBlockage->numRectangles() > 0) {
      curTerm->pmin.Set((curBlockage->xl(0) + offsetX) / unitX,
                        (curBlockage->yl(0) + offsetY) / unitY);
      curTerm->pmax.Set((curBlockage->xh(0) + offsetX) / unitX,
                        (curBlockage->yh(0) + offsetY) / unitY);
      curTerm->center.Set((curTerm->pmin.x + curTerm->pmax.x) / 2.0,
                          (curTerm->pmin.y + curTerm->pmax.y) / 2.0);
    }
    else {
      cout << "** ERROR: RePlAce requires RECT in BLOCKAGES (DEF) " << endl;
      exit(1);
    }
    curTerm->isTerminalNI = false;
    curTerm->size.Set(curTerm->pmax.x - curTerm->pmin.x,
                      curTerm->pmax.y - curTerm->pmin.y);
    curTerm->area = curTerm->size.GetProduct();
    // since size == 0, pmin == center == pmax;
    // curTerm->pmax.Set(curTerm->pmin);
    // curTerm->center.Set(curTerm->pmin);

    moduleTermMap[blockName] = make_pair(false, terminalCNT);

    curTerm->Dump();
    terminalCNT++;
  }
  PrintInfoInt("MacroCount", defMacroCnt);
  PrintInfoInt("NumModules", moduleCNT);
  PrintInfoInt("NumTerminals", terminalCNT);
}

/////////////////////////////////////////////////////
// ArrayInfo class

int ArrayInfo::GetCoordiX( float x ) {
  return INT_CONVERT ( ((x) - lx_ ) / siteSizeX_ );
}

int ArrayInfo::GetCoordiY( float y ) {
  return INT_CONVERT ( ((y) - ly_ ) / siteSizeY_ );
}

int ArrayInfo::GetLowerX( float x ) {
  return int( ((x) - lx_ ) / siteSizeX_ );
}

int ArrayInfo::GetLowerY( float y ) {
  return int( ((y) - ly_ ) / siteSizeY_ );
}

int ArrayInfo::GetUpperX (float x) {
  float val = ( x - lx_ ) / siteSizeX_;
  int intVal = int( val );
  return (fabs(val-intVal) <= 0.0001)? intVal : intVal+1;
}

int ArrayInfo::GetUpperY (float y) {
  float val = ( y - ly_ ) / siteSizeY_;
  int intVal = int( val );
  return (fabs(val-intVal) <= 0.0001)? intVal : intVal+1;
}

/////////////////////////////////////////////////////

// Dummy Cell Generation procedure to be aware of fragmented-Row
void GenerateDummyCell(Replace::Circuit& __ckt) {
  defiRow *minRow = &__ckt.defRowStor[0];
  // get the lowest one
  for(auto curRow : __ckt.defRowStor) {
    if(minRow->y() < minRow->y()) {
      minRow = &curRow;
    }
  }

  auto sitePtr = __ckt.lefSiteMap.find(string(minRow->macro()));
  if(sitePtr == __ckt.lefSiteMap.end()) {
    cout << "\n** ERROR:  Cannot find SITE in lef files: " << minRow->macro()
         << endl;
    exit(1);
  }
  // Set Site Size
  float siteSizeX_ =
       l2d * __ckt.lefSiteStor[sitePtr->second].sizeX() / unitX;
  float siteSizeY_ =
       l2d * __ckt.lefSiteStor[sitePtr->second].sizeY() / unitY;

  // cout << "siteSize: " << siteSizeX_ << " " << siteSizeY_ << endl;

  //Set LayoutArea
  DieRect dieRect_ = GetCoreFromRow();

  // Set Array Counts
  int numX_ = INT_CONVERT( (dieRect_.urx - dieRect_.llx) / siteSizeX_ );
  int numY_ = INT_CONVERT( (dieRect_.ury - dieRect_.lly) / siteSizeY_ );
  // cout << "rowCnt: " << numX_ << " " << numY_ << endl;

  float rowSizeY_ = siteSizeY_;
  // cout << "rowSize: " << rowSizeX_ << " " << rowSizeY_ << endl;

  // Empty Array Fill
  ArrayInfo::CellInfo* arr_ = new ArrayInfo::CellInfo[numX_ * numY_];
  for(int i = 0; i < numX_ * numY_; i++) {
    arr_[i] = ArrayInfo::CellInfo::Empty;
  }

  ArrayInfo ainfo(dieRect_.llx, dieRect_.lly, siteSizeX_, siteSizeY_);

  // ROW array fill
  for(int i=0; i<row_cnt ; i++) {
    ROW* curRow = &row_st[i];

    // cout << "ROW lx: " << ainfo.GetCoordiX(curRow->pmin.x)
    //   << " ux: " << ainfo.GetUpperX(curRow->pmax.x);
    // cout << " ly: " << ainfo.GetCoordiY(curRow->pmin.y)
    //   << " uy: " << ainfo.GetUpperY(curRow->pmax.y) << endl;

    for(int i = ainfo.GetCoordiX(curRow->pmin.x);
        i < ainfo.GetCoordiX(curRow->pmax.x); i++) {
      for(int j = ainfo.GetCoordiY(curRow->pmin.y);
          j < ainfo.GetCoordiY(curRow->pmax.y); j++) {
        arr_[j * numX_ + i] = ArrayInfo::CellInfo::Row;
      }
    }
  }

  // TERM array fill
  for(int i=0; i<terminalCNT; i++) {
    TERM* curTerm = &terminalInstance[i];
    if( curTerm -> isTerminalNI ) {
      continue;
    }

    // TERM-nonShape array fill
    if( shapeMap.find( curTerm->Name() ) == shapeMap.end()) {
      // curTerm->pmin.Dump("curTermPmin");
      // curTerm->pmax.Dump("curTermPmax");
      // cout << "TERM lx: " << ainfo.GetLowerX(curTerm->pmin.x)
      //   << " ux:" << ainfo.GetUpperX(curTerm->pmax.x);
      // cout << " ly: " << ainfo.GetLowerY(curTerm->pmin.y)
      //   << " uy:" << ainfo.GetUpperY(curTerm->pmax.y)
      //   << endl;
      for(int i = ainfo.GetLowerX(curTerm->pmin.x);
          i < ainfo.GetUpperX(curTerm->pmax.x); i++) {
        // out of CoreArea placed-cell handling
        if( i < 0 || i >= numX_ ) {
          continue;
        }
        for(int j = ainfo.GetLowerY(curTerm->pmin.y);
            j < ainfo.GetUpperY(curTerm->pmax.y); j++) {

          // out of CoreArea placed-cell handling
          if( j < 0 || j >= numY_ ) {
            continue;
          }
          arr_[j * numX_ + i] = ArrayInfo::CellInfo::Cell;
        }
      }
    }
    // TERM-Shape array fill
    else {
      for(auto& curIdx : shapeMap[curTerm->Name()]) {
        float llx = shapeStor[curIdx].llx,
              lly = shapeStor[curIdx].lly,
              width = shapeStor[curIdx].width,
              height = shapeStor[curIdx].height;
        // cout << "SHAPE pmin: " << llx << " " << lly << endl;
        // cout << "      pmax: " << llx + width  << " " << lly + height << endl;
        // cout << "lx: " << ainfo.GetLowerX(llx)
        //   << " ux:" << ainfo.GetUpperX(llx + width )
        //   << " ly: " << ainfo.GetLowerY(lly)
        //   << " uy:" << ainfo.GetUpperY(lly + height)
        //   << endl;

        for(int i = ainfo.GetLowerX(llx);
            i < ainfo.GetUpperX(llx + width); i++) {
          // out of CoreArea placed-cell handling
          if( i < 0 || i >= numX_ ) {
            continue;
          }
          for(int j = ainfo.GetLowerY(lly);
              j < ainfo.GetUpperY(lly + height); j++) {
            // out of CoreArea placed-cell handling
            if( j < 0 || j >= numY_ ) {
              continue;
            }
            // cout << "[Fixed] i: " << i << ", j: " << j << endl;
            arr_[j * numX_ + i] = ArrayInfo::CellInfo::Cell;
          }
        }
      }
    }
  }

  int idxCnt = terminalCNT;
  vector< TERM > dummyTermStor_;
  for(int j = 0; j < numY_; j++) {
    for(int i = 0; i < numX_; i++) {
      if(arr_[j * numX_ + i] == ArrayInfo::CellInfo::Empty) {
        int startX = i;
        while(i < numX_ && arr_[j * numX_ + i] == ArrayInfo::CellInfo::Empty) {
          i++;
        }
        int endX = i;

        TERM curTerm;
        // strcpy(curTerm.Name(),
        //   string("dummy_inst_" + to_string(dummyTermStor_.size())).c_str());
        //
        terminalNameStor.push_back(
               string("dummy_inst_" + to_string(dummyTermStor_.size())).c_str());
        curTerm.pmin.Set((prec)(dieRect_.llx + siteSizeX_ * startX),
                         (prec)(dieRect_.lly + j * siteSizeY_));
        curTerm.pmax.Set((prec)(dieRect_.llx + siteSizeX_ * endX),
                         (prec)(dieRect_.lly + j * siteSizeY_ + rowSizeY_));
        curTerm.size.Set((prec)((endX - startX) * siteSizeX_),
                         (prec)(rowSizeY_));

        curTerm.center.Set( curTerm.pmin.x + 0.5*curTerm.size.x,
                            curTerm.pmin.y + 0.5*curTerm.size.y);

        curTerm.isTerminalNI = false;
        curTerm.area = curTerm.size.GetProduct();
        curTerm.idx = idxCnt++;
        dummyTermStor_.push_back(curTerm);
      }
    }
  }
  PrintInfoInt("Inserted Dummy Terms", dummyTermStor_.size());

  // termCnt Updates
  int prevCnt = terminalCNT;
  terminalCNT += dummyTermStor_.size();
//  terminalInstance =
//    (TERM*) realloc( terminalInstance, sizeof(TERM) * terminalCNT);

  // copy into original instances
  for(int i=prevCnt; i<terminalCNT; i++) {
    terminalInstance[i] = dummyTermStor_[i - prevCnt];
  }
}

/////////////////////////////////////////////
//  DieRect Instances
//
DieRect GetDieFromProperty( bool isScaleDown ) {
  // Set DieArea from PROPERTYDEFINITIONS
  string llxStr = "FE_CORE_BOX_LL_X", urxStr = "FE_CORE_BOX_UR_X";
  string llyStr = "FE_CORE_BOX_LL_Y", uryStr = "FE_CORE_BOX_UR_Y";

  DieRect retRect;
  for(auto& prop : __ckt.defPropStor) {
    if(strcmp(prop.propType(), "design") != 0) {
      continue;
    }

    if(string(prop.propName()) == llxStr) {
      retRect.llx = (isScaleDown)?
        (prop.number() * l2d / unitX) :
        (prop.number() * l2d);
    }
    else if(string(prop.propName()) == llyStr) {
      retRect.lly = (isScaleDown)?
        (prop.number() * l2d / unitY) :
        (prop.number() * l2d);
    }
    else if(string(prop.propName()) == urxStr) {
      retRect.urx = (isScaleDown)?
        (prop.number() * l2d / unitX) :
        (prop.number() * l2d);
    }
    else if(string(prop.propName()) == uryStr) {
      retRect.ury = (isScaleDown)?
        (prop.number() * l2d / unitY) :
        (prop.number() * l2d);
    }
  }
  return retRect;
}

DieRect GetDieFromDieArea( bool isScaleDown ) {
  DieRect retRect;
  defiPoints points = __ckt.defDieArea.getPoint();
  if(points.numPoints >= 2) {
    retRect.llx = (isScaleDown)? points.x[0] / unitX : points.x[0];
    retRect.lly = (isScaleDown)? points.y[0] / unitY : points.y[0];
    retRect.urx = (isScaleDown)? points.x[1] / unitX : points.x[1];
    retRect.ury = (isScaleDown)? points.y[1] / unitY : points.y[1];
  }
  for(int i = 0; i < points.numPoints; i++) {
    cout << points.x[i] << " " << points.y[i] << endl;
  }

  retRect.Dump();
  return retRect;
}

DieRect GetCoreFromRow() {

  float minX = FLT_MAX, minY = FLT_MAX;
  float maxX = FLT_MIN, maxY = FLT_MIN;

  for(auto& curRow : __ckt.defRowStor) {
    auto sitePtr = __ckt.lefSiteMap.find(string(curRow.macro()));
    if(sitePtr == __ckt.lefSiteMap.end()) {
      cout << "\n** ERROR:  Cannot find SITE in lef files: " << curRow.macro()
           << endl;
      exit(1);
    }
    lefiSite* lefSite = &__ckt.lefSiteStor[sitePtr->second];

    float curMinX = ( (curRow.x() + offsetX) / unitX );
    float curMinY = ( (curRow.y() + offsetY) / unitY );

    minX = (minX > curMinX) ? curMinX : minX;
    minY = (minY > curMinY) ? curMinY : minY;

    float curMaxX = ( (curRow.x() + offsetX +
          curRow.xNum() * l2d * lefSite->sizeX()) / unitX );
    float curMaxY = ( (curRow.y() + offsetY +
          curRow.yNum() * l2d * lefSite->sizeY()) / unitY );

    maxX = (maxX < curMaxX) ? curMaxX : maxX;
    maxY = (maxY < curMaxY) ? curMaxY : maxY;
  }

  return DieRect(minX, minY, maxX, maxY);
}

/////////////////////////////////////////////
//  Generate RowInstance
// defRowStor -> rowInstance
// this must update grow_pmin / grow_pmax, rowHeight
void GenerateRow(Replace::Circuit& __ckt) {
  // Get the sites from ROW statements
  // usual cases
  bool isFirst = true;
  int i = 0;

  row_cnt = __ckt.defRowStor.size();
  row_st = (ROW*)malloc(sizeof(ROW) * row_cnt);

  for(auto& row : __ckt.defRowStor) {
    auto sitePtr = __ckt.lefSiteMap.find(string(row.macro()));
    if(sitePtr == __ckt.lefSiteMap.end()) {
      cout << "\n** ERROR:  Cannot find SITE in lef files: " << row.macro()
           << endl;
      exit(1);
    }

    ROW* curRow = &row_st[i];

    new(curRow) ROW();

    curRow->pmin.Set((row.x() + offsetX) / unitX, (row.y() + offsetY) / unitY);
    curRow->size.Set(
        l2d * __ckt.lefSiteStor[sitePtr->second].sizeX() / unitX *
            row.xNum(),
        l2d * __ckt.lefSiteStor[sitePtr->second].sizeY() / unitY *
            row.yNum());

    curRow->pmax.Set(curRow->pmin.x + curRow->size.x,
                     curRow->pmin.y + curRow->size.y);

    if(isFirst) {
      grow_pmin.Set(curRow->pmin);
      grow_pmax.Set(curRow->pmax);

      rowHeight =
          l2d * __ckt.lefSiteStor[sitePtr->second].sizeY() / unitY;

//      if(INT_CONVERT(l2d * __ckt.lefSiteStor[sitePtr->second].sizeY()) %
//             INT_CONVERT(unitY) !=
//         0) {
//        int _rowHeight =
//            INT_CONVERT(l2d * __ckt.lefSiteStor[sitePtr->second].sizeY());
//        cout << endl
//             << "** ERROR: rowHeight \% unitY is not zero,  " << endl
//             << "          ( rowHeight : " << _rowHeight
//             << ", unitY : " << INT_CONVERT(unitY)
//             << ", rowHeight \% unitY : " << _rowHeight % INT_CONVERT(unitY)
//             << " )" << endl;
//        cout << "          so it causes serious problem in RePlACE" << endl
//             << endl;
//        cout << "          Use custom unitY in here using -unitY command, as a "
//                "divider of rowHeight"
//             << endl;
//        exit(1);
//      }
      isFirst = false;
    }
    else {
      grow_pmin.x = min(grow_pmin.x, (prec)curRow->pmin.x);
      grow_pmin.y = min(grow_pmin.y, (prec)curRow->pmin.y);

      grow_pmax.x = max(grow_pmax.x, (prec)curRow->pmax.x);
      grow_pmax.y = max(grow_pmax.y, (prec)curRow->pmax.y);
    }

    curRow->x_cnt = row.xNum();

    //
    // this is essential to DetailPlacer
    //
    // scale down to 1.
    //
    curRow->site_wid = curRow->site_spa = SITE_SPA = row.xStep() / unitX;

    curRow->ori = string(orientStr(row.orient()));
    curRow->isXSymmetry =
        (__ckt.lefSiteStor[sitePtr->second].hasXSymmetry()) ? true : false;

    curRow->isYSymmetry =
        (__ckt.lefSiteStor[sitePtr->second].hasYSymmetry()) ? true : false;

    curRow->isR90Symmetry =
        (__ckt.lefSiteStor[sitePtr->second].has90Symmetry()) ? true : false;

    //        curRow->Dump(to_string(i));
    i++;
  }
  PrintInfoPrecPair( "RowSize", SITE_SPA, rowHeight );
  PrintInfoInt( "NumRows", row_cnt );
}

// MS-Placement requires this!
void GenerateFullRow(Replace::Circuit& __ckt) {
  PrintProcBegin("Generate Un-fragmented Rows");
  if( row_st ) {
    free(row_st);
  }
  // Newly create the all ROW area for floorplan.
  // In here, I've used DESIGN FE_CORE_BOX_LL_X statements in
  // PROPERTYDEFINITIONS

  /*
  DieRect dieArea = GetDieFromProperty();
  if(dieArea.isNotInitialize()) {
    dieArea = GetDieFromDieArea();
  }
  if(dieArea.isNotInitialize()) {
    cout << "ERROR: DIEAREA ERROR" << endl;
    exit(1);
  }*/

  DieRect coreArea = GetCoreFromRow();

  PrintInfoPrecPair("CoreAreaLxLy", coreArea.llx, coreArea.lly );
  PrintInfoPrecPair("CoreAreaUxUy", coreArea.urx, coreArea.ury );

  // this portion is somewhat HARD_CODING
  // it regards there only one SITE definition per each design!

  defiRow* minRow = &__ckt.defRowStor[0];

  // get the lowest one
  for(auto curRow : __ckt.defRowStor) {
    if(minRow->y() < minRow->y()) {
      minRow = &curRow;
    }
  }

  auto sitePtr = __ckt.lefSiteMap.find(string(minRow->macro()));
  if(sitePtr == __ckt.lefSiteMap.end()) {
    cout << "\n** ERROR:  Cannot find SITE in lef files: " << minRow->macro()
         << endl;
    exit(1);
  }

  float siteX = l2d * __ckt.lefSiteStor[sitePtr->second].sizeX() / unitX;
  float siteY = l2d * __ckt.lefSiteStor[sitePtr->second].sizeY() / unitY;

  int rowCntX = INT_CONVERT( (coreArea.urx - coreArea.llx) / siteX );
  int rowCntY = INT_CONVERT( (coreArea.ury - coreArea.lly) / siteY );

  float rowSizeX = rowCntX * siteX;
  float rowSizeY = rowHeight = siteY;

  row_cnt = rowCntY;
  row_st = (ROW*)malloc(sizeof(ROW) * row_cnt);

  /////////////////////////
  // HARD CODE PART!!!!!
  //
  // 0 ~ cut : 0 ~ 1640064
  // cut ~ 1640064 : 451298 ~ 1640064
  /*

  int cut = 635904;
  int cutY = (1.0*cut / unitY) / siteY;
  int rowCntX1 = (1.0*(1640064 - 0) / unitX) / siteX;
  int rowCntX2 = (1.0*(1640064 - 451298) / unitX) / siteX;
  int rowSizeX1 = rowCntX1 * siteX;
  int rowSizeX2 = rowCntX2 * siteX;

//    cout << siteX << endl;
//    exit(0);

  for(int i=0; i<cutY; i++) {
      ROW* curRow = &row_st[i];
      new (curRow) ROW();

      curRow->pmin.Set(llx, lly + i * siteY, 0);
      curRow->size.Set(rowSizeX1, rowSizeY, 1);
      curRow->pmax.Set(llx + rowSizeX1, lly + i * siteY + rowSizeY, 1);

      if( i == 0 ) {
          grow_pmin.Set(curRow->pmin);
      }

      curRow->x_cnt = rowCntX1;
      curRow->site_wid = curRow->site_spa = SITE_SPA = minRow->xStep()/unitX;
      curRow->Dump(to_string(i));
  }

  for(int i=cutY; i<row_cnt; i++) {
      ROW* curRow = &row_st[i];
      new (curRow) ROW();

      curRow->pmin.Set(451298 / unitX , lly + i * siteY, 0);
      curRow->size.Set(rowSizeX2, rowSizeY, 1);
      curRow->pmax.Set(451298 / unitX + rowSizeX2, lly + i * siteY + rowSizeY,
1);

      if( i == row_cnt-1 ) {
          grow_pmax.Set(curRow->pmax);
      }

      curRow->x_cnt = rowCntX2;
      curRow->site_wid = curRow->site_spa = SITE_SPA = minRow->xStep()/unitX;
      curRow->Dump(to_string(i));
  }

//    exit(1);
  */
  //
  ///////////////////////////
  // ORIGINAL!!!

  for(int i = 0; i < row_cnt; i++) {
    ROW* curRow = &row_st[i];
    new(curRow) ROW();

    curRow->pmin.Set(coreArea.llx, coreArea.lly + i * siteY);
    curRow->size.Set(rowSizeX, rowSizeY);
    curRow->pmax.Set(coreArea.llx + rowSizeX, coreArea.lly + i * siteY + rowSizeY);

    if(i == 0) {
      grow_pmin.Set(curRow->pmin);
    }
    else if(i == row_cnt - 1) {
      grow_pmax.Set(curRow->pmax);
    }

    curRow->x_cnt = rowCntX;
    curRow->site_wid = curRow->site_spa = SITE_SPA = minRow->xStep() / unitX;
//    curRow->Dump(to_string(i));
  }

  PrintInfoPrecPair( "RowSize", SITE_SPA, rowHeight );
  PrintInfoInt( "NumRows", row_cnt );
  PrintProcEnd("Generate Un-fragmented Rows");
}

//
// helper function for building Net Instance; Get IO info
//
// 0 : Input
// 1 : Output
// 2 : Both (INOUT)
//
// NETS -> COMPONENTS -> MACRO -> PIN -> DIRECTION
//
// If macroName is given (like verilog),
// then skip for NETS->COMPONENTS->MACRO
//
int GetIO(Replace::Circuit& __ckt, string& instName, string& pinName,
          int macroIdx = INT_MAX) {
  if(macroIdx == INT_MAX) {
    // First, it references COMPONENTS
    int defCompIdx = GetDefComponentIdx(__ckt, instName);

    // Second, it reference MACRO in lef
    string compName = string(__ckt.defComponentStor[defCompIdx].name());
    macroIdx = GetLefMacroIdx(__ckt, compName);
  }

  // Finally, it reference PIN from MACRO in lef
  int pinIdx = GetLefMacroPinIdx(__ckt, macroIdx, pinName);

  if(!__ckt.lefPinStor[macroIdx][pinIdx].hasDirection()) {
    cout << "** WARNING: Macro Instance ( "
         << __ckt.lefMacroStor[macroIdx].name() << " - "
         << __ckt.lefPinStor[macroIdx][pinIdx].name()
         << " ) does not have Direction! (lefPinStor) " << endl
         << "            Use INOUT(both direction) instead " << endl;
    return 2;
  }

  string pinDir = string(__ckt.lefPinStor[macroIdx][pinIdx].direction());
  return (pinDir == "INPUT")
             ? 0
             : (pinDir == "OUTPUT") ? 1 : (pinDir == "INOUT") ? 2 : 2;
}

////////
//
// Generate NetInstnace
//
// helper function for building Net Instance; Get OFFSET coordinate
// NETS -> COMPONENTS -> MACRO -> PORT -> RECT
//
// If macroName is given (like verilog),
// then skip for NETS->COMPONENTS->MACRO
//
FPOS GetOffset(Replace::Circuit& __ckt, string& instName, string& pinName,
               int macroIdx = INT_MAX) {
  //    int defCompIdx = INT_MAX;

  // First, it references COMPONENTS
  int defCompIdx = GetDefComponentIdx(__ckt, instName);

  if(macroIdx == INT_MAX) {
    // Second, it reference MACRO in lef
    string compName = string(__ckt.defComponentStor[defCompIdx].name());
    macroIdx = GetLefMacroIdx(__ckt, compName);
  }

  // Finally, it reference PIN from MACRO in lef
  int pinIdx = GetLefMacroPinIdx(__ckt, macroIdx, pinName);

  // extract orient information from def
  // default: North orientation
  int orient =
    (__ckt.defComponentStor[defCompIdx].isUnplaced())?
    0 : __ckt.defComponentStor[defCompIdx].placementOrient();

  // extract Macro's center points
  // orient-awareness
  float origMacroSizeX = (float) __ckt.lefMacroStor[macroIdx].sizeX();
  float origMacroSizeY = (float) __ckt.lefMacroStor[macroIdx].sizeY();

  std::pair<float, float> macroSize =
    GetOrientSize( origMacroSizeX, origMacroSizeY, orient );

  // real center points with orient-aware
  prec centerX = l2d * macroSize.first / 2;
  prec centerY = l2d * macroSize.second / 2;

  bool isFirstMetal = false;

  // prepare for bbox
  prec lx = PREC_MAX, ly = PREC_MAX, ux = PREC_MIN, uy = PREC_MIN;

  // MACRO PORT traverse
  for(int i = 0; i < __ckt.lefPinStor[macroIdx][pinIdx].numPorts(); i++) {
    lefiGeometries* curGeom = __ckt.lefPinStor[macroIdx][pinIdx].port(i);

    // LAYER Metal1 <-- lefiGeomLayerE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //
    //
    // LAYER VIA1 <-- Skip for this
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE
    //   RECT XXXX XXXX XXXX XXXX <-- lefiGeomRectE

    for(int j = 0; j < curGeom->numItems(); j++) {
      // First 'Metal' Layer (Metal layer have 'ROUTING' type)
      if(!isFirstMetal && curGeom->itemType(j) == lefiGeomLayerE &&
         string(
             __ckt.lefLayerStor[__ckt.lefLayerMap[string(curGeom->getLayer(j))]]
                 .type()) == "ROUTING") {
        //                cout << j << " " << curGeom->getLayer(j) << endl;
        isFirstMetal = true;
        continue;
      }

      // calculate BBox when rect type
      if(isFirstMetal && curGeom->itemType(j) == lefiGeomRectE) {
        lefiGeomRect* rect = curGeom->getRect(j);
        // generate BBox
        lx = (lx > rect->xl) ? rect->xl : lx;
        ly = (ly > rect->yl) ? rect->yl : ly;
        ux = (ux < rect->xh) ? rect->xh : ux;
        uy = (uy < rect->yh) ? rect->yh : uy;
      }
      // calculate BBox when polygon type
      else if(isFirstMetal && curGeom->itemType(j) == lefiGeomPolygonE) {
        lefiGeomPolygon* polygon = curGeom->getPolygon(j);
        // generate BBox
        for(int k = 0; k < polygon->numPoints; k++) {
          lx = (lx > polygon->x[k]) ? polygon->x[k] : lx;
          ly = (ly > polygon->y[k]) ? polygon->y[k] : ly;
          ux = (ux < polygon->x[k]) ? polygon->x[k] : ux;
          uy = (uy < polygon->y[k]) ? polygon->y[k] : uy;
        }
      }
      // now, meets another Layer
      else if(isFirstMetal && curGeom->itemType(j) == lefiGeomLayerE) {
        break;
      }
    }
    // firstMetal was visited
    if(isFirstMetal) {
      break;
    }
  }

  if(!isFirstMetal) {
    cout << "**ERROR:  CANNOT find first metal information : " << instName
         << " - " << pinName << endl;
    exit(1);
  }

  // Get pinCenter points
  // orient-awareness
  std::pair<float, float> pinCenter =
    GetOrientPoint( (lx + ux) / 2, (ly + uy) / 2,
                    origMacroSizeX, origMacroSizeY, orient  );

  // calculate center offset
  return FPOS((l2d * pinCenter.first - centerX) / unitX,
              (l2d * pinCenter.second - centerY) / unitY);
}

//////
//
// defNetStor -> netInstnace
// defPinStor -> pinInstance
//
void GenerateNetDefOnly(Replace::Circuit& __ckt) {
  PrintProcBegin("DEF Net Parsing");

  pinCNT = 0;
  netCNT = __ckt.defNetStor.size();
  for(auto& curNet : __ckt.defNetStor) {
    pinCNT += curNet.numConnections();
  }

  // memory reserve
  netInstance = (NET*)malloc(sizeof(NET) * netCNT);
  pinInstance = (PIN*)malloc(sizeof(PIN) * pinCNT);
  for(int i = 0; i < pinCNT; i++) {
    new(&pinInstance[i]) PIN;
  }

  TERM* curTerm = NULL;
  MODULE* curModule = NULL;

  NET* curNet = NULL;
  PIN* curPin = NULL;

  int pinIdx = 0;
  int netIdx = 0;

  tPinName.resize(terminalCNT);
  mPinName.resize(moduleCNT);

#ifdef USE_GOOGLE_HASH
  netNameMap.set_empty_key(INIT_STR);
#endif
  for(auto& net : __ckt.defNetStor) {
    if(strcmp(net.name(), "iccad_clk") == 0 || strcmp(net.name(), "clk") == 0 ||
       strcmp(net.name(), "clock") == 0) {
      cout << "** WARNING:  " << net.name() << " is detected. "
           << " It'll be automatically excluded"
           << " (defNetStor)" << endl;

      clockNetsDef.push_back(&net - &__ckt.defNetStor[0]);
      continue;
    }
    // skip for Power/Ground/Reset/Clock Nets
    if(net.hasUse() &&
       (strcmp(net.use(), "CLOCK") == 0 || strcmp(net.use(), "POWER") == 0 ||
        strcmp(net.use(), "GROUND") == 0 || strcmp(net.use(), "RESET") == 0)) {
      continue;
    }

    // skip for empty net definition.
    if( net.numConnections() == 0 ) {
      continue;
    }

    // special detection for avoiding signal nets
    bool isReset = false;
    for(int i = 0; i < net.numConnections(); i++) {
      if( strcmp(net.pin(i), "SI") == 0 || strcmp(net.pin(i), "SE") == 0 ) {
        isReset= true;
        break;
      }
    }
    if( isReset ) {
      continue;
    }

    curNet = &netInstance[netIdx];
    new(curNet) NET();
    string netName = string(net.name());
    //        ReplaceStringInPlace(netName, "[", "\\[");
    //        ReplaceStringInPlace(netName, "]", "\\]");

    // copy original name into netInstance
//    strcpy(curNet->name, netName.c_str());
    netNameStor.push_back( netName );

    // But, netNameMap can have escaped strings
//    ReplaceStringInPlace(netName, "\\[", "[");
//    ReplaceStringInPlace(netName, "\\]", "]");
//    ReplaceStringInPlace(netName, "\\/", "/");

    //        cout << "copied net Name: " << curNet->name << endl;
    netNameMap[netName] = netIdx;
    curNet->idx = netIdx;
    curNet->timingWeight = 0;

    curNet->pinCNTinObject = net.numConnections();
    //        cout << "connection: " << net.numConnections() << endl;
    curNet->pin = (PIN**)malloc(sizeof(PIN*) * net.numConnections());

    for(int i = 0; i < net.numConnections(); i++) {
      // net.pin(i) itself exists on termInst
      if(strcmp(net.instance(i), "PIN") == 0) {
        auto mtPtr = moduleTermMap.find(string(net.pin(i)));
        if(mtPtr == moduleTermMap.end()) {
          cout << "** ERROR:  Net Instance ( " << net.pin(i)
               << " ) does not exist in PINS statement (moduleTermMap) "
               << endl;
          exit(1);
        }

        int termIdx = mtPtr->second.second;
        curTerm = &terminalInstance[termIdx];
        //                assert( termIdx < terminalCNT );
        //                cout << "foundTermIdx: " << termIdx << endl;

        // extract Input/Output direction from PINS statement
        auto pinPtr = __ckt.defPinMap.find(string(net.pin(i)));
        if(pinPtr == __ckt.defPinMap.end()) {
          cout << "** ERROR:  Net Instance ( " << net.pin(i)
               << " ) does not exist in PINS statement (defPinMap) " << endl;
          exit(1);
        }

        int defPinIdx = pinPtr->second;
        //                cout << "foundPinIdx: " << defPinIdx << endl;
        //                assert( defPinIdx < __ckt.defPinStor.size() );

        int io = INT_MAX;
        if(!__ckt.defPinStor[defPinIdx].hasDirection()) {
          io = 2;  // both direction
        }
        else {
          // input : 0
          // output : 1
          io = (strcmp(__ckt.defPinStor[defPinIdx].direction(), "INPUT") == 0)
                   ? 0
                   : 1;
        }

        // pin Instnace mapping
        curPin = &pinInstance[pinIdx];
        curNet->pin[i] = curPin;

        // save terminal pin Name into tPinName
        tPinName[termIdx].push_back(string(net.pin(i)));

        AddPinInfoForModuleAndTerminal(&curTerm->pin, &curTerm->pof,
                                       curTerm->pinCNTinObject++, FPOS(0, 0),
                                       termIdx, netIdx, i, pinIdx++, io, true);
      }
      // net.instance(i) must exist on moduleInst or termInst
      else {
        string instName = string(net.instance(i));
        string pinName = string(net.pin(i));

        auto mtPtr = moduleTermMap.find(instName);
        if(mtPtr == moduleTermMap.end()) {
          cout << "** ERROR:  Net Instance ( " << instName
               << " ) does not exist in COMPONENTS/PINS statement "
               << "(moduleTermMap) " << endl;
          exit(1);
        }

        // Get Offset Infomation
        FPOS curOffset = GetOffset(__ckt, instName, pinName);
        //                cout << "instName: " << instName << ", pinName: " <<
        //                pinName << endl;
        //                curOffset.Dump("offset"); cout << endl;

        // Get IO information
        int io = GetIO(__ckt, instName, pinName);
        //                cout << io << endl;

        // pin Instnace mapping
        curPin = &pinInstance[pinIdx];
        curNet->pin[i] = curPin;

        // module case
        if(mtPtr->second.first) {
          curModule = &moduleInstance[mtPtr->second.second];

          // save module pin Name into mPinName
          mPinName[mtPtr->second.second].push_back(pinName);

          AddPinInfoForModuleAndTerminal(
              &curModule->pin, &curModule->pof, curModule->pinCNTinObject++,
              curOffset, curModule->idx, netIdx, i, pinIdx++, io, false);
        }
        // terminal case
        else {
          curTerm = &terminalInstance[mtPtr->second.second];

          // save terminal pin Name into tPinName
          tPinName[mtPtr->second.second].push_back(pinName);

          AddPinInfoForModuleAndTerminal(
              &curTerm->pin, &curTerm->pof, curTerm->pinCNTinObject++,
              curOffset, curTerm->idx, netIdx, i, pinIdx++, io, true);
        }
      }
    }
    netIdx++;
  }

  // update instance number
  pinCNT = pinIdx;
  netCNT = netIdx;

  // memory cutting (shrink)
//  netInstance = (NET*)realloc(netInstance, sizeof(NET) * netCNT);
//  pinInstance = (PIN*)realloc(pinInstance, sizeof(PIN) * pinCNT);

  PrintInfoInt( "NumNets", netCNT );
  PrintInfoInt( "NumPins", pinCNT );
  PrintProcEnd("DEF Net Parsing");
}

//
// this function is indended for
// re-parsing the result of detail-placer
//
// ReadPlLefDef -- moduleTermMap -- lefdefIO.cpp
// ReadBookshelf -- nodesMap -- bookshelfIO.cpp
//
void ReadPl(const char* fileName, bool isNameConvert) {
  if(auxCMD == "" && lefStor.size() != 0 && defName != "") {
    // it references moduleTermMap
    ReadPlLefDef(fileName, isNameConvert);
  }
  else if(auxCMD != "" && lefStor.size() == 0 && defName == "") {
    // it references nodesMap
    ReadPlBookshelf(fileName);
  }
}

//////
//
// Read PL back from Detailed Placer -- to use moduleTermMap again
//
// See also ReadPlBookshelf(const char* fileName) in bookShelfIO.cpp
//
void ReadPlLefDef(const char* fileName, bool isNameConvert) {
  cout << "READ BACK FROM " << fileName << endl;
  FILE* fp = fopen(fileName, "r");
  if(!fp) {
    runtimeError(fileName + string(" is not Exist!"));
  }

  char buf[BUF_SZ], name[BUF_SZ];
  int moduleID = 0;
  FPOS pof;
  while(fgets(buf, BUF_SZ, fp)) {
    char* token = strtok(buf, " \t\n");
    if(!token || token[0] == '#' || !strcmp(token, "UCLA"))
      continue;

    strcpy(name, token);

    if(name[0] == 'f' && name[1] == 'a' && name[2] == 'k' && name[3] == 'e')
      continue;

    bool isModule = false;
    string mName = (isNameConvert)?
      ((name[0] == 'o')? _bsMap.GetOrigModuleName( name ) :
       _bsMap.GetOrigTerminalName( name ))
      : name;

    if( mName == "" ) {
      continue;
    }

    auto mtPtr = moduleTermMap.find(mName);
    if(mtPtr == moduleTermMap.end()) {
      continue;
    }
    else {
      isModule = mtPtr->second.first;
      moduleID = mtPtr->second.second;
    }

    if(isModule) {
      MODULE* curModule = &moduleInstance[moduleID];

      if(curModule->flg == Macro)
        continue;

      token = strtok(NULL, " \t\n");
      curModule->pmin.x = GetScaleDownPoint( atof(token) );

      token = strtok(NULL, " \t\n");
      curModule->pmin.y = GetScaleDownPoint( atof(token) );
//      cout << "down: " << curModule->pmin.x << " " << curModule->pmin.y << endl;

      curModule->pmax.x = curModule->pmin.x + curModule->size.x;
      curModule->pmax.y = curModule->pmin.y + curModule->size.y;

      curModule->center.x = 0.5 * (curModule->pmin.x + curModule->pmax.x);
      curModule->center.y = 0.5 * (curModule->pmin.y + curModule->pmax.y);

      for(int i = 0; i < curModule->pinCNTinObject; i++) {
        PIN* pin = curModule->pin[i];
        pof = curModule->pof[i];
        pin->fp.x = curModule->center.x + pof.x;
        pin->fp.y = curModule->center.y + pof.y;
      }
    }
    else {
      continue;
    }
  }

  fclose(fp);
}

/////////////////////////////////////////////////////////
//
// Timing Part
//
/////////////////////////////////////////////////////////
namespace Timing {

// copy scale down parameter into Timing Instance
void Timing::SetLefDefEnv() {
  _unitX = unitX;
  _unitY = unitY;
  _l2d = l2d;
}

void Timing::WriteSpefClockNet(stringstream& feed) {
  if(clockNetsDef.size() != 0) {
    WriteSpefClockNetDef(feed);
  }
  else if(clockNetsVerilog.size() != 0) {
    WriteSpefClockNetVerilog(feed);
  }
}

void Timing::WriteSpefClockNetDef(stringstream& feed) {
  for(auto& curClockNet : clockNetsDef) {
    defiNet& net = __ckt.defNetStor[curClockNet];
    feed << "*D_NET " << net.name() << " 0" << endl << "*CONN" << endl;
    for(int i = 0; i < net.numConnections(); i++) {
      // net.pin(i) itself exists on termInst
      if(strcmp(net.instance(i), "PIN") == 0) {
        feed << "*P " << net.pin(i);

        // extract Input/Output direction from PINS statement
        auto pinPtr = __ckt.defPinMap.find(string(net.pin(i)));
        if(pinPtr == __ckt.defPinMap.end()) {
          cout << "** ERROR:  Net Instance ( " << net.pin(i)
               << " ) does not exist in PINS statement (defPinMap) " << endl;
          exit(1);
        }

        int defPinIdx = pinPtr->second;
        //                cout << "foundPinIdx: " << defPinIdx << endl;
        //                assert( defPinIdx < __ckt.defPinStor.size() );

        int io = INT_MAX;
        if(!__ckt.defPinStor[defPinIdx].hasDirection()) {
          cout << "** ERROR:  PINS statement in DEF, " << net.pin(i)
               << " have no direction!!" << endl;
          exit(0);
          //                    io = 2; // both direction
        }
        else {
          // input : 0
          // output : 1
          io = (strcmp(__ckt.defPinStor[defPinIdx].direction(), "INPUT") == 0)
                   ? 0
                   : 1;
        }
        feed << ((io == 0) ? " I" : " O") << endl;
      }
      else {
        string instName = string(net.instance(i));
        string pinName = string(net.pin(i));

        // Get IO information
        int io = GetIO(__ckt, instName, pinName);

        feed << "*I " << instName << ":" << pinName << ((io == 0) ? " I" : " O")
             << endl;
      }
    }
    feed << "*END" << endl << endl;
  }
}

void Timing::WriteSpefClockNetVerilog(stringstream& feed) {
  for(auto& curClockNet : clockNetsVerilog) {
    feed << "*D_NET " << curClockNet << " 0" << endl << "*CONN" << endl;
    for(auto& connection : netMap[curClockNet]) {
      /////////////// Net Info Mapping part
      //
      // find current component is in module or terminal
      //
      if(connection.macroIdx == INT_MAX && connection.compIdx == INT_MAX) {
        string pinName = string(__ckt.defPinStor[connection.pinIdx].pinName());
        auto mtPtr = moduleTermMap.find(pinName);
        if(mtPtr == moduleTermMap.end()) {
          cout << "** ERROR:  Net Instance ( " << pinName
               << " ) does not exist in COMPONENTS/PINS statement "
               << "(moduleTermMap) " << endl;
          exit(1);
        }

        int io = INT_MAX;
        if(!__ckt.defPinStor[connection.pinIdx].hasDirection()) {
          io = 2;  // both direction
        }
        else {
          // input : 0
          // output : 1
          io = (strcmp(__ckt.defPinStor[connection.pinIdx].direction(),
                       "INPUT") == 0)
                   ? 0
                   : 1;
        }
        feed << "*P " << pinName;
        feed << ((io == 0) ? " I" : " O") << endl;
      }
      else {
        auto mtPtr = moduleTermMap.find(
            string(__ckt.defComponentStor[connection.compIdx].id()));

        if(mtPtr == moduleTermMap.end()) {
          cout << "** ERROR:  Net Instance ( "
               << __ckt.defComponentStor[connection.compIdx].id()
               << " ) does not exist in COMPONENTS/PINS statement "
               << "(moduleTermMap) " << endl;
          exit(1);
        }

        string compName =
            string(__ckt.defComponentStor[connection.compIdx].id());
        string pinName = string(
            __ckt.lefPinStor[connection.macroIdx][connection.pinIdx].name());

        int moduleIdx = mtPtr->second.second;

        //
        // located in terminal cases
        if(!mtPtr->second.first) {
          TERM* curTerminal = &terminalInstance[moduleIdx];
          // outer pin
          if(curTerminal->isTerminalNI) {
            feed << "*P " << compName;
          }
          // inner fixed cell's pin
          else {
            feed << "*I " << compName << ":" << pinName;
          }
        }
        // inner module pin
        else {
          feed << "*I " << compName << ":" << pinName;
        }

        int io = GetIO(__ckt, compName, pinName, connection.macroIdx);
        feed << ((io == 0) ? " I" : " O") << endl;
      }
    }
    feed << "*END" << endl << endl;
  }
}

/*
void Timing::UpdateSpefClockNetVerilog() {
  for(auto& curClockNet : clockNetsVerilog) {
    char* netNamePtr = new char[curClockNet.length() + 1];
    strcpy(netNamePtr, curClockNet.c_str());
    sta::Net* net = sta::spef_reader->findNet(netNamePtr);
    SpefTriple* netCap = new SpefTriple(0);
    sta::spef_reader->dspfBegin(net, netCap);
    sta::spef_reader->dspfFinish();
  }
}*/

}

////////////////////////////////////////////////
//
// Routability Part
//
////////////////////////////////////////////////

void RouteInstance::SetScaleFactor() {
  this->_unitX = (float)unitX;
  this->_unitY = (float)unitY;
  this->_offsetX = (float)offsetX;
  this->_offsetY = (float)offsetY;
  this->_defDbu = (float)l2d;
}

void RouteInstance::SetCircuitInst() {
  this->_ckt = &__ckt;
}

max_stars_repo_name: enzoleo/RePlAce

max_issues_repo_name: enzoleo/RePlAce

max_forks_repo_name: enzoleo/RePlAce


text:
#include "JoinSplit.hpp"
#include "prf.h"
#include "sodium.h"

#include "zcash/util.h"

#include <memory>

#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/optional.hpp>
#include <fstream>
#include "libsnark/common/default_types/r1cs_ppzksnark_pp.hpp"
#include "libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp"
#include "libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp"
#include "libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp"

#include "sync.h"
#include "amount.h"

using namespace libsnark;

namespace libzcash {

#include "zcash/circuit/gadget.tcc"

CCriticalSection cs_ParamsIO;
CCriticalSection cs_LoadKeys;

template<typename T>
void saveToFile(std::string path, T& obj) {
    LOCK(cs_ParamsIO);

    std::stringstream ss;
    ss << obj;
    std::ofstream fh;
    fh.open(path, std::ios::binary);
    ss.rdbuf()->pubseekpos(0, std::ios_base::out);
    fh << ss.rdbuf();
    fh.flush();
    fh.close();
}

template<typename T>
void loadFromFile(std::string path, boost::optional<T>& objIn) {
    LOCK(cs_ParamsIO);

    std::stringstream ss;
    std::ifstream fh(path, std::ios::binary);

    if(!fh.is_open()) {
        throw std::runtime_error((boost::format("could not load param file at %s") % path).str());
    }

    ss << fh.rdbuf();
    fh.close();

    ss.rdbuf()->pubseekpos(0, std::ios_base::in);

    T obj;
    ss >> obj;

    objIn = std::move(obj);
}

template<size_t NumInputs, size_t NumOutputs>
class JoinSplitCircuit : public JoinSplit<NumInputs, NumOutputs> {
public:
    typedef default_r1cs_ppzksnark_pp ppzksnark_ppT;
    typedef Fr<ppzksnark_ppT> FieldT;

    boost::optional<r1cs_ppzksnark_proving_key<ppzksnark_ppT>> pk;
    boost::optional<r1cs_ppzksnark_verification_key<ppzksnark_ppT>> vk;
    boost::optional<r1cs_ppzksnark_processed_verification_key<ppzksnark_ppT>> vk_precomp;
    boost::optional<std::string> pkPath;

    JoinSplitCircuit() {}
    ~JoinSplitCircuit() {}

    void setProvingKeyPath(std::string path) {
        pkPath = path;
    }

    void loadProvingKey() {
        LOCK(cs_LoadKeys);

        if (!pk) {
            if (!pkPath) {
                throw std::runtime_error("proving key path unknown");
            }
            loadFromFile(*pkPath, pk);
        }
    }

    void saveProvingKey(std::string path) {
        if (pk) {
            saveToFile(path, *pk);
        } else {
            throw std::runtime_error("cannot save proving key; key doesn't exist");
        }
    }
    void loadVerifyingKey(std::string path) {
        LOCK(cs_LoadKeys);

        loadFromFile(path, vk);

        processVerifyingKey();
    }
    void processVerifyingKey() {
        vk_precomp = r1cs_ppzksnark_verifier_process_vk(*vk);
    }
    void saveVerifyingKey(std::string path) {
        if (vk) {
            saveToFile(path, *vk);
        } else {
            throw std::runtime_error("cannot save verifying key; key doesn't exist");
        }
    }
    void saveR1CS(std::string path) {
        auto r1cs = generate_r1cs();

        saveToFile(path, r1cs);
    }

    r1cs_constraint_system<FieldT> generate_r1cs() {
        protoboard<FieldT> pb;

        joinsplit_gadget<FieldT, NumInputs, NumOutputs> g(pb);
        g.generate_r1cs_constraints();

        return pb.get_constraint_system();
    }

    void generate() {
        LOCK(cs_LoadKeys);

        const r1cs_constraint_system<FieldT> constraint_system = generate_r1cs();
        r1cs_ppzksnark_keypair<ppzksnark_ppT> keypair = r1cs_ppzksnark_generator<ppzksnark_ppT>(constraint_system);

        pk = keypair.pk;
        vk = keypair.vk;
        processVerifyingKey();
    }

    bool verify(
        const ZCProof& proof,
        ProofVerifier& verifier,
        const uint256& pubKeyHash,
        const uint256& randomSeed,
        const boost::array<uint256, NumInputs>& macs,
        const boost::array<uint256, NumInputs>& nullifiers,
        const boost::array<uint256, NumOutputs>& commitments,
        uint64_t vpub_old,
        uint64_t vpub_new,
        const uint256& rt
    ) {
        if (!vk || !vk_precomp) {
            throw std::runtime_error("JoinSplit verifying key not loaded");
        }

        try {
            auto r1cs_proof = proof.to_libsnark_proof<r1cs_ppzksnark_proof<ppzksnark_ppT>>();

            uint256 h_sig = this->h_sig(randomSeed, nullifiers, pubKeyHash);

            auto witness = joinsplit_gadget<FieldT, NumInputs, NumOutputs>::witness_map(
                rt,
                h_sig,
                macs,
                nullifiers,
                commitments,
                vpub_old,
                vpub_new
            );

            return verifier.check(
                *vk,
                *vk_precomp,
                witness,
                r1cs_proof
            );
        } catch (...) {
            return false;
        }
    }

    ZCProof prove(
        const boost::array<JSInput, NumInputs>& inputs,
        const boost::array<JSOutput, NumOutputs>& outputs,
        boost::array<Note, NumOutputs>& out_notes,
        boost::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
        uint256& out_ephemeralKey,
        const uint256& pubKeyHash,
        uint256& out_randomSeed,
        boost::array<uint256, NumInputs>& out_macs,
        boost::array<uint256, NumInputs>& out_nullifiers,
        boost::array<uint256, NumOutputs>& out_commitments,
        uint64_t vpub_old,
        uint64_t vpub_new,
        const uint256& rt,
        bool computeProof
    ) {
        if (computeProof && !pk) {
            throw std::runtime_error("JoinSplit proving key not loaded");
        }

        if (vpub_old > MAX_MONEY) {
            throw std::invalid_argument("nonsensical vpub_old value");
        }

        if (vpub_new > MAX_MONEY) {
            throw std::invalid_argument("nonsensical vpub_new value");
        }

        uint64_t lhs_value = vpub_old;
        uint64_t rhs_value = vpub_new;

        for (size_t i = 0; i < NumInputs; i++) {
            // Sanity checks of input
            {
                // If note has nonzero value
                if (inputs[i].note.value != 0) {
                    // The witness root must equal the input root.
                    if (inputs[i].witness.root() != rt) {
                        throw std::invalid_argument("joinsplit not anchored to the correct root");
                    }

                    // The tree must witness the correct element
                    if (inputs[i].note.cm() != inputs[i].witness.element()) {
                        throw std::invalid_argument("witness of wrong element for joinsplit input");
                    }
                }

                // Ensure we have the key to this note.
                if (inputs[i].note.a_pk != inputs[i].key.address().a_pk) {
                    throw std::invalid_argument("input note not authorized to spend with given key");
                }

                // Balance must be sensical
                if (inputs[i].note.value > MAX_MONEY) {
                    throw std::invalid_argument("nonsensical input note value");
                }

                lhs_value += inputs[i].note.value;

                if (lhs_value > MAX_MONEY) {
                    throw std::invalid_argument("nonsensical left hand size of joinsplit balance");
                }
            }

            // Compute nullifier of input
            out_nullifiers[i] = inputs[i].nullifier();
        }

        // Sample randomSeed
        out_randomSeed = random_uint256();

        // Compute h_sig
        uint256 h_sig = this->h_sig(out_randomSeed, out_nullifiers, pubKeyHash);

        // Sample phi
        uint252 phi = random_uint252();

        // Compute notes for outputs
        for (size_t i = 0; i < NumOutputs; i++) {
            // Sanity checks of output
            {
                if (outputs[i].value > MAX_MONEY) {
                    throw std::invalid_argument("nonsensical output value");
                }

                rhs_value += outputs[i].value;

                if (rhs_value > MAX_MONEY) {
                    throw std::invalid_argument("nonsensical right hand side of joinsplit balance");
                }
            }

            // Sample r
            uint256 r = random_uint256();

            out_notes[i] = outputs[i].note(phi, r, i, h_sig);
        }

        if (lhs_value != rhs_value) {
            throw std::invalid_argument("invalid joinsplit balance");
        }

        // Compute the output commitments
        for (size_t i = 0; i < NumOutputs; i++) {
            out_commitments[i] = out_notes[i].cm();
        }

        // Encrypt the ciphertexts containing the note
        // plaintexts to the recipients of the value.
        {
            ZCNoteEncryption encryptor(h_sig);

            for (size_t i = 0; i < NumOutputs; i++) {
                NotePlaintext pt(out_notes[i], outputs[i].memo);

                out_ciphertexts[i] = pt.encrypt(encryptor, outputs[i].addr.pk_enc);
            }

            out_ephemeralKey = encryptor.get_epk();
        }

        // Authenticate h_sig with each of the input
        // spending keys, producing macs which protect
        // against malleability.
        for (size_t i = 0; i < NumInputs; i++) {
            out_macs[i] = PRF_pk(inputs[i].key, i, h_sig);
        }

        if (!computeProof) {
            return ZCProof();
        }

        protoboard<FieldT> pb;
        {
            joinsplit_gadget<FieldT, NumInputs, NumOutputs> g(pb);
            g.generate_r1cs_constraints();
            g.generate_r1cs_witness(
                phi,
                rt,
                h_sig,
                inputs,
                out_notes,
                vpub_old,
                vpub_new
            );
        }

        // The constraint system must be satisfied or there is an unimplemented
        // or incorrect sanity check above. Or the constraint system is broken!
        assert(pb.is_satisfied());

        // TODO: These are copies, which is not strictly necessary.
        std::vector<FieldT> primary_input = pb.primary_input();
        std::vector<FieldT> aux_input = pb.auxiliary_input();

        // Swap A and B if it's beneficial (less arithmetic in G2)
        // In our circuit, we already know that it's beneficial
        // to swap, but it takes so little time to perform this
        // estimate that it doesn't matter if we check every time.
        pb.constraint_system.swap_AB_if_beneficial();

        return ZCProof(r1cs_ppzksnark_prover<ppzksnark_ppT>(
            *pk,
            primary_input,
            aux_input,
            pb.constraint_system
        ));
    }
};

template<size_t NumInputs, size_t NumOutputs>
JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Generate()
{
    initialize_curve_params();
    auto js = new JoinSplitCircuit<NumInputs, NumOutputs>();
    js->generate();

    return js;
}

template<size_t NumInputs, size_t NumOutputs>
JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Unopened()
{
    initialize_curve_params();
    return new JoinSplitCircuit<NumInputs, NumOutputs>();
}

template<size_t NumInputs, size_t NumOutputs>
uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
    const uint256& randomSeed,
    const boost::array<uint256, NumInputs>& nullifiers,
    const uint256& pubKeyHash
) {
    const unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES]
        = {'Z','c','a','s','h','C','o','m','p','u','t','e','h','S','i','g'};

    std::vector<unsigned char> block(randomSeed.begin(), randomSeed.end());

    for (size_t i = 0; i < NumInputs; i++) {
        block.insert(block.end(), nullifiers[i].begin(), nullifiers[i].end());
    }

    block.insert(block.end(), pubKeyHash.begin(), pubKeyHash.end());

    uint256 output;

    if (crypto_generichash_blake2b_salt_personal(output.begin(), 32,
                                                 &block[0], block.size(),
                                                 NULL, 0, // No key.
                                                 NULL,    // No salt.
                                                 personalization
                                                ) != 0)
    {
        throw std::logic_error("hash function failure");
    }

    return output;
}

Note JSOutput::note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const {
    uint256 rho = PRF_rho(phi, i, h_sig);

    return Note(addr.a_pk, value, rho, r);
}

JSOutput::JSOutput() : addr(uint256(), uint256()), value(0) {
    SpendingKey a_sk = SpendingKey::random();
    addr = a_sk.address();
}

JSInput::JSInput() : witness(ZCIncrementalMerkleTree().witness()),
                     key(SpendingKey::random()) {
    note = Note(key.address().a_pk, 0, random_uint256(), random_uint256());
    ZCIncrementalMerkleTree dummy_tree;
    dummy_tree.append(note.cm());
    witness = dummy_tree.witness();
}

template class JoinSplit<ZC_NUM_JS_INPUTS,
                         ZC_NUM_JS_OUTPUTS>;

}

ext: cpp

max_stars_repo_name: j-cimb-barker/komodo

max_issues_repo_name: AudoKowitz/komodo

max_forks_repo_name: AudoKowitz/komodo


text:
// **************************************************************************/
//  作者: 陈雪飞<chenxuefei_pp@163.com>
//  日期: 2017年1月15日  14:53:16
//  工程: OpticalFlow
//  程序: OpticalFlow
//  文件: OpticalFlow.cpp
//  描述: 光流法裂纹检测
// **************************************************************************/

#include <opencv2/opencv.hpp>
#include <boost/thread.hpp>

//基本类型定义
//PI定义
const static double  PI = 3.14159265358979323846;
//特征点个数定义
const static uint    FEATURE_MAX_NUM = 600;
//图像二值化阈值
const static double  IMAGE_THRESHOLD = 127.00f;

/**
* \brief 创建窗口线程函数，将窗口独立到线程中
*/
void    output_windows_thread(const std::string &windowname)
{
    cv::namedWindow(windowname);
    cv::waitKeyEx();
}

/**
* \brief 定义平方函数
* \tparam _Ty 平方类型
* \param a 平方因子
* \return
*/
template<typename _Ty>
double square(_Ty a)
{
    return a * a;
}

/**
* \brief 两点之间线段长度
* \param p1 点向量1
* \param p2 点向量2
* \return 计算出的线段长度
*/
double  segment_length(const cv::Point & p1, const cv::Point &p2)
{
    return std::sqrt(square(p1.x - p2.x) + square(p1.y - p2.y));
}

/**
* \brief 定义图像处理函数
* \param name 处理方法名
*/
#define     DEF_IMG_HANDLER(name)   \
    void  name(cv::Mat &in,cv::Mat &out)

/**
* \brief 定义处理操作符
* \tparam Functor 处理方法
* \param img 处理图像
* \param f 方法
* \return 处理后的图像
*/
template <typename Functor>
cv::Mat  &operator << (cv::Mat &img, Functor f)
{
    f(img, img);
    return img;
}

/**
* \brief 灰度化处理方法
* \param in 原图像三通道
* \param out 输出图像，灰度图像
*/
DEF_IMG_HANDLER(cvtgray)
{
    assert(in.channels() == 3);
    cv::cvtColor(in, out, cv::COLOR_BGR2GRAY);
}

/**
* \brief 灰度图像转彩色图像
* \param in 灰度图像，单通道
* \param out 彩色图像，三通道
*/
DEF_IMG_HANDLER(cvtbgr)
{
    assert(in.channels() == 1);
    cv::cvtColor(in, out, cv::COLOR_GRAY2BGR);
}

/**
* \brief 图像转HSV格式
* \param in 源图像
* \param out hsv格式图像
*/
DEF_IMG_HANDLER(cvthsv)
{
    cv::cvtColor(in, out, cv::COLOR_BGR2HSV);
}

/**
* \brief 二值化图像
* \param in 传入图像
* \param out 二值化图像，单通道
*/
DEF_IMG_HANDLER(binary)
{
    //cv::threshold(in, out, IMAGE_THRESHOLD, 255.0f, CV_THRESH_BINARY);

    cv::adaptiveThreshold(in, out, 255.0f,
        cv::AdaptiveThresholdTypes::ADAPTIVE_THRESH_GAUSSIAN_C,
        cv::ThresholdTypes::THRESH_BINARY, 7, 0.0);
}

/**
* \brief 白平衡处理，均衡化三通道
* \param in 输入图像三通道
* \param out 输出图像三通道
*/
DEF_IMG_HANDLER(whiteblace)
{
    assert(in.channels() == 3);
    using namespace cv;
    Mat &g_srcImage = in, &dstImage = out;
    std::vector<Mat> g_vChannels;

    split(g_srcImage, g_vChannels);
    Mat imageBlueChannel = g_vChannels.at(0);
    Mat imageGreenChannel = g_vChannels.at(1);
    Mat imageRedChannel = g_vChannels.at(2);

    double imageBlueChannelAvg = 0;
    double imageGreenChannelAvg = 0;
    double imageRedChannelAvg = 0;

    //求各通道的平均值
    imageBlueChannelAvg = mean(imageBlueChannel)[0];
    imageGreenChannelAvg = mean(imageGreenChannel)[0];
    imageRedChannelAvg = mean(imageRedChannel)[0];

    //求出个通道所占增益
    double K = (imageRedChannelAvg + imageGreenChannelAvg + imageRedChannelAvg) / 3;
    double Kb = K / imageBlueChannelAvg;
    double Kg = K / imageGreenChannelAvg;
    double Kr = K / imageRedChannelAvg;

    //更新白平衡后的各通道BGR值
    addWeighted(imageBlueChannel, Kb, 0, 0, 0, imageBlueChannel);
    addWeighted(imageGreenChannel, Kg, 0, 0, 0, imageGreenChannel);
    addWeighted(imageRedChannel, Kr, 0, 0, 0, imageRedChannel);

    merge(g_vChannels, dstImage);//图像各通道合并
}

/**
* \brief 灰度直方图均衡化
* \param in 输入灰度图
* \param out 输出灰度图
*/
DEF_IMG_HANDLER(equalizeHist)
{
    assert(in.channels() == 1);
    cv::equalizeHist(in, out);
}

/**
* \brief 图像锐化，拉普拉斯算子
* \param in 输入图像
* \param out 输出图像
*/
DEF_IMG_HANDLER(sharpen)
{
    cv::Mat kernela(3, 3, CV_32F, cv::Scalar(0));
    kernela.at<float>(1, 1) = 5.0;
    kernela.at<float>(0, 1) = -1.0;
    kernela.at<float>(2, 1) = -1.0;
    kernela.at<float>(1, 0) = -1.0;
    kernela.at<float>(1, 2) = -1.0;
    filter2D(in, out, in.depth(), kernela);
}

/**
* \brief 对图像进行预处理
* \param base_image 待预处理的图像
*/
void handle_base_out_pre(cv::Mat& base_image)
{
    std::vector<cv::Mat> mv;

    //分离红色通道分量
    cv::split(base_image, mv);
    auto &red = mv.at(2);

    /// 膨胀操作
    int dilation_size = 1;
    auto element = getStructuringElement(cv::MORPH_RECT,
        cv::Size(2 * dilation_size + 1, 2 * dilation_size + 1),
        cv::Point(dilation_size, dilation_size));
    dilate(red, red, element);
    dilate(red, red, element);
    dilate(red, red, element);
    //将分量组合
    cv::merge(mv, base_image);

    cv::imshow("superposition_window", base_image);

    cv::imwrite("叠加膨胀结果.png", base_image);
}
/**
* \brief 查找最大连通域
* \param base_image
*/
void handle_base_out_last(const cv::Mat& base_image, cv::Mat & backend_image)
{
    //最大面积区域需要显示几个
    const static  auto area_number = 3;

    cv::Mat		new_image = backend_image;

    assert(!new_image.empty());//检查是否为空

    std::vector<cv::Vec4i>          hierarchy;
    std::vector<cv::Mat>            contours;

    cv::Mat input;
    base_image.copyTo(input);

    cv::cvtColor(input, input, cv::COLOR_BGR2GRAY);

    input << binary;//二值化
    cv::imwrite("二值结果.png", input);

    cv::findContours(input, contours, hierarchy,
        cv::RetrievalModes::RETR_CCOMP,
        cv::ContourApproximationModes::CHAIN_APPROX_SIMPLE);

    //输出查找到的所有轮廓
    {
        cv::Mat all_outline;
        new_image.copyTo(all_outline);
        cv::drawContours(all_outline, contours, -1, CV_RGB(0, 255, 255), 1 , cv::LINE_AA);
        cv::imwrite("查找到的所有轮廓.png", all_outline);
    }

    /// Find the convex hull object for each contour
    std::vector<std::vector<cv::Point2i> >	hull(contours.size()), dest_hull;
    // Int type hull
    std::vector<std::vector<int>>	hullsI(contours.size());
    // Convexity defects
    std::vector<cv::Mat>			defects(contours.size());

    //凹点还原
    for (size_t i = 0; i < contours.size(); i++)
    {
        cv::convexHull(contours[i], hull[i], false);
        // find int type hull
        cv::convexHull(contours[i], hullsI[i], false);
        // get convexity defects
        convexityDefects(contours[i], hullsI[i], defects[i]);
    }

    //查找最大轮廓
    for (auto i = 0; i < area_number; ++i)
    {
        auto max_contours = std::max_element(hull.begin(), hull.end(), [](const std::vector<cv::Point> &l, const std::vector<cv::Point> &r)->bool
        {
            auto area1 = fabs(cv::contourArea(l));
            auto area2 = fabs(cv::contourArea(r));
            return area1 < area2;
        });
        dest_hull.push_back(*max_contours);
        hull.erase(max_contours);
    }

    cv::drawContours(new_image, dest_hull, -1, CV_RGB(0, 255, 255), 1 , cv::LINE_AA);

    //cv::drawContours(base_image, contours ,-1, CV_RGB(255, 0, 0),1,cv::LINE_AA);
    //根据凹点还原在原图连线，表示出最大连通点
    //for (size_t i = 0; i< contours.size(); i++)
    //{
    //	cv::Scalar color = CV_RGB(0,255,0);
    //	drawContours(new_image, hull, i, color, 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point2i());

    //	//auto d = defects[i].begin<cv::Vec4i>();
    //	//while (d != defects[i].end<cv::Vec4i>()) {
    //	//	cv::Vec4i& v = (*d);
    //	//	//if(IndexOfBiggestContour == i)
    //	//	{

    //	//		int startidx = v[0];
    //	//		cv::Point2i ptStart(contours[i].at<cv::Point2i>(startidx)); // point of the contour where the defect begins
    //	//		int endidx = v[1];
    //	//		cv::Point2i ptEnd(contours[i].at<cv::Point2i>(endidx)); // point of the contour where the defect ends
    //	//		int faridx = v[2];
    //	//		cv::Point2i ptFar(contours[i].at<cv::Point2i>(faridx));// the farthest from the convex hull point within the defect
    //	//		int depth = v[3] / 256; // distance between the farthest point and the convex hull

    //	//		if (depth > 20 && depth < 80)
    //	//		{
    //	//			//line(new_image, ptStart, ptFar, CV_RGB(0, 255, 0), 2);
    //	//			//line(new_image, ptEnd, ptFar, CV_RGB(0, 255, 0), 2);
    //	//			/*circle(base_image, ptStart, 4, cv::Scalar(255, 0, 100), 2);
    //	//			circle(base_image, ptEnd, 4, cv::Scalar(255, 0, 100), 2);
    //	//			circle(base_image, ptFar, 4, cv::Scalar(100, 0, 255), 2);*/
    //	//		}
    //	//	}
    //	//	++d;
    //	//}
    //}
    //cv::drawContours(base_image, defects, -1, CV_RGB(0, 255, 0), 1, cv::LINE_AA);
    cv::imshow("output_window", new_image);
    cv::imwrite("最终结果.png", new_image);
}
/**
* \brief 开始绘制运动轨迹 如需要
* \param m1 基本矩阵
* \param frame1_features 查找到的第一帧特征点
* \param frame2_features 查找到的第二帧特征点
* \param found_features 特征点错误矩阵
*/
void    draw_path_on_baseimage(cv::Mat &m1, const cv::Mat &frame1_features, const cv::Mat &frame2_features, const cv::Mat &found_features)
{
    const static cv::Scalar line_color = CV_RGB(255, 0, 0);

    for (auto pos = 0; pos < FEATURE_MAX_NUM; ++pos)
    {
        /* 如果没找到对应特征点 */
        if (found_features.at<uchar>(pos) == 0)
            continue;

        auto p = frame1_features.at<cv::Point2f>(pos);
        auto q = frame2_features.at<cv::Point2f>(pos);

        if (segment_length(p, q) > 20.0f)
            return;

        double angle;
        angle = atan2(static_cast<double>(p.y) - q.y, static_cast<double>(p.x) - q.x);
        double hypotenuse;
        hypotenuse = sqrt(square(p.y - q.y) + square(p.x - q.x));

        /*执行缩放*/
        q.x -= 5 * hypotenuse * cos(angle);
        q.y -= 5 * hypotenuse * sin(angle);

        /*画箭头主线*/
        cv::line(m1, p, q, line_color, 1, cv::LineTypes::LINE_AA, 0);

        /* 画箭的头部*/
        p.x = q.x + 9 * cos(angle + PI / 4);
        p.y = q.y + 9 * sin(angle + PI / 4);
        cv::line(m1, p, q, line_color, 1, cv::LineTypes::LINE_AA, 0);
        p.x = q.x + 9 * cos(angle - PI / 4);
        p.y = q.y + 9 * sin(angle - PI / 4);
        cv::line(m1, p, q, line_color, 1, cv::LineTypes::LINE_AA, 0);
    }
}
/**
* \brief 将特征点信息绘制到基础背景图像中去
* \param base_image 要绘制的图像
* \param frame1_features 第一帧特征点
* \param frame2_features 第二帧特征点
* \param found_features 特征点信息
*/
void draw_features_in_base_image(cv::Mat& base_image, const cv::Mat& frame1_features, const cv::Mat& frame2_features, const cv::Mat& found_features)
{
    const static cv::Scalar area_color = CV_RGB(255, 0, 0);

    for (auto pos = 0; pos < FEATURE_MAX_NUM; ++pos)
    {
        /* 如果没找到对应特征点 */
        if (found_features.at<uchar>(pos) == 0)
            continue;
        auto start_p = frame1_features.at<cv::Point2f>(pos);
        auto end_p = frame2_features.at<cv::Point2f>(pos);
        //如果线段长度大于某个值，说明不是细微运动则排除该线段
        if (segment_length(start_p, end_p) > 20.0f)
            return;

        cv::line(base_image, start_p, end_p, area_color, 3, cv::LINE_AA);
    }
}
/**
* \brief 打开视频文件并返回帧数
* \param capture 视频句柄
* \param filename 文件名
* \return 返回帧数
*/
int open_video(cv::VideoCapture & capture, const std::string &filename)
{
    //打开视频文件
    capture.open(filename);
    auto  frame_count = 0; //总帧长

    assert(capture.isOpened());//检查是否打开

    //获取总帧数
    frame_count = static_cast<int>(capture.get(cv::VideoCaptureProperties::CAP_PROP_FRAME_COUNT));

    //进度条，可以查看处理了多少帧
    return frame_count;
}

/**
* \brief 开始LK光流法算法
* \param base_out 叠加输出基本源图像
*/
void draw_features_by_lk(cv::Mat & base_out, const std::string & in_video_name, const std::string & out_video_name)
{
    //打开视频文件并且创建进度条
    cv::VideoCapture capture{};
    auto frame_count = open_video(capture, in_video_name);
    //boost::progress_display progress_bar(frame_count, std::cout, "当前处理进度\n\t\t", "总进度\t\t", "当前进度\t");
    //打开输出视频文件 如需要
    cv::VideoWriter writer(out_video_name, CV_FOURCC('X', 'V', 'I', 'D'), 29.0, cv::Size{ 656,488 });

    //如果还有新帧则继续
    while (capture.grab())
    {
        cv::Mat     m1, m2, frame1, frame2;
        //取出视频两帧
        capture >> m1;
        capture >> m2;
        //如果返回不足两帧则退出
        if (m1.empty() || m2.empty())
            break;
        //复制到新空间
        frame1 = m1;
        frame2 = m2;
        //两帧灰度化
        frame1 << cvtgray;
        frame2 << cvtgray;

        //创建两个特征值存储矩阵
        cv::Mat frame1_features, frame2_features;
        //开始进行特征值检测，先检测出第一帧特征值
        cv::goodFeaturesToTrack(frame1, frame1_features, FEATURE_MAX_NUM, .01, .01);
        //创建查找错误矩阵
        cv::Mat found_futures, found_err;
        //创建迭代算子
        cv::TermCriteria optical_flow_termination_criteria(cv::TermCriteria::Type::MAX_ITER | cv::TermCriteria::Type::EPS, 20, .3);
        //开始进行LK光流法计算，查找第二个特征值
        cv::calcOpticalFlowPyrLK(
            frame1, frame2,
            frame1_features, frame2_features,
            found_futures, found_err,
            cv::Size{ 5,5 }, 5, optical_flow_termination_criteria);
        //绘制移动轨迹 ， 如需要
        draw_path_on_baseimage(m1, frame1_features, frame2_features, found_futures);
        //绘制运动轨迹线到背景矩阵
        draw_features_in_base_image(base_out, frame1_features, frame2_features, found_futures);

        //进度条更新
        //progress_bar += 2;

        //将运动轨迹线展示到窗口，如需要
        cv::imshow("output_window", m1);
        cv::imshow("superposition_window", base_out);
        //将运动轨迹线输出到视频文件 如需要
        writer << m1;
        //writer << (out << cvtbgr);
    }

    writer.release();
    capture.release();
}

/**
* \brief 主函数
* \return
*/
int main(int argc, char ** args)
{
    if (argc < 3)
    {
        std::cout << "请输入输入视频文件名,输入背景图像文件名,(或者输出视频文件名),按顺序空格分离." << std::endl;
        std::cout << "Example:\n\tOpticalFlow 输入视频.avi 输入背景.jpg [输出视频.avi]" << std::endl;
        exit(-1);
    }
    std::string input_video_filename = args[1];
    std::string base_image_filename = args[2];
    std::string base_output_filename = "VideoOut.avi";
    if (argc == 4)
        base_output_filename = args[3];

    //创建窗口
    auto  output_window_fu = boost::thread(output_windows_thread, "output_window");
    auto  superposition_window_fu = boost::thread(output_windows_thread, "superposition_window");

    //boost::thread(output_windows_thread).detach();
    //打开背景图像
    auto            base_image = cv::imread(base_image_filename);
    //打开是否失败
    assert(!base_image.empty());

    //创建空白背景图像
    cv::Mat         base_out{ base_image.rows,base_image.cols,base_image.type() };
    //cv::Mat          base_out = cv::imread("post.png");
    //开始进行LK光流算法，将结果图像输出到base out
    draw_features_by_lk(base_out, input_video_filename, base_output_filename);

    /*
    * ！！！！此处开始对LK算法处理后的图像进行处理！！！！
    */
    //对叠加输出图片进行预处理
    handle_base_out_pre(base_out);
    //对预处理图片进行整合处理，边缘过滤，凹点过滤
    handle_base_out_last(base_out, base_image);

    //等待窗口程序结束
    superposition_window_fu.join();
    output_window_fu.join();
    return 0;
}

max_stars_repo_name: chenxuefei-pp/OpticalFlow

max_issues_repo_name: stan-chen/OpticalFlow

max_forks_repo_name: stan-chen/OpticalFlow


text:
#pragma once

#include <string>
#include <boost/beast/core.hpp>

namespace ott
{

    namespace http
    {

        boost::beast::string_view
        mime_type(boost::beast::string_view path);

    } // http namespace

} // ott namespace

ext: hpp


text:
#include <Access/RowPolicyContext.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTExpressionList.h>
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/copy.hpp>

namespace DB
{
size_t RowPolicyContext::Hash::operator()(const DatabaseAndTableNameRef & database_and_table_name) const
{
    return std::hash<std::string_view>{}(database_and_table_name.first) - std::hash<std::string_view>{}(database_and_table_name.second);
}

RowPolicyContext::RowPolicyContext()
    : map_of_mixed_conditions(boost::make_shared<MapOfMixedConditions>())
{
}

RowPolicyContext::~RowPolicyContext() = default;

RowPolicyContext::RowPolicyContext(const UUID & user_id_, const std::vector<UUID> & enabled_roles_)
    : user_id(user_id_), enabled_roles(enabled_roles_)
{}

ASTPtr RowPolicyContext::getCondition(const String & database, const String & table_name, ConditionIndex index) const
{
    /// We don't lock `mutex` here.
    auto loaded = map_of_mixed_conditions.load();
    auto it = loaded->find({database, table_name});
    if (it == loaded->end())
        return {};
    return it->second.mixed_conditions[index];
}

ASTPtr RowPolicyContext::combineConditionsUsingAnd(const ASTPtr & lhs, const ASTPtr & rhs)
{
    if (!lhs)
        return rhs;
    if (!rhs)
        return lhs;
    auto function = std::make_shared<ASTFunction>();
    auto exp_list = std::make_shared<ASTExpressionList>();
    function->name = "and";
    function->arguments = exp_list;
    function->children.push_back(exp_list);
    exp_list->children.push_back(lhs);
    exp_list->children.push_back(rhs);
    return function;
}

std::vector<UUID> RowPolicyContext::getCurrentPolicyIDs() const
{
    /// We don't lock `mutex` here.
    auto loaded = map_of_mixed_conditions.load();
    std::vector<UUID> policy_ids;
    for (const auto & mixed_conditions : *loaded | boost::adaptors::map_values)
        boost::range::copy(mixed_conditions.policy_ids, std::back_inserter(policy_ids));
    return policy_ids;
}

std::vector<UUID> RowPolicyContext::getCurrentPolicyIDs(const String & database, const String & table_name) const
{
    /// We don't lock `mutex` here.
    auto loaded = map_of_mixed_conditions.load();
    auto it = loaded->find({database, table_name});
    if (it == loaded->end())
        return {};
    return it->second.policy_ids;
}
}

max_stars_repo_name: rodrigargar/ClickHouse

max_issues_repo_name: rodrigargar/ClickHouse

max_forks_repo_name: rodrigargar/ClickHouse